@agent-native/toolkit 0.198.3 → 0.198.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/agentkit/react/components.d.ts +8 -3
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +24 -10
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +65 -33
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
- package/dist/app/chat/AgentSidebar.js +2 -0
- package/dist/app/chat/AgentSidebar.js.map +1 -1
- package/dist/app/chat/FileStorageSetupPopover.js +2 -2
- package/dist/app/chat/FileStorageSetupPopover.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +1 -1
- package/dist/app/chat/agentkit-chat/connections.d.ts +1 -4
- package/dist/app/chat/agentkit-chat/connections.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/connections.js +1 -26
- package/dist/app/chat/agentkit-chat/connections.js.map +1 -1
- package/dist/app/chat/agentkit-chat/history.d.ts +4 -1
- package/dist/app/chat/agentkit-chat/history.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/history.js +17 -5
- package/dist/app/chat/agentkit-chat/history.js.map +1 -1
- package/dist/app/chat/chat/history-types.d.ts +1 -1
- package/dist/app/chat/chat/history-types.d.ts.map +1 -1
- package/dist/app/chat/chat-first/copy.d.ts +1 -2
- package/dist/app/chat/chat-first/copy.d.ts.map +1 -1
- package/dist/app/chat/chat-first/copy.js +1 -121
- package/dist/app/chat/chat-first/copy.js.map +1 -1
- package/dist/app/chat/chat-first-copy.d.ts +3 -0
- package/dist/app/chat/chat-first-copy.d.ts.map +1 -0
- package/dist/app/chat/chat-first-copy.js +122 -0
- package/dist/app/chat/chat-first-copy.js.map +1 -0
- package/dist/app/feature-flags/FeatureFlagsPanel.d.ts.map +1 -1
- package/dist/app/feature-flags/FeatureFlagsPanel.js +1 -0
- package/dist/app/feature-flags/FeatureFlagsPanel.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +2 -1
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +2 -1
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +2 -1
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +2 -1
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +2 -1
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +2 -1
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +2 -1
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +2 -1
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +2 -1
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +2 -1
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +2 -1
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +2 -1
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/labs/LabsSettings.d.ts.map +1 -1
- package/dist/app/labs/LabsSettings.js +7 -3
- package/dist/app/labs/LabsSettings.js.map +1 -1
- package/dist/app/org/OrgGeneralSection.d.ts.map +1 -1
- package/dist/app/org/OrgGeneralSection.js +21 -18
- package/dist/app/org/OrgGeneralSection.js.map +1 -1
- package/dist/app/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/app/org/OrgSwitcher.js +3 -2
- package/dist/app/org/OrgSwitcher.js.map +1 -1
- package/dist/app/org/workspace-app-links.d.ts +1 -0
- package/dist/app/org/workspace-app-links.d.ts.map +1 -1
- package/dist/app/org/workspace-app-links.js +3 -0
- package/dist/app/org/workspace-app-links.js.map +1 -1
- package/dist/app/resources/McpAgentKitConnectionRequest.d.ts +7 -2
- package/dist/app/resources/McpAgentKitConnectionRequest.d.ts.map +1 -1
- package/dist/app/resources/McpAgentKitConnectionRequest.js +132 -13
- package/dist/app/resources/McpAgentKitConnectionRequest.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +3 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +2 -2
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +4 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +8 -4
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/icons/ResourceIconPicker.d.ts +6 -1
- package/dist/icons/ResourceIconPicker.d.ts.map +1 -1
- package/dist/icons/ResourceIconPicker.js +45 -6
- package/dist/icons/ResourceIconPicker.js.map +1 -1
- package/package.json +6 -4
- package/src/app/agentkit/react/components.interaction.spec.tsx +93 -0
- package/src/app/agentkit/react/components.spec.tsx +4 -5
- package/src/app/agentkit/react/components.tsx +51 -8
- package/src/app/agentkit/react/composer-context.spec.tsx +7 -0
- package/src/app/agentkit/react/lifecycle.spec.tsx +42 -0
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +151 -11
- package/src/app/chat/AgentKitAssistantChat.tsx +110 -28
- package/src/app/chat/AgentPanel.header.spec.ts +59 -22
- package/src/app/chat/AgentSidebar.tsx +2 -0
- package/src/app/chat/FileStorageSetupPopover.tsx +2 -2
- package/src/app/chat/MultiTabAssistantChat.messageCount.spec.tsx +3 -1
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +8 -4
- package/src/app/chat/MultiTabAssistantChat.tsx +1 -1
- package/src/app/chat/agentkit-chat/action-widget.spec.tsx +5 -17
- package/src/app/chat/agentkit-chat/connections.spec.tsx +137 -0
- package/src/app/chat/agentkit-chat/connections.ts +2 -37
- package/src/app/chat/agentkit-chat/history.tsx +23 -8
- package/src/app/chat/chat/history-types.ts +1 -1
- package/src/app/chat/chat/tool-call-display.spec.tsx +2 -2
- package/src/app/chat/chat/widgets/record-change-widget.spec.tsx +20 -29
- package/src/app/chat/chat-first/copy.ts +1 -133
- package/src/app/chat/chat-first-copy.ts +133 -0
- package/src/app/chat/composer/use-agentkit-capabilities.hardening.spec.tsx +3 -2
- package/src/app/feature-flags/FeatureFlagsPanel.tsx +1 -0
- package/src/app/i18n/catalogs/ar-SA.ts +2 -1
- package/src/app/i18n/catalogs/de-DE.ts +3 -1
- package/src/app/i18n/catalogs/en-US.ts +2 -1
- package/src/app/i18n/catalogs/es-ES.ts +2 -1
- package/src/app/i18n/catalogs/fr-FR.ts +3 -1
- package/src/app/i18n/catalogs/hi-IN.ts +2 -1
- package/src/app/i18n/catalogs/ja-JP.ts +2 -1
- package/src/app/i18n/catalogs/ko-KR.ts +2 -1
- package/src/app/i18n/catalogs/pt-BR.ts +3 -1
- package/src/app/i18n/catalogs/zh-CN.ts +2 -1
- package/src/app/i18n/catalogs/zh-TW.ts +2 -1
- package/src/app/integrations/IntegrationDetailPage.spec.tsx +1 -1
- package/src/app/labs/LabsSettings.tsx +46 -10
- package/src/app/observability/ThumbsFeedback.spec.tsx +15 -0
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +4 -0
- package/src/app/org/OrgGeneralSection.tsx +32 -22
- package/src/app/org/OrgSwitcher.tsx +3 -2
- package/src/app/org/workspace-app-links.spec.ts +4 -0
- package/src/app/org/workspace-app-links.ts +8 -1
- package/src/app/resources/McpAgentKitConnectionRequest.spec.tsx +371 -2
- package/src/app/resources/McpAgentKitConnectionRequest.tsx +171 -11
- package/src/app/settings/SettingsTabsPage.spec.tsx +4 -2
- package/src/app/settings/shell/SettingsShell.spec.tsx +14 -8
- package/src/app/settings/shell/pages/app-group-pages.spec.tsx +35 -5
- package/src/app/settings/shell/pages/resource-pages.spec.tsx +3 -0
- package/src/app/settings/usage/UsagePage.spec.tsx +3 -3
- package/src/app/shared/lazy-chunk-error-boundary.spec.tsx +2 -0
- package/src/app-shell/sidebar-overflow.spec.tsx +4 -1
- package/src/composer/PromptComposer.tsx +7 -0
- package/src/composer/TiptapComposer.spec.ts +26 -4
- package/src/composer/TiptapComposer.tsx +12 -3
- package/src/design-tweaks/visual-style-controls.spec.tsx +38 -0
- package/src/editor/useCollabReconcile.concurrent.spec.ts +2 -1
- package/src/icons/ResourceIconPicker.spec.tsx +270 -0
- package/src/icons/ResourceIconPicker.tsx +72 -4
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuTrigger,
|
|
9
|
+
} from "@agent-native/toolkit/ui/dropdown-menu";
|
|
5
10
|
import React, { act } from "react";
|
|
6
11
|
import { createRoot, type Root } from "react-dom/client";
|
|
7
12
|
import { MemoryRouter, useLocation } from "react-router";
|
|
8
13
|
import { describe, expect, it, vi } from "vitest";
|
|
9
14
|
|
|
10
|
-
import {
|
|
11
|
-
DropdownMenu,
|
|
12
|
-
DropdownMenuContent,
|
|
13
|
-
DropdownMenuTrigger,
|
|
14
|
-
} from "../../ui/dropdown-menu.js";
|
|
15
15
|
import {
|
|
16
16
|
AgentChatSurface,
|
|
17
17
|
AgentPanelFullViewMenuItem,
|
|
@@ -51,6 +51,13 @@ import {
|
|
|
51
51
|
preloadAgentChatSurface,
|
|
52
52
|
} from "./AgentSidebar.js";
|
|
53
53
|
|
|
54
|
+
function readSource(
|
|
55
|
+
path: string,
|
|
56
|
+
_options?: "utf8" | { encoding: "utf8" },
|
|
57
|
+
): string {
|
|
58
|
+
return readFileSync(path, "utf8").replace(/\r\n/g, "\n");
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
describe("AgentPanel compatibility exports", () => {
|
|
55
62
|
it("preserves the legacy sidebar entry point", () => {
|
|
56
63
|
expect(LegacyAgentSidebar).toBe(AgentSidebar);
|
|
@@ -60,7 +67,7 @@ describe("AgentPanel compatibility exports", () => {
|
|
|
60
67
|
});
|
|
61
68
|
|
|
62
69
|
it("uses a stable-ref link in the full-view menu item", () => {
|
|
63
|
-
const source =
|
|
70
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", "utf8").replace(
|
|
64
71
|
/\s+/g,
|
|
65
72
|
" ",
|
|
66
73
|
);
|
|
@@ -150,7 +157,7 @@ describe("AgentPanel fullscreen menu", () => {
|
|
|
150
157
|
|
|
151
158
|
describe("AgentPanel suggestion placement", () => {
|
|
152
159
|
it("forwards explicit placement and defaults to context chips", () => {
|
|
153
|
-
const source =
|
|
160
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
154
161
|
encoding: "utf8",
|
|
155
162
|
});
|
|
156
163
|
|
|
@@ -323,7 +330,7 @@ describe("AgentPanel header tab visibility", () => {
|
|
|
323
330
|
});
|
|
324
331
|
|
|
325
332
|
it("exposes page header composition without moving it into app chrome", () => {
|
|
326
|
-
const source =
|
|
333
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", "utf8");
|
|
327
334
|
|
|
328
335
|
expect(source).toContain('data-agent-page-chat-header=""');
|
|
329
336
|
expect(source).toContain("pageHeaderLeadingSlot");
|
|
@@ -699,7 +706,7 @@ describe("AgentPanel Integrations link", () => {
|
|
|
699
706
|
});
|
|
700
707
|
|
|
701
708
|
it("sits right after Open full view and shares its separator", () => {
|
|
702
|
-
const source =
|
|
709
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
703
710
|
encoding: "utf8",
|
|
704
711
|
});
|
|
705
712
|
const overflowMenu = source.slice(
|
|
@@ -820,6 +827,36 @@ describe("AgentSidebar composer focus", () => {
|
|
|
820
827
|
}
|
|
821
828
|
});
|
|
822
829
|
|
|
830
|
+
it("stops retrying when the document is torn down", () => {
|
|
831
|
+
vi.useFakeTimers();
|
|
832
|
+
const previousRequestAnimationFrame = window.requestAnimationFrame;
|
|
833
|
+
const frames: Array<FrameRequestCallback> = [];
|
|
834
|
+
const panel = document.createElement("div");
|
|
835
|
+
panel.className = "agent-sidebar-panel";
|
|
836
|
+
panel.dataset.agentSidebarState = "open";
|
|
837
|
+
document.body.appendChild(panel);
|
|
838
|
+
|
|
839
|
+
window.requestAnimationFrame = ((callback: FrameRequestCallback) => {
|
|
840
|
+
frames.push(callback);
|
|
841
|
+
return frames.length;
|
|
842
|
+
}) as typeof window.requestAnimationFrame;
|
|
843
|
+
|
|
844
|
+
try {
|
|
845
|
+
focusAgentChat();
|
|
846
|
+
frames[0]!(0);
|
|
847
|
+
vi.stubGlobal("document", undefined);
|
|
848
|
+
|
|
849
|
+
expect(() => vi.advanceTimersByTime(50)).not.toThrow();
|
|
850
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
851
|
+
} finally {
|
|
852
|
+
vi.unstubAllGlobals();
|
|
853
|
+
window.requestAnimationFrame = previousRequestAnimationFrame;
|
|
854
|
+
panel.remove();
|
|
855
|
+
vi.clearAllTimers();
|
|
856
|
+
vi.useRealTimers();
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
|
|
823
860
|
it("focuses a frame-owned composer", () => {
|
|
824
861
|
const previousRequestAnimationFrame = window.requestAnimationFrame;
|
|
825
862
|
const frames: Array<FrameRequestCallback> = [];
|
|
@@ -914,10 +951,10 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
914
951
|
});
|
|
915
952
|
|
|
916
953
|
it("keeps width and full-view actions out of the icon row", () => {
|
|
917
|
-
const source =
|
|
954
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
918
955
|
encoding: "utf8",
|
|
919
956
|
});
|
|
920
|
-
const sidebarSource =
|
|
957
|
+
const sidebarSource = readSource("src/app/chat/AgentSidebar.tsx", {
|
|
921
958
|
encoding: "utf8",
|
|
922
959
|
});
|
|
923
960
|
const headerActions = source.slice(
|
|
@@ -957,7 +994,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
957
994
|
});
|
|
958
995
|
|
|
959
996
|
it("keeps the overflow menu scrollable within the viewport", () => {
|
|
960
|
-
const source =
|
|
997
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
961
998
|
encoding: "utf8",
|
|
962
999
|
});
|
|
963
1000
|
const overflowMenu = source.slice(
|
|
@@ -972,7 +1009,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
972
1009
|
});
|
|
973
1010
|
|
|
974
1011
|
it("offers sharing from the sidebar overflow for an active chat", () => {
|
|
975
|
-
const source =
|
|
1012
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
976
1013
|
encoding: "utf8",
|
|
977
1014
|
});
|
|
978
1015
|
const overflowMenu = source.slice(
|
|
@@ -992,7 +1029,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
992
1029
|
});
|
|
993
1030
|
|
|
994
1031
|
it("keeps chat headers persistent while switching app surfaces", () => {
|
|
995
|
-
const source =
|
|
1032
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
996
1033
|
encoding: "utf8",
|
|
997
1034
|
});
|
|
998
1035
|
|
|
@@ -1002,10 +1039,10 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
1002
1039
|
});
|
|
1003
1040
|
|
|
1004
1041
|
it("supports a persistent two-state sidebar toggle", () => {
|
|
1005
|
-
const source =
|
|
1042
|
+
const source = readSource("src/app/chat/AgentSidebar.tsx", {
|
|
1006
1043
|
encoding: "utf8",
|
|
1007
1044
|
});
|
|
1008
|
-
const panelSource =
|
|
1045
|
+
const panelSource = readSource("src/app/chat/AgentPanel.tsx", {
|
|
1009
1046
|
encoding: "utf8",
|
|
1010
1047
|
});
|
|
1011
1048
|
|
|
@@ -1021,7 +1058,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
1021
1058
|
});
|
|
1022
1059
|
|
|
1023
1060
|
it("keeps host CLI tabs mounted while chat is active", () => {
|
|
1024
|
-
const source =
|
|
1061
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
1025
1062
|
encoding: "utf8",
|
|
1026
1063
|
});
|
|
1027
1064
|
|
|
@@ -1035,7 +1072,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
1035
1072
|
});
|
|
1036
1073
|
|
|
1037
1074
|
it("only shows tabs for the active desktop surface", () => {
|
|
1038
|
-
const source =
|
|
1075
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
1039
1076
|
encoding: "utf8",
|
|
1040
1077
|
});
|
|
1041
1078
|
|
|
@@ -1046,7 +1083,7 @@ describe("AgentPanel header overflow actions", () => {
|
|
|
1046
1083
|
|
|
1047
1084
|
describe("AgentSidebar wide drawer layout", () => {
|
|
1048
1085
|
it("can disable the panel without unmounting the app surface", () => {
|
|
1049
|
-
const source =
|
|
1086
|
+
const source = readSource("src/app/chat/AgentSidebar.tsx", {
|
|
1050
1087
|
encoding: "utf8",
|
|
1051
1088
|
});
|
|
1052
1089
|
|
|
@@ -1058,7 +1095,7 @@ describe("AgentSidebar wide drawer layout", () => {
|
|
|
1058
1095
|
});
|
|
1059
1096
|
|
|
1060
1097
|
it("does not reserve the drawer placeholder after the panel closes", () => {
|
|
1061
|
-
const source =
|
|
1098
|
+
const source = readSource("src/app/chat/AgentSidebar.tsx", {
|
|
1062
1099
|
encoding: "utf8",
|
|
1063
1100
|
});
|
|
1064
1101
|
const placeholderStart = source.indexOf("const drawerPlaceholder");
|
|
@@ -1083,7 +1120,7 @@ describe("AgentChatSurface chrome defaults", () => {
|
|
|
1083
1120
|
});
|
|
1084
1121
|
|
|
1085
1122
|
it("keeps settings out of every chat surface", () => {
|
|
1086
|
-
const source =
|
|
1123
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
1087
1124
|
encoding: "utf8",
|
|
1088
1125
|
});
|
|
1089
1126
|
|
|
@@ -1117,7 +1154,7 @@ describe("AgentChatSurface chrome defaults", () => {
|
|
|
1117
1154
|
|
|
1118
1155
|
describe("AgentPanel stale lazy chunk recovery", () => {
|
|
1119
1156
|
it("uses the guarded reload path before the panel reset fallback", () => {
|
|
1120
|
-
const source =
|
|
1157
|
+
const source = readSource("src/app/chat/AgentPanel.tsx", {
|
|
1121
1158
|
encoding: "utf8",
|
|
1122
1159
|
});
|
|
1123
1160
|
const componentDidCatch = source.slice(
|
|
@@ -1331,6 +1331,8 @@ export function focusAgentChat() {
|
|
|
1331
1331
|
|
|
1332
1332
|
function focusAgentChatComposer() {
|
|
1333
1333
|
const focusComposer = (attempt = 0) => {
|
|
1334
|
+
if (typeof window === "undefined" || typeof document === "undefined")
|
|
1335
|
+
return;
|
|
1334
1336
|
const panel = document.querySelector(
|
|
1335
1337
|
".agent-sidebar-panel[data-agent-sidebar-state='open'], " +
|
|
1336
1338
|
".agent-frame-sidebar[data-agent-frame-sidebar-state='open']",
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { IconCloudUpload } from "@tabler/icons-react";
|
|
9
9
|
import { useRef, type RefObject } from "react";
|
|
10
10
|
|
|
11
|
-
import { BuilderConnectPopover } from "../settings/
|
|
12
|
-
import { BuilderConnectCard } from "../setup-connections/
|
|
11
|
+
import { DeferredBuilderConnectPopover as BuilderConnectPopover } from "../settings/deferred-builder-connect-popover.js";
|
|
12
|
+
import { BuilderConnectCard } from "../setup-connections/BuilderConnectCard.js";
|
|
13
13
|
|
|
14
14
|
type FileStorageSetupPopoverCommonProps = {
|
|
15
15
|
open: boolean;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import rawMultiTabSource from "./MultiTabAssistantChat.tsx?raw";
|
|
4
|
+
|
|
5
|
+
const MultiTabSource = rawMultiTabSource.replace(/\r\n/g, "\n");
|
|
4
6
|
|
|
5
7
|
describe("MultiTabAssistantChat message count", () => {
|
|
6
8
|
it("forwards the host callback instead of only counting tabs", () => {
|
|
@@ -210,9 +210,11 @@ const modelCatalogMocks = vi.hoisted(() => ({
|
|
|
210
210
|
load: null as null | (() => Promise<unknown>),
|
|
211
211
|
}));
|
|
212
212
|
|
|
213
|
-
vi.mock("@agent-native/core/client/
|
|
213
|
+
vi.mock("@agent-native/core/client/use-action", async (importOriginal) => {
|
|
214
214
|
const actual =
|
|
215
|
-
await importOriginal<
|
|
215
|
+
await importOriginal<
|
|
216
|
+
typeof import("@agent-native/core/client/use-action")
|
|
217
|
+
>();
|
|
216
218
|
return { ...actual, ...actionMocks };
|
|
217
219
|
});
|
|
218
220
|
|
|
@@ -433,6 +435,8 @@ describe("MultiTabAssistantChat postMessage bridge", () => {
|
|
|
433
435
|
beforeEach(async () => {
|
|
434
436
|
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
435
437
|
resetThreadMocks();
|
|
438
|
+
actionMocks.callAction.mockReset();
|
|
439
|
+
actionMocks.callAction.mockResolvedValue(null as never);
|
|
436
440
|
ensureLocalStorage();
|
|
437
441
|
vi.stubGlobal(
|
|
438
442
|
"fetch",
|
|
@@ -3345,7 +3349,7 @@ describe("MultiTabAssistantChat page overlay", () => {
|
|
|
3345
3349
|
).not.toBeNull();
|
|
3346
3350
|
});
|
|
3347
3351
|
|
|
3348
|
-
it("reserves
|
|
3352
|
+
it("reserves one page-header height when its actions are temporarily empty", async () => {
|
|
3349
3353
|
await act(async () => {
|
|
3350
3354
|
root.render(
|
|
3351
3355
|
<MultiTabAssistantChat
|
|
@@ -3359,7 +3363,7 @@ describe("MultiTabAssistantChat page overlay", () => {
|
|
|
3359
3363
|
"[data-agent-page-chat-topbar]",
|
|
3360
3364
|
);
|
|
3361
3365
|
expect(topbar).not.toBeNull();
|
|
3362
|
-
expect(topbar?.className).toContain("pt-
|
|
3366
|
+
expect(topbar?.className).toContain("pt-12");
|
|
3363
3367
|
});
|
|
3364
3368
|
});
|
|
3365
3369
|
|
|
@@ -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-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
718
|
-
|
|
719
|
-
|
|
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}
|