@tangle-network/agent-app 0.7.0 → 0.7.2

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.
@@ -1,17 +1,184 @@
1
1
  // src/web-react/index.tsx
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+
4
+ // src/web-react/provider-logo.tsx
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var LOGOS = {
7
+ 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"] },
8
+ 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"] },
9
+ 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"] },
10
+ 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"] },
11
+ 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"] },
12
+ 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"] },
13
+ 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"] },
14
+ 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"] },
15
+ 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"] }
16
+ };
17
+ var ALIASES = {
18
+ moonshot: "moonshotai",
19
+ deepseek_ai: "deepseek",
20
+ "x-ai": "xai",
21
+ "meta-llama": "meta"
22
+ };
23
+ var MONOGRAM = {
24
+ cohere: { bg: "#fae8ff", fg: "#c026d3" },
25
+ groq: { bg: "#fce7f3", fg: "#db2777" },
26
+ cerebras: { bg: "#ccfbf1", fg: "#0d9488" },
27
+ zai: { bg: "#ede9fe", fg: "#7c3aed" },
28
+ "z-ai": { bg: "#ede9fe", fg: "#7c3aed" },
29
+ tuner: { bg: "#dbeafe", fg: "#2563eb" }
30
+ };
31
+ function ProviderLogo({ provider, size = 16 }) {
32
+ const key = ALIASES[provider ?? ""] ?? provider ?? "";
33
+ const logo = LOGOS[key];
34
+ if (logo) {
35
+ 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)) });
36
+ }
37
+ const mono = MONOGRAM[key] ?? { bg: "#f3f4f6", fg: "#6b7280" };
38
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 16 16", role: "img", "aria-label": key || "model", children: [
39
+ /* @__PURE__ */ jsx("rect", { width: "16", height: "16", rx: "4", fill: mono.bg }),
40
+ /* @__PURE__ */ jsx("text", { x: "8", y: "11.6", textAnchor: "middle", fill: mono.fg, fontSize: "9", fontWeight: "700", fontFamily: "system-ui, sans-serif", children: (key || "?").charAt(0).toUpperCase() })
41
+ ] });
42
+ }
43
+
44
+ // src/web-react/chat-stream.ts
45
+ function dispatchChatStreamLine(line, cb) {
46
+ let receivedContent = false;
47
+ let turnId;
48
+ if (!line.trim()) return { receivedContent };
49
+ let parsed;
50
+ try {
51
+ parsed = JSON.parse(line);
52
+ } catch {
53
+ return { receivedContent };
54
+ }
55
+ if (parsed.kind === "tool_result") {
56
+ cb.onToolResult?.({
57
+ toolCallId: parsed.toolCallId,
58
+ toolName: parsed.toolName,
59
+ label: parsed.label,
60
+ outcome: parsed.outcome ?? parsed.result
61
+ });
62
+ return { receivedContent: true };
63
+ }
64
+ const evt = parsed.kind === "event" ? parsed.event : parsed;
65
+ if (!evt || typeof evt !== "object") return { receivedContent };
66
+ switch (evt.type) {
67
+ case "turn":
68
+ if (typeof evt.turnId === "string") turnId = evt.turnId;
69
+ break;
70
+ case "text":
71
+ if (typeof evt.text === "string") {
72
+ cb.onText?.(evt.text);
73
+ receivedContent = true;
74
+ }
75
+ break;
76
+ case "reasoning":
77
+ if (typeof evt.text === "string") {
78
+ cb.onReasoning?.(evt.text);
79
+ receivedContent = true;
80
+ }
81
+ break;
82
+ case "tool_call": {
83
+ const call = evt.call ?? evt;
84
+ cb.onToolCall?.({
85
+ toolCallId: call.toolCallId ?? call.id,
86
+ toolName: String(call.toolName ?? call.name ?? "unknown"),
87
+ args: call.args ?? {}
88
+ });
89
+ receivedContent = true;
90
+ break;
91
+ }
92
+ case "tool_result":
93
+ cb.onToolResult?.({
94
+ toolCallId: evt.toolCallId,
95
+ toolName: evt.toolName,
96
+ label: evt.label,
97
+ outcome: evt.outcome ?? evt.result
98
+ });
99
+ receivedContent = true;
100
+ break;
101
+ case "usage": {
102
+ const u = evt.usage;
103
+ if (u) cb.onUsage?.({ promptTokens: u.promptTokens ?? 0, completionTokens: u.completionTokens ?? 0 });
104
+ break;
105
+ }
106
+ case "metadata":
107
+ cb.onMetadata?.(evt.data ?? {});
108
+ break;
109
+ case "error":
110
+ cb.onErrorEvent?.(String(evt.details ?? evt.error ?? "Unknown stream error"));
111
+ break;
112
+ default:
113
+ break;
114
+ }
115
+ return { turnId, receivedContent };
116
+ }
117
+ async function consumeChatStream(body, cb) {
118
+ const reader = body.getReader();
119
+ const decoder = new TextDecoder();
120
+ let buffer = "";
121
+ let turnId = null;
122
+ let receivedContent = false;
123
+ const handle = (line) => {
124
+ const r = dispatchChatStreamLine(line, cb);
125
+ if (r.turnId) {
126
+ turnId = r.turnId;
127
+ cb.onTurnId?.(r.turnId);
128
+ }
129
+ if (r.receivedContent) receivedContent = true;
130
+ };
131
+ for (; ; ) {
132
+ const { done, value } = await reader.read();
133
+ if (done) {
134
+ if (buffer.trim()) handle(buffer);
135
+ break;
136
+ }
137
+ buffer += decoder.decode(value, { stream: true });
138
+ const lines = buffer.split("\n");
139
+ buffer = lines.pop() ?? "";
140
+ for (const line of lines) handle(line);
141
+ }
142
+ return { turnId, receivedContent };
143
+ }
144
+ async function streamChatTurn(opts) {
145
+ const res = await opts.start();
146
+ if (!res.ok || !res.body) {
147
+ const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
148
+ throw new Error(err.error ?? `HTTP ${res.status}`);
149
+ }
150
+ let turnId = null;
151
+ const cb = {
152
+ ...opts.callbacks,
153
+ onTurnId: (id) => {
154
+ turnId = id;
155
+ opts.callbacks.onTurnId?.(id);
156
+ }
157
+ };
158
+ try {
159
+ return await consumeChatStream(res.body, cb);
160
+ } catch (transportErr) {
161
+ if (!turnId || !opts.resume) throw transportErr;
162
+ opts.onResetForResume?.();
163
+ const resumed = await opts.resume(turnId, 0);
164
+ if (!resumed.ok || !resumed.body) throw transportErr;
165
+ return await consumeChatStream(resumed.body, cb);
166
+ }
167
+ }
168
+
169
+ // src/web-react/index.tsx
170
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
4
171
  function ChevronDown({ className }) {
5
- return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
172
+ 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" }) });
6
173
  }
7
174
  function SearchGlyph({ className }) {
8
- return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
9
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
10
- /* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
175
+ return /* @__PURE__ */ jsxs2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
176
+ /* @__PURE__ */ jsx2("circle", { cx: "11", cy: "11", r: "8" }),
177
+ /* @__PURE__ */ jsx2("path", { d: "m21 21-4.3-4.3" })
11
178
  ] });
12
179
  }
13
180
  function SparkleGlyph({ className }) {
14
- return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("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" }) });
181
+ 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" }) });
15
182
  }
16
183
  function useClickOutside(onOutside) {
17
184
  const ref = useRef(null);
@@ -50,7 +217,7 @@ function formatContext(len) {
50
217
  return `${len} ctx`;
51
218
  }
52
219
  function SectionHeader({ children }) {
53
- return /* @__PURE__ */ jsx("div", { className: "px-3 pb-1 pt-3 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/70", children });
220
+ return /* @__PURE__ */ jsx2("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground/70", children });
54
221
  }
55
222
  function ModelRow({
56
223
  model,
@@ -60,19 +227,19 @@ function ModelRow({
60
227
  }) {
61
228
  const price = formatPrice(model.pricing?.prompt);
62
229
  const ctx = formatContext(model.contextLength);
63
- return /* @__PURE__ */ jsxs(
230
+ return /* @__PURE__ */ jsxs2(
64
231
  "button",
65
232
  {
66
233
  type: "button",
67
234
  onClick: onSelect,
68
- className: `flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition ${selected ? "bg-primary/10 font-medium" : "hover:bg-accent/30"}`,
235
+ className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${selected ? "bg-primary/10 font-medium" : "hover:bg-accent/30"}`,
69
236
  children: [
70
- renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
71
- /* @__PURE__ */ jsx("span", { className: "truncate", children: model.name }),
72
- !model.supportsTools && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: "no tools" }),
73
- /* @__PURE__ */ jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-[11px] text-muted-foreground", children: [
74
- ctx && /* @__PURE__ */ jsx("span", { children: ctx }),
75
- price && /* @__PURE__ */ jsx("span", { children: price })
237
+ renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx2(ProviderLogo, { provider: model.provider, size: 16 }),
238
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: model.name }),
239
+ !model.supportsTools && /* @__PURE__ */ jsx2("span", { className: "shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: "no tools" }),
240
+ /* @__PURE__ */ jsxs2("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground", children: [
241
+ ctx && /* @__PURE__ */ jsx2("span", { children: ctx }),
242
+ price && /* @__PURE__ */ jsx2("span", { children: price })
76
243
  ] })
77
244
  ]
78
245
  }
@@ -110,24 +277,24 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
110
277
  setOpen(false);
111
278
  setQuery("");
112
279
  };
113
- return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative inline-flex", children: [
114
- /* @__PURE__ */ jsxs(
280
+ return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: "relative inline-flex", children: [
281
+ /* @__PURE__ */ jsxs2(
115
282
  "button",
116
283
  {
117
284
  type: "button",
118
285
  onClick: () => setOpen((v) => !v),
119
286
  className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30",
120
287
  children: [
121
- selected && renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */ jsx(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
122
- /* @__PURE__ */ jsx("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
123
- /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
288
+ 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" }),
289
+ /* @__PURE__ */ jsx2("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
290
+ /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
124
291
  ]
125
292
  }
126
293
  ),
127
- open && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-[420px] overflow-hidden rounded-xl border border-border bg-card shadow-lg", children: [
128
- /* @__PURE__ */ jsx("div", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-2", children: [
129
- /* @__PURE__ */ jsx(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
130
- /* @__PURE__ */ jsx(
294
+ open && /* @__PURE__ */ jsxs2("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-[420px] overflow-hidden rounded-xl border border-border bg-card shadow-lg", children: [
295
+ /* @__PURE__ */ jsx2("div", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-2", children: [
296
+ /* @__PURE__ */ jsx2(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
297
+ /* @__PURE__ */ jsx2(
131
298
  "input",
132
299
  {
133
300
  ref: inputRef,
@@ -139,20 +306,20 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
139
306
  }
140
307
  )
141
308
  ] }) }),
142
- /* @__PURE__ */ jsxs("div", { className: "max-h-[400px] overflow-y-auto p-1 pb-2", children: [
143
- loading && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
144
- !loading && filtered && /* @__PURE__ */ jsxs(Fragment, { children: [
145
- filtered.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
146
- filtered.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
309
+ /* @__PURE__ */ jsxs2("div", { className: "max-h-[400px] overflow-y-auto p-1 pb-2", children: [
310
+ loading && /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
311
+ !loading && filtered && /* @__PURE__ */ jsxs2(Fragment, { children: [
312
+ filtered.length === 0 && /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
313
+ filtered.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
147
314
  ] }),
148
- !loading && !filtered && /* @__PURE__ */ jsxs(Fragment, { children: [
149
- sections.recommended.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
150
- /* @__PURE__ */ jsx(SectionHeader, { children: recommendedLabel }),
151
- sections.recommended.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
315
+ !loading && !filtered && /* @__PURE__ */ jsxs2(Fragment, { children: [
316
+ sections.recommended.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
317
+ /* @__PURE__ */ jsx2(SectionHeader, { children: recommendedLabel }),
318
+ sections.recommended.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
152
319
  ] }),
153
- sections.byProvider.map((g) => /* @__PURE__ */ jsxs("div", { children: [
154
- /* @__PURE__ */ jsx(SectionHeader, { children: g.provider }),
155
- g.items.map((m) => /* @__PURE__ */ jsx(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
320
+ sections.byProvider.map((g) => /* @__PURE__ */ jsxs2("div", { children: [
321
+ /* @__PURE__ */ jsx2(SectionHeader, { children: g.provider }),
322
+ g.items.map((m) => /* @__PURE__ */ jsx2(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
156
323
  ] }, g.provider))
157
324
  ] })
158
325
  ] })
@@ -169,8 +336,8 @@ function EffortPicker({ value, onChange }) {
169
336
  const [open, setOpen] = useState(false);
170
337
  const containerRef = useClickOutside(() => setOpen(false));
171
338
  const selected = EFFORT_LEVELS.find((l) => l.id === value) ?? EFFORT_LEVELS[2];
172
- return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative inline-flex", children: [
173
- /* @__PURE__ */ jsxs(
339
+ return /* @__PURE__ */ jsxs2("div", { ref: containerRef, className: "relative inline-flex", children: [
340
+ /* @__PURE__ */ jsxs2(
174
341
  "button",
175
342
  {
176
343
  type: "button",
@@ -178,13 +345,13 @@ function EffortPicker({ value, onChange }) {
178
345
  title: "Reasoning effort",
179
346
  className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30",
180
347
  children: [
181
- /* @__PURE__ */ jsx(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
182
- /* @__PURE__ */ jsx("span", { children: selected.label }),
183
- /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
348
+ /* @__PURE__ */ jsx2(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
349
+ /* @__PURE__ */ jsx2("span", { children: selected.label }),
350
+ /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
184
351
  ]
185
352
  }
186
353
  ),
187
- open && /* @__PURE__ */ jsx("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-36 overflow-hidden rounded-xl border border-border bg-card p-1 shadow-lg", children: EFFORT_LEVELS.map((l) => /* @__PURE__ */ jsx(
354
+ open && /* @__PURE__ */ jsx2("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-36 overflow-hidden rounded-xl border border-border bg-card p-1 shadow-lg", children: EFFORT_LEVELS.map((l) => /* @__PURE__ */ jsx2(
188
355
  "button",
189
356
  {
190
357
  type: "button",
@@ -200,41 +367,41 @@ function EffortPicker({ value, onChange }) {
200
367
  ] });
201
368
  }
202
369
  function RunDrillIn({ run, onClose }) {
203
- return /* @__PURE__ */ jsxs("div", { className: "fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-border bg-card shadow-xl", children: [
204
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
205
- /* @__PURE__ */ jsx(
370
+ return /* @__PURE__ */ jsxs2("div", { className: "fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-border bg-card shadow-xl", children: [
371
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
372
+ /* @__PURE__ */ jsx2(
206
373
  "span",
207
374
  {
208
375
  className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-yellow-500" : run.status === "error" ? "bg-red-500" : "bg-green-500"}`
209
376
  }
210
377
  ),
211
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
212
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold", children: run.title }),
213
- /* @__PURE__ */ jsx("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: run.toolName })
378
+ /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
379
+ /* @__PURE__ */ jsx2("p", { className: "truncate text-sm font-semibold", children: run.title }),
380
+ /* @__PURE__ */ jsx2("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: run.toolName })
214
381
  ] }),
215
- /* @__PURE__ */ jsx(
382
+ /* @__PURE__ */ jsx2(
216
383
  "button",
217
384
  {
218
385
  type: "button",
219
386
  onClick: onClose,
220
387
  "aria-label": "Close",
221
388
  className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground",
222
- children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
389
+ children: /* @__PURE__ */ jsx2("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18M6 6l12 12" }) })
223
390
  }
224
391
  )
225
392
  ] }),
226
- /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
227
- run.steps.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
228
- run.steps.map((step, i) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border/60 bg-background", children: [
229
- /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5", children: [
230
- /* @__PURE__ */ jsx("span", { className: `font-mono text-[11px] ${step.status === "error" ? "text-red-600" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
231
- /* @__PURE__ */ jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
232
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: new Date(step.at).toLocaleTimeString() })
393
+ /* @__PURE__ */ jsxs2("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
394
+ run.steps.length === 0 && /* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
395
+ run.steps.map((step, i) => /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-border/60 bg-background", children: [
396
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5", children: [
397
+ /* @__PURE__ */ jsx2("span", { className: `font-mono text-[11px] ${step.status === "error" ? "text-red-600" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
398
+ /* @__PURE__ */ jsx2("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
399
+ /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: new Date(step.at).toLocaleTimeString() })
233
400
  ] }),
234
- step.detail && /* @__PURE__ */ jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: step.detail })
401
+ step.detail && /* @__PURE__ */ jsx2("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: step.detail })
235
402
  ] }, i))
236
403
  ] }),
237
- /* @__PURE__ */ jsx("p", { className: "border-t border-border px-4 py-2 text-[11px] text-muted-foreground/60", children: "Readonly drill-in. Follow up in the main chat." })
404
+ /* @__PURE__ */ jsx2("p", { className: "border-t border-border px-4 py-2 text-[11px] text-muted-foreground/60", children: "Readonly drill-in. Follow up in the main chat." })
238
405
  ] });
239
406
  }
240
407
  function pendingApprovalOf(call) {
@@ -247,19 +414,19 @@ function ToolChips({
247
414
  approval,
248
415
  onClick
249
416
  }) {
250
- return /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-col gap-1", children: toolCalls.map((tc) => {
417
+ return /* @__PURE__ */ jsx2("div", { className: "mt-2 flex flex-col gap-1", children: toolCalls.map((tc) => {
251
418
  const pending = tc.status === "done" ? pendingApprovalOf(tc) : null;
252
419
  if (pending) {
253
- return /* @__PURE__ */ jsxs(
420
+ return /* @__PURE__ */ jsxs2(
254
421
  "div",
255
422
  {
256
423
  className: "inline-flex w-fit items-center gap-2 rounded-md bg-amber-500/10 px-2.5 py-1 text-xs text-amber-700",
257
424
  children: [
258
- /* @__PURE__ */ jsx("span", { className: "font-mono opacity-70", children: "\u23F8" }),
259
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: tc.name }),
260
- /* @__PURE__ */ jsx("span", { className: "opacity-60", children: "awaiting approval" }),
261
- approval && /* @__PURE__ */ jsxs("span", { className: "ml-1 inline-flex items-center gap-1", children: [
262
- /* @__PURE__ */ jsx(
425
+ /* @__PURE__ */ jsx2("span", { className: "font-mono opacity-70", children: "\u23F8" }),
426
+ /* @__PURE__ */ jsx2("span", { className: "font-medium", children: tc.name }),
427
+ /* @__PURE__ */ jsx2("span", { className: "opacity-60", children: "awaiting approval" }),
428
+ approval && /* @__PURE__ */ jsxs2("span", { className: "ml-1 inline-flex items-center gap-1", children: [
429
+ /* @__PURE__ */ jsx2(
263
430
  "button",
264
431
  {
265
432
  type: "button",
@@ -268,7 +435,7 @@ function ToolChips({
268
435
  children: "Approve"
269
436
  }
270
437
  ),
271
- /* @__PURE__ */ jsx(
438
+ /* @__PURE__ */ jsx2(
272
439
  "button",
273
440
  {
274
441
  type: "button",
@@ -284,15 +451,15 @@ function ToolChips({
284
451
  );
285
452
  }
286
453
  const Tag = onClick ? "button" : "div";
287
- return /* @__PURE__ */ jsxs(
454
+ return /* @__PURE__ */ jsxs2(
288
455
  Tag,
289
456
  {
290
457
  ...onClick ? { type: "button", onClick: () => onClick(tc) } : {},
291
458
  className: `inline-flex w-fit items-center gap-2 rounded-md px-2.5 py-1 text-xs ${tc.status === "running" ? "bg-yellow-500/10 text-yellow-700" : tc.status === "error" ? "bg-red-500/10 text-red-700" : "bg-green-500/10 text-green-700"} ${onClick ? "cursor-pointer transition hover:ring-1 hover:ring-border" : ""}`,
292
459
  children: [
293
- /* @__PURE__ */ jsx("span", { className: "font-mono opacity-70", children: tc.status === "running" ? "\u26A1" : tc.status === "error" ? "\u2717" : "\u2713" }),
294
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: tc.name }),
295
- /* @__PURE__ */ jsx("span", { className: "opacity-60", children: tc.status === "running" ? "running\u2026" : tc.status === "error" ? "failed" : "done" })
460
+ /* @__PURE__ */ jsx2("span", { className: "font-mono opacity-70", children: tc.status === "running" ? "\u26A1" : tc.status === "error" ? "\u2717" : "\u2713" }),
461
+ /* @__PURE__ */ jsx2("span", { className: "font-medium", children: tc.name }),
462
+ /* @__PURE__ */ jsx2("span", { className: "opacity-60", children: tc.status === "running" ? "running\u2026" : tc.status === "error" ? "failed" : "done" })
296
463
  ]
297
464
  },
298
465
  tc.id
@@ -310,26 +477,36 @@ function ChatMessages({
310
477
  approval,
311
478
  onToolCallClick
312
479
  }) {
313
- const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap", children: content }));
480
+ const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */ jsx2("p", { className: "whitespace-pre-wrap", children: content }));
314
481
  const lastIsUser = messages[messages.length - 1]?.role === "user";
315
- return /* @__PURE__ */ jsxs(Fragment, { children: [
482
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
316
483
  messages.map(
317
- (msg) => msg.role === "user" ? /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs("div", { className: "ml-auto w-fit max-w-[85%]", children: [
318
- /* @__PURE__ */ jsx("p", { className: "mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: userLabel }),
319
- /* @__PURE__ */ jsx("div", { className: "rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed", children: /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap", children: msg.content }) })
320
- ] }) }, msg.id) : /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
321
- /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground/60", children: [
322
- /* @__PURE__ */ jsx("span", { className: "font-semibold uppercase", children: agentLabel }),
323
- msg.modelUsed && /* @__PURE__ */ jsx("span", { className: "font-mono normal-case", children: msg.modelUsed }),
324
- formatTokensPerSecond(msg) && /* @__PURE__ */ jsx("span", { children: formatTokensPerSecond(msg) }),
325
- formatModelCost(msg, models) && /* @__PURE__ */ jsx("span", { children: formatModelCost(msg, models) })
326
- ] }),
327
- msg.reasoning && /* @__PURE__ */ jsxs("details", { className: "mb-2 rounded-md border border-border/40 bg-muted/30 px-3 py-2", children: [
328
- /* @__PURE__ */ jsx("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: "Thinking\u2026" }),
329
- /* @__PURE__ */ jsx("div", { className: "mt-2 whitespace-pre-wrap text-sm text-muted-foreground/80", children: msg.reasoning })
484
+ (msg) => msg.role === "user" ? /* @__PURE__ */ jsx2("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs2("div", { className: "ml-auto w-fit max-w-[85%]", children: [
485
+ /* @__PURE__ */ jsx2("p", { className: "mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: userLabel }),
486
+ /* @__PURE__ */ jsx2("div", { className: "rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed", children: /* @__PURE__ */ jsx2("p", { className: "whitespace-pre-wrap", children: msg.content }) })
487
+ ] }) }, msg.id) : /* @__PURE__ */ jsxs2("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
488
+ /* @__PURE__ */ jsxs2("div", { className: "mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground/60", children: [
489
+ /* @__PURE__ */ jsx2("span", { className: "font-semibold uppercase", children: agentLabel }),
490
+ msg.modelUsed && /* @__PURE__ */ jsx2("span", { className: "font-mono normal-case", children: msg.modelUsed }),
491
+ formatTokensPerSecond(msg) && /* @__PURE__ */ jsx2("span", { children: formatTokensPerSecond(msg) }),
492
+ formatModelCost(msg, models) && /* @__PURE__ */ jsx2("span", { children: formatModelCost(msg, models) })
330
493
  ] }),
331
- /* @__PURE__ */ jsx("div", { className: "text-base leading-[1.75]", children: renderBody(msg.content) }),
332
- msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx(
494
+ msg.reasoning && /* @__PURE__ */ jsxs2(
495
+ "details",
496
+ {
497
+ className: "mb-2 rounded-md border border-border/40 bg-muted/30 px-3 py-2",
498
+ open: !msg.content,
499
+ children: [
500
+ /* @__PURE__ */ jsxs2("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: [
501
+ msg.content ? "Thinking\u2026" : "Thinking",
502
+ !msg.content && /* @__PURE__ */ jsx2("span", { className: "ml-1 inline-block animate-pulse", children: "\u25CF" })
503
+ ] }),
504
+ /* @__PURE__ */ jsx2("div", { className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-sm text-muted-foreground/80", children: msg.reasoning })
505
+ ]
506
+ }
507
+ ),
508
+ /* @__PURE__ */ jsx2("div", { className: "text-base leading-[1.75]", children: renderBody(msg.content) }),
509
+ msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx2(
333
510
  ToolChips,
334
511
  {
335
512
  toolCalls: msg.toolCalls,
@@ -340,10 +517,10 @@ function ChatMessages({
340
517
  renderExtras?.(msg)
341
518
  ] }, msg.id)
342
519
  ),
343
- loading && lastIsUser && /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
344
- /* @__PURE__ */ jsx("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: agentLabel }),
345
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-base text-muted-foreground", children: [
346
- /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
520
+ loading && lastIsUser && /* @__PURE__ */ jsxs2("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
521
+ /* @__PURE__ */ jsx2("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: agentLabel }),
522
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-base text-muted-foreground", children: [
523
+ /* @__PURE__ */ jsx2("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
347
524
  "Thinking..."
348
525
  ] })
349
526
  ] })
@@ -353,9 +530,13 @@ export {
353
530
  ChatMessages,
354
531
  EffortPicker,
355
532
  ModelPicker,
533
+ ProviderLogo,
356
534
  RunDrillIn,
535
+ consumeChatStream,
536
+ dispatchChatStreamLine,
357
537
  formatModelCost,
358
538
  formatTokensPerSecond,
359
- pendingApprovalOf
539
+ pendingApprovalOf,
540
+ streamChatTurn
360
541
  };
361
542
  //# sourceMappingURL=index.js.map