@agent-native/core 0.8.2 → 0.10.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/README.md +4 -4
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +5 -4
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +6 -3
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +8 -17
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +28 -11
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +10 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +89 -7
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +4 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +6 -5
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +12 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +96 -0
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/cli/create.d.ts +9 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +29 -11
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +177 -22
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/workspace-dev.js +66 -5
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -20
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +146 -107
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +143 -22
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts +3 -0
- package/dist/client/agent-sidebar-state.d.ts.map +1 -0
- package/dist/client/agent-sidebar-state.js +24 -0
- package/dist/client/agent-sidebar-state.js.map +1 -0
- package/dist/client/analytics.d.ts +39 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +74 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/components/PresenceBar.js +21 -15
- package/dist/client/components/PresenceBar.js.map +1 -1
- package/dist/client/components/ui/tooltip.d.ts +2 -1
- package/dist/client/components/ui/tooltip.d.ts.map +1 -1
- package/dist/client/components/ui/tooltip.js +9 -2
- package/dist/client/components/ui/tooltip.js.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.js +51 -17
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +30 -0
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +31 -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 +9 -8
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.js +4 -3
- package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +6 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +14 -3
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionEditor.js +6 -5
- package/dist/client/extensions/ExtensionEditor.js.map +1 -1
- package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionSlot.js +2 -1
- package/dist/client/extensions/ExtensionSlot.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +40 -19
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +52 -51
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/integrations/IntegrationCard.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationCard.js +2 -1
- package/dist/client/integrations/IntegrationCard.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -2
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/notifications/NotificationsBell.d.ts.map +1 -1
- package/dist/client/notifications/NotificationsBell.js +42 -6
- package/dist/client/notifications/NotificationsBell.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +3 -2
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/onboarding/SetupButton.d.ts.map +1 -1
- package/dist/client/onboarding/SetupButton.js +14 -13
- package/dist/client/onboarding/SetupButton.js.map +1 -1
- package/dist/client/org/InvitationBanner.d.ts +8 -2
- package/dist/client/org/InvitationBanner.d.ts.map +1 -1
- package/dist/client/org/InvitationBanner.js +28 -7
- package/dist/client/org/InvitationBanner.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +29 -5
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +9 -7
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/client/resources/ResourceEditor.js +2 -1
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +48 -14
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/use-mcp-servers.d.ts +2 -0
- package/dist/client/resources/use-mcp-servers.d.ts.map +1 -1
- package/dist/client/resources/use-mcp-servers.js +59 -3
- package/dist/client/resources/use-mcp-servers.js.map +1 -1
- package/dist/client/settings/AgentsSection.d.ts.map +1 -1
- package/dist/client/settings/AgentsSection.js +8 -7
- package/dist/client/settings/AgentsSection.js.map +1 -1
- package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
- package/dist/client/settings/AutomationsSection.js +4 -3
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +11 -1
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +15 -12
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +13 -30
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/index.d.ts +1 -1
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +27 -1
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +4 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +5 -1
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +59 -11
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +100 -19
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +14 -2
- package/dist/client/use-session.js.map +1 -1
- package/dist/collab/client.d.ts +1 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +18 -1
- package/dist/collab/client.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +5 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +1 -0
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/deploy/workspace-core.d.ts +1 -1
- package/dist/deploy/workspace-core.d.ts.map +1 -1
- package/dist/deploy/workspace-core.js +1 -0
- package/dist/deploy/workspace-core.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +17 -3
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/routes.js +1 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/schema.d.ts +14 -14
- package/dist/extensions/schema.d.ts.map +1 -1
- package/dist/extensions/schema.js +4 -4
- package/dist/extensions/schema.js.map +1 -1
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +23 -0
- package/dist/extensions/store.js.map +1 -1
- package/dist/extensions/theme.d.ts +8 -1
- package/dist/extensions/theme.d.ts.map +1 -1
- package/dist/extensions/theme.js +43 -34
- package/dist/extensions/theme.js.map +1 -1
- package/dist/mcp-client/routes.d.ts +1 -0
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +28 -1
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/org/auto-join-domain.d.ts +28 -0
- package/dist/org/auto-join-domain.d.ts.map +1 -0
- package/dist/org/auto-join-domain.js +92 -0
- package/dist/org/auto-join-domain.js.map +1 -0
- package/dist/org/index.d.ts +2 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +27 -1
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/index.d.ts.map +1 -1
- package/dist/scripts/db/index.js +1 -0
- package/dist/scripts/db/index.js.map +1 -1
- package/dist/scripts/db/reset-dev-owner.d.ts +27 -0
- package/dist/scripts/db/reset-dev-owner.d.ts.map +1 -0
- package/dist/scripts/db/reset-dev-owner.js +225 -0
- package/dist/scripts/db/reset-dev-owner.js.map +1 -0
- package/dist/scripts/db/scoping.d.ts.map +1 -1
- package/dist/scripts/db/scoping.js +15 -30
- package/dist/scripts/db/scoping.js.map +1 -1
- package/dist/scripts/dev-session.d.ts +46 -0
- package/dist/scripts/dev-session.d.ts.map +1 -0
- package/dist/scripts/dev-session.js +81 -0
- package/dist/scripts/dev-session.js.map +1 -0
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +21 -0
- package/dist/scripts/runner.js.map +1 -1
- package/dist/secrets/register.d.ts +1 -1
- package/dist/secrets/register.d.ts.map +1 -1
- package/dist/secrets/register.js +4 -2
- package/dist/secrets/register.js.map +1 -1
- package/dist/secrets/routes.d.ts.map +1 -1
- package/dist/secrets/routes.js +32 -0
- package/dist/secrets/routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +77 -102
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +33 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +11 -0
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +169 -68
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +56 -13
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +49 -6
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +133 -38
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/design-token-utils.d.ts +13 -2
- package/dist/server/design-token-utils.d.ts.map +1 -1
- package/dist/server/design-token-utils.js +48 -16
- package/dist/server/design-token-utils.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +31 -0
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-realtime-session.d.ts.map +1 -1
- package/dist/server/google-realtime-session.js +19 -6
- package/dist/server/google-realtime-session.js.map +1 -1
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +142 -14
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/request-context.d.ts +17 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +40 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/sentry-plugin.d.ts +11 -0
- package/dist/server/sentry-plugin.d.ts.map +1 -0
- package/dist/server/sentry-plugin.js +116 -0
- package/dist/server/sentry-plugin.js.map +1 -0
- package/dist/server/sentry.d.ts +92 -0
- package/dist/server/sentry.d.ts.map +1 -0
- package/dist/server/sentry.js +287 -0
- package/dist/server/sentry.js.map +1 -0
- package/dist/server/transcribe-voice.d.ts +2 -4
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +4 -16
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +19 -35
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/styles/agent-native.css +15 -0
- package/docs/content/cloneable-saas.md +7 -9
- package/docs/content/deployment.md +6 -2
- package/docs/content/dispatch.md +1 -1
- package/docs/content/extensions.md +177 -142
- package/docs/content/faq.md +2 -2
- package/docs/content/getting-started.md +13 -11
- package/docs/content/multi-app-workspace.md +2 -2
- package/docs/content/observability.md +47 -0
- package/docs/content/pure-agent-apps.md +1 -1
- package/docs/content/template-clips.md +3 -3
- package/docs/content/template-design.md +3 -3
- package/docs/content/template-dispatch.md +1 -1
- package/docs/content/template-forms.md +1 -1
- package/docs/content/template-mail.md +1 -1
- package/docs/content/what-is-agent-native.md +4 -4
- package/docs/content/workspace.md +1 -1
- package/package.json +1 -1
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,yBAAyB,EAAE,CAAC;AAE5B,OAAO,EACL,eAAe,EACf,aAAa,GAEd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,UAAU,EACV,WAAW,EACX,OAAO,GACR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,aAAa,GAGd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,GAEnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,kBAAkB,GAEnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,SAAS,EACT,cAAc,EACd,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAoB,MAAM,kBAAkB,CAAC;AAChE,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,GAGpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,gBAAgB,GAGjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,GAGtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EACL,cAAc,GAGf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,cAAc,GAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,cAAc,GAGf,MAAM,iBAAiB,CAAC;AACzB,4DAA4D;AAC5D,OAAO,EACL,oBAAoB,GAErB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,kBAAkB,GAInB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAuB,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,eAAe,EACf,cAAc,GAGf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAA4B,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,eAAe,GAEhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { installRouteChunkRecovery } from \"./route-chunk-recovery.js\";\n\ninstallRouteChunkRecovery();\n\nexport {\n sendToAgentChat,\n generateTabId,\n type AgentChatMessage,\n} from \"./agent-chat.js\";\nexport { useAgentChatGenerating } from \"./use-agent-chat.js\";\nexport { useDevMode } from \"./use-dev-mode.js\";\nexport {\n agentNativePath,\n appApiPath,\n appBasePath,\n appPath,\n} from \"./api-path.js\";\nexport { useSendToAgentChat } from \"./use-send-to-agent-chat.js\";\nexport {\n useChatModels,\n type UseChatModelsResult,\n type EngineModelGroup,\n} from \"./use-chat-models.js\";\nexport {\n CodeRequiredDialog,\n type CodeRequiredDialogProps,\n} from \"./components/CodeRequiredDialog.js\";\nexport {\n CodeAgentIndicator,\n type CodeAgentIndicatorProps,\n} from \"./components/CodeAgentIndicator.js\";\nexport {\n useDbSync,\n useFileWatcher,\n useScreenRefreshKey,\n} from \"./use-db-sync.js\";\nexport { cn } from \"./utils.js\";\nexport { ApiKeySettings } from \"./components/ApiKeySettings.js\";\nexport { useSession, type AuthSession } from \"./use-session.js\";\nexport {\n sendToFrame,\n onFrameMessage,\n requestUserInfo,\n getFrameOrigin,\n getCallbackOrigin,\n isInFrame,\n enterStyleEditing,\n enterTextEditing,\n exitSelectionMode,\n type UserInfo,\n} from \"./frame.js\";\nexport {\n getBuilderParentOrigin,\n isInBuilderFrame,\n sendToBuilderChat,\n type BuilderChatMessage,\n} from \"./builder-frame.js\";\nexport {\n NewWorkspaceAppFlow,\n type NewWorkspaceAppFlowProps,\n type VaultSecretOption,\n} from \"./NewWorkspaceAppFlow.js\";\nexport {\n AssistantChat,\n clearChatStorage,\n type AssistantChatProps,\n type AssistantChatHandle,\n} from \"./AssistantChat.js\";\nexport {\n MultiTabAssistantChat,\n type MultiTabAssistantChatProps,\n type MultiTabAssistantChatHeaderProps,\n} from \"./MultiTabAssistantChat.js\";\nexport { createAgentChatAdapter } from \"./agent-chat-adapter.js\";\nexport {\n PromptComposer,\n type PromptComposerProps,\n type PromptComposerFile,\n} from \"./composer/PromptComposer.js\";\nexport {\n useChatThreads,\n type ChatThreadSummary,\n type ChatThreadData,\n} from \"./use-chat-threads.js\";\nexport {\n AgentPanel,\n AgentSidebar,\n AgentToggleButton,\n focusAgentChat,\n type AgentPanelProps,\n type AgentSidebarProps,\n} from \"./AgentPanel.js\";\nexport { SettingsPanel, type SettingsPanelProps } from \"./settings/index.js\";\n// Deprecated — use AgentSidebar + AgentToggleButton instead\nexport {\n ProductionAgentPanel,\n type ProductionAgentPanelProps,\n} from \"./ProductionAgentPanel.js\";\nexport {\n useProductionAgent,\n type ProductionAgentMessage,\n type UseProductionAgentOptions,\n type UseProductionAgentResult,\n} from \"./useProductionAgent.js\";\nexport { Turnstile, type TurnstileProps } from \"./Turnstile.js\";\nexport {\n OpenSourceBadge,\n PoweredByBadge,\n type OpenSourceBadgeProps,\n type PoweredByBadgeProps,\n} from \"./PoweredByBadge.js\";\nexport { FeedbackButton, type FeedbackButtonProps } from \"./FeedbackButton.js\";\nexport { ErrorBoundary } from \"./ErrorBoundary.js\";\nexport { installRouteChunkRecovery } from \"./route-chunk-recovery.js\";\nexport { ClientOnly } from \"./ClientOnly.js\";\nexport { DefaultSpinner } from \"./DefaultSpinner.js\";\nexport {\n getThemeInitScript,\n themeInitScript,\n type ThemePreference,\n} from \"./theme.js\";\nexport { AgentTerminal, type AgentTerminalProps } from \"./terminal/index.js\";\nexport {\n trackEvent,\n trackSessionStatus,\n configureTracking,\n setSentryUser,\n captureClientException,\n type ClientCaptureContext,\n} from \"./analytics.js\";\nexport {\n useCollaborativeDoc,\n emailToColor,\n emailToName,\n type UseCollaborativeDocOptions,\n type UseCollaborativeDocResult,\n type CollabUser,\n} from \"../collab/client.js\";\nexport {\n ResourcesPanel,\n ResourceTree,\n ResourceEditor,\n useResources,\n useResourceTree,\n useResource,\n useCreateResource,\n useUpdateResource,\n useDeleteResource,\n useUploadResource,\n type Resource,\n type ResourceMeta,\n type TreeNode,\n type ResourceScope,\n type ResourceTreeProps,\n type ResourceEditorProps,\n} from \"./resources/index.js\";\nexport type {\n AppToFrameMessage,\n FrameToAppMessage,\n FrameMessage,\n CodeCompleteMessage,\n ChatRunningMessage,\n} from \"./frame-protocol.js\";\nexport {\n CommandMenu,\n useCommandMenuShortcut,\n openAgentSidebar,\n submitToAgent,\n type CommandMenuProps,\n type CommandGroupProps,\n type CommandItemProps,\n type CommandShortcutProps,\n} from \"./CommandMenu.js\";\nexport {\n DevOverlay,\n useDevOverlayShortcut,\n registerDevPanel,\n unregisterDevPanel,\n listDevPanels,\n subscribeDevPanels,\n useDevOption,\n clearAllDevOverlayStorage,\n devOptionKey,\n DEV_OVERLAY_STORAGE_PREFIX,\n type DevOverlayProps,\n type DevPanel,\n type DevOption,\n type DevBooleanOption,\n type DevSelectOption,\n type DevStringOption,\n type DevActionOption,\n type DevOptionValue,\n} from \"./dev-overlay/index.js\";\nexport {\n useActionQuery,\n useActionMutation,\n type ActionRegistry,\n} from \"./use-action.js\";\nexport {\n ShareButton,\n ShareDialog,\n VisibilityBadge,\n type ShareButtonProps,\n type ShareDialogProps,\n type VisibilityBadgeProps,\n} from \"./sharing/index.js\";\nexport {\n postNavigate,\n isInAgentEmbed,\n AGENT_NAVIGATE_MESSAGE_TYPE,\n type AgentNavigateMessage,\n} from \"./embed.js\";\nexport { IframeEmbed, parseEmbedBody } from \"./IframeEmbed.js\";\nexport {\n useAvatarUrl,\n uploadAvatar,\n invalidateAvatarCache,\n} from \"./use-avatar.js\";\nexport {\n ObservabilityDashboard,\n ThumbsFeedback,\n} from \"./observability/index.js\";\n// Presence UI components\nexport {\n PresenceBar,\n type PresenceBarProps,\n} from \"./components/PresenceBar.js\";\nexport {\n AgentPresenceChip,\n type AgentPresenceChipProps,\n} from \"./components/AgentPresenceChip.js\";\n// Structured data collaboration hooks\nexport {\n useCollaborativeMap,\n useCollaborativeArray,\n type UseCollaborativeMapOptions,\n type UseCollaborativeMapResult,\n type UseCollaborativeArrayOptions,\n type UseCollaborativeArrayResult,\n} from \"../collab/client-struct.js\";\nexport { NotificationsBell } from \"./notifications/index.js\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntegrationCard.d.ts","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationCard.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"IntegrationCard.d.ts","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationCard.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA+BnE,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,2CAmIA"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useCallback } from "react";
|
|
3
3
|
import { IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconMessageCircle, IconChevronDown, IconChevronRight, IconCopy, IconCheck, } from "@tabler/icons-react";
|
|
4
4
|
import { agentNativePath } from "../api-path.js";
|
|
5
|
+
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
5
6
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
7
|
const platformIcons = {
|
|
7
8
|
slack: IconBrandSlack,
|
|
@@ -53,6 +54,6 @@ export function IntegrationCard({ status, onRefresh, }) {
|
|
|
53
54
|
setCopied(true);
|
|
54
55
|
setTimeout(() => setCopied(false), 2000);
|
|
55
56
|
}, [status.webhookUrl]);
|
|
56
|
-
return (_jsxs("div", { className: "rounded-md border border-border bg-background", children: [_jsxs("button", { onClick: () => setExpanded(!expanded), className: "flex w-full items-center gap-2 px-2.5 py-2 text-left hover:bg-accent/50", children: [expanded ? (_jsx(IconChevronDown, { size: 12, className: "text-muted-foreground shrink-0" })) : (_jsx(IconChevronRight, { size: 12, className: "text-muted-foreground shrink-0" })), _jsx(Icon, { size: 16, className: "text-muted-foreground shrink-0" }), _jsx("span", { className: "flex-1 text-xs font-medium text-foreground", children: status.label }), _jsx(StatusDot, { enabled: status.enabled, configured: status.configured })] }), expanded && (_jsxs("div", { className: "border-t border-border px-2.5 py-2 space-y-2", children: [status.webhookUrl && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Webhook URL" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground", children: status.webhookUrl }), _jsx("button", { onClick: handleCopy, className: "shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
57
|
+
return (_jsxs("div", { className: "rounded-md border border-border bg-background", children: [_jsxs("button", { onClick: () => setExpanded(!expanded), className: "flex w-full items-center gap-2 px-2.5 py-2 text-left hover:bg-accent/50", children: [expanded ? (_jsx(IconChevronDown, { size: 12, className: "text-muted-foreground shrink-0" })) : (_jsx(IconChevronRight, { size: 12, className: "text-muted-foreground shrink-0" })), _jsx(Icon, { size: 16, className: "text-muted-foreground shrink-0" }), _jsx("span", { className: "flex-1 text-xs font-medium text-foreground", children: status.label }), _jsx(StatusDot, { enabled: status.enabled, configured: status.configured })] }), expanded && (_jsxs("div", { className: "border-t border-border px-2.5 py-2 space-y-2", children: [status.webhookUrl && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Webhook URL" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground", children: status.webhookUrl }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: handleCopy, className: "shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50", children: copied ? (_jsx(IconCheck, { size: 12 })) : (_jsx(IconCopy, { size: 12 })) }) }), _jsx(TooltipContent, { children: "Copy webhook URL" })] })] })] })), status.error && (_jsx("p", { className: "text-[10px] text-destructive", children: status.error })), toggleError && (_jsx("p", { className: "text-[10px] text-destructive", children: toggleError })), !status.configured && !status.error && (_jsx("p", { className: "text-[10px] text-muted-foreground", children: "Not configured. Set the required secrets to enable this integration." })), status.configured && (_jsx("button", { onClick: handleToggle, disabled: toggling, className: "w-full rounded-md border border-border px-2 py-1 text-[11px] font-medium text-foreground hover:bg-accent/50 disabled:opacity-50", children: toggling ? "..." : status.enabled ? "Disable" : "Enable" }))] }))] }));
|
|
57
58
|
}
|
|
58
59
|
//# sourceMappingURL=IntegrationCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntegrationCard.js","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationCard.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,SAAS,GACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"IntegrationCard.js","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationCard.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,SAAS,GACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AAErC,8DAA8D;AAC9D,MAAM,aAAa,GAA6C;IAC9D,KAAK,EAAE,cAA0C;IACjD,QAAQ,EAAE,iBAA6C;IACvD,QAAQ,EAAE,iBAA6C;CACxD,CAAC;AAEF,SAAS,SAAS,CAAC,EACjB,OAAO,EACP,UAAU,GAIX;IACC,MAAM,KAAK,GACT,OAAO,IAAI,UAAU;QACnB,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,aAAa,CAAC;IACtB,OAAO,eAAM,SAAS,EAAE,qCAAqC,KAAK,EAAE,GAAI,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAC9B,MAAM,EACN,SAAS,GAIV;IACC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEpE,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC;IAEjE,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;YACrD,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CACb,+BAA+B,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE,CAC3D,EACD,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;YACF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAExC,CAAC;YACT,cAAc,CACZ,IAAI,EAAE,KAAK;gBACT,GAAG,CAAC,UAAU;gBACd,YAAY,MAAM,IAAI,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,MAAM,GAAG,CAC5D,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,cAAc,CACZ,GAAG,YAAY,KAAK;gBAClB,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,mCAAmC,CACxC,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAE/D,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO;QAC/B,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAExB,OAAO,CACL,eAAK,SAAS,EAAC,+CAA+C,aAC5D,kBACE,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,EACrC,SAAS,EAAC,yEAAyE,aAElF,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,eAAe,IACd,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,gCAAgC,GAC1C,CACH,CAAC,CAAC,CAAC,CACF,KAAC,gBAAgB,IACf,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,gCAAgC,GAC1C,CACH,EACD,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,gCAAgC,GAAG,EAC7D,eAAM,SAAS,EAAC,4CAA4C,YACzD,MAAM,CAAC,KAAK,GACR,EACP,KAAC,SAAS,IAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,GAAI,IAC9D,EAER,QAAQ,IAAI,CACX,eAAK,SAAS,EAAC,8CAA8C,aAC1D,MAAM,CAAC,UAAU,IAAI,CACpB,0BACE,cAAK,SAAS,EAAC,oDAAoD,4BAE7D,EACN,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAM,SAAS,EAAC,4EAA4E,YACzF,MAAM,CAAC,UAAU,GACb,EACP,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,OAAO,EAAE,UAAU,EACnB,SAAS,EAAC,uFAAuF,YAEhG,MAAM,CAAC,CAAC,CAAC,CACR,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,CACxB,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,CACvB,GACM,GACM,EACjB,KAAC,cAAc,mCAAkC,IACzC,IACN,IACF,CACP,EAEA,MAAM,CAAC,KAAK,IAAI,CACf,YAAG,SAAS,EAAC,8BAA8B,YAAE,MAAM,CAAC,KAAK,GAAK,CAC/D,EAEA,WAAW,IAAI,CACd,YAAG,SAAS,EAAC,8BAA8B,YAAE,WAAW,GAAK,CAC9D,EAEA,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CACtC,YAAG,SAAS,EAAC,mCAAmC,qFAG5C,CACL,EAEA,MAAM,CAAC,UAAU,IAAI,CACpB,iBACE,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAC,iIAAiI,YAE1I,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,GAClD,CACV,IACG,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport {\n IconBrandSlack,\n IconBrandTelegram,\n IconBrandWhatsapp,\n IconMessageCircle,\n IconChevronDown,\n IconChevronRight,\n IconCopy,\n IconCheck,\n} from \"@tabler/icons-react\";\nimport type { IntegrationStatus } from \"./useIntegrationStatus.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst platformIcons: Record<string, React.ComponentType<any>> = {\n slack: IconBrandSlack as React.ComponentType<any>,\n telegram: IconBrandTelegram as React.ComponentType<any>,\n whatsapp: IconBrandWhatsapp as React.ComponentType<any>,\n};\n\nfunction StatusDot({\n enabled,\n configured,\n}: {\n enabled: boolean;\n configured: boolean;\n}) {\n const color =\n enabled && configured\n ? \"bg-green-500\"\n : configured\n ? \"bg-yellow-500\"\n : \"bg-gray-400\";\n return <span className={`inline-block h-2 w-2 rounded-full ${color}`} />;\n}\n\nexport function IntegrationCard({\n status,\n onRefresh,\n}: {\n status: IntegrationStatus;\n onRefresh: () => void;\n}) {\n const [expanded, setExpanded] = useState(false);\n const [toggling, setToggling] = useState(false);\n const [copied, setCopied] = useState(false);\n const [toggleError, setToggleError] = useState<string | null>(null);\n\n const Icon = platformIcons[status.platform] || IconMessageCircle;\n\n const handleToggle = useCallback(async () => {\n setToggling(true);\n setToggleError(null);\n try {\n const action = status.enabled ? \"disable\" : \"enable\";\n const res = await fetch(\n agentNativePath(\n `/_agent-native/integrations/${status.platform}/${action}`,\n ),\n { method: \"POST\" },\n );\n if (res.ok) {\n onRefresh();\n return;\n }\n const data = (await res.json().catch(() => null)) as {\n error?: string;\n } | null;\n setToggleError(\n data?.error ||\n res.statusText ||\n `Couldn't ${action} ${status.label} (HTTP ${res.status})`,\n );\n } catch (err) {\n setToggleError(\n err instanceof Error\n ? err.message\n : \"Network error reaching the server\",\n );\n } finally {\n setToggling(false);\n }\n }, [status.platform, status.enabled, status.label, onRefresh]);\n\n const handleCopy = useCallback(async () => {\n if (!status.webhookUrl) return;\n await navigator.clipboard.writeText(status.webhookUrl);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [status.webhookUrl]);\n\n return (\n <div className=\"rounded-md border border-border bg-background\">\n <button\n onClick={() => setExpanded(!expanded)}\n className=\"flex w-full items-center gap-2 px-2.5 py-2 text-left hover:bg-accent/50\"\n >\n {expanded ? (\n <IconChevronDown\n size={12}\n className=\"text-muted-foreground shrink-0\"\n />\n ) : (\n <IconChevronRight\n size={12}\n className=\"text-muted-foreground shrink-0\"\n />\n )}\n <Icon size={16} className=\"text-muted-foreground shrink-0\" />\n <span className=\"flex-1 text-xs font-medium text-foreground\">\n {status.label}\n </span>\n <StatusDot enabled={status.enabled} configured={status.configured} />\n </button>\n\n {expanded && (\n <div className=\"border-t border-border px-2.5 py-2 space-y-2\">\n {status.webhookUrl && (\n <div>\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Webhook URL\n </div>\n <div className=\"flex items-center gap-1\">\n <code className=\"flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground\">\n {status.webhookUrl}\n </code>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={handleCopy}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n {copied ? (\n <IconCheck size={12} />\n ) : (\n <IconCopy size={12} />\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent>Copy webhook URL</TooltipContent>\n </Tooltip>\n </div>\n </div>\n )}\n\n {status.error && (\n <p className=\"text-[10px] text-destructive\">{status.error}</p>\n )}\n\n {toggleError && (\n <p className=\"text-[10px] text-destructive\">{toggleError}</p>\n )}\n\n {!status.configured && !status.error && (\n <p className=\"text-[10px] text-muted-foreground\">\n Not configured. Set the required secrets to enable this\n integration.\n </p>\n )}\n\n {status.configured && (\n <button\n onClick={handleToggle}\n disabled={toggling}\n className=\"w-full rounded-md border border-border px-2 py-1 text-[11px] font-medium text-foreground hover:bg-accent/50 disabled:opacity-50\"\n >\n {toggling ? \"...\" : status.enabled ? \"Disable\" : \"Enable\"}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntegrationsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationsPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"IntegrationsPanel.d.ts","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationsPanel.tsx"],"names":[],"mappings":"AAwZA,wBAAgB,iBAAiB,4CAgJhC"}
|
|
@@ -3,6 +3,7 @@ import { useState, useCallback } from "react";
|
|
|
3
3
|
import { IconPlus, IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconBrandGoogleDrive, IconTerminal2, IconBuildingSkyscraper, IconCopy, IconCheck, IconChevronLeft, IconExternalLink, IconCircleCheck, } from "@tabler/icons-react";
|
|
4
4
|
import { useIntegrationStatus, } from "./useIntegrationStatus.js";
|
|
5
5
|
import { agentNativePath } from "../api-path.js";
|
|
6
|
+
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
6
7
|
const PLATFORMS = [
|
|
7
8
|
{
|
|
8
9
|
id: "slack",
|
|
@@ -141,7 +142,7 @@ function IntegrationDetail({ platform, serverStatus, onBack, onRefresh, }) {
|
|
|
141
142
|
const serviceAccountEmail = typeof serverStatus?.details?.serviceAccountEmail === "string"
|
|
142
143
|
? serverStatus.details.serviceAccountEmail
|
|
143
144
|
: null;
|
|
144
|
-
return (_jsxs("div", { children: [_jsxs("button", { onClick: onBack, className: "flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2", children: [_jsx(IconChevronLeft, { size: 12 }), "Back"] }), _jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(platform.icon, { size: 18, className: "text-foreground shrink-0" }), _jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: platform.label }), _jsx("div", { className: "text-[10px] text-muted-foreground", children: platform.description })] })] }), _jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1.5", children: "Setup" }), _jsx("ol", { className: "space-y-1", children: platform.setupSteps.map((step, i) => (_jsxs("li", { className: "flex gap-1.5 text-[10px] text-muted-foreground leading-relaxed", children: [_jsxs("span", { className: "shrink-0 text-muted-foreground/50", children: [i + 1, "."] }), step] }, i))) })] }), serviceAccountEmail && (_jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Share documents with" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground", children: serviceAccountEmail }), _jsx("button", { onClick: () => handleCopy(serviceAccountEmail), className: "shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
145
|
+
return (_jsxs("div", { children: [_jsxs("button", { onClick: onBack, className: "flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2", children: [_jsx(IconChevronLeft, { size: 12 }), "Back"] }), _jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(platform.icon, { size: 18, className: "text-foreground shrink-0" }), _jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: platform.label }), _jsx("div", { className: "text-[10px] text-muted-foreground", children: platform.description })] })] }), _jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1.5", children: "Setup" }), _jsx("ol", { className: "space-y-1", children: platform.setupSteps.map((step, i) => (_jsxs("li", { className: "flex gap-1.5 text-[10px] text-muted-foreground leading-relaxed", children: [_jsxs("span", { className: "shrink-0 text-muted-foreground/50", children: [i + 1, "."] }), step] }, i))) })] }), serviceAccountEmail && (_jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Share documents with" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground", children: serviceAccountEmail }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => handleCopy(serviceAccountEmail), className: "shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50", children: copied ? _jsx(IconCheck, { size: 12 }) : _jsx(IconCopy, { size: 12 }) }) }), _jsx(TooltipContent, { children: "Copy service account email" })] })] })] })), platform.envVars.length > 0 && (_jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Required secrets" }), _jsx("div", { className: "space-y-0.5", children: platform.envVars.map((v) => (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "text-[10px] text-foreground bg-muted px-1 py-0.5 rounded", children: v }), isConfigured && (_jsx(IconCircleCheck, { size: 11, className: "text-green-500 shrink-0" }))] }, v))) }), !isConfigured && (_jsx("p", { className: "text-[10px] text-amber-500 mt-1", children: "Set these in your .env file or environment to connect." }))] })), serverStatus?.webhookUrl && !platform.isClient && (_jsxs("div", { className: "mb-3", children: [_jsx("div", { className: "text-[10px] font-medium text-muted-foreground mb-1", children: "Webhook URL" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground", children: serverStatus.webhookUrl }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => handleCopy(serverStatus.webhookUrl), className: "shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50", children: copied ? _jsx(IconCheck, { size: 12 }) : _jsx(IconCopy, { size: 12 }) }) }), _jsx(TooltipContent, { children: "Copy" })] })] })] })), platform.docsUrl && (_jsxs("a", { href: platform.docsUrl, target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-1 text-[10px] text-blue-400 hover:text-blue-300 mb-3", children: ["Documentation", _jsx(IconExternalLink, { size: 10 })] })), serverStatus && !platform.isClient && isConfigured && (_jsx("button", { onClick: handleToggle, disabled: toggling, className: `w-full rounded-md border px-2 py-1.5 text-[11px] font-medium disabled:opacity-50 ${isEnabled
|
|
145
146
|
? "border-border text-foreground hover:bg-accent/50"
|
|
146
147
|
: "border-green-600/50 text-green-400 hover:bg-green-900/20"}`, children: toggling ? "..." : isEnabled ? "Disable" : "Enable" })), platform.isClient && (_jsx("div", { className: "rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground", children: "This agent's A2A endpoint is automatically available. No configuration needed." })), serverStatus?.error && (_jsx("p", { className: "text-[10px] text-destructive mt-2", children: serverStatus.error })), toggleError && (_jsx("p", { className: "text-[10px] text-destructive mt-2", children: toggleError }))] }));
|
|
147
148
|
}
|
|
@@ -170,7 +171,7 @@ export function IntegrationsPanel() {
|
|
|
170
171
|
setShowPicker(false);
|
|
171
172
|
} })] }));
|
|
172
173
|
}
|
|
173
|
-
return (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Chat Integrations" }), _jsx("div", { className: "text-[10px] text-muted-foreground", children: "Talk to this agent from other platforms" })] }), _jsx("button", { onClick: () => setShowPicker(true), className: "flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
174
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Chat Integrations" }), _jsx("div", { className: "text-[10px] text-muted-foreground", children: "Talk to this agent from other platforms" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { onClick: () => setShowPicker(true), className: "flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 12 }) }) }), _jsx(TooltipContent, { children: "Add integration" })] })] }), loading ? (_jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "h-6 w-full rounded bg-muted/50 animate-pulse" }), _jsx("div", { className: "h-6 w-3/4 rounded bg-muted/50 animate-pulse" })] })) : connectedPlatforms.length === 0 ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("button", { onClick: () => setShowPicker(true), className: "flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30", children: [_jsx(IconPlus, { size: 12, className: "shrink-0" }), "Add integration"] }), _jsxs("div", { className: "rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground", children: ["For a central Slack or Telegram entrypoint that can route work across multiple apps, use the", " ", _jsx("a", { href: "https://dispatch.agent-native.com", target: "_blank", rel: "noopener noreferrer", className: "no-underline font-medium text-foreground hover:text-foreground/80", children: "dispatch template" }), "."] })] })) : (_jsxs("div", { className: "space-y-2", children: [connectedPlatforms.map((platform) => {
|
|
174
175
|
const s = statusMap.get(platform.id);
|
|
175
176
|
return (_jsxs("button", { onClick: () => setSelectedPlatform(platform), className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent/50", children: [_jsx(platform.icon, { size: 14, className: "shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-[11px] font-medium text-foreground truncate", children: platform.label }), s && (_jsx("span", { className: `inline-block h-1.5 w-1.5 rounded-full shrink-0 ${s.enabled && s.configured
|
|
176
177
|
? "bg-green-500"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntegrationsPanel.js","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationsPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport {\n IconPlus,\n IconBrandSlack,\n IconBrandTelegram,\n IconBrandWhatsapp,\n IconBrandGoogleDrive,\n IconTerminal2,\n IconBuildingSkyscraper,\n IconMessageCircle,\n IconCopy,\n IconCheck,\n IconChevronLeft,\n IconExternalLink,\n IconCircleCheck,\n} from \"@tabler/icons-react\";\nimport {\n useIntegrationStatus,\n type IntegrationStatus,\n} from \"./useIntegrationStatus.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\n// ─── Platform config ─────────────────────────────────────────────────────────\n\ninterface PlatformInfo {\n id: string;\n label: string;\n icon: React.ComponentType<any>;\n description: string;\n envVars: string[];\n setupSteps: string[];\n docsUrl?: string;\n /** If true, this is a \"client\" integration (user connects TO the agent) rather than a webhook */\n isClient?: boolean;\n}\n\nconst PLATFORMS: PlatformInfo[] = [\n {\n id: \"slack\",\n label: \"Slack\",\n icon: IconBrandSlack,\n description: \"Message your agent from any Slack channel or DM.\",\n envVars: [\"SLACK_BOT_TOKEN\", \"SLACK_SIGNING_SECRET\"],\n setupSteps: [\n \"Create a Slack app at api.slack.com/apps\",\n 'Enable \"Event Subscriptions\" and point to your webhook URL',\n \"Subscribe to message.im and app_mention events\",\n \"Install the app to your workspace\",\n \"Copy the Bot Token and Signing Secret into your environment\",\n ],\n docsUrl: \"https://api.slack.com/apps\",\n },\n {\n id: \"telegram\",\n label: \"Telegram\",\n icon: IconBrandTelegram,\n description: \"Chat with your agent via a Telegram bot.\",\n envVars: [\"TELEGRAM_BOT_TOKEN\"],\n setupSteps: [\n \"Message @BotFather on Telegram to create a new bot\",\n \"Copy the bot token into your environment\",\n 'Click \"Setup webhook\" below to register automatically',\n ],\n },\n {\n id: \"whatsapp\",\n label: \"WhatsApp\",\n icon: IconBrandWhatsapp,\n description: \"Connect your agent to WhatsApp Business.\",\n envVars: [\"WHATSAPP_TOKEN\", \"WHATSAPP_VERIFY_TOKEN\"],\n setupSteps: [\n \"Create a Meta Business app at developers.facebook.com\",\n \"Set up WhatsApp Business API\",\n \"Configure the webhook URL and verify token\",\n \"Copy the access token into your environment\",\n ],\n docsUrl: \"https://developers.facebook.com/docs/whatsapp\",\n },\n {\n id: \"google-docs\",\n label: \"Google Docs\",\n icon: IconBrandGoogleDrive,\n description: \"Tag the agent in Google Doc comments to get responses.\",\n envVars: [\"GOOGLE_SERVICE_ACCOUNT_KEY\"],\n setupSteps: [\n \"Create a Google Cloud service account and download the JSON key\",\n \"Set GOOGLE_SERVICE_ACCOUNT_KEY in your environment (JSON string or file path)\",\n \"Share your Google Docs with the service account email\",\n 'Write a comment containing \"@Agent\" to trigger the agent',\n ],\n },\n {\n id: \"openclaw\",\n label: \"OpenClaw\",\n icon: IconTerminal2,\n description: \"Access this agent from OpenClaw's unified agent interface.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Install OpenClaw: npm install -g openclaw\",\n \"Add this agent's URL as a provider in your OpenClaw config\",\n \"OpenClaw discovers your agent's capabilities via the A2A protocol\",\n ],\n },\n {\n id: \"claude-code\",\n label: \"Claude Code\",\n icon: IconTerminal2,\n description:\n \"Let Claude Code call this agent via A2A for data and actions.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Your agent exposes an A2A endpoint at /.well-known/agent-card.json\",\n \"In Claude Code, reference your agent's URL when asking for data\",\n \"Claude Code will discover and call your agent's skills automatically\",\n ],\n },\n {\n id: \"builder\",\n label: \"Builder.io\",\n icon: IconBuildingSkyscraper,\n description:\n \"One chat interface that orchestrates all your agents together.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Connect your agent-native apps in your Builder.io workspace\",\n \"Builder.io discovers each agent's skills via A2A\",\n \"Chat with one agent that can trigger actions across all your apps\",\n ],\n docsUrl: \"https://www.builder.io\",\n },\n];\n\n// ─── Integration detail view ─────────────────────────────────────────────────\n\nfunction IntegrationDetail({\n platform,\n serverStatus,\n onBack,\n onRefresh,\n}: {\n platform: PlatformInfo;\n serverStatus?: IntegrationStatus;\n onBack: () => void;\n onRefresh: () => void;\n}) {\n const [toggling, setToggling] = useState(false);\n const [copied, setCopied] = useState(false);\n const [toggleError, setToggleError] = useState<string | null>(null);\n\n const handleToggle = useCallback(async () => {\n setToggling(true);\n setToggleError(null);\n try {\n const action = serverStatus?.enabled ? \"disable\" : \"enable\";\n const res = await fetch(\n agentNativePath(`/_agent-native/integrations/${platform.id}/${action}`),\n { method: \"POST\" },\n );\n if (res.ok) {\n onRefresh();\n return;\n }\n // Surface the real reason instead of silently doing nothing.\n // The endpoint returns `{ error }` for known failures (admin gating,\n // missing secrets, etc.); fall back to status text otherwise.\n const data = (await res.json().catch(() => null)) as {\n error?: string;\n } | null;\n setToggleError(\n data?.error ||\n res.statusText ||\n `Couldn't ${action} ${platform.label} (HTTP ${res.status})`,\n );\n } catch (err) {\n setToggleError(\n err instanceof Error\n ? err.message\n : \"Network error reaching the server\",\n );\n } finally {\n setToggling(false);\n }\n }, [platform.id, platform.label, serverStatus?.enabled, onRefresh]);\n\n const handleCopy = useCallback(async (text: string) => {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, []);\n\n const isConfigured = serverStatus?.configured ?? false;\n const isEnabled = serverStatus?.enabled ?? false;\n const serviceAccountEmail =\n typeof serverStatus?.details?.serviceAccountEmail === \"string\"\n ? serverStatus.details.serviceAccountEmail\n : null;\n\n return (\n <div>\n <button\n onClick={onBack}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2\"\n >\n <IconChevronLeft size={12} />\n Back\n </button>\n\n <div className=\"flex items-center gap-2 mb-2\">\n <platform.icon size={18} className=\"text-foreground shrink-0\" />\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n {platform.label}\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n {platform.description}\n </div>\n </div>\n </div>\n\n {/* Setup steps */}\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1.5\">\n Setup\n </div>\n <ol className=\"space-y-1\">\n {platform.setupSteps.map((step, i) => (\n <li\n key={i}\n className=\"flex gap-1.5 text-[10px] text-muted-foreground leading-relaxed\"\n >\n <span className=\"shrink-0 text-muted-foreground/50\">\n {i + 1}.\n </span>\n {step}\n </li>\n ))}\n </ol>\n </div>\n\n {serviceAccountEmail && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Share documents with\n </div>\n <div className=\"flex items-center gap-1\">\n <code className=\"flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground\">\n {serviceAccountEmail}\n </code>\n <button\n onClick={() => handleCopy(serviceAccountEmail)}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n title=\"Copy service account email\"\n >\n {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}\n </button>\n </div>\n </div>\n )}\n\n {/* Required secrets */}\n {platform.envVars.length > 0 && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Required secrets\n </div>\n <div className=\"space-y-0.5\">\n {platform.envVars.map((v) => (\n <div key={v} className=\"flex items-center gap-1\">\n <code className=\"text-[10px] text-foreground bg-muted px-1 py-0.5 rounded\">\n {v}\n </code>\n {isConfigured && (\n <IconCircleCheck\n size={11}\n className=\"text-green-500 shrink-0\"\n />\n )}\n </div>\n ))}\n </div>\n {!isConfigured && (\n <p className=\"text-[10px] text-amber-500 mt-1\">\n Set these in your .env file or environment to connect.\n </p>\n )}\n </div>\n )}\n\n {/* Webhook URL */}\n {serverStatus?.webhookUrl && !platform.isClient && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Webhook URL\n </div>\n <div className=\"flex items-center gap-1\">\n <code className=\"flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground\">\n {serverStatus.webhookUrl}\n </code>\n <button\n onClick={() => handleCopy(serverStatus.webhookUrl!)}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n title=\"Copy\"\n >\n {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}\n </button>\n </div>\n </div>\n )}\n\n {/* Docs link */}\n {platform.docsUrl && (\n <a\n href={platform.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 text-[10px] text-blue-400 hover:text-blue-300 mb-3\"\n >\n Documentation\n <IconExternalLink size={10} />\n </a>\n )}\n\n {/* Enable/disable for server integrations */}\n {serverStatus && !platform.isClient && isConfigured && (\n <button\n onClick={handleToggle}\n disabled={toggling}\n className={`w-full rounded-md border px-2 py-1.5 text-[11px] font-medium disabled:opacity-50 ${\n isEnabled\n ? \"border-border text-foreground hover:bg-accent/50\"\n : \"border-green-600/50 text-green-400 hover:bg-green-900/20\"\n }`}\n >\n {toggling ? \"...\" : isEnabled ? \"Disable\" : \"Enable\"}\n </button>\n )}\n\n {/* Status for client integrations */}\n {platform.isClient && (\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n This agent's A2A endpoint is automatically available. No configuration\n needed.\n </div>\n )}\n\n {serverStatus?.error && (\n <p className=\"text-[10px] text-destructive mt-2\">\n {serverStatus.error}\n </p>\n )}\n\n {toggleError && (\n <p className=\"text-[10px] text-destructive mt-2\">{toggleError}</p>\n )}\n </div>\n );\n}\n\n// ─── Add integration picker ──────────────────────────────────────────────────\n\nfunction AddIntegrationPicker({\n connectedIds,\n onSelect,\n}: {\n connectedIds: Set<string>;\n onSelect: (platform: PlatformInfo) => void;\n}) {\n return (\n <div className=\"space-y-1\">\n {PLATFORMS.filter((p) => !connectedIds.has(p.id)).map((platform) => (\n <button\n key={platform.id}\n onClick={() => onSelect(platform)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent/50\"\n >\n <platform.icon size={14} className=\"shrink-0 text-muted-foreground\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-[11px] font-medium text-foreground\">\n {platform.label}\n </div>\n <div className=\"text-[10px] text-muted-foreground truncate\">\n {platform.description}\n </div>\n </div>\n </button>\n ))}\n </div>\n );\n}\n\n// ─── Main panel ──────────────────────────────────────────────────────────────\n\nexport function IntegrationsPanel() {\n const { statuses, loading, refetch } = useIntegrationStatus();\n const [selectedPlatform, setSelectedPlatform] = useState<PlatformInfo | null>(\n null,\n );\n const [showPicker, setShowPicker] = useState(false);\n\n const statusMap = new Map(statuses.map((s) => [s.platform, s]));\n\n // Show connected (enabled or configured) integrations\n const connectedPlatforms = PLATFORMS.filter((p) => {\n const s = statusMap.get(p.id);\n return s?.configured || s?.enabled;\n });\n\n const connectedIds = new Set(connectedPlatforms.map((p) => p.id));\n\n if (selectedPlatform) {\n return (\n <IntegrationDetail\n platform={selectedPlatform}\n serverStatus={statusMap.get(selectedPlatform.id)}\n onBack={() => setSelectedPlatform(null)}\n onRefresh={refetch}\n />\n );\n }\n\n if (showPicker) {\n return (\n <div>\n <button\n onClick={() => setShowPicker(false)}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2\"\n >\n <IconChevronLeft size={12} />\n Back\n </button>\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1.5\">\n Add a chat integration\n </div>\n <AddIntegrationPicker\n connectedIds={connectedIds}\n onSelect={(p) => {\n setSelectedPlatform(p);\n setShowPicker(false);\n }}\n />\n </div>\n );\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n Chat Integrations\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n Talk to this agent from other platforms\n </div>\n </div>\n <button\n onClick={() => setShowPicker(true)}\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n title=\"Add integration\"\n >\n <IconPlus size={12} />\n </button>\n </div>\n\n {loading ? (\n <div className=\"space-y-1.5\">\n <div className=\"h-6 w-full rounded bg-muted/50 animate-pulse\" />\n <div className=\"h-6 w-3/4 rounded bg-muted/50 animate-pulse\" />\n </div>\n ) : connectedPlatforms.length === 0 ? (\n <div className=\"space-y-2\">\n <button\n onClick={() => setShowPicker(true)}\n className=\"flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30\"\n >\n <IconPlus size={12} className=\"shrink-0\" />\n Add integration\n </button>\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n For a central Slack or Telegram entrypoint that can route work\n across multiple apps, use the{\" \"}\n <a\n href=\"https://dispatch.agent-native.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"no-underline font-medium text-foreground hover:text-foreground/80\"\n >\n dispatch template\n </a>\n .\n </div>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {connectedPlatforms.map((platform) => {\n const s = statusMap.get(platform.id);\n return (\n <button\n key={platform.id}\n onClick={() => setSelectedPlatform(platform)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent/50\"\n >\n <platform.icon\n size={14}\n className=\"shrink-0 text-muted-foreground\"\n />\n <span className=\"flex-1 text-[11px] font-medium text-foreground truncate\">\n {platform.label}\n </span>\n {s && (\n <span\n className={`inline-block h-1.5 w-1.5 rounded-full shrink-0 ${\n s.enabled && s.configured\n ? \"bg-green-500\"\n : s.configured\n ? \"bg-yellow-500\"\n : \"bg-gray-400\"\n }`}\n />\n )}\n </button>\n );\n })}\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n Need one shared messaging surface for your workspace? Connect Slack\n or Telegram to a dispatch app and let it delegate to other agents\n over A2A.\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"IntegrationsPanel.js","sourceRoot":"","sources":["../../../src/client/integrations/IntegrationsPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport {\n IconPlus,\n IconBrandSlack,\n IconBrandTelegram,\n IconBrandWhatsapp,\n IconBrandGoogleDrive,\n IconTerminal2,\n IconBuildingSkyscraper,\n IconMessageCircle,\n IconCopy,\n IconCheck,\n IconChevronLeft,\n IconExternalLink,\n IconCircleCheck,\n} from \"@tabler/icons-react\";\nimport {\n useIntegrationStatus,\n type IntegrationStatus,\n} from \"./useIntegrationStatus.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\n// ─── Platform config ─────────────────────────────────────────────────────────\n\ninterface PlatformInfo {\n id: string;\n label: string;\n icon: React.ComponentType<any>;\n description: string;\n envVars: string[];\n setupSteps: string[];\n docsUrl?: string;\n /** If true, this is a \"client\" integration (user connects TO the agent) rather than a webhook */\n isClient?: boolean;\n}\n\nconst PLATFORMS: PlatformInfo[] = [\n {\n id: \"slack\",\n label: \"Slack\",\n icon: IconBrandSlack,\n description: \"Message your agent from any Slack channel or DM.\",\n envVars: [\"SLACK_BOT_TOKEN\", \"SLACK_SIGNING_SECRET\"],\n setupSteps: [\n \"Create a Slack app at api.slack.com/apps\",\n 'Enable \"Event Subscriptions\" and point to your webhook URL',\n \"Subscribe to message.im and app_mention events\",\n \"Install the app to your workspace\",\n \"Copy the Bot Token and Signing Secret into your environment\",\n ],\n docsUrl: \"https://api.slack.com/apps\",\n },\n {\n id: \"telegram\",\n label: \"Telegram\",\n icon: IconBrandTelegram,\n description: \"Chat with your agent via a Telegram bot.\",\n envVars: [\"TELEGRAM_BOT_TOKEN\"],\n setupSteps: [\n \"Message @BotFather on Telegram to create a new bot\",\n \"Copy the bot token into your environment\",\n 'Click \"Setup webhook\" below to register automatically',\n ],\n },\n {\n id: \"whatsapp\",\n label: \"WhatsApp\",\n icon: IconBrandWhatsapp,\n description: \"Connect your agent to WhatsApp Business.\",\n envVars: [\"WHATSAPP_TOKEN\", \"WHATSAPP_VERIFY_TOKEN\"],\n setupSteps: [\n \"Create a Meta Business app at developers.facebook.com\",\n \"Set up WhatsApp Business API\",\n \"Configure the webhook URL and verify token\",\n \"Copy the access token into your environment\",\n ],\n docsUrl: \"https://developers.facebook.com/docs/whatsapp\",\n },\n {\n id: \"google-docs\",\n label: \"Google Docs\",\n icon: IconBrandGoogleDrive,\n description: \"Tag the agent in Google Doc comments to get responses.\",\n envVars: [\"GOOGLE_SERVICE_ACCOUNT_KEY\"],\n setupSteps: [\n \"Create a Google Cloud service account and download the JSON key\",\n \"Set GOOGLE_SERVICE_ACCOUNT_KEY in your environment (JSON string or file path)\",\n \"Share your Google Docs with the service account email\",\n 'Write a comment containing \"@Agent\" to trigger the agent',\n ],\n },\n {\n id: \"openclaw\",\n label: \"OpenClaw\",\n icon: IconTerminal2,\n description: \"Access this agent from OpenClaw's unified agent interface.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Install OpenClaw: npm install -g openclaw\",\n \"Add this agent's URL as a provider in your OpenClaw config\",\n \"OpenClaw discovers your agent's capabilities via the A2A protocol\",\n ],\n },\n {\n id: \"claude-code\",\n label: \"Claude Code\",\n icon: IconTerminal2,\n description:\n \"Let Claude Code call this agent via A2A for data and actions.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Your agent exposes an A2A endpoint at /.well-known/agent-card.json\",\n \"In Claude Code, reference your agent's URL when asking for data\",\n \"Claude Code will discover and call your agent's skills automatically\",\n ],\n },\n {\n id: \"builder\",\n label: \"Builder.io\",\n icon: IconBuildingSkyscraper,\n description:\n \"One chat interface that orchestrates all your agents together.\",\n envVars: [],\n isClient: true,\n setupSteps: [\n \"Connect your agent-native apps in your Builder.io workspace\",\n \"Builder.io discovers each agent's skills via A2A\",\n \"Chat with one agent that can trigger actions across all your apps\",\n ],\n docsUrl: \"https://www.builder.io\",\n },\n];\n\n// ─── Integration detail view ─────────────────────────────────────────────────\n\nfunction IntegrationDetail({\n platform,\n serverStatus,\n onBack,\n onRefresh,\n}: {\n platform: PlatformInfo;\n serverStatus?: IntegrationStatus;\n onBack: () => void;\n onRefresh: () => void;\n}) {\n const [toggling, setToggling] = useState(false);\n const [copied, setCopied] = useState(false);\n const [toggleError, setToggleError] = useState<string | null>(null);\n\n const handleToggle = useCallback(async () => {\n setToggling(true);\n setToggleError(null);\n try {\n const action = serverStatus?.enabled ? \"disable\" : \"enable\";\n const res = await fetch(\n agentNativePath(`/_agent-native/integrations/${platform.id}/${action}`),\n { method: \"POST\" },\n );\n if (res.ok) {\n onRefresh();\n return;\n }\n // Surface the real reason instead of silently doing nothing.\n // The endpoint returns `{ error }` for known failures (admin gating,\n // missing secrets, etc.); fall back to status text otherwise.\n const data = (await res.json().catch(() => null)) as {\n error?: string;\n } | null;\n setToggleError(\n data?.error ||\n res.statusText ||\n `Couldn't ${action} ${platform.label} (HTTP ${res.status})`,\n );\n } catch (err) {\n setToggleError(\n err instanceof Error\n ? err.message\n : \"Network error reaching the server\",\n );\n } finally {\n setToggling(false);\n }\n }, [platform.id, platform.label, serverStatus?.enabled, onRefresh]);\n\n const handleCopy = useCallback(async (text: string) => {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, []);\n\n const isConfigured = serverStatus?.configured ?? false;\n const isEnabled = serverStatus?.enabled ?? false;\n const serviceAccountEmail =\n typeof serverStatus?.details?.serviceAccountEmail === \"string\"\n ? serverStatus.details.serviceAccountEmail\n : null;\n\n return (\n <div>\n <button\n onClick={onBack}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2\"\n >\n <IconChevronLeft size={12} />\n Back\n </button>\n\n <div className=\"flex items-center gap-2 mb-2\">\n <platform.icon size={18} className=\"text-foreground shrink-0\" />\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n {platform.label}\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n {platform.description}\n </div>\n </div>\n </div>\n\n {/* Setup steps */}\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1.5\">\n Setup\n </div>\n <ol className=\"space-y-1\">\n {platform.setupSteps.map((step, i) => (\n <li\n key={i}\n className=\"flex gap-1.5 text-[10px] text-muted-foreground leading-relaxed\"\n >\n <span className=\"shrink-0 text-muted-foreground/50\">\n {i + 1}.\n </span>\n {step}\n </li>\n ))}\n </ol>\n </div>\n\n {serviceAccountEmail && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Share documents with\n </div>\n <div className=\"flex items-center gap-1\">\n <code className=\"flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground\">\n {serviceAccountEmail}\n </code>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => handleCopy(serviceAccountEmail)}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}\n </button>\n </TooltipTrigger>\n <TooltipContent>Copy service account email</TooltipContent>\n </Tooltip>\n </div>\n </div>\n )}\n\n {/* Required secrets */}\n {platform.envVars.length > 0 && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Required secrets\n </div>\n <div className=\"space-y-0.5\">\n {platform.envVars.map((v) => (\n <div key={v} className=\"flex items-center gap-1\">\n <code className=\"text-[10px] text-foreground bg-muted px-1 py-0.5 rounded\">\n {v}\n </code>\n {isConfigured && (\n <IconCircleCheck\n size={11}\n className=\"text-green-500 shrink-0\"\n />\n )}\n </div>\n ))}\n </div>\n {!isConfigured && (\n <p className=\"text-[10px] text-amber-500 mt-1\">\n Set these in your .env file or environment to connect.\n </p>\n )}\n </div>\n )}\n\n {/* Webhook URL */}\n {serverStatus?.webhookUrl && !platform.isClient && (\n <div className=\"mb-3\">\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1\">\n Webhook URL\n </div>\n <div className=\"flex items-center gap-1\">\n <code className=\"flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground\">\n {serverStatus.webhookUrl}\n </code>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => handleCopy(serverStatus.webhookUrl!)}\n className=\"shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}\n </button>\n </TooltipTrigger>\n <TooltipContent>Copy</TooltipContent>\n </Tooltip>\n </div>\n </div>\n )}\n\n {/* Docs link */}\n {platform.docsUrl && (\n <a\n href={platform.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 text-[10px] text-blue-400 hover:text-blue-300 mb-3\"\n >\n Documentation\n <IconExternalLink size={10} />\n </a>\n )}\n\n {/* Enable/disable for server integrations */}\n {serverStatus && !platform.isClient && isConfigured && (\n <button\n onClick={handleToggle}\n disabled={toggling}\n className={`w-full rounded-md border px-2 py-1.5 text-[11px] font-medium disabled:opacity-50 ${\n isEnabled\n ? \"border-border text-foreground hover:bg-accent/50\"\n : \"border-green-600/50 text-green-400 hover:bg-green-900/20\"\n }`}\n >\n {toggling ? \"...\" : isEnabled ? \"Disable\" : \"Enable\"}\n </button>\n )}\n\n {/* Status for client integrations */}\n {platform.isClient && (\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n This agent's A2A endpoint is automatically available. No configuration\n needed.\n </div>\n )}\n\n {serverStatus?.error && (\n <p className=\"text-[10px] text-destructive mt-2\">\n {serverStatus.error}\n </p>\n )}\n\n {toggleError && (\n <p className=\"text-[10px] text-destructive mt-2\">{toggleError}</p>\n )}\n </div>\n );\n}\n\n// ─── Add integration picker ──────────────────────────────────────────────────\n\nfunction AddIntegrationPicker({\n connectedIds,\n onSelect,\n}: {\n connectedIds: Set<string>;\n onSelect: (platform: PlatformInfo) => void;\n}) {\n return (\n <div className=\"space-y-1\">\n {PLATFORMS.filter((p) => !connectedIds.has(p.id)).map((platform) => (\n <button\n key={platform.id}\n onClick={() => onSelect(platform)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent/50\"\n >\n <platform.icon size={14} className=\"shrink-0 text-muted-foreground\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-[11px] font-medium text-foreground\">\n {platform.label}\n </div>\n <div className=\"text-[10px] text-muted-foreground truncate\">\n {platform.description}\n </div>\n </div>\n </button>\n ))}\n </div>\n );\n}\n\n// ─── Main panel ──────────────────────────────────────────────────────────────\n\nexport function IntegrationsPanel() {\n const { statuses, loading, refetch } = useIntegrationStatus();\n const [selectedPlatform, setSelectedPlatform] = useState<PlatformInfo | null>(\n null,\n );\n const [showPicker, setShowPicker] = useState(false);\n\n const statusMap = new Map(statuses.map((s) => [s.platform, s]));\n\n // Show connected (enabled or configured) integrations\n const connectedPlatforms = PLATFORMS.filter((p) => {\n const s = statusMap.get(p.id);\n return s?.configured || s?.enabled;\n });\n\n const connectedIds = new Set(connectedPlatforms.map((p) => p.id));\n\n if (selectedPlatform) {\n return (\n <IntegrationDetail\n platform={selectedPlatform}\n serverStatus={statusMap.get(selectedPlatform.id)}\n onBack={() => setSelectedPlatform(null)}\n onRefresh={refetch}\n />\n );\n }\n\n if (showPicker) {\n return (\n <div>\n <button\n onClick={() => setShowPicker(false)}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2\"\n >\n <IconChevronLeft size={12} />\n Back\n </button>\n <div className=\"text-[10px] font-medium text-muted-foreground mb-1.5\">\n Add a chat integration\n </div>\n <AddIntegrationPicker\n connectedIds={connectedIds}\n onSelect={(p) => {\n setSelectedPlatform(p);\n setShowPicker(false);\n }}\n />\n </div>\n );\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n Chat Integrations\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n Talk to this agent from other platforms\n </div>\n </div>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={() => setShowPicker(true)}\n className=\"flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n <IconPlus size={12} />\n </button>\n </TooltipTrigger>\n <TooltipContent>Add integration</TooltipContent>\n </Tooltip>\n </div>\n\n {loading ? (\n <div className=\"space-y-1.5\">\n <div className=\"h-6 w-full rounded bg-muted/50 animate-pulse\" />\n <div className=\"h-6 w-3/4 rounded bg-muted/50 animate-pulse\" />\n </div>\n ) : connectedPlatforms.length === 0 ? (\n <div className=\"space-y-2\">\n <button\n onClick={() => setShowPicker(true)}\n className=\"flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30\"\n >\n <IconPlus size={12} className=\"shrink-0\" />\n Add integration\n </button>\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n For a central Slack or Telegram entrypoint that can route work\n across multiple apps, use the{\" \"}\n <a\n href=\"https://dispatch.agent-native.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"no-underline font-medium text-foreground hover:text-foreground/80\"\n >\n dispatch template\n </a>\n .\n </div>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {connectedPlatforms.map((platform) => {\n const s = statusMap.get(platform.id);\n return (\n <button\n key={platform.id}\n onClick={() => setSelectedPlatform(platform)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent/50\"\n >\n <platform.icon\n size={14}\n className=\"shrink-0 text-muted-foreground\"\n />\n <span className=\"flex-1 text-[11px] font-medium text-foreground truncate\">\n {platform.label}\n </span>\n {s && (\n <span\n className={`inline-block h-1.5 w-1.5 rounded-full shrink-0 ${\n s.enabled && s.configured\n ? \"bg-green-500\"\n : s.configured\n ? \"bg-yellow-500\"\n : \"bg-gray-400\"\n }`}\n />\n )}\n </button>\n );\n })}\n <div className=\"rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground\">\n Need one shared messaging surface for your workspace? Connect Slack\n or Telegram to a dispatch app and let it delegate to other agents\n over A2A.\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationsBell.d.ts","sourceRoot":"","sources":["../../../src/client/notifications/NotificationsBell.tsx"],"names":[],"mappings":"AAmBA,UAAU,sBAAsB;IAC9B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAwB,EACxB,SAAS,EACT,oBAA4B,GAC7B,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"NotificationsBell.d.ts","sourceRoot":"","sources":["../../../src/client/notifications/NotificationsBell.tsx"],"names":[],"mappings":"AAmBA,UAAU,sBAAsB;IAC9B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAwB,EACxB,SAAS,EACT,oBAA4B,GAC7B,EAAE,sBAAsB,2CAySxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { agentNativePath } from "../api-path.js";
|
|
2
|
+
import { agentNativePath, appPath } from "../api-path.js";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { IconBell, IconBellRinging, IconLoader2, IconX, } from "@tabler/icons-react";
|
|
5
5
|
import { usePausingInterval } from "../use-pausing-interval.js";
|
|
@@ -105,8 +105,12 @@ export function NotificationsBell({ pollMs = POLL_MS_DEFAULT, className, browser
|
|
|
105
105
|
}, [open, loadItems]);
|
|
106
106
|
const markRead = async (id) => {
|
|
107
107
|
try {
|
|
108
|
+
// `keepalive: true` lets the request survive page navigation —
|
|
109
|
+
// without it, clicking a notification with a link aborts this
|
|
110
|
+
// request mid-flight and the row stays unread.
|
|
108
111
|
await fetch(agentNativePath(`/_agent-native/notifications/${id}/read`), {
|
|
109
112
|
method: "POST",
|
|
113
|
+
keepalive: true,
|
|
110
114
|
});
|
|
111
115
|
setItems((prev) => prev
|
|
112
116
|
? prev.map((n) => n.id === id ? { ...n, readAt: new Date().toISOString() } : n)
|
|
@@ -117,6 +121,25 @@ export function NotificationsBell({ pollMs = POLL_MS_DEFAULT, className, browser
|
|
|
117
121
|
// best-effort
|
|
118
122
|
}
|
|
119
123
|
};
|
|
124
|
+
// Reject any URL that isn't http(s) or a same-origin relative path. Blocks
|
|
125
|
+
// `javascript:` execution, `data:` URIs, and absolute redirects to phishing
|
|
126
|
+
// sites. Relative paths starting with `/` are routed through `appPath()` so
|
|
127
|
+
// the link works in mounted deployments (e.g. /mail subdirectory).
|
|
128
|
+
const safeNotificationLink = (link) => {
|
|
129
|
+
if (link.startsWith("/") && !link.startsWith("//")) {
|
|
130
|
+
return appPath(link);
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const url = new URL(link, window.location.origin);
|
|
134
|
+
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
135
|
+
return url.toString();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// fallthrough
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
};
|
|
120
143
|
const markAllRead = async () => {
|
|
121
144
|
try {
|
|
122
145
|
await fetch(agentNativePath(`/_agent-native/notifications/read-all`), {
|
|
@@ -151,11 +174,24 @@ export function NotificationsBell({ pollMs = POLL_MS_DEFAULT, className, browser
|
|
|
151
174
|
permission === "default" ? (_jsxs("div", { className: "flex items-center justify-between gap-2 border-b border-border bg-accent/40 px-3 py-2 text-xs text-foreground", children: [_jsx("span", { children: "Get a system popup for new notifications." }), _jsx("button", { type: "button", onClick: async () => {
|
|
152
175
|
const result = await Notification.requestPermission();
|
|
153
176
|
setPermission(result);
|
|
154
|
-
}, className: "shrink-0 rounded bg-primary px-2 py-0.5 font-medium text-primary-foreground hover:bg-primary/90", children: "Enable" })] })) : null, _jsx("div", { className: "max-h-96 overflow-y-auto", children: items === null ? (_jsxs("div", { className: "flex items-center gap-2 p-4 text-sm text-muted-foreground", children: [_jsx(IconLoader2, { size: 14, className: "animate-spin" }), " Loading\u2026"] })) : items.length > 0 ? (items.map((n) =>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
177
|
+
}, className: "shrink-0 rounded bg-primary px-2 py-0.5 font-medium text-primary-foreground hover:bg-primary/90", children: "Enable" })] })) : null, _jsx("div", { className: "max-h-96 overflow-y-auto", children: items === null ? (_jsxs("div", { className: "flex items-center gap-2 p-4 text-sm text-muted-foreground", children: [_jsx(IconLoader2, { size: 14, className: "animate-spin" }), " Loading\u2026"] })) : items.length > 0 ? (items.map((n) => {
|
|
178
|
+
const rawLink = typeof n.metadata?.link === "string" ? n.metadata.link : null;
|
|
179
|
+
const link = rawLink ? safeNotificationLink(rawLink) : null;
|
|
180
|
+
const onItemClick = () => {
|
|
181
|
+
if (!n.readAt)
|
|
182
|
+
void markRead(n.id);
|
|
183
|
+
if (link) {
|
|
184
|
+
setOpen(false);
|
|
185
|
+
window.location.assign(link);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
return (_jsxs("div", { className: "group relative border-b border-border last:border-b-0 hover:bg-accent/40 " +
|
|
189
|
+
(n.readAt ? "opacity-60" : ""), children: [_jsxs("button", { type: "button", onClick: onItemClick, className: "flex w-full flex-col items-start gap-0.5 px-3 py-2 pr-8 text-left" +
|
|
190
|
+
(link ? " cursor-pointer" : ""), children: [_jsxs("div", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: n.title }), _jsx(SeverityBadge, { severity: n.severity })] }), n.body ? (_jsx("span", { className: "line-clamp-2 text-xs text-muted-foreground", children: n.body })) : null, _jsx("span", { className: "text-[10px] text-muted-foreground/70", children: new Date(n.createdAt).toLocaleString() })] }), _jsx("button", { type: "button", "aria-label": "Dismiss notification", onClick: (e) => {
|
|
191
|
+
e.stopPropagation();
|
|
192
|
+
void dismiss(n.id);
|
|
193
|
+
}, className: "absolute right-2 top-2 hidden rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground group-hover:flex", children: _jsx(IconX, { size: 12 }) })] }, n.id));
|
|
194
|
+
})) : (_jsx("div", { className: "p-4 text-sm text-muted-foreground", children: "No notifications." })) })] })] }));
|
|
159
195
|
}
|
|
160
196
|
// Severity color pairs — use /20 opacity backdrops that work against both
|
|
161
197
|
// light and dark theme backgrounds; text uses 700/300 so it stays readable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationsBell.js","sourceRoot":"","sources":["../../../src/client/notifications/NotificationsBell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n IconBell,\n IconBellRinging,\n IconLoader2,\n IconX,\n} from \"@tabler/icons-react\";\nimport { usePausingInterval } from \"../use-pausing-interval.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport type {\n Notification as NotificationDto,\n NotificationSeverity,\n} from \"../../notifications/types.js\";\n\ninterface NotificationsBellProps {\n /** Poll interval in ms. Set to 0 to disable polling. Default: 10000. */\n pollMs?: number;\n /** Optional className for the outer container. */\n className?: string;\n /**\n * When true, fires a system-level `new Notification(...)` popup for each\n * new unread notification — handy when the tab is in the background.\n * Renders an \"Enable browser notifications\" prompt in the dropdown until\n * the user grants permission. Silently no-ops on denied or unsupported.\n */\n browserNotifications?: boolean;\n}\n\nconst POLL_MS_DEFAULT = 10_000;\nconst SUPPORTS_NOTIFICATION =\n typeof window !== \"undefined\" && \"Notification\" in window;\n\n/**\n * Header-bar bell that shows the unread-notification count and a dropdown of\n * recent entries. Polling keeps it in sync (the framework poll loop already\n * bumps a version counter so notifications ride on that signal, but we poll\n * the count endpoint directly so the bell updates even outside an app-state\n * change).\n */\nexport function NotificationsBell({\n pollMs = POLL_MS_DEFAULT,\n className,\n browserNotifications = false,\n}: NotificationsBellProps) {\n const [unreadCount, setUnreadCount] = useState(0);\n const [open, setOpen] = useState(false);\n const [items, setItems] = useState<NotificationDto[] | null>(null);\n // Init to \"default\" unconditionally so server and client render the same\n // HTML — reading Notification.permission at init would diverge between SSR\n // (\"denied\", no API) and hydration (\"default\"/\"granted\"), causing a mismatch\n // in templates that mount the bell outside a ClientOnly boundary. We sync\n // to the real value in a useEffect below.\n const [permission, setPermission] =\n useState<NotificationPermission>(\"default\");\n\n useEffect(() => {\n if (SUPPORTS_NOTIFICATION) setPermission(Notification.permission);\n }, []);\n // Ids already popped as browser notifications. Seeded on first run so\n // existing unread don't pop retroactively on page load.\n const seenIdsRef = useRef<Set<string> | null>(null);\n\n const loadItems = useCallback(async () => {\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications?limit=20\"),\n );\n if (!res.ok) return;\n const rows = (await res.json()) as NotificationDto[];\n setItems(rows);\n } catch {\n // best-effort\n }\n }, []);\n\n // One polling callback used by both paths. When browserNotifications is on\n // we fetch the unread list (source of truth for both the badge count AND\n // the popup loop — no second /count request), and pop Notification() for\n // any new ids. When off, we fetch just /count. The unread-list branch also\n // opts out of visibility pause so popups still fire for backgrounded tabs.\n const refresh = useCallback(async () => {\n if (browserNotifications) {\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications?unread=true&limit=20\"),\n );\n if (!res.ok) return;\n const rows = (await res.json()) as NotificationDto[];\n setUnreadCount(rows.length);\n // First run: treat everything as already seen so we don't pop\n // retroactively on page load. After that, rebuild from the current\n // unread list so ids for read/archived rows drop out — keeps the\n // set bounded to the unread fetch limit (~20).\n const prev = seenIdsRef.current;\n const seen = new Set<string>();\n for (const n of rows) {\n const alreadySeen = prev?.has(n.id) ?? true;\n seen.add(n.id);\n if (alreadySeen) continue;\n if (!SUPPORTS_NOTIFICATION) continue;\n if (Notification.permission !== \"granted\") continue;\n try {\n new Notification(n.title, { body: n.body, tag: n.id });\n } catch {\n // Safari / restricted contexts may throw even when permission\n // claims to be granted — silent no-op.\n }\n }\n seenIdsRef.current = seen;\n } catch {\n // best-effort\n }\n return;\n }\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications/count\"),\n );\n if (!res.ok) return;\n const data = (await res.json()) as { count: number };\n setUnreadCount(data.count);\n } catch {\n // best-effort\n }\n }, [browserNotifications]);\n\n usePausingInterval(\n refresh,\n pollMs,\n /* pauseWhenHidden */ !browserNotifications,\n );\n\n useEffect(() => {\n if (!open) return;\n loadItems();\n }, [open, loadItems]);\n\n const markRead = async (id: string) => {\n try {\n await fetch(agentNativePath(`/_agent-native/notifications/${id}/read`), {\n method: \"POST\",\n });\n setItems((prev) =>\n prev\n ? prev.map((n) =>\n n.id === id ? { ...n, readAt: new Date().toISOString() } : n,\n )\n : prev,\n );\n refresh();\n } catch {\n // best-effort\n }\n };\n\n const markAllRead = async () => {\n try {\n await fetch(agentNativePath(`/_agent-native/notifications/read-all`), {\n method: \"POST\",\n });\n setItems((prev) =>\n prev\n ? prev.map((n) =>\n n.readAt ? n : { ...n, readAt: new Date().toISOString() },\n )\n : prev,\n );\n setUnreadCount(0);\n } catch {\n // best-effort\n }\n };\n\n const dismiss = async (id: string) => {\n try {\n await fetch(agentNativePath(`/_agent-native/notifications/${id}`), {\n method: \"DELETE\",\n });\n setItems((prev) => (prev ? prev.filter((n) => n.id !== id) : prev));\n refresh();\n } catch {\n // best-effort\n }\n };\n\n const hasUnread = unreadCount > 0;\n const Icon = hasUnread ? IconBellRinging : IconBell;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasUnread ? `${unreadCount} unread notifications` : \"Notifications\"\n }\n className={\n \"an-notifications-bell__trigger relative inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/40 hover:text-foreground\" +\n (className ? ` ${className}` : \"\")\n }\n >\n <Icon size={18} aria-hidden />\n {hasUnread ? (\n <span\n aria-hidden\n className=\"an-notifications-bell__badge absolute -right-0.5 -top-0.5 rounded-full bg-destructive px-1 text-[10px] leading-[14px] font-medium text-destructive-foreground\"\n >\n {unreadCount > 99 ? \"99+\" : unreadCount}\n </span>\n ) : null}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n sideOffset={8}\n className=\"an-notifications-bell__menu w-80 p-0\"\n >\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2 text-sm font-medium\">\n <span>Notifications</span>\n {hasUnread ? (\n <button\n type=\"button\"\n onClick={markAllRead}\n className=\"text-xs text-primary hover:underline\"\n >\n Mark all read\n </button>\n ) : null}\n </div>\n {browserNotifications &&\n SUPPORTS_NOTIFICATION &&\n permission === \"default\" ? (\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-accent/40 px-3 py-2 text-xs text-foreground\">\n <span>Get a system popup for new notifications.</span>\n <button\n type=\"button\"\n onClick={async () => {\n const result = await Notification.requestPermission();\n setPermission(result);\n }}\n className=\"shrink-0 rounded bg-primary px-2 py-0.5 font-medium text-primary-foreground hover:bg-primary/90\"\n >\n Enable\n </button>\n </div>\n ) : null}\n <div className=\"max-h-96 overflow-y-auto\">\n {items === null ? (\n <div className=\"flex items-center gap-2 p-4 text-sm text-muted-foreground\">\n <IconLoader2 size={14} className=\"animate-spin\" /> Loading…\n </div>\n ) : items.length > 0 ? (\n items.map((n) => (\n <div\n key={n.id}\n className={\n \"group relative border-b border-border last:border-b-0 hover:bg-accent/40 \" +\n (n.readAt ? \"opacity-60\" : \"\")\n }\n >\n <button\n type=\"button\"\n onClick={() => (n.readAt ? undefined : markRead(n.id))}\n className=\"flex w-full flex-col items-start gap-0.5 px-3 py-2 pr-8 text-left\"\n >\n <div className=\"flex w-full items-center justify-between gap-2\">\n <span className=\"truncate text-sm font-medium text-foreground\">\n {n.title}\n </span>\n <SeverityBadge severity={n.severity} />\n </div>\n {n.body ? (\n <span className=\"line-clamp-2 text-xs text-muted-foreground\">\n {n.body}\n </span>\n ) : null}\n <span className=\"text-[10px] text-muted-foreground/70\">\n {new Date(n.createdAt).toLocaleString()}\n </span>\n </button>\n <button\n type=\"button\"\n aria-label=\"Dismiss notification\"\n onClick={(e) => {\n e.stopPropagation();\n void dismiss(n.id);\n }}\n className=\"absolute right-2 top-2 hidden rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground group-hover:flex\"\n >\n <IconX size={12} />\n </button>\n </div>\n ))\n ) : (\n <div className=\"p-4 text-sm text-muted-foreground\">\n No notifications.\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\n// Severity color pairs — use /20 opacity backdrops that work against both\n// light and dark theme backgrounds; text uses 700/300 so it stays readable\n// in each mode (the `dark:` prefix is one of the few places where explicit\n// variants are necessary since these are brand-color tokens, not semantic).\nfunction SeverityBadge({ severity }: { severity: NotificationSeverity }) {\n const color =\n severity === \"critical\"\n ? \"bg-red-500/20 text-red-700 dark:text-red-300\"\n : severity === \"warning\"\n ? \"bg-amber-500/20 text-amber-700 dark:text-amber-300\"\n : \"bg-muted text-muted-foreground\";\n return (\n <span className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${color}`}>\n {severity}\n </span>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"NotificationsBell.js","sourceRoot":"","sources":["../../../src/client/notifications/NotificationsBell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, appPath } from \"../api-path.js\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n IconBell,\n IconBellRinging,\n IconLoader2,\n IconX,\n} from \"@tabler/icons-react\";\nimport { usePausingInterval } from \"../use-pausing-interval.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport type {\n Notification as NotificationDto,\n NotificationSeverity,\n} from \"../../notifications/types.js\";\n\ninterface NotificationsBellProps {\n /** Poll interval in ms. Set to 0 to disable polling. Default: 10000. */\n pollMs?: number;\n /** Optional className for the outer container. */\n className?: string;\n /**\n * When true, fires a system-level `new Notification(...)` popup for each\n * new unread notification — handy when the tab is in the background.\n * Renders an \"Enable browser notifications\" prompt in the dropdown until\n * the user grants permission. Silently no-ops on denied or unsupported.\n */\n browserNotifications?: boolean;\n}\n\nconst POLL_MS_DEFAULT = 10_000;\nconst SUPPORTS_NOTIFICATION =\n typeof window !== \"undefined\" && \"Notification\" in window;\n\n/**\n * Header-bar bell that shows the unread-notification count and a dropdown of\n * recent entries. Polling keeps it in sync (the framework poll loop already\n * bumps a version counter so notifications ride on that signal, but we poll\n * the count endpoint directly so the bell updates even outside an app-state\n * change).\n */\nexport function NotificationsBell({\n pollMs = POLL_MS_DEFAULT,\n className,\n browserNotifications = false,\n}: NotificationsBellProps) {\n const [unreadCount, setUnreadCount] = useState(0);\n const [open, setOpen] = useState(false);\n const [items, setItems] = useState<NotificationDto[] | null>(null);\n // Init to \"default\" unconditionally so server and client render the same\n // HTML — reading Notification.permission at init would diverge between SSR\n // (\"denied\", no API) and hydration (\"default\"/\"granted\"), causing a mismatch\n // in templates that mount the bell outside a ClientOnly boundary. We sync\n // to the real value in a useEffect below.\n const [permission, setPermission] =\n useState<NotificationPermission>(\"default\");\n\n useEffect(() => {\n if (SUPPORTS_NOTIFICATION) setPermission(Notification.permission);\n }, []);\n // Ids already popped as browser notifications. Seeded on first run so\n // existing unread don't pop retroactively on page load.\n const seenIdsRef = useRef<Set<string> | null>(null);\n\n const loadItems = useCallback(async () => {\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications?limit=20\"),\n );\n if (!res.ok) return;\n const rows = (await res.json()) as NotificationDto[];\n setItems(rows);\n } catch {\n // best-effort\n }\n }, []);\n\n // One polling callback used by both paths. When browserNotifications is on\n // we fetch the unread list (source of truth for both the badge count AND\n // the popup loop — no second /count request), and pop Notification() for\n // any new ids. When off, we fetch just /count. The unread-list branch also\n // opts out of visibility pause so popups still fire for backgrounded tabs.\n const refresh = useCallback(async () => {\n if (browserNotifications) {\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications?unread=true&limit=20\"),\n );\n if (!res.ok) return;\n const rows = (await res.json()) as NotificationDto[];\n setUnreadCount(rows.length);\n // First run: treat everything as already seen so we don't pop\n // retroactively on page load. After that, rebuild from the current\n // unread list so ids for read/archived rows drop out — keeps the\n // set bounded to the unread fetch limit (~20).\n const prev = seenIdsRef.current;\n const seen = new Set<string>();\n for (const n of rows) {\n const alreadySeen = prev?.has(n.id) ?? true;\n seen.add(n.id);\n if (alreadySeen) continue;\n if (!SUPPORTS_NOTIFICATION) continue;\n if (Notification.permission !== \"granted\") continue;\n try {\n new Notification(n.title, { body: n.body, tag: n.id });\n } catch {\n // Safari / restricted contexts may throw even when permission\n // claims to be granted — silent no-op.\n }\n }\n seenIdsRef.current = seen;\n } catch {\n // best-effort\n }\n return;\n }\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/notifications/count\"),\n );\n if (!res.ok) return;\n const data = (await res.json()) as { count: number };\n setUnreadCount(data.count);\n } catch {\n // best-effort\n }\n }, [browserNotifications]);\n\n usePausingInterval(\n refresh,\n pollMs,\n /* pauseWhenHidden */ !browserNotifications,\n );\n\n useEffect(() => {\n if (!open) return;\n loadItems();\n }, [open, loadItems]);\n\n const markRead = async (id: string) => {\n try {\n // `keepalive: true` lets the request survive page navigation —\n // without it, clicking a notification with a link aborts this\n // request mid-flight and the row stays unread.\n await fetch(agentNativePath(`/_agent-native/notifications/${id}/read`), {\n method: \"POST\",\n keepalive: true,\n });\n setItems((prev) =>\n prev\n ? prev.map((n) =>\n n.id === id ? { ...n, readAt: new Date().toISOString() } : n,\n )\n : prev,\n );\n refresh();\n } catch {\n // best-effort\n }\n };\n\n // Reject any URL that isn't http(s) or a same-origin relative path. Blocks\n // `javascript:` execution, `data:` URIs, and absolute redirects to phishing\n // sites. Relative paths starting with `/` are routed through `appPath()` so\n // the link works in mounted deployments (e.g. /mail subdirectory).\n const safeNotificationLink = (link: string): string | null => {\n if (link.startsWith(\"/\") && !link.startsWith(\"//\")) {\n return appPath(link);\n }\n try {\n const url = new URL(link, window.location.origin);\n if (url.protocol === \"http:\" || url.protocol === \"https:\") {\n return url.toString();\n }\n } catch {\n // fallthrough\n }\n return null;\n };\n\n const markAllRead = async () => {\n try {\n await fetch(agentNativePath(`/_agent-native/notifications/read-all`), {\n method: \"POST\",\n });\n setItems((prev) =>\n prev\n ? prev.map((n) =>\n n.readAt ? n : { ...n, readAt: new Date().toISOString() },\n )\n : prev,\n );\n setUnreadCount(0);\n } catch {\n // best-effort\n }\n };\n\n const dismiss = async (id: string) => {\n try {\n await fetch(agentNativePath(`/_agent-native/notifications/${id}`), {\n method: \"DELETE\",\n });\n setItems((prev) => (prev ? prev.filter((n) => n.id !== id) : prev));\n refresh();\n } catch {\n // best-effort\n }\n };\n\n const hasUnread = unreadCount > 0;\n const Icon = hasUnread ? IconBellRinging : IconBell;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasUnread ? `${unreadCount} unread notifications` : \"Notifications\"\n }\n className={\n \"an-notifications-bell__trigger relative inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/40 hover:text-foreground\" +\n (className ? ` ${className}` : \"\")\n }\n >\n <Icon size={18} aria-hidden />\n {hasUnread ? (\n <span\n aria-hidden\n className=\"an-notifications-bell__badge absolute -right-0.5 -top-0.5 rounded-full bg-destructive px-1 text-[10px] leading-[14px] font-medium text-destructive-foreground\"\n >\n {unreadCount > 99 ? \"99+\" : unreadCount}\n </span>\n ) : null}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n sideOffset={8}\n className=\"an-notifications-bell__menu w-80 p-0\"\n >\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2 text-sm font-medium\">\n <span>Notifications</span>\n {hasUnread ? (\n <button\n type=\"button\"\n onClick={markAllRead}\n className=\"text-xs text-primary hover:underline\"\n >\n Mark all read\n </button>\n ) : null}\n </div>\n {browserNotifications &&\n SUPPORTS_NOTIFICATION &&\n permission === \"default\" ? (\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-accent/40 px-3 py-2 text-xs text-foreground\">\n <span>Get a system popup for new notifications.</span>\n <button\n type=\"button\"\n onClick={async () => {\n const result = await Notification.requestPermission();\n setPermission(result);\n }}\n className=\"shrink-0 rounded bg-primary px-2 py-0.5 font-medium text-primary-foreground hover:bg-primary/90\"\n >\n Enable\n </button>\n </div>\n ) : null}\n <div className=\"max-h-96 overflow-y-auto\">\n {items === null ? (\n <div className=\"flex items-center gap-2 p-4 text-sm text-muted-foreground\">\n <IconLoader2 size={14} className=\"animate-spin\" /> Loading…\n </div>\n ) : items.length > 0 ? (\n items.map((n) => {\n const rawLink =\n typeof n.metadata?.link === \"string\" ? n.metadata.link : null;\n const link = rawLink ? safeNotificationLink(rawLink) : null;\n const onItemClick = () => {\n if (!n.readAt) void markRead(n.id);\n if (link) {\n setOpen(false);\n window.location.assign(link);\n }\n };\n return (\n <div\n key={n.id}\n className={\n \"group relative border-b border-border last:border-b-0 hover:bg-accent/40 \" +\n (n.readAt ? \"opacity-60\" : \"\")\n }\n >\n <button\n type=\"button\"\n onClick={onItemClick}\n className={\n \"flex w-full flex-col items-start gap-0.5 px-3 py-2 pr-8 text-left\" +\n (link ? \" cursor-pointer\" : \"\")\n }\n >\n <div className=\"flex w-full items-center justify-between gap-2\">\n <span className=\"truncate text-sm font-medium text-foreground\">\n {n.title}\n </span>\n <SeverityBadge severity={n.severity} />\n </div>\n {n.body ? (\n <span className=\"line-clamp-2 text-xs text-muted-foreground\">\n {n.body}\n </span>\n ) : null}\n <span className=\"text-[10px] text-muted-foreground/70\">\n {new Date(n.createdAt).toLocaleString()}\n </span>\n </button>\n <button\n type=\"button\"\n aria-label=\"Dismiss notification\"\n onClick={(e) => {\n e.stopPropagation();\n void dismiss(n.id);\n }}\n className=\"absolute right-2 top-2 hidden rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground group-hover:flex\"\n >\n <IconX size={12} />\n </button>\n </div>\n );\n })\n ) : (\n <div className=\"p-4 text-sm text-muted-foreground\">\n No notifications.\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\n// Severity color pairs — use /20 opacity backdrops that work against both\n// light and dark theme backgrounds; text uses 700/300 so it stays readable\n// in each mode (the `dark:` prefix is one of the few places where explicit\n// variants are necessary since these are brand-color tokens, not semantic).\nfunction SeverityBadge({ severity }: { severity: NotificationSeverity }) {\n const color =\n severity === \"critical\"\n ? \"bg-red-500/20 text-red-700 dark:text-red-300\"\n : severity === \"warning\"\n ? \"bg-amber-500/20 text-amber-700 dark:text-amber-300\"\n : \"bg-muted text-muted-foreground\";\n return (\n <span className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${color}`}>\n {severity}\n </span>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OnboardingPanel.d.ts","sourceRoot":"","sources":["../../../src/client/onboarding/OnboardingPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OnboardingPanel.d.ts","sourceRoot":"","sources":["../../../src/client/onboarding/OnboardingPanel.tsx"],"names":[],"mappings":"AAqCA,UAAU,oBAAoB;IAC5B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,KAAe,GAChB,EAAE,oBAAoB,2CA6HtB"}
|
|
@@ -14,6 +14,7 @@ import { useOnboardingPreviewMode } from "./use-preview-mode.js";
|
|
|
14
14
|
import { sendToAgentChat } from "../agent-chat.js";
|
|
15
15
|
import { useDevMode } from "../use-dev-mode.js";
|
|
16
16
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
17
|
+
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
17
18
|
export function OnboardingPanel({ className, title = "Setup", }) {
|
|
18
19
|
const previewMode = useOnboardingPreviewMode();
|
|
19
20
|
const onboarding = useOnboarding({ preview: previewMode });
|
|
@@ -52,9 +53,9 @@ export function OnboardingPanel({ className, title = "Setup", }) {
|
|
|
52
53
|
return null;
|
|
53
54
|
}
|
|
54
55
|
if (!expanded) {
|
|
55
|
-
return (_jsx("div", { className: className, style: styles.compactBanner, children: _jsxs("button", { type: "button", onClick: () => setExpanded(true), style: styles.compactBannerBtn,
|
|
56
|
+
return (_jsx("div", { className: className, style: styles.compactBanner, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => setExpanded(true), style: styles.compactBannerBtn, "aria-label": "Expand setup", children: [_jsx("span", { style: allComplete ? styles.checkDone : styles.checkTodo, children: allComplete ? _jsx(IconCheck, { size: 12, strokeWidth: 3 }) : null }), _jsx("span", { style: styles.headerTitle, children: title }), _jsxs("span", { style: styles.headerCounter, children: [completeCount, " of ", totalCount] }), _jsx("span", { style: { marginLeft: "auto", opacity: 0.5, display: "flex" }, children: _jsx(IconChevronDown, { size: 14 }) })] }) }), _jsx(TooltipContent, { children: "Expand setup" })] }) }));
|
|
56
57
|
}
|
|
57
|
-
return (_jsxs("div", { className: className, style: styles.root, children: [_jsxs("div", { style: styles.header, children: [_jsxs("div", { style: styles.headerLeft, children: [allComplete ? (_jsx("span", { style: styles.checkDone, children: _jsx(IconCheck, { size: 12, strokeWidth: 3 }) })) : (_jsx(IconChecklist, { size: 14, style: styles.headerIcon, "aria-hidden": true })), _jsx("span", { style: styles.headerTitle, children: title }), _jsxs("span", { style: styles.headerCounter, children: [completeCount, " of ", totalCount] })] }), _jsx("button", { type: "button", onClick: () => setExpanded(false),
|
|
58
|
+
return (_jsxs("div", { className: className, style: styles.root, children: [_jsxs("div", { style: styles.header, children: [_jsxs("div", { style: styles.headerLeft, children: [allComplete ? (_jsx("span", { style: styles.checkDone, children: _jsx(IconCheck, { size: 12, strokeWidth: 3 }) })) : (_jsx(IconChecklist, { size: 14, style: styles.headerIcon, "aria-hidden": true })), _jsx("span", { style: styles.headerTitle, children: title }), _jsxs("span", { style: styles.headerCounter, children: [completeCount, " of ", totalCount] })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setExpanded(false), "aria-label": "Collapse onboarding", style: styles.dismissBtn, children: _jsx(IconChevronUp, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Collapse" })] })] }), _jsx("div", { style: styles.list, children: steps.map((step) => (_jsx(StepCard, { step: step, expanded: step.id === currentStepId, onMarkComplete: () => complete(step.id), onRefresh: refresh }, step.id))) }), _jsx("div", { style: styles.footer, children: _jsx("button", { type: "button", onClick: dismiss, style: styles.hideLink, children: "Hide setup" }) })] }));
|
|
58
59
|
}
|
|
59
60
|
// ─── StepCard ──────────────────────────────────────────────────────────────
|
|
60
61
|
function StepCard({ step, expanded: expandedProp, onMarkComplete, onRefresh, }) {
|