@invergent/agent-chat-react 1.9.8 → 1.10.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.
package/dist/index.cjs CHANGED
@@ -3418,7 +3418,7 @@ function Textarea({ className, ...props }) {
3418
3418
  {
3419
3419
  "data-slot": "textarea",
3420
3420
  className: cn(
3421
- "flex field-sizing-content min-h-16 w-full resize-none rounded-none border border-transparent border-b-input bg-transparent px-0 py-3 text-base transition-[color,border-color] outline-none placeholder:text-muted-foreground focus-visible:border-b-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-b-destructive md:text-sm dark:aria-invalid:border-b-destructive/50",
3421
+ "flex field-sizing-content min-h-16 w-full resize-none rounded-none border border-transparent border-b-input bg-transparent px-0 py-3 text-base transition-[color,border-color] outline-none placeholder:text-muted-foreground focus-visible:border-b-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-b-destructive dark:aria-invalid:border-b-destructive/50",
3422
3422
  className
3423
3423
  ),
3424
3424
  ...props
@@ -4689,7 +4689,7 @@ function CommandInput({
4689
4689
  className,
4690
4690
  ...props
4691
4691
  }) {
4692
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "command-input-wrapper", className: "p-1", children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: "border-transparent border-b-input bg-transparent px-3", children: [
4692
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "command-input-wrapper", className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: "rounded-lg border-transparent bg-muted px-3", children: [
4693
4693
  /* @__PURE__ */ jsxRuntime.jsx(
4694
4694
  cmdk.Command.Input,
4695
4695
  {
@@ -4733,35 +4733,6 @@ function CommandEmpty({
4733
4733
  }
4734
4734
  );
4735
4735
  }
4736
- function CommandGroup({
4737
- className,
4738
- ...props
4739
- }) {
4740
- return /* @__PURE__ */ jsxRuntime.jsx(
4741
- cmdk.Command.Group,
4742
- {
4743
- "data-slot": "command-group",
4744
- className: cn(
4745
- "overflow-hidden p-1.5 text-foreground **:[[cmdk-group-heading]]:px-3 **:[[cmdk-group-heading]]:py-2 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-semibold **:[[cmdk-group-heading]]:tracking-wider **:[[cmdk-group-heading]]:text-muted-foreground **:[[cmdk-group-heading]]:uppercase",
4746
- className
4747
- ),
4748
- ...props
4749
- }
4750
- );
4751
- }
4752
- function CommandSeparator({
4753
- className,
4754
- ...props
4755
- }) {
4756
- return /* @__PURE__ */ jsxRuntime.jsx(
4757
- cmdk.Command.Separator,
4758
- {
4759
- "data-slot": "command-separator",
4760
- className: cn("-mx-1.5 my-1.5 h-px bg-border/50", className),
4761
- ...props
4762
- }
4763
- );
4764
- }
4765
4736
  function CommandItem({
4766
4737
  className,
4767
4738
  children,
@@ -4772,7 +4743,7 @@ function CommandItem({
4772
4743
  {
4773
4744
  "data-slot": "command-item",
4774
4745
  className: cn(
4775
- "group/command-item relative flex cursor-default items-center gap-2 rounded-none px-3 py-2 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 data-selected:*:[svg]:text-foreground",
4746
+ "group/command-item relative flex cursor-default items-center gap-2 rounded-none px-3 py-2 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-muted data-[selected=true]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 data-[selected=true]:*:[svg]:text-foreground",
4776
4747
  className
4777
4748
  ),
4778
4749
  ...props,
@@ -4784,95 +4755,6 @@ function CommandItem({
4784
4755
  );
4785
4756
  }
4786
4757
 
4787
- // src/components/ui/dropdown-menu.tsx
4788
- init_utils();
4789
- function DropdownMenu({
4790
- ...props
4791
- }) {
4792
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.DropdownMenu.Root, { "data-slot": "dropdown-menu", ...props });
4793
- }
4794
- function DropdownMenuTrigger({
4795
- ...props
4796
- }) {
4797
- return /* @__PURE__ */ jsxRuntime.jsx(
4798
- radixUi.DropdownMenu.Trigger,
4799
- {
4800
- "data-slot": "dropdown-menu-trigger",
4801
- ...props
4802
- }
4803
- );
4804
- }
4805
- function DropdownMenuContent({
4806
- className,
4807
- align = "start",
4808
- sideOffset = 4,
4809
- ...props
4810
- }) {
4811
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.DropdownMenu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4812
- radixUi.DropdownMenu.Content,
4813
- {
4814
- "data-slot": "dropdown-menu-content",
4815
- sideOffset,
4816
- align,
4817
- className: cn("z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-48 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-none bg-popover p-1.5 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
4818
- ...props
4819
- }
4820
- ) });
4821
- }
4822
- function DropdownMenuItem({
4823
- className,
4824
- inset,
4825
- variant = "default",
4826
- ...props
4827
- }) {
4828
- return /* @__PURE__ */ jsxRuntime.jsx(
4829
- radixUi.DropdownMenu.Item,
4830
- {
4831
- "data-slot": "dropdown-menu-item",
4832
- "data-inset": inset,
4833
- "data-variant": variant,
4834
- className: cn(
4835
- "group/dropdown-menu-item relative flex cursor-default items-center gap-2.5 rounded-none px-3 py-2 text-xs font-medium tracking-wider uppercase outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-9.5 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 data-[variant=destructive]:*:[svg]:text-destructive",
4836
- className
4837
- ),
4838
- ...props
4839
- }
4840
- );
4841
- }
4842
-
4843
- // src/components/ui/hover-card.tsx
4844
- init_utils();
4845
- function HoverCard({
4846
- ...props
4847
- }) {
4848
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.HoverCard.Root, { "data-slot": "hover-card", ...props });
4849
- }
4850
- function HoverCardTrigger({
4851
- ...props
4852
- }) {
4853
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.HoverCard.Trigger, { "data-slot": "hover-card-trigger", ...props });
4854
- }
4855
- function HoverCardContent({
4856
- className,
4857
- align = "center",
4858
- sideOffset = 4,
4859
- ...props
4860
- }) {
4861
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.HoverCard.Portal, { "data-slot": "hover-card-portal", children: /* @__PURE__ */ jsxRuntime.jsx(
4862
- radixUi.HoverCard.Content,
4863
- {
4864
- "data-slot": "hover-card-content",
4865
- align,
4866
- sideOffset,
4867
- className: cn(
4868
- "z-50 w-72 origin-(--radix-hover-card-content-transform-origin) bg-popover p-4 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
4869
- className
4870
- ),
4871
- ...props
4872
- }
4873
- ) });
4874
- }
4875
-
4876
4758
  // src/components/ui/spinner.tsx
4877
4759
  init_utils();
4878
4760
  function Spinner({ className, ...props }) {
@@ -5029,24 +4911,6 @@ var usePromptInputAttachments = () => {
5029
4911
  return context;
5030
4912
  };
5031
4913
  var LocalReferencedSourcesContext = react.createContext(null);
5032
- var PromptInputActionAddAttachments = ({
5033
- label = "Add photos or files",
5034
- ...props
5035
- }) => {
5036
- const attachments = usePromptInputAttachments();
5037
- const handleSelect = react.useCallback(
5038
- (e) => {
5039
- e.preventDefault();
5040
- attachments.openFileDialog();
5041
- },
5042
- [attachments]
5043
- );
5044
- return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { ...props, onSelect: handleSelect, children: [
5045
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImageIcon, { className: "mr-2 size-4" }),
5046
- " ",
5047
- label
5048
- ] });
5049
- };
5050
4914
  var PromptInput = ({
5051
4915
  className,
5052
4916
  accept,
@@ -5382,7 +5246,7 @@ var PromptInput = ({
5382
5246
  onSubmit: handleSubmit,
5383
5247
  ref: formRef,
5384
5248
  ...props,
5385
- children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup, { className: "overflow-hidden", children })
5249
+ children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup, { className: "overflow-hidden rounded-3xl border border-input bg-white px-3 py-1 shadow-sm dark:bg-card dark:shadow-none dark:ring-1 dark:ring-white/5 has-[textarea]:rounded-3xl has-[>[data-align=block-end]]:rounded-3xl has-[>[data-align=block-start]]:rounded-3xl", children })
5386
5250
  }
5387
5251
  )
5388
5252
  ] });
@@ -5472,7 +5336,7 @@ var PromptInputTextarea = ({
5472
5336
  return /* @__PURE__ */ jsxRuntime.jsx(
5473
5337
  InputGroupTextarea,
5474
5338
  {
5475
- className: cn("field-sizing-content max-h-48 min-h-16", className),
5339
+ className: cn("field-sizing-content max-h-48 min-h-16 px-1.5 py-3", className),
5476
5340
  name: "message",
5477
5341
  onCompositionEnd: handleCompositionEnd,
5478
5342
  onCompositionStart: handleCompositionStart,
@@ -5516,7 +5380,11 @@ var PromptInputButton = ({
5516
5380
  const button = /* @__PURE__ */ jsxRuntime.jsx(
5517
5381
  InputGroupButton,
5518
5382
  {
5519
- className: cn(className),
5383
+ className: cn(
5384
+ "rounded-sm border border-input/70 text-foreground hover:bg-accent",
5385
+ newSize === "icon-sm" && "size-9",
5386
+ className
5387
+ ),
5520
5388
  size: newSize,
5521
5389
  type: "button",
5522
5390
  variant,
@@ -5537,19 +5405,9 @@ var PromptInputButton = ({
5537
5405
  ] })
5538
5406
  ] });
5539
5407
  };
5540
- var PromptInputActionMenu = (props) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu, { ...props });
5541
- var PromptInputActionMenuTrigger = ({
5542
- className,
5543
- children,
5544
- ...props
5545
- }) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(PromptInputButton, { className, ...props, children: children ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "size-4" }) }) });
5546
- var PromptInputActionMenuContent = ({
5547
- className,
5548
- ...props
5549
- }) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "start", className: cn(className), ...props });
5550
5408
  var PromptInputSubmit = ({
5551
5409
  className,
5552
- variant = "default",
5410
+ variant = "secondary",
5553
5411
  size = "icon-sm",
5554
5412
  status,
5555
5413
  onStop,
@@ -5558,11 +5416,11 @@ var PromptInputSubmit = ({
5558
5416
  ...props
5559
5417
  }) => {
5560
5418
  const isGenerating = status === "submitted" || status === "streaming";
5561
- let Icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CornerDownLeftIcon, { className: "size-4" });
5419
+ let Icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, { className: "size-4" });
5562
5420
  if (status === "submitted") {
5563
5421
  Icon = /* @__PURE__ */ jsxRuntime.jsx(Spinner, {});
5564
5422
  } else if (status === "streaming") {
5565
- Icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquareIcon, { className: "size-4" });
5423
+ Icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquareIcon, { className: "size-3 fill-current" });
5566
5424
  } else if (status === "error") {
5567
5425
  Icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, { className: "size-4" });
5568
5426
  }
@@ -5581,7 +5439,7 @@ var PromptInputSubmit = ({
5581
5439
  InputGroupButton,
5582
5440
  {
5583
5441
  "aria-label": isGenerating ? "Stop" : "Submit",
5584
- className: cn(className),
5442
+ className: cn("rounded-full", className),
5585
5443
  onClick: handleClick,
5586
5444
  size,
5587
5445
  type: isGenerating && onStop ? "button" : "submit",
@@ -5592,6 +5450,44 @@ var PromptInputSubmit = ({
5592
5450
  );
5593
5451
  };
5594
5452
 
5453
+ // src/components/ui/popover.tsx
5454
+ init_utils();
5455
+ function Popover({
5456
+ ...props
5457
+ }) {
5458
+ return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Root, { "data-slot": "popover", ...props });
5459
+ }
5460
+ function PopoverTrigger({
5461
+ ...props
5462
+ }) {
5463
+ return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
5464
+ }
5465
+ function PopoverContent({
5466
+ className,
5467
+ align = "center",
5468
+ sideOffset = 4,
5469
+ ...props
5470
+ }) {
5471
+ return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
5472
+ radixUi.Popover.Content,
5473
+ {
5474
+ "data-slot": "popover-content",
5475
+ align,
5476
+ sideOffset,
5477
+ className: cn(
5478
+ "z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-4 rounded-none bg-popover p-4 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-150 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
5479
+ className
5480
+ ),
5481
+ ...props
5482
+ }
5483
+ ) });
5484
+ }
5485
+ function PopoverAnchor({
5486
+ ...props
5487
+ }) {
5488
+ return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Anchor, { "data-slot": "popover-anchor", ...props });
5489
+ }
5490
+
5595
5491
  // src/components/ui/progress.tsx
5596
5492
  init_utils();
5597
5493
  function Progress({
@@ -5646,7 +5542,7 @@ var Context = ({
5646
5542
  () => ({ maxTokens, modelId, usage, usedTokens }),
5647
5543
  [maxTokens, modelId, usage, usedTokens]
5648
5544
  );
5649
- return /* @__PURE__ */ jsxRuntime.jsx(ContextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(HoverCard, { closeDelay: 100, openDelay: 0, ...props }) });
5545
+ return /* @__PURE__ */ jsxRuntime.jsx(ContextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(Popover, { ...props }) });
5650
5546
  };
5651
5547
  var ContextIcon = () => {
5652
5548
  const { usedTokens, maxTokens } = useContextValue();
@@ -5696,13 +5592,13 @@ var ContextIcon = () => {
5696
5592
  );
5697
5593
  };
5698
5594
  var ContextTrigger = ({ children, ...props }) => {
5699
- return /* @__PURE__ */ jsxRuntime.jsx(HoverCardTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ContextIcon, {}) }) });
5595
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ContextIcon, {}) }) });
5700
5596
  };
5701
5597
  var ContextContent = ({
5702
5598
  className,
5703
5599
  ...props
5704
5600
  }) => /* @__PURE__ */ jsxRuntime.jsx(
5705
- HoverCardContent,
5601
+ PopoverContent,
5706
5602
  {
5707
5603
  className: cn("min-w-60 divide-y overflow-hidden p-0", className),
5708
5604
  ...props
@@ -6008,39 +5904,6 @@ function ItemActions({ className, ...props }) {
6008
5904
  }
6009
5905
  );
6010
5906
  }
6011
-
6012
- // src/components/ui/popover.tsx
6013
- init_utils();
6014
- function Popover({
6015
- ...props
6016
- }) {
6017
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Root, { "data-slot": "popover", ...props });
6018
- }
6019
- function PopoverContent({
6020
- className,
6021
- align = "center",
6022
- sideOffset = 4,
6023
- ...props
6024
- }) {
6025
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
6026
- radixUi.Popover.Content,
6027
- {
6028
- "data-slot": "popover-content",
6029
- align,
6030
- sideOffset,
6031
- className: cn(
6032
- "z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-4 rounded-none bg-popover p-4 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
6033
- className
6034
- ),
6035
- ...props
6036
- }
6037
- ) });
6038
- }
6039
- function PopoverAnchor({
6040
- ...props
6041
- }) {
6042
- return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Anchor, { "data-slot": "popover-anchor", ...props });
6043
- }
6044
5907
  function ChatComposer(props) {
6045
5908
  return /* @__PURE__ */ jsxRuntime.jsx(PromptInputProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ChatComposerInner, { ...props }) });
6046
5909
  }
@@ -6122,10 +5985,12 @@ function ChatComposerInner({
6122
5985
  onComposerError
6123
5986
  }) {
6124
5987
  const { adapter } = useAgentChatAdapterContext();
6125
- const { textInput } = usePromptInputController();
5988
+ const { textInput, attachments } = usePromptInputController();
6126
5989
  const status = isRunning ? "streaming" : disabled ? "error" : "ready";
6127
5990
  const [adapterCommands, setAdapterCommands] = react.useState([]);
6128
5991
  const [buttonMenuOpen, setButtonMenuOpen] = react.useState(false);
5992
+ const [menuMode, setMenuMode] = react.useState("all");
5993
+ const [addMenuOpen, setAddMenuOpen] = react.useState(false);
6129
5994
  const [menuDismissed, setMenuDismissed] = react.useState(false);
6130
5995
  const showSlashMenu = !menuDismissed && (textInput.value.startsWith("/") || buttonMenuOpen);
6131
5996
  react.useEffect(() => {
@@ -6133,17 +5998,17 @@ function ChatComposerInner({
6133
5998
  setMenuDismissed(false);
6134
5999
  }
6135
6000
  }, [buttonMenuOpen, menuDismissed, textInput.value]);
6136
- const [wasClosed, setWasClosed] = react.useState(true);
6137
6001
  react.useEffect(() => {
6138
- if (showSlashMenu && wasClosed) {
6139
- setWasClosed(false);
6002
+ if (textInput.value.startsWith("/")) {
6003
+ setMenuMode("all");
6004
+ }
6005
+ }, [textInput.value]);
6006
+ react.useEffect(() => {
6007
+ if (showSlashMenu && (menuMode === "skills" || menuMode === "all")) {
6140
6008
  adapter.listSlashCommands?.().then(setAdapterCommands).catch(() => {
6141
6009
  });
6142
6010
  }
6143
- if (!showSlashMenu && !wasClosed) {
6144
- setWasClosed(true);
6145
- }
6146
- }, [adapter, showSlashMenu, wasClosed]);
6011
+ }, [adapter, showSlashMenu, menuMode]);
6147
6012
  const builtinCommands = react.useMemo(
6148
6013
  () => [
6149
6014
  { value: "/clear", label: "/clear", description: "Clear conversation" },
@@ -6164,6 +6029,23 @@ function ChatComposerInner({
6164
6029
  ],
6165
6030
  []
6166
6031
  );
6032
+ const scheduledExamples = react.useMemo(
6033
+ () => [
6034
+ { value: "/loop list", label: "/loop list", description: "List your active scheduled tasks" },
6035
+ { value: "/loop cancel ", label: "/loop cancel <id>", description: "Cancel a scheduled task by ID" },
6036
+ { value: "/loop 5m check the deployment status and surface any failures", label: "/loop 5m deployment check", description: "Every 5 minutes: poll deployment status" },
6037
+ { value: "/loop 10m pull the build queue and report any stuck jobs", label: "/loop 10m build queue", description: "Every 10 minutes: review the build queue" },
6038
+ { value: "/loop 15m triage new PRs assigned to me", label: "/loop 15m PR triage", description: "Every 15 minutes: triage incoming PRs" },
6039
+ { value: "/loop 30m summarize new threads in support inbox", label: "/loop 30m support inbox", description: "Every 30 minutes: summarize support traffic" },
6040
+ { value: "/loop 1h review the on-call dashboard and flag anomalies", label: "/loop 1h on-call check", description: "Hourly: review the on-call dashboard" },
6041
+ { value: "/loop 2h scan production error rates and alert if elevated", label: "/loop 2h error scan", description: "Every 2 hours: production error scan" },
6042
+ { value: "/loop 1d give me a morning briefing of yesterday's activity", label: "/loop 1d daily briefing", description: "Daily: morning briefing of prior day" },
6043
+ { value: "/loop every 5 minutes check whether CI on the current branch has finished", label: "/loop every 5 minutes (verbose)", description: "Verbose interval form" },
6044
+ { value: "/loop watch the active deploy and notify me when it stabilises or rolls back", label: "/loop <prompt> (dynamic)", description: "Dynamic loop \u2014 model self-paces 1m\u20131h via loop_wait" },
6045
+ { value: "/loop babysit the long-running data migration and only ping me on errors or completion", label: "/loop migration watcher (dynamic)", description: "Dynamic loop \u2014 best when cadence is unpredictable" }
6046
+ ],
6047
+ []
6048
+ );
6167
6049
  const searchQuery = showSlashMenu ? textInput.value.slice(1) : "";
6168
6050
  const menuOpen = showSlashMenu;
6169
6051
  const textareaRef = react.useRef(null);
@@ -6178,7 +6060,7 @@ function ChatComposerInner({
6178
6060
  }, []);
6179
6061
  const handleCommandSelect = react.useCallback(
6180
6062
  (commandValue) => {
6181
- textInput.setInput(commandValue + " ");
6063
+ textInput.setInput(`${commandValue} `);
6182
6064
  setButtonMenuOpen(false);
6183
6065
  setMenuDismissed(true);
6184
6066
  focusTextareaAtEnd();
@@ -6187,7 +6069,7 @@ function ChatComposerInner({
6187
6069
  );
6188
6070
  const handleSearchChange = react.useCallback(
6189
6071
  (next) => {
6190
- textInput.setInput("/" + next);
6072
+ textInput.setInput(`/${next}`);
6191
6073
  },
6192
6074
  [textInput]
6193
6075
  );
@@ -6282,6 +6164,62 @@ function ChatComposerInner({
6282
6164
  },
6283
6165
  children: [
6284
6166
  /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewStrip, {}),
6167
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2 px-1 pb-2", children: [
6168
+ /* @__PURE__ */ jsxRuntime.jsxs(
6169
+ Button,
6170
+ {
6171
+ type: "button",
6172
+ variant: "secondary",
6173
+ size: "sm",
6174
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
6175
+ onClick: () => {
6176
+ setMenuMode("commands");
6177
+ setMenuDismissed(false);
6178
+ setButtonMenuOpen(true);
6179
+ },
6180
+ children: [
6181
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TerminalIcon, {}),
6182
+ "Commands"
6183
+ ]
6184
+ }
6185
+ ),
6186
+ /* @__PURE__ */ jsxRuntime.jsxs(
6187
+ Button,
6188
+ {
6189
+ type: "button",
6190
+ variant: "secondary",
6191
+ size: "sm",
6192
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
6193
+ onClick: () => {
6194
+ setMenuMode("skills");
6195
+ setMenuDismissed(false);
6196
+ setButtonMenuOpen(true);
6197
+ },
6198
+ children: [
6199
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SparklesIcon, {}),
6200
+ "Skills"
6201
+ ]
6202
+ }
6203
+ ),
6204
+ /* @__PURE__ */ jsxRuntime.jsxs(
6205
+ Button,
6206
+ {
6207
+ type: "button",
6208
+ variant: "secondary",
6209
+ size: "sm",
6210
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
6211
+ onClick: () => {
6212
+ setMenuMode("scheduled");
6213
+ setMenuDismissed(false);
6214
+ setButtonMenuOpen(true);
6215
+ },
6216
+ children: [
6217
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClockIcon, {}),
6218
+ "Scheduled Tasks"
6219
+ ]
6220
+ }
6221
+ )
6222
+ ] }),
6285
6223
  /* @__PURE__ */ jsxRuntime.jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
6286
6224
  PromptInput,
6287
6225
  {
@@ -6301,25 +6239,56 @@ function ChatComposerInner({
6301
6239
  ) }),
6302
6240
  /* @__PURE__ */ jsxRuntime.jsxs(PromptInputFooter, { children: [
6303
6241
  /* @__PURE__ */ jsxRuntime.jsxs(PromptInputTools, { children: [
6304
- /* @__PURE__ */ jsxRuntime.jsxs(PromptInputActionMenu, { children: [
6305
- /* @__PURE__ */ jsxRuntime.jsx(PromptInputActionMenuTrigger, {}),
6306
- /* @__PURE__ */ jsxRuntime.jsx(PromptInputActionMenuContent, { children: /* @__PURE__ */ jsxRuntime.jsx(PromptInputActionAddAttachments, {}) })
6242
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: addMenuOpen, onOpenChange: setAddMenuOpen, children: [
6243
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(PromptInputButton, { "aria-label": "Add", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "size-4" }) }) }),
6244
+ /* @__PURE__ */ jsxRuntime.jsx(
6245
+ PopoverContent,
6246
+ {
6247
+ side: "top",
6248
+ align: "start",
6249
+ className: "w-64 overflow-hidden rounded-xl p-1",
6250
+ children: /* @__PURE__ */ jsxRuntime.jsx(Command, { children: /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { children: [
6251
+ /* @__PURE__ */ jsxRuntime.jsxs(
6252
+ CommandItem,
6253
+ {
6254
+ disabled: true,
6255
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
6256
+ children: [
6257
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CloudIcon, { className: "size-4 shrink-0 text-sky-500" }),
6258
+ "Add from OneDrive",
6259
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "ml-auto size-4 shrink-0 text-muted-foreground" })
6260
+ ]
6261
+ }
6262
+ ),
6263
+ /* @__PURE__ */ jsxRuntime.jsxs(
6264
+ CommandItem,
6265
+ {
6266
+ disabled: true,
6267
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
6268
+ children: [
6269
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HardDriveIcon, { className: "size-4 shrink-0 text-emerald-500" }),
6270
+ "Add from Google Drive"
6271
+ ]
6272
+ }
6273
+ ),
6274
+ /* @__PURE__ */ jsxRuntime.jsxs(
6275
+ CommandItem,
6276
+ {
6277
+ onSelect: () => {
6278
+ setAddMenuOpen(false);
6279
+ attachments.openFileDialog();
6280
+ },
6281
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
6282
+ children: [
6283
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaperclipIcon, { className: "size-4 shrink-0 text-muted-foreground" }),
6284
+ "Add local files"
6285
+ ]
6286
+ }
6287
+ )
6288
+ ] }) })
6289
+ }
6290
+ )
6307
6291
  ] }),
6308
- /* @__PURE__ */ jsxRuntime.jsx(
6309
- Button,
6310
- {
6311
- type: "button",
6312
- variant: "ghost",
6313
- size: "icon-xs",
6314
- className: "text-muted-foreground",
6315
- onClick: (e) => {
6316
- e.preventDefault();
6317
- setButtonMenuOpen((v) => !v);
6318
- },
6319
- "aria-label": "Slash commands",
6320
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold", children: "/" })
6321
- }
6322
- ),
6323
6292
  tokenUsage && tokenUsage.contextWindow > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
6324
6293
  Context,
6325
6294
  {
@@ -6336,7 +6305,13 @@ function ChatComposerInner({
6336
6305
  outputTokenDetails: void 0
6337
6306
  },
6338
6307
  children: [
6339
- /* @__PURE__ */ jsxRuntime.jsx(ContextTrigger, {}),
6308
+ /* @__PURE__ */ jsxRuntime.jsx(
6309
+ ContextTrigger,
6310
+ {
6311
+ size: "icon-sm",
6312
+ className: "rounded-sm border border-input/70 text-foreground hover:bg-accent"
6313
+ }
6314
+ ),
6340
6315
  /* @__PURE__ */ jsxRuntime.jsxs(ContextContent, { children: [
6341
6316
  /* @__PURE__ */ jsxRuntime.jsx(ContextContentHeader, {}),
6342
6317
  /* @__PURE__ */ jsxRuntime.jsx(ContextContentBody, { children: tokenUsage.totalTokens > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -6381,14 +6356,14 @@ function ChatComposerInner({
6381
6356
  {
6382
6357
  side: "top",
6383
6358
  align: "start",
6384
- className: "overflow-hidden p-0",
6359
+ className: "overflow-hidden rounded-xl p-0",
6385
6360
  style: { width: "var(--radix-popover-trigger-width)" },
6386
6361
  onCloseAutoFocus: (e) => e.preventDefault(),
6387
6362
  onEscapeKeyDown: () => {
6388
6363
  focusTextareaAtEnd();
6389
6364
  },
6390
6365
  children: /* @__PURE__ */ jsxRuntime.jsxs(Command, { children: [
6391
- /* @__PURE__ */ jsxRuntime.jsx(
6366
+ menuMode === "skills" ? /* @__PURE__ */ jsxRuntime.jsx(CommandInput, { placeholder: "Search skills..." }) : menuMode === "scheduled" ? /* @__PURE__ */ jsxRuntime.jsx(CommandInput, { placeholder: "Search scheduled tasks..." }) : /* @__PURE__ */ jsxRuntime.jsx(
6392
6367
  CommandInput,
6393
6368
  {
6394
6369
  placeholder: "Type a command or search...",
@@ -6397,8 +6372,36 @@ function ChatComposerInner({
6397
6372
  }
6398
6373
  ),
6399
6374
  /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { children: [
6400
- /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No commands found." }),
6401
- builtinCommands.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(CommandGroup, { heading: "Built-in commands", children: builtinCommands.map((cmd) => /* @__PURE__ */ jsxRuntime.jsxs(
6375
+ /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: menuMode === "skills" ? "No skills found." : menuMode === "scheduled" ? "No scheduled tasks found." : "No commands found." }),
6376
+ menuMode === "scheduled" && scheduledExamples.map((cmd) => /* @__PURE__ */ jsxRuntime.jsxs(
6377
+ CommandItem,
6378
+ {
6379
+ value: cmd.value,
6380
+ keywords: [cmd.description],
6381
+ onSelect: () => handleCommandSelect(cmd.value),
6382
+ className: "grid grid-cols-[14rem_1fr] items-baseline gap-3 [&_svg]:hidden",
6383
+ children: [
6384
+ /* @__PURE__ */ jsxRuntime.jsx(
6385
+ "span",
6386
+ {
6387
+ className: "font-mono font-semibold text-foreground truncate",
6388
+ title: cmd.label,
6389
+ children: cmd.label
6390
+ }
6391
+ ),
6392
+ /* @__PURE__ */ jsxRuntime.jsx(
6393
+ "span",
6394
+ {
6395
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6396
+ title: cmd.description,
6397
+ children: cmd.description
6398
+ }
6399
+ )
6400
+ ]
6401
+ },
6402
+ cmd.value
6403
+ )),
6404
+ (menuMode === "commands" || menuMode === "all") && builtinCommands.map((cmd) => /* @__PURE__ */ jsxRuntime.jsxs(
6402
6405
  CommandItem,
6403
6406
  {
6404
6407
  value: cmd.value,
@@ -6409,7 +6412,7 @@ function ChatComposerInner({
6409
6412
  /* @__PURE__ */ jsxRuntime.jsx(
6410
6413
  "span",
6411
6414
  {
6412
- className: "font-mono text-foreground truncate",
6415
+ className: "font-mono font-semibold text-foreground truncate",
6413
6416
  title: cmd.label,
6414
6417
  children: cmd.label
6415
6418
  }
@@ -6417,7 +6420,7 @@ function ChatComposerInner({
6417
6420
  /* @__PURE__ */ jsxRuntime.jsx(
6418
6421
  "span",
6419
6422
  {
6420
- className: "min-w-0 truncate text-xs text-muted-foreground",
6423
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6421
6424
  title: cmd.description,
6422
6425
  children: cmd.description
6423
6426
  }
@@ -6425,9 +6428,8 @@ function ChatComposerInner({
6425
6428
  ]
6426
6429
  },
6427
6430
  cmd.value
6428
- )) }),
6429
- builtinCommands.length > 0 && adapterCommands.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(CommandSeparator, {}),
6430
- adapterCommands.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(CommandGroup, { heading: "Skills", children: adapterCommands.map((cmd) => /* @__PURE__ */ jsxRuntime.jsxs(
6431
+ )),
6432
+ (menuMode === "skills" || menuMode === "all") && adapterCommands.map((cmd) => /* @__PURE__ */ jsxRuntime.jsxs(
6431
6433
  CommandItem,
6432
6434
  {
6433
6435
  value: cmd.value,
@@ -6438,7 +6440,7 @@ function ChatComposerInner({
6438
6440
  /* @__PURE__ */ jsxRuntime.jsx(
6439
6441
  "span",
6440
6442
  {
6441
- className: "font-mono text-foreground truncate",
6443
+ className: "font-mono font-semibold text-foreground truncate",
6442
6444
  title: cmd.label,
6443
6445
  children: cmd.label
6444
6446
  }
@@ -6446,7 +6448,7 @@ function ChatComposerInner({
6446
6448
  /* @__PURE__ */ jsxRuntime.jsx(
6447
6449
  "span",
6448
6450
  {
6449
- className: "min-w-0 truncate text-xs text-muted-foreground",
6451
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6450
6452
  title: cmd.description,
6451
6453
  children: cmd.description
6452
6454
  }
@@ -6454,7 +6456,7 @@ function ChatComposerInner({
6454
6456
  ]
6455
6457
  },
6456
6458
  cmd.value
6457
- )) })
6459
+ ))
6458
6460
  ] })
6459
6461
  ] })
6460
6462
  }