@agent-native/toolkit 0.198.3 → 0.198.4

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 (144) hide show
  1. package/dist/app/agentkit/react/components.d.ts +4 -1
  2. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  3. package/dist/app/agentkit/react/components.js +12 -4
  4. package/dist/app/agentkit/react/components.js.map +1 -1
  5. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  6. package/dist/app/chat/AgentKitAssistantChat.js +43 -21
  7. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  8. package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
  9. package/dist/app/chat/AgentSidebar.js +2 -0
  10. package/dist/app/chat/AgentSidebar.js.map +1 -1
  11. package/dist/app/chat/FileStorageSetupPopover.js +2 -2
  12. package/dist/app/chat/FileStorageSetupPopover.js.map +1 -1
  13. package/dist/app/chat/MultiTabAssistantChat.js +1 -1
  14. package/dist/app/chat/agentkit-chat/connections.d.ts +1 -4
  15. package/dist/app/chat/agentkit-chat/connections.d.ts.map +1 -1
  16. package/dist/app/chat/agentkit-chat/connections.js +1 -26
  17. package/dist/app/chat/agentkit-chat/connections.js.map +1 -1
  18. package/dist/app/chat/agentkit-chat/history.d.ts +4 -1
  19. package/dist/app/chat/agentkit-chat/history.d.ts.map +1 -1
  20. package/dist/app/chat/agentkit-chat/history.js +17 -5
  21. package/dist/app/chat/agentkit-chat/history.js.map +1 -1
  22. package/dist/app/chat/chat/history-types.d.ts +1 -1
  23. package/dist/app/chat/chat/history-types.d.ts.map +1 -1
  24. package/dist/app/chat/chat-first/copy.d.ts +1 -2
  25. package/dist/app/chat/chat-first/copy.d.ts.map +1 -1
  26. package/dist/app/chat/chat-first/copy.js +1 -121
  27. package/dist/app/chat/chat-first/copy.js.map +1 -1
  28. package/dist/app/chat/chat-first-copy.d.ts +3 -0
  29. package/dist/app/chat/chat-first-copy.d.ts.map +1 -0
  30. package/dist/app/chat/chat-first-copy.js +122 -0
  31. package/dist/app/chat/chat-first-copy.js.map +1 -0
  32. package/dist/app/feature-flags/FeatureFlagsPanel.d.ts.map +1 -1
  33. package/dist/app/feature-flags/FeatureFlagsPanel.js +1 -0
  34. package/dist/app/feature-flags/FeatureFlagsPanel.js.map +1 -1
  35. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  36. package/dist/app/i18n/catalogs/ar-SA.js +2 -1
  37. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  38. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  39. package/dist/app/i18n/catalogs/de-DE.js +2 -1
  40. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  41. package/dist/app/i18n/catalogs/en-US.d.ts +2 -1
  42. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  43. package/dist/app/i18n/catalogs/en-US.js +2 -1
  44. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  45. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  46. package/dist/app/i18n/catalogs/es-ES.js +2 -1
  47. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  48. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  49. package/dist/app/i18n/catalogs/fr-FR.js +2 -1
  50. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  51. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  52. package/dist/app/i18n/catalogs/hi-IN.js +2 -1
  53. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  54. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  55. package/dist/app/i18n/catalogs/ja-JP.js +2 -1
  56. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  57. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  58. package/dist/app/i18n/catalogs/ko-KR.js +2 -1
  59. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  60. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  61. package/dist/app/i18n/catalogs/pt-BR.js +2 -1
  62. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  63. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  64. package/dist/app/i18n/catalogs/zh-CN.js +2 -1
  65. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  66. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  67. package/dist/app/i18n/catalogs/zh-TW.js +2 -1
  68. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  69. package/dist/app/labs/LabsSettings.d.ts.map +1 -1
  70. package/dist/app/labs/LabsSettings.js +7 -3
  71. package/dist/app/labs/LabsSettings.js.map +1 -1
  72. package/dist/app/org/OrgGeneralSection.d.ts.map +1 -1
  73. package/dist/app/org/OrgGeneralSection.js +21 -18
  74. package/dist/app/org/OrgGeneralSection.js.map +1 -1
  75. package/dist/app/org/OrgSwitcher.d.ts.map +1 -1
  76. package/dist/app/org/OrgSwitcher.js +3 -2
  77. package/dist/app/org/OrgSwitcher.js.map +1 -1
  78. package/dist/app/org/workspace-app-links.d.ts +1 -0
  79. package/dist/app/org/workspace-app-links.d.ts.map +1 -1
  80. package/dist/app/org/workspace-app-links.js +3 -0
  81. package/dist/app/org/workspace-app-links.js.map +1 -1
  82. package/dist/app/resources/McpAgentKitConnectionRequest.d.ts +7 -2
  83. package/dist/app/resources/McpAgentKitConnectionRequest.d.ts.map +1 -1
  84. package/dist/app/resources/McpAgentKitConnectionRequest.js +132 -13
  85. package/dist/app/resources/McpAgentKitConnectionRequest.js.map +1 -1
  86. package/dist/icons/ResourceIconPicker.d.ts +6 -1
  87. package/dist/icons/ResourceIconPicker.d.ts.map +1 -1
  88. package/dist/icons/ResourceIconPicker.js +45 -6
  89. package/dist/icons/ResourceIconPicker.js.map +1 -1
  90. package/package.json +6 -4
  91. package/src/app/agentkit/react/components.spec.tsx +3 -3
  92. package/src/app/agentkit/react/components.tsx +22 -4
  93. package/src/app/agentkit/react/lifecycle.spec.tsx +42 -0
  94. package/src/app/chat/AgentKitAssistantChat.spec.tsx +114 -11
  95. package/src/app/chat/AgentKitAssistantChat.tsx +78 -17
  96. package/src/app/chat/AgentPanel.header.spec.ts +59 -22
  97. package/src/app/chat/AgentSidebar.tsx +2 -0
  98. package/src/app/chat/FileStorageSetupPopover.tsx +2 -2
  99. package/src/app/chat/MultiTabAssistantChat.messageCount.spec.tsx +3 -1
  100. package/src/app/chat/MultiTabAssistantChat.spec.tsx +8 -4
  101. package/src/app/chat/MultiTabAssistantChat.tsx +1 -1
  102. package/src/app/chat/agentkit-chat/action-widget.spec.tsx +5 -17
  103. package/src/app/chat/agentkit-chat/connections.spec.tsx +137 -0
  104. package/src/app/chat/agentkit-chat/connections.ts +2 -37
  105. package/src/app/chat/agentkit-chat/history.tsx +23 -8
  106. package/src/app/chat/chat/history-types.ts +1 -1
  107. package/src/app/chat/chat/tool-call-display.spec.tsx +2 -2
  108. package/src/app/chat/chat/widgets/record-change-widget.spec.tsx +20 -29
  109. package/src/app/chat/chat-first/copy.ts +1 -133
  110. package/src/app/chat/chat-first-copy.ts +133 -0
  111. package/src/app/chat/composer/use-agentkit-capabilities.hardening.spec.tsx +3 -2
  112. package/src/app/feature-flags/FeatureFlagsPanel.tsx +1 -0
  113. package/src/app/i18n/catalogs/ar-SA.ts +2 -1
  114. package/src/app/i18n/catalogs/de-DE.ts +3 -1
  115. package/src/app/i18n/catalogs/en-US.ts +2 -1
  116. package/src/app/i18n/catalogs/es-ES.ts +2 -1
  117. package/src/app/i18n/catalogs/fr-FR.ts +3 -1
  118. package/src/app/i18n/catalogs/hi-IN.ts +2 -1
  119. package/src/app/i18n/catalogs/ja-JP.ts +2 -1
  120. package/src/app/i18n/catalogs/ko-KR.ts +2 -1
  121. package/src/app/i18n/catalogs/pt-BR.ts +3 -1
  122. package/src/app/i18n/catalogs/zh-CN.ts +2 -1
  123. package/src/app/i18n/catalogs/zh-TW.ts +2 -1
  124. package/src/app/integrations/IntegrationDetailPage.spec.tsx +1 -1
  125. package/src/app/labs/LabsSettings.tsx +46 -10
  126. package/src/app/observability/ThumbsFeedback.spec.tsx +15 -0
  127. package/src/app/onboarding/FirstRunOnboarding.spec.tsx +4 -0
  128. package/src/app/org/OrgGeneralSection.tsx +32 -22
  129. package/src/app/org/OrgSwitcher.tsx +3 -2
  130. package/src/app/org/workspace-app-links.spec.ts +4 -0
  131. package/src/app/org/workspace-app-links.ts +8 -1
  132. package/src/app/resources/McpAgentKitConnectionRequest.spec.tsx +371 -2
  133. package/src/app/resources/McpAgentKitConnectionRequest.tsx +171 -11
  134. package/src/app/settings/SettingsTabsPage.spec.tsx +4 -2
  135. package/src/app/settings/shell/SettingsShell.spec.tsx +14 -8
  136. package/src/app/settings/shell/pages/app-group-pages.spec.tsx +35 -5
  137. package/src/app/settings/shell/pages/resource-pages.spec.tsx +3 -0
  138. package/src/app/settings/usage/UsagePage.spec.tsx +3 -3
  139. package/src/app/shared/lazy-chunk-error-boundary.spec.tsx +2 -0
  140. package/src/app-shell/sidebar-overflow.spec.tsx +4 -1
  141. package/src/design-tweaks/visual-style-controls.spec.tsx +38 -0
  142. package/src/editor/useCollabReconcile.concurrent.spec.ts +2 -1
  143. package/src/icons/ResourceIconPicker.spec.tsx +270 -0
  144. package/src/icons/ResourceIconPicker.tsx +72 -4
@@ -3090,7 +3090,7 @@ export function MultiTabAssistantChat({
3090
3090
  <div
3091
3091
  className={cn(
3092
3092
  "relative flex-1 flex flex-col min-h-0",
3093
- renderOverlay && "pt-14",
3093
+ renderOverlay && "pt-12",
3094
3094
  )}
3095
3095
  data-agent-page-chat-topbar={renderOverlay ? "" : undefined}
3096
3096
  data-agent-page-chat-scrolled={
@@ -11,10 +11,7 @@ import {
11
11
  ACTION_CHAT_UI_DATA_WIDGET_RENDERER,
12
12
  ACTION_CHAT_UI_RECORD_CHANGE_RENDERER,
13
13
  } from "@agent-native/core/action-ui";
14
- import {
15
- AgentNativeI18nProvider as CoreAgentNativeI18nProvider,
16
- type AgentNativeI18nProviderProps,
17
- } from "@agent-native/core/client/i18n";
14
+ import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
18
15
  import {
19
16
  createDataInsightsWidgetResult,
20
17
  createDataTableWidgetResult,
@@ -32,16 +29,7 @@ import {
32
29
  } from "../chat/tool-render-registry.js";
33
30
  import { AgentKitActionWidget } from "./action-widget.js";
34
31
 
35
- const toolkitI18nCatalog = createToolkitI18nCatalog({ messages: {} });
36
-
37
- function AgentNativeI18nProvider(props: AgentNativeI18nProviderProps) {
38
- return (
39
- <CoreAgentNativeI18nProvider
40
- {...props}
41
- catalog={props.catalog ?? toolkitI18nCatalog}
42
- />
43
- );
44
- }
32
+ const catalog = createToolkitI18nCatalog({ messages: {} });
45
33
 
46
34
  describe("AgentKitActionWidget", () => {
47
35
  it("resolves the renderer with stored action args and structured result", async () => {
@@ -229,7 +217,7 @@ describe("AgentKitActionWidget", () => {
229
217
  try {
230
218
  await act(async () => {
231
219
  root.render(
232
- <AgentNativeI18nProvider persistPreference={false}>
220
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
233
221
  <AgentKitProvider controller={client} threadId="thread-1">
234
222
  <>
235
223
  <AgentKitActionWidget value={formsWidget} threadId="thread-1" />
@@ -316,7 +304,7 @@ describe("AgentKitActionWidget", () => {
316
304
  try {
317
305
  await act(async () => {
318
306
  root.render(
319
- <AgentNativeI18nProvider persistPreference={false}>
307
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
320
308
  <AgentKitProvider controller={client} threadId="thread-1">
321
309
  <>
322
310
  {widgets.map((widget) => (
@@ -399,7 +387,7 @@ describe("AgentKitActionWidget", () => {
399
387
  try {
400
388
  await act(async () => {
401
389
  root.render(
402
- <AgentNativeI18nProvider persistPreference={false}>
390
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
403
391
  <AgentKitProvider controller={client} threadId="thread-1">
404
392
  {widgets.map((widget) => (
405
393
  <AgentKitActionWidget
@@ -1,6 +1,8 @@
1
1
  // @vitest-environment happy-dom
2
2
 
3
3
  import {
4
+ clearMcpConnectionResume,
5
+ getPendingMcpConnectionResume,
4
6
  notifyMcpConnectionComplete,
5
7
  saveMcpConnectionResume,
6
8
  } from "@agent-native/core/client/resources/mcp-connection-resume";
@@ -16,6 +18,7 @@ afterEach(() => {
16
18
  if (root) act(() => root?.unmount());
17
19
  root = undefined;
18
20
  window.sessionStorage.clear();
21
+ window.localStorage.clear();
19
22
  window.history.replaceState({}, "", "/chat/thread-1");
20
23
  });
21
24
 
@@ -78,4 +81,138 @@ describe("McpAgentKitConnectionResume", () => {
78
81
  );
79
82
  expect(onMessageResume).not.toHaveBeenCalled();
80
83
  });
84
+
85
+ it("shows a failure and keeps the saved request when resuming fails", async () => {
86
+ const target = { threadId: "thread-1", runId: "run-1", requestId: "req-1" };
87
+ saveMcpConnectionResume("Restore the request.", target);
88
+ const onResume = vi.fn().mockRejectedValue(new Error("offline"));
89
+ const container = document.createElement("div");
90
+ root = createRoot(container);
91
+
92
+ await act(async () => {
93
+ root?.render(<McpAgentKitConnectionResume onResume={onResume} />);
94
+ await Promise.resolve();
95
+ });
96
+
97
+ expect(container.querySelector('[role="alert"]')).not.toBeNull();
98
+ expect(getPendingMcpConnectionResume()).toMatchObject({
99
+ message: "Restore the request.",
100
+ agentKit: target,
101
+ });
102
+ });
103
+
104
+ it("resumes a completed popup after remount and continues when the run is gone", async () => {
105
+ window.history.replaceState({}, "", "/chat/thread-1");
106
+ const target = {
107
+ threadId: "thread-1",
108
+ runId: "run-1",
109
+ requestId: "req-1",
110
+ };
111
+ const completionId = "8d1bd7cf-419e-4ff0-8545-19dedb819154";
112
+ saveMcpConnectionResume("Restore the request.", target, completionId);
113
+ const onResume = vi
114
+ .fn()
115
+ .mockRejectedValue(new Error(`Unknown AgentKit run: ${target.runId}`));
116
+ const onMessageResume = vi.fn();
117
+ const container = document.createElement("div");
118
+ root = createRoot(container);
119
+
120
+ await act(async () => {
121
+ root?.render(
122
+ <McpAgentKitConnectionResume
123
+ onResume={onResume}
124
+ onMessageResume={onMessageResume}
125
+ />,
126
+ );
127
+ });
128
+ expect(onResume).not.toHaveBeenCalled();
129
+ expect(getPendingMcpConnectionResume()).toBeNull();
130
+
131
+ act(() => {
132
+ root?.unmount();
133
+ });
134
+ root = undefined;
135
+ window.localStorage.setItem(
136
+ `agent-native:mcp-connection-completion:${completionId}`,
137
+ "1",
138
+ );
139
+
140
+ const remountedContainer = document.createElement("div");
141
+ root = createRoot(remountedContainer);
142
+ await act(async () => {
143
+ root?.render(
144
+ <McpAgentKitConnectionResume
145
+ onResume={onResume}
146
+ onMessageResume={onMessageResume}
147
+ />,
148
+ );
149
+ await new Promise((resolve) => setTimeout(resolve, 0));
150
+ });
151
+
152
+ expect(onResume).toHaveBeenCalledOnce();
153
+ expect(onResume).toHaveBeenCalledWith(
154
+ target,
155
+ expect.objectContaining({ message: "Restore the request." }),
156
+ );
157
+ expect(onMessageResume).toHaveBeenCalledOnce();
158
+ expect(onMessageResume).toHaveBeenCalledWith(
159
+ expect.objectContaining({ message: "Restore the request." }),
160
+ );
161
+ expect(getPendingMcpConnectionResume()).toBeNull();
162
+ clearMcpConnectionResume();
163
+ });
164
+
165
+ it("keeps the saved request when the fallback chat submission fails", async () => {
166
+ const target = { threadId: "thread-1", runId: "run-1", requestId: "req-1" };
167
+ saveMcpConnectionResume("Restore the request.", target);
168
+ const onResume = vi
169
+ .fn()
170
+ .mockRejectedValue(new Error(`Unknown AgentKit run: ${target.runId}`));
171
+ const onMessageResume = vi.fn().mockRejectedValue(new Error("offline"));
172
+ const container = document.createElement("div");
173
+ root = createRoot(container);
174
+
175
+ await act(async () => {
176
+ root?.render(
177
+ <McpAgentKitConnectionResume
178
+ onResume={onResume}
179
+ onMessageResume={onMessageResume}
180
+ />,
181
+ );
182
+ await new Promise((resolve) => setTimeout(resolve, 0));
183
+ });
184
+
185
+ expect(onMessageResume).toHaveBeenCalledOnce();
186
+ expect(container.querySelector('[role="alert"]')).not.toBeNull();
187
+ expect(getPendingMcpConnectionResume()).toMatchObject({
188
+ message: "Restore the request.",
189
+ agentKit: target,
190
+ });
191
+ });
192
+
193
+ it("clears a stale failure alert after a later successful retry", async () => {
194
+ const target = { threadId: "thread-1", runId: "run-1", requestId: "req-1" };
195
+ saveMcpConnectionResume("Restore the request.", target);
196
+ const onResume = vi
197
+ .fn()
198
+ .mockRejectedValueOnce(new Error("offline"))
199
+ .mockResolvedValue(undefined);
200
+ const container = document.createElement("div");
201
+ root = createRoot(container);
202
+
203
+ await act(async () => {
204
+ root?.render(<McpAgentKitConnectionResume onResume={onResume} />);
205
+ await new Promise((resolve) => setTimeout(resolve, 0));
206
+ });
207
+ expect(container.querySelector('[role="alert"]')).not.toBeNull();
208
+
209
+ await act(async () => {
210
+ notifyMcpConnectionComplete();
211
+ await new Promise((resolve) => setTimeout(resolve, 0));
212
+ });
213
+
214
+ expect(onResume).toHaveBeenCalledTimes(2);
215
+ expect(container.querySelector('[role="alert"]')).toBeNull();
216
+ expect(getPendingMcpConnectionResume()).toBeNull();
217
+ });
81
218
  });
@@ -1,39 +1,4 @@
1
- import {
2
- addMcpConnectionCompleteListener,
3
- consumeMcpConnectionResume,
4
- } from "@agent-native/core/client/resources/mcp-connection-resume";
5
- import { useEffect, useRef } from "react";
6
-
7
- import {
1
+ export {
8
2
  McpAgentKitConnectionRequestCard,
9
- type McpAgentKitConnectionResumeProps,
3
+ McpAgentKitConnectionResume,
10
4
  } from "../../resources/index.js";
11
-
12
- export { McpAgentKitConnectionRequestCard };
13
-
14
- /** Consumes OAuth resumes once and routes them to the matching chat submit API. */
15
- export function McpAgentKitConnectionResume({
16
- onResume,
17
- onMessageResume,
18
- }: McpAgentKitConnectionResumeProps) {
19
- const onResumeRef = useRef(onResume);
20
- const onMessageResumeRef = useRef(onMessageResume);
21
- onResumeRef.current = onResume;
22
- onMessageResumeRef.current = onMessageResume;
23
-
24
- // Chat callbacks change with render state; one listener must own each stored resume.
25
- useEffect(() => {
26
- const resumePending = () => {
27
- const request = consumeMcpConnectionResume();
28
- if (!request) return;
29
- const operation = request.agentKit
30
- ? onResumeRef.current(request.agentKit, request)
31
- : onMessageResumeRef.current?.(request);
32
- void Promise.resolve(operation).catch(() => {});
33
- };
34
-
35
- resumePending();
36
- return addMcpConnectionCompleteListener(resumePending);
37
- }, []);
38
- return null;
39
- }
@@ -79,7 +79,7 @@ export interface AgentKitHistoryConfig<
79
79
  args?:
80
80
  | Record<string, unknown>
81
81
  | ((threadId: ThreadId) => Record<string, unknown>);
82
- getVersions: (result: TListResult) => readonly TVersion[];
82
+ getVersions: (result: TListResult) => readonly TVersion[] | null;
83
83
  };
84
84
  restore: {
85
85
  action: string;
@@ -108,6 +108,8 @@ export interface AgentKitHistoryConfig<
108
108
 
109
109
  export interface AgentKitHistoryContextValue {
110
110
  beginningVersion: AgentKitHistoryVersion | null;
111
+ historyLoadFailed: boolean;
112
+ isRetryingHistory: boolean;
111
113
  isBusy: boolean;
112
114
  isRestoring: boolean;
113
115
  isSubmissionInFlight: boolean;
@@ -117,6 +119,7 @@ export interface AgentKitHistoryContextValue {
117
119
  beginSubmission: () => Promise<(() => void) | null>;
118
120
  /** Wait until an in-flight restore has finished before mutating the host. */
119
121
  waitForRestore: () => Promise<void>;
122
+ retryHistory: () => void;
120
123
  findVersion: (
121
124
  message: AgentKitHistoryMessage,
122
125
  ) => AgentKitHistoryVersion | null;
@@ -711,15 +714,18 @@ export function AgentKitHistoryProvider<
711
714
  const currentThreadRef = useRef(threadId);
712
715
  const initializedRef = useRef(false);
713
716
 
714
- const versions = useMemo(() => {
715
- if (listQuery.data == null) return [];
717
+ const loadedVersions = useMemo(() => {
718
+ if (listQuery.data == null) return null;
716
719
  const result = history.list.getVersions(listQuery.data);
717
- return Array.isArray(result)
718
- ? result.filter((version): version is TVersion =>
719
- isAssistantChatHistoryVersion(version),
720
- )
721
- : [];
720
+ if (!Array.isArray(result)) return null;
721
+ return result.filter((version): version is TVersion =>
722
+ isAssistantChatHistoryVersion(version),
723
+ );
722
724
  }, [history.list, listQuery.data]);
725
+ const versions = loadedVersions ?? [];
726
+ const retryHistory = useCallback(() => {
727
+ void listQuery.refetch();
728
+ }, [listQuery.refetch]);
723
729
  const historyMessages = useMemo(
724
730
  () => getAgentKitHistoryMessages(threadId, thread, history.scope),
725
731
  [history.scope, thread, threadId],
@@ -918,6 +924,9 @@ export function AgentKitHistoryProvider<
918
924
  threadId,
919
925
  history.isEditable,
920
926
  ),
927
+ historyLoadFailed:
928
+ listQuery.isError || (listQuery.isSuccess && loadedVersions == null),
929
+ isRetryingHistory: listQuery.isFetching,
921
930
  isBusy:
922
931
  thread.activeRunIds.length > 0 ||
923
932
  isRestoring ||
@@ -930,6 +939,7 @@ export function AgentKitHistoryProvider<
930
939
  findVersion,
931
940
  toHistoryMessage,
932
941
  restoreVersion,
942
+ retryHistory,
933
943
  }),
934
944
  [
935
945
  findVersion,
@@ -937,8 +947,13 @@ export function AgentKitHistoryProvider<
937
947
  beginSubmission,
938
948
  waitForRestore,
939
949
  history.isEditable,
950
+ listQuery.isError,
951
+ listQuery.isFetching,
952
+ listQuery.isSuccess,
953
+ loadedVersions,
940
954
  isRestoring,
941
955
  restoreVersion,
956
+ retryHistory,
942
957
  submissionsInFlight,
943
958
  submissionCountsByThread,
944
959
  thread.activeRunIds.length,
@@ -38,7 +38,7 @@ export interface AssistantChatHistoryConfig<
38
38
  args?:
39
39
  | Record<string, unknown>
40
40
  | ((threadId?: string) => Record<string, unknown>);
41
- getVersions: (result: TListResult) => readonly TVersion[];
41
+ getVersions: (result: TListResult) => readonly TVersion[] | null;
42
42
  };
43
43
  restore: {
44
44
  action: string;
@@ -990,7 +990,7 @@ describe("ToolCallDisplay native renderers", () => {
990
990
  await act(async () => {
991
991
  root.render(
992
992
  <AgentNativeI18nProvider
993
- catalog={{
993
+ catalog={createToolkitI18nCatalog({
994
994
  sourceLocale: "en-US",
995
995
  messages: {
996
996
  agentChat: {
@@ -1001,7 +1001,7 @@ describe("ToolCallDisplay native renderers", () => {
1001
1001
  },
1002
1002
  },
1003
1003
  },
1004
- }}
1004
+ })}
1005
1005
  initialLocale="en-US"
1006
1006
  initialPreference="en-US"
1007
1007
  persistPreference={false}
@@ -42,24 +42,12 @@ vi.mock("@agent-native/core/client/hooks", () => ({
42
42
 
43
43
  import { ACTION_CHAT_UI_RECORD_CHANGE_RENDERER } from "@agent-native/core/action-ui";
44
44
  import { normalizeActionChangeResult } from "@agent-native/core/action-ui";
45
- import {
46
- AgentNativeI18nProvider as CoreAgentNativeI18nProvider,
47
- type AgentNativeI18nProviderProps,
48
- } from "@agent-native/core/client/i18n";
45
+ import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
49
46
 
50
47
  import { createToolkitI18nCatalog } from "../../../i18n.js";
51
48
  import { RecordChangeWidget } from "./RecordChangeWidget.js";
52
49
 
53
- const toolkitI18nCatalog = createToolkitI18nCatalog({ messages: {} });
54
-
55
- function AgentNativeI18nProvider(props: AgentNativeI18nProviderProps) {
56
- return (
57
- <CoreAgentNativeI18nProvider
58
- {...props}
59
- catalog={props.catalog ?? toolkitI18nCatalog}
60
- />
61
- );
62
- }
50
+ const catalog = createToolkitI18nCatalog({ messages: {} });
63
51
 
64
52
  describe("core.record-change", () => {
65
53
  let container: HTMLDivElement;
@@ -179,7 +167,7 @@ describe("core.record-change", () => {
179
167
  };
180
168
  await act(async () => {
181
169
  root.render(
182
- <AgentNativeI18nProvider persistPreference={false}>
170
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
183
171
  <RecordChangeWidget context={context} />
184
172
  </AgentNativeI18nProvider>,
185
173
  );
@@ -211,7 +199,7 @@ describe("core.record-change", () => {
211
199
 
212
200
  await act(async () => {
213
201
  root.render(
214
- <AgentNativeI18nProvider persistPreference={false}>
202
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
215
203
  <RecordChangeWidget context={context} />
216
204
  </AgentNativeI18nProvider>,
217
205
  );
@@ -248,7 +236,7 @@ describe("core.record-change", () => {
248
236
 
249
237
  await act(async () => {
250
238
  root.render(
251
- <AgentNativeI18nProvider persistPreference={false}>
239
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
252
240
  <RecordChangeWidget context={context} />
253
241
  </AgentNativeI18nProvider>,
254
242
  );
@@ -272,7 +260,7 @@ describe("core.record-change", () => {
272
260
  root = createRoot(container);
273
261
  await act(async () => {
274
262
  root.render(
275
- <AgentNativeI18nProvider persistPreference={false}>
263
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
276
264
  <RecordChangeWidget context={context} />
277
265
  </AgentNativeI18nProvider>,
278
266
  );
@@ -306,10 +294,10 @@ describe("core.record-change", () => {
306
294
  await act(async () => {
307
295
  root.render(
308
296
  <>
309
- <AgentNativeI18nProvider persistPreference={false}>
297
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
310
298
  <RecordChangeWidget context={context} />
311
299
  </AgentNativeI18nProvider>
312
- <AgentNativeI18nProvider persistPreference={false}>
300
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
313
301
  <RecordChangeWidget context={context} />
314
302
  </AgentNativeI18nProvider>
315
303
  </>,
@@ -382,7 +370,7 @@ describe("core.record-change", () => {
382
370
 
383
371
  await act(async () => {
384
372
  root.render(
385
- <AgentNativeI18nProvider persistPreference={false}>
373
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
386
374
  <RecordChangeWidget context={context} />
387
375
  </AgentNativeI18nProvider>,
388
376
  );
@@ -411,7 +399,7 @@ describe("core.record-change", () => {
411
399
  it("does not render unsafe change URLs as links", async () => {
412
400
  await act(async () => {
413
401
  root.render(
414
- <AgentNativeI18nProvider persistPreference={false}>
402
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
415
403
  <RecordChangeWidget
416
404
  context={{
417
405
  toolName: "test-action",
@@ -438,7 +426,7 @@ describe("core.record-change", () => {
438
426
  it("shows saved drafts as awaiting review with a review and edit action", async () => {
439
427
  await act(async () => {
440
428
  root.render(
441
- <AgentNativeI18nProvider persistPreference={false}>
429
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
442
430
  <RecordChangeWidget
443
431
  context={{
444
432
  toolName: "manage-draft",
@@ -473,7 +461,7 @@ describe("core.record-change", () => {
473
461
  it("uses the filter icon for Mail rule changes", async () => {
474
462
  await act(async () => {
475
463
  root.render(
476
- <AgentNativeI18nProvider persistPreference={false}>
464
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
477
465
  <RecordChangeWidget
478
466
  context={{
479
467
  toolName: "manage-email-rules",
@@ -503,7 +491,7 @@ describe("core.record-change", () => {
503
491
  it("localizes sharing roles and visibility in action cards", async () => {
504
492
  await act(async () => {
505
493
  root.render(
506
- <AgentNativeI18nProvider persistPreference={false}>
494
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
507
495
  <RecordChangeWidget
508
496
  context={{
509
497
  toolName: "share-resource",
@@ -537,7 +525,7 @@ describe("core.record-change", () => {
537
525
  ]) {
538
526
  await act(async () => {
539
527
  root.render(
540
- <AgentNativeI18nProvider persistPreference={false}>
528
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
541
529
  <RecordChangeWidget
542
530
  context={{
543
531
  toolName: "set-resource-visibility",
@@ -566,7 +554,7 @@ describe("core.record-change", () => {
566
554
  it("renders an available Calendar time with a use-time action", async () => {
567
555
  await act(async () => {
568
556
  root.render(
569
- <AgentNativeI18nProvider persistPreference={false}>
557
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
570
558
  <RecordChangeWidget
571
559
  context={{
572
560
  toolName: "find-a-time",
@@ -602,7 +590,7 @@ describe("core.record-change", () => {
602
590
  }).format(Date.parse(scheduledAt));
603
591
  await act(async () => {
604
592
  root.render(
605
- <AgentNativeI18nProvider persistPreference={false}>
593
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
606
594
  <RecordChangeWidget
607
595
  context={{
608
596
  toolName: "create-scheduled-send",
@@ -634,7 +622,7 @@ describe("core.record-change", () => {
634
622
  it("localizes booking-link fallback titles and durations", async () => {
635
623
  await act(async () => {
636
624
  root.render(
637
- <AgentNativeI18nProvider persistPreference={false}>
625
+ <AgentNativeI18nProvider catalog={catalog} persistPreference={false}>
638
626
  <RecordChangeWidget
639
627
  context={{
640
628
  toolName: "create-booking-link",
@@ -666,6 +654,7 @@ describe("core.record-change", () => {
666
654
  await act(async () => {
667
655
  root.render(
668
656
  <AgentNativeI18nProvider
657
+ catalog={catalog}
669
658
  initialLocale="es-ES"
670
659
  initialPreference="es-ES"
671
660
  persistPreference={false}
@@ -697,6 +686,7 @@ describe("core.record-change", () => {
697
686
  await act(async () => {
698
687
  root.render(
699
688
  <AgentNativeI18nProvider
689
+ catalog={catalog}
700
690
  initialLocale="fr-FR"
701
691
  initialPreference="fr-FR"
702
692
  persistPreference={false}
@@ -730,6 +720,7 @@ describe("core.record-change", () => {
730
720
  await act(async () => {
731
721
  root.render(
732
722
  <AgentNativeI18nProvider
723
+ catalog={catalog}
733
724
  initialLocale="es-ES"
734
725
  initialPreference="es-ES"
735
726
  persistPreference={false}
@@ -1,133 +1 @@
1
- import type { ChatFirstSurfaceKind } from "@agent-native/core/client/agent-chat";
2
-
3
- import type { ChatFirstCopy } from "./types.js";
4
-
5
- const DEFAULT_COPY: Record<string, string> = {
6
- newChat: "New chat",
7
- search: "Search",
8
- workspaceApps: "Apps",
9
- allApps: "All apps",
10
- integrations: "Integrations",
11
- scheduled: "Scheduled",
12
- createWorkspaceApp: "Create app",
13
- openApp: "Open {name}",
14
- appsLoadError: "Apps could not be loaded",
15
- noWorkspaceApps: "No apps yet",
16
- createApp: "Create app",
17
- retry: "Retry",
18
- dismiss: "Dismiss",
19
- unpinApp: "Unpin this app",
20
- pinApp: "Pin this app",
21
- reloadApp: "Reload app",
22
- removePinned: "Remove from pinned apps",
23
- pinTop: "Pin app to the top",
24
- moveUp: "Move up",
25
- moveDown: "Move down",
26
- removeApp: "Remove app from workspace",
27
- showMore: "Show more",
28
- showLess: "Show less",
29
- appOrderUnavailable: "App order could not be saved on this device.",
30
- openSideSurfaces: "Open side surfaces",
31
- sideSurfaces: "Side surfaces",
32
- resizeSideSurface: "Resize side surface",
33
- closeTab: "Close {name}",
34
- close: "Close",
35
- closeOthers: "Close others",
36
- closeToRight: "Close to the right",
37
- closeAll: "Close all",
38
- deferred: "Deferred",
39
- openActivity: "Open activity",
40
- unavailable: "This surface is not available here.",
41
- browserBack: "Back",
42
- browserForward: "Forward",
43
- browserReload: "Reload page",
44
- browserAddress: "Browser address",
45
- browserOpenExternal: "Open in external browser",
46
- browserClose: "Close browser",
47
- browserPage: "Browser page",
48
- browserInvalidUrl: "Enter a full http(s) URL to navigate.",
49
- browserPreviewStarting: "Starting preview…",
50
- browserPreviewError: "Preview unavailable",
51
- appUnavailable: "This workspace app is no longer available.",
52
- appLoadError: "This app could not be loaded",
53
- appLoading: "Loading app",
54
- agentActivityEyebrow: "Workspace",
55
- agentActivityTitle: "Agent activity",
56
- agentActivityDescription:
57
- "Follow runs and open a second session beside this chat.",
58
- refreshAgentActivity: "Refresh agent activity",
59
- noAgentSessions: "No agent sessions yet",
60
- startAgentSession: "Start an agent run and it will appear here.",
61
- watchSession: "Watch",
62
- copySessionId: "Copy session ID",
63
- copySessionIdFor: "Copy session ID for {name}",
64
- sessionIdCopied: "Session ID copied",
65
- sessionIdShort: "ID",
66
- copied: "Copied",
67
- agentActivityStatusQueued: "Queued",
68
- agentActivityStatusRunning: "Running",
69
- agentActivityStatusPaused: "Paused",
70
- agentActivityStatusNeedsApproval: "Needs approval",
71
- agentActivityStatusCompleted: "Completed",
72
- agentActivityStatusErrored: "Needs attention",
73
- agentActivityStatusRecent: "Recent",
74
- agentActivityStatusUnknown: "Unknown",
75
- watchingSession: "Watching {name}",
76
- session: "session",
77
- stopWatchingSession: "Stop watching session",
78
- stopWatching: "Stop watching",
79
- watchedSession: "Watched session",
80
- agentsTitle: "Subagents",
81
- };
82
-
83
- const SURFACE_COPY: Record<
84
- ChatFirstSurfaceKind,
85
- { label: string; reason: string }
86
- > = {
87
- app: {
88
- label: "App",
89
- reason: "Open a workspace app beside the conversation.",
90
- },
91
- browser: {
92
- label: "Browser",
93
- reason: "Ask the agent to open a web URL.",
94
- },
95
- terminal: {
96
- label: "Terminal",
97
- reason:
98
- "Deferred: an embedded PTY lifecycle is not connected in this release.",
99
- },
100
- files: {
101
- label: "Files",
102
- reason:
103
- "Deferred: a bounded workspace tree is not connected in this release.",
104
- },
105
- diff: {
106
- label: "Diff",
107
- reason: "Deferred: changed-file data is not connected in this release.",
108
- },
109
- "side-chat": {
110
- label: "Side chat",
111
- reason: "Choose Watch and message from any chat row.",
112
- },
113
- agents: {
114
- label: "Agents",
115
- reason: "Review recent runs or watch one beside this conversation.",
116
- },
117
- };
118
-
119
- function interpolate(value: string, values?: Record<string, string>): string {
120
- if (!values) return value;
121
- return value.replace(/\{(\w+)\}/g, (_, key: string) => values[key] ?? "");
122
- }
123
-
124
- export const defaultChatFirstCopy: ChatFirstCopy = (key, values) => {
125
- if (key.startsWith("surface.")) {
126
- const [, kind, field] = key.split(".");
127
- const surface = SURFACE_COPY[kind as ChatFirstSurfaceKind];
128
- if (surface && (field === "label" || field === "reason")) {
129
- return surface[field];
130
- }
131
- }
132
- return interpolate(DEFAULT_COPY[key] ?? key, values);
133
- };
1
+ export { defaultChatFirstCopy } from "../chat-first-copy.js";