@agent-native/toolkit 0.201.0-nightly-20261005153421 → 0.201.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.
@@ -171,7 +171,7 @@ function ProviderDialogContent(props: ProviderDialogProps) {
171
171
  const failed = listing.isError || models.isError;
172
172
  return (
173
173
  <DialogContent
174
- className="max-w-lg"
174
+ className="flex max-w-lg flex-col"
175
175
  closeLabel={t("agentChat.settingsInfra.close")}
176
176
  aria-describedby={undefined}
177
177
  >
@@ -496,7 +496,7 @@ function ProviderDialogForm({
496
496
  if (restricted) {
497
497
  return (
498
498
  <DialogContent
499
- className="max-w-lg"
499
+ className="flex max-w-lg flex-col"
500
500
  closeLabel={t("agentChat.settingsInfra.close")}
501
501
  aria-describedby={undefined}
502
502
  >
@@ -537,215 +537,220 @@ function ProviderDialogForm({
537
537
 
538
538
  return (
539
539
  <DialogContent
540
- className="max-w-lg"
540
+ className="flex max-w-lg flex-col overflow-hidden"
541
541
  closeLabel={t("agentChat.settingsInfra.close")}
542
542
  aria-describedby={undefined}
543
543
  >
544
- <DialogHeader>
544
+ <DialogHeader className="shrink-0">
545
545
  <DialogTitle>{title}</DialogTitle>
546
546
  </DialogHeader>
547
547
  <form
548
- className="grid gap-5"
548
+ className="flex min-h-0 flex-col gap-5"
549
549
  onSubmit={(event) => {
550
550
  event.preventDefault();
551
551
  void save();
552
552
  }}
553
553
  >
554
- {mode === "add" ? (
555
- <div className="grid gap-2">
556
- <Label htmlFor={ids.provider}>{t(`${K}provider`)}</Label>
557
- <Select
558
- value={provider}
559
- onValueChange={(value) =>
560
- chooseProvider(value as AgentProviderId)
561
- }
562
- disabled={saving}
563
- >
564
- <SelectTrigger id={ids.provider} autoFocus>
565
- <SelectValue />
566
- </SelectTrigger>
567
- <SelectContent>
568
- {choices.map((id) => (
569
- <SelectItem key={id} value={id}>
570
- <span className="flex items-center gap-2">
571
- <BrandLogo
572
- logoId={PROVIDER_LOGO_IDS[id]}
573
- fallback={IconServer}
574
- size="sm"
575
- />
576
- {providerLabel(id)}
577
- </span>
578
- </SelectItem>
579
- ))}
580
- </SelectContent>
581
- </Select>
582
- </div>
583
- ) : null}
584
-
585
- <div className="grid gap-2">
586
- <Label htmlFor={ids.key}>
587
- {isOllama ? t(`${K}endpointUrl`) : t(`${K}apiKey`)}
588
- </Label>
589
- {replacing ? (
590
- <Input
591
- ref={keyInputRef}
592
- id={ids.key}
593
- type={isOllama ? "url" : "password"}
594
- value={keyValue}
595
- autoComplete="off"
596
- spellCheck={false}
597
- autoFocus={mode !== "add"}
598
- disabled={saving}
599
- placeholder={
600
- isOllama
601
- ? OLLAMA_PLACEHOLDER
602
- : t(`${K}keyPlaceholder`, { provider: name })
603
- }
604
- aria-invalid={keyError || check.state === "failed"}
605
- aria-describedby={`${ids.key}-hint`}
606
- onChange={(event) => {
607
- setKeyValue(event.target.value);
608
- setKeyError(false);
609
- }}
610
- />
611
- ) : (
612
- <div className="flex h-9 items-center justify-between gap-2 rounded-md border border-input bg-background ps-3 pe-1.5">
613
- <span className="truncate font-mono text-sm">
614
- {isOllama ? existing?.endpoint : existing?.masked}
615
- </span>
616
- <Button
617
- type="button"
618
- variant="secondary"
619
- size="xs"
554
+ <div className="-mx-2 grid min-h-0 gap-5 overflow-y-auto px-2">
555
+ {mode === "add" ? (
556
+ <div className="grid gap-2">
557
+ <Label htmlFor={ids.provider}>{t(`${K}provider`)}</Label>
558
+ <Select
559
+ value={provider}
560
+ onValueChange={(value) =>
561
+ chooseProvider(value as AgentProviderId)
562
+ }
620
563
  disabled={saving}
621
- onClick={() => {
622
- setReplacing(true);
623
- window.requestAnimationFrame(() =>
624
- keyInputRef.current?.focus(),
625
- );
626
- }}
627
564
  >
628
- {isOllama ? t(`${K}change`) : t(`${K}replace`)}
629
- </Button>
565
+ <SelectTrigger id={ids.provider} autoFocus>
566
+ <SelectValue />
567
+ </SelectTrigger>
568
+ <SelectContent>
569
+ {choices.map((id) => (
570
+ <SelectItem key={id} value={id}>
571
+ <span className="flex items-center gap-2">
572
+ <BrandLogo
573
+ logoId={PROVIDER_LOGO_IDS[id]}
574
+ fallback={IconServer}
575
+ size="sm"
576
+ />
577
+ {providerLabel(id)}
578
+ </span>
579
+ </SelectItem>
580
+ ))}
581
+ </SelectContent>
582
+ </Select>
630
583
  </div>
631
- )}
632
- <KeyHint
633
- id={`${ids.key}-hint`}
634
- provider={provider}
635
- name={name}
636
- replacing={replacing}
637
- keyError={keyError}
638
- savedRejected={savedRejected}
639
- hasValue={!!keyValue.trim()}
640
- recheck={recheck}
641
- updatedAt={existing?.updatedAt ?? null}
642
- formatDate={(value, options) =>
643
- formatters.formatDate(value, options)
644
- }
645
- onRecheck={runRecheck}
646
- />
647
- </div>
584
+ ) : null}
648
585
 
649
- {isOpenAi ? (
650
- endpointOpen ? (
651
- <div className="grid gap-2">
652
- <Label htmlFor={ids.endpoint}>{t(`${K}endpointUrl`)}</Label>
586
+ <div className="grid gap-2">
587
+ <Label htmlFor={ids.key}>
588
+ {isOllama ? t(`${K}endpointUrl`) : t(`${K}apiKey`)}
589
+ </Label>
590
+ {replacing ? (
653
591
  <Input
654
- id={ids.endpoint}
655
- type="url"
656
- value={endpoint}
592
+ ref={keyInputRef}
593
+ id={ids.key}
594
+ type={isOllama ? "url" : "password"}
595
+ value={keyValue}
657
596
  autoComplete="off"
658
597
  spellCheck={false}
598
+ autoFocus={mode !== "add"}
659
599
  disabled={saving}
660
- placeholder={GATEWAY_PLACEHOLDER}
661
- onChange={(event) => setEndpoint(event.target.value)}
600
+ placeholder={
601
+ isOllama
602
+ ? OLLAMA_PLACEHOLDER
603
+ : t(`${K}keyPlaceholder`, { provider: name })
604
+ }
605
+ aria-invalid={keyError || check.state === "failed"}
606
+ aria-describedby={`${ids.key}-hint`}
607
+ onChange={(event) => {
608
+ setKeyValue(event.target.value);
609
+ setKeyError(false);
610
+ }}
662
611
  />
663
- <p className="text-xs leading-5 text-muted-foreground">
664
- {t(`${K}endpointHint`)}
665
- </p>
666
- </div>
667
- ) : (
668
- <button
669
- type="button"
670
- className="justify-self-start text-sm font-medium text-foreground underline-offset-4 hover:underline"
671
- onClick={() => setEndpointOpen(true)}
672
- >
673
- {t(`${K}addEndpoint`)}
674
- </button>
675
- )
676
- ) : null}
612
+ ) : (
613
+ <div className="flex h-9 items-center justify-between gap-2 rounded-md border border-input bg-background ps-3 pe-1.5">
614
+ <span className="truncate font-mono text-sm">
615
+ {isOllama ? existing?.endpoint : existing?.masked}
616
+ </span>
617
+ <Button
618
+ type="button"
619
+ variant="secondary"
620
+ size="xs"
621
+ disabled={saving}
622
+ onClick={() => {
623
+ setReplacing(true);
624
+ window.requestAnimationFrame(() =>
625
+ keyInputRef.current?.focus(),
626
+ );
627
+ }}
628
+ >
629
+ {isOllama ? t(`${K}change`) : t(`${K}replace`)}
630
+ </Button>
631
+ </div>
632
+ )}
633
+ <KeyHint
634
+ id={`${ids.key}-hint`}
635
+ provider={provider}
636
+ name={name}
637
+ replacing={replacing}
638
+ keyError={keyError}
639
+ savedRejected={savedRejected}
640
+ hasValue={!!keyValue.trim()}
641
+ recheck={recheck}
642
+ updatedAt={existing?.updatedAt ?? null}
643
+ formatDate={(value, options) =>
644
+ formatters.formatDate(value, options)
645
+ }
646
+ onRecheck={runRecheck}
647
+ />
648
+ </div>
677
649
 
678
- <div className="grid gap-2">
679
- <div className="flex min-h-5 items-center justify-between gap-2">
680
- <span id={ids.models} className="text-sm font-medium leading-none">
681
- {t(`${K}models`)}
682
- </span>
683
- {listReady && available.length > 0 ? (
650
+ {isOpenAi ? (
651
+ endpointOpen ? (
652
+ <div className="grid gap-2">
653
+ <Label htmlFor={ids.endpoint}>{t(`${K}endpointUrl`)}</Label>
654
+ <Input
655
+ id={ids.endpoint}
656
+ type="url"
657
+ value={endpoint}
658
+ autoComplete="off"
659
+ spellCheck={false}
660
+ disabled={saving}
661
+ placeholder={GATEWAY_PLACEHOLDER}
662
+ onChange={(event) => setEndpoint(event.target.value)}
663
+ />
664
+ <p className="text-xs leading-5 text-muted-foreground">
665
+ {t(`${K}endpointHint`)}
666
+ </p>
667
+ </div>
668
+ ) : (
684
669
  <button
685
670
  type="button"
686
- className="text-sm font-medium text-foreground underline-offset-4 hover:underline"
687
- onClick={() => setChecked(allChecked ? [] : [...available])}
671
+ className="justify-self-start text-sm font-medium text-foreground underline-offset-4 hover:underline"
672
+ onClick={() => setEndpointOpen(true)}
688
673
  >
689
- {allChecked ? t(`${K}clear`) : t(`${K}selectAll`)}
674
+ {t(`${K}addEndpoint`)}
690
675
  </button>
691
- ) : null}
676
+ )
677
+ ) : null}
678
+
679
+ <div className="grid gap-2">
680
+ <div className="flex min-h-5 items-center justify-between gap-2">
681
+ <span
682
+ id={ids.models}
683
+ className="text-sm font-medium leading-none"
684
+ >
685
+ {t(`${K}models`)}
686
+ </span>
687
+ {listReady && available.length > 0 ? (
688
+ <button
689
+ type="button"
690
+ className="text-sm font-medium text-foreground underline-offset-4 hover:underline"
691
+ onClick={() => setChecked(allChecked ? [] : [...available])}
692
+ >
693
+ {allChecked ? t(`${K}clear`) : t(`${K}selectAll`)}
694
+ </button>
695
+ ) : null}
696
+ </div>
697
+ <div
698
+ role="group"
699
+ aria-labelledby={ids.models}
700
+ className="h-44 overflow-y-auto rounded-md border border-input"
701
+ >
702
+ <ModelsBox
703
+ idPrefix={ids.models}
704
+ check={check}
705
+ listReady={listReady}
706
+ available={available}
707
+ checked={checked}
708
+ isOllama={isOllama}
709
+ name={name}
710
+ disabled={saving}
711
+ onToggle={(model, on) =>
712
+ setChecked((previous) =>
713
+ on
714
+ ? available.filter(
715
+ (item) => item === model || previous.includes(item),
716
+ )
717
+ : previous.filter((item) => item !== model),
718
+ )
719
+ }
720
+ />
721
+ </div>
722
+ <p className="text-xs leading-5 text-muted-foreground">
723
+ {fromService && serviceLabel
724
+ ? t(`${K}modelsHintService`, { service: serviceLabel })
725
+ : t(`${K}modelsHint`)}
726
+ </p>
692
727
  </div>
693
- <div
694
- role="group"
695
- aria-labelledby={ids.models}
696
- className="h-44 overflow-y-auto rounded-md border border-input"
697
- >
698
- <ModelsBox
699
- idPrefix={ids.models}
700
- check={check}
701
- listReady={listReady}
702
- available={available}
703
- checked={checked}
704
- isOllama={isOllama}
705
- name={name}
728
+
729
+ {listing.hasOrganization ? (
730
+ <WhoField
731
+ id={ids.who}
732
+ hint={whoHint(
733
+ t,
734
+ replaceTarget ? "manage" : mode,
735
+ mode === "add" && whoChoice && !replaceTarget,
736
+ orgName,
737
+ )}
738
+ choice={mode === "add" && whoChoice && !replaceTarget}
739
+ scope={scope}
706
740
  disabled={saving}
707
- onToggle={(model, on) =>
708
- setChecked((previous) =>
709
- on
710
- ? available.filter(
711
- (item) => item === model || previous.includes(item),
712
- )
713
- : previous.filter((item) => item !== model),
714
- )
715
- }
741
+ onChange={setScope}
716
742
  />
717
- </div>
718
- <p className="text-xs leading-5 text-muted-foreground">
719
- {fromService && serviceLabel
720
- ? t(`${K}modelsHintService`, { service: serviceLabel })
721
- : t(`${K}modelsHint`)}
722
- </p>
723
- </div>
724
-
725
- {listing.hasOrganization ? (
726
- <WhoField
727
- id={ids.who}
728
- hint={whoHint(
729
- t,
730
- replaceTarget ? "manage" : mode,
731
- mode === "add" && whoChoice && !replaceTarget,
732
- orgName,
733
- )}
734
- choice={mode === "add" && whoChoice && !replaceTarget}
735
- scope={scope}
736
- disabled={saving}
737
- onChange={setScope}
738
- />
739
- ) : null}
743
+ ) : null}
740
744
 
741
- {error ? (
742
- <Alert variant="destructive">
743
- <IconAlertCircle />
744
- <AlertDescription>{error}</AlertDescription>
745
- </Alert>
746
- ) : null}
745
+ {error ? (
746
+ <Alert variant="destructive">
747
+ <IconAlertCircle />
748
+ <AlertDescription>{error}</AlertDescription>
749
+ </Alert>
750
+ ) : null}
751
+ </div>
747
752
 
748
- <DialogFooter className="gap-2 sm:space-x-0">
753
+ <DialogFooter className="shrink-0 gap-2 sm:space-x-0">
749
754
  {mode === "manage" ? (
750
755
  <Button
751
756
  type="button"
@@ -1,6 +1,9 @@
1
1
  import { useEffect } from "react";
2
2
 
3
- export function useHomeSearchShortcut(enabled: boolean): void {
3
+ export function useHomeSearchShortcut(
4
+ enabled: boolean,
5
+ revealSearch?: () => boolean,
6
+ ): void {
4
7
  useEffect(() => {
5
8
  if (!enabled) return;
6
9
  const onKeyDown = (event: KeyboardEvent) => {
@@ -27,14 +30,26 @@ export function useHomeSearchShortcut(enabled: boolean): void {
27
30
  ) {
28
31
  return;
29
32
  }
30
- const search = Array.from(
31
- document.querySelectorAll<HTMLInputElement>("[data-home-search]"),
32
- ).find((input) => input.getClientRects().length > 0);
33
- if (!search || search.disabled) return;
33
+ const findSearch = () =>
34
+ Array.from(
35
+ document.querySelectorAll<HTMLInputElement>("[data-home-search]"),
36
+ ).find((input) => input.getClientRects().length > 0);
37
+ const search = findSearch();
38
+ if (search && !search.disabled) {
39
+ event.preventDefault();
40
+ search.focus();
41
+ return;
42
+ }
43
+ if (!revealSearch?.()) return;
34
44
  event.preventDefault();
35
- search.focus();
45
+ window.requestAnimationFrame(() => {
46
+ const revealedSearch = findSearch();
47
+ if (revealedSearch && !revealedSearch.disabled) {
48
+ revealedSearch.focus();
49
+ }
50
+ });
36
51
  };
37
52
  document.addEventListener("keydown", onKeyDown);
38
53
  return () => document.removeEventListener("keydown", onKeyDown);
39
- }, [enabled]);
54
+ }, [enabled, revealSearch]);
40
55
  }
@@ -138,8 +138,10 @@ DropdownMenuCheckboxItem.displayName =
138
138
 
139
139
  const DropdownMenuRadioItem = React.forwardRef<
140
140
  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
141
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
142
- >(({ className, children, ...props }, ref) => (
141
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> & {
142
+ indicator?: "circle" | "check";
143
+ }
144
+ >(({ className, children, indicator = "circle", ...props }, ref) => (
143
145
  <DropdownMenuPrimitive.RadioItem
144
146
  ref={ref}
145
147
  className={cn(
@@ -150,7 +152,11 @@ const DropdownMenuRadioItem = React.forwardRef<
150
152
  >
151
153
  <span className="absolute start-2 flex h-3.5 w-3.5 items-center justify-center">
152
154
  <DropdownMenuPrimitive.ItemIndicator>
153
- <IconCircle className="h-2 w-2 fill-current" />
155
+ {indicator === "check" ? (
156
+ <IconCheck className="h-4 w-4" />
157
+ ) : (
158
+ <IconCircle className="h-2 w-2 fill-current" />
159
+ )}
154
160
  </DropdownMenuPrimitive.ItemIndicator>
155
161
  </span>
156
162
  {children}