@agent-native/core 0.98.4 → 0.98.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/docs/content/durable-background-runs.mdx +37 -0
- package/corpus/core/docs/content/external-agents.mdx +62 -7
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/handlers.ts +95 -21
- package/corpus/core/src/a2a/task-store.ts +65 -3
- package/corpus/core/src/agent/durable-background.ts +16 -16
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +25 -8
- package/corpus/core/src/agent/engine/anthropic-engine.ts +17 -3
- package/corpus/core/src/agent/engine/output-tokens.ts +6 -6
- package/corpus/core/src/agent/production-agent.ts +200 -27
- package/corpus/core/src/agent/run-manager.ts +81 -1
- package/corpus/core/src/agent/run-store.ts +301 -41
- package/corpus/core/src/client/AgentPanel.tsx +6 -2
- package/corpus/core/src/client/AssistantChat.tsx +364 -69
- package/corpus/core/src/client/agent-chat-adapter.ts +169 -1
- package/corpus/core/src/client/chat/message-components.tsx +3 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +20 -36
- package/corpus/core/src/client/conversation/use-near-bottom-autoscroll.ts +7 -0
- package/corpus/core/src/client/extensions/AgentNativeExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +2 -0
- package/corpus/core/src/client/extensions/ExtensionEditor.tsx +9 -2
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +2 -0
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/portable-extension.ts +2 -0
- package/corpus/core/src/client/session-replay.ts +361 -29
- package/corpus/core/src/client/sse-event-processor.ts +43 -1
- package/corpus/core/src/demo/actions/toggle-demo-mode.ts +1 -1
- package/corpus/core/src/demo/config.ts +6 -6
- package/corpus/core/src/demo/fetch-interceptor.ts +13 -4
- package/corpus/core/src/demo/redact.ts +13 -149
- package/corpus/core/src/extensions/html-shell.ts +3 -0
- package/corpus/core/src/extensions/session-replay-iframe.ts +131 -0
- package/corpus/core/src/integrations/adapters/slack.ts +123 -13
- package/corpus/core/src/integrations/identity-links-store.ts +210 -0
- package/corpus/core/src/integrations/identity.ts +132 -0
- package/corpus/core/src/integrations/index.ts +6 -0
- package/corpus/core/src/integrations/plugin.ts +58 -1
- package/corpus/core/src/integrations/types.ts +7 -0
- package/corpus/core/src/mcp/build-server.ts +127 -22
- package/corpus/core/src/mcp/external-agent-policy.ts +18 -0
- package/corpus/core/src/mcp/index.ts +1 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -20
- package/corpus/core/src/server/agent-chat/plugin-options.ts +12 -1
- package/corpus/core/src/server/agent-chat/script-entries.ts +20 -3
- package/corpus/core/src/server/agent-chat-plugin.ts +3 -0
- package/corpus/core/src/session-replay-iframe-protocol.ts +58 -0
- package/corpus/core/src/shared/reasoning-effort.ts +35 -0
- package/corpus/core/src/styles/agent-conversation.css +26 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +30 -21
- package/corpus/templates/analytics/AGENTS.md +27 -0
- package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +0 -1
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-summary.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-timeline.ts +40 -0
- package/corpus/templates/analytics/actions/list-error-issues.ts +13 -0
- package/corpus/templates/analytics/actions/list-session-recordings.ts +1 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -0
- package/corpus/templates/analytics/app/global.css +2 -2
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +41 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +52 -203
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +69 -16
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-chat-retries-before-showing-a-generic-no-data-mess.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-sessions-search-no-longer-loses-fast-keystrokes-an.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-chart-selection-respects-chat-state.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-connected-external-agents-can-now-look-up-sessions-error-iss.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-anonymizes-error-reporting-emails.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-identities-stay-visible-when-demo-mode-is-off.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-replays-show-iframe-content.md +6 -0
- package/corpus/templates/analytics/netlify.toml +0 -3
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +14 -0
- package/corpus/templates/analytics/server/lib/error-capture.ts +101 -2
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +24 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +49 -17
- package/corpus/templates/analytics/server/lib/session-replay.ts +18 -16
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +43 -6
- package/corpus/templates/analytics/server/plugins/db.ts +15 -0
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/brain/app/global.css +2 -2
- package/corpus/templates/brain/changelog/2026-07-12-fix-long-response-progress.md +6 -0
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +1 -1
- package/corpus/templates/forms/app/components/ThemeToggle.tsx +22 -6
- package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +5 -5
- package/corpus/templates/forms/app/components/builder/FieldRenderer.tsx +3 -3
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +16 -16
- package/corpus/templates/forms/app/global.css +164 -13
- package/corpus/templates/forms/app/pages/AskPage.tsx +35 -13
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +143 -67
- package/corpus/templates/forms/app/pages/FormFillPage.tsx +44 -11
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +42 -24
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +28 -15
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +46 -20
- package/corpus/templates/forms/app/routes/_app.settings.tsx +1 -1
- package/corpus/templates/forms/changelog/2026-07-12-ask-forms-suggestions-now-sit-beneath-the-composer-for-a-tig.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-builder-response-tables-now-fill-the-view-without-a-redundan.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-form-builder-surfaces-are-calmer-fields-stay-stable-on-hover.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-response-tables-now-fill-the-available-pane-with-a-flexible-.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-smoother-more-tactile-controls-throughout-animated-icon-and-.md +6 -0
- package/corpus/templates/mail/AGENTS.md +3 -1
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +21 -13
- package/corpus/templates/mail/app/components/email/email-iframe-document.ts +18 -0
- package/corpus/templates/mail/server/lib/mail-integrations.ts +3 -0
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +84 -15
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/task-store.d.ts +20 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +57 -4
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/durable-background.d.ts +10 -10
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +16 -16
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +19 -8
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +11 -3
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/output-tokens.js +6 -6
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/production-agent.d.ts +52 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +154 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +71 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +9 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +243 -48
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +298 -67
- 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 +146 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +2 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +3 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +13 -37
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts +1 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +6 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js +2 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +2 -1
- 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 +5 -2
- package/dist/client/extensions/ExtensionEditor.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +2 -1
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +2 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +2 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +308 -29
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +5 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +37 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/demo/actions/toggle-demo-mode.js +1 -1
- package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
- package/dist/demo/config.js +6 -6
- package/dist/demo/config.js.map +1 -1
- package/dist/demo/fetch-interceptor.d.ts.map +1 -1
- package/dist/demo/fetch-interceptor.js +13 -4
- package/dist/demo/fetch-interceptor.js.map +1 -1
- package/dist/demo/redact.d.ts +7 -7
- package/dist/demo/redact.d.ts.map +1 -1
- package/dist/demo/redact.js +8 -145
- package/dist/demo/redact.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +2 -0
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/session-replay-iframe.d.ts +10 -0
- package/dist/extensions/session-replay-iframe.d.ts.map +1 -0
- package/dist/extensions/session-replay-iframe.js +121 -0
- package/dist/extensions/session-replay-iframe.js.map +1 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +98 -13
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/identity-links-store.d.ts +23 -0
- package/dist/integrations/identity-links-store.d.ts.map +1 -0
- package/dist/integrations/identity-links-store.js +158 -0
- package/dist/integrations/identity-links-store.js.map +1 -0
- package/dist/integrations/identity.d.ts +11 -0
- package/dist/integrations/identity.d.ts.map +1 -0
- package/dist/integrations/identity.js +100 -0
- package/dist/integrations/identity.js.map +1 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +43 -1
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +6 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/mcp/build-server.d.ts +9 -2
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +97 -20
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/external-agent-policy.d.ts +19 -0
- package/dist/mcp/external-agent-policy.d.ts.map +1 -0
- package/dist/mcp/external-agent-policy.js +2 -0
- package/dist/mcp/external-agent-policy.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -19
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +11 -1
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +16 -2
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/session-replay-iframe-protocol.d.ts +36 -0
- package/dist/session-replay-iframe-protocol.d.ts.map +1 -0
- package/dist/session-replay-iframe-protocol.js +24 -0
- package/dist/session-replay-iframe-protocol.js.map +1 -0
- package/dist/shared/reasoning-effort.d.ts +11 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +36 -0
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/styles/agent-conversation.css +26 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/docs/content/durable-background-runs.mdx +37 -0
- package/docs/content/external-agents.mdx +62 -7
- package/docs/content/locales/ar-SA/external-agents.mdx +38 -7
- package/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/docs/content/locales/de-DE/external-agents.mdx +39 -7
- package/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/docs/content/locales/es-ES/external-agents.mdx +39 -7
- package/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/docs/content/locales/fr-FR/external-agents.mdx +39 -7
- package/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/docs/content/locales/hi-IN/external-agents.mdx +38 -7
- package/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/docs/content/locales/ja-JP/external-agents.mdx +38 -7
- package/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/docs/content/locales/ko-KR/external-agents.mdx +38 -7
- package/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/docs/content/locales/pt-BR/external-agents.mdx +39 -7
- package/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/docs/content/locales/zh-CN/external-agents.mdx +37 -7
- package/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/docs/content/locales/zh-TW/external-agents.mdx +37 -7
- package/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/docs/content/tracking.mdx +2 -0
- package/package.json +2 -2
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +34 -5
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Demo mode gate.
|
|
3
3
|
*
|
|
4
|
-
* Demo mode replaces email
|
|
5
|
-
*
|
|
6
|
-
* preserving names, free text, labels, IDs, dates, URLs,
|
|
7
|
-
* app keeps working. The redaction WALK (see ./redact.ts)
|
|
8
|
-
* large payloads, so callers MUST gate it behind this function
|
|
9
|
-
* when it returns true.
|
|
4
|
+
* Demo mode replaces every email address with `anonymous@builder.io` and
|
|
5
|
+
* anonymizes numbers in every action result — for both the UI and what the
|
|
6
|
+
* agent sees — while preserving names, free text, labels, IDs, dates, URLs,
|
|
7
|
+
* and structure so the app keeps working. The redaction WALK (see ./redact.ts)
|
|
8
|
+
* is expensive on large payloads, so callers MUST gate it behind this function
|
|
9
|
+
* and only walk when it returns true.
|
|
10
10
|
*
|
|
11
11
|
* This gate itself is intentionally cheap:
|
|
12
12
|
* - An env-forced deployment (a hosted demo site) short-circuits with zero
|
|
@@ -46,10 +46,19 @@ const SKIP_SUBSTRINGS = [
|
|
|
46
46
|
"/_agent-native/runs",
|
|
47
47
|
];
|
|
48
48
|
|
|
49
|
-
// Raw rrweb payloads are playback data, not ordinary app UI records.
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
49
|
+
// Raw rrweb payloads are playback data, not ordinary app UI records. Skipping
|
|
50
|
+
// these is not just a perf optimization that avoids walking/cloning huge
|
|
51
|
+
// DOM/event trees on the main thread: demo number
|
|
52
|
+
// redaction previously ran over this exact raw replay JSON and faked any
|
|
53
|
+
// integer >= 1000 it found — Meta/ViewportResize widths, pointer x/y
|
|
54
|
+
// coordinates, and numeric values inside `_cssText` and SVG attributes. That
|
|
55
|
+
// was the root cause of the 2026-07 "ultra-wide replay" bugs (stages
|
|
56
|
+
// rendered thousands of pixels wide, frozen/teleporting cursors, giant
|
|
57
|
+
// icons) even though every stored recording was always geometrically sane —
|
|
58
|
+
// the corruption happened at *view* time, not at capture/storage time. Small
|
|
59
|
+
// list/summary/manifest responses stay eligible so rendered visitor identities
|
|
60
|
+
// are still anonymized. NEVER remove the raw payload skips or broaden them to
|
|
61
|
+
// metadata endpoints that the UI renders directly.
|
|
53
62
|
const RAW_REPLAY_PAYLOAD_RE =
|
|
54
63
|
/\/api\/session-replay\/recordings\/[^/?#]+\/(?:chunks(?:\/[^/?#]+)?|events)(?:[/?#]|$)/;
|
|
55
64
|
const RAW_AGENT_REPLAY_EVENTS_RE =
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure, dependency-free, deterministic demo-mode redactor.
|
|
3
3
|
*
|
|
4
|
-
* Replaces
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* placeholders before any transform runs, restore them byte-identical
|
|
4
|
+
* Replaces every email with one canonical anonymous address and free numbers
|
|
5
|
+
* with stable fake substitutes. Crucially, it NEVER rewrites identifiers,
|
|
6
|
+
* structural tokens, or timestamps. Names and other free text are deliberately
|
|
7
|
+
* left alone because guessing whether arbitrary text is a person's name is too
|
|
8
|
+
* inaccurate. The string redactor uses a protect-first strategy (mask IDs with
|
|
9
|
+
* opaque placeholders before any transform runs, restore them byte-identical
|
|
11
10
|
* afterwards), and the structure-aware walker additionally protects leaf
|
|
12
11
|
* values by key name.
|
|
13
12
|
*/
|
|
@@ -58,10 +57,6 @@ function seededRng(value: string, salt: string): () => number {
|
|
|
58
57
|
return mulberry32(seedFn());
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
function pick<T>(rng: () => number, pool: readonly T[]): T {
|
|
62
|
-
return pool[Math.floor(rng() * pool.length) % pool.length];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
60
|
/* ------------------------------------------------------------------ *
|
|
66
61
|
* Stable mapping cache (bounded, TTL, leak-free)
|
|
67
62
|
*
|
|
@@ -157,150 +152,19 @@ function memoFake(
|
|
|
157
152
|
return value;
|
|
158
153
|
}
|
|
159
154
|
|
|
160
|
-
/* ------------------------------------------------------------------ *
|
|
161
|
-
* Curated name pools
|
|
162
|
-
* ------------------------------------------------------------------ */
|
|
163
|
-
|
|
164
|
-
const FIRST_NAMES: readonly string[] = [
|
|
165
|
-
"Jane",
|
|
166
|
-
"John",
|
|
167
|
-
"Alex",
|
|
168
|
-
"Maria",
|
|
169
|
-
"Sam",
|
|
170
|
-
"Olivia",
|
|
171
|
-
"Liam",
|
|
172
|
-
"Emma",
|
|
173
|
-
"Noah",
|
|
174
|
-
"Ava",
|
|
175
|
-
"Lucas",
|
|
176
|
-
"Mia",
|
|
177
|
-
"Ethan",
|
|
178
|
-
"Sofia",
|
|
179
|
-
"Mason",
|
|
180
|
-
"Isla",
|
|
181
|
-
"Leo",
|
|
182
|
-
"Aria",
|
|
183
|
-
"Henry",
|
|
184
|
-
"Zoe",
|
|
185
|
-
"Owen",
|
|
186
|
-
"Nora",
|
|
187
|
-
"Caleb",
|
|
188
|
-
"Lily",
|
|
189
|
-
"Ryan",
|
|
190
|
-
"Ruby",
|
|
191
|
-
"Adam",
|
|
192
|
-
"Chloe",
|
|
193
|
-
"Eli",
|
|
194
|
-
"Hazel",
|
|
195
|
-
"Max",
|
|
196
|
-
"Iris",
|
|
197
|
-
"Ben",
|
|
198
|
-
"Clara",
|
|
199
|
-
"Theo",
|
|
200
|
-
"Maya",
|
|
201
|
-
"Felix",
|
|
202
|
-
"Elena",
|
|
203
|
-
"Jonah",
|
|
204
|
-
"Greta",
|
|
205
|
-
];
|
|
206
|
-
|
|
207
|
-
const LAST_NAMES: readonly string[] = [
|
|
208
|
-
"Doe",
|
|
209
|
-
"Smith",
|
|
210
|
-
"Johnson",
|
|
211
|
-
"Lee",
|
|
212
|
-
"Brown",
|
|
213
|
-
"Garcia",
|
|
214
|
-
"Miller",
|
|
215
|
-
"Davis",
|
|
216
|
-
"Wilson",
|
|
217
|
-
"Moore",
|
|
218
|
-
"Taylor",
|
|
219
|
-
"Anderson",
|
|
220
|
-
"Thomas",
|
|
221
|
-
"Jackson",
|
|
222
|
-
"White",
|
|
223
|
-
"Harris",
|
|
224
|
-
"Martin",
|
|
225
|
-
"Clark",
|
|
226
|
-
"Lewis",
|
|
227
|
-
"Walker",
|
|
228
|
-
"Hall",
|
|
229
|
-
"Young",
|
|
230
|
-
"King",
|
|
231
|
-
"Wright",
|
|
232
|
-
"Hill",
|
|
233
|
-
"Green",
|
|
234
|
-
"Adams",
|
|
235
|
-
"Baker",
|
|
236
|
-
"Nelson",
|
|
237
|
-
"Carter",
|
|
238
|
-
"Mitchell",
|
|
239
|
-
"Perez",
|
|
240
|
-
"Roberts",
|
|
241
|
-
"Turner",
|
|
242
|
-
"Phillips",
|
|
243
|
-
"Campbell",
|
|
244
|
-
"Parker",
|
|
245
|
-
"Evans",
|
|
246
|
-
"Edwards",
|
|
247
|
-
"Collins",
|
|
248
|
-
];
|
|
249
|
-
|
|
250
155
|
/* ------------------------------------------------------------------ *
|
|
251
156
|
* Fake value generators (deterministic in value + salt)
|
|
252
157
|
* ------------------------------------------------------------------ */
|
|
253
158
|
|
|
254
|
-
|
|
255
|
-
// local part is fake, so no real mailbox is implied) plus the canonical
|
|
256
|
-
// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read
|
|
257
|
-
// as real businesses but are intentional placeholders. No example.com.
|
|
258
|
-
const FAKE_EMAIL_DOMAINS: readonly string[] = [
|
|
259
|
-
"gmail.com",
|
|
260
|
-
"outlook.com",
|
|
261
|
-
"icloud.com",
|
|
262
|
-
"yahoo.com",
|
|
263
|
-
"proton.me",
|
|
264
|
-
"hey.com",
|
|
265
|
-
"fastmail.com",
|
|
266
|
-
"contoso.com",
|
|
267
|
-
"fabrikam.com",
|
|
268
|
-
"northwind.com",
|
|
269
|
-
"acme.io",
|
|
270
|
-
"globex.net",
|
|
271
|
-
];
|
|
159
|
+
export const DEMO_ANONYMOUS_EMAIL = "anonymous@builder.io";
|
|
272
160
|
|
|
273
161
|
function fakeEmail(original: string, salt: string): string {
|
|
274
|
-
return memoFake(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const shape = Math.floor(rng() * 6);
|
|
281
|
-
let local: string;
|
|
282
|
-
switch (shape) {
|
|
283
|
-
case 0:
|
|
284
|
-
local = `${first}.${last}`;
|
|
285
|
-
break;
|
|
286
|
-
case 1:
|
|
287
|
-
local = `${first}${last}`;
|
|
288
|
-
break;
|
|
289
|
-
case 2:
|
|
290
|
-
local = `${first[0]}${last}`;
|
|
291
|
-
break;
|
|
292
|
-
case 3:
|
|
293
|
-
local = `${first}.${last}${1 + Math.floor(rng() * 89)}`;
|
|
294
|
-
break;
|
|
295
|
-
case 4:
|
|
296
|
-
local = `${first}_${last}`;
|
|
297
|
-
break;
|
|
298
|
-
default:
|
|
299
|
-
local = `${last}.${first}`;
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
return `${local}@${domain}`;
|
|
303
|
-
});
|
|
162
|
+
return memoFake(
|
|
163
|
+
"email",
|
|
164
|
+
original.toLowerCase(),
|
|
165
|
+
salt,
|
|
166
|
+
() => DEMO_ANONYMOUS_EMAIL,
|
|
167
|
+
);
|
|
304
168
|
}
|
|
305
169
|
|
|
306
170
|
/**
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { buildSessionReplayIframeBootstrap } from "./session-replay-iframe.js";
|
|
2
|
+
|
|
1
3
|
const EXTENSION_IFRAME_CSP_BASE =
|
|
2
4
|
"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';";
|
|
3
5
|
|
|
@@ -744,6 +746,7 @@ export function buildExtensionHtml(
|
|
|
744
746
|
}
|
|
745
747
|
});
|
|
746
748
|
</script>
|
|
749
|
+
${buildSessionReplayIframeBootstrap()}
|
|
747
750
|
</head>
|
|
748
751
|
<body${extensionId ? ` data-extension-id="${extensionIdAttr}" data-tool-id="${extensionIdAttr}"` : ""} class="text-foreground">
|
|
749
752
|
${content}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isTrustedSessionReplayIframeParentOrigin,
|
|
3
|
+
SESSION_REPLAY_IFRAME_PROBE,
|
|
4
|
+
SESSION_REPLAY_IFRAME_START,
|
|
5
|
+
SESSION_REPLAY_IFRAME_STOP,
|
|
6
|
+
} from "../session-replay-iframe-protocol.js";
|
|
7
|
+
|
|
8
|
+
export const RRWEB_RECORD_IFRAME_CDN_URL =
|
|
9
|
+
"https://cdn.jsdelivr.net/npm/@rrweb/record@2.1.0/umd/record.min.js";
|
|
10
|
+
export const RRWEB_RECORD_IFRAME_SRI =
|
|
11
|
+
"sha384-MrD66HBNSykaP2N95+6hQCFlF5oH2tvL3TD/zyvHNkP/sAFWZx98DX9MEDy8MdVT";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Installs the cooperative side of rrweb's cross-origin iframe protocol.
|
|
15
|
+
* Nothing is fetched or recorded until a trusted first-party parent asks the
|
|
16
|
+
* frame to start. rrweb then forwards its events directly to that parent.
|
|
17
|
+
*/
|
|
18
|
+
export function buildSessionReplayIframeBootstrap(): string {
|
|
19
|
+
const probeType = JSON.stringify(SESSION_REPLAY_IFRAME_PROBE);
|
|
20
|
+
const startType = JSON.stringify(SESSION_REPLAY_IFRAME_START);
|
|
21
|
+
const stopType = JSON.stringify(SESSION_REPLAY_IFRAME_STOP);
|
|
22
|
+
const scriptUrl = JSON.stringify(RRWEB_RECORD_IFRAME_CDN_URL);
|
|
23
|
+
const integrity = JSON.stringify(RRWEB_RECORD_IFRAME_SRI);
|
|
24
|
+
|
|
25
|
+
return `<script>
|
|
26
|
+
(function() {
|
|
27
|
+
var recorderStop = null;
|
|
28
|
+
var recorderLoad = null;
|
|
29
|
+
var startGeneration = 0;
|
|
30
|
+
var isTrustedParentOrigin = ${isTrustedSessionReplayIframeParentOrigin.toString()};
|
|
31
|
+
|
|
32
|
+
function stopRecorder() {
|
|
33
|
+
startGeneration += 1;
|
|
34
|
+
if (typeof recorderStop === 'function') {
|
|
35
|
+
try { recorderStop(); } catch (_) {}
|
|
36
|
+
}
|
|
37
|
+
recorderStop = null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getRecord() {
|
|
41
|
+
return window.rrwebRecord && typeof window.rrwebRecord.record === 'function'
|
|
42
|
+
? window.rrwebRecord.record
|
|
43
|
+
: null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function loadRecorder() {
|
|
47
|
+
if (recorderLoad) return recorderLoad;
|
|
48
|
+
recorderLoad = new Promise(function(resolve, reject) {
|
|
49
|
+
var script = document.createElement('script');
|
|
50
|
+
script.src = ${scriptUrl};
|
|
51
|
+
script.integrity = ${integrity};
|
|
52
|
+
script.crossOrigin = 'anonymous';
|
|
53
|
+
script.referrerPolicy = 'no-referrer';
|
|
54
|
+
script.async = true;
|
|
55
|
+
script.onload = function() {
|
|
56
|
+
var record = getRecord();
|
|
57
|
+
if (record) resolve(record);
|
|
58
|
+
else reject(new Error('rrweb recorder did not initialize'));
|
|
59
|
+
};
|
|
60
|
+
script.onerror = function() {
|
|
61
|
+
recorderLoad = null;
|
|
62
|
+
reject(new Error('rrweb recorder failed to load'));
|
|
63
|
+
};
|
|
64
|
+
document.head.appendChild(script);
|
|
65
|
+
});
|
|
66
|
+
return recorderLoad;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function validOptions(options) {
|
|
70
|
+
return !!options &&
|
|
71
|
+
typeof options === 'object' &&
|
|
72
|
+
typeof options.blockSelector === 'string' &&
|
|
73
|
+
typeof options.ignoreSelector === 'string' &&
|
|
74
|
+
typeof options.maskTextSelector === 'string' &&
|
|
75
|
+
typeof options.maskAllInputs === 'boolean' &&
|
|
76
|
+
typeof options.recordCanvas === 'boolean' &&
|
|
77
|
+
typeof options.collectFonts === 'boolean' &&
|
|
78
|
+
typeof options.inlineImages === 'boolean' &&
|
|
79
|
+
!!options.sampling && typeof options.sampling === 'object';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function startRecorder(options) {
|
|
83
|
+
if (!validOptions(options)) return;
|
|
84
|
+
stopRecorder();
|
|
85
|
+
var generation = startGeneration;
|
|
86
|
+
loadRecorder().then(function(record) {
|
|
87
|
+
if (generation !== startGeneration) return;
|
|
88
|
+
recorderStop = record({
|
|
89
|
+
blockSelector: options.blockSelector,
|
|
90
|
+
ignoreSelector: options.ignoreSelector,
|
|
91
|
+
maskTextClass: options.maskTextClass,
|
|
92
|
+
maskTextSelector: options.maskTextSelector,
|
|
93
|
+
maskAllInputs: options.maskAllInputs,
|
|
94
|
+
maskInputOptions: options.maskInputOptions,
|
|
95
|
+
recordCanvas: options.recordCanvas,
|
|
96
|
+
collectFonts: options.collectFonts,
|
|
97
|
+
inlineImages: options.inlineImages,
|
|
98
|
+
sampling: options.sampling,
|
|
99
|
+
recordCrossOriginIframes: true
|
|
100
|
+
}) || null;
|
|
101
|
+
}).catch(function() {});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
window.addEventListener('message', function(event) {
|
|
105
|
+
if (event.source !== window.parent || !isTrustedParentOrigin(event.origin, window.location.href)) return;
|
|
106
|
+
var message = event.data;
|
|
107
|
+
if (!message || typeof message !== 'object') return;
|
|
108
|
+
if (message.type === ${startType}) startRecorder(message.options);
|
|
109
|
+
else if (message.type === ${stopType}) stopRecorder();
|
|
110
|
+
});
|
|
111
|
+
window.addEventListener('pagehide', stopRecorder);
|
|
112
|
+
|
|
113
|
+
if (window.parent !== window) {
|
|
114
|
+
window.parent.postMessage({ type: ${probeType} }, '*');
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
</script>`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function injectSessionReplayIframeBootstrap(html: string): string {
|
|
121
|
+
const bootstrap = buildSessionReplayIframeBootstrap();
|
|
122
|
+
const headClose = html.search(/<\/head\s*>/i);
|
|
123
|
+
if (headClose >= 0) {
|
|
124
|
+
return `${html.slice(0, headClose)}${bootstrap}${html.slice(headClose)}`;
|
|
125
|
+
}
|
|
126
|
+
const bodyOpen = html.search(/<body(?:\s[^>]*)?>/i);
|
|
127
|
+
if (bodyOpen >= 0) {
|
|
128
|
+
return `${html.slice(0, bodyOpen)}${bootstrap}${html.slice(bodyOpen)}`;
|
|
129
|
+
}
|
|
130
|
+
return `${bootstrap}${html}`;
|
|
131
|
+
}
|
|
@@ -38,6 +38,23 @@ const SLACK_PERMALINK_TIMEOUT_MS = 1_000;
|
|
|
38
38
|
const SLACK_CONTEXT_MESSAGE_LIMIT = 15;
|
|
39
39
|
const SLACK_CONTEXT_TEXT_LIMIT = 2_000;
|
|
40
40
|
const SLACK_CALM_PROGRESS_THRESHOLD_SECONDS = 30;
|
|
41
|
+
const SLACK_IDENTITY_TIMEOUT_MS = 1_000;
|
|
42
|
+
const SLACK_IDENTITY_CACHE_TTL_MS = 10 * 60 * 1_000;
|
|
43
|
+
// Failed users.info lookups only get a short negative TTL: a transient Slack
|
|
44
|
+
// API blip must not fail-close a sender's identity (and DMs) for 10 minutes.
|
|
45
|
+
const SLACK_IDENTITY_NEGATIVE_CACHE_TTL_MS = 30 * 1_000;
|
|
46
|
+
const SLACK_IDENTITY_CACHE_MAX_ENTRIES = 1_000;
|
|
47
|
+
|
|
48
|
+
interface SlackUserIdentity {
|
|
49
|
+
email: string | null;
|
|
50
|
+
name: string | null;
|
|
51
|
+
memberType: "owner" | "admin" | "member" | "guest" | "external" | "unknown";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const slackIdentityCache = new Map<
|
|
55
|
+
string,
|
|
56
|
+
{ identity: SlackUserIdentity | null; expiresAt: number }
|
|
57
|
+
>();
|
|
41
58
|
|
|
42
59
|
export interface SlackAdapterOptions {
|
|
43
60
|
/** Resolve the bot token for the exact Slack installation. */
|
|
@@ -356,6 +373,14 @@ export function slackAdapter(
|
|
|
356
373
|
return hydrateSlackContext(token, incoming);
|
|
357
374
|
},
|
|
358
375
|
|
|
376
|
+
async hydrateIncomingIdentity(
|
|
377
|
+
incoming: IncomingMessage,
|
|
378
|
+
): Promise<IncomingMessage> {
|
|
379
|
+
const token = await resolveBotToken(incoming);
|
|
380
|
+
if (!token) return incoming;
|
|
381
|
+
return hydrateSlackIdentity(token, incoming);
|
|
382
|
+
},
|
|
383
|
+
|
|
359
384
|
async startRunProgress(
|
|
360
385
|
incoming: IncomingMessage,
|
|
361
386
|
): Promise<PlatformRunProgress | null> {
|
|
@@ -1070,6 +1095,93 @@ async function slackJson(
|
|
|
1070
1095
|
}
|
|
1071
1096
|
}
|
|
1072
1097
|
|
|
1098
|
+
function slackIdentityCacheKey(incoming: IncomingMessage): string | null {
|
|
1099
|
+
const teamId = incoming.platformContext.teamId;
|
|
1100
|
+
const senderId = incoming.senderId;
|
|
1101
|
+
if (typeof senderId !== "string" || !senderId.trim()) return null;
|
|
1102
|
+
return `${typeof teamId === "string" && teamId ? teamId : "unknown"}:${senderId}`;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
async function resolveSlackUserIdentity(
|
|
1106
|
+
token: string,
|
|
1107
|
+
incoming: IncomingMessage,
|
|
1108
|
+
): Promise<SlackUserIdentity | null> {
|
|
1109
|
+
const cacheKey = slackIdentityCacheKey(incoming);
|
|
1110
|
+
if (!cacheKey) return null;
|
|
1111
|
+
const cached = slackIdentityCache.get(cacheKey);
|
|
1112
|
+
if (cached && cached.expiresAt > Date.now()) return cached.identity;
|
|
1113
|
+
if (cached) slackIdentityCache.delete(cacheKey);
|
|
1114
|
+
|
|
1115
|
+
const user = await slackJson(
|
|
1116
|
+
token,
|
|
1117
|
+
"users.info",
|
|
1118
|
+
{ user: incoming.senderId! },
|
|
1119
|
+
SLACK_IDENTITY_TIMEOUT_MS,
|
|
1120
|
+
);
|
|
1121
|
+
const profile = user?.user?.profile;
|
|
1122
|
+
const identity: SlackUserIdentity | null = user?.user
|
|
1123
|
+
? {
|
|
1124
|
+
email:
|
|
1125
|
+
typeof profile?.email === "string" && profile.email.trim()
|
|
1126
|
+
? profile.email.trim().toLowerCase()
|
|
1127
|
+
: null,
|
|
1128
|
+
name:
|
|
1129
|
+
typeof profile?.real_name === "string" && profile.real_name.trim()
|
|
1130
|
+
? profile.real_name.trim()
|
|
1131
|
+
: typeof profile?.display_name === "string" &&
|
|
1132
|
+
profile.display_name.trim()
|
|
1133
|
+
? profile.display_name.trim()
|
|
1134
|
+
: typeof user.user.real_name === "string" &&
|
|
1135
|
+
user.user.real_name.trim()
|
|
1136
|
+
? user.user.real_name.trim()
|
|
1137
|
+
: typeof user.user.name === "string" && user.user.name.trim()
|
|
1138
|
+
? user.user.name.trim()
|
|
1139
|
+
: null,
|
|
1140
|
+
memberType: user.user.is_ultra_restricted
|
|
1141
|
+
? "external"
|
|
1142
|
+
: user.user.is_restricted
|
|
1143
|
+
? "guest"
|
|
1144
|
+
: user.user.is_owner
|
|
1145
|
+
? "owner"
|
|
1146
|
+
: user.user.is_admin
|
|
1147
|
+
? "admin"
|
|
1148
|
+
: "member",
|
|
1149
|
+
}
|
|
1150
|
+
: null;
|
|
1151
|
+
if (slackIdentityCache.size >= SLACK_IDENTITY_CACHE_MAX_ENTRIES) {
|
|
1152
|
+
const oldestKey = slackIdentityCache.keys().next().value;
|
|
1153
|
+
if (oldestKey) slackIdentityCache.delete(oldestKey);
|
|
1154
|
+
}
|
|
1155
|
+
slackIdentityCache.set(cacheKey, {
|
|
1156
|
+
identity,
|
|
1157
|
+
expiresAt:
|
|
1158
|
+
Date.now() +
|
|
1159
|
+
(identity
|
|
1160
|
+
? SLACK_IDENTITY_CACHE_TTL_MS
|
|
1161
|
+
: SLACK_IDENTITY_NEGATIVE_CACHE_TTL_MS),
|
|
1162
|
+
});
|
|
1163
|
+
return identity;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
async function hydrateSlackIdentity(
|
|
1167
|
+
token: string,
|
|
1168
|
+
incoming: IncomingMessage,
|
|
1169
|
+
): Promise<IncomingMessage> {
|
|
1170
|
+
const identity = await resolveSlackUserIdentity(token, incoming);
|
|
1171
|
+
if (!identity) return incoming;
|
|
1172
|
+
return {
|
|
1173
|
+
...incoming,
|
|
1174
|
+
...(identity.name ? { senderName: identity.name } : {}),
|
|
1175
|
+
...(identity.email
|
|
1176
|
+
? { senderEmail: identity.email, senderVerified: true }
|
|
1177
|
+
: { senderVerified: false }),
|
|
1178
|
+
actorTrust: {
|
|
1179
|
+
memberType: identity.memberType,
|
|
1180
|
+
verified: true,
|
|
1181
|
+
},
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1073
1185
|
async function hydrateSlackContext(
|
|
1074
1186
|
token: string,
|
|
1075
1187
|
incoming: IncomingMessage,
|
|
@@ -1081,7 +1193,7 @@ async function hydrateSlackContext(
|
|
|
1081
1193
|
return incoming;
|
|
1082
1194
|
}
|
|
1083
1195
|
|
|
1084
|
-
const [thread, history, pins, conversation,
|
|
1196
|
+
const [thread, history, pins, conversation, identity] = await Promise.all([
|
|
1085
1197
|
slackJson(token, "conversations.replies", {
|
|
1086
1198
|
channel: channelId,
|
|
1087
1199
|
ts: threadTs,
|
|
@@ -1095,7 +1207,7 @@ async function hydrateSlackContext(
|
|
|
1095
1207
|
}),
|
|
1096
1208
|
slackJson(token, "pins.list", { channel: channelId }),
|
|
1097
1209
|
slackJson(token, "conversations.info", { channel: channelId }),
|
|
1098
|
-
senderId ?
|
|
1210
|
+
senderId ? resolveSlackUserIdentity(token, incoming) : null,
|
|
1099
1211
|
]);
|
|
1100
1212
|
|
|
1101
1213
|
// Agent View can attach the Slack surface the user is currently viewing to
|
|
@@ -1186,9 +1298,9 @@ async function hydrateSlackContext(
|
|
|
1186
1298
|
})
|
|
1187
1299
|
: [];
|
|
1188
1300
|
|
|
1189
|
-
const profile =
|
|
1190
|
-
const isGuest =
|
|
1191
|
-
const isExternal =
|
|
1301
|
+
const profile = identity;
|
|
1302
|
+
const isGuest = identity?.memberType === "guest";
|
|
1303
|
+
const isExternal = identity?.memberType === "external";
|
|
1192
1304
|
const isPrivate = conversation?.channel?.is_private === true;
|
|
1193
1305
|
const isExternalShared = conversation?.channel?.is_ext_shared === true;
|
|
1194
1306
|
const isMpim = conversation?.channel?.is_mpim === true;
|
|
@@ -1231,17 +1343,15 @@ async function hydrateSlackContext(
|
|
|
1231
1343
|
);
|
|
1232
1344
|
return {
|
|
1233
1345
|
...incoming,
|
|
1234
|
-
...(
|
|
1235
|
-
|
|
1236
|
-
: typeof profile?.real_name === "string" && profile.real_name
|
|
1237
|
-
? { senderName: profile.real_name }
|
|
1238
|
-
: {}),
|
|
1239
|
-
...(typeof profile?.email === "string"
|
|
1346
|
+
...(profile?.name ? { senderName: profile.name } : {}),
|
|
1347
|
+
...(profile?.email
|
|
1240
1348
|
? { senderEmail: profile.email, senderVerified: true }
|
|
1241
|
-
: {}),
|
|
1349
|
+
: { senderVerified: false }),
|
|
1242
1350
|
conversationType,
|
|
1243
1351
|
actorTrust: {
|
|
1244
|
-
memberType:
|
|
1352
|
+
memberType:
|
|
1353
|
+
identity?.memberType ??
|
|
1354
|
+
(isExternal ? "external" : isGuest ? "guest" : "member"),
|
|
1245
1355
|
verified: true,
|
|
1246
1356
|
},
|
|
1247
1357
|
contextMessages: hydratedMessages,
|