@tangle-network/agent-app 0.45.65 → 0.46.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 (39) hide show
  1. package/dist/assistant/index.js +3 -3
  2. package/dist/chat-react/index.js +2 -2
  3. package/dist/chunk-2RTYQU4W.js +441 -0
  4. package/dist/chunk-2RTYQU4W.js.map +1 -0
  5. package/dist/{chunk-23J72UUA.js → chunk-DINGA2MO.js} +94 -560
  6. package/dist/chunk-DINGA2MO.js.map +1 -0
  7. package/dist/{chunk-AWM4H5XR.js → chunk-MBKNKAN2.js} +6 -4
  8. package/dist/{chunk-AWM4H5XR.js.map → chunk-MBKNKAN2.js.map} +1 -1
  9. package/dist/chunk-YDOQE47G.js +518 -0
  10. package/dist/chunk-YDOQE47G.js.map +1 -0
  11. package/dist/stories/studio/fixtures.d.ts +0 -4
  12. package/dist/studio/generation.d.ts +16 -74
  13. package/dist/studio/index.d.ts +2 -2
  14. package/dist/studio/index.js +27 -25
  15. package/dist/studio/model-options.d.ts +61 -0
  16. package/dist/studio-react/composer-option-controls.d.ts +140 -0
  17. package/dist/studio-react/generation-notice.d.ts +18 -0
  18. package/dist/studio-react/index.d.ts +6 -12
  19. package/dist/studio-react/index.js +902 -827
  20. package/dist/studio-react/index.js.map +1 -1
  21. package/dist/studio-react/studio-composer.d.ts +34 -0
  22. package/dist/studio-react/studio-workspace.d.ts +2 -4
  23. package/dist/studio-react/studio.css +51 -0
  24. package/dist/theme/tokens.css +18 -0
  25. package/dist/web-react/index.js +11 -11
  26. package/package.json +1 -1
  27. package/dist/chunk-23J72UUA.js.map +0 -1
  28. package/dist/chunk-HSBJB46C.js +0 -305
  29. package/dist/chunk-HSBJB46C.js.map +0 -1
  30. package/dist/chunk-MLG6XKPV.js +0 -44
  31. package/dist/chunk-MLG6XKPV.js.map +0 -1
  32. package/dist/studio-react/avatar-composer.d.ts +0 -8
  33. package/dist/studio-react/composer-hero.d.ts +0 -12
  34. package/dist/studio-react/composer-shell.d.ts +0 -18
  35. package/dist/studio-react/image-composer.d.ts +0 -8
  36. package/dist/studio-react/publish-package-composer.d.ts +0 -18
  37. package/dist/studio-react/speech-composer.d.ts +0 -4
  38. package/dist/studio-react/transcription-composer.d.ts +0 -12
  39. package/dist/studio-react/video-composer.d.ts +0 -10
@@ -0,0 +1,518 @@
1
+ // src/web-react/provider-logo.tsx
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ var LOGOS = {
4
+ anthropic: { viewBox: "0 0 24 24", fill: "#D97757", paths: ["M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"] },
5
+ google: { viewBox: "0 0 24 24", fill: "#8E75B2", paths: ["M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81"] },
6
+ deepseek: { viewBox: "0 0 24 24", fill: "#4D6BFE", paths: ["M23.748 4.651c-.254-.124-.364.113-.512.233-.051.04-.094.09-.137.137-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.155-.708-.311-.955-.65-.172-.24-.219-.509-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.094.172.187.129.323-.082.28-.18.553-.266.833-.055.179-.137.218-.328.14a5.5 5.5 0 0 1-1.737-1.179c-.857-.828-1.631-1.743-2.597-2.46a12 12 0 0 0-.689-.47c-.985-.957.13-1.743.387-1.836.27-.098.094-.433-.778-.428-.872.003-1.67.295-2.687.685a3 3 0 0 1-.465.136 9.6 9.6 0 0 0-2.883-.101c-1.885.21-3.39 1.1-4.497 2.622C.082 8.776-.231 10.854.152 13.02c.403 2.284 1.568 4.175 3.36 5.653 1.857 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.132-.284 4.994-1.86.47.234.962.328 1.78.398.629.058 1.235-.031 1.705-.129.735-.155.684-.836.418-.961-2.155-1.004-1.682-.595-2.112-.926 1.095-1.295 2.768-3.598 3.284-6.733.05-.346.115-.834.108-1.114-.004-.171.035-.238.23-.257a4.2 4.2 0 0 0 1.545-.475c1.397-.763 1.96-2.016 2.093-3.517.02-.23-.004-.467-.247-.588M11.58 18.168c-2.088-1.642-3.101-2.183-3.52-2.16-.39.024-.32.472-.234.763.09.288.207.487.371.74.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.168-1.361-.801-2.5-1.86-3.301-3.306-.775-1.393-1.225-2.888-1.299-4.482-.02-.385.094-.522.477-.592a4.7 4.7 0 0 1 1.53-.038c2.131.311 3.946 1.264 5.467 2.774.868.86 1.525 1.887 2.202 2.89.72 1.066 1.494 2.082 2.48 2.915.348.291.626.513.892.677-.802.09-2.14.109-3.055-.615zm1.001-6.44a.306.306 0 0 1 .415-.287.3.3 0 0 1 .113.074.3.3 0 0 1 .086.214c0 .17-.136.307-.308.307a.303.303 0 0 1-.306-.307m3.11 1.596c-.2.081-.4.151-.591.16a1.25 1.25 0 0 1-.798-.254c-.274-.23-.47-.358-.551-.758a1.7 1.7 0 0 1 .015-.588c.07-.327-.007-.537-.238-.727-.188-.156-.426-.199-.689-.199a.6.6 0 0 1-.254-.078.253.253 0 0 1-.114-.358 1 1 0 0 1 .192-.21c.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.392.451.462.576.685.915.176.264.336.536.446.848.066.194-.02.353-.25.45"] },
7
+ mistral: { viewBox: "0 0 24 24", fill: "#FA520F", paths: ["M17.143 3.429v3.428h-3.429v3.429h-3.428V6.857H6.857V3.43H3.43v13.714H0v3.428h10.286v-3.428H6.857v-3.429h3.429v3.429h3.429v-3.429h3.428v3.429h-3.428v3.428H24v-3.428h-3.43V3.429z"] },
8
+ xai: { viewBox: "0 0 24 24", fill: "#000000", paths: ["M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z"] },
9
+ nvidia: { viewBox: "0 0 24 24", fill: "#76B900", paths: ["M8.948 8.798v-1.43a6.7 6.7 0 0 1 .424-.018c3.922-.124 6.493 3.374 6.493 3.374s-2.774 3.851-5.75 3.851c-.398 0-.787-.062-1.158-.185v-4.346c1.528.185 1.837.857 2.747 2.385l2.04-1.714s-1.492-1.952-4-1.952a6.016 6.016 0 0 0-.796.035m0-4.735v2.138l.424-.027c5.45-.185 9.01 4.47 9.01 4.47s-4.08 4.964-8.33 4.964c-.37 0-.733-.035-1.095-.097v1.325c.3.035.61.062.91.062 3.957 0 6.82-2.023 9.593-4.408.459.371 2.34 1.263 2.73 1.652-2.633 2.208-8.772 3.984-12.253 3.984-.335 0-.653-.018-.971-.053v1.864H24V4.063zm0 10.326v1.131c-3.657-.654-4.673-4.46-4.673-4.46s1.758-1.944 4.673-2.262v1.237H8.94c-1.528-.186-2.73 1.245-2.73 1.245s.68 2.412 2.739 3.11M2.456 10.9s2.164-3.197 6.5-3.533V6.201C4.153 6.59 0 10.653 0 10.653s2.35 6.802 8.948 7.42v-1.237c-4.84-.6-6.492-5.936-6.492-5.936z"] },
10
+ meta: { viewBox: "0 0 24 24", fill: "#0467DF", paths: ["M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z"] },
11
+ moonshotai: { viewBox: "0 0 24 24", fill: "#16191E", paths: ["m1.053 16.91 9.538 2.55a21 20.981 0 0 0 .06 2.031l5.956 1.592a12 11.99 0 0 1-15.554-6.172m-1.02-5.79 11.352 3.035a21 20.981 0 0 0-.469 2.01l10.817 2.89a12 11.99 0 0 1-1.845 2.004L.658 15.918a12 11.99 0 0 1-.625-4.796m1.593-5.146L13.573 9.17a21 20.981 0 0 0-1.01 1.874l11.297 3.02a21 20.981 0 0 1-.67 2.362l-11.55-3.087L.125 10.26a12 11.99 0 0 1 1.499-4.285ZM6.067 1.58l11.285 3.016a21 20.981 0 0 0-1.688 1.719l7.824 2.091a21 20.981 0 0 1 .513 2.664L2.107 5.218a12 11.99 0 0 1 3.96-3.638M21.68 4.866 7.222 1.003A12 11.99 0 0 1 21.68 4.866"] },
12
+ openai: { viewBox: "0 0 256 260", fill: "#10A37F", paths: ["M239.184 106.203a64.72 64.72 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.72 64.72 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.67 64.67 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.77 64.77 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483m-97.56 136.338a48.4 48.4 0 0 1-31.105-11.255l1.535-.87l51.67-29.825a8.6 8.6 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601M37.158 197.93a48.35 48.35 0 0 1-5.781-32.589l1.534.921l51.722 29.826a8.34 8.34 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803M23.549 85.38a48.5 48.5 0 0 1 25.58-21.333v61.39a8.29 8.29 0 0 0 4.195 7.316l62.874 36.272l-21.845 12.636a.82.82 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405zm179.466 41.695l-63.08-36.63L161.73 77.86a.82.82 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.54 8.54 0 0 0-4.4-7.213m21.742-32.69l-1.535-.922l-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.72.72 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391zM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87l-51.67 29.825a8.6 8.6 0 0 0-4.246 7.367zm11.868-25.58L128.067 97.3l28.188 16.218v32.434l-28.086 16.218l-28.188-16.218z"] }
13
+ };
14
+ var ALIASES = {
15
+ moonshot: "moonshotai",
16
+ deepseek_ai: "deepseek",
17
+ "x-ai": "xai",
18
+ "meta-llama": "meta"
19
+ };
20
+ var MONOGRAM = {
21
+ cohere: { bg: "#fae8ff", fg: "#c026d3" },
22
+ groq: { bg: "#fce7f3", fg: "#db2777" },
23
+ cerebras: { bg: "#ccfbf1", fg: "#0d9488" },
24
+ zai: { bg: "#ede9fe", fg: "#7c3aed" },
25
+ "z-ai": { bg: "#ede9fe", fg: "#7c3aed" },
26
+ tuner: { bg: "#dbeafe", fg: "#2563eb" }
27
+ };
28
+ function ProviderLogo({ provider, size = 16 }) {
29
+ const key = ALIASES[provider ?? ""] ?? provider ?? "";
30
+ const logo = LOGOS[key];
31
+ if (logo) {
32
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: logo.viewBox, role: "img", "aria-label": key, children: logo.paths.map((d, i) => /* @__PURE__ */ jsx("path", { d, fill: logo.fill }, i)) });
33
+ }
34
+ const mono = MONOGRAM[key];
35
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 16 16", role: "img", "aria-label": key || "model", children: [
36
+ /* @__PURE__ */ jsx("rect", { width: "16", height: "16", rx: "4", style: { fill: mono ? mono.bg : "hsl(var(--secondary))" } }),
37
+ /* @__PURE__ */ jsx("text", { x: "8", y: "11.6", textAnchor: "middle", style: { fill: mono ? mono.fg : "hsl(var(--muted-foreground))" }, fontSize: "9", fontWeight: "700", fontFamily: "system-ui, sans-serif", children: (key || "?").charAt(0).toUpperCase() })
38
+ ] });
39
+ }
40
+
41
+ // src/web-react/controls.tsx
42
+ import {
43
+ useCallback,
44
+ useEffect,
45
+ useId,
46
+ useLayoutEffect,
47
+ useMemo,
48
+ useRef,
49
+ useState
50
+ } from "react";
51
+ import { createPortal } from "react-dom";
52
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
53
+ function ChevronDown({ className }) {
54
+ return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }) });
55
+ }
56
+ function SearchGlyph({ className }) {
57
+ return /* @__PURE__ */ jsxs2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
58
+ /* @__PURE__ */ jsx2("circle", { cx: "11", cy: "11", r: "8" }),
59
+ /* @__PURE__ */ jsx2("path", { d: "m21 21-4.3-4.3" })
60
+ ] });
61
+ }
62
+ function SparkleGlyph({ className }) {
63
+ return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1M7.7 16.3l-2.1 2.1" }) });
64
+ }
65
+ function BrainGlyph({ className }) {
66
+ return /* @__PURE__ */ jsxs2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
67
+ /* @__PURE__ */ jsx2("path", { d: "M12 18V5" }),
68
+ /* @__PURE__ */ jsx2("path", { d: "M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4" }),
69
+ /* @__PURE__ */ jsx2("path", { d: "M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5" }),
70
+ /* @__PURE__ */ jsx2("path", { d: "M17.997 5.125a4 4 0 0 1 2.526 5.77" }),
71
+ /* @__PURE__ */ jsx2("path", { d: "M18 18a4 4 0 0 0 2-7.464" }),
72
+ /* @__PURE__ */ jsx2("path", { d: "M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517" }),
73
+ /* @__PURE__ */ jsx2("path", { d: "M6 18a4 4 0 0 1-2-7.464" }),
74
+ /* @__PURE__ */ jsx2("path", { d: "M6.003 5.125a4 4 0 0 0-2.526 5.77" })
75
+ ] });
76
+ }
77
+ function CheckGlyph({ className }) {
78
+ return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "M20 6 9 17l-5-5" }) });
79
+ }
80
+ function usePopover(open, setOpen) {
81
+ const containerRef = useRef(null);
82
+ const triggerRef = useRef(null);
83
+ const panelRef = useRef(null);
84
+ useEffect(() => {
85
+ if (!open) return;
86
+ function onMouseDown(e) {
87
+ const target = e.target;
88
+ if (containerRef.current?.contains(target)) return;
89
+ const panel = panelRef.current;
90
+ if (panel?.contains(target)) return;
91
+ const ownPath = panel?.getAttribute(POPOVER_SURFACE_ATTR);
92
+ const hitPath = target instanceof Element ? target.closest(`[${POPOVER_SURFACE_ATTR}]`)?.getAttribute(POPOVER_SURFACE_ATTR) : null;
93
+ if (ownPath && hitPath && (hitPath === ownPath || hitPath.startsWith(`${ownPath}${POPOVER_PATH_SEPARATOR}`))) return;
94
+ setOpen(false);
95
+ }
96
+ function onKeyDown(e) {
97
+ if (e.key === "Escape") {
98
+ setOpen(false);
99
+ triggerRef.current?.focus();
100
+ }
101
+ }
102
+ document.addEventListener("mousedown", onMouseDown);
103
+ document.addEventListener("keydown", onKeyDown);
104
+ return () => {
105
+ document.removeEventListener("mousedown", onMouseDown);
106
+ document.removeEventListener("keydown", onKeyDown);
107
+ };
108
+ }, [open, setOpen]);
109
+ return {
110
+ containerRef,
111
+ triggerRef,
112
+ panelRef,
113
+ triggerProps: {
114
+ ref: triggerRef,
115
+ "aria-haspopup": true,
116
+ "aria-expanded": open
117
+ }
118
+ };
119
+ }
120
+ var POPOVER_GAP = 8;
121
+ var POPOVER_VIEWPORT_MARGIN = 16;
122
+ var POPOVER_MIN_HEIGHT = 120;
123
+ var POPOVER_SURFACE_ATTR = "data-agent-app-popover";
124
+ var POPOVER_PATH_SEPARATOR = "/";
125
+ var useBrowserLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
126
+ function PopoverSurface({
127
+ open,
128
+ triggerRef,
129
+ panelRef,
130
+ className,
131
+ role,
132
+ id,
133
+ matchTriggerWidth,
134
+ children
135
+ }) {
136
+ const surfaceId = useId();
137
+ const [style, setStyle] = useState(() => ({
138
+ position: "fixed",
139
+ top: 0,
140
+ left: 0,
141
+ visibility: "hidden"
142
+ }));
143
+ const place = useCallback(() => {
144
+ const trigger = triggerRef.current;
145
+ const panel = panelRef.current;
146
+ if (!trigger || !panel) return;
147
+ const anchor = trigger.getBoundingClientRect();
148
+ const viewportWidth = window.innerWidth;
149
+ const viewportHeight = window.innerHeight;
150
+ const contentHeight = panel.scrollHeight;
151
+ const panelWidth = panel.offsetWidth;
152
+ const roomAbove = anchor.top - POPOVER_GAP - POPOVER_VIEWPORT_MARGIN;
153
+ const roomBelow = viewportHeight - anchor.bottom - POPOVER_GAP - POPOVER_VIEWPORT_MARGIN;
154
+ const above = contentHeight <= roomAbove || roomAbove >= roomBelow;
155
+ const maxHeight = Math.max(POPOVER_MIN_HEIGHT, above ? roomAbove : roomBelow);
156
+ const height = Math.min(contentHeight, maxHeight);
157
+ const top = above ? Math.max(POPOVER_VIEWPORT_MARGIN, anchor.top - POPOVER_GAP - height) : anchor.bottom + POPOVER_GAP;
158
+ const rightBound = Math.max(POPOVER_VIEWPORT_MARGIN, viewportWidth - panelWidth - POPOVER_VIEWPORT_MARGIN);
159
+ const left = Math.min(Math.max(POPOVER_VIEWPORT_MARGIN, anchor.left), rightBound);
160
+ setStyle({
161
+ position: "fixed",
162
+ top,
163
+ left,
164
+ maxHeight,
165
+ visibility: "visible",
166
+ ...matchTriggerWidth ? { minWidth: anchor.width } : {}
167
+ });
168
+ }, [matchTriggerWidth, panelRef, triggerRef]);
169
+ useBrowserLayoutEffect(() => {
170
+ if (!open) {
171
+ setStyle({ position: "fixed", top: 0, left: 0, visibility: "hidden" });
172
+ return;
173
+ }
174
+ place();
175
+ }, [open, place]);
176
+ useEffect(() => {
177
+ if (!open) return;
178
+ const onViewportChange = () => place();
179
+ window.addEventListener("scroll", onViewportChange, true);
180
+ window.addEventListener("resize", onViewportChange);
181
+ return () => {
182
+ window.removeEventListener("scroll", onViewportChange, true);
183
+ window.removeEventListener("resize", onViewportChange);
184
+ };
185
+ }, [open, place]);
186
+ if (!open || typeof document === "undefined") return null;
187
+ const ownerPath = triggerRef.current?.closest?.(`[${POPOVER_SURFACE_ATTR}]`)?.getAttribute(POPOVER_SURFACE_ATTR);
188
+ const path = ownerPath ? `${ownerPath}${POPOVER_PATH_SEPARATOR}${surfaceId}` : surfaceId;
189
+ return createPortal(
190
+ /* @__PURE__ */ jsx2(
191
+ "div",
192
+ {
193
+ ref: panelRef,
194
+ id,
195
+ role,
196
+ style,
197
+ ...{ [POPOVER_SURFACE_ATTR]: path },
198
+ className: `z-[1000] ${className ?? ""}`,
199
+ children
200
+ }
201
+ ),
202
+ document.body
203
+ );
204
+ }
205
+ var POPOVER_OPTION_FOCUS = "focus-visible:[outline-offset:-2px]";
206
+ var OVERLAY_SHADOW = "shadow-[var(--shadow-overlay)]";
207
+ function pickerRootClass(fullWidth) {
208
+ return `relative ${fullWidth ? "flex w-full" : "inline-flex"}`;
209
+ }
210
+ function usePending() {
211
+ const [pending, setPending] = useState(false);
212
+ const inFlight = useRef(false);
213
+ const mounted = useRef(true);
214
+ useEffect(() => {
215
+ mounted.current = true;
216
+ return () => {
217
+ mounted.current = false;
218
+ };
219
+ }, []);
220
+ const run = (action) => {
221
+ if (inFlight.current) return;
222
+ let result;
223
+ try {
224
+ result = action();
225
+ } catch {
226
+ return;
227
+ }
228
+ if (!(result instanceof Promise)) return;
229
+ inFlight.current = true;
230
+ setPending(true);
231
+ void result.finally(() => {
232
+ inFlight.current = false;
233
+ if (mounted.current) setPending(false);
234
+ });
235
+ };
236
+ return { pending, run };
237
+ }
238
+ function formatPrice(p) {
239
+ if (!p) return void 0;
240
+ const n = Number(p);
241
+ if (isNaN(n) || n === 0) return void 0;
242
+ const perM = n * 1e6;
243
+ return perM >= 1 ? `$${perM.toFixed(0)}/M` : `$${perM.toFixed(2)}/M`;
244
+ }
245
+ function formatContext(len) {
246
+ if (!len) return void 0;
247
+ if (len >= 1e6) return `${(len / 1e6).toFixed(1)}M ctx`;
248
+ if (len >= 1e3) return `${Math.round(len / 1e3)}K ctx`;
249
+ return `${len} ctx`;
250
+ }
251
+ function SectionHeader({ children }) {
252
+ return /* @__PURE__ */ jsx2("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children });
253
+ }
254
+ function ModelRow({
255
+ model,
256
+ selected,
257
+ onSelect,
258
+ renderProviderBadge
259
+ }) {
260
+ const price = formatPrice(model.pricing?.prompt);
261
+ const ctx = formatContext(model.contextLength);
262
+ return /* @__PURE__ */ jsxs2(
263
+ "button",
264
+ {
265
+ type: "button",
266
+ onClick: onSelect,
267
+ className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${selected ? "bg-primary/10 font-medium" : "hover:bg-accent"}`,
268
+ children: [
269
+ renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx2(ProviderLogo, { provider: model.provider, size: 16 }),
270
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: model.name }),
271
+ !model.supportsTools && /* @__PURE__ */ jsx2("span", { className: "shrink-0 rounded bg-secondary px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: "no tools" }),
272
+ /* @__PURE__ */ jsxs2("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground", children: [
273
+ ctx && /* @__PURE__ */ jsx2("span", { children: ctx }),
274
+ price && /* @__PURE__ */ jsx2("span", { children: price })
275
+ ] })
276
+ ]
277
+ }
278
+ );
279
+ }
280
+ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel = "Recommended", priorityGroup }) {
281
+ const [open, setOpen] = useState(false);
282
+ const [query, setQuery] = useState("");
283
+ const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
284
+ const inputRef = useRef(null);
285
+ const panelId = useId();
286
+ useEffect(() => {
287
+ if (open) inputRef.current?.focus();
288
+ }, [open]);
289
+ const selected = models.find((m) => m.id === value);
290
+ const filtered = useMemo(() => {
291
+ const q = query.trim().toLowerCase();
292
+ if (!q) return null;
293
+ return models.filter(
294
+ (m) => m.id.toLowerCase().includes(q) || m.name.toLowerCase().includes(q) || (m.description?.toLowerCase() ?? "").includes(q) || m.provider.toLowerCase().includes(q)
295
+ );
296
+ }, [models, query]);
297
+ const sections = useMemo(() => {
298
+ const isPriority = priorityGroup ? (m) => priorityGroup.match(m) : () => false;
299
+ const priority = priorityGroup ? models.filter(isPriority) : [];
300
+ const recommended = models.filter((m) => m.featured && !isPriority(m));
301
+ const byProvider = [];
302
+ for (const m of models) {
303
+ if (m.featured || isPriority(m)) continue;
304
+ const last = byProvider[byProvider.length - 1];
305
+ if (last && last.provider === m.provider) last.items.push(m);
306
+ else byProvider.push({ provider: m.provider, items: [m] });
307
+ }
308
+ return { priority, recommended, byProvider };
309
+ }, [models, priorityGroup]);
310
+ const select = (id) => {
311
+ onChange(id);
312
+ setOpen(false);
313
+ setQuery("");
314
+ };
315
+ return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: "relative inline-flex", children: [
316
+ /* @__PURE__ */ jsxs2(
317
+ "button",
318
+ {
319
+ type: "button",
320
+ ...triggerProps,
321
+ "aria-controls": open ? panelId : void 0,
322
+ onClick: () => setOpen(!open),
323
+ className: "inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent",
324
+ children: [
325
+ selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */ jsx2(ProviderLogo, { provider: selected.provider, size: 16 }) : /* @__PURE__ */ jsx2(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
326
+ /* @__PURE__ */ jsx2("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
327
+ /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
328
+ ]
329
+ }
330
+ ),
331
+ /* @__PURE__ */ jsxs2(
332
+ PopoverSurface,
333
+ {
334
+ open,
335
+ id: panelId,
336
+ triggerRef,
337
+ panelRef,
338
+ className: `flex w-[420px] max-w-[calc(100vw-2rem)] flex-col overflow-hidden rounded-xl border border-card-edge bg-popover ${OVERLAY_SHADOW}`,
339
+ children: [
340
+ /* @__PURE__ */ jsx2("div", { className: "shrink-0 border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 rounded-lg border border-strong bg-background px-3 py-2", children: [
341
+ /* @__PURE__ */ jsx2(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
342
+ /* @__PURE__ */ jsx2(
343
+ "input",
344
+ {
345
+ ref: inputRef,
346
+ type: "text",
347
+ value: query,
348
+ onChange: (e) => setQuery(e.target.value),
349
+ placeholder: "Search models...",
350
+ className: "flex-1 bg-transparent text-sm placeholder:text-muted-foreground"
351
+ }
352
+ )
353
+ ] }) }),
354
+ /* @__PURE__ */ jsxs2("div", { className: "max-h-[400px] min-h-0 overflow-y-auto p-1 pb-2", children: [
355
+ loading && /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
356
+ !loading && filtered && /* @__PURE__ */ jsxs2(Fragment, { children: [
357
+ filtered.length === 0 && /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
358
+ filtered.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
359
+ ] }),
360
+ !loading && !filtered && models.length === 0 && /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models available" }),
361
+ !loading && !filtered && models.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
362
+ priorityGroup && sections.priority.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
363
+ /* @__PURE__ */ jsx2(SectionHeader, { children: priorityGroup.label }),
364
+ sections.priority.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
365
+ ] }),
366
+ sections.recommended.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
367
+ /* @__PURE__ */ jsx2(SectionHeader, { children: recommendedLabel }),
368
+ sections.recommended.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
369
+ ] }),
370
+ sections.byProvider.map((g) => /* @__PURE__ */ jsxs2("div", { children: [
371
+ /* @__PURE__ */ jsx2(SectionHeader, { children: g.provider }),
372
+ g.items.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
373
+ ] }, g.provider))
374
+ ] })
375
+ ] })
376
+ ]
377
+ }
378
+ )
379
+ ] });
380
+ }
381
+ var KNOWN_EFFORT_LABELS = {
382
+ off: "Off",
383
+ low: "Quick",
384
+ medium: "Standard",
385
+ high: "Extended",
386
+ xhigh: "Extra",
387
+ ultracode: "Ultra"
388
+ };
389
+ var DEFAULT_EFFORT_LEVELS = [
390
+ { id: "off", label: KNOWN_EFFORT_LABELS.off },
391
+ { id: "low", label: KNOWN_EFFORT_LABELS.low },
392
+ { id: "medium", label: KNOWN_EFFORT_LABELS.medium },
393
+ { id: "high", label: KNOWN_EFFORT_LABELS.high }
394
+ ];
395
+ function effortLevelLabel(id) {
396
+ const known = KNOWN_EFFORT_LABELS[id];
397
+ if (known) return known;
398
+ const words = id.replace(/[-_]+/g, " ").trim();
399
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : id;
400
+ }
401
+ function effortLevelsFromIds(ids) {
402
+ return ids.map((id) => ({ id, label: effortLevelLabel(id) }));
403
+ }
404
+ function reconcileEffortLevels(value, levels = DEFAULT_EFFORT_LEVELS) {
405
+ if (!value || levels.some((l) => l.id === value)) return levels;
406
+ return [{ id: value, label: effortLevelLabel(value) }, ...levels];
407
+ }
408
+ var EFFORT_METER_SEGMENTS = 4;
409
+ var EFFORT_METER_FILL_OPACITY = [0.25, 0.5, 0.75, 1];
410
+ var EFFORT_METER_GHOST_OPACITY = 0.15;
411
+ var OFF_LEVEL_IDS = /* @__PURE__ */ new Set(["off", "none"]);
412
+ var UNPLACEABLE_LEVEL_IDS = /* @__PURE__ */ new Set(["auto"]);
413
+ function effortMeterFill(levelId, levels = DEFAULT_EFFORT_LEVELS) {
414
+ if (OFF_LEVEL_IDS.has(levelId) || UNPLACEABLE_LEVEL_IDS.has(levelId)) return 0;
415
+ const active = levels.filter((l) => !OFF_LEVEL_IDS.has(l.id) && !UNPLACEABLE_LEVEL_IDS.has(l.id));
416
+ const index = active.findIndex((l) => l.id === levelId);
417
+ if (index < 0 || active.length === 0) return 0;
418
+ return Math.max(1, Math.floor((index + 1) * EFFORT_METER_SEGMENTS / active.length));
419
+ }
420
+ function EffortMeter({ fill, className }) {
421
+ return /* @__PURE__ */ jsx2("span", { "aria-hidden": true, className: `inline-flex items-center gap-[2px] ${className ?? ""}`, children: Array.from({ length: EFFORT_METER_SEGMENTS }, (_, i) => /* @__PURE__ */ jsx2(
422
+ "span",
423
+ {
424
+ className: "h-3 w-[3px] rounded-full bg-current",
425
+ style: { opacity: i < fill ? EFFORT_METER_FILL_OPACITY[i] : EFFORT_METER_GHOST_OPACITY }
426
+ },
427
+ i
428
+ )) });
429
+ }
430
+ function EffortPicker({ value, onChange, levels = DEFAULT_EFFORT_LEVELS, label = "Thinking", fullWidth = false }) {
431
+ const [open, setOpen] = useState(false);
432
+ const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
433
+ const panelId = useId();
434
+ const rendered = reconcileEffortLevels(value, levels);
435
+ const isDeclared = (id) => levels.some((l) => l.id === id) && !UNPLACEABLE_LEVEL_IDS.has(id);
436
+ const selected = rendered.find((l) => l.id === value);
437
+ return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: pickerRootClass(fullWidth), children: [
438
+ /* @__PURE__ */ jsxs2(
439
+ "button",
440
+ {
441
+ type: "button",
442
+ ...triggerProps,
443
+ "aria-controls": open ? panelId : void 0,
444
+ onClick: () => setOpen(!open),
445
+ title: label ? `${label} \u2014 how hard the agent reasons before answering` : "Reasoning effort",
446
+ className: `inline-flex min-h-[36px] shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent ${fullWidth ? "w-full" : ""}`,
447
+ children: [
448
+ /* @__PURE__ */ jsx2(BrainGlyph, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
449
+ /* @__PURE__ */ jsxs2("span", { className: fullWidth ? "flex-1 truncate text-left" : void 0, children: [
450
+ label ? /* @__PURE__ */ jsxs2("span", { className: "text-muted-foreground", children: [
451
+ label,
452
+ ": "
453
+ ] }) : null,
454
+ selected ? selected.label : "\u2014"
455
+ ] }),
456
+ selected && isDeclared(selected.id) && /* @__PURE__ */ jsx2(EffortMeter, { fill: effortMeterFill(selected.id, levels), className: "shrink-0 text-foreground" }),
457
+ /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })
458
+ ]
459
+ }
460
+ ),
461
+ /* @__PURE__ */ jsx2(
462
+ PopoverSurface,
463
+ {
464
+ open,
465
+ id: panelId,
466
+ role: "menu",
467
+ triggerRef,
468
+ panelRef,
469
+ matchTriggerWidth: fullWidth,
470
+ className: `w-44 overflow-y-auto rounded-xl border border-card-edge bg-popover p-1 ${OVERLAY_SHADOW}`,
471
+ children: rendered.map((l) => /* @__PURE__ */ jsxs2(
472
+ "button",
473
+ {
474
+ type: "button",
475
+ role: "menuitemradio",
476
+ "aria-checked": l.id === value,
477
+ onClick: () => {
478
+ onChange(l.id);
479
+ setOpen(false);
480
+ },
481
+ className: `flex min-h-[40px] w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${l.id === value ? "bg-primary/10 font-medium" : "hover:bg-accent"}`,
482
+ children: [
483
+ /* @__PURE__ */ jsx2(BrainGlyph, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
484
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: l.label }),
485
+ isDeclared(l.id) && /* @__PURE__ */ jsx2(EffortMeter, { fill: effortMeterFill(l.id, levels), className: "ml-auto text-foreground" }),
486
+ l.id === value && /* @__PURE__ */ jsx2(CheckGlyph, { className: `${isDeclared(l.id) ? "" : "ml-auto "}h-3.5 w-3.5 shrink-0 text-primary` })
487
+ ]
488
+ },
489
+ l.id
490
+ ))
491
+ }
492
+ )
493
+ ] });
494
+ }
495
+
496
+ export {
497
+ ProviderLogo,
498
+ ChevronDown,
499
+ BrainGlyph,
500
+ CheckGlyph,
501
+ usePopover,
502
+ POPOVER_SURFACE_ATTR,
503
+ PopoverSurface,
504
+ POPOVER_OPTION_FOCUS,
505
+ OVERLAY_SHADOW,
506
+ pickerRootClass,
507
+ usePending,
508
+ ModelPicker,
509
+ DEFAULT_EFFORT_LEVELS,
510
+ effortLevelLabel,
511
+ effortLevelsFromIds,
512
+ reconcileEffortLevels,
513
+ EFFORT_METER_SEGMENTS,
514
+ effortMeterFill,
515
+ EffortMeter,
516
+ EffortPicker
517
+ };
518
+ //# sourceMappingURL=chunk-YDOQE47G.js.map