@agent-native/toolkit 0.209.0 → 0.209.1-nightly-20261015005848

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 (42) hide show
  1. package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
  2. package/dist/app/chat/AgentSidebar.js +22 -11
  3. package/dist/app/chat/AgentSidebar.js.map +1 -1
  4. package/dist/app/review/InlineMarkdown.d.ts +2 -0
  5. package/dist/app/review/InlineMarkdown.d.ts.map +1 -1
  6. package/dist/app/review/InlineMarkdown.js +25 -7
  7. package/dist/app/review/InlineMarkdown.js.map +1 -1
  8. package/dist/composer/MentionChip.d.ts +14 -0
  9. package/dist/composer/MentionChip.d.ts.map +1 -0
  10. package/dist/composer/MentionChip.js +11 -0
  11. package/dist/composer/MentionChip.js.map +1 -0
  12. package/dist/composer/MentionPopover.d.ts +5 -0
  13. package/dist/composer/MentionPopover.d.ts.map +1 -1
  14. package/dist/composer/MentionPopover.js +55 -44
  15. package/dist/composer/MentionPopover.js.map +1 -1
  16. package/dist/composer/PromptComposer.d.ts +6 -1
  17. package/dist/composer/PromptComposer.d.ts.map +1 -1
  18. package/dist/composer/PromptComposer.js +3 -3
  19. package/dist/composer/PromptComposer.js.map +1 -1
  20. package/dist/composer/TiptapComposer.d.ts +18 -2
  21. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  22. package/dist/composer/TiptapComposer.js +60 -12
  23. package/dist/composer/TiptapComposer.js.map +1 -1
  24. package/dist/composer/extensions/MentionReference.d.ts.map +1 -1
  25. package/dist/composer/extensions/MentionReference.js +16 -5
  26. package/dist/composer/extensions/MentionReference.js.map +1 -1
  27. package/dist/composer/index.d.ts +2 -1
  28. package/dist/composer/index.d.ts.map +1 -1
  29. package/dist/composer/index.js +1 -0
  30. package/dist/composer/index.js.map +1 -1
  31. package/package.json +4 -4
  32. package/src/app/chat/AgentSidebar.spec.tsx +339 -2
  33. package/src/app/chat/AgentSidebar.tsx +25 -10
  34. package/src/app/review/InlineMarkdown.spec.tsx +25 -0
  35. package/src/app/review/InlineMarkdown.tsx +29 -13
  36. package/src/composer/MentionChip.tsx +46 -0
  37. package/src/composer/MentionPopover.tsx +49 -7
  38. package/src/composer/PromptComposer.text-references.spec.tsx +198 -0
  39. package/src/composer/PromptComposer.tsx +12 -0
  40. package/src/composer/TiptapComposer.tsx +100 -10
  41. package/src/composer/extensions/MentionReference.tsx +22 -14
  42. package/src/composer/index.ts +2 -0
@@ -656,14 +656,43 @@ function ComposerModeChip({ mode, onRemove, }) {
656
656
  const Icon = config.icon;
657
657
  return (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground", children: [_jsx(Icon, { className: "h-3 w-3 text-muted-foreground" }), config.label, _jsx("button", { type: "button", onClick: onRemove, "aria-label": t("agentChat.common.cancel", { defaultValue: "Cancel" }), className: "ms-0.5 rounded-sm text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
658
658
  }
659
- function plainTextToDoc(text) {
660
- const lines = text.length > 0 ? text.split(/\r?\n/) : [""];
659
+ function plainTextToDoc(text, chips = []) {
660
+ const ordered = [...chips].sort((a, b) => a.start - b.start);
661
+ const lines = [];
662
+ let lineStart = 0;
663
+ for (const separator of text.matchAll(/\r?\n/g)) {
664
+ lines.push({ start: lineStart, end: separator.index });
665
+ lineStart = separator.index + separator[0].length;
666
+ }
667
+ lines.push({ start: lineStart, end: text.length });
661
668
  return {
662
669
  type: "doc",
663
- content: lines.map((line) => ({
664
- type: "paragraph",
665
- content: line ? [{ type: "text", text: line }] : [],
666
- })),
670
+ content: lines.map((line) => {
671
+ const content = [];
672
+ let cursor = line.start;
673
+ const addText = (end) => {
674
+ if (end > cursor) {
675
+ content.push({ type: "text", text: text.slice(cursor, end) });
676
+ }
677
+ };
678
+ for (const chip of ordered) {
679
+ if (chip.start < cursor ||
680
+ line.end < chip.end ||
681
+ chip.end <= chip.start)
682
+ continue;
683
+ addText(chip.start);
684
+ content.push({ type: "mentionReference", attrs: chip.attrs });
685
+ cursor = chip.end;
686
+ }
687
+ addText(line.end);
688
+ // Drafts are reported trimmed, so a chip that ends one lost the space
689
+ // picking it added; without it the next word typed joins the chip's text.
690
+ if (cursor === text.length &&
691
+ content.at(-1)?.type === "mentionReference") {
692
+ content.push({ type: "text", text: " " });
693
+ }
694
+ return { type: "paragraph", content };
695
+ }),
667
696
  };
668
697
  }
669
698
  /** Tiptap keeps the Editor object truthy after destroy but clears commandManager. */
@@ -1376,12 +1405,20 @@ function ModelSelector({ model, effort, engines, agents, selectedAgent, selected
1376
1405
  ? "text-foreground"
1377
1406
  : "text-muted-foreground"}`, children: option.label }), option.enabled === terminalModeControl.enabled && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, option.label))) }))] }) }) })] }) })] }));
1378
1407
  }
1379
- export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isReferenceTarget, contextControlsDisabled = false, submissionDisabled = false, sendButtonDisabled = false, sendButtonBusy = false, submitting = false, maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES, documentAttachmentLimitLabel = "PDFs", attachmentsEnabled = true, onAttachmentRequest, contextButtonTooltipDisabled = false, focusRef, initialText, initialTextKey, onSubmit, onEmptySubmit, onBeforeSubmit, onSubmissionPendingChange, getSubmitFailureDraftScope, clearOnSubmit = true, clearOnSubmitImmediately = false, onTextChange, actionButton, willQueue = false, extraActionButton, stopButton, attachButton, modeControl, toolbarSlot, layoutVariant = "default", slashCommands = [], slashSkills = [], includeDefaultSlashCommands = true, includeDefaultSlashSkills = true, onSlashCommand, execMode, onExecModeChange, planModeDisabled = false, planModeDisabledReason, voiceEnabled = DEFAULT_VOICE_DICTATION_ENABLED, selectedModel, selectedEngine, selectedEffort, showAutoModelOption = true, modelSelectorOpen, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, agentOnly = false, hostedHarness, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled, onConnectProvider, onConnectLocalRuntime, imageModelMenu, draftScope, contextItems: providedContextItems, onRemoveContextItem, onRetryContextItem, contextMenuItems, plusMenuMode = "full", terminalModeControl, extensionTools = false, interceptBuildRequestsForBuilder = false, onAttachmentError, mentionItems: hostMentionItems = [], mentionPopoverDensity = "default", includeDefaultMentionSearch = true, onReferencesChange, onEscape, onFocus, onBlur, onSelectionChange, }) {
1408
+ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isReferenceTarget, contextControlsDisabled = false, submissionDisabled = false, sendButtonDisabled = false, sendButtonBusy = false, submitting = false, maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES, documentAttachmentLimitLabel = "PDFs", attachmentsEnabled = true, onAttachmentRequest, contextButtonTooltipDisabled = false, focusRef, initialText, initialTextKey, initialReferences, onSubmit, onEmptySubmit, onBeforeSubmit, onSubmissionPendingChange, getSubmitFailureDraftScope, clearOnSubmit = true, clearOnSubmitImmediately = false, onTextChange, actionButton, willQueue = false, extraActionButton, stopButton, attachButton, modeControl, toolbarSlot, layoutVariant = "default", slashCommands = [], slashSkills = [], includeDefaultSlashCommands = true, includeDefaultSlashSkills = true, onSlashCommand, execMode, onExecModeChange, planModeDisabled = false, planModeDisabledReason, voiceEnabled = DEFAULT_VOICE_DICTATION_ENABLED, selectedModel, selectedEngine, selectedEffort, showAutoModelOption = true, modelSelectorOpen, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, agentOnly = false, hostedHarness, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled, onConnectProvider, onConnectLocalRuntime, imageModelMenu, draftScope, contextItems: providedContextItems, onRemoveContextItem, onRetryContextItem, contextMenuItems, plusMenuMode = "full", terminalModeControl, extensionTools = false, interceptBuildRequestsForBuilder = false, onAttachmentError, mentionItems: hostMentionItems = [], mentionItemsError, onRetryMentionItems, mentionPopoverDensity = "default", includeDefaultMentionSearch = true, onReferencesChange, onEscape, onFocus, onBlur, onSelectionChange, }) {
1380
1409
  const contextItems = providedContextItems ?? [];
1381
1410
  const hasContextMenu = (contextMenuItems !== undefined || plusMenuMode !== "hidden") &&
1382
1411
  !(attachmentsEnabled && attachButton);
1383
1412
  const adapters = useComposerRuntimeAdapters();
1384
1413
  const t = adapters.translate;
1414
+ const initialReferencesRef = useRef(initialReferences);
1415
+ initialReferencesRef.current = initialReferences;
1416
+ const textChips = useCallback((references = []) => references.flatMap(({ start, end, reference }) => {
1417
+ const normalized = adapters.agentChat.normalizeReference(reference);
1418
+ return normalized
1419
+ ? [{ start, end, attrs: mentionReferenceAttrs(normalized) }]
1420
+ : [];
1421
+ }), [adapters]);
1385
1422
  const sendButtonTooltip = t(getComposerSendTooltipKey(willQueue), {
1386
1423
  defaultValue: willQueue ? "Queue message" : "Send message",
1387
1424
  });
@@ -2023,6 +2060,12 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
2023
2060
  popoverRef.current?.moveDown();
2024
2061
  return true;
2025
2062
  }
2063
+ if ((event.key === "Enter" ||
2064
+ (event.key === "Tab" && !event.shiftKey)) &&
2065
+ popoverRef.current?.activateRetry()) {
2066
+ event.preventDefault();
2067
+ return true;
2068
+ }
2026
2069
  // A mention comes only from an explicit pick of a highlighted row. With
2027
2070
  // nothing highlighted, even while a search is pending, the "@" is
2028
2071
  // plain text: Enter submits it and a late result changes nothing.
@@ -2385,7 +2428,11 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
2385
2428
  if (from > 1 && before !== "" && !/\s/.test(before))
2386
2429
  inserted = ` @`;
2387
2430
  }
2388
- if (typeof document.execCommand !== "function" ||
2431
+ // The popover anchors on the selection right after this insert, but an
2432
+ // execCommand edit reaches the editor state only once ProseMirror reads
2433
+ // the DOM back, so an @ goes through the editor directly.
2434
+ if (mention ||
2435
+ typeof document.execCommand !== "function" ||
2389
2436
  !document.execCommand("insertText", false, inserted)) {
2390
2437
  editor.commands.insertContent(inserted);
2391
2438
  }
@@ -2405,10 +2452,10 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
2405
2452
  popoverStateRef.current = state;
2406
2453
  setPopover(state);
2407
2454
  },
2408
- setText(text) {
2455
+ setText(text, references) {
2409
2456
  if (!isComposerEditorUsable(editor))
2410
2457
  return;
2411
- editor.commands.setContent(plainTextToDoc(text));
2458
+ editor.commands.setContent(plainTextToDoc(text, textChips(references)));
2412
2459
  editor.commands.focus("end");
2413
2460
  const trimmed = editor.getText({ blockSeparator: "\n" }).trim();
2414
2461
  setEditorHasText(trimmed.length > 0);
@@ -3861,7 +3908,7 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
3861
3908
  }
3862
3909
  else if (initialTextKeyRef.current !== key) {
3863
3910
  initialTextKeyRef.current = key;
3864
- editor.commands.setContent(plainTextToDoc(initialText));
3911
+ editor.commands.setContent(plainTextToDoc(initialText, textChips(initialReferencesRef.current)));
3865
3912
  }
3866
3913
  else {
3867
3914
  return;
@@ -3883,6 +3930,7 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
3883
3930
  initialText,
3884
3931
  initialTextKey,
3885
3932
  scheduleComposerDraftPersist,
3933
+ textChips,
3886
3934
  updateSlotReferences,
3887
3935
  ]);
3888
3936
  // Tiptap only reads `editable` at init; prop changes need setEditable.
@@ -4015,6 +4063,6 @@ export function TiptapComposer({ placeholder, ariaLabel, disabled = false, isRef
4015
4063
  }
4016
4064
  const pageTarget = Array.from(document.querySelectorAll('button:not(:disabled), a[href], input:not([type="hidden"]):not(:disabled), textarea:not(:disabled)')).find((element) => !root?.contains(element) && !element.closest("[hidden]"));
4017
4065
  pageTarget?.focus();
4018
- }, disabled: launchersDisabled })) : null, toolbarSlot ?? modeControl, _jsx("div", { "data-agent-composer-slot": "toolbar-spacer", className: "flex-1" }), shouldRenderModelSelector(availableModels, onModelChange) && (_jsx(ModelSelector, { model: selectedModel ?? "", selectedEngine: selectedEngine, open: modelSelectorOpen, effort: selectedEffort, engines: availableModels, agents: availableAgents, selectedAgent: selectedAgent, agentOnly: agentOnly, hostedHarness: hostedHarness, showAutoModelOption: showAutoModelOption, modelListLoading: modelListLoading, onChange: onModelChange, onEffortChange: onEffortChange, onAgentChange: onAgentChange, onModelSelectorOpenChange: onModelSelectorOpenChange, providerConnectStatusEnabled: providerConnectStatusEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, terminalModeControl: terminalModeControl, imageModel: imageModelMenu })), execMode && onExecModeChange && (_jsx(ModeSelector, { mode: execMode, onChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason })), actionButton ?? (_jsxs(_Fragment, { children: [extraActionButton, voiceEnabled && (_jsx(VoiceButton, { voice: voice, isMac: isMac, disabled: disabled })), primaryAction === "stop" ? (stopButton) : (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: (event) => void submitComposer("immediate", undefined, event.metaKey || event.ctrlKey), disabled: !canSend || sendButtonDisabled, "aria-label": sendButtonTooltip, "aria-busy": sendButtonBusy || undefined, "data-agent-composer-slot": "send-button", className: "agent-composer-send-button shrink-0 flex h-7 w-7 items-center justify-center rounded-full bg-primary text-primary-foreground hover:opacity-90 transition-[opacity,transform] duration-150 active:scale-[0.97] disabled:opacity-30 disabled:cursor-not-allowed", children: sendButtonBusy ? (_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin motion-reduce:animate-none" })) : (_jsx(IconArrowUp, { className: "h-3.5 w-3.5" })) }) }), _jsx(TooltipContent, { children: sendButtonTooltip })] }))] }))] }), _jsx(MentionPopover, { ref: popoverRef, density: mentionPopoverDensity, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: inlineMentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
4066
+ }, disabled: launchersDisabled })) : null, toolbarSlot ?? modeControl, _jsx("div", { "data-agent-composer-slot": "toolbar-spacer", className: "flex-1" }), shouldRenderModelSelector(availableModels, onModelChange) && (_jsx(ModelSelector, { model: selectedModel ?? "", selectedEngine: selectedEngine, open: modelSelectorOpen, effort: selectedEffort, engines: availableModels, agents: availableAgents, selectedAgent: selectedAgent, agentOnly: agentOnly, hostedHarness: hostedHarness, showAutoModelOption: showAutoModelOption, modelListLoading: modelListLoading, onChange: onModelChange, onEffortChange: onEffortChange, onAgentChange: onAgentChange, onModelSelectorOpenChange: onModelSelectorOpenChange, providerConnectStatusEnabled: providerConnectStatusEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, terminalModeControl: terminalModeControl, imageModel: imageModelMenu })), execMode && onExecModeChange && (_jsx(ModeSelector, { mode: execMode, onChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason })), actionButton ?? (_jsxs(_Fragment, { children: [extraActionButton, voiceEnabled && (_jsx(VoiceButton, { voice: voice, isMac: isMac, disabled: disabled })), primaryAction === "stop" ? (stopButton) : (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: (event) => void submitComposer("immediate", undefined, event.metaKey || event.ctrlKey), disabled: !canSend || sendButtonDisabled, "aria-label": sendButtonTooltip, "aria-busy": sendButtonBusy || undefined, "data-agent-composer-slot": "send-button", className: "agent-composer-send-button shrink-0 flex h-7 w-7 items-center justify-center rounded-full bg-primary text-primary-foreground hover:opacity-90 transition-[opacity,transform] duration-150 active:scale-[0.97] disabled:opacity-30 disabled:cursor-not-allowed", children: sendButtonBusy ? (_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin motion-reduce:animate-none" })) : (_jsx(IconArrowUp, { className: "h-3.5 w-3.5" })) }) }), _jsx(TooltipContent, { children: sendButtonTooltip })] }))] }))] }), _jsx(MentionPopover, { ref: popoverRef, density: mentionPopoverDensity, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: inlineMentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, error: mentionItemsError, onRetry: onRetryMentionItems, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
4019
4067
  }
4020
4068
  //# sourceMappingURL=TiptapComposer.js.map