@agent-native/toolkit 0.15.1 → 0.16.1

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 (60) hide show
  1. package/README.md +26 -0
  2. package/agent-native.eject.json +16 -0
  3. package/dist/composer/ComposerPlusMenu.d.ts.map +1 -1
  4. package/dist/composer/ComposerPlusMenu.js +29 -19
  5. package/dist/composer/ComposerPlusMenu.js.map +1 -1
  6. package/dist/composer/PromptComposer.d.ts +11 -1
  7. package/dist/composer/PromptComposer.d.ts.map +1 -1
  8. package/dist/composer/PromptComposer.js +2 -2
  9. package/dist/composer/PromptComposer.js.map +1 -1
  10. package/dist/composer/TiptapComposer.d.ts +30 -1
  11. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  12. package/dist/composer/TiptapComposer.js +255 -145
  13. package/dist/composer/TiptapComposer.js.map +1 -1
  14. package/dist/composer/TiptapComposer.spec.js +33 -1
  15. package/dist/composer/TiptapComposer.spec.js.map +1 -1
  16. package/dist/composer/index.d.ts +1 -0
  17. package/dist/composer/index.d.ts.map +1 -1
  18. package/dist/composer/index.js +1 -0
  19. package/dist/composer/index.js.map +1 -1
  20. package/dist/composer/model-selection.d.ts +12 -0
  21. package/dist/composer/model-selection.d.ts.map +1 -0
  22. package/dist/composer/model-selection.js +31 -0
  23. package/dist/composer/model-selection.js.map +1 -0
  24. package/dist/composer/model-selection.spec.d.ts +2 -0
  25. package/dist/composer/model-selection.spec.d.ts.map +1 -0
  26. package/dist/composer/model-selection.spec.js +38 -0
  27. package/dist/composer/model-selection.spec.js.map +1 -0
  28. package/dist/data-grid/DataGrid.d.ts +92 -0
  29. package/dist/data-grid/DataGrid.d.ts.map +1 -0
  30. package/dist/data-grid/DataGrid.js +315 -0
  31. package/dist/data-grid/DataGrid.js.map +1 -0
  32. package/dist/data-grid/DataGrid.spec.d.ts +2 -0
  33. package/dist/data-grid/DataGrid.spec.d.ts.map +1 -0
  34. package/dist/data-grid/DataGrid.spec.js +134 -0
  35. package/dist/data-grid/DataGrid.spec.js.map +1 -0
  36. package/dist/data-grid/index.d.ts +2 -0
  37. package/dist/data-grid/index.d.ts.map +1 -0
  38. package/dist/data-grid/index.js +2 -0
  39. package/dist/data-grid/index.js.map +1 -0
  40. package/dist/sharing/SharePrimitives.d.ts +14 -3
  41. package/dist/sharing/SharePrimitives.d.ts.map +1 -1
  42. package/dist/sharing/SharePrimitives.js +11 -3
  43. package/dist/sharing/SharePrimitives.js.map +1 -1
  44. package/dist/sharing/index.d.ts +1 -1
  45. package/dist/sharing/index.d.ts.map +1 -1
  46. package/dist/sharing/index.js +1 -1
  47. package/dist/sharing/index.js.map +1 -1
  48. package/package.json +15 -1
  49. package/src/composer/ComposerPlusMenu.tsx +122 -65
  50. package/src/composer/PromptComposer.tsx +21 -0
  51. package/src/composer/TiptapComposer.spec.ts +46 -0
  52. package/src/composer/TiptapComposer.tsx +721 -349
  53. package/src/composer/index.ts +6 -0
  54. package/src/composer/model-selection.spec.ts +45 -0
  55. package/src/composer/model-selection.ts +51 -0
  56. package/src/data-grid/DataGrid.spec.tsx +243 -0
  57. package/src/data-grid/DataGrid.tsx +754 -0
  58. package/src/data-grid/index.ts +15 -0
  59. package/src/sharing/SharePrimitives.tsx +47 -8
  60. package/src/sharing/index.ts +4 -0
@@ -1,12 +1,12 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Skeleton } from "@agent-native/toolkit/ui/skeleton";
3
3
  import { useComposer, useComposerRuntime } from "@assistant-ui/react";
4
- import { IconArrowUp, IconCheck, IconChevronDown, IconChevronRight, IconBulb, IconClock, IconBolt, IconTool, IconX, IconClipboardList, IconKey, IconPencil, IconPlugConnected, } from "@tabler/icons-react";
4
+ import { IconArrowUp, IconCheck, IconChevronDown, IconChevronRight, IconBulb, IconClock, IconBolt, IconTool, IconX, IconClipboardList, IconKey, IconPencil, IconPlugConnected, IconHelpCircle, } from "@tabler/icons-react";
5
5
  import Placeholder from "@tiptap/extension-placeholder";
6
6
  import { useEditor, EditorContent } from "@tiptap/react";
7
7
  import StarterKit from "@tiptap/starter-kit";
8
8
  import { useState, useRef, useEffect, useCallback, useImperativeHandle, useMemo, } from "react";
9
- import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
9
+ import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, } from "../ui/popover.js";
10
10
  import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip.js";
11
11
  import { ComposerPlusMenu } from "./ComposerPlusMenu.js";
12
12
  import { getComposerDraftKey } from "./draft-key.js";
@@ -14,6 +14,7 @@ import { FileReference } from "./extensions/FileReference.js";
14
14
  import { MentionReference } from "./extensions/MentionReference.js";
15
15
  import { SkillReference } from "./extensions/SkillReference.js";
16
16
  import { MentionPopover } from "./MentionPopover.js";
17
+ import { isClaudeCodeAgentId, isLunaModel, resolvePreferredAgentModel, } from "./model-selection.js";
17
18
  import { createPastedAttachmentFile, readClipboardPaste, shouldConvertClipboardToAttachment, } from "./pasted-text.js";
18
19
  import { AGENT_CHAT_INSERT_REFERENCE_EVENT, AGENT_CHAT_INSERT_REFERENCE_MESSAGE_TYPE, DEFAULT_REASONING_EFFORT, formatPromptContextItems, getReasoningEffortOptionsForModel, reasoningEffortLabel, resolveReasoningEffortSelection, useComposerRuntimeAdapters, } from "./runtime-adapters.js";
19
20
  import { useMentionSearch } from "./use-mention-search.js";
@@ -513,7 +514,7 @@ function ModeSelector({ mode, onChange, planModeDisabled = false, planModeDisabl
513
514
  setOpen(false);
514
515
  }, className: "flex w-full items-center gap-3 px-3 py-2 hover:bg-accent/50 text-start", children: [_jsx(IconPencil, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "font-medium text-foreground text-[13px]", children: t("agentChat.plan.act", { defaultValue: "Act" }) }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: t("agentChat.composer.actDescription", {
515
516
  defaultValue: "Use tools and make approved changes",
516
- }) })] }), mode === "build" && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }), _jsxs("button", { type: "button", disabled: planModeDisabled, title: planModeDisabled ? resolvedPlanModeDisabledReason : undefined, onClick: () => {
517
+ }) })] }), mode === "build" && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }), _jsxs("button", { type: "button", disabled: planModeDisabled, title: planModeDisabled ? resolvedPlanModeDisabledReason : undefined, onClick: () => {
517
518
  if (planModeDisabled)
518
519
  return;
519
520
  onChange("plan");
@@ -524,20 +525,48 @@ function ModeSelector({ mode, onChange, planModeDisabled = false, planModeDisabl
524
525
  ? resolvedPlanModeDisabledReason
525
526
  : t("agentChat.composer.planDescription", {
526
527
  defaultValue: "Read-only research and approval first",
527
- }) })] }), mode === "plan" && !planModeDisabled && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] })] })] }));
528
+ }) })] }), mode === "plan" && !planModeDisabled && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] })] })] }));
528
529
  }
529
530
  const FRIENDLY_MODEL_NAMES = {
530
531
  auto: "Default model",
531
532
  "codex-cli": "Codex",
533
+ "claude-cli": "Claude Code",
534
+ "pi-cli": "Pi",
535
+ "opencode-cli": "OpenCode",
532
536
  "claude-fable-5": "Fable 5",
533
537
  "kimi-k2-5": "Kimi K2.5",
534
538
  "deepseek-v3-1": "DeepSeek v3.1",
535
539
  "z-ai/glm-5.2": "GLM 5.2",
536
540
  };
541
+ const LOCAL_RUNTIME_ENGINES = new Set([
542
+ "codex-cli",
543
+ "claude-cli",
544
+ "pi-cli",
545
+ "opencode-cli",
546
+ ]);
547
+ function isOpenAiModelId(model) {
548
+ const normalizedModel = model.toLowerCase();
549
+ return (normalizedModel.startsWith("gpt-") ||
550
+ normalizedModel.startsWith("openai/gpt-"));
551
+ }
552
+ export function isOpenAiModelProviderGroup(group) {
553
+ const engine = group.engine.toLowerCase();
554
+ const label = group.label.toLowerCase();
555
+ if (engine === "codex-cli") {
556
+ return group.models.some(isOpenAiModelId);
557
+ }
558
+ return (engine.includes("openai") ||
559
+ label.includes("openai") ||
560
+ group.models.some(isOpenAiModelId));
561
+ }
562
+ const HARNESS_AGENTS_DOCS_URL = "https://www.agent-native.com/docs/harness-agents";
537
563
  export const MODEL_SELECTOR_POPOVER_STYLE = {
538
564
  fontSize: 13,
539
565
  maxHeight: "min(500px, var(--radix-popover-content-available-height, 500px))",
540
566
  };
567
+ const MODEL_SELECTOR_POPOVER_CLASS = "box-border w-64 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none";
568
+ const PICKER_HELP_BUTTON_CLASS = "flex size-3 shrink-0 items-center justify-center rounded text-muted-foreground/60 hover:text-foreground";
569
+ const PICKER_HELP_ICON_CLASS = "size-2";
541
570
  export function shouldShowModelSelectorSkeleton(isLoading, engineCount) {
542
571
  return isLoading && engineCount === 0;
543
572
  }
@@ -712,21 +741,25 @@ function ModelCostTier({ model }) {
712
741
  : tier === 2
713
742
  ? t("agentChat.composer.costMedium", { defaultValue: "Medium cost" })
714
743
  : t("agentChat.composer.costHigher", { defaultValue: "Higher cost" });
715
- return (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", className: "shrink-0 text-[11px] tabular-nums text-muted-foreground/60", children: "$".repeat(tier) }), _jsx("span", { className: "sr-only", children: costLabel })] }));
744
+ return _jsx("span", { className: "sr-only", children: costLabel });
716
745
  }
717
746
  export function getComposerReasoningEffortOptions(model) {
718
747
  return model === "auto"
719
748
  ? ["low", "medium", "high", "xhigh", "max"]
720
749
  : getReasoningEffortOptionsForModel(model);
721
750
  }
722
- function ModelSelector({ model, effort, engines, showAutoModelOption = true, modelListLoading = false, onChange, onEffortChange, providerConnectStatusEnabled = true, onConnectProvider, onConnectLocalRuntime, imageModel, }) {
751
+ function ModelSelector({ model, effort, engines, agents, selectedAgent, hostedHarness = false, showAutoModelOption = true, modelListLoading = false, open: controlledOpen, onChange, onEffortChange, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled = true, onConnectProvider, onConnectLocalRuntime, imageModel, }) {
723
752
  const adapters = useComposerRuntimeAdapters();
724
753
  const t = adapters.translate;
725
754
  const reasoning = adapters.models?.reasoning;
726
755
  const defaultEffort = reasoning?.defaultEffort ?? DEFAULT_REASONING_EFFORT;
727
- const [open, setOpen] = useState(false);
756
+ const [internalOpen, setInternalOpen] = useState(false);
757
+ const open = controlledOpen ?? internalOpen;
758
+ const isClaudeCodeAgent = isClaudeCodeAgentId(selectedAgent);
728
759
  const autoModelGroup = showAutoModelOption
729
- ? engines.find((group) => group.models.includes("auto"))
760
+ ? isClaudeCodeAgent
761
+ ? undefined
762
+ : engines.find((group) => group.models.includes("auto"))
730
763
  : undefined;
731
764
  const providerGroups = useMemo(() => engines
732
765
  .map((group) => ({
@@ -734,164 +767,241 @@ function ModelSelector({ model, effort, engines, showAutoModelOption = true, mod
734
767
  models: group.models.filter((candidate) => candidate !== "auto"),
735
768
  }))
736
769
  .filter((group) => group.models.length > 0), [engines]);
770
+ const isCodexAgent = selectedAgent === "codex" || selectedAgent === "codex-cli";
771
+ const modelProviderGroups = useMemo(() => {
772
+ const hasCodexLocalGroup = providerGroups.some((group) => group.engine === "codex-cli");
773
+ const groups = providerGroups.flatMap((group) => {
774
+ if (group.engine === "codex-cli") {
775
+ return isCodexAgent && isOpenAiModelProviderGroup(group) ? [group] : [];
776
+ }
777
+ if (isCodexAgent &&
778
+ hasCodexLocalGroup &&
779
+ group.engine === "ai-sdk:openai") {
780
+ return [];
781
+ }
782
+ if (LOCAL_RUNTIME_ENGINES.has(group.engine))
783
+ return [];
784
+ if (!isCodexAgent)
785
+ return [group];
786
+ if (!isOpenAiModelProviderGroup(group))
787
+ return [];
788
+ const isExplicitOpenAiProvider = group.engine.toLowerCase().includes("openai") ||
789
+ group.label.toLowerCase().includes("openai");
790
+ const models = isExplicitOpenAiProvider
791
+ ? group.models
792
+ : group.models.filter(isOpenAiModelId);
793
+ return models.length > 0 ? [{ ...group, models }] : [];
794
+ });
795
+ if (!isClaudeCodeAgent)
796
+ return groups;
797
+ return groups
798
+ .map((group) => ({
799
+ ...group,
800
+ models: group.models.filter((candidate) => !isLunaModel(candidate)),
801
+ }))
802
+ .filter((group) => group.models.length > 0);
803
+ }, [isClaudeCodeAgent, isCodexAgent, providerGroups]);
804
+ const preferredAgentModel = useMemo(() => resolvePreferredAgentModel(selectedAgent, providerGroups), [providerGroups, selectedAgent]);
805
+ useEffect(() => {
806
+ if (!isClaudeCodeAgent || !isLunaModel(model) || !preferredAgentModel) {
807
+ return;
808
+ }
809
+ if (preferredAgentModel.model === model &&
810
+ preferredAgentModel.engine ===
811
+ engines.find((group) => group.models.includes(model))?.engine) {
812
+ return;
813
+ }
814
+ onChange(preferredAgentModel.model, preferredAgentModel.engine);
815
+ }, [engines, isClaudeCodeAgent, model, onChange, preferredAgentModel]);
737
816
  const effortOptions = reasoning?.getOptionsForModel?.(model) ??
738
817
  getComposerReasoningEffortOptions(model);
739
818
  const selectedEffort = reasoning?.resolve?.(model, effort) ??
740
819
  resolveReasoningEffortSelection(model, effort ?? defaultEffort);
741
820
  const effortLabel = useCallback((value) => localizedReasoningEffortLabel(t, value, (reasoning?.label ?? reasoningEffortLabel)(value)), [reasoning?.label, t]);
742
- // Collapse non-selected families by default. The family containing the
743
- // currently-selected model stays expanded so the user sees their pick at
744
- // a glance; clicking another family's header expands it inline.
745
- const selectedGroupKey = useMemo(() => {
746
- const found = providerGroups.find((g) => g.models.includes(model));
747
- return found ? `${found.engine}:${found.label}` : null;
748
- }, [model, providerGroups]);
749
- const [expandedGroups, setExpandedGroups] = useState(() => new Set(selectedGroupKey ? [selectedGroupKey] : []));
750
- // Reset expansion when the popover re-opens so the picker always lands
751
- // on the "selected family expanded, others collapsed" view.
752
- useEffect(() => {
753
- if (open) {
754
- setExpandedGroups(new Set(selectedGroupKey ? [selectedGroupKey] : []));
755
- }
756
- }, [open, selectedGroupKey]);
757
- const toggleGroup = useCallback((key) => {
758
- setExpandedGroups((prev) => {
759
- const next = new Set(prev);
760
- if (next.has(key))
761
- next.delete(key);
762
- else
763
- next.add(key);
764
- return next;
765
- });
766
- }, []);
767
- // The effort list is collapsed by default — it's a secondary
768
- // control most users don't touch, so it stays tucked behind a header that
769
- // reveals the current effort at a glance. Reset to collapsed on each open.
770
- const [effortExpanded, setEffortExpanded] = useState(false);
771
- useEffect(() => {
772
- if (open)
773
- setEffortExpanded(false);
774
- }, [open]);
775
- // The optional image-model section follows the same collapsed-by-default
776
- // pattern; the current selection shows next to the header.
777
- const [imageExpanded, setImageExpanded] = useState(false);
778
- useEffect(() => {
779
- if (open)
780
- setImageExpanded(false);
781
- }, [open]);
782
- const imageModelLabel = imageModel?.options.find((option) => option.value === imageModel.value)
783
- ?.label ?? imageModel?.value;
821
+ const selectedAgentOption = agents?.find((agent) => agent.id === (selectedAgent ?? "default"));
822
+ const selectedAgentLabel = selectedAgentOption?.label ?? "Default";
823
+ const selectedModelLabel = friendlyModelName(model, t).replace(/^GPT-/, "");
824
+ const [detailSection, setDetailSection] = useState(null);
825
+ const resolvedSection = detailSection ?? "model";
826
+ const setPickerOpen = useCallback((nextOpen) => {
827
+ if (controlledOpen === undefined)
828
+ setInternalOpen(nextOpen);
829
+ if (nextOpen)
830
+ setDetailSection(null);
831
+ onModelSelectorOpenChange?.(nextOpen);
832
+ }, [controlledOpen, onModelSelectorOpenChange]);
833
+ const visibleProviderGroups = modelProviderGroups;
784
834
  const showModelListSkeleton = shouldShowModelSelectorSkeleton(modelListLoading, engines.length);
785
- // When Builder.io isn't connected, surface a one-click connect path
786
- // it unlocks every model family (Claude, OpenAI, Gemini) without the
787
- // user having to paste individual API keys.
835
+ // Keep setup actions beside model choices while any visible provider still
836
+ // needs configuration. The model rows remain visible so the user can see
837
+ // what becomes available after connecting or adding a key.
788
838
  const builderFlow = adapters.builder.useConnectFlow({
789
839
  enabled: providerConnectStatusEnabled,
790
840
  trackingSource: "composer_builder_cta",
791
841
  });
792
842
  const hasConfiguredBuilderModels = providerGroups.some((group) => group.engine === "builder" && group.configured);
793
843
  const hasConnectedSubscription = providerGroups.some((group) => group.configured && group.isSubscription);
794
- const showBuilderCta = (builderFlow.hasFetchedStatus ||
795
- (!providerConnectStatusEnabled && !!onConnectProvider)) &&
796
- !builderFlow.configured &&
797
- !builderFlow.envManaged &&
798
- !hasConfiguredBuilderModels &&
799
- !hasConnectedSubscription;
800
- const onlyConnectPathAvailable = shouldShowOnlyConnectPath(showBuilderCta, providerGroups);
844
+ const hasUnconfiguredVisibleModels = modelProviderGroups.some((group) => !group.configured);
845
+ const showBuilderAction = hasUnconfiguredVisibleModels &&
846
+ (Boolean(onConnectProvider) ||
847
+ (providerConnectStatusEnabled &&
848
+ !builderFlow.configured &&
849
+ !builderFlow.envManaged &&
850
+ !hasConfiguredBuilderModels &&
851
+ !hasConnectedSubscription));
852
+ const showAddKeysAction = hasUnconfiguredVisibleModels;
853
+ const showProviderActions = showBuilderAction || showAddKeysAction;
854
+ const onlyConnectPathAvailable = shouldShowOnlyConnectPath(showBuilderAction, providerGroups) &&
855
+ modelProviderGroups.length === 0;
801
856
  const openLlmSettings = useCallback(() => {
802
857
  try {
803
858
  window.location.hash = "llm";
804
859
  }
805
860
  catch { }
806
861
  window.dispatchEvent(new CustomEvent("agent-panel:open-settings"));
807
- setOpen(false);
808
- }, []);
862
+ setPickerOpen(false);
863
+ }, [setPickerOpen]);
809
864
  const connectLocalRuntime = useCallback((engine) => {
810
865
  onConnectLocalRuntime?.(engine);
811
- setOpen(false);
812
- }, [onConnectLocalRuntime]);
813
- return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-agent-composer-slot": "model-button", "aria-label": `${t("agentChat.composer.model", {
866
+ setPickerOpen(false);
867
+ }, [onConnectLocalRuntime, setPickerOpen]);
868
+ return (_jsxs(Popover, { open: open, onOpenChange: setPickerOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-agent-composer-slot": "model-button", "aria-label": `${t("agentChat.composer.model", {
814
869
  defaultValue: "Model",
815
870
  })}: ${friendlyModelName(model, t)}${effortOptions.length > 0
816
- ? `. ${t("agentChat.composer.reasoning", {
817
- defaultValue: "Reasoning",
871
+ ? `. ${t("agentChat.composer.effort", {
872
+ defaultValue: "Effort",
818
873
  })}: ${effortLabel(selectedEffort)}`
819
- : ""}`, className: "agent-composer-model-button flex min-w-0 max-w-[10.5rem] shrink items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground", children: [_jsx("span", { className: "min-w-0 truncate", children: compactComposerModelName(model, t) }), effortOptions.length > 0 && (_jsxs("span", { className: "agent-composer-model-effort min-w-0 shrink truncate text-muted-foreground/70", children: ["\u00B7 ", compactComposerReasoningEffortLabel(selectedEffort, t)] })), _jsx(IconChevronDown, { className: "h-3 w-3 shrink-0 opacity-60" })] }) }), _jsxs(PopoverContent, { side: "top", align: "end", sideOffset: 6, collisionPadding: 8, "data-agent-native-composer-popover": "true", className: "z-[260] box-border w-72 overflow-y-auto rounded-lg border-border p-0 py-1 shadow-lg", style: MODEL_SELECTOR_POPOVER_STYLE, children: [showBuilderCta && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => {
820
- if (onConnectProvider) {
821
- onConnectProvider();
822
- }
823
- else {
824
- builderFlow.start();
825
- }
826
- }, disabled: !onConnectProvider && builderFlow.connecting, className: "flex w-full items-start gap-2 px-3 py-2 text-start hover:bg-accent/50 disabled:opacity-60", children: [_jsx(IconPlugConnected, { className: "h-4 w-4 shrink-0 mt-0.5 text-blue-500" }), _jsxs("span", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: !onConnectProvider && builderFlow.connecting
827
- ? t("agentPanel.connectingBuilder", {
828
- defaultValue: "Connecting Builder.io…",
829
- })
830
- : t("agentPanel.connectBuilderIo", {
831
- defaultValue: "Connect Builder.io",
832
- }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.builderModelCredits", {
833
- defaultValue: "Free credits for Claude, OpenAI & Gemini",
834
- }) })] })] }), !onConnectProvider && builderFlow.error && (_jsx("p", { role: "alert", className: "px-3 pb-2 ps-9 text-[11px] text-destructive", children: builderFlow.error })), _jsxs("button", { type: "button", onClick: openLlmSettings, className: "flex w-full items-start gap-2 px-3 py-2 text-start hover:bg-accent/50", children: [_jsx(IconKey, { className: "mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: t("agentPanel.addOwnKeys", {
835
- defaultValue: "Add your own keys",
836
- }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.configureProviderKeys", {
837
- defaultValue: "Choose a cloud, gateway, or local provider",
838
- }) })] })] }), !onlyConnectPathAvailable && (_jsx("div", { className: "my-1 border-t border-border" }))] })), imageModel && imageModel.options.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex items-center hover:bg-accent/30", children: _jsxs("button", { type: "button", "aria-expanded": imageExpanded, onClick: () => setImageExpanded((prev) => !prev), className: "flex flex-1 min-w-0 items-center gap-1.5 px-2 py-1.5 cursor-pointer text-start", children: [imageExpanded ? (_jsx(IconChevronDown, { className: "h-3 w-3 shrink-0 text-muted-foreground" })) : (_jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" })), _jsx("span", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0", children: imageModel.label ??
839
- t("agentChat.composer.imageModel", {
840
- defaultValue: "Image model",
841
- }) }), !imageExpanded && imageModelLabel && (_jsx("span", { className: "text-[11px] text-muted-foreground/80 truncate", children: imageModelLabel }))] }) }), imageExpanded &&
842
- imageModel.options.map((option) => (_jsxs("button", { type: "button", onClick: () => {
843
- imageModel.onChange(option.value);
844
- setImageExpanded(false);
845
- }, className: "flex w-full items-center gap-3 ps-7 pe-3 py-1.5 text-start hover:bg-accent/50", children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: option.label }), option.value === imageModel.value && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }, option.value))), _jsx("div", { className: "my-1 border-t border-border" })] })), showModelListSkeleton && _jsx(ModelSelectorSkeleton, {}), autoModelGroup && !onlyConnectPathAvailable && (_jsxs("button", { type: "button", onClick: () => {
846
- onChange("auto", autoModelGroup.engine);
847
- setOpen(false);
848
- }, className: "flex w-full items-center gap-3 px-3 py-1.5 text-start hover:bg-accent/50", children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: t("agentChat.composer.auto", { defaultValue: "Auto" }) }), model === "auto" && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] })), autoModelGroup &&
849
- providerGroups.length > 0 &&
850
- !onlyConnectPathAvailable && (_jsx("div", { className: "my-1 border-t border-border" })), !onlyConnectPathAvailable &&
851
- providerGroups.map((group) => {
852
- const models = latestModelsOnly(group.models);
853
- const groupKey = `${group.engine}:${group.label}`;
854
- const isExpanded = expandedGroups.has(groupKey);
855
- const ChevronIcon = isExpanded ? IconChevronDown : IconChevronRight;
856
- const isLocalRuntime = group.engine === "codex-cli" || group.engine === "claude-cli";
857
- const canConnectLocalRuntime = isLocalRuntime && Boolean(onConnectLocalRuntime);
858
- const statusLabel = group.statusLabel ??
859
- (!group.configured
860
- ? canConnectLocalRuntime
861
- ? t("agentChat.auth.logIn", { defaultValue: "Sign in" })
862
- : t("agentChat.composer.needsApiKey", {
863
- defaultValue: "needs API key",
864
- })
865
- : undefined);
866
- return (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center hover:bg-accent/30", children: [_jsxs("button", { type: "button", "aria-expanded": isExpanded, onClick: () => toggleGroup(groupKey), className: "flex flex-1 min-w-0 items-center gap-1.5 px-2 py-1.5 cursor-pointer text-start", children: [_jsx(ChevronIcon, { className: "h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" }), _jsx("span", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0", children: group.label }), !isExpanded && groupKey === selectedGroupKey && (_jsx("span", { className: "text-[11px] text-muted-foreground/80 truncate", children: friendlyModelName(model, t) }))] }), !group.configured && statusLabel && (_jsx("button", { type: "button", className: "ms-auto max-w-[9rem] shrink-0 text-end text-[10px] text-muted-foreground/60 hover:text-foreground cursor-pointer pe-3 py-1.5", onClick: () => canConnectLocalRuntime
867
- ? connectLocalRuntime(group.engine)
868
- : openLlmSettings(), children: statusLabel })), group.configured && statusLabel && (_jsx("span", { className: "ms-auto max-w-[9rem] shrink-0 pe-3 text-end text-[10px] text-muted-foreground/70", children: statusLabel }))] }), isExpanded &&
869
- models.map((m) => (_jsxs("button", { type: "button", onClick: () => {
870
- if (!group.configured) {
871
- if (canConnectLocalRuntime) {
872
- connectLocalRuntime(group.engine);
873
- }
874
- else {
875
- openLlmSettings();
876
- }
877
- return;
878
- }
879
- onChange(m, group.engine);
880
- const nextOptions = getReasoningEffortOptionsForModel(m);
881
- if (nextOptions.length > 0 &&
882
- !nextOptions.includes(selectedEffort)) {
883
- onEffortChange?.(defaultEffort);
884
- }
885
- setOpen(false);
886
- }, className: `flex w-full items-center gap-3 ps-7 pe-3 py-1.5 text-start ${group.configured
887
- ? "hover:bg-accent/50"
888
- : "opacity-40 cursor-default"}`, children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: friendlyModelName(m, t) }), _jsx(ModelCostTier, { model: m }), m === model && group.configured && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }, m)))] }, groupKey));
889
- }), !showModelListSkeleton &&
890
- !onlyConnectPathAvailable &&
891
- effortOptions.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "my-1 border-t border-border" }), _jsx("div", { className: "flex items-center hover:bg-accent/30", children: _jsxs("button", { type: "button", "aria-expanded": effortExpanded, onClick: () => setEffortExpanded((prev) => !prev), className: "flex flex-1 min-w-0 items-center gap-1.5 px-2 py-1.5 cursor-pointer text-start", children: [effortExpanded ? (_jsx(IconChevronDown, { className: "h-3 w-3 shrink-0 text-muted-foreground" })) : (_jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" })), _jsx("span", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0", children: t("agentChat.composer.reasoning", {
892
- defaultValue: "Reasoning",
893
- }) }), !effortExpanded && (_jsx("span", { className: "text-[11px] text-muted-foreground/80 truncate", children: effortLabel(selectedEffort) }))] }) }), effortExpanded &&
894
- effortOptions.map((option) => (_jsxs("button", { type: "button", onClick: () => onEffortChange?.(option), className: "flex w-full items-center gap-3 ps-7 pe-3 py-1.5 text-start hover:bg-accent/50", children: [_jsx("span", { className: "flex-1 min-w-0 text-[13px] text-foreground truncate", children: effortLabel(option) }), option === selectedEffort && (_jsx(IconCheck, { className: "h-3.5 w-3.5 shrink-0 text-blue-500" }))] }, option)))] }))] })] }));
874
+ : ""}${selectedAgentOption && selectedAgentOption.id !== "default"
875
+ ? `. Agent: ${selectedAgentLabel}`
876
+ : ""}`, className: "agent-composer-model-button flex min-w-0 max-w-[10.5rem] shrink items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground", children: [_jsx("span", { className: "min-w-0 truncate", children: selectedAgentOption && selectedAgentOption.id !== "default"
877
+ ? selectedAgentLabel
878
+ : compactComposerModelName(model, t) }), effortOptions.length > 0 && (_jsxs("span", { className: "agent-composer-model-effort min-w-0 shrink truncate text-muted-foreground/70", children: ["\u00B7 ", compactComposerReasoningEffortLabel(selectedEffort, t)] })), _jsx(IconChevronDown, { className: "h-3 w-3 shrink-0 opacity-60" })] }) }), _jsx(PopoverContent, { side: "top", align: "end", sideOffset: 6, collisionPadding: 8, "data-agent-native-composer-popover": "true", className: `z-[260] overflow-visible ${MODEL_SELECTOR_POPOVER_CLASS}`, style: MODEL_SELECTOR_POPOVER_STYLE, children: _jsxs(Popover, { open: detailSection !== null, onOpenChange: () => undefined, children: [_jsx(PopoverAnchor, { asChild: true, children: _jsxs("div", { className: "flex flex-col", role: "tablist", "aria-label": t("agentChat.composer.pickerSections", {
879
+ defaultValue: "Picker sections",
880
+ }), children: [agents && agents.length > 0 && (_jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "agent", onClick: () => setDetailSection("agent"), onMouseEnter: () => setDetailSection("agent"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "agent"
881
+ ? "bg-accent text-foreground"
882
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsxs("span", { className: "flex min-w-0 items-center", children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: "Agent" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { role: "img", "aria-label": t("agentChat.composer.harnessAgentHelp", {
883
+ defaultValue: "Learn about harness agents",
884
+ }), onClick: (event) => event.stopPropagation(), className: `ms-1.5 ${PICKER_HELP_BUTTON_CLASS}`, children: _jsx(IconHelpCircle, { "aria-hidden": "true", className: PICKER_HELP_ICON_CLASS, strokeWidth: 1.8 }) }) }), _jsxs(TooltipContent, { side: "right", className: "z-[400] max-w-xs", children: [_jsx("span", { className: "block", children: hostedHarness
885
+ ? t("agentChat.composer.hostedHarnessDescription", {
886
+ defaultValue: "Hosted mode uses app tools only. For full coding with a repository and shell, use Agent Native Desktop.",
887
+ })
888
+ : t("agentChat.composer.harnessAgentDescription", {
889
+ defaultValue: "Harnesses run their own coding loop and local tools.",
890
+ }) }), _jsx("a", { href: HARNESS_AGENTS_DOCS_URL, target: "_blank", rel: "noreferrer", className: "mt-1 block underline underline-offset-2 hover:no-underline", children: t("agentChat.composer.learnMoreHarnessAgents", {
891
+ defaultValue: "Learn more about harness agents",
892
+ }) })] })] })] }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: selectedAgentLabel }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] })), _jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "model", onClick: () => setDetailSection("model"), onMouseEnter: () => setDetailSection("model"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "model"
893
+ ? "bg-accent text-foreground"
894
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: "Model" }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: selectedModelLabel }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] }), effortOptions.length > 0 && (_jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "effort", onClick: () => setDetailSection("effort"), onMouseEnter: () => setDetailSection("effort"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "effort"
895
+ ? "bg-accent text-foreground"
896
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: t("agentChat.composer.effort", {
897
+ defaultValue: "Effort",
898
+ }) }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: effortLabel(selectedEffort) }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] }))] }) }), _jsx(PopoverContent, { side: "right", align: "start", sideOffset: 4, alignOffset: -8, collisionPadding: 8, className: `z-[320] overflow-visible ${MODEL_SELECTOR_POPOVER_CLASS}`, style: MODEL_SELECTOR_POPOVER_STYLE, children: _jsx("div", { className: "max-h-[min(500px,var(--radix-popover-content-available-height,500px))] overflow-y-auto", children: _jsxs("div", { className: "min-h-0 min-w-0", role: "tabpanel", "aria-label": resolvedSection, children: [resolvedSection === "agent" && agents && (_jsx("div", { className: "flex flex-col", children: agents.map((agent) => {
899
+ const isSelected = agent.id === (selectedAgent ?? "default");
900
+ const isConfigured = agent.configured !== false;
901
+ const canConnect = !isConfigured && Boolean(onConnectLocalRuntime);
902
+ const statusLabel = agent.statusLabel ??
903
+ (!isConfigured ? "Unavailable" : undefined);
904
+ return (_jsxs("div", { className: "group flex items-center rounded-md hover:bg-accent/30", children: [_jsxs("button", { type: "button", disabled: !isConfigured || !onAgentChange, "aria-current": isSelected ? "true" : undefined, onClick: () => {
905
+ if (!isConfigured)
906
+ return;
907
+ onAgentChange?.(agent.id);
908
+ setPickerOpen(false);
909
+ }, className: `flex min-w-0 flex-1 items-center gap-0.5 px-2 py-2 text-start ${isConfigured
910
+ ? "hover:bg-accent/50"
911
+ : "cursor-default opacity-50"}`, children: [_jsx("span", { className: `min-w-0 truncate text-[12px] ${isSelected
912
+ ? "text-foreground"
913
+ : "text-muted-foreground"}`, children: agent.label }), agent.description && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { role: "img", "aria-label": `${agent.label} details`, onClick: (event) => event.stopPropagation(), className: PICKER_HELP_BUTTON_CLASS, children: _jsx(IconHelpCircle, { "aria-hidden": "true", className: PICKER_HELP_ICON_CLASS, strokeWidth: 1.8 }) }) }), _jsx(TooltipContent, { side: "left", className: "z-[400] max-w-xs", children: agent.description })] })), _jsx("span", { className: "min-w-0 flex-1", "aria-hidden": "true" }), isSelected && isConfigured && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }), !isConfigured && statusLabel && (_jsx("button", { type: "button", disabled: !canConnect, className: "ms-auto max-w-[6rem] shrink-0 truncate px-2 py-2 text-end text-[10px] text-muted-foreground/70 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 hover:text-foreground focus-visible:opacity-100 disabled:cursor-default", onClick: () => {
914
+ if (canConnect)
915
+ connectLocalRuntime(agent.id);
916
+ }, children: statusLabel }))] }, agent.id));
917
+ }) })), resolvedSection === "model" && (_jsxs(_Fragment, { children: [showProviderActions && (_jsxs(_Fragment, { children: [showBuilderAction && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => {
918
+ if (onConnectProvider) {
919
+ onConnectProvider();
920
+ }
921
+ else {
922
+ builderFlow.start();
923
+ }
924
+ }, disabled: !onConnectProvider && builderFlow.connecting, className: "flex w-full items-start gap-2 rounded-md px-2 py-2 text-start hover:bg-accent/50 disabled:opacity-60", children: [_jsx(IconPlugConnected, { className: "mt-0.5 h-4 w-4 shrink-0 text-primary" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: !onConnectProvider && builderFlow.connecting
925
+ ? t("agentPanel.connectingBuilder", {
926
+ defaultValue: "Connecting Builder.io…",
927
+ })
928
+ : t("agentPanel.connectBuilderIo", {
929
+ defaultValue: "Connect Builder.io",
930
+ }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.builderModelCredits", {
931
+ defaultValue: "Free credits for Claude, OpenAI & Gemini",
932
+ }) })] })] }), !onConnectProvider && builderFlow.error && (_jsx("p", { role: "alert", className: "px-2 pb-2 ps-8 text-[11px] text-destructive", children: builderFlow.error }))] })), showAddKeysAction && (_jsxs("button", { type: "button", onClick: openLlmSettings, className: "flex w-full items-start gap-2 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx(IconKey, { className: "mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: t("agentPanel.addOwnKeys", {
933
+ defaultValue: "Add your own keys",
934
+ }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.configureProviderKeys", {
935
+ defaultValue: "Choose a cloud, gateway, or local provider",
936
+ }) })] })] }))] })), imageModel && imageModel.options.length > 0 && (_jsxs("div", { className: "mt-2 pt-1", children: [_jsx("div", { className: "px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: imageModel.label ??
937
+ t("agentChat.composer.imageModel", {
938
+ defaultValue: "Image model",
939
+ }) }), imageModel.options.map((option) => (_jsxs("button", { type: "button", onClick: () => {
940
+ imageModel.onChange(option.value);
941
+ setPickerOpen(false);
942
+ }, className: "flex w-full items-center gap-3 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${option.value === imageModel.value
943
+ ? "text-foreground"
944
+ : "text-muted-foreground"}`, children: option.label }), option.value === imageModel.value && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, option.value)))] })), showModelListSkeleton && _jsx(ModelSelectorSkeleton, {}), isCodexAgent &&
945
+ !showModelListSkeleton &&
946
+ !onlyConnectPathAvailable &&
947
+ modelProviderGroups.length === 0 && (_jsxs("button", { type: "button", onClick: openLlmSettings, className: "flex w-full items-center rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-muted-foreground", children: t("agentChat.composer.noOpenAiModels", {
948
+ defaultValue: "No OpenAI models configured",
949
+ }) }), _jsx("span", { className: "shrink-0 text-[11px] text-muted-foreground/70", children: "Configure" })] })), autoModelGroup && !onlyConnectPathAvailable && (_jsxs("button", { type: "button", onClick: () => {
950
+ onChange("auto", autoModelGroup.engine);
951
+ setPickerOpen(false);
952
+ }, className: "mt-1 flex w-full items-center gap-3 rounded-md px-2 py-1.5 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[13px] ${model === "auto"
953
+ ? "text-foreground"
954
+ : "text-muted-foreground"}`, children: t("agentChat.composer.auto", {
955
+ defaultValue: "Auto",
956
+ }) }), model === "auto" && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] })), !onlyConnectPathAvailable &&
957
+ visibleProviderGroups.map((group, groupIndex) => {
958
+ const models = latestModelsOnly(group.models);
959
+ const showProviderLabels = visibleProviderGroups.length > 1;
960
+ const isLocalRuntime = group.engine === "codex-cli" ||
961
+ group.engine === "claude-cli";
962
+ const canConnectLocalRuntime = isLocalRuntime && Boolean(onConnectLocalRuntime);
963
+ const statusLabel = group.statusLabel ??
964
+ (!group.configured
965
+ ? canConnectLocalRuntime
966
+ ? t("agentChat.auth.logIn", {
967
+ defaultValue: "Sign in",
968
+ })
969
+ : t("agentChat.composer.needsApiKey", {
970
+ defaultValue: "needs API key",
971
+ })
972
+ : undefined);
973
+ return (_jsxs("div", { className: showProviderLabels && groupIndex > 0
974
+ ? "mt-2 pt-1"
975
+ : "", children: [showProviderLabels && (_jsxs("div", { className: "group flex items-center px-2 py-1", children: [_jsx("span", { className: "shrink-0 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: group.label }), !group.configured && statusLabel && (_jsx("button", { type: "button", "aria-label": statusLabel, className: "ms-auto max-w-[9rem] shrink-0 cursor-pointer truncate px-0 py-1 text-end text-[10px] text-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 hover:text-foreground focus-visible:opacity-100", onClick: () => canConnectLocalRuntime
976
+ ? connectLocalRuntime(group.engine)
977
+ : openLlmSettings(), children: statusLabel })), group.configured && statusLabel && (_jsx("span", { className: "ms-auto max-w-[9rem] shrink-0 truncate py-1 text-end text-[10px] text-muted-foreground/70 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100", children: statusLabel }))] })), models.map((m) => {
978
+ const isSelected = m === model && group.configured;
979
+ return (_jsxs("button", { type: "button", onClick: () => {
980
+ if (!group.configured) {
981
+ if (canConnectLocalRuntime) {
982
+ connectLocalRuntime(group.engine);
983
+ }
984
+ else {
985
+ openLlmSettings();
986
+ }
987
+ return;
988
+ }
989
+ onChange(m, group.engine);
990
+ const nextOptions = getReasoningEffortOptionsForModel(m);
991
+ if (nextOptions.length > 0 &&
992
+ !nextOptions.includes(selectedEffort)) {
993
+ onEffortChange?.(defaultEffort);
994
+ }
995
+ setPickerOpen(false);
996
+ }, className: `group flex w-full items-center gap-3 rounded-md px-2 py-2 text-start ${group.configured
997
+ ? "hover:bg-accent/50"
998
+ : "cursor-default opacity-40"}`, children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${isSelected
999
+ ? "text-foreground"
1000
+ : "text-muted-foreground"}`, children: friendlyModelName(m, t) }), _jsx(ModelCostTier, { model: m }), !showProviderLabels && statusLabel && (_jsx("span", { className: "hidden max-w-[9rem] shrink-0 truncate text-[10px] text-muted-foreground/70 group-hover:inline", children: statusLabel })), isSelected && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, m));
1001
+ })] }, `${group.engine}:${group.label}`));
1002
+ })] })), resolvedSection === "effort" && effortOptions.length > 0 && (_jsx("div", { className: "flex flex-col", children: effortOptions.map((option) => (_jsxs("button", { type: "button", onClick: () => onEffortChange?.(option), className: "flex w-full items-center gap-3 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${option === selectedEffort
1003
+ ? "text-foreground"
1004
+ : "text-muted-foreground"}`, children: effortLabel(option) }), option === selectedEffort && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, option))) }))] }) }) })] }) })] }));
895
1005
  }
896
1006
  function ModelSelectorSkeleton() {
897
1007
  const t = useComposerRuntimeAdapters().translate;
@@ -901,7 +1011,7 @@ function ModelSelectorSkeleton() {
901
1011
  defaultValue: "Loading models…",
902
1012
  }) }), ["w-24", "w-32", "w-20", "w-28"].map((width, index) => (_jsxs("div", { className: "flex items-center gap-1.5 px-1 py-1.5", children: [_jsx(Skeleton, { className: "size-3 rounded-sm" }), _jsx(Skeleton, { className: `h-3 ${width}` })] }, index)))] }));
903
1013
  }
904
- export function TiptapComposer({ placeholder, disabled = false, maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES, documentAttachmentLimitLabel = "PDFs", focusRef, initialText, initialTextKey, onSubmit, onBeforeSubmit, clearOnSubmit = true, 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, selectedEffort, showAutoModelOption = true, availableModels, modelListLoading, onModelChange, onEffortChange, providerConnectStatusEnabled, onConnectProvider, onConnectLocalRuntime, imageModelMenu, draftScope, contextItems = [], onRemoveContextItem, plusMenuMode = "full", extensionTools = false, interceptBuildRequestsForBuilder = false, onAttachmentError, }) {
1014
+ export function TiptapComposer({ placeholder, disabled = false, maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES, documentAttachmentLimitLabel = "PDFs", focusRef, initialText, initialTextKey, onSubmit, onBeforeSubmit, clearOnSubmit = true, 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, selectedEffort, showAutoModelOption = true, modelSelectorOpen, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, hostedHarness, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled, onConnectProvider, onConnectLocalRuntime, imageModelMenu, draftScope, contextItems = [], onRemoveContextItem, plusMenuMode = "full", extensionTools = false, interceptBuildRequestsForBuilder = false, onAttachmentError, }) {
905
1015
  const adapters = useComposerRuntimeAdapters();
906
1016
  const t = adapters.translate;
907
1017
  const sendButtonTooltip = t(getComposerSendTooltipKey(willQueue), {
@@ -2116,6 +2226,6 @@ export function TiptapComposer({ placeholder, disabled = false, maxDocumentAttac
2116
2226
  defaultValue: "Remove {{name}} context",
2117
2227
  name: item.title,
2118
2228
  }), className: "ms-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconX, { className: "h-3 w-3" }) })] }, item.key)))] })), _jsx("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "editor-wrap", className: `agent-composer-editor-wrap ${composerMode || hasContextRows ? "px-2 pt-1 pb-1" : "px-2 pt-2 pb-1"}`, children: _jsx(EditorContent, { editor: editor, "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "editor", className: "agent-composer-editor aui-composer flex-1 min-w-0 [&_.ProseMirror]:outline-none [&_.ProseMirror_p]:m-0 px-0.5" }) }), voiceEnabled && _jsx(VoiceRecordingOverlay, { voice: voice }), _jsxs("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "toolbar", className: "agent-composer-toolbar flex items-center gap-1 px-2 py-1.5", children: [attachButton ??
2119
- (plusMenuMode === "hidden" ? null : (_jsx(ComposerPlusMenu, { onSelectMode: handleSelectMode, mode: plusMenuMode, extensionTools: extensionTools, onAttachmentError: onAttachmentError }))), toolbarSlot ?? modeControl, _jsx("div", { "data-agent-composer-slot": "toolbar-spacer", className: "flex-1" }), selectedModel && availableModels && onModelChange && (_jsx(ModelSelector, { model: selectedModel, effort: selectedEffort, engines: availableModels, showAutoModelOption: showAutoModelOption, modelListLoading: modelListLoading, onChange: onModelChange, onEffortChange: onEffortChange, providerConnectStatusEnabled: providerConnectStatusEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, 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: () => void submitComposer("immediate"), disabled: !canSend, "data-agent-composer-slot": "send-button", className: "agent-composer-send-button shrink-0 flex h-7 w-7 items-center justify-center rounded-md 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: _jsx(IconArrowUp, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: sendButtonTooltip })] }))] }))] }), _jsx(MentionPopover, { ref: popoverRef, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: filteredMentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
2229
+ (plusMenuMode === "hidden" ? null : (_jsx(ComposerPlusMenu, { onSelectMode: handleSelectMode, mode: plusMenuMode, extensionTools: extensionTools, onAttachmentError: onAttachmentError }))), toolbarSlot ?? modeControl, _jsx("div", { "data-agent-composer-slot": "toolbar-spacer", className: "flex-1" }), selectedModel && availableModels && onModelChange && (_jsx(ModelSelector, { model: selectedModel, open: modelSelectorOpen, effort: selectedEffort, engines: availableModels, agents: availableAgents, selectedAgent: selectedAgent, hostedHarness: hostedHarness, showAutoModelOption: showAutoModelOption, modelListLoading: modelListLoading, onChange: onModelChange, onEffortChange: onEffortChange, onAgentChange: onAgentChange, onModelSelectorOpenChange: onModelSelectorOpenChange, providerConnectStatusEnabled: providerConnectStatusEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, 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: () => void submitComposer("immediate"), disabled: !canSend, "data-agent-composer-slot": "send-button", className: "agent-composer-send-button shrink-0 flex h-7 w-7 items-center justify-center rounded-md 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: _jsx(IconArrowUp, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: sendButtonTooltip })] }))] }))] }), _jsx(MentionPopover, { ref: popoverRef, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: filteredMentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
2120
2230
  }
2121
2231
  //# sourceMappingURL=TiptapComposer.js.map