@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.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { cn } from './chunk-QSC4UIVT.js';
2
2
  import { createContext, memo, useRef, useEffect, useCallback, useMemo, useState, lazy, useContext, Suspense, Children } from 'react';
3
- import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, File as File$1, FileImage, FileAudio, FileVideo, FileText, FileCode, FileArchive, FileSpreadsheet, InboxIcon, Loader2, AlertCircle, Pause, Play, Ban, TargetIcon, ChevronRightIcon, CalendarClockIcon, UsersIcon, MessageSquareIcon, ZapIcon, Maximize2Icon, FolderOpenIcon, Loader2Icon, UploadIcon, RefreshCwIcon, AlertCircleIcon, ExternalLinkIcon, ClipboardCheckIcon, ShieldAlertIcon, TimerIcon, CircleDotIcon, XIcon, Trash2Icon, SquareIcon, ArrowDownIcon, RotateCcwIcon, MousePointer2Icon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, CheckIcon, CopyIcon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, PlusIcon, SearchIcon, GitBranchIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, EyeIcon, GlobeIcon, ListTodoIcon, CornerDownLeftIcon, XCircleIcon, CheckCircle2Icon, Code, TerminalIcon, CircleCheckIcon, CircleXIcon, SkullIcon, ClockIcon, CheckCircleIcon, CircleIcon } from 'lucide-react';
3
+ import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, File as File$1, FileImage, FileAudio, FileVideo, FileText, FileCode, FileArchive, FileSpreadsheet, InboxIcon, Loader2, AlertCircle, Pause, Play, Ban, TargetIcon, ChevronRightIcon, CalendarClockIcon, UsersIcon, MessageSquareIcon, ZapIcon, Maximize2Icon, FolderOpenIcon, Loader2Icon, UploadIcon, RefreshCwIcon, AlertCircleIcon, ExternalLinkIcon, ClipboardCheckIcon, ShieldAlertIcon, TimerIcon, CircleDotIcon, XIcon, Trash2Icon, SquareIcon, ArrowDownIcon, RotateCcwIcon, MousePointer2Icon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, CheckIcon, CopyIcon, TerminalIcon, SparklesIcon, ClockIcon, PlusIcon, CloudIcon, HardDriveIcon, PaperclipIcon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, SearchIcon, GitBranchIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, EyeIcon, GlobeIcon, ListTodoIcon, ArrowUpIcon, XCircleIcon, CheckCircle2Icon, Code, CircleCheckIcon, CircleXIcon, SkullIcon, CheckCircleIcon, CircleIcon } from 'lucide-react';
4
4
  import { cva } from 'class-variance-authority';
5
- import { Collapsible as Collapsible$1, Slot, Tooltip as Tooltip$1, Separator as Separator$1, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, HoverCard as HoverCard$1, Progress as Progress$1, Tabs as Tabs$1 } from 'radix-ui';
5
+ import { Collapsible as Collapsible$1, Slot, Tooltip as Tooltip$1, Separator as Separator$1, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Popover as Popover$1, Progress as Progress$1, Tabs as Tabs$1 } from 'radix-ui';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { StickToBottom, useStickToBottomContext } from 'use-stick-to-bottom';
8
8
  import { cjk } from '@streamdown/cjk';
@@ -3171,7 +3171,7 @@ function Textarea({ className, ...props }) {
3171
3171
  {
3172
3172
  "data-slot": "textarea",
3173
3173
  className: cn(
3174
- "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",
3174
+ "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",
3175
3175
  className
3176
3176
  ),
3177
3177
  ...props
@@ -4423,7 +4423,7 @@ function CommandInput({
4423
4423
  className,
4424
4424
  ...props
4425
4425
  }) {
4426
- return /* @__PURE__ */ jsx("div", { "data-slot": "command-input-wrapper", className: "p-1", children: /* @__PURE__ */ jsxs(InputGroup, { className: "border-transparent border-b-input bg-transparent px-3", children: [
4426
+ return /* @__PURE__ */ jsx("div", { "data-slot": "command-input-wrapper", className: "p-3", children: /* @__PURE__ */ jsxs(InputGroup, { className: "rounded-lg border-transparent bg-muted px-3", children: [
4427
4427
  /* @__PURE__ */ jsx(
4428
4428
  Command$1.Input,
4429
4429
  {
@@ -4467,35 +4467,6 @@ function CommandEmpty({
4467
4467
  }
4468
4468
  );
4469
4469
  }
4470
- function CommandGroup({
4471
- className,
4472
- ...props
4473
- }) {
4474
- return /* @__PURE__ */ jsx(
4475
- Command$1.Group,
4476
- {
4477
- "data-slot": "command-group",
4478
- className: cn(
4479
- "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",
4480
- className
4481
- ),
4482
- ...props
4483
- }
4484
- );
4485
- }
4486
- function CommandSeparator({
4487
- className,
4488
- ...props
4489
- }) {
4490
- return /* @__PURE__ */ jsx(
4491
- Command$1.Separator,
4492
- {
4493
- "data-slot": "command-separator",
4494
- className: cn("-mx-1.5 my-1.5 h-px bg-border/50", className),
4495
- ...props
4496
- }
4497
- );
4498
- }
4499
4470
  function CommandItem({
4500
4471
  className,
4501
4472
  children,
@@ -4506,7 +4477,7 @@ function CommandItem({
4506
4477
  {
4507
4478
  "data-slot": "command-item",
4508
4479
  className: cn(
4509
- "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",
4480
+ "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",
4510
4481
  className
4511
4482
  ),
4512
4483
  ...props,
@@ -4517,89 +4488,6 @@ function CommandItem({
4517
4488
  }
4518
4489
  );
4519
4490
  }
4520
- function DropdownMenu({
4521
- ...props
4522
- }) {
4523
- return /* @__PURE__ */ jsx(DropdownMenu$1.Root, { "data-slot": "dropdown-menu", ...props });
4524
- }
4525
- function DropdownMenuTrigger({
4526
- ...props
4527
- }) {
4528
- return /* @__PURE__ */ jsx(
4529
- DropdownMenu$1.Trigger,
4530
- {
4531
- "data-slot": "dropdown-menu-trigger",
4532
- ...props
4533
- }
4534
- );
4535
- }
4536
- function DropdownMenuContent({
4537
- className,
4538
- align = "start",
4539
- sideOffset = 4,
4540
- ...props
4541
- }) {
4542
- return /* @__PURE__ */ jsx(DropdownMenu$1.Portal, { children: /* @__PURE__ */ jsx(
4543
- DropdownMenu$1.Content,
4544
- {
4545
- "data-slot": "dropdown-menu-content",
4546
- sideOffset,
4547
- align,
4548
- 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),
4549
- ...props
4550
- }
4551
- ) });
4552
- }
4553
- function DropdownMenuItem({
4554
- className,
4555
- inset,
4556
- variant = "default",
4557
- ...props
4558
- }) {
4559
- return /* @__PURE__ */ jsx(
4560
- DropdownMenu$1.Item,
4561
- {
4562
- "data-slot": "dropdown-menu-item",
4563
- "data-inset": inset,
4564
- "data-variant": variant,
4565
- className: cn(
4566
- "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",
4567
- className
4568
- ),
4569
- ...props
4570
- }
4571
- );
4572
- }
4573
- function HoverCard({
4574
- ...props
4575
- }) {
4576
- return /* @__PURE__ */ jsx(HoverCard$1.Root, { "data-slot": "hover-card", ...props });
4577
- }
4578
- function HoverCardTrigger({
4579
- ...props
4580
- }) {
4581
- return /* @__PURE__ */ jsx(HoverCard$1.Trigger, { "data-slot": "hover-card-trigger", ...props });
4582
- }
4583
- function HoverCardContent({
4584
- className,
4585
- align = "center",
4586
- sideOffset = 4,
4587
- ...props
4588
- }) {
4589
- return /* @__PURE__ */ jsx(HoverCard$1.Portal, { "data-slot": "hover-card-portal", children: /* @__PURE__ */ jsx(
4590
- HoverCard$1.Content,
4591
- {
4592
- "data-slot": "hover-card-content",
4593
- align,
4594
- sideOffset,
4595
- className: cn(
4596
- "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",
4597
- className
4598
- ),
4599
- ...props
4600
- }
4601
- ) });
4602
- }
4603
4491
  function Spinner({ className, ...props }) {
4604
4492
  return /* @__PURE__ */ jsx(Loader2Icon, { role: "status", "aria-label": "Loading", className: cn("size-4 animate-spin", className), ...props });
4605
4493
  }
@@ -4751,24 +4639,6 @@ var usePromptInputAttachments = () => {
4751
4639
  return context;
4752
4640
  };
4753
4641
  var LocalReferencedSourcesContext = createContext(null);
4754
- var PromptInputActionAddAttachments = ({
4755
- label = "Add photos or files",
4756
- ...props
4757
- }) => {
4758
- const attachments = usePromptInputAttachments();
4759
- const handleSelect = useCallback(
4760
- (e) => {
4761
- e.preventDefault();
4762
- attachments.openFileDialog();
4763
- },
4764
- [attachments]
4765
- );
4766
- return /* @__PURE__ */ jsxs(DropdownMenuItem, { ...props, onSelect: handleSelect, children: [
4767
- /* @__PURE__ */ jsx(ImageIcon, { className: "mr-2 size-4" }),
4768
- " ",
4769
- label
4770
- ] });
4771
- };
4772
4642
  var PromptInput = ({
4773
4643
  className,
4774
4644
  accept,
@@ -5104,7 +4974,7 @@ var PromptInput = ({
5104
4974
  onSubmit: handleSubmit,
5105
4975
  ref: formRef,
5106
4976
  ...props,
5107
- children: /* @__PURE__ */ jsx(InputGroup, { className: "overflow-hidden", children })
4977
+ children: /* @__PURE__ */ 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 })
5108
4978
  }
5109
4979
  )
5110
4980
  ] });
@@ -5194,7 +5064,7 @@ var PromptInputTextarea = ({
5194
5064
  return /* @__PURE__ */ jsx(
5195
5065
  InputGroupTextarea,
5196
5066
  {
5197
- className: cn("field-sizing-content max-h-48 min-h-16", className),
5067
+ className: cn("field-sizing-content max-h-48 min-h-16 px-1.5 py-3", className),
5198
5068
  name: "message",
5199
5069
  onCompositionEnd: handleCompositionEnd,
5200
5070
  onCompositionStart: handleCompositionStart,
@@ -5238,7 +5108,11 @@ var PromptInputButton = ({
5238
5108
  const button = /* @__PURE__ */ jsx(
5239
5109
  InputGroupButton,
5240
5110
  {
5241
- className: cn(className),
5111
+ className: cn(
5112
+ "rounded-sm border border-input/70 text-foreground hover:bg-accent",
5113
+ newSize === "icon-sm" && "size-9",
5114
+ className
5115
+ ),
5242
5116
  size: newSize,
5243
5117
  type: "button",
5244
5118
  variant,
@@ -5259,19 +5133,9 @@ var PromptInputButton = ({
5259
5133
  ] })
5260
5134
  ] });
5261
5135
  };
5262
- var PromptInputActionMenu = (props) => /* @__PURE__ */ jsx(DropdownMenu, { ...props });
5263
- var PromptInputActionMenuTrigger = ({
5264
- className,
5265
- children,
5266
- ...props
5267
- }) => /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(PromptInputButton, { className, ...props, children: children ?? /* @__PURE__ */ jsx(PlusIcon, { className: "size-4" }) }) });
5268
- var PromptInputActionMenuContent = ({
5269
- className,
5270
- ...props
5271
- }) => /* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: cn(className), ...props });
5272
5136
  var PromptInputSubmit = ({
5273
5137
  className,
5274
- variant = "default",
5138
+ variant = "secondary",
5275
5139
  size = "icon-sm",
5276
5140
  status,
5277
5141
  onStop,
@@ -5280,11 +5144,11 @@ var PromptInputSubmit = ({
5280
5144
  ...props
5281
5145
  }) => {
5282
5146
  const isGenerating = status === "submitted" || status === "streaming";
5283
- let Icon = /* @__PURE__ */ jsx(CornerDownLeftIcon, { className: "size-4" });
5147
+ let Icon = /* @__PURE__ */ jsx(ArrowUpIcon, { className: "size-4" });
5284
5148
  if (status === "submitted") {
5285
5149
  Icon = /* @__PURE__ */ jsx(Spinner, {});
5286
5150
  } else if (status === "streaming") {
5287
- Icon = /* @__PURE__ */ jsx(SquareIcon, { className: "size-4" });
5151
+ Icon = /* @__PURE__ */ jsx(SquareIcon, { className: "size-3 fill-current" });
5288
5152
  } else if (status === "error") {
5289
5153
  Icon = /* @__PURE__ */ jsx(XIcon, { className: "size-4" });
5290
5154
  }
@@ -5303,7 +5167,7 @@ var PromptInputSubmit = ({
5303
5167
  InputGroupButton,
5304
5168
  {
5305
5169
  "aria-label": isGenerating ? "Stop" : "Submit",
5306
- className: cn(className),
5170
+ className: cn("rounded-full", className),
5307
5171
  onClick: handleClick,
5308
5172
  size,
5309
5173
  type: isGenerating && onStop ? "button" : "submit",
@@ -5313,6 +5177,41 @@ var PromptInputSubmit = ({
5313
5177
  }
5314
5178
  );
5315
5179
  };
5180
+ function Popover({
5181
+ ...props
5182
+ }) {
5183
+ return /* @__PURE__ */ jsx(Popover$1.Root, { "data-slot": "popover", ...props });
5184
+ }
5185
+ function PopoverTrigger({
5186
+ ...props
5187
+ }) {
5188
+ return /* @__PURE__ */ jsx(Popover$1.Trigger, { "data-slot": "popover-trigger", ...props });
5189
+ }
5190
+ function PopoverContent({
5191
+ className,
5192
+ align = "center",
5193
+ sideOffset = 4,
5194
+ ...props
5195
+ }) {
5196
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
5197
+ Popover$1.Content,
5198
+ {
5199
+ "data-slot": "popover-content",
5200
+ align,
5201
+ sideOffset,
5202
+ className: cn(
5203
+ "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",
5204
+ className
5205
+ ),
5206
+ ...props
5207
+ }
5208
+ ) });
5209
+ }
5210
+ function PopoverAnchor({
5211
+ ...props
5212
+ }) {
5213
+ return /* @__PURE__ */ jsx(Popover$1.Anchor, { "data-slot": "popover-anchor", ...props });
5214
+ }
5316
5215
  function Progress({
5317
5216
  className,
5318
5217
  value,
@@ -5362,7 +5261,7 @@ var Context = ({
5362
5261
  () => ({ maxTokens, modelId, usage, usedTokens }),
5363
5262
  [maxTokens, modelId, usage, usedTokens]
5364
5263
  );
5365
- return /* @__PURE__ */ jsx(ContextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(HoverCard, { closeDelay: 100, openDelay: 0, ...props }) });
5264
+ return /* @__PURE__ */ jsx(ContextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(Popover, { ...props }) });
5366
5265
  };
5367
5266
  var ContextIcon = () => {
5368
5267
  const { usedTokens, maxTokens } = useContextValue();
@@ -5412,13 +5311,13 @@ var ContextIcon = () => {
5412
5311
  );
5413
5312
  };
5414
5313
  var ContextTrigger = ({ children, ...props }) => {
5415
- return /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", ...props, children: /* @__PURE__ */ jsx(ContextIcon, {}) }) });
5314
+ return /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", ...props, children: /* @__PURE__ */ jsx(ContextIcon, {}) }) });
5416
5315
  };
5417
5316
  var ContextContent = ({
5418
5317
  className,
5419
5318
  ...props
5420
5319
  }) => /* @__PURE__ */ jsx(
5421
- HoverCardContent,
5320
+ PopoverContent,
5422
5321
  {
5423
5322
  className: cn("min-w-60 divide-y overflow-hidden p-0", className),
5424
5323
  ...props
@@ -5721,36 +5620,6 @@ function ItemActions({ className, ...props }) {
5721
5620
  }
5722
5621
  );
5723
5622
  }
5724
- function Popover({
5725
- ...props
5726
- }) {
5727
- return /* @__PURE__ */ jsx(Popover$1.Root, { "data-slot": "popover", ...props });
5728
- }
5729
- function PopoverContent({
5730
- className,
5731
- align = "center",
5732
- sideOffset = 4,
5733
- ...props
5734
- }) {
5735
- return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
5736
- Popover$1.Content,
5737
- {
5738
- "data-slot": "popover-content",
5739
- align,
5740
- sideOffset,
5741
- className: cn(
5742
- "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",
5743
- className
5744
- ),
5745
- ...props
5746
- }
5747
- ) });
5748
- }
5749
- function PopoverAnchor({
5750
- ...props
5751
- }) {
5752
- return /* @__PURE__ */ jsx(Popover$1.Anchor, { "data-slot": "popover-anchor", ...props });
5753
- }
5754
5623
  function ChatComposer(props) {
5755
5624
  return /* @__PURE__ */ jsx(PromptInputProvider, { children: /* @__PURE__ */ jsx(ChatComposerInner, { ...props }) });
5756
5625
  }
@@ -5832,10 +5701,12 @@ function ChatComposerInner({
5832
5701
  onComposerError
5833
5702
  }) {
5834
5703
  const { adapter } = useAgentChatAdapterContext();
5835
- const { textInput } = usePromptInputController();
5704
+ const { textInput, attachments } = usePromptInputController();
5836
5705
  const status = isRunning ? "streaming" : disabled ? "error" : "ready";
5837
5706
  const [adapterCommands, setAdapterCommands] = useState([]);
5838
5707
  const [buttonMenuOpen, setButtonMenuOpen] = useState(false);
5708
+ const [menuMode, setMenuMode] = useState("all");
5709
+ const [addMenuOpen, setAddMenuOpen] = useState(false);
5839
5710
  const [menuDismissed, setMenuDismissed] = useState(false);
5840
5711
  const showSlashMenu = !menuDismissed && (textInput.value.startsWith("/") || buttonMenuOpen);
5841
5712
  useEffect(() => {
@@ -5843,17 +5714,17 @@ function ChatComposerInner({
5843
5714
  setMenuDismissed(false);
5844
5715
  }
5845
5716
  }, [buttonMenuOpen, menuDismissed, textInput.value]);
5846
- const [wasClosed, setWasClosed] = useState(true);
5847
5717
  useEffect(() => {
5848
- if (showSlashMenu && wasClosed) {
5849
- setWasClosed(false);
5718
+ if (textInput.value.startsWith("/")) {
5719
+ setMenuMode("all");
5720
+ }
5721
+ }, [textInput.value]);
5722
+ useEffect(() => {
5723
+ if (showSlashMenu && (menuMode === "skills" || menuMode === "all")) {
5850
5724
  adapter.listSlashCommands?.().then(setAdapterCommands).catch(() => {
5851
5725
  });
5852
5726
  }
5853
- if (!showSlashMenu && !wasClosed) {
5854
- setWasClosed(true);
5855
- }
5856
- }, [adapter, showSlashMenu, wasClosed]);
5727
+ }, [adapter, showSlashMenu, menuMode]);
5857
5728
  const builtinCommands = useMemo(
5858
5729
  () => [
5859
5730
  { value: "/clear", label: "/clear", description: "Clear conversation" },
@@ -5874,6 +5745,23 @@ function ChatComposerInner({
5874
5745
  ],
5875
5746
  []
5876
5747
  );
5748
+ const scheduledExamples = useMemo(
5749
+ () => [
5750
+ { value: "/loop list", label: "/loop list", description: "List your active scheduled tasks" },
5751
+ { value: "/loop cancel ", label: "/loop cancel <id>", description: "Cancel a scheduled task by ID" },
5752
+ { value: "/loop 5m check the deployment status and surface any failures", label: "/loop 5m deployment check", description: "Every 5 minutes: poll deployment status" },
5753
+ { 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" },
5754
+ { value: "/loop 15m triage new PRs assigned to me", label: "/loop 15m PR triage", description: "Every 15 minutes: triage incoming PRs" },
5755
+ { value: "/loop 30m summarize new threads in support inbox", label: "/loop 30m support inbox", description: "Every 30 minutes: summarize support traffic" },
5756
+ { value: "/loop 1h review the on-call dashboard and flag anomalies", label: "/loop 1h on-call check", description: "Hourly: review the on-call dashboard" },
5757
+ { value: "/loop 2h scan production error rates and alert if elevated", label: "/loop 2h error scan", description: "Every 2 hours: production error scan" },
5758
+ { value: "/loop 1d give me a morning briefing of yesterday's activity", label: "/loop 1d daily briefing", description: "Daily: morning briefing of prior day" },
5759
+ { value: "/loop every 5 minutes check whether CI on the current branch has finished", label: "/loop every 5 minutes (verbose)", description: "Verbose interval form" },
5760
+ { 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" },
5761
+ { 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" }
5762
+ ],
5763
+ []
5764
+ );
5877
5765
  const searchQuery = showSlashMenu ? textInput.value.slice(1) : "";
5878
5766
  const menuOpen = showSlashMenu;
5879
5767
  const textareaRef = useRef(null);
@@ -5888,7 +5776,7 @@ function ChatComposerInner({
5888
5776
  }, []);
5889
5777
  const handleCommandSelect = useCallback(
5890
5778
  (commandValue) => {
5891
- textInput.setInput(commandValue + " ");
5779
+ textInput.setInput(`${commandValue} `);
5892
5780
  setButtonMenuOpen(false);
5893
5781
  setMenuDismissed(true);
5894
5782
  focusTextareaAtEnd();
@@ -5897,7 +5785,7 @@ function ChatComposerInner({
5897
5785
  );
5898
5786
  const handleSearchChange = useCallback(
5899
5787
  (next) => {
5900
- textInput.setInput("/" + next);
5788
+ textInput.setInput(`/${next}`);
5901
5789
  },
5902
5790
  [textInput]
5903
5791
  );
@@ -5992,6 +5880,62 @@ function ChatComposerInner({
5992
5880
  },
5993
5881
  children: [
5994
5882
  /* @__PURE__ */ jsx(AttachmentPreviewStrip, {}),
5883
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2 px-1 pb-2", children: [
5884
+ /* @__PURE__ */ jsxs(
5885
+ Button,
5886
+ {
5887
+ type: "button",
5888
+ variant: "secondary",
5889
+ size: "sm",
5890
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
5891
+ onClick: () => {
5892
+ setMenuMode("commands");
5893
+ setMenuDismissed(false);
5894
+ setButtonMenuOpen(true);
5895
+ },
5896
+ children: [
5897
+ /* @__PURE__ */ jsx(TerminalIcon, {}),
5898
+ "Commands"
5899
+ ]
5900
+ }
5901
+ ),
5902
+ /* @__PURE__ */ jsxs(
5903
+ Button,
5904
+ {
5905
+ type: "button",
5906
+ variant: "secondary",
5907
+ size: "sm",
5908
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
5909
+ onClick: () => {
5910
+ setMenuMode("skills");
5911
+ setMenuDismissed(false);
5912
+ setButtonMenuOpen(true);
5913
+ },
5914
+ children: [
5915
+ /* @__PURE__ */ jsx(SparklesIcon, {}),
5916
+ "Skills"
5917
+ ]
5918
+ }
5919
+ ),
5920
+ /* @__PURE__ */ jsxs(
5921
+ Button,
5922
+ {
5923
+ type: "button",
5924
+ variant: "secondary",
5925
+ size: "sm",
5926
+ className: "rounded-sm -uppercase font-display bg-white dark:bg-accent border-2 border-accent",
5927
+ onClick: () => {
5928
+ setMenuMode("scheduled");
5929
+ setMenuDismissed(false);
5930
+ setButtonMenuOpen(true);
5931
+ },
5932
+ children: [
5933
+ /* @__PURE__ */ jsx(ClockIcon, {}),
5934
+ "Scheduled Tasks"
5935
+ ]
5936
+ }
5937
+ )
5938
+ ] }),
5995
5939
  /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
5996
5940
  PromptInput,
5997
5941
  {
@@ -6011,25 +5955,56 @@ function ChatComposerInner({
6011
5955
  ) }),
6012
5956
  /* @__PURE__ */ jsxs(PromptInputFooter, { children: [
6013
5957
  /* @__PURE__ */ jsxs(PromptInputTools, { children: [
6014
- /* @__PURE__ */ jsxs(PromptInputActionMenu, { children: [
6015
- /* @__PURE__ */ jsx(PromptInputActionMenuTrigger, {}),
6016
- /* @__PURE__ */ jsx(PromptInputActionMenuContent, { children: /* @__PURE__ */ jsx(PromptInputActionAddAttachments, {}) })
5958
+ /* @__PURE__ */ jsxs(Popover, { open: addMenuOpen, onOpenChange: setAddMenuOpen, children: [
5959
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(PromptInputButton, { "aria-label": "Add", children: /* @__PURE__ */ jsx(PlusIcon, { className: "size-4" }) }) }),
5960
+ /* @__PURE__ */ jsx(
5961
+ PopoverContent,
5962
+ {
5963
+ side: "top",
5964
+ align: "start",
5965
+ className: "w-64 overflow-hidden rounded-xl p-1",
5966
+ children: /* @__PURE__ */ jsx(Command, { children: /* @__PURE__ */ jsxs(CommandList, { children: [
5967
+ /* @__PURE__ */ jsxs(
5968
+ CommandItem,
5969
+ {
5970
+ disabled: true,
5971
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
5972
+ children: [
5973
+ /* @__PURE__ */ jsx(CloudIcon, { className: "size-4 shrink-0 text-sky-500" }),
5974
+ "Add from OneDrive",
5975
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4 shrink-0 text-muted-foreground" })
5976
+ ]
5977
+ }
5978
+ ),
5979
+ /* @__PURE__ */ jsxs(
5980
+ CommandItem,
5981
+ {
5982
+ disabled: true,
5983
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
5984
+ children: [
5985
+ /* @__PURE__ */ jsx(HardDriveIcon, { className: "size-4 shrink-0 text-emerald-500" }),
5986
+ "Add from Google Drive"
5987
+ ]
5988
+ }
5989
+ ),
5990
+ /* @__PURE__ */ jsxs(
5991
+ CommandItem,
5992
+ {
5993
+ onSelect: () => {
5994
+ setAddMenuOpen(false);
5995
+ attachments.openFileDialog();
5996
+ },
5997
+ className: "gap-3 rounded-md px-3 py-2 [&>svg:last-child]:hidden",
5998
+ children: [
5999
+ /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4 shrink-0 text-muted-foreground" }),
6000
+ "Add local files"
6001
+ ]
6002
+ }
6003
+ )
6004
+ ] }) })
6005
+ }
6006
+ )
6017
6007
  ] }),
6018
- /* @__PURE__ */ jsx(
6019
- Button,
6020
- {
6021
- type: "button",
6022
- variant: "ghost",
6023
- size: "icon-xs",
6024
- className: "text-muted-foreground",
6025
- onClick: (e) => {
6026
- e.preventDefault();
6027
- setButtonMenuOpen((v) => !v);
6028
- },
6029
- "aria-label": "Slash commands",
6030
- children: /* @__PURE__ */ jsx("span", { className: "text-xs font-bold", children: "/" })
6031
- }
6032
- ),
6033
6008
  tokenUsage && tokenUsage.contextWindow > 0 && /* @__PURE__ */ jsxs(
6034
6009
  Context,
6035
6010
  {
@@ -6046,7 +6021,13 @@ function ChatComposerInner({
6046
6021
  outputTokenDetails: void 0
6047
6022
  },
6048
6023
  children: [
6049
- /* @__PURE__ */ jsx(ContextTrigger, {}),
6024
+ /* @__PURE__ */ jsx(
6025
+ ContextTrigger,
6026
+ {
6027
+ size: "icon-sm",
6028
+ className: "rounded-sm border border-input/70 text-foreground hover:bg-accent"
6029
+ }
6030
+ ),
6050
6031
  /* @__PURE__ */ jsxs(ContextContent, { children: [
6051
6032
  /* @__PURE__ */ jsx(ContextContentHeader, {}),
6052
6033
  /* @__PURE__ */ jsx(ContextContentBody, { children: tokenUsage.totalTokens > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -6091,14 +6072,14 @@ function ChatComposerInner({
6091
6072
  {
6092
6073
  side: "top",
6093
6074
  align: "start",
6094
- className: "overflow-hidden p-0",
6075
+ className: "overflow-hidden rounded-xl p-0",
6095
6076
  style: { width: "var(--radix-popover-trigger-width)" },
6096
6077
  onCloseAutoFocus: (e) => e.preventDefault(),
6097
6078
  onEscapeKeyDown: () => {
6098
6079
  focusTextareaAtEnd();
6099
6080
  },
6100
6081
  children: /* @__PURE__ */ jsxs(Command, { children: [
6101
- /* @__PURE__ */ jsx(
6082
+ menuMode === "skills" ? /* @__PURE__ */ jsx(CommandInput, { placeholder: "Search skills..." }) : menuMode === "scheduled" ? /* @__PURE__ */ jsx(CommandInput, { placeholder: "Search scheduled tasks..." }) : /* @__PURE__ */ jsx(
6102
6083
  CommandInput,
6103
6084
  {
6104
6085
  placeholder: "Type a command or search...",
@@ -6107,8 +6088,36 @@ function ChatComposerInner({
6107
6088
  }
6108
6089
  ),
6109
6090
  /* @__PURE__ */ jsxs(CommandList, { children: [
6110
- /* @__PURE__ */ jsx(CommandEmpty, { children: "No commands found." }),
6111
- builtinCommands.length > 0 && /* @__PURE__ */ jsx(CommandGroup, { heading: "Built-in commands", children: builtinCommands.map((cmd) => /* @__PURE__ */ jsxs(
6091
+ /* @__PURE__ */ jsx(CommandEmpty, { children: menuMode === "skills" ? "No skills found." : menuMode === "scheduled" ? "No scheduled tasks found." : "No commands found." }),
6092
+ menuMode === "scheduled" && scheduledExamples.map((cmd) => /* @__PURE__ */ jsxs(
6093
+ CommandItem,
6094
+ {
6095
+ value: cmd.value,
6096
+ keywords: [cmd.description],
6097
+ onSelect: () => handleCommandSelect(cmd.value),
6098
+ className: "grid grid-cols-[14rem_1fr] items-baseline gap-3 [&_svg]:hidden",
6099
+ children: [
6100
+ /* @__PURE__ */ jsx(
6101
+ "span",
6102
+ {
6103
+ className: "font-mono font-semibold text-foreground truncate",
6104
+ title: cmd.label,
6105
+ children: cmd.label
6106
+ }
6107
+ ),
6108
+ /* @__PURE__ */ jsx(
6109
+ "span",
6110
+ {
6111
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6112
+ title: cmd.description,
6113
+ children: cmd.description
6114
+ }
6115
+ )
6116
+ ]
6117
+ },
6118
+ cmd.value
6119
+ )),
6120
+ (menuMode === "commands" || menuMode === "all") && builtinCommands.map((cmd) => /* @__PURE__ */ jsxs(
6112
6121
  CommandItem,
6113
6122
  {
6114
6123
  value: cmd.value,
@@ -6119,7 +6128,7 @@ function ChatComposerInner({
6119
6128
  /* @__PURE__ */ jsx(
6120
6129
  "span",
6121
6130
  {
6122
- className: "font-mono text-foreground truncate",
6131
+ className: "font-mono font-semibold text-foreground truncate",
6123
6132
  title: cmd.label,
6124
6133
  children: cmd.label
6125
6134
  }
@@ -6127,7 +6136,7 @@ function ChatComposerInner({
6127
6136
  /* @__PURE__ */ jsx(
6128
6137
  "span",
6129
6138
  {
6130
- className: "min-w-0 truncate text-xs text-muted-foreground",
6139
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6131
6140
  title: cmd.description,
6132
6141
  children: cmd.description
6133
6142
  }
@@ -6135,9 +6144,8 @@ function ChatComposerInner({
6135
6144
  ]
6136
6145
  },
6137
6146
  cmd.value
6138
- )) }),
6139
- builtinCommands.length > 0 && adapterCommands.length > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
6140
- adapterCommands.length > 0 && /* @__PURE__ */ jsx(CommandGroup, { heading: "Skills", children: adapterCommands.map((cmd) => /* @__PURE__ */ jsxs(
6147
+ )),
6148
+ (menuMode === "skills" || menuMode === "all") && adapterCommands.map((cmd) => /* @__PURE__ */ jsxs(
6141
6149
  CommandItem,
6142
6150
  {
6143
6151
  value: cmd.value,
@@ -6148,7 +6156,7 @@ function ChatComposerInner({
6148
6156
  /* @__PURE__ */ jsx(
6149
6157
  "span",
6150
6158
  {
6151
- className: "font-mono text-foreground truncate",
6159
+ className: "font-mono font-semibold text-foreground truncate",
6152
6160
  title: cmd.label,
6153
6161
  children: cmd.label
6154
6162
  }
@@ -6156,7 +6164,7 @@ function ChatComposerInner({
6156
6164
  /* @__PURE__ */ jsx(
6157
6165
  "span",
6158
6166
  {
6159
- className: "min-w-0 truncate text-xs text-muted-foreground",
6167
+ className: "min-w-0 truncate text-sm text-muted-foreground",
6160
6168
  title: cmd.description,
6161
6169
  children: cmd.description
6162
6170
  }
@@ -6164,7 +6172,7 @@ function ChatComposerInner({
6164
6172
  ]
6165
6173
  },
6166
6174
  cmd.value
6167
- )) })
6175
+ ))
6168
6176
  ] })
6169
6177
  ] })
6170
6178
  }