@agent-native/toolkit 0.225.1 → 0.226.0-nightly-20261106182619
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/agent-native.eject.json +1 -0
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +124 -9
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +1 -1
- package/dist/app/agentkit/react/core-file-storage.d.ts +21 -0
- package/dist/app/agentkit/react/core-file-storage.d.ts.map +1 -0
- package/dist/app/agentkit/react/core-file-storage.js +3 -0
- package/dist/app/agentkit/react/core-file-storage.js.map +1 -0
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +89 -10
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +39 -58
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +3 -1
- package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/root.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/root.js +66 -2
- package/dist/app/chat/agentkit-chat/root.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +1 -0
- package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
- package/dist/app/chat/chat/surface-types.js.map +1 -1
- package/dist/app/chat/composer/runtime-adapters.d.ts.map +1 -1
- package/dist/app/chat/composer/runtime-adapters.js +2 -0
- package/dist/app/chat/composer/runtime-adapters.js.map +1 -1
- package/dist/app/chat/composer/use-agentkit-capabilities.d.ts +3 -1
- package/dist/app/chat/composer/use-agentkit-capabilities.d.ts.map +1 -1
- package/dist/app/chat/composer/use-agentkit-capabilities.js +11 -11
- package/dist/app/chat/composer/use-agentkit-capabilities.js.map +1 -1
- package/dist/app/chat/composer/use-workspace-composer-menu.d.ts +3 -0
- package/dist/app/chat/composer/use-workspace-composer-menu.d.ts.map +1 -0
- package/dist/app/chat/composer/use-workspace-composer-menu.js +80 -0
- package/dist/app/chat/composer/use-workspace-composer-menu.js.map +1 -0
- package/dist/app/chat/index.d.ts +1 -0
- package/dist/app/chat/index.d.ts.map +1 -1
- package/dist/app/chat/index.js +1 -0
- package/dist/app/chat/index.js.map +1 -1
- package/dist/app/chat/prepare-prompt-composer-agent-handoff.d.ts +5 -0
- package/dist/app/chat/prepare-prompt-composer-agent-handoff.d.ts.map +1 -0
- package/dist/app/chat/prepare-prompt-composer-agent-handoff.js +108 -0
- package/dist/app/chat/prepare-prompt-composer-agent-handoff.js.map +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +6 -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 +6 -1
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +6 -1
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +6 -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 +6 -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 +6 -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 +6 -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 +6 -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 +6 -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 +6 -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 +6 -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 +6 -1
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/resources/McpIntegrationDialog.d.ts +3 -1
- package/dist/app/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/app/resources/McpIntegrationDialog.js +2 -2
- package/dist/app/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +119 -40
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/dist/composer/ComposerContextMenu.d.ts +36 -2
- package/dist/composer/ComposerContextMenu.d.ts.map +1 -1
- package/dist/composer/ComposerContextMenu.js +108 -40
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.d.ts.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.js +63 -26
- package/dist/composer/ComposerContextPickerDialog.js.map +1 -1
- package/dist/composer/ComposerPlusMenu.d.ts +5 -3
- package/dist/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/composer/ComposerPlusMenu.js +166 -121
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/MentionItemMedia.d.ts.map +1 -1
- package/dist/composer/MentionItemMedia.js +3 -1
- package/dist/composer/MentionItemMedia.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +1 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +1 -0
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +117 -50
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/index.d.ts +1 -0
- package/dist/composer/index.d.ts.map +1 -1
- package/dist/composer/runtime-adapters.d.ts +15 -0
- package/dist/composer/runtime-adapters.d.ts.map +1 -1
- package/dist/composer/runtime-adapters.js.map +1 -1
- package/dist/composer/use-composer-panel-placement.d.ts.map +1 -1
- package/dist/composer/use-composer-panel-placement.js +2 -4
- package/dist/composer/use-composer-panel-placement.js.map +1 -1
- package/dist/composer/use-mention-search.d.ts +7 -0
- package/dist/composer/use-mention-search.d.ts.map +1 -1
- package/dist/composer/use-mention-search.js +86 -19
- package/dist/composer/use-mention-search.js.map +1 -1
- package/dist/composer/useComposerContextPicker.d.ts +5 -1
- package/dist/composer/useComposerContextPicker.d.ts.map +1 -1
- package/dist/composer/useComposerContextPicker.js +18 -4
- package/dist/composer/useComposerContextPicker.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/components.tsx +158 -11
- package/src/app/agentkit/react/composer-context.spec.tsx +180 -0
- package/src/app/agentkit/react/core-file-storage.tsx +14 -0
- package/src/app/auth/AuthPage.interaction.spec.tsx +143 -0
- package/src/app/auth/AuthPage.tsx +159 -13
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +65 -3
- package/src/app/chat/AgentKitAssistantChat.tsx +57 -65
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +21 -0
- package/src/app/chat/MultiTabAssistantChat.tsx +4 -0
- package/src/app/chat/agentkit-chat/root.tsx +91 -8
- package/src/app/chat/chat/surface-types.ts +1 -0
- package/src/app/chat/composer/runtime-adapters.tsx +2 -0
- package/src/app/chat/composer/use-agentkit-capabilities.hardening.spec.tsx +26 -1
- package/src/app/chat/composer/use-agentkit-capabilities.ts +11 -11
- package/src/app/chat/composer/use-agentkit-integration-menu.spec.tsx +2 -4
- package/src/app/chat/composer/use-workspace-composer-menu.spec.tsx +174 -0
- package/src/app/chat/composer/use-workspace-composer-menu.tsx +122 -0
- package/src/app/chat/index.ts +1 -0
- package/src/app/chat/prepare-prompt-composer-agent-handoff.spec.ts +162 -0
- package/src/app/chat/prepare-prompt-composer-agent-handoff.ts +134 -0
- package/src/app/i18n/catalogs/ar-SA.ts +6 -1
- package/src/app/i18n/catalogs/de-DE.ts +6 -1
- package/src/app/i18n/catalogs/en-US.ts +6 -1
- package/src/app/i18n/catalogs/es-ES.ts +6 -1
- package/src/app/i18n/catalogs/fr-FR.ts +6 -1
- package/src/app/i18n/catalogs/hi-IN.ts +6 -1
- package/src/app/i18n/catalogs/ja-JP.ts +6 -1
- package/src/app/i18n/catalogs/ko-KR.ts +6 -1
- package/src/app/i18n/catalogs/pt-BR.ts +6 -1
- package/src/app/i18n/catalogs/zh-CN.ts +6 -1
- package/src/app/i18n/catalogs/zh-TW.ts +6 -1
- package/src/app/resources/McpIntegrationDialog.tsx +5 -0
- package/src/app/settings/useBuilderStatus.spec.tsx +229 -13
- package/src/app/settings/useBuilderStatus.ts +145 -47
- package/src/composer/ComposerContextMenu.spec.tsx +95 -32
- package/src/composer/ComposerContextMenu.tsx +284 -73
- package/src/composer/ComposerContextPicker.spec.tsx +13 -14
- package/src/composer/ComposerContextPickerDialog.spec.tsx +40 -3
- package/src/composer/ComposerContextPickerDialog.tsx +158 -24
- package/src/composer/ComposerPlusMenu.parity.spec.tsx +442 -62
- package/src/composer/ComposerPlusMenu.tsx +322 -237
- package/src/composer/MentionItemMedia.tsx +3 -0
- package/src/composer/PromptComposer.context.spec.tsx +253 -82
- package/src/composer/PromptComposer.tsx +2 -0
- package/src/composer/TiptapComposer.spec.ts +6 -8
- package/src/composer/TiptapComposer.tsx +148 -55
- package/src/composer/index.ts +5 -0
- package/src/composer/runtime-adapters.tsx +18 -0
- package/src/composer/use-composer-panel-placement.ts +2 -4
- package/src/composer/use-mention-search.spec.tsx +99 -1
- package/src/composer/use-mention-search.ts +101 -24
- package/src/composer/useComposerContextPicker.ts +25 -5
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
IconMail,
|
|
8
8
|
IconMessageChatbot,
|
|
9
9
|
IconPresentation,
|
|
10
|
+
IconPlugConnected,
|
|
10
11
|
IconStack2,
|
|
11
12
|
IconUser,
|
|
12
13
|
} from "@tabler/icons-react";
|
|
@@ -41,6 +42,8 @@ function LegacyMentionIcon({
|
|
|
41
42
|
);
|
|
42
43
|
}
|
|
43
44
|
switch (icon) {
|
|
45
|
+
case "integration":
|
|
46
|
+
return <IconPlugConnected {...iconProps} />;
|
|
44
47
|
case "folder":
|
|
45
48
|
return <IconFolder {...iconProps} />;
|
|
46
49
|
case "document":
|
|
@@ -105,7 +105,7 @@ describe("controlled composer context", () => {
|
|
|
105
105
|
);
|
|
106
106
|
const menu = document.querySelector('[role="menu"]')!;
|
|
107
107
|
expect(menu.querySelector('[role="searchbox"]')).toBeNull();
|
|
108
|
-
expect(menu.textContent).toContain("
|
|
108
|
+
expect(menu.textContent).toContain("Files and images");
|
|
109
109
|
expect(menu.textContent).toContain("Add context");
|
|
110
110
|
await act(async () =>
|
|
111
111
|
document.dispatchEvent(
|
|
@@ -522,22 +522,9 @@ describe("controlled composer context", () => {
|
|
|
522
522
|
);
|
|
523
523
|
|
|
524
524
|
const plusMenu = document.querySelector<HTMLElement>('[role="menu"]');
|
|
525
|
-
expect(plusMenu?.textContent).toContain("
|
|
525
|
+
expect(plusMenu?.textContent).toContain("Files and images");
|
|
526
526
|
expect(plusMenu?.textContent).toContain("Add context");
|
|
527
|
-
expect(plusMenu?.textContent).
|
|
528
|
-
const addContext = Array.from(
|
|
529
|
-
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
530
|
-
).find((item) => item.textContent === "Add context")!;
|
|
531
|
-
await act(async () => {
|
|
532
|
-
addContext.focus();
|
|
533
|
-
addContext.dispatchEvent(
|
|
534
|
-
new KeyboardEvent("keydown", {
|
|
535
|
-
key: "ArrowRight",
|
|
536
|
-
bubbles: true,
|
|
537
|
-
cancelable: true,
|
|
538
|
-
}),
|
|
539
|
-
);
|
|
540
|
-
});
|
|
527
|
+
expect(plusMenu?.textContent).toContain("Choose source");
|
|
541
528
|
const sourceAction = Array.from(
|
|
542
529
|
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
543
530
|
).find((item) => item.textContent === "Choose source")!;
|
|
@@ -575,19 +562,6 @@ describe("controlled composer context", () => {
|
|
|
575
562
|
}),
|
|
576
563
|
);
|
|
577
564
|
});
|
|
578
|
-
const addContext = Array.from(
|
|
579
|
-
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
580
|
-
).find((item) => item.textContent === "Add context")!;
|
|
581
|
-
await act(async () => {
|
|
582
|
-
addContext.focus();
|
|
583
|
-
addContext.dispatchEvent(
|
|
584
|
-
new KeyboardEvent("keydown", {
|
|
585
|
-
key: "ArrowRight",
|
|
586
|
-
bubbles: true,
|
|
587
|
-
cancelable: true,
|
|
588
|
-
}),
|
|
589
|
-
);
|
|
590
|
-
});
|
|
591
565
|
const integrations = Array.from(
|
|
592
566
|
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
593
567
|
).find((item) => item.textContent === "Integrations")!;
|
|
@@ -645,41 +619,17 @@ describe("controlled composer context", () => {
|
|
|
645
619
|
}),
|
|
646
620
|
);
|
|
647
621
|
});
|
|
648
|
-
const
|
|
649
|
-
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
650
|
-
).find((item) => item.textContent === "Add context");
|
|
651
|
-
if (addContext) {
|
|
652
|
-
await act(async () => {
|
|
653
|
-
addContext.focus();
|
|
654
|
-
addContext.dispatchEvent(
|
|
655
|
-
new KeyboardEvent("keydown", {
|
|
656
|
-
key: "ArrowRight",
|
|
657
|
-
bubbles: true,
|
|
658
|
-
cancelable: true,
|
|
659
|
-
}),
|
|
660
|
-
);
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
const section = Array.from(
|
|
664
|
-
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
665
|
-
).find((item) => item.textContent === "Connected Agents");
|
|
666
|
-
if (section) {
|
|
667
|
-
await act(async () => {
|
|
668
|
-
section.focus();
|
|
669
|
-
section.dispatchEvent(
|
|
670
|
-
new KeyboardEvent("keydown", {
|
|
671
|
-
key: "ArrowRight",
|
|
672
|
-
bubbles: true,
|
|
673
|
-
cancelable: true,
|
|
674
|
-
}),
|
|
675
|
-
);
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
const row = Array.from(
|
|
622
|
+
const search = Array.from(
|
|
679
623
|
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
680
|
-
).find(
|
|
681
|
-
|
|
682
|
-
)
|
|
624
|
+
).find((item) => item.textContent === "Search workspace…")!;
|
|
625
|
+
expect(search).toBeDefined();
|
|
626
|
+
await act(async () => {
|
|
627
|
+
search.click();
|
|
628
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
629
|
+
});
|
|
630
|
+
const row = Array.from(
|
|
631
|
+
document.querySelectorAll<HTMLElement>('[role="option"]'),
|
|
632
|
+
).find((item) => item.textContent === "Slides")!;
|
|
683
633
|
expect(row).toBeDefined();
|
|
684
634
|
await act(async () => row.click());
|
|
685
635
|
await act(async () => {
|
|
@@ -829,7 +779,7 @@ describe("controlled composer context", () => {
|
|
|
829
779
|
}
|
|
830
780
|
bounds = { ...bounds, y: window.innerHeight + 500 };
|
|
831
781
|
await act(async () => observation.resize());
|
|
832
|
-
if (plusMenu) expect(panel.style.maxHeight).toBe("
|
|
782
|
+
if (plusMenu) expect(panel.style.maxHeight).toBe("480px");
|
|
833
783
|
bounds = { ...bounds, x: 120, y: 160 };
|
|
834
784
|
await act(async () => window.dispatchEvent(new Event("scroll")));
|
|
835
785
|
if (!plusMenu) {
|
|
@@ -840,7 +790,7 @@ describe("controlled composer context", () => {
|
|
|
840
790
|
"--radix-popover-content-available-height",
|
|
841
791
|
);
|
|
842
792
|
} else {
|
|
843
|
-
expect(panel.style.maxHeight).toBe("
|
|
793
|
+
expect(panel.style.maxHeight).toBe("446px");
|
|
844
794
|
}
|
|
845
795
|
await act(async () =>
|
|
846
796
|
editor.dispatchEvent(
|
|
@@ -858,7 +808,7 @@ describe("controlled composer context", () => {
|
|
|
858
808
|
vi.restoreAllMocks();
|
|
859
809
|
},
|
|
860
810
|
);
|
|
861
|
-
it("requests storage setup only after choosing
|
|
811
|
+
it("requests storage setup only after choosing Files and images", async () => {
|
|
862
812
|
const onAttachmentRequest = vi.fn();
|
|
863
813
|
await mount({
|
|
864
814
|
attachmentsEnabled: false,
|
|
@@ -882,7 +832,7 @@ describe("controlled composer context", () => {
|
|
|
882
832
|
});
|
|
883
833
|
const uploadFile = Array.from(
|
|
884
834
|
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
885
|
-
).find((button) => button.textContent?.includes("
|
|
835
|
+
).find((button) => button.textContent?.includes("Files and images"));
|
|
886
836
|
expect(uploadFile).toBeDefined();
|
|
887
837
|
await act(async () => uploadFile!.click());
|
|
888
838
|
await act(async () => new Promise((resolve) => setTimeout(resolve, 0)));
|
|
@@ -909,11 +859,243 @@ describe("controlled composer context", () => {
|
|
|
909
859
|
);
|
|
910
860
|
const uploadFile = document.querySelector<HTMLElement>('[role="menuitem"]');
|
|
911
861
|
expect(uploadFile).toBeDefined();
|
|
912
|
-
expect(uploadFile?.textContent).toContain("
|
|
862
|
+
expect(uploadFile?.textContent).toContain("Files and images");
|
|
913
863
|
await act(async () => uploadFile!.click());
|
|
914
864
|
await act(async () => new Promise((resolve) => setTimeout(resolve, 0)));
|
|
915
865
|
expect(onAttachmentRequest).toHaveBeenCalledOnce();
|
|
916
866
|
});
|
|
867
|
+
it("shows localized source errors in the reference picker", async () => {
|
|
868
|
+
vi.stubGlobal(
|
|
869
|
+
"fetch",
|
|
870
|
+
vi.fn(
|
|
871
|
+
async () =>
|
|
872
|
+
new Response(
|
|
873
|
+
JSON.stringify({
|
|
874
|
+
error: {
|
|
875
|
+
code: "mention_source_unavailable",
|
|
876
|
+
message: "Impossible de charger les références.",
|
|
877
|
+
source: "dashboards",
|
|
878
|
+
},
|
|
879
|
+
}),
|
|
880
|
+
{ status: 503 },
|
|
881
|
+
),
|
|
882
|
+
),
|
|
883
|
+
);
|
|
884
|
+
await mount({
|
|
885
|
+
contextMenuItems: [
|
|
886
|
+
{
|
|
887
|
+
id: "dashboards",
|
|
888
|
+
label: "Reference a dashboard…",
|
|
889
|
+
section: "context",
|
|
890
|
+
referenceType: "dashboard",
|
|
891
|
+
referencePicker: { source: "dashboards", referenceType: "dashboard" },
|
|
892
|
+
},
|
|
893
|
+
],
|
|
894
|
+
});
|
|
895
|
+
await act(async () => {
|
|
896
|
+
container
|
|
897
|
+
.querySelector<HTMLElement>('button[aria-label="Add context"]')!
|
|
898
|
+
.dispatchEvent(
|
|
899
|
+
new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
|
|
900
|
+
);
|
|
901
|
+
});
|
|
902
|
+
await act(async () => {
|
|
903
|
+
Array.from(document.querySelectorAll<HTMLElement>('[role="menuitem"]'))
|
|
904
|
+
.find((item) => item.textContent === "Reference a dashboard…")!
|
|
905
|
+
.click();
|
|
906
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
907
|
+
});
|
|
908
|
+
expect(document.body.textContent).toContain(
|
|
909
|
+
"Impossible de charger les références.",
|
|
910
|
+
);
|
|
911
|
+
});
|
|
912
|
+
it("opens scoped native references in one dialog and excludes them from workspace search", async () => {
|
|
913
|
+
const fetch = vi.fn(
|
|
914
|
+
async () =>
|
|
915
|
+
new Response(
|
|
916
|
+
JSON.stringify({
|
|
917
|
+
items: [
|
|
918
|
+
{
|
|
919
|
+
id: "dashboard:one",
|
|
920
|
+
label: "Revenue overview",
|
|
921
|
+
source: "dashboards",
|
|
922
|
+
refType: "dashboard",
|
|
923
|
+
refId: "one",
|
|
924
|
+
section: "Dashboards",
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
id: "file:brief",
|
|
928
|
+
label: "Launch brief",
|
|
929
|
+
source: "resource:personal",
|
|
930
|
+
refType: "file",
|
|
931
|
+
refPath: "brief.md",
|
|
932
|
+
section: "Files",
|
|
933
|
+
},
|
|
934
|
+
],
|
|
935
|
+
}),
|
|
936
|
+
),
|
|
937
|
+
);
|
|
938
|
+
vi.stubGlobal("fetch", fetch);
|
|
939
|
+
const { composerRef, onSubmit } = await mount({
|
|
940
|
+
contextMenuItems: [
|
|
941
|
+
{
|
|
942
|
+
id: "dashboards",
|
|
943
|
+
label: "Reference a dashboard…",
|
|
944
|
+
section: "context",
|
|
945
|
+
referenceType: "dashboard",
|
|
946
|
+
referencePicker: { source: "dashboards", referenceType: "dashboard" },
|
|
947
|
+
},
|
|
948
|
+
],
|
|
949
|
+
});
|
|
950
|
+
const open = async () => {
|
|
951
|
+
await act(async () => {
|
|
952
|
+
container
|
|
953
|
+
.querySelector<HTMLElement>('button[aria-label="Add context"]')!
|
|
954
|
+
.dispatchEvent(
|
|
955
|
+
new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
|
|
956
|
+
);
|
|
957
|
+
});
|
|
958
|
+
};
|
|
959
|
+
await open();
|
|
960
|
+
expect(fetch).not.toHaveBeenCalled();
|
|
961
|
+
expect(
|
|
962
|
+
document.querySelector('[role="menu"] .skeleton-shimmer'),
|
|
963
|
+
).toBeNull();
|
|
964
|
+
const choose = async (name: string) => {
|
|
965
|
+
await act(async () => {
|
|
966
|
+
Array.from(document.querySelectorAll<HTMLElement>('[role="menuitem"]'))
|
|
967
|
+
.find((item) => item.textContent === name)!
|
|
968
|
+
.click();
|
|
969
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
970
|
+
});
|
|
971
|
+
};
|
|
972
|
+
await choose("Reference a dashboard…");
|
|
973
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
974
|
+
expect.stringContaining("source=dashboards"),
|
|
975
|
+
{ signal: expect.any(AbortSignal) },
|
|
976
|
+
);
|
|
977
|
+
expect(
|
|
978
|
+
document
|
|
979
|
+
.querySelector('[role="dialog"]')
|
|
980
|
+
?.getAttribute("aria-labelledby"),
|
|
981
|
+
).toBeTruthy();
|
|
982
|
+
expect(document.activeElement?.getAttribute("role")).toBe("combobox");
|
|
983
|
+
expect(
|
|
984
|
+
Array.from(document.querySelectorAll('[role="option"]')).map(
|
|
985
|
+
(item) => item.textContent,
|
|
986
|
+
),
|
|
987
|
+
).toEqual(["Revenue overview"]);
|
|
988
|
+
await act(async () =>
|
|
989
|
+
document.querySelector<HTMLElement>('[role="option"]')!.click(),
|
|
990
|
+
);
|
|
991
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
992
|
+
expect(document.activeElement).toBe(
|
|
993
|
+
container.querySelector(".ProseMirror"),
|
|
994
|
+
);
|
|
995
|
+
await open();
|
|
996
|
+
await choose("Search workspace…");
|
|
997
|
+
expect(
|
|
998
|
+
Array.from(document.querySelectorAll('[role="option"]')).map(
|
|
999
|
+
(item) => item.textContent,
|
|
1000
|
+
),
|
|
1001
|
+
).toEqual(["Launch brief"]);
|
|
1002
|
+
await act(async () =>
|
|
1003
|
+
document.dispatchEvent(
|
|
1004
|
+
new KeyboardEvent("keydown", {
|
|
1005
|
+
key: "Escape",
|
|
1006
|
+
bubbles: true,
|
|
1007
|
+
cancelable: true,
|
|
1008
|
+
}),
|
|
1009
|
+
),
|
|
1010
|
+
);
|
|
1011
|
+
await act(async () => composerRef.current!.submit());
|
|
1012
|
+
expect(onSubmit.mock.calls[0][2]).toEqual(
|
|
1013
|
+
expect.arrayContaining([
|
|
1014
|
+
expect.objectContaining({ refType: "dashboard", refId: "one" }),
|
|
1015
|
+
]),
|
|
1016
|
+
);
|
|
1017
|
+
expect(onSubmit.mock.calls[0][3].references).toEqual(
|
|
1018
|
+
onSubmit.mock.calls[0][2],
|
|
1019
|
+
);
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
it("aborts a workspace picker on identity change before stale results can be selected", async () => {
|
|
1023
|
+
let scopeKey = "org:one";
|
|
1024
|
+
let finish: (response: Response) => void = () => {
|
|
1025
|
+
throw new Error("No search started");
|
|
1026
|
+
};
|
|
1027
|
+
const fetch = vi.fn(
|
|
1028
|
+
() =>
|
|
1029
|
+
new Promise<Response>((resolve) => {
|
|
1030
|
+
finish = resolve;
|
|
1031
|
+
}),
|
|
1032
|
+
);
|
|
1033
|
+
vi.stubGlobal("fetch", fetch);
|
|
1034
|
+
const onReferencesChange = vi.fn();
|
|
1035
|
+
const render = async () => {
|
|
1036
|
+
await act(async () =>
|
|
1037
|
+
root.render(
|
|
1038
|
+
<ComposerRuntimeAdaptersProvider
|
|
1039
|
+
adapters={{
|
|
1040
|
+
resources: { useWorkspaceMenu: () => ({ scopeKey, items: [] }) },
|
|
1041
|
+
}}
|
|
1042
|
+
>
|
|
1043
|
+
<PromptComposer
|
|
1044
|
+
onSubmit={vi.fn()}
|
|
1045
|
+
onReferencesChange={onReferencesChange}
|
|
1046
|
+
showModelSelector={false}
|
|
1047
|
+
modelStatusChecksEnabled={false}
|
|
1048
|
+
includeDefaultSlashSkills={false}
|
|
1049
|
+
voiceEnabled={false}
|
|
1050
|
+
/>
|
|
1051
|
+
</ComposerRuntimeAdaptersProvider>,
|
|
1052
|
+
),
|
|
1053
|
+
);
|
|
1054
|
+
};
|
|
1055
|
+
await render();
|
|
1056
|
+
onReferencesChange.mockClear();
|
|
1057
|
+
const open = async () => {
|
|
1058
|
+
await act(async () => {
|
|
1059
|
+
const trigger = container.querySelector<HTMLElement>(
|
|
1060
|
+
'button[aria-label="Add context"]',
|
|
1061
|
+
);
|
|
1062
|
+
if (!trigger) throw new Error("Missing context trigger");
|
|
1063
|
+
trigger.dispatchEvent(
|
|
1064
|
+
new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
|
|
1065
|
+
);
|
|
1066
|
+
});
|
|
1067
|
+
await act(async () => {
|
|
1068
|
+
const action = Array.from(
|
|
1069
|
+
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
1070
|
+
).find((item) => item.textContent === "Search workspace…");
|
|
1071
|
+
if (!action) throw new Error("Missing workspace search");
|
|
1072
|
+
action.click();
|
|
1073
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1074
|
+
});
|
|
1075
|
+
};
|
|
1076
|
+
await open();
|
|
1077
|
+
const signal = fetch.mock.calls[0][1].signal;
|
|
1078
|
+
expect(signal.aborted).toBe(false);
|
|
1079
|
+
expect(document.querySelector('[role="dialog"]')).not.toBeNull();
|
|
1080
|
+
scopeKey = "org:two";
|
|
1081
|
+
await render();
|
|
1082
|
+
expect(signal.aborted).toBe(true);
|
|
1083
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
1084
|
+
await act(async () =>
|
|
1085
|
+
finish(
|
|
1086
|
+
new Response(
|
|
1087
|
+
JSON.stringify({
|
|
1088
|
+
items: [
|
|
1089
|
+
{ id: "stale", label: "Private old reference", refType: "file" },
|
|
1090
|
+
],
|
|
1091
|
+
}),
|
|
1092
|
+
),
|
|
1093
|
+
),
|
|
1094
|
+
);
|
|
1095
|
+
expect(document.body.textContent).not.toContain("Private old reference");
|
|
1096
|
+
expect(onReferencesChange).not.toHaveBeenCalled();
|
|
1097
|
+
});
|
|
1098
|
+
|
|
917
1099
|
async function mount(props: Partial<PromptComposerProps> = {}) {
|
|
918
1100
|
const composerRef = React.createRef<TiptapComposerHandle>();
|
|
919
1101
|
const onSubmit = vi.fn();
|
|
@@ -1322,19 +1504,6 @@ describe("controlled composer context", () => {
|
|
|
1322
1504
|
new KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true }),
|
|
1323
1505
|
),
|
|
1324
1506
|
);
|
|
1325
|
-
const addContext = Array.from(
|
|
1326
|
-
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
1327
|
-
).find((element) => element.textContent === "Add context")!;
|
|
1328
|
-
await act(async () => {
|
|
1329
|
-
addContext.focus();
|
|
1330
|
-
addContext.dispatchEvent(
|
|
1331
|
-
new KeyboardEvent("keydown", {
|
|
1332
|
-
key: "ArrowRight",
|
|
1333
|
-
bubbles: true,
|
|
1334
|
-
cancelable: true,
|
|
1335
|
-
}),
|
|
1336
|
-
);
|
|
1337
|
-
});
|
|
1338
1507
|
const option = Array.from(
|
|
1339
1508
|
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
1340
1509
|
).find((element) => element.textContent?.includes("Choose brief"))!;
|
|
@@ -1683,7 +1852,9 @@ describe("controlled composer context", () => {
|
|
|
1683
1852
|
expect(editor.textContent).toBe("Typed while readiness was checking");
|
|
1684
1853
|
expect(sendButton.disabled).toBe(false);
|
|
1685
1854
|
expect(sendButton.getAttribute("aria-busy")).toBeNull();
|
|
1686
|
-
const statuses =
|
|
1855
|
+
const statuses = Array.from(
|
|
1856
|
+
container.querySelectorAll('[role="status"]'),
|
|
1857
|
+
).filter((status) => status.textContent?.trim());
|
|
1687
1858
|
expect(statuses).toHaveLength(1);
|
|
1688
1859
|
expect(statuses[0]?.textContent).toContain(
|
|
1689
1860
|
"agentChat.setup.providerStatusUnavailable",
|
|
@@ -100,6 +100,7 @@ const MAX_INLINE_TEXT_FILE_CHARS = 60_000;
|
|
|
100
100
|
export type PromptComposerFile = File;
|
|
101
101
|
|
|
102
102
|
export interface PromptComposerSubmitOptions {
|
|
103
|
+
references?: Reference[];
|
|
103
104
|
intent?: ComposerSubmitIntent;
|
|
104
105
|
steer?: boolean;
|
|
105
106
|
/** Clear the submitted draft once the host owns the message and its failure recovery. */
|
|
@@ -1119,6 +1120,7 @@ function PromptComposerInner({
|
|
|
1119
1120
|
inlineTextAttachments,
|
|
1120
1121
|
});
|
|
1121
1122
|
await onSubmit(finalText, files, references, {
|
|
1123
|
+
references,
|
|
1122
1124
|
intent: submitOptions?.intent ?? "immediate",
|
|
1123
1125
|
...(submitOptions?.steer ? { steer: true } : {}),
|
|
1124
1126
|
onLocalSubmit: submitOptions?.onLocalSubmit,
|
|
@@ -457,7 +457,7 @@ describe("createTiptapComposerExtensions", () => {
|
|
|
457
457
|
});
|
|
458
458
|
act(() => {
|
|
459
459
|
Array.from(document.querySelectorAll<HTMLElement>('[role="menuitem"]'))
|
|
460
|
-
.find((button) => button.textContent?.trim() === "
|
|
460
|
+
.find((button) => button.textContent?.trim() === "Commands")
|
|
461
461
|
?.dispatchEvent(
|
|
462
462
|
new KeyboardEvent("keydown", {
|
|
463
463
|
key: "ArrowRight",
|
|
@@ -820,10 +820,6 @@ describe("createTiptapComposerExtensions", () => {
|
|
|
820
820
|
);
|
|
821
821
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
822
822
|
});
|
|
823
|
-
const addContextItem = Array.from(
|
|
824
|
-
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
825
|
-
).find((item) => item.textContent?.trim() === "Add context");
|
|
826
|
-
await act(async () => addContextItem?.click());
|
|
827
823
|
const clickMenuItem = async (label: string) => {
|
|
828
824
|
const item = Array.from(
|
|
829
825
|
document.querySelectorAll<HTMLElement>('[role^="menuitem"]'),
|
|
@@ -3387,7 +3383,7 @@ describe("createTiptapComposerExtensions", () => {
|
|
|
3387
3383
|
});
|
|
3388
3384
|
|
|
3389
3385
|
describe("TiptapComposer storage gate", () => {
|
|
3390
|
-
it("opens storage setup from
|
|
3386
|
+
it("opens storage setup from Files and images without exposing a file picker", async () => {
|
|
3391
3387
|
const onAttachmentRequest = vi.fn();
|
|
3392
3388
|
|
|
3393
3389
|
function Harness() {
|
|
@@ -3432,9 +3428,11 @@ describe("TiptapComposer storage gate", () => {
|
|
|
3432
3428
|
const uploadItem = Array.from(
|
|
3433
3429
|
document.querySelectorAll<HTMLElement>("[role=menuitem]"),
|
|
3434
3430
|
).at(0);
|
|
3435
|
-
expect(uploadItem).
|
|
3431
|
+
expect(uploadItem?.textContent).toBe("Files and images");
|
|
3436
3432
|
await act(async () => uploadItem?.click());
|
|
3437
|
-
|
|
3433
|
+
await act(async () =>
|
|
3434
|
+
vi.waitFor(() => expect(onAttachmentRequest).toHaveBeenCalledOnce()),
|
|
3435
|
+
);
|
|
3438
3436
|
expect(container.querySelector('input[type="file"]')).toBeNull();
|
|
3439
3437
|
});
|
|
3440
3438
|
});
|