@agent-native/toolkit 0.218.0 → 0.220.0-nightly-20261023183804
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/styles.css +13 -6
- package/dist/app/chat/AgentKitAssistantChat.d.ts +2 -0
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +11 -3
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentPanel.js +6 -6
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +5 -3
- package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/action-widget.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/action-widget.js +1 -0
- package/dist/app/chat/agentkit-chat/action-widget.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +2 -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/chat/tool-call-display.d.ts +3 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +5 -4
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/chat/tool-render-registry.d.ts +2 -0
- package/dist/app/chat/chat/tool-render-registry.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-render-registry.js.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.js +6 -1
- package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
- package/dist/app/shared/CommandMenu.d.ts +2 -0
- package/dist/app/shared/CommandMenu.d.ts.map +1 -1
- package/dist/app/shared/CommandMenu.js +11 -6
- package/dist/app/shared/CommandMenu.js.map +1 -1
- package/dist/composer/ComposerContextMenu.d.ts.map +1 -1
- package/dist/composer/ComposerContextMenu.js +27 -2
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/composer/ComposerPlusMenu.js +50 -4
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/TiptapComposer.js +1 -1
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/components.spec.tsx +7 -5
- package/src/app/agentkit/react/styles.css +13 -6
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +258 -27
- package/src/app/chat/AgentKitAssistantChat.tsx +15 -2
- package/src/app/chat/AgentPanel.tsx +8 -8
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +17 -0
- package/src/app/chat/MultiTabAssistantChat.tsx +7 -2
- package/src/app/chat/agentkit-chat/action-widget.spec.tsx +62 -0
- package/src/app/chat/agentkit-chat/action-widget.tsx +1 -0
- package/src/app/chat/chat/surface-types.ts +2 -0
- package/src/app/chat/chat/tool-call-display.tsx +10 -1
- package/src/app/chat/chat/tool-render-registry.tsx +2 -0
- package/src/app/chat/conversation/AgentConversation.spec.tsx +51 -1
- package/src/app/chat/conversation/AgentConversation.tsx +11 -2
- package/src/app/shared/CommandMenu.spec.tsx +175 -6
- package/src/app/shared/CommandMenu.tsx +24 -7
- package/src/composer/ComposerContextMenu.tsx +32 -3
- package/src/composer/ComposerPlusMenu.parity.spec.tsx +96 -2
- package/src/composer/ComposerPlusMenu.tsx +48 -4
- package/src/composer/TiptapComposer.tsx +1 -1
|
@@ -71,7 +71,10 @@ afterEach(() => {
|
|
|
71
71
|
async function settle() {
|
|
72
72
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
73
73
|
}
|
|
74
|
-
async function mount(
|
|
74
|
+
async function mount(
|
|
75
|
+
props: Partial<PromptComposerProps> = {},
|
|
76
|
+
settleAfterRender = true,
|
|
77
|
+
) {
|
|
75
78
|
const composerRef = React.createRef<TiptapComposerHandle>();
|
|
76
79
|
const onSubmit = vi.fn();
|
|
77
80
|
await act(async () => {
|
|
@@ -92,7 +95,7 @@ async function mount(props: Partial<PromptComposerProps> = {}) {
|
|
|
92
95
|
/>
|
|
93
96
|
</ComposerRuntimeAdaptersProvider>,
|
|
94
97
|
);
|
|
95
|
-
await settle();
|
|
98
|
+
if (settleAfterRender) await settle();
|
|
96
99
|
});
|
|
97
100
|
return { composerRef, onSubmit };
|
|
98
101
|
}
|
|
@@ -722,4 +725,95 @@ describe("shared default action preservation", () => {
|
|
|
722
725
|
expect(document.querySelector('[role="status"]')).toBeNull();
|
|
723
726
|
expect(item("Upload skill file")).toBeDefined();
|
|
724
727
|
});
|
|
728
|
+
|
|
729
|
+
it("resumes skill-file review after the native picker dismisses the menu", async () => {
|
|
730
|
+
await mount();
|
|
731
|
+
await open();
|
|
732
|
+
await choose("Create Skill");
|
|
733
|
+
await choose("Upload skill file");
|
|
734
|
+
|
|
735
|
+
await act(async () => {
|
|
736
|
+
await new Promise((resolve) => setTimeout(resolve, 120));
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
const input = container.querySelector<HTMLInputElement>(
|
|
740
|
+
'input[accept=".md,text/markdown"]',
|
|
741
|
+
)!;
|
|
742
|
+
const file = new File(["# Test skill\nDo the test."], "Test Skill.md", {
|
|
743
|
+
type: "text/markdown",
|
|
744
|
+
});
|
|
745
|
+
Object.defineProperty(input, "files", {
|
|
746
|
+
configurable: true,
|
|
747
|
+
value: [file],
|
|
748
|
+
});
|
|
749
|
+
await act(async () => {
|
|
750
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
751
|
+
await settle();
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
const form = document.querySelector<HTMLFormElement>("[role=menu] form");
|
|
755
|
+
expect(form).not.toBeNull();
|
|
756
|
+
expect(form?.textContent).toContain(
|
|
757
|
+
"Review the content from Test Skill.md before saving.",
|
|
758
|
+
);
|
|
759
|
+
expect(form?.querySelector("textarea")?.value).toBe(
|
|
760
|
+
"# Test skill\nDo the test.",
|
|
761
|
+
);
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
it("restores the skill submenu when the native picker is canceled", async () => {
|
|
765
|
+
await mount();
|
|
766
|
+
await open();
|
|
767
|
+
await choose("Create Skill");
|
|
768
|
+
await choose("Upload skill file");
|
|
769
|
+
|
|
770
|
+
await act(async () => {
|
|
771
|
+
await new Promise((resolve) => setTimeout(resolve, 120));
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
const input = container.querySelector<HTMLInputElement>(
|
|
775
|
+
'input[accept=".md,text/markdown"]',
|
|
776
|
+
)!;
|
|
777
|
+
await act(async () => {
|
|
778
|
+
input.dispatchEvent(new Event("cancel"));
|
|
779
|
+
await settle();
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
expect(labels()).toContain("Upload skill file");
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
it("does not resume the skill page if the composer is disabled", async () => {
|
|
786
|
+
await mount();
|
|
787
|
+
await open();
|
|
788
|
+
await choose("Create Skill");
|
|
789
|
+
await choose("Upload skill file");
|
|
790
|
+
|
|
791
|
+
const input = container.querySelector<HTMLInputElement>(
|
|
792
|
+
'input[accept=".md,text/markdown"]',
|
|
793
|
+
)!;
|
|
794
|
+
vi.useFakeTimers();
|
|
795
|
+
try {
|
|
796
|
+
const scheduledTimeouts = vi.spyOn(globalThis, "setTimeout");
|
|
797
|
+
const clearedTimeouts = vi.spyOn(globalThis, "clearTimeout");
|
|
798
|
+
const timersBeforeCancel = vi.getTimerCount();
|
|
799
|
+
const timeoutCallIndex = scheduledTimeouts.mock.calls.length;
|
|
800
|
+
act(() => input.dispatchEvent(new Event("cancel")));
|
|
801
|
+
expect(vi.getTimerCount()).toBe(timersBeforeCancel + 1);
|
|
802
|
+
const resumeTimer =
|
|
803
|
+
scheduledTimeouts.mock.results[timeoutCallIndex]?.value;
|
|
804
|
+
expect(resumeTimer).toBeDefined();
|
|
805
|
+
|
|
806
|
+
await mount({ disabled: true }, false);
|
|
807
|
+
expect(clearedTimeouts).toHaveBeenCalledWith(resumeTimer);
|
|
808
|
+
|
|
809
|
+
await act(async () => {
|
|
810
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
expect(document.querySelector("[role=menu] form")).toBeNull();
|
|
814
|
+
expect(labels()).not.toContain("Upload skill file");
|
|
815
|
+
} finally {
|
|
816
|
+
vi.useRealTimers();
|
|
817
|
+
}
|
|
818
|
+
});
|
|
725
819
|
});
|
|
@@ -92,6 +92,9 @@ export function useComposerDefaultActions({
|
|
|
92
92
|
const [view, setView] = useState<View>("menu");
|
|
93
93
|
const skillFileInputRef = useRef<HTMLInputElement>(null);
|
|
94
94
|
const skillControls = useRef<ComposerContextPageControls | null>(null);
|
|
95
|
+
const skillFilePickerOpen = useRef(false);
|
|
96
|
+
const skillPageDismissedWhilePickerOpen = useRef(false);
|
|
97
|
+
const skillResumeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
95
98
|
const skillEpoch = useRef(0);
|
|
96
99
|
const skillRequest = useRef<AbortController | null>(null);
|
|
97
100
|
const skillCloseTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -104,13 +107,48 @@ export function useComposerDefaultActions({
|
|
|
104
107
|
} | null>(null);
|
|
105
108
|
const [skillUploadBusy, setSkillUploadBusy] = useState(false);
|
|
106
109
|
const formId = useId();
|
|
107
|
-
const
|
|
110
|
+
const invalidateSkillWork = useCallback(() => {
|
|
108
111
|
skillEpoch.current++;
|
|
109
112
|
skillRequest.current?.abort();
|
|
110
113
|
skillRequest.current = null;
|
|
111
114
|
if (skillCloseTimer.current !== null) clearTimeout(skillCloseTimer.current);
|
|
112
115
|
skillCloseTimer.current = null;
|
|
113
116
|
}, []);
|
|
117
|
+
const cancelSkillWork = useCallback(() => {
|
|
118
|
+
skillFilePickerOpen.current = false;
|
|
119
|
+
skillPageDismissedWhilePickerOpen.current = false;
|
|
120
|
+
if (skillResumeTimer.current !== null)
|
|
121
|
+
clearTimeout(skillResumeTimer.current);
|
|
122
|
+
skillResumeTimer.current = null;
|
|
123
|
+
invalidateSkillWork();
|
|
124
|
+
}, [invalidateSkillWork]);
|
|
125
|
+
const finishSkillFilePicker = useCallback(() => {
|
|
126
|
+
skillFilePickerOpen.current = false;
|
|
127
|
+
if (!skillPageDismissedWhilePickerOpen.current) return;
|
|
128
|
+
skillPageDismissedWhilePickerOpen.current = false;
|
|
129
|
+
if (skillResumeTimer.current !== null)
|
|
130
|
+
clearTimeout(skillResumeTimer.current);
|
|
131
|
+
skillResumeTimer.current = setTimeout(() => {
|
|
132
|
+
skillResumeTimer.current = null;
|
|
133
|
+
skillControls.current?.onResume();
|
|
134
|
+
}, 0);
|
|
135
|
+
}, []);
|
|
136
|
+
const dismissSkillPage = useCallback(() => {
|
|
137
|
+
if (skillFilePickerOpen.current) {
|
|
138
|
+
skillPageDismissedWhilePickerOpen.current = true;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
cancelSkillWork();
|
|
142
|
+
}, [cancelSkillWork]);
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
const input = skillFileInputRef.current;
|
|
145
|
+
input?.addEventListener("cancel", finishSkillFilePicker);
|
|
146
|
+
return () => {
|
|
147
|
+
input?.removeEventListener("cancel", finishSkillFilePicker);
|
|
148
|
+
if (skillResumeTimer.current !== null)
|
|
149
|
+
clearTimeout(skillResumeTimer.current);
|
|
150
|
+
};
|
|
151
|
+
}, [finishSkillFilePicker]);
|
|
114
152
|
useEffect(() => cancelSkillWork, [cancelSkillWork, adapters.resolvePath]);
|
|
115
153
|
useEffect(() => {
|
|
116
154
|
if (!disabled) return;
|
|
@@ -128,7 +166,7 @@ export function useComposerDefaultActions({
|
|
|
128
166
|
setSkillUploadBusy(false);
|
|
129
167
|
};
|
|
130
168
|
const handleSkillFileSelected = async (file: File) => {
|
|
131
|
-
|
|
169
|
+
invalidateSkillWork();
|
|
132
170
|
const epoch = skillEpoch.current;
|
|
133
171
|
setSkillUploadStatus(null);
|
|
134
172
|
try {
|
|
@@ -298,7 +336,7 @@ export function useComposerDefaultActions({
|
|
|
298
336
|
}),
|
|
299
337
|
],
|
|
300
338
|
onSelect: resetSkillUpload,
|
|
301
|
-
onDismiss:
|
|
339
|
+
onDismiss: dismissSkillPage,
|
|
302
340
|
render: (controls) => {
|
|
303
341
|
skillControls.current = controls;
|
|
304
342
|
return view === "menu" ? (
|
|
@@ -317,7 +355,12 @@ export function useComposerDefaultActions({
|
|
|
317
355
|
<DropdownMenuItem
|
|
318
356
|
onSelect={(event) => {
|
|
319
357
|
event.preventDefault();
|
|
320
|
-
skillFileInputRef.current
|
|
358
|
+
const input = skillFileInputRef.current;
|
|
359
|
+
if (!input) return;
|
|
360
|
+
skillPageDismissedWhilePickerOpen.current = false;
|
|
361
|
+
skillFilePickerOpen.current = true;
|
|
362
|
+
controls.onClose({ restoreFocus: false });
|
|
363
|
+
input.click();
|
|
321
364
|
}}
|
|
322
365
|
>
|
|
323
366
|
{t("agentChat.composer.skill.uploadFile", {
|
|
@@ -451,6 +494,7 @@ export function useComposerDefaultActions({
|
|
|
451
494
|
onChange={(event) => {
|
|
452
495
|
const file = event.target.files?.[0];
|
|
453
496
|
event.target.value = "";
|
|
497
|
+
finishSkillFilePicker();
|
|
454
498
|
if (file) void handleSkillFileSelected(file);
|
|
455
499
|
}}
|
|
456
500
|
/>
|
|
@@ -2207,7 +2207,7 @@ function ModelSelector({
|
|
|
2207
2207
|
? `. Agent: ${selectedAgentLabel}`
|
|
2208
2208
|
: ""
|
|
2209
2209
|
}`}
|
|
2210
|
-
className="agent-composer-model-button flex min-w-0 max-w-none shrink
|
|
2210
|
+
className="agent-composer-model-button flex min-w-0 max-w-none shrink items-center gap-1 overflow-hidden rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground"
|
|
2211
2211
|
>
|
|
2212
2212
|
<span className="min-w-0 truncate">
|
|
2213
2213
|
{selectedAgentOption?.icon ? (
|