@agent-native/toolkit 0.203.0-nightly-20261007064822 → 0.203.0

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 (40) hide show
  1. package/dist/agentkit.d.ts +2 -1
  2. package/dist/agentkit.d.ts.map +1 -1
  3. package/dist/agentkit.js +2 -1
  4. package/dist/agentkit.js.map +1 -1
  5. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  6. package/dist/app/agentkit/react/components.js +5 -5
  7. package/dist/app/agentkit/react/components.js.map +1 -1
  8. package/dist/app/agentkit/react/context.d.ts +1 -0
  9. package/dist/app/agentkit/react/context.d.ts.map +1 -1
  10. package/dist/app/agentkit/react/context.js +1 -0
  11. package/dist/app/agentkit/react/context.js.map +1 -1
  12. package/dist/app/agentkit/react/styles.css +6 -1
  13. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  14. package/dist/app/chat/AgentKitAssistantChat.js +94 -5
  15. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  16. package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
  17. package/dist/app/chat/MultiTabAssistantChat.js +4 -1
  18. package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
  19. package/dist/composer/PromptComposer.d.ts +1 -0
  20. package/dist/composer/PromptComposer.d.ts.map +1 -1
  21. package/dist/composer/PromptComposer.js +13 -1
  22. package/dist/composer/PromptComposer.js.map +1 -1
  23. package/dist/composer/TiptapComposer.d.ts +2 -2
  24. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  25. package/dist/composer/TiptapComposer.js +9 -6
  26. package/dist/composer/TiptapComposer.js.map +1 -1
  27. package/package.json +4 -4
  28. package/src/agentkit.ts +2 -0
  29. package/src/app/agentkit/react/components.interaction.spec.tsx +68 -0
  30. package/src/app/agentkit/react/components.tsx +11 -4
  31. package/src/app/agentkit/react/context.tsx +2 -0
  32. package/src/app/agentkit/react/styles.css +6 -1
  33. package/src/app/chat/AgentKitAssistantChat.spec.tsx +38 -1
  34. package/src/app/chat/AgentKitAssistantChat.tsx +111 -4
  35. package/src/app/chat/MultiTabAssistantChat.spec.tsx +82 -0
  36. package/src/app/chat/MultiTabAssistantChat.tsx +4 -1
  37. package/src/composer/PromptComposer.spec.ts +80 -0
  38. package/src/composer/PromptComposer.tsx +15 -0
  39. package/src/composer/TiptapComposer.spec.ts +23 -0
  40. package/src/composer/TiptapComposer.tsx +18 -7
@@ -33,6 +33,7 @@ import { cn } from "../utils.js";
33
33
  import { AgentComposerFrame } from "./AgentComposerFrame.js";
34
34
  import { IMAGE_ATTACHMENT_ACCEPT } from "./attachment-accept.js";
35
35
  import {
36
+ CHAT_DOCUMENT_ATTACHMENT_ACCEPT,
36
37
  PROMPT_DOCUMENT_ATTACHMENT_ACCEPT,
37
38
  TextAttachmentAdapter,
38
39
  } from "./attachment-accept.js";
@@ -314,6 +315,20 @@ class RasterImageAttachmentAdapter extends SimpleImageAttachmentAdapter {
314
315
  }
315
316
  }
316
317
 
318
+ // SVGs never match the raster adapter, so agent chat stages them as reference
319
+ // documents rather than images a model would try to read as pixels.
320
+ class ChatDocumentAttachmentAdapter extends BinaryDocumentAttachmentAdapter {
321
+ public accept = CHAT_DOCUMENT_ATTACHMENT_ACCEPT;
322
+ }
323
+
324
+ export function createChatAttachmentAdapter(): AttachmentAdapter {
325
+ return new CompositeAttachmentAdapter([
326
+ new RasterImageAttachmentAdapter(),
327
+ new ChatDocumentAttachmentAdapter(),
328
+ new TextAttachmentAdapter(),
329
+ ]);
330
+ }
331
+
317
332
  function isInlineableTextFile(file: File): boolean {
318
333
  if (file.type.startsWith("text/")) return true;
319
334
  if (
@@ -2554,6 +2554,29 @@ describe("createTiptapComposerExtensions", () => {
2554
2554
  });
2555
2555
  });
2556
2556
 
2557
+ it("names a rejected image drop by the file the user dropped", async () => {
2558
+ const file = new File(["<svg/>"], "logo.svg", { type: "image/svg+xml" });
2559
+ const added: File[] = [];
2560
+ const onError = vi.fn();
2561
+ handleComposerFileDrop({
2562
+ event: {
2563
+ dataTransfer: { files: [file] },
2564
+ preventDefault: () => {},
2565
+ stopPropagation: () => {},
2566
+ } as unknown as DragEvent,
2567
+ addAttachment: async (attachment) => {
2568
+ added.push(attachment);
2569
+ throw new Error("File type image/svg+xml is not accepted.");
2570
+ },
2571
+ onError,
2572
+ });
2573
+
2574
+ await vi.waitFor(() => {
2575
+ expect(onError).toHaveBeenCalledWith(expect.any(Error), "logo.svg");
2576
+ });
2577
+ expect(added[0]?.name).toMatch(/^\d+-[a-z0-9]+-logo\.svg$/);
2578
+ });
2579
+
2557
2580
  it("caps the model picker height without forcing empty vertical space", () => {
2558
2581
  expect(MODEL_SELECTOR_POPOVER_STYLE).toMatchObject({
2559
2582
  fontSize: 13,
@@ -770,16 +770,15 @@ export function handleComposerFileDrop(options: {
770
770
  options.event.preventDefault();
771
771
  options.event.stopPropagation();
772
772
  if (options.attachmentsEnabled === false) return true;
773
- const attachments = droppedFiles.map(uniquifyComposerImageFile);
774
773
  let errorReported = false;
775
774
  void Promise.all(
776
- attachments.map(async (file) => {
775
+ droppedFiles.map(async (droppedFile) => {
777
776
  try {
778
- await options.addAttachment(file);
777
+ await options.addAttachment(uniquifyComposerImageFile(droppedFile));
779
778
  } catch (error) {
780
779
  if (errorReported) return;
781
780
  errorReported = true;
782
- options.onError?.(error, file.name);
781
+ options.onError?.(error, droppedFile.name);
783
782
  }
784
783
  }),
785
784
  );
@@ -1223,8 +1222,8 @@ export interface TiptapComposerProps {
1223
1222
  interceptBuildRequestsForBuilder?: boolean;
1224
1223
  /**
1225
1224
  * Called when a drag-drop or paste attachment fails (e.g. unsupported format,
1226
- * size cap). Use this to surface a visible error in the parent chat surface
1227
- * rather than silently swallowing the problem.
1225
+ * size cap) so the host can show it in its own surface. Without it, the
1226
+ * composer shows the message inline.
1228
1227
  */
1229
1228
  onAttachmentError?: (message: string) => void;
1230
1229
  }
@@ -2873,8 +2872,10 @@ export function TiptapComposer({
2873
2872
  // Refs for values accessed in handleKeyDown (ProseMirror doesn't re-bind)
2874
2873
  const popoverStateRef = useRef<PopoverState>(null);
2875
2874
  const composingRef = useRef(false);
2875
+ const [attachmentError, setAttachmentError] = useState<string | null>(null);
2876
2876
  const onAttachmentErrorRef = useRef(onAttachmentError);
2877
- onAttachmentErrorRef.current = onAttachmentError;
2877
+ // Many standalone prompts pass no handler; a rejected file must still say so.
2878
+ onAttachmentErrorRef.current = onAttachmentError ?? setAttachmentError;
2878
2879
  const onSubmitRef = useRef(onSubmit);
2879
2880
  onSubmitRef.current = onSubmit;
2880
2881
  const execModeRef = useRef(execMode);
@@ -3101,6 +3102,7 @@ export function TiptapComposer({
3101
3102
  }, [cleanStaleAttachments, composerRuntime]);
3102
3103
  const addAttachmentForCurrentScope = useCallback(
3103
3104
  (file: File) => {
3105
+ setAttachmentError(null);
3104
3106
  const scopeGeneration = draftScopeGenerationRef.current;
3105
3107
  const submissionBarrier = attachmentSubmissionBarrierRef.current;
3106
3108
  let resolveOperation!: () => void;
@@ -3297,6 +3299,7 @@ export function TiptapComposer({
3297
3299
  // Drive the send button's enabled state from the actual editor contents;
3298
3300
  // the composer runtime is only synced on submit, so its isEmpty lags.
3299
3301
  setEditorHasText(composerDocumentHasContent(ed.state.doc));
3302
+ setAttachmentError(null);
3300
3303
  onTextChangeRef.current?.(ed.getText({ blockSeparator: "\n" }).trim());
3301
3304
  setReferenceRevision((revision) => revision + 1);
3302
3305
 
@@ -5871,6 +5874,14 @@ export function TiptapComposer({
5871
5874
  {contextSubmissionError}
5872
5875
  </p>
5873
5876
  ) : null}
5877
+ {attachmentError ? (
5878
+ <p
5879
+ role="alert"
5880
+ className="break-words px-2.5 pt-2 text-xs text-destructive"
5881
+ >
5882
+ {attachmentError}
5883
+ </p>
5884
+ ) : null}
5874
5885
  <div
5875
5886
  data-agent-composer-variant={layoutVariant}
5876
5887
  data-agent-composer-slot="editor-wrap"