@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/toolkit",
3
- "version": "0.205.0",
3
+ "version": "0.206.0-nightly-20261009011246",
4
4
  "description": "Reusable app-building UI and helpers for Agent-Native apps.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -673,7 +673,7 @@
673
673
  "y-protocols": "^1.0.7",
674
674
  "yjs": "^13.6.33",
675
675
  "zod": "^4.3.6",
676
- "@agent-native/agentkit": "^0.205.0"
676
+ "@agent-native/agentkit": "^0.206.0-nightly-20261009011246"
677
677
  },
678
678
  "devDependencies": {
679
679
  "@excalidraw/excalidraw": "0.18.1",
@@ -697,10 +697,10 @@
697
697
  "typescript-7": "npm:typescript@^7.0.2",
698
698
  "vite": "8.1.0",
699
699
  "vitest": "^4.1.5",
700
- "@agent-native/core": "^0.205.0"
700
+ "@agent-native/core": "^0.206.0-nightly-20261009011246"
701
701
  },
702
702
  "peerDependencies": {
703
- "@agent-native/core": ">=0.196.0",
703
+ "@agent-native/core": "0.206.0-nightly-20261009011246",
704
704
  "@excalidraw/excalidraw": ">=0.18",
705
705
  "@excalidraw/mermaid-to-excalidraw": ">=2",
706
706
  "@tanstack/react-query": "^5.99.2",
@@ -45,11 +45,152 @@ vi.mock("../../../design-system/index.js", async (importOriginal) => {
45
45
 
46
46
  import { AgentKitClient } from "@agent-native/agentkit/client";
47
47
  import type { AgentTransport } from "@agent-native/agentkit/protocol";
48
+ import {
49
+ SESSION_REPLAY_BLOCK_ATTRIBUTE,
50
+ SESSION_REPLAY_MASK_ATTRIBUTE,
51
+ } from "@agent-native/core/client/session-replay-privacy";
48
52
 
49
53
  import { getComposerDraftKey } from "../../../composer/draft-key.js";
50
- import { AgentKitChat, AgentMessageActions } from "./components.js";
54
+ import {
55
+ AgentActivityItem,
56
+ AgentInteractionItem,
57
+ AgentKitChat,
58
+ AgentMessageActions,
59
+ } from "./components.js";
51
60
  import { AgentKitProvider } from "./context.js";
52
61
 
62
+ describe("AgentActivityItem replay privacy", () => {
63
+ it.each(["failed", "completed"] as const)(
64
+ "hides only failed activity diagnostics (%s)",
65
+ async (status) => {
66
+ const client = new AgentKitClient({
67
+ transport: {
68
+ async startRun() {
69
+ return { runId: "run-example" };
70
+ },
71
+ async *subscribeToRun() {},
72
+ async cancelRun() {},
73
+ },
74
+ });
75
+ const container = document.createElement("div");
76
+ document.body.appendChild(container);
77
+ const root = createRoot(container);
78
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
79
+ try {
80
+ await act(async () =>
81
+ root.render(
82
+ <AgentKitProvider controller={client} threadId="thread-example">
83
+ <AgentActivityItem
84
+ value={{
85
+ id: "activity-example",
86
+ kind: "tool",
87
+ label: "Example tool",
88
+ status,
89
+ detail: "Example Person's example notes.",
90
+ summary: [
91
+ { type: "text", text: "Example Document diagnostics." },
92
+ {
93
+ type: "citation",
94
+ title: "Example report",
95
+ url: "https://example.test/report?person=example",
96
+ },
97
+ ],
98
+ }}
99
+ threadId="thread-example"
100
+ />
101
+ </AgentKitProvider>,
102
+ ),
103
+ );
104
+ const disclosure = container.querySelector<HTMLButtonElement>(
105
+ "button[aria-expanded]",
106
+ )!;
107
+ expect(
108
+ disclosure.closest(`[${SESSION_REPLAY_MASK_ATTRIBUTE}]`),
109
+ ).toBeNull();
110
+ expect(
111
+ container
112
+ .querySelector(".agentkit-activity-label")
113
+ ?.closest(`[${SESSION_REPLAY_MASK_ATTRIBUTE}]`),
114
+ ).toBeNull();
115
+ const detail = container.querySelector(".agentkit-activity-detail");
116
+ expect(detail?.hasAttribute(SESSION_REPLAY_MASK_ATTRIBUTE)).toBe(
117
+ status === "failed",
118
+ );
119
+ expect(detail?.hasAttribute("title")).toBe(status !== "failed");
120
+ await act(async () => disclosure.click());
121
+ const summary = container.querySelector(".agentkit-activity-summary");
122
+ expect(summary?.textContent).toContain("Example Document diagnostics.");
123
+ expect(
124
+ summary
125
+ ?.querySelector('a[href^="https://example.test/report"]')
126
+ ?.closest(`[${SESSION_REPLAY_BLOCK_ATTRIBUTE}]`) !== null,
127
+ ).toBe(status === "failed");
128
+ } finally {
129
+ await act(async () => root.unmount());
130
+ await client.shutdown();
131
+ container.remove();
132
+ vi.unstubAllGlobals();
133
+ }
134
+ },
135
+ );
136
+ });
137
+
138
+ describe("AgentInteractionItem replay privacy", () => {
139
+ it.each(["failed", "completed"] as const)(
140
+ "masks only failed interaction details (%s)",
141
+ async (kind) => {
142
+ const client = new AgentKitClient({
143
+ transport: {
144
+ async startRun() {
145
+ return { runId: "run-example" };
146
+ },
147
+ async *subscribeToRun() {},
148
+ async cancelRun() {},
149
+ },
150
+ });
151
+ const container = document.createElement("div");
152
+ document.body.appendChild(container);
153
+ const root = createRoot(container);
154
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
155
+ try {
156
+ await act(async () =>
157
+ root.render(
158
+ <AgentKitProvider controller={client} threadId="thread-example">
159
+ <AgentInteractionItem
160
+ value={{
161
+ id: "interaction-example",
162
+ kind,
163
+ agentId: "agent-example",
164
+ detail: "Example Person's example notes",
165
+ }}
166
+ threadId="thread-example"
167
+ />
168
+ </AgentKitProvider>,
169
+ ),
170
+ );
171
+ const detail = container.querySelector(
172
+ ".agentkit-agent-interaction-detail",
173
+ );
174
+ expect(detail?.textContent).toBe("Example Person's example notes");
175
+ expect(detail?.hasAttribute(SESSION_REPLAY_MASK_ATTRIBUTE)).toBe(
176
+ kind === "failed",
177
+ );
178
+ expect(detail?.hasAttribute("title")).toBe(kind !== "failed");
179
+ expect(
180
+ container
181
+ .querySelector(".agentkit-agent-interaction-label")
182
+ ?.closest(`[${SESSION_REPLAY_MASK_ATTRIBUTE}]`),
183
+ ).toBeNull();
184
+ } finally {
185
+ await act(async () => root.unmount());
186
+ await client.shutdown();
187
+ container.remove();
188
+ vi.unstubAllGlobals();
189
+ }
190
+ },
191
+ );
192
+ });
193
+
53
194
  describe("AgentKitChat interactions", () => {
54
195
  it("preserves host submission disablement", async () => {
55
196
  const client = new AgentKitClient({
@@ -1045,6 +1186,93 @@ describe("AgentKitChat interactions", () => {
1045
1186
  }
1046
1187
  });
1047
1188
 
1189
+ it("masks the default composer's send and attachment errors", async () => {
1190
+ const transport: AgentTransport = {
1191
+ capabilities: { uploads: true },
1192
+ async startRun() {
1193
+ throw new Error("Jane Doe's notes are locked");
1194
+ },
1195
+ async *subscribeToRun() {},
1196
+ async cancelRun() {},
1197
+ };
1198
+ const client = new AgentKitClient({ transport });
1199
+ const container = document.createElement("div");
1200
+ document.body.appendChild(container);
1201
+ const root = createRoot(container);
1202
+ const actEnvironment = globalThis as typeof globalThis & {
1203
+ IS_REACT_ACT_ENVIRONMENT?: boolean;
1204
+ };
1205
+ const previousActEnvironment = actEnvironment.IS_REACT_ACT_ENVIRONMENT;
1206
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
1207
+ const composerError = (text: string) =>
1208
+ [...container.querySelectorAll(".agentkit-composer-error span")].find(
1209
+ (span) => span.textContent?.includes(text),
1210
+ );
1211
+
1212
+ try {
1213
+ await act(async () => {
1214
+ root.render(
1215
+ <AgentKitProvider controller={client} threadId="thread-errors">
1216
+ <AgentKitChat
1217
+ composerProps={{
1218
+ initialText: "Summarize my notes",
1219
+ modelStatusChecksEnabled: false,
1220
+ }}
1221
+ />
1222
+ </AgentKitProvider>,
1223
+ );
1224
+ await Promise.resolve();
1225
+ });
1226
+
1227
+ const drop = new Event("drop", { bubbles: true, cancelable: true });
1228
+ Object.defineProperty(drop, "dataTransfer", {
1229
+ value: {
1230
+ types: ["Files"],
1231
+ files: [
1232
+ new File(["zip"], "Jane Doe taxes.zip", {
1233
+ type: "application/zip",
1234
+ }),
1235
+ ],
1236
+ dropEffect: "none",
1237
+ },
1238
+ });
1239
+ await act(async () => {
1240
+ container.querySelector(".agentkit-chat")?.dispatchEvent(drop);
1241
+ await new Promise((resolve) => setTimeout(resolve, 0));
1242
+ });
1243
+ expect(
1244
+ composerError("Jane Doe taxes.zip")?.hasAttribute(
1245
+ SESSION_REPLAY_MASK_ATTRIBUTE,
1246
+ ),
1247
+ ).toBe(true);
1248
+
1249
+ await act(async () => {
1250
+ container
1251
+ .querySelector<HTMLButtonElement>(
1252
+ '[data-agent-composer-slot="send-button"]',
1253
+ )
1254
+ ?.click();
1255
+ await new Promise((resolve) => setTimeout(resolve, 0));
1256
+ });
1257
+ expect(
1258
+ composerError("Jane Doe's notes are locked")?.hasAttribute(
1259
+ SESSION_REPLAY_MASK_ATTRIBUTE,
1260
+ ),
1261
+ ).toBe(true);
1262
+ } finally {
1263
+ await act(async () => {
1264
+ root.unmount();
1265
+ await Promise.resolve();
1266
+ });
1267
+ container.remove();
1268
+ if (previousActEnvironment === undefined) {
1269
+ delete actEnvironment.IS_REACT_ACT_ENVIRONMENT;
1270
+ } else {
1271
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = previousActEnvironment;
1272
+ }
1273
+ }
1274
+ });
1275
+
1048
1276
  it("disables transcript file drops when the host disables uploads", async () => {
1049
1277
  const transport: AgentTransport = {
1050
1278
  capabilities: { uploads: true },
@@ -17,6 +17,7 @@ import {
17
17
  import { ToolkitProvider } from "../../../provider.js";
18
18
  import { AgentChat } from "./chat.js";
19
19
  import {
20
+ AgentConnectionErrorView,
20
21
  AgentKitComposer,
21
22
  AgentKitChat,
22
23
  type AgentKitComposerProps,
@@ -32,6 +33,43 @@ import {
32
33
  } from "./context.js";
33
34
  import { AgentKitRoot } from "./root.js";
34
35
 
36
+ describe("AgentConnectionErrorView replay privacy", () => {
37
+ it("masks connection and recovery messages while preserving the headline and reconnect control", () => {
38
+ const client = new AgentKitClient({
39
+ transport: {
40
+ async startRun() {
41
+ return { runId: "run-example" };
42
+ },
43
+ async *subscribeToRun() {},
44
+ async cancelRun() {},
45
+ },
46
+ });
47
+ const html = renderToStaticMarkup(
48
+ <AgentKitProvider controller={client} threadId="thread-example">
49
+ <AgentConnectionErrorView
50
+ error={{
51
+ code: "runtime_error",
52
+ message: "Example Person's connection failed.",
53
+ retryable: true,
54
+ }}
55
+ threadId="thread-example"
56
+ recover={async () => {}}
57
+ recovering={false}
58
+ recoveryError={new Error("Example Document recovery failed.")}
59
+ />
60
+ </AgentKitProvider>,
61
+ );
62
+ expect(html).toContain(
63
+ '<span data-an-mask="">Example Person&#x27;s connection failed.</span>',
64
+ );
65
+ expect(html).toContain(
66
+ '<span data-an-mask="" class="agentkit-command-error">Example Document recovery failed.</span>',
67
+ );
68
+ expect(html).toContain("<strong>Something went wrong</strong>");
69
+ expect(html).toContain("Reconnect");
70
+ });
71
+ });
72
+
35
73
  describe("AgentMessageActions request IDs", () => {
36
74
  it("prefers an explicit request ID and never uses the local message ID", () => {
37
75
  expect(
@@ -1782,7 +1820,10 @@ describe("AgentKitChat", () => {
1782
1820
  expect(defaultHtml.match(/class="agentkit-run-failure"/g)).toHaveLength(1);
1783
1821
  expect(defaultHtml).toContain('data-run-id="run-failure"');
1784
1822
  expect(defaultHtml).toContain('data-error-code="tool_timeout"');
1785
- expect(defaultHtml).toContain("The dashboard check timed out.");
1823
+ expect(defaultHtml).toContain(
1824
+ '<span data-an-mask="">The dashboard check timed out.</span>',
1825
+ );
1826
+ expect(defaultHtml).toContain("<strong>Run failed</strong>");
1786
1827
 
1787
1828
  const slotCalls: AgentRunFailureRenderProps[] = [];
1788
1829
  const RunFailure = (props: AgentRunFailureRenderProps) => {
@@ -138,6 +138,11 @@ import {
138
138
  } from "./context.js";
139
139
  import { AgentStreamingText } from "./streaming-text.js";
140
140
 
141
+ // AgentKit React installs without @agent-native/core, so it repeats core's
142
+ // replay markers. Its specs assert core's attribute names.
143
+ const SESSION_REPLAY_MASK_PROPS = { "data-an-mask": "" } as const;
144
+ const SESSION_REPLAY_BLOCK_PROPS = { "data-an-block": "" } as const;
145
+
141
146
  export interface AgentKitErrorBoundaryProps {
142
147
  children: ReactNode;
143
148
  resetKey?: string | number;
@@ -920,7 +925,12 @@ export function AgentInteractionItem({
920
925
  {object ? (
921
926
  <ObjectRenderer value={object} threadId={threadId} />
922
927
  ) : detail ? (
923
- <span className="agentkit-agent-interaction-detail" title={detail}>
928
+ <span
929
+ {...(interaction.kind === "failed"
930
+ ? SESSION_REPLAY_MASK_PROPS
931
+ : { title: detail })}
932
+ className="agentkit-agent-interaction-detail"
933
+ >
924
934
  {detail}
925
935
  </span>
926
936
  ) : null}
@@ -987,7 +997,13 @@ export function AgentActivityItem({
987
997
  </span>
988
998
  {object ? <ObjectRenderer value={object} threadId={threadId} /> : null}
989
999
  {detail ? (
990
- <span className="agentkit-activity-detail" title={detail}>
1000
+ // Replays mask text but record attributes, so failure text gets no title.
1001
+ <span
1002
+ {...(activity.status === "failed"
1003
+ ? SESSION_REPLAY_MASK_PROPS
1004
+ : { title: detail })}
1005
+ className="agentkit-activity-detail"
1006
+ >
991
1007
  {detail}
992
1008
  </span>
993
1009
  ) : null}
@@ -1008,7 +1024,11 @@ export function AgentActivityItem({
1008
1024
  ) : null}
1009
1025
  </div>
1010
1026
  {open ? (
1011
- <div className="agentkit-activity-summary">
1027
+ // Summary parts can render links, and replays keep their attributes.
1028
+ <div
1029
+ {...(activity.status === "failed" ? SESSION_REPLAY_BLOCK_PROPS : {})}
1030
+ className="agentkit-activity-summary"
1031
+ >
1012
1032
  {activity.summary?.map((part, index) => {
1013
1033
  const safePart =
1014
1034
  part.type === "text"
@@ -2331,7 +2351,11 @@ export function AgentApprovalPrompt({
2331
2351
  )}
2332
2352
  </div>
2333
2353
  {resolution.error ? (
2334
- <p className="agentkit-command-error" role="alert">
2354
+ <p
2355
+ {...SESSION_REPLAY_MASK_PROPS}
2356
+ className="agentkit-command-error"
2357
+ role="alert"
2358
+ >
2335
2359
  {resolution.error.message}
2336
2360
  </p>
2337
2361
  ) : null}
@@ -2452,7 +2476,7 @@ export function AgentConnectionRequestCard({
2452
2476
  {resolution.error ? (
2453
2477
  <div className="agentkit-command-error" role="alert">
2454
2478
  <IconAlertCircle aria-hidden="true" className="agentkit-icon" />
2455
- <span>{resolution.error.message}</span>
2479
+ <span {...SESSION_REPLAY_MASK_PROPS}>{resolution.error.message}</span>
2456
2480
  </div>
2457
2481
  ) : null}
2458
2482
  </Surface>
@@ -2501,7 +2525,11 @@ function AgentWidgetActionButton({
2501
2525
  {action.label}
2502
2526
  </ActionButton>
2503
2527
  {invocation.error ? (
2504
- <span className="agentkit-command-error" role="alert">
2528
+ <span
2529
+ {...SESSION_REPLAY_MASK_PROPS}
2530
+ className="agentkit-command-error"
2531
+ role="alert"
2532
+ >
2505
2533
  {invocation.error.message}
2506
2534
  </span>
2507
2535
  ) : null}
@@ -3724,7 +3752,11 @@ export function AgentMessageActions({
3724
3752
  </>
3725
3753
  )}
3726
3754
  {actionError ? (
3727
- <span className="agentkit-command-error" role="alert">
3755
+ <span
3756
+ {...SESSION_REPLAY_MASK_PROPS}
3757
+ className="agentkit-command-error"
3758
+ role="alert"
3759
+ >
3728
3760
  {actionError.message}
3729
3761
  </span>
3730
3762
  ) : null}
@@ -3880,7 +3912,7 @@ export function AgentRunFailure({
3880
3912
  <IconAlertCircle aria-hidden="true" className="agentkit-icon" />
3881
3913
  <div className="agentkit-run-failure-copy">
3882
3914
  <strong>{labels.runFailed}</strong>
3883
- <span>{error.message}</span>
3915
+ <span {...SESSION_REPLAY_MASK_PROPS}>{error.message}</span>
3884
3916
  {canContinue ? (
3885
3917
  <div className="agentkit-error-actions">
3886
3918
  <ActionButton
@@ -3919,7 +3951,7 @@ export function AgentConnectionErrorView({
3919
3951
  role="alert"
3920
3952
  >
3921
3953
  <strong>{labels.error}</strong>
3922
- <span>{error.message}</span>
3954
+ <span {...SESSION_REPLAY_MASK_PROPS}>{error.message}</span>
3923
3955
  {error.retryable ? (
3924
3956
  <div className="agentkit-error-actions">
3925
3957
  <ActionButton
@@ -3933,7 +3965,9 @@ export function AgentConnectionErrorView({
3933
3965
  </div>
3934
3966
  ) : null}
3935
3967
  {recoveryError ? (
3936
- <span className="agentkit-command-error">{recoveryError.message}</span>
3968
+ <span {...SESSION_REPLAY_MASK_PROPS} className="agentkit-command-error">
3969
+ {recoveryError.message}
3970
+ </span>
3937
3971
  ) : null}
3938
3972
  </div>
3939
3973
  );
@@ -4691,13 +4725,13 @@ export function AgentKitComposer({
4691
4725
  {command.error ? (
4692
4726
  <div className="agentkit-composer-error" role="alert">
4693
4727
  <IconAlertCircle aria-hidden="true" className="agentkit-icon" />
4694
- <span>{command.error.message}</span>
4728
+ <span {...SESSION_REPLAY_MASK_PROPS}>{command.error.message}</span>
4695
4729
  </div>
4696
4730
  ) : null}
4697
4731
  {attachmentError ? (
4698
4732
  <div className="agentkit-composer-error" role="alert">
4699
4733
  <IconAlertCircle aria-hidden="true" className="agentkit-icon" />
4700
- <span>{attachmentError}</span>
4734
+ <span {...SESSION_REPLAY_MASK_PROPS}>{attachmentError}</span>
4701
4735
  </div>
4702
4736
  ) : null}
4703
4737
  </div>
@@ -204,9 +204,22 @@ async function requestJson(
204
204
  url: string,
205
205
  init: RequestInit = {},
206
206
  ): Promise<AuthRequestResult> {
207
+ const headers = new Headers(init.headers);
208
+ if (typeof window !== "undefined") {
209
+ const requestUrl = new URL(url, window.location.href);
210
+ const sessionId = getAnalyticsSessionId();
211
+ if (
212
+ requestUrl.origin === window.location.origin &&
213
+ sessionId &&
214
+ /^[!-~]{1,127}$/.test(sessionId)
215
+ ) {
216
+ headers.set("X-Agent-Native-Session-Id", sessionId);
217
+ }
218
+ }
207
219
  const response = await fetch(url, {
208
220
  credentials: "include",
209
221
  ...init,
222
+ headers,
210
223
  });
211
224
  let data: Record<string, unknown> = {};
212
225
  let readable = false;
@@ -1,7 +1,10 @@
1
1
  // @vitest-environment happy-dom
2
2
 
3
3
  import { AgentKitClient } from "@agent-native/agentkit/client";
4
- import type { AgentTransport } from "@agent-native/agentkit/protocol";
4
+ import type {
5
+ AgentMessage,
6
+ AgentTransport,
7
+ } from "@agent-native/agentkit/protocol";
5
8
  import React, { act, createRef } from "react";
6
9
  import { createRoot, type Root } from "react-dom/client";
7
10
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
@@ -639,6 +642,7 @@ import {
639
642
  import { AgentKitActionWidget } from "./agentkit-chat/action-widget.js";
640
643
  import {
641
644
  AgentKitAssistantChat,
645
+ agentMessageTextFromParts,
642
646
  type AgentKitAssistantChatProps,
643
647
  } from "./AgentKitAssistantChat.js";
644
648
  import type {
@@ -859,7 +863,10 @@ describe("AgentKitAssistantChat host behavior", () => {
859
863
  parts: [
860
864
  {
861
865
  type: "text",
862
- text: 'Summarize @[the sprint|resource:123]\n<context data-agentkit-context-encoding="entities-v1">Private context</context>',
866
+ text: appendAgentChatContextToMessage(
867
+ "Summarize @[the sprint|resource:123] <context>",
868
+ "Private context",
869
+ ),
863
870
  },
864
871
  ],
865
872
  };
@@ -902,7 +909,81 @@ describe("AgentKitAssistantChat host behavior", () => {
902
909
 
903
910
  expect(savedSnapshots).toHaveBeenCalledWith(
904
911
  chatMocks.threadId,
905
- expect.objectContaining({ title: "Summarize @the sprint" }),
912
+ expect.objectContaining({
913
+ title: "Summarize @the sprint <context>",
914
+ preview: "Summarize @[the sprint|resource:123] <context>",
915
+ }),
916
+ );
917
+ });
918
+
919
+ it("strips ambiguous text between legacy blocks across raw message parts", async () => {
920
+ const savedSnapshots = vi.fn();
921
+ const messageParts: AgentMessage["parts"] = [
922
+ {
923
+ type: "text",
924
+ text: "Summarize sprint <context>private first</context>ambiguous private",
925
+ },
926
+ {
927
+ type: "text",
928
+ text: " gap<context>private second</context> visible continuation",
929
+ },
930
+ ];
931
+ const message = {
932
+ id: "message-user-legacy-context",
933
+ role: "user",
934
+ status: "complete",
935
+ createdAt: "2026-10-07T12:00:00.000Z",
936
+ parts: messageParts,
937
+ };
938
+ chatMocks.thread = {
939
+ ...chatMocks.thread,
940
+ thread: {
941
+ id: chatMocks.threadId,
942
+ title: "",
943
+ createdAt: message.createdAt,
944
+ updatedAt: message.createdAt,
945
+ },
946
+ messages: [message],
947
+ events: [],
948
+ activeRunIds: [],
949
+ runs: {},
950
+ approvals: {},
951
+ approvalRunIds: {},
952
+ connectionRequests: {},
953
+ connectionRequestRunIds: {},
954
+ tools: {},
955
+ activities: {},
956
+ queuedMessages: [],
957
+ tasks: {},
958
+ taskGroups: {},
959
+ widgets: {},
960
+ widgetMessageIds: {},
961
+ annotations: {},
962
+ annotationMessageIds: {},
963
+ agents: {},
964
+ agentInteractions: [],
965
+ artifacts: [],
966
+ };
967
+
968
+ const props = baseProps({
969
+ onSaveThread: savedSnapshots,
970
+ runtime: {} as never,
971
+ });
972
+ await mount(props);
973
+ await act(async () => root.render(null));
974
+
975
+ expect(agentMessageTextFromParts(messageParts)).toBe(
976
+ "Summarize sprint visible continuation",
977
+ );
978
+ expect(savedSnapshots).toHaveBeenCalledWith(
979
+ chatMocks.threadId,
980
+ expect.objectContaining({
981
+ title: "Summarize sprint visible continuation",
982
+ preview: "Summarize sprint visible continuation",
983
+ }),
984
+ );
985
+ expect(savedSnapshots.mock.calls[0]?.[1].preview).not.toContain(
986
+ "ambiguous private",
906
987
  );
907
988
  });
908
989
 
@@ -4511,6 +4592,29 @@ describe("AgentKitAssistantChat host behavior", () => {
4511
4592
  window.removeEventListener("agent-chat:missing-api-key", onBlocked);
4512
4593
  });
4513
4594
 
4595
+ it("masks a connection failure message without masking recovery controls", async () => {
4596
+ chatMocks.connectionError = {
4597
+ code: "runtime_error",
4598
+ message: "Example Person's example document is locked.",
4599
+ retryable: true,
4600
+ };
4601
+ await mount(baseProps());
4602
+ const message = Array.from(container.querySelectorAll("span")).find(
4603
+ (element) =>
4604
+ element.textContent === `Error: ${chatMocks.connectionError.message}`,
4605
+ );
4606
+ expect(message?.hasAttribute("data-an-mask")).toBe(true);
4607
+ expect(
4608
+ message?.closest('[role="alert"]')?.hasAttribute("data-an-mask"),
4609
+ ).toBe(false);
4610
+ expect(
4611
+ message
4612
+ ?.closest('[role="alert"]')
4613
+ ?.querySelector("button")
4614
+ ?.closest("[data-an-mask]"),
4615
+ ).toBeNull();
4616
+ });
4617
+
4514
4618
  it("does not repeat the composer setup card in a missing-key run failure", async () => {
4515
4619
  chatMocks.readiness = {
4516
4620
  canChat: false,
@@ -5078,8 +5182,15 @@ describe("AgentKitAssistantChat host behavior", () => {
5078
5182
  chatMocks.composerProps.stopButton.props.onClick();
5079
5183
  await Promise.resolve();
5080
5184
  });
5081
- expect(container.querySelector('[role="alert"]')?.textContent).toContain(
5082
- "Stop unavailable",
5185
+ const alert = container.querySelector('[role="alert"]');
5186
+ expect(alert?.textContent).toContain("Stop unavailable");
5187
+ const message = Array.from(alert?.querySelectorAll("span") ?? []).find(
5188
+ (element) => element.textContent === "Stop unavailable",
5189
+ );
5190
+ expect(message?.hasAttribute("data-an-mask")).toBe(true);
5191
+ expect(alert?.hasAttribute("data-an-mask")).toBe(false);
5192
+ expect(alert?.querySelector("button")?.closest("[data-an-mask]")).toBe(
5193
+ null,
5083
5194
  );
5084
5195
  await act(async () => {
5085
5196
  chatMocks.composerProps.stopButton.props.onClick();