AkurAI Build
Menu

popagent

public

Latest change 53b750b193f23dd583eb784579b26e92200bda45 - Expose fusion orchestration and local agent roles by AkurAI Build

import { CheckCircle2, ChevronDown, Cpu, Hammer, Search, Sparkles, Zap } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import type { ModelProfile } from "../api-types";
import { filterModels, groupModels, modelLabel } from "./model-picker";
import { useFocusTrap } from "./use-focus-trap";

export function ModelPicker({
  models,
  profiles,
  value,
  onChange,
}: {
  models: string[];
  profiles: Record<string, ModelProfile>;
  value: string;
  onChange: (model: string) => void;
}) {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const buttonRef = useRef<HTMLButtonElement>(null);
  const searchRef = useRef<HTMLInputElement>(null);
  const popoverRef = useRef<HTMLDivElement>(null);
  const grouped = useMemo(() => groupModels(filterModels(models, query)), [models, query]);

  useEffect(() => {
    if (!open) return;
    searchRef.current?.focus();
    const close = (event: KeyboardEvent) => {
      if (event.key !== "Escape") return;
      setOpen(false);
      buttonRef.current?.focus();
    };
    document.addEventListener("keydown", close);
    return () => document.removeEventListener("keydown", close);
  }, [open]);

  const choose = (model: string) => {
    onChange(model);
    setOpen(false);
    setQuery("");
    buttonRef.current?.focus();
  };
  useFocusTrap(popoverRef, open);

  const activeProfile = profiles[value];
  const ActiveIcon = activeProfile?.role === "orchestrator"
    ? Sparkles
    : activeProfile?.role === "fast"
      ? Zap
      : activeProfile?.role === "local"
        ? Hammer
        : Cpu;
  return (
    <div className="relative">
      <button ref={buttonRef} type="button" aria-haspopup="dialog" aria-expanded={open} onClick={() => setOpen((current) => !current)} className="liquid-control flex min-h-10 max-w-56 items-center gap-2 rounded px-3 text-left text-sm text-ink md:max-w-72">
        <ActiveIcon className="size-4 shrink-0 text-accent" />
        <span className="min-w-0 flex-1 truncate">{activeProfile?.label ?? modelLabel(value)}</span>
        <ChevronDown className="size-3.5 shrink-0 text-ink-muted" />
      </button>
      {open ? (
        <>
          <button type="button" aria-label="Close model picker" onClick={() => setOpen(false)} className="fixed inset-0 z-20 cursor-default" />
          <div ref={popoverRef} role="dialog" aria-label="Choose model" className="liquid-popover fixed inset-x-3 top-20 z-30 max-h-[70dvh] overflow-hidden border shadow-2xl md:absolute md:inset-x-auto md:right-0 md:top-12 md:w-96">
            <label className="liquid-control m-3 flex min-h-11 items-center gap-2 rounded px-3">
              <Search className="size-4 text-ink-muted" />
              <input ref={searchRef} aria-label="Search models" value={query} onChange={(event) => setQuery(event.currentTarget.value)} placeholder="Search models or providers" className="min-w-0 flex-1 bg-transparent text-sm outline-none" />
            </label>
            <div className="max-h-[calc(70dvh-4.5rem)] overflow-y-auto px-2 pb-2">
              {grouped.map((group) => (
                <section key={group.provider} aria-labelledby={`provider-${group.provider}`}>
                  <h3 id={`provider-${group.provider}`} className="px-2 pb-1 pt-3 text-[11px] font-medium uppercase tracking-[0.12em] text-ink-dim">{group.provider}</h3>
                  {group.models.map((model) => {
                    const profile = profiles[model];
                    const ProfileIcon = profile?.role === "orchestrator" ? Sparkles : profile?.role === "fast" ? Zap : profile?.role === "local" ? Hammer : Cpu;
                    return <button key={model} type="button" onClick={() => choose(model)} className={`flex min-h-11 w-full items-center gap-2 rounded px-2 py-2 text-left hover:bg-panel-2 ${model === value ? "bg-accent-soft text-ink" : "text-ink-muted"}`}>
                      <ProfileIcon className={`size-4 shrink-0 ${profile ? "text-accent" : "text-ink-dim"}`} />
                      <span className="min-w-0 flex-1">
                        <span className="flex items-center gap-2">
                          <span className="block truncate text-sm text-ink">{profile?.label ?? modelLabel(model)}</span>
                          {profile ? <span className="rounded-full border border-accent/20 bg-accent-soft px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-[0.08em] text-accent">{profile.role}</span> : null}
                        </span>
                        <span className="block truncate text-[11px]">{profile?.summary ?? model}</span>
                      </span>
                      {model === value ? <CheckCircle2 className="size-4 shrink-0 text-accent" /> : null}
                    </button>;
                  })}
                </section>
              ))}
              {!grouped.length ? <p className="p-6 text-center text-sm text-ink-muted">{models.length ? "No matching models" : "Model catalog unavailable"}</p> : null}
            </div>
          </div>
        </>
      ) : null}
    </div>
  );
}