@agent-native/toolkit 0.205.0 → 0.206.0-nightly-20261009011246

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.
Files changed (143) hide show
  1. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  2. package/dist/app/agentkit/react/components.js +17 -9
  3. package/dist/app/agentkit/react/components.js.map +1 -1
  4. package/dist/app/auth/AuthPage.d.ts.map +1 -1
  5. package/dist/app/auth/AuthPage.js +11 -0
  6. package/dist/app/auth/AuthPage.js.map +1 -1
  7. package/dist/app/chat/AgentKitAssistantChat.d.ts +2 -0
  8. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  9. package/dist/app/chat/AgentKitAssistantChat.js +24 -14
  10. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  11. package/dist/app/chat/AgentPanel.d.ts.map +1 -1
  12. package/dist/app/chat/AgentPanel.js +3 -2
  13. package/dist/app/chat/AgentPanel.js.map +1 -1
  14. package/dist/app/chat/MultiTabAssistantChat.d.ts +4 -1
  15. package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
  16. package/dist/app/chat/MultiTabAssistantChat.js +61 -3
  17. package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
  18. package/dist/app/chat/agentkit-chat/approval-card.d.ts.map +1 -1
  19. package/dist/app/chat/agentkit-chat/approval-card.js +2 -1
  20. package/dist/app/chat/agentkit-chat/approval-card.js.map +1 -1
  21. package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
  22. package/dist/app/chat/chat/run-recovery.js +74 -8
  23. package/dist/app/chat/chat/run-recovery.js.map +1 -1
  24. package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
  25. package/dist/app/chat/chat/tool-call-display.js +6 -4
  26. package/dist/app/chat/chat/tool-call-display.js.map +1 -1
  27. package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.d.ts.map +1 -1
  28. package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js +2 -1
  29. package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js.map +1 -1
  30. package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
  31. package/dist/app/chat/conversation/AgentConversation.js +10 -7
  32. package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
  33. package/dist/app/chat/fallback-chat-title.d.ts.map +1 -1
  34. package/dist/app/chat/fallback-chat-title.js +2 -4
  35. package/dist/app/chat/fallback-chat-title.js.map +1 -1
  36. package/dist/app/chat/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  37. package/dist/app/chat/mcp-apps/McpAppRenderer.js +3 -2
  38. package/dist/app/chat/mcp-apps/McpAppRenderer.js.map +1 -1
  39. package/dist/app/chat/session-replay-privacy.d.ts +7 -0
  40. package/dist/app/chat/session-replay-privacy.d.ts.map +1 -0
  41. package/dist/app/chat/session-replay-privacy.js +6 -0
  42. package/dist/app/chat/session-replay-privacy.js.map +1 -0
  43. package/dist/app/extensions/ExtensionViewer.d.ts +4 -1
  44. package/dist/app/extensions/ExtensionViewer.d.ts.map +1 -1
  45. package/dist/app/extensions/ExtensionViewer.js +3 -3
  46. package/dist/app/extensions/ExtensionViewer.js.map +1 -1
  47. package/dist/app/extensions/ExtensionViewerPage.d.ts +4 -1
  48. package/dist/app/extensions/ExtensionViewerPage.d.ts.map +1 -1
  49. package/dist/app/extensions/ExtensionViewerPage.js +2 -2
  50. package/dist/app/extensions/ExtensionViewerPage.js.map +1 -1
  51. package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
  52. package/dist/app/onboarding/FirstRunOnboarding.js +53 -12
  53. package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
  54. package/dist/app/onboarding/OnboardingPanel.d.ts.map +1 -1
  55. package/dist/app/onboarding/OnboardingPanel.js +14 -4
  56. package/dist/app/onboarding/OnboardingPanel.js.map +1 -1
  57. package/dist/app/resources/ResourceEditor.d.ts +4 -1
  58. package/dist/app/resources/ResourceEditor.d.ts.map +1 -1
  59. package/dist/app/resources/ResourceEditor.js +18 -7
  60. package/dist/app/resources/ResourceEditor.js.map +1 -1
  61. package/dist/app/resources/ResourcesPanel.d.ts +4 -1
  62. package/dist/app/resources/ResourcesPanel.d.ts.map +1 -1
  63. package/dist/app/resources/ResourcesPanel.js +18 -18
  64. package/dist/app/resources/ResourcesPanel.js.map +1 -1
  65. package/dist/app/resources/custom-agent-model-options.d.ts +16 -0
  66. package/dist/app/resources/custom-agent-model-options.d.ts.map +1 -0
  67. package/dist/app/resources/custom-agent-model-options.js +53 -0
  68. package/dist/app/resources/custom-agent-model-options.js.map +1 -0
  69. package/dist/app/settings/SettingsPanel.d.ts.map +1 -1
  70. package/dist/app/settings/SettingsPanel.js +34 -3
  71. package/dist/app/settings/SettingsPanel.js.map +1 -1
  72. package/dist/app/settings/SettingsTabsPage.d.ts.map +1 -1
  73. package/dist/app/settings/SettingsTabsPage.js +2 -0
  74. package/dist/app/settings/SettingsTabsPage.js.map +1 -1
  75. package/dist/app/settings/api-keys/ApiKeyDialogs.d.ts.map +1 -1
  76. package/dist/app/settings/api-keys/ApiKeyDialogs.js +49 -9
  77. package/dist/app/settings/api-keys/ApiKeyDialogs.js.map +1 -1
  78. package/dist/app/settings/api-keys/ApiKeysSettingsPage.js +2 -1
  79. package/dist/app/settings/api-keys/ApiKeysSettingsPage.js.map +1 -1
  80. package/dist/app/settings/model/ModelSettingsPage.d.ts.map +1 -1
  81. package/dist/app/settings/model/ModelSettingsPage.js +43 -9
  82. package/dist/app/settings/model/ModelSettingsPage.js.map +1 -1
  83. package/dist/app/settings/model/ProviderDialog.d.ts +4 -0
  84. package/dist/app/settings/model/ProviderDialog.d.ts.map +1 -1
  85. package/dist/app/settings/model/ProviderDialog.js +107 -11
  86. package/dist/app/settings/model/ProviderDialog.js.map +1 -1
  87. package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
  88. package/dist/app/settings/useBuilderStatus.js +13 -10
  89. package/dist/app/settings/useBuilderStatus.js.map +1 -1
  90. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  91. package/dist/composer/TiptapComposer.js +51 -13
  92. package/dist/composer/TiptapComposer.js.map +1 -1
  93. package/package.json +4 -4
  94. package/src/app/agentkit/react/components.interaction.spec.tsx +229 -1
  95. package/src/app/agentkit/react/components.spec.tsx +42 -1
  96. package/src/app/agentkit/react/components.tsx +46 -12
  97. package/src/app/auth/AuthPage.tsx +13 -0
  98. package/src/app/chat/AgentKitAssistantChat.spec.tsx +116 -5
  99. package/src/app/chat/AgentKitAssistantChat.tsx +41 -20
  100. package/src/app/chat/AgentPanel.tsx +5 -1
  101. package/src/app/chat/MultiTabAssistantChat.spec.tsx +152 -7
  102. package/src/app/chat/MultiTabAssistantChat.tsx +71 -4
  103. package/src/app/chat/agentkit-chat/approval-card.spec.tsx +17 -0
  104. package/src/app/chat/agentkit-chat/approval-card.tsx +2 -0
  105. package/src/app/chat/chat/run-recovery.spec.tsx +354 -9
  106. package/src/app/chat/chat/run-recovery.tsx +178 -10
  107. package/src/app/chat/chat/tool-call-display.spec.tsx +77 -0
  108. package/src/app/chat/chat/tool-call-display.tsx +23 -6
  109. package/src/app/chat/chat-first/ChatFirstAgentActivityPanel.tsx +2 -1
  110. package/src/app/chat/conversation/AgentConversation.spec.tsx +190 -1
  111. package/src/app/chat/conversation/AgentConversation.tsx +32 -8
  112. package/src/app/chat/fallback-chat-title.spec.ts +44 -0
  113. package/src/app/chat/fallback-chat-title.ts +3 -4
  114. package/src/app/chat/mcp-apps/McpAppRenderer.spec.ts +24 -0
  115. package/src/app/chat/mcp-apps/McpAppRenderer.tsx +10 -2
  116. package/src/app/chat/session-replay-privacy.spec.ts +14 -0
  117. package/src/app/chat/session-replay-privacy.ts +5 -0
  118. package/src/app/extensions/ExtensionViewer.tsx +15 -3
  119. package/src/app/extensions/ExtensionViewerPage.tsx +7 -3
  120. package/src/app/onboarding/FirstRunOnboarding.spec.tsx +252 -2
  121. package/src/app/onboarding/FirstRunOnboarding.tsx +56 -9
  122. package/src/app/onboarding/OnboardingPanel.save-scope.spec.tsx +1 -0
  123. package/src/app/onboarding/OnboardingPanel.tsx +15 -3
  124. package/src/app/resources/ResourceEditor.spec.tsx +240 -5
  125. package/src/app/resources/ResourceEditor.tsx +57 -10
  126. package/src/app/resources/ResourcesPanel.spec.ts +86 -4
  127. package/src/app/resources/ResourcesPanel.tsx +49 -16
  128. package/src/app/resources/custom-agent-model-options.ts +92 -0
  129. package/src/app/settings/SettingsPanel.model-defaults.spec.tsx +26 -13
  130. package/src/app/settings/SettingsPanel.tsx +35 -3
  131. package/src/app/settings/SettingsTabsPage.spec.tsx +97 -0
  132. package/src/app/settings/SettingsTabsPage.tsx +2 -0
  133. package/src/app/settings/api-keys/ApiKeyDialogs.tsx +84 -22
  134. package/src/app/settings/api-keys/ApiKeysSettingsPage.spec.tsx +229 -1
  135. package/src/app/settings/api-keys/ApiKeysSettingsPage.tsx +3 -2
  136. package/src/app/settings/model/ModelSettingsPage.spec.tsx +99 -9
  137. package/src/app/settings/model/ModelSettingsPage.tsx +79 -11
  138. package/src/app/settings/model/ProviderDialog.spec.tsx +192 -1
  139. package/src/app/settings/model/ProviderDialog.tsx +225 -29
  140. package/src/app/settings/useBuilderStatus.spec.tsx +49 -0
  141. package/src/app/settings/useBuilderStatus.ts +16 -10
  142. package/src/composer/TiptapComposer.spec.ts +97 -2
  143. package/src/composer/TiptapComposer.tsx +67 -13
@@ -4,10 +4,12 @@ import {
4
4
  localizeKnownChatErrorText,
5
5
  } from "@agent-native/core/client/agent-chat";
6
6
  import { agentNativePath } from "@agent-native/core/client/api-path";
7
+ import { injectedAgentNativeAppId } from "@agent-native/core/client/app-config";
7
8
  import { BuilderBMark } from "@agent-native/core/client/builder-mark";
8
9
  import { formatClientFailureReport } from "@agent-native/core/client/failure-report";
9
10
  import { useFeatureFlagState } from "@agent-native/core/client/feature-flags";
10
11
  import { useFormatters, useT } from "@agent-native/core/client/i18n";
12
+ import { trackOnboardingEvent } from "@agent-native/core/client/onboarding/use-onboarding";
11
13
  import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
12
14
  import { buildSettingsRoute } from "@agent-native/core/navigation";
13
15
  import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
@@ -35,14 +37,57 @@ import { useState, useEffect, useCallback, useRef } from "react";
35
37
  import { Link } from "react-router";
36
38
 
37
39
  import { DeferredBuilderConnectPopover } from "../../settings/deferred-builder-connect-popover.js";
40
+ import { currentTemplateId } from "../../settings/shell/app-identity.js";
38
41
  import { useBuilderConnectFlow } from "../../settings/useBuilderStatus.js";
39
42
  import { BuilderReferralInviteRow } from "../BuilderReferralInviteRow.js";
43
+ import { SESSION_REPLAY_MASK_PROPS } from "../session-replay-privacy.js";
40
44
 
41
45
  const builderSubscriptionUrl = withBuilderUtmTrackingParams(
42
46
  "https://builder.io/account/subscription?signupSource=agent-native",
43
47
  { content: "chat_credit_limit" },
44
48
  );
45
49
 
50
+ function setupTelemetryAppName(): string {
51
+ const appId = injectedAgentNativeAppId() ?? currentTemplateId();
52
+ return appId && /^[a-z0-9][a-z0-9-]{0,63}$/.test(appId)
53
+ ? appId.replace(/^agent-native-/, "") || "framework"
54
+ : "framework";
55
+ }
56
+
57
+ type SetupTelemetryEventName =
58
+ | "integration_setup_exposed"
59
+ | "integration_method_clicked"
60
+ | "integration_method_outcome";
61
+ type SetupTelemetryMethodId = "setup_card" | "builder" | "custom_keys";
62
+ type SetupTelemetryAction = "view" | "click" | "connect";
63
+ type SetupTelemetryOutcome =
64
+ | "exposed"
65
+ | "started"
66
+ | "connected"
67
+ | "status_read_failed"
68
+ | "connection_failed";
69
+
70
+ function trackSetupFunnelEvent(
71
+ eventName: SetupTelemetryEventName,
72
+ methodId: SetupTelemetryMethodId,
73
+ action: SetupTelemetryAction,
74
+ outcome: SetupTelemetryOutcome,
75
+ ): void {
76
+ trackOnboardingEvent(eventName, {
77
+ flow: "chat_setup",
78
+ app_name: setupTelemetryAppName(),
79
+ step_id: "connect_ai",
80
+ method_id: methodId,
81
+ action,
82
+ outcome,
83
+ });
84
+ }
85
+
86
+ type BuilderConnectTelemetryAttempt = {
87
+ statusAvailableAfterStart: boolean;
88
+ terminalErrorCleared: boolean;
89
+ };
90
+
46
91
  export type LoopLimitInfo = { maxIterations?: number };
47
92
 
48
93
  export type RunErrorInfo = {
@@ -233,12 +278,61 @@ export function BuilderConnectCta({
233
278
  reconnect?: boolean;
234
279
  }) {
235
280
  const t = useT();
281
+ const connectAttemptRef = useRef<BuilderConnectTelemetryAttempt | null>(null);
282
+ const handleConnected = useCallback(async () => {
283
+ try {
284
+ await onConnected?.();
285
+ } finally {
286
+ if (!connectAttemptRef.current) return;
287
+ connectAttemptRef.current = null;
288
+ trackSetupFunnelEvent(
289
+ "integration_method_outcome",
290
+ "builder",
291
+ "connect",
292
+ "connected",
293
+ );
294
+ }
295
+ }, [onConnected]);
236
296
  const flow = useBuilderConnectFlow({
237
297
  provisionAccount: true,
238
298
  trackingSource: "assistant_chat_builder_cta",
239
- onConnected,
299
+ onConnected: handleConnected,
240
300
  });
241
301
  const { configured, orgName, connecting, error } = flow;
302
+ useEffect(() => {
303
+ const attempt = connectAttemptRef.current;
304
+ if (!attempt) return;
305
+ if (!flow.statusUnavailable) attempt.statusAvailableAfterStart = true;
306
+ if (!flow.terminalError) attempt.terminalErrorCleared = true;
307
+
308
+ const outcome =
309
+ flow.statusUnavailable &&
310
+ flow.errorKind === "status-read" &&
311
+ attempt.statusAvailableAfterStart
312
+ ? "status_read_failed"
313
+ : flow.terminalError && attempt.terminalErrorCleared
314
+ ? "connection_failed"
315
+ : null;
316
+ if (!outcome) return;
317
+ connectAttemptRef.current = null;
318
+ trackSetupFunnelEvent(
319
+ "integration_method_outcome",
320
+ "builder",
321
+ "connect",
322
+ outcome,
323
+ );
324
+ }, [flow.errorKind, flow.statusUnavailable, flow.terminalError]);
325
+
326
+ const startBuilderConnect = useCallback(
327
+ (provisionAccount: boolean) => {
328
+ connectAttemptRef.current = {
329
+ statusAvailableAfterStart: !flow.statusUnavailable,
330
+ terminalErrorCleared: !flow.terminalError,
331
+ };
332
+ flow.start({ provisionAccount });
333
+ },
334
+ [flow.start, flow.statusUnavailable, flow.terminalError],
335
+ );
242
336
 
243
337
  if (variant === "compact") {
244
338
  if (configured && !reconnect) {
@@ -254,10 +348,21 @@ export function BuilderConnectCta({
254
348
 
255
349
  return (
256
350
  <div className="agent-builder-setup-card__builder-cta flex min-w-0 flex-col items-start gap-1 sm:items-end">
257
- <DeferredBuilderConnectPopover flow={flow}>
351
+ <DeferredBuilderConnectPopover
352
+ flow={flow}
353
+ onConnect={startBuilderConnect}
354
+ >
258
355
  <button
259
356
  type="button"
260
357
  disabled={connecting}
358
+ onClick={() =>
359
+ trackSetupFunnelEvent(
360
+ "integration_method_clicked",
361
+ "builder",
362
+ "click",
363
+ "started",
364
+ )
365
+ }
261
366
  className="agent-builder-setup-card__builder-button inline-flex h-8 shrink-0 items-center gap-1 whitespace-nowrap rounded-md bg-foreground px-3 text-[11px] font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60"
262
367
  aria-busy={connecting}
263
368
  >
@@ -277,7 +382,10 @@ export function BuilderConnectCta({
277
382
  </button>
278
383
  </DeferredBuilderConnectPopover>
279
384
  {error && (
280
- <p className="max-w-[13rem] text-[10px] leading-snug text-destructive sm:text-end">
385
+ <p
386
+ {...SESSION_REPLAY_MASK_PROPS}
387
+ className="max-w-[13rem] text-[10px] leading-snug text-destructive sm:text-end"
388
+ >
281
389
  {error}
282
390
  </p>
283
391
  )}
@@ -318,12 +426,30 @@ export function BuilderConnectCta({
318
426
  <p className="text-[11px] text-muted-foreground mt-0.5 max-w-[220px]">
319
427
  {t("agentChat.setup.freeCredits")}
320
428
  </p>
321
- {error && <p className="mt-1 text-[10px] text-destructive">{error}</p>}
429
+ {error && (
430
+ <p
431
+ {...SESSION_REPLAY_MASK_PROPS}
432
+ className="mt-1 text-[10px] text-destructive"
433
+ >
434
+ {error}
435
+ </p>
436
+ )}
322
437
  </div>
323
- <DeferredBuilderConnectPopover flow={flow}>
438
+ <DeferredBuilderConnectPopover
439
+ flow={flow}
440
+ onConnect={startBuilderConnect}
441
+ >
324
442
  <button
325
443
  type="button"
326
444
  disabled={connecting}
445
+ onClick={() =>
446
+ trackSetupFunnelEvent(
447
+ "integration_method_clicked",
448
+ "builder",
449
+ "click",
450
+ "started",
451
+ )
452
+ }
327
453
  className="ms-auto inline-flex items-center gap-1 shrink-0 rounded-md bg-foreground px-3 py-1.5 text-[11px] font-medium no-underline text-background hover:opacity-90 disabled:opacity-60 disabled:cursor-wait"
328
454
  aria-busy={connecting}
329
455
  >
@@ -407,6 +533,15 @@ export function BuilderSetupContent({
407
533
  <BuilderConnectCta variant="compact" onConnected={onConnected} />
408
534
  <Link
409
535
  to={buildSettingsRoute(redesign.enabled ? "model" : "keys")}
536
+ state={{ providerSetupTrackingFlow: "chat_setup" }}
537
+ onClick={() =>
538
+ trackSetupFunnelEvent(
539
+ "integration_method_clicked",
540
+ "custom_keys",
541
+ "click",
542
+ "started",
543
+ )
544
+ }
410
545
  className={cn(
411
546
  "agent-builder-setup-card__key-button inline-flex shrink-0 items-center whitespace-nowrap rounded-md text-[11px] font-medium",
412
547
  sidebarLayout
@@ -445,6 +580,18 @@ export function BuilderSetupCard({
445
580
  const t = useT();
446
581
  const retryRequestedRef = useRef(false);
447
582
  const [retryRequested, setRetryRequested] = useState(false);
583
+ const exposureTrackedRef = useRef(false);
584
+
585
+ useEffect(() => {
586
+ if (exposureTrackedRef.current) return;
587
+ exposureTrackedRef.current = true;
588
+ trackSetupFunnelEvent(
589
+ "integration_setup_exposed",
590
+ "setup_card",
591
+ "view",
592
+ "exposed",
593
+ );
594
+ }, []);
448
595
 
449
596
  const handleRetry = useCallback(() => {
450
597
  if (!onRetry || retryRequestedRef.current) return;
@@ -732,7 +879,10 @@ export function RunErrorRecoveryCard({
732
879
  terminal: t("agentChat.error.failed"),
733
880
  })}
734
881
  </div>
735
- <p className="mt-1 whitespace-pre-wrap break-words text-xs leading-relaxed text-muted-foreground">
882
+ <p
883
+ {...SESSION_REPLAY_MASK_PROPS}
884
+ className="mt-1 whitespace-pre-wrap break-words text-xs leading-relaxed text-muted-foreground"
885
+ >
736
886
  {localizeKnownChatErrorText(info.message, t)}
737
887
  </p>
738
888
  {shouldShowBuilderReconnect && !builderReconnectResolved && (
@@ -771,7 +921,10 @@ export function RunErrorRecoveryCard({
771
921
  {info.runId && <div>run: {info.runId}</div>}
772
922
  {info.errorCode && <div>code: {info.errorCode}</div>}
773
923
  {info.details && (
774
- <pre className="mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono">
924
+ <pre
925
+ {...SESSION_REPLAY_MASK_PROPS}
926
+ className="mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono"
927
+ >
775
928
  {info.details}
776
929
  </pre>
777
930
  )}
@@ -898,12 +1051,20 @@ export function RunErrorRecoveryCard({
898
1051
  </div>
899
1052
  </div>
900
1053
  {shouldShowBuilderReconnect && builderReconnect.error && (
901
- <p className="mt-2 text-xs leading-relaxed text-red-500">
1054
+ <p
1055
+ {...SESSION_REPLAY_MASK_PROPS}
1056
+ className="mt-2 text-xs leading-relaxed text-destructive"
1057
+ >
902
1058
  {builderReconnect.error}
903
1059
  </p>
904
1060
  )}
905
1061
  {forkError && (
906
- <p className="mt-2 text-xs leading-relaxed text-red-500">{forkError}</p>
1062
+ <p
1063
+ {...SESSION_REPLAY_MASK_PROPS}
1064
+ className="mt-2 text-xs leading-relaxed text-destructive"
1065
+ >
1066
+ {forkError}
1067
+ </p>
907
1068
  )}
908
1069
  {continueError && (
909
1070
  <p className="mt-2 text-xs leading-relaxed text-destructive">
@@ -1102,7 +1263,14 @@ export function LoopLimitContinueCard({
1102
1263
  {t("agentChat.limit.ownerOnly")}
1103
1264
  </p>
1104
1265
  )}
1105
- {error && <p className="mt-2 text-[11px] text-destructive">{error}</p>}
1266
+ {error && (
1267
+ <p
1268
+ {...SESSION_REPLAY_MASK_PROPS}
1269
+ className="mt-2 text-[11px] text-destructive"
1270
+ >
1271
+ {error}
1272
+ </p>
1273
+ )}
1106
1274
  </div>
1107
1275
  );
1108
1276
  }
@@ -5,6 +5,7 @@ import {
5
5
  AgentNativeI18nProvider as CoreAgentNativeI18nProvider,
6
6
  type AgentNativeI18nProviderProps,
7
7
  } from "@agent-native/core/client/i18n";
8
+ import { SESSION_REPLAY_BLOCK_ATTRIBUTE } from "@agent-native/core/client/session-replay-privacy";
8
9
  import type { AgentMcpAppPayload } from "@agent-native/core/mcp-client";
9
10
  import { act, useState, type ReactNode } from "react";
10
11
  import { createRoot, type Root } from "react-dom/client";
@@ -428,6 +429,14 @@ describe("ToolCallDisplay native renderers", () => {
428
429
 
429
430
  expect(disclosure?.getAttribute("aria-expanded")).toBe("true");
430
431
  expect(container.textContent).toContain(errorMessage);
432
+ expect(
433
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
434
+ (element) => element.textContent === errorMessage,
435
+ ),
436
+ ).toBe(true);
437
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
438
+ expect(button.closest("[data-an-mask]")).toBeNull();
439
+ }
431
440
  });
432
441
 
433
442
  it("shows regular tool errors only after explicitly expanding the call", () => {
@@ -456,6 +465,14 @@ describe("ToolCallDisplay native renderers", () => {
456
465
 
457
466
  expect(disclosure?.getAttribute("aria-expanded")).toBe("true");
458
467
  expect(container.textContent).toContain(errorMessage);
468
+ expect(
469
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
470
+ (element) => element.textContent === errorMessage,
471
+ ),
472
+ ).toBe(true);
473
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
474
+ expect(button.closest("[data-an-mask]")).toBeNull();
475
+ }
459
476
  expect(container.querySelector(".text-destructive")).toBeNull();
460
477
  });
461
478
 
@@ -489,6 +506,14 @@ describe("ToolCallDisplay native renderers", () => {
489
506
  act(() => disclosure?.click());
490
507
 
491
508
  expect(container.textContent).toContain(errorMessage);
509
+ expect(
510
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
511
+ (element) => element.textContent === errorMessage,
512
+ ),
513
+ ).toBe(true);
514
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
515
+ expect(button.closest("[data-an-mask]")).toBeNull();
516
+ }
492
517
  });
493
518
 
494
519
  it("bypasses native tool renderers for failures and keeps details collapsed", () => {
@@ -521,6 +546,14 @@ describe("ToolCallDisplay native renderers", () => {
521
546
  act(() => disclosure?.click());
522
547
 
523
548
  expect(container.textContent).toContain(errorMessage);
549
+ expect(
550
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
551
+ (element) => element.textContent === errorMessage,
552
+ ),
553
+ ).toBe(true);
554
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
555
+ expect(button.closest("[data-an-mask]")).toBeNull();
556
+ }
524
557
  expect(container.querySelector(".text-destructive")).toBeNull();
525
558
  });
526
559
 
@@ -599,6 +632,14 @@ describe("ToolCallDisplay native renderers", () => {
599
632
 
600
633
  expect(subtool?.getAttribute("aria-expanded")).toBe("true");
601
634
  expect(container.textContent).toContain(errorMessage);
635
+ expect(
636
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
637
+ (element) => element.textContent === errorMessage,
638
+ ),
639
+ ).toBe(true);
640
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
641
+ expect(button.closest("[data-an-mask]")).toBeNull();
642
+ }
602
643
  });
603
644
 
604
645
  it("keeps failed delegated subtools expandable without error text", () => {
@@ -802,6 +843,14 @@ describe("ToolCallDisplay native renderers", () => {
802
843
 
803
844
  expect(disclosure?.getAttribute("aria-expanded")).toBe("true");
804
845
  expect(container.textContent).toContain(errorMessage);
846
+ expect(
847
+ Array.from(container.querySelectorAll("[data-an-mask]")).some(
848
+ (element) => element.textContent === errorMessage,
849
+ ),
850
+ ).toBe(true);
851
+ for (const button of container.querySelectorAll("button[aria-expanded]")) {
852
+ expect(button.closest("[data-an-mask]")).toBeNull();
853
+ }
805
854
  expect(container.querySelector(".text-destructive")).toBeNull();
806
855
  });
807
856
 
@@ -1695,6 +1744,34 @@ describe("ToolCallDisplay native renderers", () => {
1695
1744
  expect(container.textContent).not.toContain("MCP APP");
1696
1745
  });
1697
1746
 
1747
+ it.each([true, false])(
1748
+ "blocks only an errored MCP App from replays (isError %s)",
1749
+ (isError) => {
1750
+ act(() => {
1751
+ root.render(
1752
+ <ToolCallDisplay
1753
+ toolName="external-widget"
1754
+ args={{}}
1755
+ result={
1756
+ isError
1757
+ ? "Error running external-widget: Example Document failed."
1758
+ : JSON.stringify({ ok: true })
1759
+ }
1760
+ mcpApp={mcpApp}
1761
+ isRunning={false}
1762
+ isError={isError}
1763
+ />,
1764
+ );
1765
+ });
1766
+
1767
+ const app = container.querySelector('[data-testid="mcp-app"]');
1768
+ expect(app).not.toBeNull();
1769
+ expect(app?.closest(`[${SESSION_REPLAY_BLOCK_ATTRIBUTE}]`) !== null).toBe(
1770
+ isError,
1771
+ );
1772
+ },
1773
+ );
1774
+
1698
1775
  it("renders MCP Apps when there is no native widget payload", () => {
1699
1776
  act(() => {
1700
1777
  root.render(
@@ -51,6 +51,10 @@ import { AgentTaskCard } from "../AgentTaskCard.js";
51
51
  import { ConnectBuilderCard } from "../ConnectBuilderCard.js";
52
52
  import { FileStorageSetupPopover } from "../FileStorageSetupPopover.js";
53
53
  import { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
54
+ import {
55
+ SESSION_REPLAY_BLOCK_PROPS,
56
+ SESSION_REPLAY_MASK_PROPS,
57
+ } from "../session-replay-privacy.js";
54
58
  import { useThinkingDisplay } from "../thinking-display.js";
55
59
  import {
56
60
  BashCell,
@@ -980,9 +984,13 @@ function ToolCallDisplayGeneric({
980
984
 
981
985
  return (
982
986
  <div className="group/tool my-0.5 w-full overflow-hidden">
983
- {mcpApp && !(suppressInlineOpenApp && toolName === "open_app") && (
984
- <McpAppRenderer app={mcpApp} className="mb-1.5" />
985
- )}
987
+ {mcpApp &&
988
+ !(suppressInlineOpenApp && toolName === "open_app") && (
989
+ // The recorder keeps iframe attributes, and a snapshot's srcdoc can show the failure.
990
+ <div {...(isError ? SESSION_REPLAY_BLOCK_PROPS : {})}>
991
+ <McpAppRenderer app={mcpApp} className="mb-1.5" />
992
+ </div>
993
+ )}
986
994
  <button
987
995
  type="button"
988
996
  onClick={() => canExpand && setExpanded(!isExpanded)}
@@ -1079,7 +1087,10 @@ function ToolCallDisplayGeneric({
1079
1087
  />
1080
1088
  )}
1081
1089
  {isError ? (
1082
- <div className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground">
1090
+ <div
1091
+ {...SESSION_REPLAY_MASK_PROPS}
1092
+ className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground"
1093
+ >
1083
1094
  {result || t("agentChat.tool.failedWithoutDetails")}
1084
1095
  </div>
1085
1096
  ) : resultPayload ? (
@@ -1289,7 +1300,10 @@ function AgentCallCell({
1289
1300
  </div>
1290
1301
  )}
1291
1302
  {isError && errorText ? (
1292
- <div className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground">
1303
+ <div
1304
+ {...SESSION_REPLAY_MASK_PROPS}
1305
+ className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground"
1306
+ >
1293
1307
  {errorText}
1294
1308
  </div>
1295
1309
  ) : null}
@@ -1372,7 +1386,10 @@ function AgentActivityToolCallRow({
1372
1386
  />
1373
1387
  </button>
1374
1388
  <AnimatedCollapse open={open}>
1375
- <div className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground">
1389
+ <div
1390
+ {...SESSION_REPLAY_MASK_PROPS}
1391
+ className="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/70 px-2.5 py-1 text-xs text-muted-foreground"
1392
+ >
1376
1393
  {failureDetails}
1377
1394
  </div>
1378
1395
  </AnimatedCollapse>
@@ -19,6 +19,7 @@ import {
19
19
  } from "@tabler/icons-react";
20
20
  import { useState } from "react";
21
21
 
22
+ import { SESSION_REPLAY_MASK_PROPS } from "../session-replay-privacy.js";
22
23
  import { defaultChatFirstCopy } from "./copy.js";
23
24
  import type { ChatFirstCopy } from "./types.js";
24
25
 
@@ -111,7 +112,7 @@ export function ChatFirstAgentActivityPanel({
111
112
  data-chat-first-agents-error
112
113
  >
113
114
  <IconAlertCircle size={15} aria-hidden="true" />
114
- <span>{error}</span>
115
+ <span {...SESSION_REPLAY_MASK_PROPS}>{error}</span>
115
116
  {onRefresh ? (
116
117
  <button
117
118
  type="button"