@wrongstack/webui 0.255.0 → 0.256.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/index-DHok34Zp.js +164 -0
- package/dist/assets/{index-u41ruU9Z.css → index-DVRA0JCZ.css} +1 -1
- package/dist/assets/{vendor-DEuauVA6.js → vendor-XlX63RRU.js} +228 -228
- package/dist/index.html +3 -3
- package/dist/index.js +742 -559
- package/dist/index.js.map +1 -1
- package/dist/server/entry.js +325 -170
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.d.ts +131 -4
- package/dist/server/index.js +331 -170
- package/dist/server/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/assets/index-DcnrP-gv.js +0 -163
package/dist/index.js
CHANGED
|
@@ -63,26 +63,14 @@ function installFaviconVisibilityReset() {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// src/lib/ws-client.ts
|
|
66
|
-
|
|
67
|
-
function getStoredToken() {
|
|
66
|
+
function getTokenFromWsUrl(wsUrl) {
|
|
68
67
|
try {
|
|
69
|
-
|
|
68
|
+
const u = new URL(wsUrl);
|
|
69
|
+
return u.searchParams.get("token");
|
|
70
70
|
} catch {
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
function setStoredToken(token) {
|
|
75
|
-
try {
|
|
76
|
-
sessionStorage.setItem(WS_TOKEN_KEY, token);
|
|
77
|
-
} catch {
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function clearStoredToken() {
|
|
81
|
-
try {
|
|
82
|
-
sessionStorage.removeItem(WS_TOKEN_KEY);
|
|
83
|
-
} catch {
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
74
|
var WrongStackWebSocketClient = class {
|
|
87
75
|
ws = null;
|
|
88
76
|
url;
|
|
@@ -120,7 +108,53 @@ var WrongStackWebSocketClient = class {
|
|
|
120
108
|
constructor(url) {
|
|
121
109
|
this.url = url ?? defaultWsUrl();
|
|
122
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Exchange a stored token for an HttpOnly auth cookie via `/ws-auth`.
|
|
113
|
+
* Called once before the first connect so subsequent reconnections can
|
|
114
|
+
* drop the `?token=` from the WS URL (C-2 fix — token-in-URL closes
|
|
115
|
+
* the C-598 query-string exposure class). No-op when the cookie is
|
|
116
|
+
* already set, when the server is on a loopback bind (no token
|
|
117
|
+
* required), or when no token is available yet.
|
|
118
|
+
*
|
|
119
|
+
* Failure is non-fatal: the legacy `?token=` URL path still works, so
|
|
120
|
+
* the client just continues to use it. Cookie is a defense-in-depth
|
|
121
|
+
* layer, not a hard requirement.
|
|
122
|
+
*/
|
|
123
|
+
async ensureAuthCookie() {
|
|
124
|
+
if (typeof window === "undefined") return;
|
|
125
|
+
if (document.cookie.split(";").some((c) => c.trim().startsWith("ws_token="))) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const token = getTokenFromWsUrl(this.url);
|
|
129
|
+
if (!token) return;
|
|
130
|
+
const authUrl = httpOriginForAuth() + `/ws-auth?token=${encodeURIComponent(token)}`;
|
|
131
|
+
try {
|
|
132
|
+
const res = await fetch(authUrl, {
|
|
133
|
+
method: "GET",
|
|
134
|
+
credentials: "same-origin",
|
|
135
|
+
// Cache-Control: no-store on the server side. Don't let the
|
|
136
|
+
// browser cache a 401 or replay a stale response.
|
|
137
|
+
cache: "no-store"
|
|
138
|
+
});
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
console.warn(JSON.stringify({
|
|
141
|
+
level: "warn",
|
|
142
|
+
event: "ws_client.ws_auth_failed",
|
|
143
|
+
status: res.status,
|
|
144
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.warn(JSON.stringify({
|
|
149
|
+
level: "warn",
|
|
150
|
+
event: "ws_client.ws_auth_error",
|
|
151
|
+
message: err instanceof Error ? err.message : String(err),
|
|
152
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
123
156
|
async connect() {
|
|
157
|
+
await this.ensureAuthCookie();
|
|
124
158
|
return new Promise((resolve, reject) => {
|
|
125
159
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
126
160
|
resolve();
|
|
@@ -128,8 +162,8 @@ var WrongStackWebSocketClient = class {
|
|
|
128
162
|
}
|
|
129
163
|
this.setStatus({ state: "connecting" });
|
|
130
164
|
try {
|
|
131
|
-
const
|
|
132
|
-
const wsUrl =
|
|
165
|
+
const urlToken = getTokenFromWsUrl(this.url);
|
|
166
|
+
const wsUrl = urlToken ? `${this.url}${this.url.includes("?") ? "&" : "?"}token=${urlToken}` : this.url;
|
|
133
167
|
this.ws = new WebSocket(wsUrl);
|
|
134
168
|
this.ws.binaryType = "arraybuffer";
|
|
135
169
|
const connectTimeout = setTimeout(() => {
|
|
@@ -264,9 +298,6 @@ var WrongStackWebSocketClient = class {
|
|
|
264
298
|
if (msg.type === "session.start") {
|
|
265
299
|
const payload = msg.payload;
|
|
266
300
|
this.sessionId = payload.sessionId;
|
|
267
|
-
if (payload.wsToken) {
|
|
268
|
-
setStoredToken(payload.wsToken);
|
|
269
|
-
}
|
|
270
301
|
}
|
|
271
302
|
this.emit(msg);
|
|
272
303
|
}
|
|
@@ -510,7 +541,6 @@ var WrongStackWebSocketClient = class {
|
|
|
510
541
|
}
|
|
511
542
|
this.ws?.close();
|
|
512
543
|
this.ws = null;
|
|
513
|
-
clearStoredToken();
|
|
514
544
|
}
|
|
515
545
|
get isConnected() {
|
|
516
546
|
return this.ws?.readyState === WebSocket.OPEN;
|
|
@@ -538,6 +568,18 @@ function defaultWsUrl() {
|
|
|
538
568
|
}
|
|
539
569
|
return `ws://${window.location.hostname}:${port}`;
|
|
540
570
|
}
|
|
571
|
+
function httpOriginForAuth() {
|
|
572
|
+
if (typeof window === "undefined" || !window.location?.hostname) {
|
|
573
|
+
return "http://127.0.0.1:3456";
|
|
574
|
+
}
|
|
575
|
+
const host = window.location.hostname.toLowerCase();
|
|
576
|
+
const pagePort = window.location.port ? Number.parseInt(window.location.port, 10) : Number.NaN;
|
|
577
|
+
const httpPort = Number.isFinite(pagePort) && pagePort > 0 ? pagePort : 3456;
|
|
578
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "::1") {
|
|
579
|
+
return `http://127.0.0.1:${httpPort}`;
|
|
580
|
+
}
|
|
581
|
+
return `http://${window.location.hostname}:${httpPort}`;
|
|
582
|
+
}
|
|
541
583
|
function getWSClient(url) {
|
|
542
584
|
if (!client) {
|
|
543
585
|
client = new WrongStackWebSocketClient(url);
|
|
@@ -619,11 +661,15 @@ var useChatStore = create()(
|
|
|
619
661
|
}));
|
|
620
662
|
},
|
|
621
663
|
appendToolProgress: (id, line) => {
|
|
664
|
+
get().appendToolProgressLines(id, [line]);
|
|
665
|
+
},
|
|
666
|
+
appendToolProgressLines: (id, lines) => {
|
|
667
|
+
if (lines.length === 0) return;
|
|
622
668
|
set((state) => ({
|
|
623
669
|
messages: state.messages.map((m) => {
|
|
624
670
|
if (m.id !== id) return m;
|
|
625
671
|
const prev = m.progressLines ?? [];
|
|
626
|
-
const next = [...prev,
|
|
672
|
+
const next = [...prev, ...lines];
|
|
627
673
|
const trimmed = next.length > 30 ? next.slice(next.length - 30) : next;
|
|
628
674
|
return { ...m, progressLines: trimmed };
|
|
629
675
|
})
|
|
@@ -828,6 +874,7 @@ var useUIStore = create4()(
|
|
|
828
874
|
shortcutsOpen: false,
|
|
829
875
|
searchOpen: false,
|
|
830
876
|
searchQuery: "",
|
|
877
|
+
scrollTarget: null,
|
|
831
878
|
promptHistory: [],
|
|
832
879
|
sidebarWidth: SIDEBAR_DEFAULT_WIDTH,
|
|
833
880
|
pinnedIds: [],
|
|
@@ -852,6 +899,7 @@ var useUIStore = create4()(
|
|
|
852
899
|
setShortcutsOpen: (open) => set({ shortcutsOpen: open }),
|
|
853
900
|
setSearchOpen: (open) => set({ searchOpen: open, searchQuery: open ? "" : "" }),
|
|
854
901
|
setSearchQuery: (q) => set({ searchQuery: q }),
|
|
902
|
+
requestScrollToMessage: (id) => set((s) => ({ scrollTarget: { id, nonce: (s.scrollTarget?.nonce ?? 0) + 1 } })),
|
|
855
903
|
pushPrompt: (text) => set((state) => {
|
|
856
904
|
const trimmed = text.trim();
|
|
857
905
|
if (!trimmed) return state;
|
|
@@ -1924,6 +1972,69 @@ function notifyIfHidden(title, body, tag) {
|
|
|
1924
1972
|
}
|
|
1925
1973
|
}
|
|
1926
1974
|
|
|
1975
|
+
// src/lib/stream-coalescer.ts
|
|
1976
|
+
function scheduleRaf(cb) {
|
|
1977
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1978
|
+
requestAnimationFrame(cb);
|
|
1979
|
+
} else {
|
|
1980
|
+
queueMicrotask(cb);
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
var StreamCoalescer = class {
|
|
1984
|
+
pending = /* @__PURE__ */ new Map();
|
|
1985
|
+
scheduled = false;
|
|
1986
|
+
/**
|
|
1987
|
+
* Queue `text` under `key`, to be flushed via `flush(key, joinedText)` on the
|
|
1988
|
+
* next frame. Repeated calls for the same key before a flush concatenate.
|
|
1989
|
+
* The `flush` callback is captured per key from the latest push.
|
|
1990
|
+
*/
|
|
1991
|
+
push(key, text, flush) {
|
|
1992
|
+
if (!text) return;
|
|
1993
|
+
const existing = this.pending.get(key);
|
|
1994
|
+
if (existing) {
|
|
1995
|
+
existing.buffer += text;
|
|
1996
|
+
existing.flush = flush;
|
|
1997
|
+
} else {
|
|
1998
|
+
this.pending.set(key, { buffer: text, flush });
|
|
1999
|
+
}
|
|
2000
|
+
this.schedule();
|
|
2001
|
+
}
|
|
2002
|
+
schedule() {
|
|
2003
|
+
if (this.scheduled) return;
|
|
2004
|
+
this.scheduled = true;
|
|
2005
|
+
scheduleRaf(() => {
|
|
2006
|
+
this.scheduled = false;
|
|
2007
|
+
this.drain();
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
drain() {
|
|
2011
|
+
if (this.pending.size === 0) return;
|
|
2012
|
+
const batch = Array.from(this.pending.entries());
|
|
2013
|
+
this.pending.clear();
|
|
2014
|
+
for (const [key, p] of batch) {
|
|
2015
|
+
if (p.buffer) p.flush(key, p.buffer);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
/** Discard a key's buffered text without flushing. Used when the thinking
|
|
2019
|
+
* buffer is cleared (model started replying) so a pending thinking delta
|
|
2020
|
+
* can't re-populate it a frame later. */
|
|
2021
|
+
drop(key) {
|
|
2022
|
+
this.pending.delete(key);
|
|
2023
|
+
}
|
|
2024
|
+
/** Drain a single key immediately (if buffered). Safe to call when empty. */
|
|
2025
|
+
flush(key) {
|
|
2026
|
+
const p = this.pending.get(key);
|
|
2027
|
+
if (!p) return;
|
|
2028
|
+
this.pending.delete(key);
|
|
2029
|
+
if (p.buffer) p.flush(key, p.buffer);
|
|
2030
|
+
}
|
|
2031
|
+
/** Drain every buffered key immediately. Call at run end / before finalize. */
|
|
2032
|
+
flushAll() {
|
|
2033
|
+
this.drain();
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
var streamCoalescer = new StreamCoalescer();
|
|
2037
|
+
|
|
1927
2038
|
// src/hooks/ws-handlers.ts
|
|
1928
2039
|
function handleSessionStart(msg) {
|
|
1929
2040
|
const vizStart = wsToVizEvent("session.start", msg.payload);
|
|
@@ -2095,6 +2206,7 @@ function handleProviderResponse(msg) {
|
|
|
2095
2206
|
if (payload.stopReason !== "tool_use" && payload.stopReason !== "tool_call") useChatStore.getState().setLoading(false);
|
|
2096
2207
|
const id = useChatStore.getState().currentAssistantMessageId;
|
|
2097
2208
|
if (id) {
|
|
2209
|
+
streamCoalescer.flush(id);
|
|
2098
2210
|
useChatStore.getState().finalizeMessage(id);
|
|
2099
2211
|
if (payload.usage.output > 0) useChatStore.getState().updateMessage(id, { usage: payload.usage });
|
|
2100
2212
|
}
|
|
@@ -2124,17 +2236,26 @@ function handleIterationStarted(msg) {
|
|
|
2124
2236
|
function handleTextDelta(msg) {
|
|
2125
2237
|
const payload = msg.payload;
|
|
2126
2238
|
useChatStore.getState().clearThinking();
|
|
2239
|
+
streamCoalescer.drop("__thinking__");
|
|
2127
2240
|
let id = useChatStore.getState().currentAssistantMessageId;
|
|
2128
2241
|
if (!id) {
|
|
2129
2242
|
id = useChatStore.getState().addMessage({ role: "assistant", content: "", streaming: true });
|
|
2130
2243
|
useChatStore.getState().setCurrentAssistantMessage(id);
|
|
2131
2244
|
}
|
|
2132
|
-
|
|
2245
|
+
streamCoalescer.push(
|
|
2246
|
+
id,
|
|
2247
|
+
payload.text,
|
|
2248
|
+
(mid, text) => useChatStore.getState().appendToMessage(mid, text)
|
|
2249
|
+
);
|
|
2133
2250
|
}
|
|
2134
2251
|
function handleThinkingDelta(msg) {
|
|
2135
2252
|
const payload = msg.payload;
|
|
2136
2253
|
if (!payload.text) return;
|
|
2137
|
-
|
|
2254
|
+
streamCoalescer.push(
|
|
2255
|
+
"__thinking__",
|
|
2256
|
+
payload.text,
|
|
2257
|
+
(_k, text) => useChatStore.getState().appendThinking(text)
|
|
2258
|
+
);
|
|
2138
2259
|
}
|
|
2139
2260
|
function handleToolStarted(msg) {
|
|
2140
2261
|
const payload = msg.payload;
|
|
@@ -2144,6 +2265,7 @@ function handleToolStarted(msg) {
|
|
|
2144
2265
|
return;
|
|
2145
2266
|
}
|
|
2146
2267
|
useChatStore.getState().clearThinking();
|
|
2268
|
+
streamCoalescer.drop("__thinking__");
|
|
2147
2269
|
useChatStore.getState().setCurrentAssistantMessage(null);
|
|
2148
2270
|
const id = useChatStore.getState().addMessage({ role: "tool", content: "", toolName: payload.name, toolInput: payload.input, toolUseId: payload.id });
|
|
2149
2271
|
useChatStore.getState().setCurrentToolId(id);
|
|
@@ -2157,7 +2279,15 @@ function handleToolProgress(msg) {
|
|
|
2157
2279
|
const owner = messages.find((m) => m.toolUseId === payload.id);
|
|
2158
2280
|
if (!owner) return;
|
|
2159
2281
|
const prefix = payload.event?.type === "warning" ? "\u26A0 " : "";
|
|
2160
|
-
|
|
2282
|
+
streamCoalescer.push(
|
|
2283
|
+
owner.id,
|
|
2284
|
+
`${prefix}${text}
|
|
2285
|
+
`,
|
|
2286
|
+
(oid, buffered) => useChatStore.getState().appendToolProgressLines(
|
|
2287
|
+
oid,
|
|
2288
|
+
buffered.split("\n").filter((l) => l.length > 0)
|
|
2289
|
+
)
|
|
2290
|
+
);
|
|
2161
2291
|
}
|
|
2162
2292
|
function handleToolExecuted(msg) {
|
|
2163
2293
|
const payload = msg.payload;
|
|
@@ -2165,6 +2295,7 @@ function handleToolExecuted(msg) {
|
|
|
2165
2295
|
const owner = payload.id ? messages.find((m) => m.toolUseId === payload.id) : currentToolId ? messages.find((m) => m.id === currentToolId) : void 0;
|
|
2166
2296
|
if (owner?.toolResult !== void 0) return;
|
|
2167
2297
|
if (owner) {
|
|
2298
|
+
streamCoalescer.drop(owner.id);
|
|
2168
2299
|
useChatStore.getState().setToolResult(owner.id, payload.output ?? "", payload.ok);
|
|
2169
2300
|
useChatStore.getState().updateMessage(owner.id, { toolDurationMs: payload.durationMs });
|
|
2170
2301
|
}
|
|
@@ -2185,6 +2316,7 @@ function handleToolConfirmNeeded(msg) {
|
|
|
2185
2316
|
}
|
|
2186
2317
|
function handleRunResult(msg) {
|
|
2187
2318
|
const payload = msg.payload;
|
|
2319
|
+
streamCoalescer.flushAll();
|
|
2188
2320
|
useSessionStore.getState().setIteration(null);
|
|
2189
2321
|
useChatStore.getState().setLoading(false);
|
|
2190
2322
|
useChatStore.getState().setCurrentAssistantMessage(null);
|
|
@@ -3062,11 +3194,103 @@ import {
|
|
|
3062
3194
|
import { useCallback as useCallback2, useEffect as useEffect5, useMemo, useRef as useRef2, useState as useState3 } from "react";
|
|
3063
3195
|
|
|
3064
3196
|
// src/components/ChatView/utils.ts
|
|
3197
|
+
import { expectDefined as expectDefined3 } from "@wrongstack/core";
|
|
3065
3198
|
function fmtTok(n) {
|
|
3066
3199
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
3067
3200
|
if (n >= 1e3) return `${(n / 1e3).toFixed(n >= 1e4 ? 0 : 1)}k`;
|
|
3068
3201
|
return String(n);
|
|
3069
3202
|
}
|
|
3203
|
+
var dayKey = (ts) => {
|
|
3204
|
+
const d = new Date(ts);
|
|
3205
|
+
return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
|
|
3206
|
+
};
|
|
3207
|
+
function dayLabel(ts, now) {
|
|
3208
|
+
const d = new Date(ts);
|
|
3209
|
+
const today = new Date(now);
|
|
3210
|
+
const yest = new Date(now - 864e5);
|
|
3211
|
+
if (dayKey(ts) === dayKey(today.getTime())) return "Today";
|
|
3212
|
+
if (dayKey(ts) === dayKey(yest.getTime())) return "Yesterday";
|
|
3213
|
+
return d.toLocaleDateString(void 0, {
|
|
3214
|
+
weekday: "short",
|
|
3215
|
+
month: "short",
|
|
3216
|
+
day: "numeric",
|
|
3217
|
+
year: d.getFullYear() === today.getFullYear() ? void 0 : "numeric"
|
|
3218
|
+
});
|
|
3219
|
+
}
|
|
3220
|
+
function buildChatRows(messages, now = Date.now()) {
|
|
3221
|
+
const groups = [];
|
|
3222
|
+
for (let i = 0; i < messages.length; i++) {
|
|
3223
|
+
const m = expectDefined3(messages[i]);
|
|
3224
|
+
if (m.role === "tool") {
|
|
3225
|
+
const last = groups[groups.length - 1];
|
|
3226
|
+
if (last && last.kind === "tools") {
|
|
3227
|
+
last.tools.push(m);
|
|
3228
|
+
} else {
|
|
3229
|
+
groups.push({ kind: "tools", tools: [m], key: m.id });
|
|
3230
|
+
}
|
|
3231
|
+
} else {
|
|
3232
|
+
const prev = messages[i - 1];
|
|
3233
|
+
groups.push({ kind: "msg", message: m, isFirst: !prev || prev.role !== m.role });
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
const turns = [];
|
|
3237
|
+
for (const g of groups) {
|
|
3238
|
+
if (g.kind === "msg" && g.message.role === "user") {
|
|
3239
|
+
turns.push({ kind: "user", message: g.message, key: g.message.id });
|
|
3240
|
+
continue;
|
|
3241
|
+
}
|
|
3242
|
+
const last = turns[turns.length - 1];
|
|
3243
|
+
if (last && last.kind === "agent") {
|
|
3244
|
+
last.items.push(g);
|
|
3245
|
+
} else {
|
|
3246
|
+
const key = g.kind === "msg" ? g.message.id : g.key;
|
|
3247
|
+
turns.push({ kind: "agent", items: [g], key });
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
const turnTs = (t) => {
|
|
3251
|
+
if (t.kind === "user") return t.message.timestamp;
|
|
3252
|
+
const first = expectDefined3(t.items[0]);
|
|
3253
|
+
return first.kind === "msg" ? first.message.timestamp : first.tools[0]?.timestamp ?? 0;
|
|
3254
|
+
};
|
|
3255
|
+
const rows = [];
|
|
3256
|
+
let prevDay = null;
|
|
3257
|
+
for (let idx = 0; idx < turns.length; idx++) {
|
|
3258
|
+
const t = expectDefined3(turns[idx]);
|
|
3259
|
+
const ts = turnTs(t);
|
|
3260
|
+
const day = dayKey(ts);
|
|
3261
|
+
if (day !== prevDay) {
|
|
3262
|
+
rows.push({ kind: "day", key: `day-${day}-${idx}`, label: dayLabel(ts, now) });
|
|
3263
|
+
prevDay = day;
|
|
3264
|
+
}
|
|
3265
|
+
if (t.kind === "user") {
|
|
3266
|
+
rows.push({ kind: "user", key: t.key, message: t.message });
|
|
3267
|
+
continue;
|
|
3268
|
+
}
|
|
3269
|
+
const isLastTurn = idx === turns.length - 1;
|
|
3270
|
+
const items = t.items.map((g, gi) => {
|
|
3271
|
+
const isContinuation = gi > 0;
|
|
3272
|
+
if (g.kind === "msg") {
|
|
3273
|
+
return {
|
|
3274
|
+
kind: "msg",
|
|
3275
|
+
key: g.message.id,
|
|
3276
|
+
message: g.message,
|
|
3277
|
+
isFirst: !isContinuation && g.isFirst,
|
|
3278
|
+
isContinuation
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
return {
|
|
3282
|
+
kind: "tools",
|
|
3283
|
+
key: g.key,
|
|
3284
|
+
tools: g.tools,
|
|
3285
|
+
isContinuation,
|
|
3286
|
+
isLastGroup: gi === t.items.length - 1,
|
|
3287
|
+
hasRunningTool: g.tools.some((tt) => tt.toolResult === void 0)
|
|
3288
|
+
};
|
|
3289
|
+
});
|
|
3290
|
+
rows.push({ kind: "agent", key: t.key, items, isLastTurn });
|
|
3291
|
+
}
|
|
3292
|
+
return rows;
|
|
3293
|
+
}
|
|
3070
3294
|
|
|
3071
3295
|
// src/components/ContextBar.tsx
|
|
3072
3296
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -4425,7 +4649,7 @@ function TaskBoard({
|
|
|
4425
4649
|
}
|
|
4426
4650
|
|
|
4427
4651
|
// src/components/WorktreeGraph.tsx
|
|
4428
|
-
import { expectDefined as
|
|
4652
|
+
import { expectDefined as expectDefined4 } from "@wrongstack/core";
|
|
4429
4653
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4430
4654
|
var LANE_COLORS = ["#3b82f6", "#06b6d4", "#22c55e", "#eab308", "#f97316", "#a855f7", "#ec4899"];
|
|
4431
4655
|
var shortBranch = (b) => b.replace(/^wstack\/ap\//, "");
|
|
@@ -4464,7 +4688,7 @@ function WorktreeGraph({
|
|
|
4464
4688
|
/* @__PURE__ */ jsx9("text", { x: trunkX - 4, y: 14, fontSize: 11, fill: "#9ca3af", children: baseBranch || "HEAD" }),
|
|
4465
4689
|
/* @__PURE__ */ jsx9("circle", { cx: trunkX, cy: 20, r: 5, fill: "#F93951" }),
|
|
4466
4690
|
nodes.map((n) => {
|
|
4467
|
-
const e = EDGE_STATE[n.handle.status] ??
|
|
4691
|
+
const e = EDGE_STATE[n.handle.status] ?? expectDefined4(EDGE_STATE.active);
|
|
4468
4692
|
const merged = n.handle.status === "merged";
|
|
4469
4693
|
const conflict = n.handle.status === "needs-review" || n.handle.status === "failed";
|
|
4470
4694
|
return /* @__PURE__ */ jsxs8("g", { className: "transition-all duration-500", children: [
|
|
@@ -4792,7 +5016,6 @@ function AutoPhaseView({ onClose }) {
|
|
|
4792
5016
|
}
|
|
4793
5017
|
|
|
4794
5018
|
// src/components/ChatView/index.tsx
|
|
4795
|
-
import { expectDefined as expectDefined12 } from "@wrongstack/core";
|
|
4796
5019
|
import {
|
|
4797
5020
|
Activity as Activity3,
|
|
4798
5021
|
ArrowDown as ArrowDown3,
|
|
@@ -4806,7 +5029,8 @@ import {
|
|
|
4806
5029
|
Terminal as Terminal4,
|
|
4807
5030
|
Zap as Zap5
|
|
4808
5031
|
} from "lucide-react";
|
|
4809
|
-
import { useCallback as useCallback10, useEffect as useEffect18, useRef as useRef14, useState as useState24 } from "react";
|
|
5032
|
+
import { memo as memo5, useCallback as useCallback10, useEffect as useEffect18, useMemo as useMemo8, useRef as useRef14, useState as useState24 } from "react";
|
|
5033
|
+
import { VList } from "virtua";
|
|
4810
5034
|
|
|
4811
5035
|
// src/components/AutonomyPicker.tsx
|
|
4812
5036
|
import {
|
|
@@ -4925,7 +5149,7 @@ function AutonomyPicker({
|
|
|
4925
5149
|
}
|
|
4926
5150
|
|
|
4927
5151
|
// src/components/ChatInput.tsx
|
|
4928
|
-
import { expectDefined as
|
|
5152
|
+
import { expectDefined as expectDefined7 } from "@wrongstack/core";
|
|
4929
5153
|
import { Pencil, Send, Square as Square2, Sparkles as Sparkles3 } from "lucide-react";
|
|
4930
5154
|
import { useCallback as useCallback5, useEffect as useEffect10, useRef as useRef7, useState as useState9 } from "react";
|
|
4931
5155
|
|
|
@@ -5436,7 +5660,7 @@ function renderGroupedList(filtered, index, dispatch, setIndex) {
|
|
|
5436
5660
|
}
|
|
5437
5661
|
|
|
5438
5662
|
// src/components/FilePicker.tsx
|
|
5439
|
-
import { expectDefined as
|
|
5663
|
+
import { expectDefined as expectDefined5 } from "@wrongstack/core";
|
|
5440
5664
|
import { FileText as FileText2, Folder } from "lucide-react";
|
|
5441
5665
|
import { useEffect as useEffect8, useRef as useRef5, useState as useState7 } from "react";
|
|
5442
5666
|
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
@@ -5478,7 +5702,7 @@ function FilePicker({ query, onPick, onClose }) {
|
|
|
5478
5702
|
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
5479
5703
|
if (files.length === 0) return;
|
|
5480
5704
|
e.preventDefault();
|
|
5481
|
-
onPick(
|
|
5705
|
+
onPick(expectDefined5(files[index]));
|
|
5482
5706
|
} else if (e.key === "Escape") {
|
|
5483
5707
|
e.preventDefault();
|
|
5484
5708
|
onClose();
|
|
@@ -5516,7 +5740,7 @@ function FilePicker({ query, onPick, onClose }) {
|
|
|
5516
5740
|
}
|
|
5517
5741
|
|
|
5518
5742
|
// src/components/ChatInput/slash-commands.ts
|
|
5519
|
-
import { expectDefined as
|
|
5743
|
+
import { expectDefined as expectDefined6 } from "@wrongstack/core";
|
|
5520
5744
|
var SLASH_COMMANDS = [
|
|
5521
5745
|
// Session
|
|
5522
5746
|
{ name: "/new", category: "Session", description: "Start a brand-new session (fresh on disk and in memory)" },
|
|
@@ -5543,12 +5767,12 @@ var SLASH_COMMANDS = [
|
|
|
5543
5767
|
// Config
|
|
5544
5768
|
{ name: "/settings", category: "Config", aliases: ["/model"], description: "Open settings (provider/model/keys)" },
|
|
5545
5769
|
{ name: "/enhance", category: "Config", description: "Toggle prompt refinement before sending" },
|
|
5546
|
-
{ name: "/
|
|
5770
|
+
{ name: "/interrupt", category: "Run", aliases: ["/abort", "/stop", "/int"], description: "Stop the current run (abort the in-flight request)" },
|
|
5547
5771
|
// App
|
|
5548
5772
|
{ name: "/help", category: "App", description: "Show every slash command and what it does" },
|
|
5549
5773
|
{ name: "/exit", category: "App", description: "Exit the session and close WebUI" }
|
|
5550
5774
|
];
|
|
5551
|
-
var SLASH_CATEGORY_ORDER = ["Session", "Inspect", "Config", "App"];
|
|
5775
|
+
var SLASH_CATEGORY_ORDER = ["Run", "Session", "Inspect", "Config", "App"];
|
|
5552
5776
|
function matchSlash(query) {
|
|
5553
5777
|
const q = query.toLowerCase();
|
|
5554
5778
|
if (q === "/" || q === "") return SLASH_COMMANDS;
|
|
@@ -5559,7 +5783,7 @@ function matchSlash(query) {
|
|
|
5559
5783
|
function detectAtMention(value, cursor) {
|
|
5560
5784
|
let i = cursor - 1;
|
|
5561
5785
|
while (i >= 0) {
|
|
5562
|
-
const c =
|
|
5786
|
+
const c = expectDefined6(value[i]);
|
|
5563
5787
|
if (c === "@") {
|
|
5564
5788
|
const prev = i > 0 ? value[i - 1] : "";
|
|
5565
5789
|
if (i === 0 || /\s/.test(prev ?? "")) {
|
|
@@ -6160,8 +6384,10 @@ function ChatInput({
|
|
|
6160
6384
|
downloadChatAsMarkdown();
|
|
6161
6385
|
addMessage({ role: "assistant", content: "\u{1F4E5} Chat exported to your downloads folder." });
|
|
6162
6386
|
return true;
|
|
6387
|
+
case "/interrupt":
|
|
6163
6388
|
case "/abort":
|
|
6164
6389
|
case "/stop":
|
|
6390
|
+
case "/int":
|
|
6165
6391
|
sendAbort();
|
|
6166
6392
|
setLoading(false);
|
|
6167
6393
|
return true;
|
|
@@ -6367,7 +6593,7 @@ function ChatInput({
|
|
|
6367
6593
|
setLoading(false);
|
|
6368
6594
|
const all = useChatStore.getState().messages;
|
|
6369
6595
|
for (let i = all.length - 1; i >= 0; i--) {
|
|
6370
|
-
const m =
|
|
6596
|
+
const m = expectDefined7(all[i]);
|
|
6371
6597
|
if (m.role === "user" && m.content) {
|
|
6372
6598
|
setInput(m.content);
|
|
6373
6599
|
requestAnimationFrame(() => {
|
|
@@ -7041,7 +7267,7 @@ function CheckpointTimeline({
|
|
|
7041
7267
|
}
|
|
7042
7268
|
|
|
7043
7269
|
// src/components/ContextModePicker.tsx
|
|
7044
|
-
import { expectDefined as
|
|
7270
|
+
import { expectDefined as expectDefined8 } from "@wrongstack/core";
|
|
7045
7271
|
import { Check as Check2, ChevronDown as ChevronDown3, Gauge as Gauge2, Wrench as Wrench4, Zap as Zap3, FileSearch } from "lucide-react";
|
|
7046
7272
|
import { useCallback as useCallback7, useEffect as useEffect12, useRef as useRef9, useState as useState11 } from "react";
|
|
7047
7273
|
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
@@ -7100,7 +7326,7 @@ function ContextModePicker() {
|
|
|
7100
7326
|
setOpen(false);
|
|
7101
7327
|
}, [client2]);
|
|
7102
7328
|
const items = contextModes.length > 0 ? contextModes : FALLBACK_MODES;
|
|
7103
|
-
const active = items.find((m) => m.id === contextMode) ??
|
|
7329
|
+
const active = items.find((m) => m.id === contextMode) ?? expectDefined8(items[0]);
|
|
7104
7330
|
return /* @__PURE__ */ jsxs17("div", { ref: rootRef, className: "relative shrink-0", children: [
|
|
7105
7331
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
|
|
7106
7332
|
/* @__PURE__ */ jsxs17(
|
|
@@ -7386,7 +7612,7 @@ function CostChip() {
|
|
|
7386
7612
|
}
|
|
7387
7613
|
|
|
7388
7614
|
// src/components/MessageBubble/index.tsx
|
|
7389
|
-
import { expectDefined as
|
|
7615
|
+
import { expectDefined as expectDefined11 } from "@wrongstack/core";
|
|
7390
7616
|
|
|
7391
7617
|
// src/lib/tool-summary.ts
|
|
7392
7618
|
var FALLBACK_HEAD_FIELDS = [
|
|
@@ -7523,7 +7749,7 @@ import ReactMarkdown from "react-markdown";
|
|
|
7523
7749
|
import remarkGfm from "remark-gfm";
|
|
7524
7750
|
|
|
7525
7751
|
// src/components/DiffView.tsx
|
|
7526
|
-
import { expectDefined as
|
|
7752
|
+
import { expectDefined as expectDefined9 } from "@wrongstack/core";
|
|
7527
7753
|
import { memo, useMemo as useMemo3 } from "react";
|
|
7528
7754
|
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
7529
7755
|
var DiffView = memo(function DiffView2({ oldText, newText, caption }) {
|
|
@@ -7595,8 +7821,8 @@ function computeDiff(oldText, newText) {
|
|
|
7595
7821
|
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
7596
7822
|
for (let i2 = n - 1; i2 >= 0; i2--) {
|
|
7597
7823
|
for (let j2 = m - 1; j2 >= 0; j2--) {
|
|
7598
|
-
if (a[i2] === b[j2])
|
|
7599
|
-
else
|
|
7824
|
+
if (a[i2] === b[j2]) expectDefined9(dp[i2])[j2] = expectDefined9(dp[i2 + 1]?.[j2 + 1]) + 1;
|
|
7825
|
+
else expectDefined9(dp[i2])[j2] = Math.max(expectDefined9(dp[i2 + 1]?.[j2]), expectDefined9(dp[i2]?.[j2 + 1]));
|
|
7600
7826
|
}
|
|
7601
7827
|
}
|
|
7602
7828
|
const rows = [];
|
|
@@ -7604,19 +7830,19 @@ function computeDiff(oldText, newText) {
|
|
|
7604
7830
|
let j = 0;
|
|
7605
7831
|
while (i < n && j < m) {
|
|
7606
7832
|
if (a[i] === b[j]) {
|
|
7607
|
-
rows.push({ kind: "ctx", text:
|
|
7833
|
+
rows.push({ kind: "ctx", text: expectDefined9(a[i]) });
|
|
7608
7834
|
i++;
|
|
7609
7835
|
j++;
|
|
7610
|
-
} else if (
|
|
7611
|
-
rows.push({ kind: "del", text:
|
|
7836
|
+
} else if (expectDefined9(dp[i + 1]?.[j]) >= expectDefined9(dp[i]?.[j + 1])) {
|
|
7837
|
+
rows.push({ kind: "del", text: expectDefined9(a[i]) });
|
|
7612
7838
|
i++;
|
|
7613
7839
|
} else {
|
|
7614
|
-
rows.push({ kind: "add", text:
|
|
7840
|
+
rows.push({ kind: "add", text: expectDefined9(b[j]) });
|
|
7615
7841
|
j++;
|
|
7616
7842
|
}
|
|
7617
7843
|
}
|
|
7618
|
-
while (i < n) rows.push({ kind: "del", text:
|
|
7619
|
-
while (j < m) rows.push({ kind: "add", text:
|
|
7844
|
+
while (i < n) rows.push({ kind: "del", text: expectDefined9(a[i++]) });
|
|
7845
|
+
while (j < m) rows.push({ kind: "add", text: expectDefined9(b[j++]) });
|
|
7620
7846
|
return rows;
|
|
7621
7847
|
}
|
|
7622
7848
|
function diffFromToolInput(toolName, input) {
|
|
@@ -8092,13 +8318,13 @@ function CopyButton({
|
|
|
8092
8318
|
}
|
|
8093
8319
|
|
|
8094
8320
|
// src/components/MessageBubble/ErrorBody.tsx
|
|
8095
|
-
import { expectDefined as
|
|
8321
|
+
import { expectDefined as expectDefined10 } from "@wrongstack/core";
|
|
8096
8322
|
import { useState as useState16 } from "react";
|
|
8097
8323
|
import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
8098
8324
|
function detectStackBoundary(text) {
|
|
8099
8325
|
const lines = text.split("\n");
|
|
8100
8326
|
for (let i = 0; i < lines.length; i++) {
|
|
8101
|
-
const ln =
|
|
8327
|
+
const ln = expectDefined10(lines[i]);
|
|
8102
8328
|
if (/^\s*at\s+\S+.*\(.*:\d+:\d+\)\s*$/.test(ln)) return i;
|
|
8103
8329
|
if (/^\s*at\s+\S+\.\S+\(\S+\.java:\d+\)\s*$/.test(ln)) return i;
|
|
8104
8330
|
if (/^\s+File "[^"]+", line \d+/.test(ln)) return i;
|
|
@@ -8229,7 +8455,7 @@ var MessageBubble = memo3(function MessageBubble2({
|
|
|
8229
8455
|
if (message.role !== "assistant" || isLoading) return false;
|
|
8230
8456
|
const all = useChatStore.getState().messages;
|
|
8231
8457
|
for (let i = all.length - 1; i >= 0; i--) {
|
|
8232
|
-
const m =
|
|
8458
|
+
const m = expectDefined11(all[i]);
|
|
8233
8459
|
if (m.role === "assistant") return m.id === message.id;
|
|
8234
8460
|
}
|
|
8235
8461
|
return false;
|
|
@@ -8246,7 +8472,7 @@ var MessageBubble = memo3(function MessageBubble2({
|
|
|
8246
8472
|
}
|
|
8247
8473
|
}
|
|
8248
8474
|
if (userIdx === -1) return;
|
|
8249
|
-
const userMsg =
|
|
8475
|
+
const userMsg = expectDefined11(all[userIdx]);
|
|
8250
8476
|
truncateAfter(userMsg.id);
|
|
8251
8477
|
addMessage({ role: "user", content: userMsg.content });
|
|
8252
8478
|
setLoading(true);
|
|
@@ -8723,8 +8949,10 @@ function SearchOverlay() {
|
|
|
8723
8949
|
const query = useUIStore((s) => s.searchQuery);
|
|
8724
8950
|
const setQuery = useUIStore((s) => s.setSearchQuery);
|
|
8725
8951
|
const messages = useChatStore((s) => s.messages);
|
|
8952
|
+
const requestScrollToMessage = useUIStore((s) => s.requestScrollToMessage);
|
|
8726
8953
|
const inputRef = useRef13(null);
|
|
8727
8954
|
const [activeHit, setActiveHit] = useState21(0);
|
|
8955
|
+
const [repaintNonce, setRepaintNonce] = useState21(0);
|
|
8728
8956
|
useEffect16(() => {
|
|
8729
8957
|
if (open) requestAnimationFrame(() => inputRef.current?.focus());
|
|
8730
8958
|
}, [open]);
|
|
@@ -8794,15 +9022,18 @@ function SearchOverlay() {
|
|
|
8794
9022
|
highlights.delete("chat-search-active");
|
|
8795
9023
|
}
|
|
8796
9024
|
return clear;
|
|
8797
|
-
}, [query, hits, activeHit, open]);
|
|
9025
|
+
}, [query, hits, activeHit, open, repaintNonce]);
|
|
8798
9026
|
useEffect16(() => {
|
|
8799
9027
|
const id = hits[activeHit];
|
|
8800
9028
|
if (!id) return;
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
9029
|
+
requestScrollToMessage(id);
|
|
9030
|
+
let n = 0;
|
|
9031
|
+
let raf = requestAnimationFrame(function tick() {
|
|
9032
|
+
setRepaintNonce((v) => v + 1);
|
|
9033
|
+
if (++n < 3) raf = requestAnimationFrame(tick);
|
|
9034
|
+
});
|
|
9035
|
+
return () => cancelAnimationFrame(raf);
|
|
9036
|
+
}, [hits, activeHit, requestScrollToMessage]);
|
|
8806
9037
|
if (!open) return null;
|
|
8807
9038
|
const step = (dir) => {
|
|
8808
9039
|
if (hits.length === 0) return;
|
|
@@ -8876,7 +9107,7 @@ function SearchOverlay() {
|
|
|
8876
9107
|
}
|
|
8877
9108
|
|
|
8878
9109
|
// src/components/ToolGroup.tsx
|
|
8879
|
-
import { expectDefined as
|
|
9110
|
+
import { expectDefined as expectDefined12 } from "@wrongstack/core";
|
|
8880
9111
|
import { CheckCircle2 as CheckCircle26, ChevronDown as ChevronDown7, ChevronRight as ChevronRight5, Loader2 as Loader22, Terminal as Terminal3, XCircle as XCircle6 } from "lucide-react";
|
|
8881
9112
|
import { memo as memo4, useState as useState22 } from "react";
|
|
8882
9113
|
import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
@@ -8894,7 +9125,7 @@ var ToolGroup = memo4(function ToolGroup2({
|
|
|
8894
9125
|
}) {
|
|
8895
9126
|
const [open, setOpen] = useState22(defaultOpen);
|
|
8896
9127
|
if (tools.length === 1) {
|
|
8897
|
-
return /* @__PURE__ */ jsx32(MessageBubble, { message:
|
|
9128
|
+
return /* @__PURE__ */ jsx32(MessageBubble, { message: expectDefined12(tools[0]), isFirst: true, isContinuation });
|
|
8898
9129
|
}
|
|
8899
9130
|
const running = tools.filter((t) => t.toolResult === void 0).length;
|
|
8900
9131
|
const errored = tools.filter((t) => t.isError).length;
|
|
@@ -8942,13 +9173,13 @@ var ToolGroup = memo4(function ToolGroup2({
|
|
|
8942
9173
|
import {
|
|
8943
9174
|
ArchiveRestore as ArchiveRestore2,
|
|
8944
9175
|
ArrowRight as ArrowRight3,
|
|
8945
|
-
Bug,
|
|
8946
9176
|
Clock as Clock7,
|
|
9177
|
+
Crosshair,
|
|
8947
9178
|
KeyRound,
|
|
8948
9179
|
Keyboard as Keyboard2,
|
|
9180
|
+
Lightbulb as Lightbulb2,
|
|
8949
9181
|
Search as Search3,
|
|
8950
9182
|
Sparkles as Sparkles4,
|
|
8951
|
-
Wrench as Wrench5,
|
|
8952
9183
|
Zap as Zap4
|
|
8953
9184
|
} from "lucide-react";
|
|
8954
9185
|
import { useEffect as useEffect17, useState as useState23 } from "react";
|
|
@@ -8956,46 +9187,46 @@ import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs31 } from "react/jsx-r
|
|
|
8956
9187
|
var CARDS = [
|
|
8957
9188
|
{
|
|
8958
9189
|
icon: Search3,
|
|
8959
|
-
title: "
|
|
8960
|
-
hint: "
|
|
9190
|
+
title: "Understand",
|
|
9191
|
+
hint: "Explore and analyze the codebase",
|
|
8961
9192
|
tone: "text-blue-600 dark:text-blue-400 bg-blue-500/10 border-blue-500/20",
|
|
8962
9193
|
prompts: [
|
|
8963
|
-
"
|
|
8964
|
-
"Find the public API surface
|
|
8965
|
-
"
|
|
9194
|
+
"Map out the structure of this codebase: what are the main modules or components, how do they depend on each other, and what are the key patterns used throughout?",
|
|
9195
|
+
"Find and document the public API surface \u2014 all exported interfaces, functions, and types that other parts of the system depend on.",
|
|
9196
|
+
"Trace the flow of data through the system for a typical operation. Where does input validation happen? Where are side effects triggered?"
|
|
8966
9197
|
]
|
|
8967
9198
|
},
|
|
8968
9199
|
{
|
|
8969
|
-
icon:
|
|
8970
|
-
title: "
|
|
8971
|
-
hint: "
|
|
9200
|
+
icon: Lightbulb2,
|
|
9201
|
+
title: "Create",
|
|
9202
|
+
hint: "Build new features and functionality",
|
|
8972
9203
|
tone: "text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 border-emerald-500/20",
|
|
8973
9204
|
prompts: [
|
|
8974
|
-
"Add a new
|
|
8975
|
-
"Write comprehensive tests for
|
|
8976
|
-
"Add
|
|
9205
|
+
"Add a new feature that covers the full stack: data model, business logic, and any UI or API layers. Follow existing patterns in this codebase.",
|
|
9206
|
+
"Write comprehensive tests for a module with low coverage. Include happy paths, edge cases, and error scenarios.",
|
|
9207
|
+
"Add observability to a critical path \u2014 structured logging, error tracking, or metrics that help diagnose issues in production."
|
|
8977
9208
|
]
|
|
8978
9209
|
},
|
|
8979
9210
|
{
|
|
8980
|
-
icon:
|
|
8981
|
-
title: "
|
|
8982
|
-
hint: "
|
|
9211
|
+
icon: Crosshair,
|
|
9212
|
+
title: "Investigate",
|
|
9213
|
+
hint: "Debug issues and find root causes",
|
|
8983
9214
|
tone: "text-amber-600 dark:text-amber-400 bg-amber-500/10 border-amber-500/20",
|
|
8984
9215
|
prompts: [
|
|
8985
|
-
"Something isn't
|
|
8986
|
-
"
|
|
8987
|
-
"Performance
|
|
9216
|
+
"Something isn't working as expected \u2014 help me trace from the symptom to the root cause. Follow the code path and identify where behavior diverges from intent.",
|
|
9217
|
+
"There's a difference between how this works locally versus in production or CI. Check for environment differences, configuration issues, or hidden assumptions.",
|
|
9218
|
+
"Performance is degrading. Identify the bottlenecks \u2014 whether N+1 queries, blocking I/O, unnecessary allocations, or something else \u2014 and propose targeted fixes."
|
|
8988
9219
|
]
|
|
8989
9220
|
},
|
|
8990
9221
|
{
|
|
8991
9222
|
icon: Sparkles4,
|
|
8992
|
-
title: "
|
|
8993
|
-
hint: "
|
|
9223
|
+
title: "Improve",
|
|
9224
|
+
hint: "Refactor and optimize existing code",
|
|
8994
9225
|
tone: "text-violet-600 dark:text-violet-400 bg-violet-500/10 border-violet-500/20",
|
|
8995
9226
|
prompts: [
|
|
8996
|
-
"Find duplicated or
|
|
8997
|
-
"Identify modules that have grown too large or
|
|
8998
|
-
"
|
|
9227
|
+
"Find duplicated or similar logic that could be consolidated into shared utilities. Extract the common parts and update the call sites.",
|
|
9228
|
+
"Identify modules that have grown too large or handle too many responsibilities. Propose a cleaner separation that can be done incrementally.",
|
|
9229
|
+
"Review error handling across the codebase: are errors consistent, well-contextualized, and properly propagated? Suggest improvements to the worst cases."
|
|
8999
9230
|
]
|
|
9000
9231
|
}
|
|
9001
9232
|
];
|
|
@@ -9211,62 +9442,73 @@ function WelcomeScreen() {
|
|
|
9211
9442
|
] });
|
|
9212
9443
|
}
|
|
9213
9444
|
|
|
9214
|
-
// src/components/ui/scroll-area.tsx
|
|
9215
|
-
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
9216
|
-
import * as React2 from "react";
|
|
9217
|
-
import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
9218
|
-
var ScrollArea = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs32(
|
|
9219
|
-
ScrollAreaPrimitive.Root,
|
|
9220
|
-
{
|
|
9221
|
-
ref,
|
|
9222
|
-
className: cn("relative overflow-hidden", className),
|
|
9223
|
-
...props,
|
|
9224
|
-
children: [
|
|
9225
|
-
/* @__PURE__ */ jsx34(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
|
|
9226
|
-
/* @__PURE__ */ jsx34(ScrollBar, {}),
|
|
9227
|
-
/* @__PURE__ */ jsx34(ScrollAreaPrimitive.Corner, {})
|
|
9228
|
-
]
|
|
9229
|
-
}
|
|
9230
|
-
));
|
|
9231
|
-
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
9232
|
-
var ScrollBar = React2.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx34(
|
|
9233
|
-
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
9234
|
-
{
|
|
9235
|
-
ref,
|
|
9236
|
-
orientation,
|
|
9237
|
-
className: cn(
|
|
9238
|
-
"flex touch-none select-none transition-colors",
|
|
9239
|
-
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
9240
|
-
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
9241
|
-
className
|
|
9242
|
-
),
|
|
9243
|
-
...props,
|
|
9244
|
-
children: /* @__PURE__ */ jsx34(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
|
|
9245
|
-
}
|
|
9246
|
-
));
|
|
9247
|
-
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
9248
|
-
|
|
9249
9445
|
// src/components/ChatView/ThinkingBubble.tsx
|
|
9250
9446
|
import { Brain as Brain2 } from "lucide-react";
|
|
9251
|
-
import { jsx as
|
|
9447
|
+
import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
9252
9448
|
function ThinkingBubble() {
|
|
9253
9449
|
const buf = useChatStore((s) => s.thinkingBuffer);
|
|
9254
9450
|
if (!buf) return null;
|
|
9255
9451
|
const tailLines = buf.split("\n").slice(-6);
|
|
9256
9452
|
const tail = tailLines.join("\n").trim();
|
|
9257
|
-
return /* @__PURE__ */
|
|
9258
|
-
/* @__PURE__ */
|
|
9259
|
-
/* @__PURE__ */
|
|
9260
|
-
/* @__PURE__ */
|
|
9261
|
-
/* @__PURE__ */
|
|
9453
|
+
return /* @__PURE__ */ jsxs32("div", { className: "flex gap-3 animate-message", children: [
|
|
9454
|
+
/* @__PURE__ */ jsx34("div", { className: "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-violet-500/10 text-violet-600 dark:text-violet-400 ring-2 ring-offset-2 ring-offset-background ring-violet-500/20", children: /* @__PURE__ */ jsx34(Brain2, { className: "h-4 w-4 animate-pulse" }) }),
|
|
9455
|
+
/* @__PURE__ */ jsxs32("div", { className: "flex flex-col gap-1 max-w-[85%] min-w-0", children: [
|
|
9456
|
+
/* @__PURE__ */ jsx34("span", { className: "text-xs font-medium text-violet-600 dark:text-violet-400 px-1", children: "Thinking\u2026" }),
|
|
9457
|
+
/* @__PURE__ */ jsx34("div", { className: "rounded-2xl rounded-bl-md px-3 py-2 bg-violet-500/[0.04] border border-violet-500/20 text-foreground/80", children: /* @__PURE__ */ jsx34("pre", { className: "whitespace-pre-wrap break-words font-sans text-xs leading-relaxed italic max-h-32 overflow-hidden", children: tail || "\u2026" }) })
|
|
9262
9458
|
] })
|
|
9263
9459
|
] });
|
|
9264
9460
|
}
|
|
9265
9461
|
|
|
9266
9462
|
// src/components/ChatView/index.tsx
|
|
9267
|
-
import { Fragment as Fragment9, jsx as
|
|
9463
|
+
import { Fragment as Fragment9, jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
9464
|
+
var ChatRowView = memo5(function ChatRowView2({
|
|
9465
|
+
row,
|
|
9466
|
+
isLoading,
|
|
9467
|
+
compactMode,
|
|
9468
|
+
isFirstRow
|
|
9469
|
+
}) {
|
|
9470
|
+
const wrap = cn(
|
|
9471
|
+
"mx-auto max-w-5xl w-full px-4",
|
|
9472
|
+
isFirstRow && "pt-4",
|
|
9473
|
+
compactMode ? "pb-3" : "pb-6"
|
|
9474
|
+
);
|
|
9475
|
+
if (row.kind === "day") {
|
|
9476
|
+
return /* @__PURE__ */ jsx35("div", { className: wrap, children: /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-3 py-1 text-[11px] text-muted-foreground/70 uppercase tracking-wider font-medium", children: [
|
|
9477
|
+
/* @__PURE__ */ jsx35("div", { className: "flex-1 h-px bg-border/50" }),
|
|
9478
|
+
/* @__PURE__ */ jsx35("span", { children: row.label }),
|
|
9479
|
+
/* @__PURE__ */ jsx35("div", { className: "flex-1 h-px bg-border/50" })
|
|
9480
|
+
] }) });
|
|
9481
|
+
}
|
|
9482
|
+
if (row.kind === "user") {
|
|
9483
|
+
return /* @__PURE__ */ jsx35("div", { className: wrap, children: /* @__PURE__ */ jsx35(MessageBubble, { message: row.message, isFirst: true }) });
|
|
9484
|
+
}
|
|
9485
|
+
return /* @__PURE__ */ jsx35("div", { className: wrap, children: /* @__PURE__ */ jsx35("div", { className: cn("chat-turn", compactMode ? "space-y-1" : "space-y-1.5"), children: row.items.map((it) => {
|
|
9486
|
+
if (it.kind === "msg") {
|
|
9487
|
+
return /* @__PURE__ */ jsx35(
|
|
9488
|
+
MessageBubble,
|
|
9489
|
+
{
|
|
9490
|
+
message: it.message,
|
|
9491
|
+
isFirst: it.isFirst,
|
|
9492
|
+
isContinuation: it.isContinuation
|
|
9493
|
+
},
|
|
9494
|
+
it.key
|
|
9495
|
+
);
|
|
9496
|
+
}
|
|
9497
|
+
const defaultOpen = row.isLastTurn && it.isLastGroup && isLoading && it.hasRunningTool;
|
|
9498
|
+
return /* @__PURE__ */ jsx35(
|
|
9499
|
+
ToolGroup,
|
|
9500
|
+
{
|
|
9501
|
+
tools: it.tools,
|
|
9502
|
+
defaultOpen,
|
|
9503
|
+
isContinuation: it.isContinuation
|
|
9504
|
+
},
|
|
9505
|
+
it.key
|
|
9506
|
+
);
|
|
9507
|
+
}) }) });
|
|
9508
|
+
});
|
|
9268
9509
|
function ChatView() {
|
|
9269
|
-
const
|
|
9510
|
+
const messages = useChatStore((s) => s.messages);
|
|
9511
|
+
const isLoading = useChatStore((s) => s.isLoading);
|
|
9270
9512
|
const sidebarOpen = useUIStore((s) => s.sidebarOpen);
|
|
9271
9513
|
const toggleSidebar = useUIStore((s) => s.toggleSidebar);
|
|
9272
9514
|
const compactMode = useUIStore((s) => s.compactMode);
|
|
@@ -9297,7 +9539,24 @@ function ChatView() {
|
|
|
9297
9539
|
};
|
|
9298
9540
|
}, [switcherOpen]);
|
|
9299
9541
|
const { provider, model } = useConfigStore();
|
|
9300
|
-
const
|
|
9542
|
+
const vlistRef = useRef14(null);
|
|
9543
|
+
const rows = useMemo8(() => buildChatRows(messages), [messages]);
|
|
9544
|
+
const childCountRef = useRef14(0);
|
|
9545
|
+
childCountRef.current = rows.length + 1;
|
|
9546
|
+
const rowIndexById = useMemo8(() => {
|
|
9547
|
+
const map = /* @__PURE__ */ new Map();
|
|
9548
|
+
rows.forEach((row, i) => {
|
|
9549
|
+
if (row.kind === "user") map.set(row.message.id, i);
|
|
9550
|
+
else if (row.kind === "agent") {
|
|
9551
|
+
for (const it of row.items) {
|
|
9552
|
+
if (it.kind === "msg") map.set(it.message.id, i);
|
|
9553
|
+
else for (const t of it.tools) map.set(t.id, i);
|
|
9554
|
+
}
|
|
9555
|
+
}
|
|
9556
|
+
});
|
|
9557
|
+
return map;
|
|
9558
|
+
}, [rows]);
|
|
9559
|
+
const scrollTarget = useUIStore((s) => s.scrollTarget);
|
|
9301
9560
|
const autonomy = useLocalPrefs((s) => s.autonomy);
|
|
9302
9561
|
const handleAutonomyChange = useCallback10((mode) => {
|
|
9303
9562
|
useLocalPrefs.getState().set({ autonomy: mode });
|
|
@@ -9318,58 +9577,52 @@ function ChatView() {
|
|
|
9318
9577
|
const [unreadCount, setUnreadCount] = useState24(0);
|
|
9319
9578
|
const [scrolledDeep, setScrolledDeep] = useState24(false);
|
|
9320
9579
|
const lastSeenCount = useRef14(messages.length);
|
|
9321
|
-
const
|
|
9322
|
-
|
|
9580
|
+
const handleScroll = useCallback10(() => {
|
|
9581
|
+
const h = vlistRef.current;
|
|
9582
|
+
if (!h) return;
|
|
9583
|
+
const dist = h.scrollSize - h.scrollOffset - h.viewportSize;
|
|
9584
|
+
const nowPinned = dist < 120;
|
|
9585
|
+
setPinnedToBottom(nowPinned);
|
|
9586
|
+
if (nowPinned) {
|
|
9587
|
+
setUnreadCount(0);
|
|
9588
|
+
lastSeenCount.current = useChatStore.getState().messages.length;
|
|
9589
|
+
}
|
|
9590
|
+
setScrolledDeep(h.scrollOffset > h.viewportSize && h.scrollSize > h.viewportSize * 2.5);
|
|
9323
9591
|
}, []);
|
|
9324
9592
|
useEffect18(() => {
|
|
9325
|
-
const
|
|
9326
|
-
if (!
|
|
9327
|
-
const onScroll = () => {
|
|
9328
|
-
const dist = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
|
|
9329
|
-
const nowPinned = dist < 120;
|
|
9330
|
-
setPinnedToBottom(nowPinned);
|
|
9331
|
-
if (nowPinned) {
|
|
9332
|
-
setUnreadCount(0);
|
|
9333
|
-
lastSeenCount.current = messages.length;
|
|
9334
|
-
}
|
|
9335
|
-
const deep = viewport.scrollTop > viewport.clientHeight && viewport.scrollHeight > viewport.clientHeight * 2.5;
|
|
9336
|
-
setScrolledDeep(deep);
|
|
9337
|
-
};
|
|
9338
|
-
viewport.addEventListener("scroll", onScroll, { passive: true });
|
|
9339
|
-
return () => viewport.removeEventListener("scroll", onScroll);
|
|
9340
|
-
}, [getViewport, messages.length]);
|
|
9341
|
-
useEffect18(() => {
|
|
9342
|
-
const viewport = getViewport();
|
|
9343
|
-
if (!viewport) return;
|
|
9593
|
+
const h = vlistRef.current;
|
|
9594
|
+
if (!h) return;
|
|
9344
9595
|
if (pinnedToBottom) {
|
|
9345
|
-
|
|
9596
|
+
h.scrollToIndex(childCountRef.current - 1, { align: "end" });
|
|
9346
9597
|
lastSeenCount.current = messages.length;
|
|
9347
9598
|
} else {
|
|
9348
9599
|
const delta = messages.length - lastSeenCount.current;
|
|
9349
9600
|
if (delta > 0) setUnreadCount(delta);
|
|
9350
9601
|
}
|
|
9351
|
-
}, [messages, pinnedToBottom
|
|
9602
|
+
}, [messages, pinnedToBottom]);
|
|
9352
9603
|
useEffect18(() => {
|
|
9353
|
-
const viewport = getViewport();
|
|
9354
|
-
if (!viewport) return;
|
|
9355
|
-
viewport.scrollTop = viewport.scrollHeight;
|
|
9356
9604
|
setPinnedToBottom(true);
|
|
9357
9605
|
setUnreadCount(0);
|
|
9358
9606
|
lastSeenCount.current = useChatStore.getState().messages.length;
|
|
9359
|
-
|
|
9607
|
+
requestAnimationFrame(() => {
|
|
9608
|
+
vlistRef.current?.scrollToIndex(childCountRef.current - 1, { align: "end" });
|
|
9609
|
+
});
|
|
9610
|
+
}, [sessionId]);
|
|
9611
|
+
useEffect18(() => {
|
|
9612
|
+
if (!scrollTarget) return;
|
|
9613
|
+
const idx = rowIndexById.get(scrollTarget.id);
|
|
9614
|
+
if (idx === void 0) return;
|
|
9615
|
+
vlistRef.current?.scrollToIndex(idx, { align: "center", smooth: true });
|
|
9616
|
+
}, [scrollTarget, rowIndexById]);
|
|
9360
9617
|
const scrollToBottom = useCallback10(() => {
|
|
9361
|
-
|
|
9362
|
-
if (!viewport) return;
|
|
9363
|
-
viewport.scrollTo({ top: viewport.scrollHeight, behavior: "smooth" });
|
|
9618
|
+
vlistRef.current?.scrollToIndex(childCountRef.current - 1, { align: "end", smooth: true });
|
|
9364
9619
|
setPinnedToBottom(true);
|
|
9365
9620
|
setUnreadCount(0);
|
|
9366
|
-
lastSeenCount.current = messages.length;
|
|
9367
|
-
}, [
|
|
9621
|
+
lastSeenCount.current = useChatStore.getState().messages.length;
|
|
9622
|
+
}, []);
|
|
9368
9623
|
const scrollToTop = useCallback10(() => {
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
viewport.scrollTo({ top: 0, behavior: "smooth" });
|
|
9372
|
-
}, [getViewport]);
|
|
9624
|
+
vlistRef.current?.scrollToIndex(0, { align: "start", smooth: true });
|
|
9625
|
+
}, []);
|
|
9373
9626
|
const [runStartedAt, setRunStartedAt] = useState24(null);
|
|
9374
9627
|
const [nowTick, setNowTick] = useState24(() => Date.now());
|
|
9375
9628
|
const streamAnchor = useRef14(null);
|
|
@@ -9398,11 +9651,11 @@ function ChatView() {
|
|
|
9398
9651
|
})();
|
|
9399
9652
|
const stateTone = agentState === "idle" ? "bg-muted text-muted-foreground" : agentState === "streaming" ? "bg-blue-500/10 text-blue-600 dark:text-blue-400" : "bg-amber-500/10 text-amber-600 dark:text-amber-400";
|
|
9400
9653
|
const hasStatusContent = maxContext > 0 && lastInputTokens > 0 || totalTokens.input > 0 || !!startTime;
|
|
9401
|
-
return /* @__PURE__ */
|
|
9402
|
-
/* @__PURE__ */
|
|
9403
|
-
/* @__PURE__ */
|
|
9404
|
-
/* @__PURE__ */
|
|
9405
|
-
!sidebarOpen && /* @__PURE__ */
|
|
9654
|
+
return /* @__PURE__ */ jsxs33("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
9655
|
+
/* @__PURE__ */ jsxs33("header", { className: "flex flex-col border-b bg-card/95 backdrop-blur-sm supports-[backdrop-filter]:bg-card/80 shrink-0 sticky top-0 z-20", children: [
|
|
9656
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-2 px-3 py-2", children: [
|
|
9657
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-1.5 min-w-0 flex-1 overflow-hidden", children: [
|
|
9658
|
+
!sidebarOpen && /* @__PURE__ */ jsx35(
|
|
9406
9659
|
Button,
|
|
9407
9660
|
{
|
|
9408
9661
|
variant: "ghost",
|
|
@@ -9410,11 +9663,11 @@ function ChatView() {
|
|
|
9410
9663
|
className: "h-7 w-7 shrink-0",
|
|
9411
9664
|
onClick: toggleSidebar,
|
|
9412
9665
|
title: "Open sidebar (Ctrl+\\\\)",
|
|
9413
|
-
children: /* @__PURE__ */
|
|
9666
|
+
children: /* @__PURE__ */ jsx35(PanelLeftOpen, { className: "h-4 w-4" })
|
|
9414
9667
|
}
|
|
9415
9668
|
),
|
|
9416
|
-
!sidebarOpen && /* @__PURE__ */
|
|
9417
|
-
/* @__PURE__ */
|
|
9669
|
+
!sidebarOpen && /* @__PURE__ */ jsx35("div", { className: "flex items-center gap-1.5 shrink-0 mr-1", children: /* @__PURE__ */ jsx35("div", { className: "w-5 h-5 rounded bg-primary flex items-center justify-center", children: /* @__PURE__ */ jsx35(Zap5, { className: "h-3 w-3 text-primary-foreground" }) }) }),
|
|
9670
|
+
/* @__PURE__ */ jsxs33(
|
|
9418
9671
|
"span",
|
|
9419
9672
|
{
|
|
9420
9673
|
className: cn(
|
|
@@ -9423,12 +9676,12 @@ function ChatView() {
|
|
|
9423
9676
|
),
|
|
9424
9677
|
title: `Agent state: ${agentState}`,
|
|
9425
9678
|
children: [
|
|
9426
|
-
agentState !== "idle" && /* @__PURE__ */
|
|
9427
|
-
/* @__PURE__ */
|
|
9679
|
+
agentState !== "idle" && /* @__PURE__ */ jsx35("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-pulse" }),
|
|
9680
|
+
/* @__PURE__ */ jsx35("span", { children: agentState })
|
|
9428
9681
|
]
|
|
9429
9682
|
}
|
|
9430
9683
|
),
|
|
9431
|
-
sessionId && (renamingTitle ? /* @__PURE__ */
|
|
9684
|
+
sessionId && (renamingTitle ? /* @__PURE__ */ jsx35(
|
|
9432
9685
|
"input",
|
|
9433
9686
|
{
|
|
9434
9687
|
value: titleDraft,
|
|
@@ -9451,7 +9704,7 @@ function ChatView() {
|
|
|
9451
9704
|
className: "h-5 px-1.5 text-[11px] bg-background border border-primary/40 rounded focus:outline-none focus:ring-1 focus:ring-ring shrink-0 w-32",
|
|
9452
9705
|
autoFocus: true
|
|
9453
9706
|
}
|
|
9454
|
-
) : /* @__PURE__ */
|
|
9707
|
+
) : /* @__PURE__ */ jsxs33(
|
|
9455
9708
|
"button",
|
|
9456
9709
|
{
|
|
9457
9710
|
type: "button",
|
|
@@ -9462,15 +9715,15 @@ function ChatView() {
|
|
|
9462
9715
|
className: "flex items-center gap-1 text-[11px] font-medium text-foreground/80 hover:text-foreground truncate max-w-[12rem] shrink-0 px-1 -mx-1 rounded hover:bg-muted/50 transition-colors",
|
|
9463
9716
|
title: "Click to rename session",
|
|
9464
9717
|
children: [
|
|
9465
|
-
/* @__PURE__ */
|
|
9466
|
-
/* @__PURE__ */
|
|
9718
|
+
/* @__PURE__ */ jsx35(Pencil3, { className: "h-2.5 w-2.5 text-muted-foreground shrink-0" }),
|
|
9719
|
+
/* @__PURE__ */ jsx35("span", { className: "truncate", children: nickname || sessionTitle || "Untitled" })
|
|
9467
9720
|
]
|
|
9468
9721
|
}
|
|
9469
9722
|
))
|
|
9470
9723
|
] }),
|
|
9471
|
-
/* @__PURE__ */
|
|
9472
|
-
historyEntries.length > 1 && /* @__PURE__ */
|
|
9473
|
-
/* @__PURE__ */
|
|
9724
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
9725
|
+
historyEntries.length > 1 && /* @__PURE__ */ jsxs33("div", { ref: switcherRef, className: "relative shrink-0", children: [
|
|
9726
|
+
/* @__PURE__ */ jsxs33(
|
|
9474
9727
|
"button",
|
|
9475
9728
|
{
|
|
9476
9729
|
type: "button",
|
|
@@ -9478,12 +9731,12 @@ function ChatView() {
|
|
|
9478
9731
|
className: "flex items-center gap-0.5 px-1 py-0.5 rounded text-[10px] text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors",
|
|
9479
9732
|
title: "Switch session",
|
|
9480
9733
|
children: [
|
|
9481
|
-
/* @__PURE__ */
|
|
9482
|
-
/* @__PURE__ */
|
|
9734
|
+
/* @__PURE__ */ jsx35(History2, { className: "h-3 w-3" }),
|
|
9735
|
+
/* @__PURE__ */ jsx35(ChevronDown8, { className: "h-2.5 w-2.5" })
|
|
9483
9736
|
]
|
|
9484
9737
|
}
|
|
9485
9738
|
),
|
|
9486
|
-
switcherOpen && /* @__PURE__ */
|
|
9739
|
+
switcherOpen && /* @__PURE__ */ jsx35("div", { className: "absolute left-0 top-full mt-1 z-40 w-64 rounded-md border bg-popover shadow-lg p-1 max-h-60 overflow-y-auto", children: historyEntries.slice(0, 15).map((e) => /* @__PURE__ */ jsxs33(
|
|
9487
9740
|
"button",
|
|
9488
9741
|
{
|
|
9489
9742
|
type: "button",
|
|
@@ -9497,8 +9750,8 @@ function ChatView() {
|
|
|
9497
9750
|
e.isCurrent && "bg-primary/10"
|
|
9498
9751
|
),
|
|
9499
9752
|
children: [
|
|
9500
|
-
/* @__PURE__ */
|
|
9501
|
-
/* @__PURE__ */
|
|
9753
|
+
/* @__PURE__ */ jsx35("div", { className: "font-medium truncate", children: e.title || "(empty)" }),
|
|
9754
|
+
/* @__PURE__ */ jsxs33("div", { className: "text-[10px] text-muted-foreground font-mono truncate", children: [
|
|
9502
9755
|
e.provider,
|
|
9503
9756
|
"/",
|
|
9504
9757
|
e.model,
|
|
@@ -9511,7 +9764,7 @@ function ChatView() {
|
|
|
9511
9764
|
e.id
|
|
9512
9765
|
)) })
|
|
9513
9766
|
] }),
|
|
9514
|
-
/* @__PURE__ */
|
|
9767
|
+
/* @__PURE__ */ jsxs33(
|
|
9515
9768
|
"button",
|
|
9516
9769
|
{
|
|
9517
9770
|
type: "button",
|
|
@@ -9519,20 +9772,20 @@ function ChatView() {
|
|
|
9519
9772
|
className: "group hidden sm:flex items-center gap-1 px-2 py-0.5 rounded-md border bg-background/50 hover:bg-accent hover:border-primary/40 transition-colors text-[11px] min-w-0 shrink-0",
|
|
9520
9773
|
title: "Change provider / model (Ctrl+M)",
|
|
9521
9774
|
children: [
|
|
9522
|
-
/* @__PURE__ */
|
|
9523
|
-
/* @__PURE__ */
|
|
9524
|
-
/* @__PURE__ */
|
|
9525
|
-
/* @__PURE__ */
|
|
9526
|
-
/* @__PURE__ */
|
|
9775
|
+
/* @__PURE__ */ jsx35(Cpu5, { className: "h-3 w-3 text-muted-foreground group-hover:text-foreground shrink-0" }),
|
|
9776
|
+
/* @__PURE__ */ jsxs33("span", { className: "font-mono truncate max-w-[9rem] xl:max-w-[16rem]", children: [
|
|
9777
|
+
/* @__PURE__ */ jsx35("span", { className: "text-muted-foreground", children: provider || "no-provider" }),
|
|
9778
|
+
/* @__PURE__ */ jsx35("span", { className: "text-muted-foreground/40 mx-0.5", children: "/" }),
|
|
9779
|
+
/* @__PURE__ */ jsx35("span", { className: "font-medium", children: model || "no-model" })
|
|
9527
9780
|
] })
|
|
9528
9781
|
]
|
|
9529
9782
|
}
|
|
9530
9783
|
),
|
|
9531
|
-
/* @__PURE__ */
|
|
9532
|
-
/* @__PURE__ */
|
|
9533
|
-
/* @__PURE__ */
|
|
9784
|
+
/* @__PURE__ */ jsxs33("div", { className: "hidden md:flex items-center gap-1.5 shrink-0", children: [
|
|
9785
|
+
/* @__PURE__ */ jsx35(ModePicker, {}),
|
|
9786
|
+
/* @__PURE__ */ jsx35(ContextModePicker, {})
|
|
9534
9787
|
] }),
|
|
9535
|
-
iteration && /* @__PURE__ */
|
|
9788
|
+
iteration && /* @__PURE__ */ jsxs33(
|
|
9536
9789
|
"button",
|
|
9537
9790
|
{
|
|
9538
9791
|
type: "button",
|
|
@@ -9540,17 +9793,17 @@ function ChatView() {
|
|
|
9540
9793
|
title: "Agent iteration \u2014 click to jump to live activity",
|
|
9541
9794
|
onClick: () => document.getElementById("chat-activity")?.scrollIntoView({ behavior: "smooth", block: "center" }),
|
|
9542
9795
|
children: [
|
|
9543
|
-
/* @__PURE__ */
|
|
9796
|
+
/* @__PURE__ */ jsx35(Activity3, { className: "h-3 w-3 animate-pulse" }),
|
|
9544
9797
|
"iter ",
|
|
9545
9798
|
iteration.index,
|
|
9546
9799
|
iteration.max > 0 ? `/${iteration.max}` : ""
|
|
9547
9800
|
]
|
|
9548
9801
|
}
|
|
9549
9802
|
),
|
|
9550
|
-
/* @__PURE__ */
|
|
9803
|
+
/* @__PURE__ */ jsx35(AutonomyPicker, { value: autonomy, onChange: handleAutonomyChange, compact: true })
|
|
9551
9804
|
] }),
|
|
9552
|
-
/* @__PURE__ */
|
|
9553
|
-
/* @__PURE__ */
|
|
9805
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-0.5 shrink-0", children: [
|
|
9806
|
+
/* @__PURE__ */ jsxs33(
|
|
9554
9807
|
Button,
|
|
9555
9808
|
{
|
|
9556
9809
|
variant: processOpen ? "secondary" : "ghost",
|
|
@@ -9559,12 +9812,12 @@ function ChatView() {
|
|
|
9559
9812
|
onClick: () => setProcessOpen((v) => !v),
|
|
9560
9813
|
title: "Running processes",
|
|
9561
9814
|
children: [
|
|
9562
|
-
/* @__PURE__ */
|
|
9563
|
-
processOpen && /* @__PURE__ */
|
|
9815
|
+
/* @__PURE__ */ jsx35(Terminal4, { className: "h-4 w-4" }),
|
|
9816
|
+
processOpen && /* @__PURE__ */ jsx35("span", { className: "absolute -bottom-0.5 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-amber-500" })
|
|
9564
9817
|
]
|
|
9565
9818
|
}
|
|
9566
9819
|
),
|
|
9567
|
-
/* @__PURE__ */
|
|
9820
|
+
/* @__PURE__ */ jsxs33(
|
|
9568
9821
|
Button,
|
|
9569
9822
|
{
|
|
9570
9823
|
variant: checkpointOpen ? "secondary" : "ghost",
|
|
@@ -9573,16 +9826,16 @@ function ChatView() {
|
|
|
9573
9826
|
onClick: () => setCheckpointOpen((v) => !v),
|
|
9574
9827
|
title: "Session checkpoints \u2014 rewind",
|
|
9575
9828
|
children: [
|
|
9576
|
-
/* @__PURE__ */
|
|
9577
|
-
checkpointOpen && /* @__PURE__ */
|
|
9829
|
+
/* @__PURE__ */ jsx35(History2, { className: "h-4 w-4" }),
|
|
9830
|
+
checkpointOpen && /* @__PURE__ */ jsx35("span", { className: "absolute -bottom-0.5 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-violet-500" })
|
|
9578
9831
|
]
|
|
9579
9832
|
}
|
|
9580
9833
|
)
|
|
9581
9834
|
] })
|
|
9582
9835
|
] }),
|
|
9583
|
-
hasStatusContent && /* @__PURE__ */
|
|
9584
|
-
/* @__PURE__ */
|
|
9585
|
-
lastInputTokens > 0 && /* @__PURE__ */
|
|
9836
|
+
hasStatusContent && /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-3 px-3 py-1 border-t bg-muted/20 text-[11px] text-muted-foreground", children: [
|
|
9837
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-3 min-w-0 flex-1 tabular-nums", children: [
|
|
9838
|
+
lastInputTokens > 0 && /* @__PURE__ */ jsx35(
|
|
9586
9839
|
ContextFillBar,
|
|
9587
9840
|
{
|
|
9588
9841
|
pct: ctxPct,
|
|
@@ -9591,26 +9844,26 @@ function ChatView() {
|
|
|
9591
9844
|
onClick: () => setBreakdownOpen(true)
|
|
9592
9845
|
}
|
|
9593
9846
|
),
|
|
9594
|
-
totalTokens.input > 0 && /* @__PURE__ */
|
|
9595
|
-
/* @__PURE__ */
|
|
9596
|
-
/* @__PURE__ */
|
|
9597
|
-
/* @__PURE__ */
|
|
9847
|
+
totalTokens.input > 0 && /* @__PURE__ */ jsxs33(Fragment9, { children: [
|
|
9848
|
+
/* @__PURE__ */ jsxs33("span", { className: "flex items-center gap-1", children: [
|
|
9849
|
+
/* @__PURE__ */ jsx35("span", { className: "font-medium text-foreground", children: fmtTok(totalTokens.input) }),
|
|
9850
|
+
/* @__PURE__ */ jsx35("span", { children: "in" })
|
|
9598
9851
|
] }),
|
|
9599
|
-
/* @__PURE__ */
|
|
9600
|
-
/* @__PURE__ */
|
|
9601
|
-
/* @__PURE__ */
|
|
9852
|
+
/* @__PURE__ */ jsxs33("span", { className: "flex items-center gap-1", children: [
|
|
9853
|
+
/* @__PURE__ */ jsx35("span", { className: "font-medium text-foreground", children: fmtTok(totalTokens.output) }),
|
|
9854
|
+
/* @__PURE__ */ jsx35("span", { children: "out" })
|
|
9602
9855
|
] }),
|
|
9603
9856
|
totalTokens.cacheRead && totalTokens.cacheRead > 0 && (() => {
|
|
9604
9857
|
const denom = (totalTokens.cacheRead ?? 0) + totalTokens.input;
|
|
9605
9858
|
const pct = denom > 0 ? Math.round((totalTokens.cacheRead ?? 0) / denom * 100) : 0;
|
|
9606
|
-
return /* @__PURE__ */
|
|
9859
|
+
return /* @__PURE__ */ jsxs33(
|
|
9607
9860
|
"span",
|
|
9608
9861
|
{
|
|
9609
9862
|
className: "flex items-center gap-1",
|
|
9610
9863
|
title: `Cache hit ratio: ${pct}%`,
|
|
9611
9864
|
children: [
|
|
9612
|
-
/* @__PURE__ */
|
|
9613
|
-
/* @__PURE__ */
|
|
9865
|
+
/* @__PURE__ */ jsx35("span", { className: "font-medium text-foreground", children: fmtTok(totalTokens.cacheRead) }),
|
|
9866
|
+
/* @__PURE__ */ jsxs33("span", { children: [
|
|
9614
9867
|
"cache (",
|
|
9615
9868
|
pct,
|
|
9616
9869
|
"%)"
|
|
@@ -9619,15 +9872,15 @@ function ChatView() {
|
|
|
9619
9872
|
}
|
|
9620
9873
|
);
|
|
9621
9874
|
})(),
|
|
9622
|
-
/* @__PURE__ */
|
|
9875
|
+
/* @__PURE__ */ jsx35(CostChip, {})
|
|
9623
9876
|
] })
|
|
9624
9877
|
] }),
|
|
9625
|
-
startTime && /* @__PURE__ */
|
|
9878
|
+
startTime && /* @__PURE__ */ jsx35("span", { className: "text-muted-foreground/70 tabular-nums shrink-0", children: formatDuration3(startTime) })
|
|
9626
9879
|
] })
|
|
9627
9880
|
] }),
|
|
9628
|
-
/* @__PURE__ */
|
|
9629
|
-
/* @__PURE__ */
|
|
9630
|
-
!pinnedToBottom && /* @__PURE__ */
|
|
9881
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex-1 relative overflow-hidden", children: [
|
|
9882
|
+
/* @__PURE__ */ jsx35(SearchOverlay, {}),
|
|
9883
|
+
!pinnedToBottom && /* @__PURE__ */ jsxs33(
|
|
9631
9884
|
"button",
|
|
9632
9885
|
{
|
|
9633
9886
|
type: "button",
|
|
@@ -9639,12 +9892,12 @@ function ChatView() {
|
|
|
9639
9892
|
"hover:bg-primary/90 transition-colors animate-message"
|
|
9640
9893
|
),
|
|
9641
9894
|
children: [
|
|
9642
|
-
/* @__PURE__ */
|
|
9895
|
+
/* @__PURE__ */ jsx35(ArrowDown3, { className: "h-3.5 w-3.5" }),
|
|
9643
9896
|
unreadCount > 0 ? `${unreadCount} new message${unreadCount === 1 ? "" : "s"}` : "Jump to latest"
|
|
9644
9897
|
]
|
|
9645
9898
|
}
|
|
9646
9899
|
),
|
|
9647
|
-
scrolledDeep && /* @__PURE__ */
|
|
9900
|
+
scrolledDeep && /* @__PURE__ */ jsxs33(
|
|
9648
9901
|
"button",
|
|
9649
9902
|
{
|
|
9650
9903
|
type: "button",
|
|
@@ -9657,135 +9910,29 @@ function ChatView() {
|
|
|
9657
9910
|
"hover:text-foreground hover:bg-background transition-colors animate-message"
|
|
9658
9911
|
),
|
|
9659
9912
|
children: [
|
|
9660
|
-
/* @__PURE__ */
|
|
9661
|
-
/* @__PURE__ */
|
|
9913
|
+
/* @__PURE__ */ jsx35(ArrowUp3, { className: "h-3 w-3" }),
|
|
9914
|
+
/* @__PURE__ */ jsx35("span", { children: "Top" })
|
|
9662
9915
|
]
|
|
9663
9916
|
}
|
|
9664
9917
|
),
|
|
9665
|
-
/* @__PURE__ */
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
groups.push({ kind: "tools", tools: [m], key: m.id });
|
|
9684
|
-
}
|
|
9685
|
-
} else {
|
|
9686
|
-
const prev = messages[i - 1];
|
|
9687
|
-
groups.push({
|
|
9688
|
-
kind: "msg",
|
|
9689
|
-
message: m,
|
|
9690
|
-
isFirst: !prev || prev.role !== m.role
|
|
9691
|
-
});
|
|
9692
|
-
}
|
|
9693
|
-
}
|
|
9694
|
-
const turns = [];
|
|
9695
|
-
for (const g of groups) {
|
|
9696
|
-
if (g.kind === "msg" && g.message.role === "user") {
|
|
9697
|
-
turns.push({ kind: "user", message: g.message, key: g.message.id });
|
|
9698
|
-
continue;
|
|
9699
|
-
}
|
|
9700
|
-
const last = turns[turns.length - 1];
|
|
9701
|
-
if (last && last.kind === "agent") {
|
|
9702
|
-
last.items.push(g);
|
|
9703
|
-
} else {
|
|
9704
|
-
const key = g.kind === "msg" ? g.message.id : g.key;
|
|
9705
|
-
turns.push({ kind: "agent", items: [g], key });
|
|
9706
|
-
}
|
|
9707
|
-
}
|
|
9708
|
-
let prevDay = null;
|
|
9709
|
-
const dayKey = (ts) => {
|
|
9710
|
-
const d = new Date(ts);
|
|
9711
|
-
return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
|
|
9712
|
-
};
|
|
9713
|
-
const dayLabel = (ts) => {
|
|
9714
|
-
const d = new Date(ts);
|
|
9715
|
-
const today = /* @__PURE__ */ new Date();
|
|
9716
|
-
const yest = new Date(Date.now() - 864e5);
|
|
9717
|
-
if (dayKey(ts) === dayKey(today.getTime())) return "Today";
|
|
9718
|
-
if (dayKey(ts) === dayKey(yest.getTime())) return "Yesterday";
|
|
9719
|
-
return d.toLocaleDateString(void 0, {
|
|
9720
|
-
weekday: "short",
|
|
9721
|
-
month: "short",
|
|
9722
|
-
day: "numeric",
|
|
9723
|
-
year: d.getFullYear() === today.getFullYear() ? void 0 : "numeric"
|
|
9724
|
-
});
|
|
9725
|
-
};
|
|
9726
|
-
const turnTs = (t) => {
|
|
9727
|
-
if (t.kind === "user") return t.message.timestamp;
|
|
9728
|
-
const first = expectDefined12(t.items[0]);
|
|
9729
|
-
return first.kind === "msg" ? first.message.timestamp : first.tools[0]?.timestamp;
|
|
9730
|
-
};
|
|
9731
|
-
const out = [];
|
|
9732
|
-
for (let idx = 0; idx < turns.length; idx++) {
|
|
9733
|
-
const t = expectDefined12(turns[idx]);
|
|
9734
|
-
const ts = turnTs(t);
|
|
9735
|
-
const day = dayKey(ts);
|
|
9736
|
-
if (day !== prevDay) {
|
|
9737
|
-
out.push(
|
|
9738
|
-
/* @__PURE__ */ jsxs34(
|
|
9739
|
-
"div",
|
|
9740
|
-
{
|
|
9741
|
-
className: "flex items-center gap-3 py-1 text-[11px] text-muted-foreground/70 uppercase tracking-wider font-medium",
|
|
9742
|
-
children: [
|
|
9743
|
-
/* @__PURE__ */ jsx36("div", { className: "flex-1 h-px bg-border/50" }),
|
|
9744
|
-
/* @__PURE__ */ jsx36("span", { children: dayLabel(ts) }),
|
|
9745
|
-
/* @__PURE__ */ jsx36("div", { className: "flex-1 h-px bg-border/50" })
|
|
9746
|
-
]
|
|
9747
|
-
},
|
|
9748
|
-
`day-${day}-${idx}`
|
|
9749
|
-
)
|
|
9750
|
-
);
|
|
9751
|
-
prevDay = day;
|
|
9752
|
-
}
|
|
9753
|
-
if (t.kind === "user") {
|
|
9754
|
-
out.push(/* @__PURE__ */ jsx36(MessageBubble, { message: t.message, isFirst: true }, t.key));
|
|
9755
|
-
continue;
|
|
9756
|
-
}
|
|
9757
|
-
const isLastTurn = idx === turns.length - 1;
|
|
9758
|
-
out.push(
|
|
9759
|
-
/* @__PURE__ */ jsx36("div", { className: cn("chat-turn", compactMode ? "space-y-1" : "space-y-1.5"), children: t.items.map((g, gi) => {
|
|
9760
|
-
const continuation = gi > 0;
|
|
9761
|
-
if (g.kind === "msg") {
|
|
9762
|
-
return /* @__PURE__ */ jsx36(
|
|
9763
|
-
MessageBubble,
|
|
9764
|
-
{
|
|
9765
|
-
message: g.message,
|
|
9766
|
-
isFirst: !continuation && g.isFirst,
|
|
9767
|
-
isContinuation: continuation
|
|
9768
|
-
},
|
|
9769
|
-
g.message.id
|
|
9770
|
-
);
|
|
9771
|
-
}
|
|
9772
|
-
const isLatestRunning = isLastTurn && gi === t.items.length - 1 && isLoading && g.tools.some((tt) => tt.toolResult === void 0);
|
|
9773
|
-
return /* @__PURE__ */ jsx36(
|
|
9774
|
-
ToolGroup,
|
|
9775
|
-
{
|
|
9776
|
-
tools: g.tools,
|
|
9777
|
-
defaultOpen: isLatestRunning,
|
|
9778
|
-
isContinuation: continuation
|
|
9779
|
-
},
|
|
9780
|
-
g.key
|
|
9781
|
-
);
|
|
9782
|
-
}) }, t.key)
|
|
9783
|
-
);
|
|
9784
|
-
}
|
|
9785
|
-
return out;
|
|
9786
|
-
})(),
|
|
9787
|
-
/* @__PURE__ */ jsxs34("div", { id: "chat-activity", children: [
|
|
9788
|
-
/* @__PURE__ */ jsx36(ThinkingBubble, {}),
|
|
9918
|
+
rows.length === 0 && !isLoading ? /* @__PURE__ */ jsx35("div", { className: "mx-auto max-w-5xl w-full px-4 pt-4", children: /* @__PURE__ */ jsx35(WelcomeScreen, {}) }) : /* @__PURE__ */ jsxs33(VList, { ref: vlistRef, className: "h-full", onScroll: handleScroll, children: [
|
|
9919
|
+
rows.map((row, i) => /* @__PURE__ */ jsx35(
|
|
9920
|
+
ChatRowView,
|
|
9921
|
+
{
|
|
9922
|
+
row,
|
|
9923
|
+
isLoading,
|
|
9924
|
+
compactMode,
|
|
9925
|
+
isFirstRow: i === 0
|
|
9926
|
+
},
|
|
9927
|
+
row.key
|
|
9928
|
+
)),
|
|
9929
|
+
/* @__PURE__ */ jsxs33(
|
|
9930
|
+
"div",
|
|
9931
|
+
{
|
|
9932
|
+
id: "chat-activity",
|
|
9933
|
+
className: cn("mx-auto max-w-5xl w-full px-4", compactMode ? "pb-3" : "pb-8"),
|
|
9934
|
+
children: [
|
|
9935
|
+
/* @__PURE__ */ jsx35(ThinkingBubble, {}),
|
|
9789
9936
|
isLoading && (() => {
|
|
9790
9937
|
const last = messages[messages.length - 1];
|
|
9791
9938
|
const runningTools = messages.filter(
|
|
@@ -9827,94 +9974,95 @@ function ChatView() {
|
|
|
9827
9974
|
} else if (streamAnchor.current) {
|
|
9828
9975
|
streamAnchor.current = null;
|
|
9829
9976
|
}
|
|
9830
|
-
return /* @__PURE__ */
|
|
9831
|
-
/* @__PURE__ */
|
|
9832
|
-
/* @__PURE__ */
|
|
9833
|
-
/* @__PURE__ */
|
|
9834
|
-
/* @__PURE__ */
|
|
9835
|
-
/* @__PURE__ */
|
|
9836
|
-
/* @__PURE__ */
|
|
9977
|
+
return /* @__PURE__ */ jsxs33("div", { className: "flex gap-3 animate-message", children: [
|
|
9978
|
+
/* @__PURE__ */ jsx35("div", { className: "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center bg-accent text-accent-foreground ring-2 ring-offset-2 ring-offset-background ring-accent/20", children: /* @__PURE__ */ jsx35(Bot4, { className: "h-4 w-4" }) }),
|
|
9979
|
+
/* @__PURE__ */ jsx35("div", { className: "flex flex-col gap-1.5", children: /* @__PURE__ */ jsx35("div", { className: "rounded-2xl px-4 py-3 bg-card border text-foreground", children: /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
9980
|
+
/* @__PURE__ */ jsxs33("span", { className: "flex gap-1", children: [
|
|
9981
|
+
/* @__PURE__ */ jsx35("span", { className: "h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.3s]" }),
|
|
9982
|
+
/* @__PURE__ */ jsx35("span", { className: "h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce [animation-delay:-0.15s]" }),
|
|
9983
|
+
/* @__PURE__ */ jsx35("span", { className: "h-1.5 w-1.5 rounded-full bg-primary/70 animate-bounce" })
|
|
9837
9984
|
] }),
|
|
9838
|
-
/* @__PURE__ */
|
|
9839
|
-
/* @__PURE__ */
|
|
9840
|
-
iteration && /* @__PURE__ */
|
|
9985
|
+
/* @__PURE__ */ jsx35("span", { className: "text-foreground/90", children: label }),
|
|
9986
|
+
/* @__PURE__ */ jsx35("span", { className: "text-xs text-muted-foreground tabular-nums", children: elapsed }),
|
|
9987
|
+
iteration && /* @__PURE__ */ jsxs33("span", { className: "text-xs text-muted-foreground tabular-nums", children: [
|
|
9841
9988
|
"\xB7 iter ",
|
|
9842
9989
|
iteration.index,
|
|
9843
9990
|
iteration.max > 0 ? `/${iteration.max}` : ""
|
|
9844
9991
|
] }),
|
|
9845
|
-
speedLabel && /* @__PURE__ */
|
|
9992
|
+
speedLabel && /* @__PURE__ */ jsxs33("span", { className: "text-xs text-muted-foreground/80 tabular-nums", children: [
|
|
9846
9993
|
"\xB7 ",
|
|
9847
9994
|
speedLabel
|
|
9848
9995
|
] })
|
|
9849
9996
|
] }) }) })
|
|
9850
9997
|
] });
|
|
9851
9998
|
})()
|
|
9852
|
-
]
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9999
|
+
]
|
|
10000
|
+
},
|
|
10001
|
+
"__live"
|
|
10002
|
+
)
|
|
10003
|
+
] })
|
|
9856
10004
|
] }),
|
|
9857
|
-
/* @__PURE__ */
|
|
9858
|
-
/* @__PURE__ */
|
|
9859
|
-
/* @__PURE__ */
|
|
9860
|
-
/* @__PURE__ */
|
|
10005
|
+
/* @__PURE__ */ jsxs33("div", { className: "border-t bg-card/50 backdrop-blur supports-[backdrop-filter]:bg-card/50 shrink-0", children: [
|
|
10006
|
+
/* @__PURE__ */ jsxs33("div", { className: "max-w-5xl mx-auto px-4 pt-1.5 flex items-center gap-3 text-[10px] text-muted-foreground/50 select-none overflow-x-auto", children: [
|
|
10007
|
+
/* @__PURE__ */ jsxs33("span", { title: "Enter", className: "inline-flex items-center gap-1", children: [
|
|
10008
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Enter" }),
|
|
9861
10009
|
" send"
|
|
9862
10010
|
] }),
|
|
9863
|
-
/* @__PURE__ */
|
|
9864
|
-
/* @__PURE__ */
|
|
9865
|
-
/* @__PURE__ */
|
|
10011
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10012
|
+
/* @__PURE__ */ jsxs33("span", { title: "Shift+Enter", className: "inline-flex items-center gap-1", children: [
|
|
10013
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Shift" }),
|
|
9866
10014
|
"+",
|
|
9867
|
-
/* @__PURE__ */
|
|
10015
|
+
/* @__PURE__ */ jsx35("kbd", { children: "\u21B5" }),
|
|
9868
10016
|
" newline"
|
|
9869
10017
|
] }),
|
|
9870
|
-
/* @__PURE__ */
|
|
9871
|
-
/* @__PURE__ */
|
|
9872
|
-
/* @__PURE__ */
|
|
10018
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10019
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+\\\\", className: "inline-flex items-center gap-1", children: [
|
|
10020
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+\\" }),
|
|
9873
10021
|
" sidebar"
|
|
9874
10022
|
] }),
|
|
9875
|
-
/* @__PURE__ */
|
|
9876
|
-
/* @__PURE__ */
|
|
9877
|
-
/* @__PURE__ */
|
|
10023
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10024
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+F", className: "inline-flex items-center gap-1", children: [
|
|
10025
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+F" }),
|
|
9878
10026
|
" search"
|
|
9879
10027
|
] }),
|
|
9880
|
-
/* @__PURE__ */
|
|
9881
|
-
/* @__PURE__ */
|
|
9882
|
-
/* @__PURE__ */
|
|
10028
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10029
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+K", className: "inline-flex items-center gap-1", children: [
|
|
10030
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+K" }),
|
|
9883
10031
|
" palette"
|
|
9884
10032
|
] }),
|
|
9885
|
-
/* @__PURE__ */
|
|
9886
|
-
/* @__PURE__ */
|
|
9887
|
-
/* @__PURE__ */
|
|
10033
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10034
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+L / Ctrl+N", className: "inline-flex items-center gap-1", children: [
|
|
10035
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+L" }),
|
|
9888
10036
|
" clear"
|
|
9889
10037
|
] }),
|
|
9890
|
-
/* @__PURE__ */
|
|
9891
|
-
/* @__PURE__ */
|
|
9892
|
-
/* @__PURE__ */
|
|
9893
|
-
/* @__PURE__ */
|
|
10038
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10039
|
+
/* @__PURE__ */ jsxs33("span", { title: "j/k to navigate", className: "inline-flex items-center gap-1", children: [
|
|
10040
|
+
/* @__PURE__ */ jsx35("kbd", { children: "j" }),
|
|
10041
|
+
/* @__PURE__ */ jsx35("kbd", { children: "k" }),
|
|
9894
10042
|
" navigate"
|
|
9895
10043
|
] }),
|
|
9896
|
-
/* @__PURE__ */
|
|
9897
|
-
/* @__PURE__ */
|
|
9898
|
-
/* @__PURE__ */
|
|
10044
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10045
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+M", className: "inline-flex items-center gap-1", children: [
|
|
10046
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+M" }),
|
|
9899
10047
|
" model"
|
|
9900
10048
|
] }),
|
|
9901
|
-
/* @__PURE__ */
|
|
9902
|
-
/* @__PURE__ */
|
|
9903
|
-
/* @__PURE__ */
|
|
10049
|
+
/* @__PURE__ */ jsx35("span", { className: "opacity-50", children: "\xB7" }),
|
|
10050
|
+
/* @__PURE__ */ jsxs33("span", { title: "Ctrl+Shift+D", className: "inline-flex items-center gap-1", children: [
|
|
10051
|
+
/* @__PURE__ */ jsx35("kbd", { children: "Ctrl+\u21E7D" }),
|
|
9904
10052
|
" density"
|
|
9905
10053
|
] })
|
|
9906
10054
|
] }),
|
|
9907
|
-
/* @__PURE__ */
|
|
10055
|
+
/* @__PURE__ */ jsx35("div", { className: "p-4", children: /* @__PURE__ */ jsx35("div", { className: "max-w-5xl mx-auto", children: /* @__PURE__ */ jsx35(ChatInput, { onOpenBreakdown: () => setBreakdownOpen(true) }) }) })
|
|
9908
10056
|
] }),
|
|
9909
|
-
/* @__PURE__ */
|
|
9910
|
-
/* @__PURE__ */
|
|
9911
|
-
/* @__PURE__ */
|
|
10057
|
+
/* @__PURE__ */ jsx35(ProcessMonitor, { open: processOpen, onClose: () => setProcessOpen(false) }),
|
|
10058
|
+
/* @__PURE__ */ jsx35(CheckpointTimeline, { open: checkpointOpen, onClose: () => setCheckpointOpen(false) }),
|
|
10059
|
+
/* @__PURE__ */ jsx35(ContextBreakdownModal, { open: breakdownOpen, onClose: () => setBreakdownOpen(false) })
|
|
9912
10060
|
] });
|
|
9913
10061
|
}
|
|
9914
10062
|
|
|
9915
10063
|
// src/components/CodeEditor.tsx
|
|
9916
10064
|
import { X as X8, Circle as Circle3 } from "lucide-react";
|
|
9917
|
-
import { useCallback as useCallback11, useEffect as useEffect19, useMemo as
|
|
10065
|
+
import { useCallback as useCallback11, useEffect as useEffect19, useMemo as useMemo9, useRef as useRef15 } from "react";
|
|
9918
10066
|
import Editor, { loader } from "@monaco-editor/react";
|
|
9919
10067
|
import * as monaco2 from "monaco-editor";
|
|
9920
10068
|
|
|
@@ -10274,7 +10422,7 @@ function getMonacoTheme() {
|
|
|
10274
10422
|
}
|
|
10275
10423
|
|
|
10276
10424
|
// src/components/CodeEditor.tsx
|
|
10277
|
-
import { jsx as
|
|
10425
|
+
import { jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
10278
10426
|
loader.config({ monaco: monaco2 });
|
|
10279
10427
|
var LANG_MAP = {
|
|
10280
10428
|
ts: "typescript",
|
|
@@ -10314,10 +10462,10 @@ function EditorTabs() {
|
|
|
10314
10462
|
const setActiveFile = useFileStore((s) => s.setActiveFile);
|
|
10315
10463
|
const closeFile = useFileStore((s) => s.closeFile);
|
|
10316
10464
|
if (openFiles.length === 0) return null;
|
|
10317
|
-
return /* @__PURE__ */
|
|
10465
|
+
return /* @__PURE__ */ jsx36("div", { className: "flex items-center border-b bg-muted/40 overflow-x-auto shrink-0", children: openFiles.map((f) => {
|
|
10318
10466
|
const isActive = f.path === activeFilePath;
|
|
10319
10467
|
const baseName = f.path.split("/").pop() ?? f.path;
|
|
10320
|
-
return /* @__PURE__ */
|
|
10468
|
+
return /* @__PURE__ */ jsxs34(
|
|
10321
10469
|
"button",
|
|
10322
10470
|
{
|
|
10323
10471
|
type: "button",
|
|
@@ -10334,9 +10482,9 @@ function EditorTabs() {
|
|
|
10334
10482
|
),
|
|
10335
10483
|
title: f.path,
|
|
10336
10484
|
children: [
|
|
10337
|
-
f.dirty && /* @__PURE__ */
|
|
10338
|
-
/* @__PURE__ */
|
|
10339
|
-
/* @__PURE__ */
|
|
10485
|
+
f.dirty && /* @__PURE__ */ jsx36(Circle3, { className: "h-2 w-2 fill-current text-primary shrink-0" }),
|
|
10486
|
+
/* @__PURE__ */ jsx36("span", { className: "truncate", children: baseName }),
|
|
10487
|
+
/* @__PURE__ */ jsx36(
|
|
10340
10488
|
X8,
|
|
10341
10489
|
{
|
|
10342
10490
|
className: cn(
|
|
@@ -10361,7 +10509,7 @@ function CodeEditor() {
|
|
|
10361
10509
|
const updateContent = useFileStore((s) => s.updateContent);
|
|
10362
10510
|
const { theme: appTheme } = useTheme();
|
|
10363
10511
|
const editorRef = useRef15(null);
|
|
10364
|
-
const activeFile =
|
|
10512
|
+
const activeFile = useMemo9(
|
|
10365
10513
|
() => openFiles.find((f) => f.path === activeFilePath) ?? null,
|
|
10366
10514
|
[openFiles, activeFilePath]
|
|
10367
10515
|
);
|
|
@@ -10408,14 +10556,14 @@ function CodeEditor() {
|
|
|
10408
10556
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
10409
10557
|
}, [activeFilePath]);
|
|
10410
10558
|
if (openFiles.length === 0) {
|
|
10411
|
-
return /* @__PURE__ */
|
|
10412
|
-
/* @__PURE__ */
|
|
10413
|
-
/* @__PURE__ */
|
|
10559
|
+
return /* @__PURE__ */ jsx36("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs34("div", { className: "text-center space-y-2", children: [
|
|
10560
|
+
/* @__PURE__ */ jsx36("p", { className: "text-sm text-muted-foreground", children: "No files open" }),
|
|
10561
|
+
/* @__PURE__ */ jsx36("p", { className: "text-[11px] text-muted-foreground/60", children: "Select a file from the explorer to start editing" })
|
|
10414
10562
|
] }) });
|
|
10415
10563
|
}
|
|
10416
|
-
return /* @__PURE__ */
|
|
10417
|
-
/* @__PURE__ */
|
|
10418
|
-
/* @__PURE__ */
|
|
10564
|
+
return /* @__PURE__ */ jsxs34("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
|
|
10565
|
+
/* @__PURE__ */ jsx36(EditorTabs, {}),
|
|
10566
|
+
/* @__PURE__ */ jsx36("div", { className: "flex-1 relative", children: activeFile ? /* @__PURE__ */ jsx36(
|
|
10419
10567
|
Editor,
|
|
10420
10568
|
{
|
|
10421
10569
|
language,
|
|
@@ -10423,7 +10571,7 @@ function CodeEditor() {
|
|
|
10423
10571
|
onChange: handleChange,
|
|
10424
10572
|
theme: monacoTheme,
|
|
10425
10573
|
onMount: handleMount,
|
|
10426
|
-
loading: /* @__PURE__ */
|
|
10574
|
+
loading: /* @__PURE__ */ jsx36("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx36("span", { className: "text-[11px] text-muted-foreground animate-pulse", children: "Loading editor\u2026" }) }),
|
|
10427
10575
|
options: {
|
|
10428
10576
|
minimap: { enabled: false },
|
|
10429
10577
|
fontSize: 13,
|
|
@@ -10443,23 +10591,23 @@ function CodeEditor() {
|
|
|
10443
10591
|
}
|
|
10444
10592
|
},
|
|
10445
10593
|
activeFile.path
|
|
10446
|
-
) : /* @__PURE__ */
|
|
10594
|
+
) : /* @__PURE__ */ jsx36("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx36("p", { className: "text-[11px] text-muted-foreground", children: "Select a tab to view its content" }) }) })
|
|
10447
10595
|
] });
|
|
10448
10596
|
}
|
|
10449
10597
|
|
|
10450
10598
|
// src/components/ConfirmDialog.tsx
|
|
10451
|
-
import { AlertTriangle as AlertTriangle3, FileEdit, Globe as Globe2, ShieldAlert, Terminal as Terminal5, Wrench as
|
|
10599
|
+
import { AlertTriangle as AlertTriangle3, FileEdit, Globe as Globe2, ShieldAlert, Terminal as Terminal5, Wrench as Wrench5 } from "lucide-react";
|
|
10452
10600
|
import { useEffect as useEffect20, useRef as useRef16 } from "react";
|
|
10453
10601
|
|
|
10454
10602
|
// src/components/ui/dialog.tsx
|
|
10455
10603
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
10456
10604
|
import { X as X9 } from "lucide-react";
|
|
10457
|
-
import * as
|
|
10458
|
-
import { jsx as
|
|
10605
|
+
import * as React2 from "react";
|
|
10606
|
+
import { jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
10459
10607
|
var Dialog = DialogPrimitive.Root;
|
|
10460
10608
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
10461
10609
|
var DialogPortal = DialogPrimitive.Portal;
|
|
10462
|
-
var DialogOverlay =
|
|
10610
|
+
var DialogOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
|
|
10463
10611
|
DialogPrimitive.Overlay,
|
|
10464
10612
|
{
|
|
10465
10613
|
ref,
|
|
@@ -10471,9 +10619,9 @@ var DialogOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
10471
10619
|
}
|
|
10472
10620
|
));
|
|
10473
10621
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
10474
|
-
var DialogContent =
|
|
10475
|
-
/* @__PURE__ */
|
|
10476
|
-
/* @__PURE__ */
|
|
10622
|
+
var DialogContent = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs35(DialogPortal, { children: [
|
|
10623
|
+
/* @__PURE__ */ jsx37(DialogOverlay, {}),
|
|
10624
|
+
/* @__PURE__ */ jsxs35(
|
|
10477
10625
|
DialogPrimitive.Content,
|
|
10478
10626
|
{
|
|
10479
10627
|
ref,
|
|
@@ -10484,18 +10632,18 @@ var DialogContent = React3.forwardRef(({ className, children, ...props }, ref) =
|
|
|
10484
10632
|
...props,
|
|
10485
10633
|
children: [
|
|
10486
10634
|
children,
|
|
10487
|
-
/* @__PURE__ */
|
|
10488
|
-
/* @__PURE__ */
|
|
10489
|
-
/* @__PURE__ */
|
|
10635
|
+
/* @__PURE__ */ jsxs35(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
|
|
10636
|
+
/* @__PURE__ */ jsx37(X9, { className: "h-4 w-4" }),
|
|
10637
|
+
/* @__PURE__ */ jsx37("span", { className: "sr-only", children: "Close" })
|
|
10490
10638
|
] })
|
|
10491
10639
|
]
|
|
10492
10640
|
}
|
|
10493
10641
|
)
|
|
10494
10642
|
] }));
|
|
10495
10643
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
10496
|
-
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */
|
|
10644
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx37("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
10497
10645
|
DialogHeader.displayName = "DialogHeader";
|
|
10498
|
-
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */
|
|
10646
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx37(
|
|
10499
10647
|
"div",
|
|
10500
10648
|
{
|
|
10501
10649
|
className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
|
|
@@ -10503,7 +10651,7 @@ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx38(
|
|
|
10503
10651
|
}
|
|
10504
10652
|
);
|
|
10505
10653
|
DialogFooter.displayName = "DialogFooter";
|
|
10506
|
-
var DialogTitle =
|
|
10654
|
+
var DialogTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
|
|
10507
10655
|
DialogPrimitive.Title,
|
|
10508
10656
|
{
|
|
10509
10657
|
ref,
|
|
@@ -10512,7 +10660,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
10512
10660
|
}
|
|
10513
10661
|
));
|
|
10514
10662
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
10515
|
-
var DialogDescription =
|
|
10663
|
+
var DialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
|
|
10516
10664
|
DialogPrimitive.Description,
|
|
10517
10665
|
{
|
|
10518
10666
|
ref,
|
|
@@ -10523,12 +10671,12 @@ var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
10523
10671
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
10524
10672
|
|
|
10525
10673
|
// src/components/ConfirmDialog.tsx
|
|
10526
|
-
import { jsx as
|
|
10674
|
+
import { jsx as jsx38, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
10527
10675
|
function pickToolIcon(toolName) {
|
|
10528
10676
|
if (/edit|write|create|patch/i.test(toolName)) return FileEdit;
|
|
10529
10677
|
if (/bash|shell|exec|run|command/i.test(toolName)) return Terminal5;
|
|
10530
10678
|
if (/fetch|http|web|curl|request/i.test(toolName)) return Globe2;
|
|
10531
|
-
return
|
|
10679
|
+
return Wrench5;
|
|
10532
10680
|
}
|
|
10533
10681
|
function SmartInputPreview({
|
|
10534
10682
|
toolName,
|
|
@@ -10536,7 +10684,7 @@ function SmartInputPreview({
|
|
|
10536
10684
|
}) {
|
|
10537
10685
|
const diffArgs = diffFromToolInput(toolName, input);
|
|
10538
10686
|
if (diffArgs) {
|
|
10539
|
-
return /* @__PURE__ */
|
|
10687
|
+
return /* @__PURE__ */ jsx38("div", { className: "rounded-lg overflow-hidden border", children: /* @__PURE__ */ jsx38(
|
|
10540
10688
|
DiffView,
|
|
10541
10689
|
{
|
|
10542
10690
|
oldText: diffArgs.oldText,
|
|
@@ -10549,12 +10697,12 @@ function SmartInputPreview({
|
|
|
10549
10697
|
const obj = input;
|
|
10550
10698
|
const cmd = obj.command ?? obj.cmd ?? obj.script;
|
|
10551
10699
|
if (typeof cmd === "string" && cmd.trim().length > 0) {
|
|
10552
|
-
return /* @__PURE__ */
|
|
10553
|
-
/* @__PURE__ */
|
|
10554
|
-
/* @__PURE__ */
|
|
10555
|
-
/* @__PURE__ */
|
|
10700
|
+
return /* @__PURE__ */ jsxs36("div", { className: "rounded-lg border bg-background/40 overflow-hidden", children: [
|
|
10701
|
+
/* @__PURE__ */ jsxs36("div", { className: "px-3 py-1.5 text-[10px] uppercase tracking-wider text-muted-foreground border-b bg-muted/40 flex items-center gap-1.5", children: [
|
|
10702
|
+
/* @__PURE__ */ jsx38(Terminal5, { className: "h-3 w-3" }),
|
|
10703
|
+
/* @__PURE__ */ jsx38("span", { children: "Command" })
|
|
10556
10704
|
] }),
|
|
10557
|
-
/* @__PURE__ */
|
|
10705
|
+
/* @__PURE__ */ jsxs36("pre", { className: "px-3 py-2 text-xs font-mono whitespace-pre-wrap break-all max-h-40 overflow-auto", children: [
|
|
10558
10706
|
"$",
|
|
10559
10707
|
cmd
|
|
10560
10708
|
] })
|
|
@@ -10563,16 +10711,16 @@ function SmartInputPreview({
|
|
|
10563
10711
|
const url = obj.url;
|
|
10564
10712
|
if (typeof url === "string") {
|
|
10565
10713
|
const method = obj.method ?? "GET";
|
|
10566
|
-
return /* @__PURE__ */
|
|
10567
|
-
/* @__PURE__ */
|
|
10714
|
+
return /* @__PURE__ */ jsxs36("div", { className: "rounded-lg border bg-background/40 px-3 py-2 text-xs font-mono", children: [
|
|
10715
|
+
/* @__PURE__ */ jsx38("span", { className: "text-muted-foreground", children: method.toUpperCase() }),
|
|
10568
10716
|
" ",
|
|
10569
|
-
/* @__PURE__ */
|
|
10717
|
+
/* @__PURE__ */ jsx38("span", { className: "break-all", children: url })
|
|
10570
10718
|
] });
|
|
10571
10719
|
}
|
|
10572
10720
|
}
|
|
10573
|
-
return /* @__PURE__ */
|
|
10574
|
-
/* @__PURE__ */
|
|
10575
|
-
/* @__PURE__ */
|
|
10721
|
+
return /* @__PURE__ */ jsxs36("div", { className: "p-3 rounded-lg bg-muted/50 border text-xs font-mono", children: [
|
|
10722
|
+
/* @__PURE__ */ jsx38("div", { className: "text-muted-foreground mb-2", children: "Input:" }),
|
|
10723
|
+
/* @__PURE__ */ jsx38("pre", { className: "whitespace-pre-wrap break-all max-h-60 overflow-auto", children: JSON.stringify(input, null, 2) })
|
|
10576
10724
|
] });
|
|
10577
10725
|
}
|
|
10578
10726
|
function ConfirmDialog() {
|
|
@@ -10610,50 +10758,50 @@ function ConfirmDialog() {
|
|
|
10610
10758
|
return () => window.removeEventListener("keydown", onKey);
|
|
10611
10759
|
}, [showConfirmDialog, confirmInfo?.id]);
|
|
10612
10760
|
if (!confirmInfo) {
|
|
10613
|
-
return /* @__PURE__ */
|
|
10761
|
+
return /* @__PURE__ */ jsx38(Dialog, { open: showConfirmDialog, onOpenChange: () => hideConfirm(), children: /* @__PURE__ */ jsx38(DialogContent, {}) });
|
|
10614
10762
|
}
|
|
10615
10763
|
const Icon2 = pickToolIcon(confirmInfo.toolName);
|
|
10616
10764
|
const isEdit = /edit|write/i.test(confirmInfo.toolName);
|
|
10617
|
-
return /* @__PURE__ */
|
|
10618
|
-
/* @__PURE__ */
|
|
10619
|
-
/* @__PURE__ */
|
|
10620
|
-
/* @__PURE__ */
|
|
10765
|
+
return /* @__PURE__ */ jsx38(Dialog, { open: showConfirmDialog, onOpenChange: () => hideConfirm(), children: /* @__PURE__ */ jsxs36(DialogContent, { className: "sm:max-w-2xl border-yellow-500/50", ref: dialogRef, tabIndex: -1, children: [
|
|
10766
|
+
/* @__PURE__ */ jsxs36(DialogHeader, { children: [
|
|
10767
|
+
/* @__PURE__ */ jsxs36(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
10768
|
+
/* @__PURE__ */ jsx38(ShieldAlert, { className: "h-5 w-5 text-yellow-500 animate-pulse" }),
|
|
10621
10769
|
"Approval required: ",
|
|
10622
10770
|
confirmInfo.toolName
|
|
10623
10771
|
] }),
|
|
10624
|
-
/* @__PURE__ */
|
|
10772
|
+
/* @__PURE__ */ jsxs36(DialogDescription, { children: [
|
|
10625
10773
|
"The agent wants to ",
|
|
10626
10774
|
isEdit ? "modify a file" : "run this tool",
|
|
10627
10775
|
". Review the request below and decide whether to proceed."
|
|
10628
10776
|
] })
|
|
10629
10777
|
] }),
|
|
10630
|
-
/* @__PURE__ */
|
|
10631
|
-
/* @__PURE__ */
|
|
10632
|
-
/* @__PURE__ */
|
|
10633
|
-
/* @__PURE__ */
|
|
10634
|
-
/* @__PURE__ */
|
|
10635
|
-
/* @__PURE__ */
|
|
10778
|
+
/* @__PURE__ */ jsxs36("div", { className: "py-2 space-y-3", children: [
|
|
10779
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-3 p-3 rounded-lg bg-muted", children: [
|
|
10780
|
+
/* @__PURE__ */ jsx38(Icon2, { className: "h-5 w-5 text-muted-foreground" }),
|
|
10781
|
+
/* @__PURE__ */ jsxs36("div", { className: "min-w-0", children: [
|
|
10782
|
+
/* @__PURE__ */ jsx38("div", { className: "font-medium font-mono truncate", children: confirmInfo.toolName }),
|
|
10783
|
+
/* @__PURE__ */ jsxs36("div", { className: "text-xs text-muted-foreground", children: [
|
|
10636
10784
|
isEdit ? "File modification" : "Tool execution",
|
|
10637
10785
|
" \u2014 preview below"
|
|
10638
10786
|
] })
|
|
10639
10787
|
] })
|
|
10640
10788
|
] }),
|
|
10641
|
-
confirmInfo.input !== void 0 && /* @__PURE__ */
|
|
10642
|
-
confirmInfo.suggestedPattern && /* @__PURE__ */
|
|
10643
|
-
/* @__PURE__ */
|
|
10644
|
-
/* @__PURE__ */
|
|
10645
|
-
/* @__PURE__ */
|
|
10646
|
-
/* @__PURE__ */
|
|
10647
|
-
/* @__PURE__ */
|
|
10789
|
+
confirmInfo.input !== void 0 && /* @__PURE__ */ jsx38(SmartInputPreview, { toolName: confirmInfo.toolName, input: confirmInfo.input }),
|
|
10790
|
+
confirmInfo.suggestedPattern && /* @__PURE__ */ jsxs36("div", { className: "flex items-start gap-2 p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/20", children: [
|
|
10791
|
+
/* @__PURE__ */ jsx38(AlertTriangle3, { className: "h-4 w-4 text-yellow-600 mt-0.5 shrink-0" }),
|
|
10792
|
+
/* @__PURE__ */ jsxs36("div", { className: "text-sm min-w-0", children: [
|
|
10793
|
+
/* @__PURE__ */ jsx38("div", { className: "font-medium text-yellow-800 dark:text-yellow-200", children: "Trust pattern suggestion" }),
|
|
10794
|
+
/* @__PURE__ */ jsx38("div", { className: "font-mono text-xs mt-1 break-all", children: confirmInfo.suggestedPattern }),
|
|
10795
|
+
/* @__PURE__ */ jsxs36("div", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
10648
10796
|
"Picking ",
|
|
10649
|
-
/* @__PURE__ */
|
|
10797
|
+
/* @__PURE__ */ jsx38("span", { className: "font-medium", children: "Always" }),
|
|
10650
10798
|
" will whitelist matching calls for this project."
|
|
10651
10799
|
] })
|
|
10652
10800
|
] })
|
|
10653
10801
|
] })
|
|
10654
10802
|
] }),
|
|
10655
|
-
/* @__PURE__ */
|
|
10656
|
-
/* @__PURE__ */
|
|
10803
|
+
/* @__PURE__ */ jsxs36(DialogFooter, { className: "gap-2 sm:gap-2 flex-wrap", children: [
|
|
10804
|
+
/* @__PURE__ */ jsxs36(
|
|
10657
10805
|
Button,
|
|
10658
10806
|
{
|
|
10659
10807
|
variant: "outline",
|
|
@@ -10662,11 +10810,11 @@ function ConfirmDialog() {
|
|
|
10662
10810
|
title: "Reject this and all future calls matching the pattern (d)",
|
|
10663
10811
|
children: [
|
|
10664
10812
|
"Deny always ",
|
|
10665
|
-
/* @__PURE__ */
|
|
10813
|
+
/* @__PURE__ */ jsx38("kbd", { className: "ml-1 text-[10px] border rounded px-1 bg-background", children: "d" })
|
|
10666
10814
|
]
|
|
10667
10815
|
}
|
|
10668
10816
|
),
|
|
10669
|
-
/* @__PURE__ */
|
|
10817
|
+
/* @__PURE__ */ jsxs36(
|
|
10670
10818
|
Button,
|
|
10671
10819
|
{
|
|
10672
10820
|
variant: "outline",
|
|
@@ -10675,11 +10823,11 @@ function ConfirmDialog() {
|
|
|
10675
10823
|
title: "Reject this single call (Esc / n)",
|
|
10676
10824
|
children: [
|
|
10677
10825
|
"No ",
|
|
10678
|
-
/* @__PURE__ */
|
|
10826
|
+
/* @__PURE__ */ jsx38("kbd", { className: "ml-1 text-[10px] border rounded px-1 bg-background", children: "n" })
|
|
10679
10827
|
]
|
|
10680
10828
|
}
|
|
10681
10829
|
),
|
|
10682
|
-
/* @__PURE__ */
|
|
10830
|
+
/* @__PURE__ */ jsxs36(
|
|
10683
10831
|
Button,
|
|
10684
10832
|
{
|
|
10685
10833
|
variant: "outline",
|
|
@@ -10688,11 +10836,11 @@ function ConfirmDialog() {
|
|
|
10688
10836
|
title: "Approve and remember the pattern for the project (a)",
|
|
10689
10837
|
children: [
|
|
10690
10838
|
"Always ",
|
|
10691
|
-
/* @__PURE__ */
|
|
10839
|
+
/* @__PURE__ */ jsx38("kbd", { className: "ml-1 text-[10px] border rounded px-1 bg-background", children: "a" })
|
|
10692
10840
|
]
|
|
10693
10841
|
}
|
|
10694
10842
|
),
|
|
10695
|
-
/* @__PURE__ */
|
|
10843
|
+
/* @__PURE__ */ jsxs36(
|
|
10696
10844
|
Button,
|
|
10697
10845
|
{
|
|
10698
10846
|
size: "sm",
|
|
@@ -10700,7 +10848,7 @@ function ConfirmDialog() {
|
|
|
10700
10848
|
title: "Approve this single call (y)",
|
|
10701
10849
|
children: [
|
|
10702
10850
|
"Yes ",
|
|
10703
|
-
/* @__PURE__ */
|
|
10851
|
+
/* @__PURE__ */ jsx38("kbd", { className: "ml-1 text-[10px] border rounded px-1 bg-background/80", children: "y" })
|
|
10704
10852
|
]
|
|
10705
10853
|
}
|
|
10706
10854
|
)
|
|
@@ -10711,7 +10859,7 @@ function ConfirmDialog() {
|
|
|
10711
10859
|
// src/components/ConfirmModal.tsx
|
|
10712
10860
|
import { useEffect as useEffect21 } from "react";
|
|
10713
10861
|
import { create as create15 } from "zustand";
|
|
10714
|
-
import { jsx as
|
|
10862
|
+
import { jsx as jsx39, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
10715
10863
|
var useConfirmModalStore = create15()((set, get) => ({
|
|
10716
10864
|
request: null,
|
|
10717
10865
|
open: (request) => {
|
|
@@ -10742,21 +10890,21 @@ function ConfirmModalHost() {
|
|
|
10742
10890
|
window.addEventListener("keydown", onKey);
|
|
10743
10891
|
return () => window.removeEventListener("keydown", onKey);
|
|
10744
10892
|
}, [request]);
|
|
10745
|
-
return /* @__PURE__ */
|
|
10893
|
+
return /* @__PURE__ */ jsx39(
|
|
10746
10894
|
Dialog,
|
|
10747
10895
|
{
|
|
10748
10896
|
open: request !== null,
|
|
10749
10897
|
onOpenChange: (open) => {
|
|
10750
10898
|
if (!open) settle(false);
|
|
10751
10899
|
},
|
|
10752
|
-
children: /* @__PURE__ */
|
|
10753
|
-
/* @__PURE__ */
|
|
10754
|
-
/* @__PURE__ */
|
|
10755
|
-
request?.message && /* @__PURE__ */
|
|
10900
|
+
children: /* @__PURE__ */ jsxs37(DialogContent, { className: "max-w-md", children: [
|
|
10901
|
+
/* @__PURE__ */ jsxs37(DialogHeader, { children: [
|
|
10902
|
+
/* @__PURE__ */ jsx39(DialogTitle, { children: request?.title }),
|
|
10903
|
+
request?.message && /* @__PURE__ */ jsx39(DialogDescription, { children: request.message })
|
|
10756
10904
|
] }),
|
|
10757
|
-
/* @__PURE__ */
|
|
10758
|
-
/* @__PURE__ */
|
|
10759
|
-
/* @__PURE__ */
|
|
10905
|
+
/* @__PURE__ */ jsxs37(DialogFooter, { className: "gap-2", children: [
|
|
10906
|
+
/* @__PURE__ */ jsx39(Button, { variant: "outline", size: "sm", onClick: () => settle(false), children: request?.cancelLabel ?? "Cancel" }),
|
|
10907
|
+
/* @__PURE__ */ jsx39(
|
|
10760
10908
|
Button,
|
|
10761
10909
|
{
|
|
10762
10910
|
variant: request?.danger ? "destructive" : "default",
|
|
@@ -10775,7 +10923,7 @@ function ConfirmModalHost() {
|
|
|
10775
10923
|
// src/components/ConnectionBanner.tsx
|
|
10776
10924
|
import { Loader2 as Loader23, RotateCcw as RotateCcw4, WifiOff, X as X10 } from "lucide-react";
|
|
10777
10925
|
import { useEffect as useEffect22, useState as useState25 } from "react";
|
|
10778
|
-
import { jsx as
|
|
10926
|
+
import { jsx as jsx40, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
10779
10927
|
function ConnectionBanner() {
|
|
10780
10928
|
const wsStatus = useConfigStore((s) => s.wsStatus);
|
|
10781
10929
|
const wsUrl = useConfigStore((s) => s.wsUrl);
|
|
@@ -10795,7 +10943,7 @@ function ConnectionBanner() {
|
|
|
10795
10943
|
const isReconnecting = wsStatus.state === "reconnecting";
|
|
10796
10944
|
const errorText = wsStatus.state === "closed" ? wsStatus.error : wsStatus.state === "reconnecting" ? wsStatus.lastError : void 0;
|
|
10797
10945
|
const remaining = isReconnecting ? Math.max(0, Math.ceil((wsStatus.nextRetryAt - now) / 1e3)) : 0;
|
|
10798
|
-
return /* @__PURE__ */
|
|
10946
|
+
return /* @__PURE__ */ jsxs38(
|
|
10799
10947
|
"div",
|
|
10800
10948
|
{
|
|
10801
10949
|
className: cn(
|
|
@@ -10803,12 +10951,12 @@ function ConnectionBanner() {
|
|
|
10803
10951
|
isReconnecting ? "bg-orange-500/10 text-orange-700 dark:text-orange-300 border-orange-500/30" : "bg-red-500/10 text-red-700 dark:text-red-300 border-red-500/30"
|
|
10804
10952
|
),
|
|
10805
10953
|
children: [
|
|
10806
|
-
isReconnecting ? /* @__PURE__ */
|
|
10807
|
-
/* @__PURE__ */
|
|
10808
|
-
/* @__PURE__ */
|
|
10809
|
-
errorText && /* @__PURE__ */
|
|
10954
|
+
isReconnecting ? /* @__PURE__ */ jsx40(Loader23, { className: "h-4 w-4 animate-spin shrink-0" }) : /* @__PURE__ */ jsx40(WifiOff, { className: "h-4 w-4 shrink-0" }),
|
|
10955
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex-1 min-w-0", children: [
|
|
10956
|
+
/* @__PURE__ */ jsx40("div", { className: "font-medium", children: isReconnecting ? `Reconnecting to backend (attempt ${wsStatus.attempt}) \u2014 retrying in ${remaining}s` : "Disconnected from backend" }),
|
|
10957
|
+
errorText && /* @__PURE__ */ jsx40("div", { className: "text-xs opacity-80 truncate", children: errorText })
|
|
10810
10958
|
] }),
|
|
10811
|
-
/* @__PURE__ */
|
|
10959
|
+
/* @__PURE__ */ jsxs38(
|
|
10812
10960
|
"button",
|
|
10813
10961
|
{
|
|
10814
10962
|
type: "button",
|
|
@@ -10820,19 +10968,19 @@ function ConnectionBanner() {
|
|
|
10820
10968
|
),
|
|
10821
10969
|
title: "Retry connection now",
|
|
10822
10970
|
children: [
|
|
10823
|
-
/* @__PURE__ */
|
|
10971
|
+
/* @__PURE__ */ jsx40(RotateCcw4, { className: "h-3 w-3" }),
|
|
10824
10972
|
"Retry now"
|
|
10825
10973
|
]
|
|
10826
10974
|
}
|
|
10827
10975
|
),
|
|
10828
|
-
/* @__PURE__ */
|
|
10976
|
+
/* @__PURE__ */ jsx40(
|
|
10829
10977
|
"button",
|
|
10830
10978
|
{
|
|
10831
10979
|
type: "button",
|
|
10832
10980
|
onClick: () => setDismissed(true),
|
|
10833
10981
|
className: "text-current/60 hover:text-current shrink-0",
|
|
10834
10982
|
title: "Dismiss (chip in topbar still shows status)",
|
|
10835
|
-
children: /* @__PURE__ */
|
|
10983
|
+
children: /* @__PURE__ */ jsx40(X10, { className: "h-4 w-4" })
|
|
10836
10984
|
}
|
|
10837
10985
|
)
|
|
10838
10986
|
]
|
|
@@ -10843,7 +10991,7 @@ function ConnectionBanner() {
|
|
|
10843
10991
|
// src/components/ErrorBoundary.tsx
|
|
10844
10992
|
import { AlertTriangle as AlertTriangle4, RefreshCw as RefreshCw2 } from "lucide-react";
|
|
10845
10993
|
import { Component } from "react";
|
|
10846
|
-
import { jsx as
|
|
10994
|
+
import { jsx as jsx41, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
10847
10995
|
var ErrorBoundary = class extends Component {
|
|
10848
10996
|
state = { error: null };
|
|
10849
10997
|
static getDerivedStateFromError(error) {
|
|
@@ -10858,17 +11006,17 @@ var ErrorBoundary = class extends Component {
|
|
|
10858
11006
|
};
|
|
10859
11007
|
render() {
|
|
10860
11008
|
if (this.state.error) {
|
|
10861
|
-
return /* @__PURE__ */
|
|
10862
|
-
/* @__PURE__ */
|
|
10863
|
-
/* @__PURE__ */
|
|
10864
|
-
/* @__PURE__ */
|
|
10865
|
-
/* @__PURE__ */
|
|
10866
|
-
/* @__PURE__ */
|
|
10867
|
-
/* @__PURE__ */
|
|
10868
|
-
/* @__PURE__ */
|
|
11009
|
+
return /* @__PURE__ */ jsx41("div", { className: "flex items-center justify-center h-screen bg-background", children: /* @__PURE__ */ jsxs39("div", { className: "flex flex-col items-center gap-4 p-8 max-w-md text-center", children: [
|
|
11010
|
+
/* @__PURE__ */ jsx41(AlertTriangle4, { className: "h-12 w-12 text-destructive" }),
|
|
11011
|
+
/* @__PURE__ */ jsx41("h1", { className: "text-lg font-semibold", children: "Something went wrong" }),
|
|
11012
|
+
/* @__PURE__ */ jsx41("p", { className: "text-sm text-muted-foreground", children: "A rendering error occurred. Your session is still active on the server \u2014 reloading will pick up where you left off." }),
|
|
11013
|
+
/* @__PURE__ */ jsx41("pre", { className: "text-xs font-mono text-muted-foreground bg-muted/50 rounded p-3 max-h-32 overflow-auto w-full text-left", children: this.state.error.message }),
|
|
11014
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex gap-2", children: [
|
|
11015
|
+
/* @__PURE__ */ jsxs39(Button, { size: "sm", variant: "outline", onClick: () => window.location.reload(), children: [
|
|
11016
|
+
/* @__PURE__ */ jsx41(RefreshCw2, { className: "h-4 w-4 mr-1" }),
|
|
10869
11017
|
"Reload page"
|
|
10870
11018
|
] }),
|
|
10871
|
-
/* @__PURE__ */
|
|
11019
|
+
/* @__PURE__ */ jsx41(Button, { size: "sm", onClick: this.handleReset, children: "Try again" })
|
|
10872
11020
|
] })
|
|
10873
11021
|
] }) });
|
|
10874
11022
|
}
|
|
@@ -10878,7 +11026,7 @@ var ErrorBoundary = class extends Component {
|
|
|
10878
11026
|
|
|
10879
11027
|
// src/components/QuickModelSwitcher.tsx
|
|
10880
11028
|
import { ArrowRight as ArrowRight4, Cpu as Cpu6, Search as Search4 } from "lucide-react";
|
|
10881
|
-
import { useEffect as useEffect23, useMemo as
|
|
11029
|
+
import { useEffect as useEffect23, useMemo as useMemo10, useRef as useRef17, useState as useState26 } from "react";
|
|
10882
11030
|
|
|
10883
11031
|
// src/components/QuickModelSwitcher.filter.ts
|
|
10884
11032
|
function buildModelCandidates(saved, modelsByProvider, query, currentProvider, currentModel) {
|
|
@@ -10906,7 +11054,7 @@ function buildModelCandidates(saved, modelsByProvider, query, currentProvider, c
|
|
|
10906
11054
|
}
|
|
10907
11055
|
|
|
10908
11056
|
// src/components/QuickModelSwitcher.tsx
|
|
10909
|
-
import { jsx as
|
|
11057
|
+
import { jsx as jsx42, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
10910
11058
|
function QuickModelSwitcher() {
|
|
10911
11059
|
const open = useUIStore((s) => s.modelSwitcherOpen);
|
|
10912
11060
|
const setOpen = useUIStore((s) => s.setModelSwitcherOpen);
|
|
@@ -10967,7 +11115,7 @@ function QuickModelSwitcher() {
|
|
|
10967
11115
|
}
|
|
10968
11116
|
}
|
|
10969
11117
|
}, [open, saved, modelsByProvider, listProviderModels]);
|
|
10970
|
-
const candidates =
|
|
11118
|
+
const candidates = useMemo10(
|
|
10971
11119
|
() => buildModelCandidates(
|
|
10972
11120
|
saved,
|
|
10973
11121
|
modelsByProvider,
|
|
@@ -10987,7 +11135,7 @@ function QuickModelSwitcher() {
|
|
|
10987
11135
|
setOpen(false);
|
|
10988
11136
|
};
|
|
10989
11137
|
if (!open) return null;
|
|
10990
|
-
return /* @__PURE__ */
|
|
11138
|
+
return /* @__PURE__ */ jsx42(
|
|
10991
11139
|
"div",
|
|
10992
11140
|
{
|
|
10993
11141
|
className: "fixed inset-0 z-50 flex items-start justify-center bg-background/60 backdrop-blur-sm pt-[15vh]",
|
|
@@ -10997,10 +11145,10 @@ function QuickModelSwitcher() {
|
|
|
10997
11145
|
onKeyDown: (e) => {
|
|
10998
11146
|
if (e.key === "Escape") setOpen(false);
|
|
10999
11147
|
},
|
|
11000
|
-
children: /* @__PURE__ */
|
|
11001
|
-
/* @__PURE__ */
|
|
11002
|
-
/* @__PURE__ */
|
|
11003
|
-
/* @__PURE__ */
|
|
11148
|
+
children: /* @__PURE__ */ jsxs40("div", { className: "w-full max-w-xl rounded-xl border bg-popover shadow-2xl overflow-hidden", children: [
|
|
11149
|
+
/* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-2 border-b px-3 py-2", children: [
|
|
11150
|
+
/* @__PURE__ */ jsx42(Search4, { className: "h-4 w-4 text-muted-foreground" }),
|
|
11151
|
+
/* @__PURE__ */ jsx42(
|
|
11004
11152
|
"input",
|
|
11005
11153
|
{
|
|
11006
11154
|
ref: inputRef,
|
|
@@ -11028,9 +11176,9 @@ function QuickModelSwitcher() {
|
|
|
11028
11176
|
className: "flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground"
|
|
11029
11177
|
}
|
|
11030
11178
|
),
|
|
11031
|
-
/* @__PURE__ */
|
|
11179
|
+
/* @__PURE__ */ jsx42("span", { className: "text-[10px] text-muted-foreground font-mono", children: "\u2191\u2193 \xB7 Enter \xB7 Esc" })
|
|
11032
11180
|
] }),
|
|
11033
|
-
/* @__PURE__ */
|
|
11181
|
+
/* @__PURE__ */ jsx42("div", { className: "max-h-[50vh] overflow-y-auto py-1", children: candidates.length === 0 ? /* @__PURE__ */ jsx42("div", { className: "px-4 py-8 text-center text-sm text-muted-foreground", children: saved.length === 0 ? "No saved providers \u2014 register a key in Settings first." : "Loading models\u2026" }) : candidates.map((c, idx) => /* @__PURE__ */ jsxs40(
|
|
11034
11182
|
"button",
|
|
11035
11183
|
{
|
|
11036
11184
|
type: "button",
|
|
@@ -11042,7 +11190,7 @@ function QuickModelSwitcher() {
|
|
|
11042
11190
|
c.isCurrent && "font-medium"
|
|
11043
11191
|
),
|
|
11044
11192
|
children: [
|
|
11045
|
-
/* @__PURE__ */
|
|
11193
|
+
/* @__PURE__ */ jsx42(
|
|
11046
11194
|
Cpu6,
|
|
11047
11195
|
{
|
|
11048
11196
|
className: cn(
|
|
@@ -11051,19 +11199,19 @@ function QuickModelSwitcher() {
|
|
|
11051
11199
|
)
|
|
11052
11200
|
}
|
|
11053
11201
|
),
|
|
11054
|
-
/* @__PURE__ */
|
|
11055
|
-
/* @__PURE__ */
|
|
11056
|
-
/* @__PURE__ */
|
|
11057
|
-
/* @__PURE__ */
|
|
11058
|
-
/* @__PURE__ */
|
|
11202
|
+
/* @__PURE__ */ jsxs40("div", { className: "min-w-0 flex-1", children: [
|
|
11203
|
+
/* @__PURE__ */ jsxs40("div", { className: "truncate", children: [
|
|
11204
|
+
/* @__PURE__ */ jsx42("span", { className: "text-muted-foreground", children: c.provider }),
|
|
11205
|
+
/* @__PURE__ */ jsx42("span", { className: "mx-1 text-muted-foreground/40", children: "\xB7" }),
|
|
11206
|
+
/* @__PURE__ */ jsx42("span", { children: c.modelName })
|
|
11059
11207
|
] }),
|
|
11060
|
-
c.contextWindow && /* @__PURE__ */
|
|
11208
|
+
c.contextWindow && /* @__PURE__ */ jsxs40("div", { className: "text-[10px] text-muted-foreground font-mono", children: [
|
|
11061
11209
|
c.model,
|
|
11062
11210
|
" \xB7 ctx ",
|
|
11063
11211
|
c.contextWindow.toLocaleString()
|
|
11064
11212
|
] })
|
|
11065
11213
|
] }),
|
|
11066
|
-
c.isCurrent ? /* @__PURE__ */
|
|
11214
|
+
c.isCurrent ? /* @__PURE__ */ jsx42("span", { className: "text-[10px] uppercase tracking-wide text-primary font-semibold", children: "active" }) : /* @__PURE__ */ jsx42(ArrowRight4, { className: "h-3.5 w-3.5 text-muted-foreground opacity-0 group-hover:opacity-100" })
|
|
11067
11215
|
]
|
|
11068
11216
|
},
|
|
11069
11217
|
`${c.provider}:${c.model}`
|
|
@@ -11093,11 +11241,11 @@ import {
|
|
|
11093
11241
|
import { useState as useState28, useEffect as useEffect24, useCallback as useCallback13 } from "react";
|
|
11094
11242
|
|
|
11095
11243
|
// src/components/ui/input.tsx
|
|
11096
|
-
import * as
|
|
11097
|
-
import { jsx as
|
|
11098
|
-
var Input =
|
|
11244
|
+
import * as React3 from "react";
|
|
11245
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
11246
|
+
var Input = React3.forwardRef(
|
|
11099
11247
|
({ className, type, ...props }, ref) => {
|
|
11100
|
-
return /* @__PURE__ */
|
|
11248
|
+
return /* @__PURE__ */ jsx43(
|
|
11101
11249
|
"input",
|
|
11102
11250
|
{
|
|
11103
11251
|
type,
|
|
@@ -11113,6 +11261,41 @@ var Input = React4.forwardRef(
|
|
|
11113
11261
|
);
|
|
11114
11262
|
Input.displayName = "Input";
|
|
11115
11263
|
|
|
11264
|
+
// src/components/ui/scroll-area.tsx
|
|
11265
|
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
11266
|
+
import * as React4 from "react";
|
|
11267
|
+
import { jsx as jsx44, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
11268
|
+
var ScrollArea = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs41(
|
|
11269
|
+
ScrollAreaPrimitive.Root,
|
|
11270
|
+
{
|
|
11271
|
+
ref,
|
|
11272
|
+
className: cn("relative overflow-hidden", className),
|
|
11273
|
+
...props,
|
|
11274
|
+
children: [
|
|
11275
|
+
/* @__PURE__ */ jsx44(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
|
|
11276
|
+
/* @__PURE__ */ jsx44(ScrollBar, {}),
|
|
11277
|
+
/* @__PURE__ */ jsx44(ScrollAreaPrimitive.Corner, {})
|
|
11278
|
+
]
|
|
11279
|
+
}
|
|
11280
|
+
));
|
|
11281
|
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
11282
|
+
var ScrollBar = React4.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx44(
|
|
11283
|
+
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
11284
|
+
{
|
|
11285
|
+
ref,
|
|
11286
|
+
orientation,
|
|
11287
|
+
className: cn(
|
|
11288
|
+
"flex touch-none select-none transition-colors",
|
|
11289
|
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
11290
|
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
11291
|
+
className
|
|
11292
|
+
),
|
|
11293
|
+
...props,
|
|
11294
|
+
children: /* @__PURE__ */ jsx44(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
|
|
11295
|
+
}
|
|
11296
|
+
));
|
|
11297
|
+
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
11298
|
+
|
|
11116
11299
|
// src/components/ui/tabs.tsx
|
|
11117
11300
|
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
11118
11301
|
import * as React5 from "react";
|
|
@@ -13003,7 +13186,7 @@ import {
|
|
|
13003
13186
|
Database as Database3,
|
|
13004
13187
|
FolderOpen as FolderOpen3,
|
|
13005
13188
|
Target,
|
|
13006
|
-
Wrench as
|
|
13189
|
+
Wrench as Wrench6,
|
|
13007
13190
|
X as X13,
|
|
13008
13191
|
FileText as FileText3,
|
|
13009
13192
|
Terminal as Terminal6,
|
|
@@ -13085,7 +13268,7 @@ var TOOL_ICONS = {
|
|
|
13085
13268
|
exec: /* @__PURE__ */ jsx55(Terminal6, { className: "h-3 w-3" }),
|
|
13086
13269
|
glob: /* @__PURE__ */ jsx55(FolderOpen3, { className: "h-3 w-3" }),
|
|
13087
13270
|
grep: /* @__PURE__ */ jsx55(Target, { className: "h-3 w-3" }),
|
|
13088
|
-
edit: /* @__PURE__ */ jsx55(
|
|
13271
|
+
edit: /* @__PURE__ */ jsx55(Wrench6, { className: "h-3 w-3" }),
|
|
13089
13272
|
fetch: /* @__PURE__ */ jsx55(Globe5, { className: "h-3 w-3" }),
|
|
13090
13273
|
search: /* @__PURE__ */ jsx55(Target, { className: "h-3 w-3" })
|
|
13091
13274
|
};
|
|
@@ -13132,7 +13315,7 @@ function AgentNode({ data }) {
|
|
|
13132
13315
|
/* @__PURE__ */ jsxs50("div", { className: "flex-1 min-w-0", children: [
|
|
13133
13316
|
/* @__PURE__ */ jsx55("div", { className: "text-[10px] font-bold truncate", style: { color: colors }, children: data.label }),
|
|
13134
13317
|
data.currentTool && /* @__PURE__ */ jsxs50("div", { className: "flex items-center gap-1 text-[9px] text-amber-400/70", children: [
|
|
13135
|
-
/* @__PURE__ */ jsx55(
|
|
13318
|
+
/* @__PURE__ */ jsx55(Wrench6, { className: "h-2.5 w-2.5" }),
|
|
13136
13319
|
/* @__PURE__ */ jsx55("span", { className: "truncate font-mono", children: data.currentTool })
|
|
13137
13320
|
] })
|
|
13138
13321
|
] }),
|
|
@@ -13172,7 +13355,7 @@ function AgentNode({ data }) {
|
|
|
13172
13355
|
}
|
|
13173
13356
|
function ToolNode({ data }) {
|
|
13174
13357
|
const colors = data.color || "#f59e0b";
|
|
13175
|
-
const icon = TOOL_ICONS[data.label?.toLowerCase() ?? ""] || /* @__PURE__ */ jsx55(
|
|
13358
|
+
const icon = TOOL_ICONS[data.label?.toLowerCase() ?? ""] || /* @__PURE__ */ jsx55(Wrench6, { className: "h-3 w-3" });
|
|
13176
13359
|
return /* @__PURE__ */ jsxs50("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/10 p-2 min-w-[100px] transition-all", children: [
|
|
13177
13360
|
/* @__PURE__ */ jsxs50("div", { className: "flex items-center gap-2", children: [
|
|
13178
13361
|
/* @__PURE__ */ jsx55("span", { style: { color: colors }, children: icon }),
|
|
@@ -13744,7 +13927,7 @@ import {
|
|
|
13744
13927
|
Loader2 as Loader28,
|
|
13745
13928
|
Minimize2
|
|
13746
13929
|
} from "lucide-react";
|
|
13747
|
-
import { useCallback as useCallback17, useEffect as useEffect29, useMemo as
|
|
13930
|
+
import { useCallback as useCallback17, useEffect as useEffect29, useMemo as useMemo12, useRef as useRef19, useState as useState32 } from "react";
|
|
13748
13931
|
import { jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
13749
13932
|
var EXT_ICONS = {
|
|
13750
13933
|
// ── Code ──
|
|
@@ -13970,7 +14153,7 @@ function FileExplorer() {
|
|
|
13970
14153
|
const segments = cwd.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
13971
14154
|
return (segments[segments.length - 1] ?? "") === projectName;
|
|
13972
14155
|
})();
|
|
13973
|
-
const breadcrumbs =
|
|
14156
|
+
const breadcrumbs = useMemo12(() => {
|
|
13974
14157
|
if (!cwd || !projectName) return [];
|
|
13975
14158
|
const norm = cwd.replace(/\\/g, "/");
|
|
13976
14159
|
const segments = norm.split("/").filter(Boolean);
|
|
@@ -14063,7 +14246,7 @@ function FileExplorer() {
|
|
|
14063
14246
|
}, [treeLoading]);
|
|
14064
14247
|
const [selectedPath, setSelectedPath] = useState32(null);
|
|
14065
14248
|
const [globalExpand, setGlobalExpand] = useState32(null);
|
|
14066
|
-
const dirCount =
|
|
14249
|
+
const dirCount = useMemo12(() => {
|
|
14067
14250
|
let count = 0;
|
|
14068
14251
|
const walk = (nodes) => {
|
|
14069
14252
|
for (const n of nodes) {
|
|
@@ -14074,7 +14257,7 @@ function FileExplorer() {
|
|
|
14074
14257
|
walk(tree);
|
|
14075
14258
|
return count;
|
|
14076
14259
|
}, [tree]);
|
|
14077
|
-
const cwdStats =
|
|
14260
|
+
const cwdStats = useMemo12(() => {
|
|
14078
14261
|
let files = 0;
|
|
14079
14262
|
let dirs = 0;
|
|
14080
14263
|
for (const n of tree) {
|
|
@@ -14774,12 +14957,12 @@ function ProjectsPanel({ fullView }) {
|
|
|
14774
14957
|
}
|
|
14775
14958
|
|
|
14776
14959
|
// src/components/SidePanel/AgentsPanel.tsx
|
|
14777
|
-
import { Bot as Bot10, LayoutGrid as LayoutGrid2, Wrench as
|
|
14778
|
-
import { useMemo as
|
|
14960
|
+
import { Bot as Bot10, LayoutGrid as LayoutGrid2, Wrench as Wrench8 } from "lucide-react";
|
|
14961
|
+
import { useMemo as useMemo14, useState as useState36 } from "react";
|
|
14779
14962
|
|
|
14780
14963
|
// src/components/FleetPanel.tsx
|
|
14781
|
-
import { Bot as Bot9, Check as Check7, ChevronDown as ChevronDown9, ChevronRight as ChevronRight8, Clock as Clock11, Copy as Copy4, Cpu as Cpu12, Crown, Wrench as
|
|
14782
|
-
import { useCallback as useCallback19, useMemo as
|
|
14964
|
+
import { Bot as Bot9, Check as Check7, ChevronDown as ChevronDown9, ChevronRight as ChevronRight8, Clock as Clock11, Copy as Copy4, Cpu as Cpu12, Crown, Wrench as Wrench7, X as X14, Zap as Zap9 } from "lucide-react";
|
|
14965
|
+
import { useCallback as useCallback19, useMemo as useMemo13, useState as useState35 } from "react";
|
|
14783
14966
|
|
|
14784
14967
|
// src/components/ui/sparkline.tsx
|
|
14785
14968
|
import { jsx as jsx59 } from "react/jsx-runtime";
|
|
@@ -14985,7 +15168,7 @@ function AgentDetail({
|
|
|
14985
15168
|
active ? "border-primary/30 bg-primary/[0.04]" : "border-border bg-muted/30"
|
|
14986
15169
|
),
|
|
14987
15170
|
children: [
|
|
14988
|
-
/* @__PURE__ */ jsx60(
|
|
15171
|
+
/* @__PURE__ */ jsx60(Wrench7, { className: cn("h-3.5 w-3.5", active ? "text-primary animate-pulse" : "text-muted-foreground") }),
|
|
14989
15172
|
/* @__PURE__ */ jsx60("span", { className: "text-xs font-mono", children: tool }),
|
|
14990
15173
|
/* @__PURE__ */ jsx60("span", { className: "text-[10px] text-muted-foreground ml-auto", children: agent.currentTool ? "running\u2026" : "last tool" })
|
|
14991
15174
|
]
|
|
@@ -15122,7 +15305,7 @@ function AgentCard({
|
|
|
15122
15305
|
),
|
|
15123
15306
|
title: a.currentTool ? `running ${tool}` : `last: ${tool}`,
|
|
15124
15307
|
children: [
|
|
15125
|
-
/* @__PURE__ */ jsx60(
|
|
15308
|
+
/* @__PURE__ */ jsx60(Wrench7, { className: cn("h-2.5 w-2.5 shrink-0", active && "animate-pulse") }),
|
|
15126
15309
|
/* @__PURE__ */ jsx60("span", { className: "truncate font-mono", children: tool })
|
|
15127
15310
|
]
|
|
15128
15311
|
}
|
|
@@ -15158,7 +15341,7 @@ function FleetPanel({
|
|
|
15158
15341
|
const agents = useFleetStore((s) => s.agents);
|
|
15159
15342
|
const [collapsed, setCollapsed] = useState35(true);
|
|
15160
15343
|
const [selectedId, setSelectedId] = useState35(null);
|
|
15161
|
-
const list =
|
|
15344
|
+
const list = useMemo13(() => {
|
|
15162
15345
|
const arr = Array.from(agents.values());
|
|
15163
15346
|
arr.sort((x, y) => {
|
|
15164
15347
|
const xa = x.status === "running" ? 0 : 1;
|
|
@@ -15261,7 +15444,7 @@ function AgentRow2({ agent, onClick }) {
|
|
|
15261
15444
|
/* @__PURE__ */ jsx61("span", { className: "tabular ml-auto text-[10px] text-foreground/70", children: fmtCost3(agent.costUsd) })
|
|
15262
15445
|
] }),
|
|
15263
15446
|
(agent.currentTool || agent.lastTool) && /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-1 mt-1 text-[10px] text-muted-foreground truncate", children: [
|
|
15264
|
-
/* @__PURE__ */ jsx61(
|
|
15447
|
+
/* @__PURE__ */ jsx61(Wrench8, { className: cn("h-2.5 w-2.5 shrink-0", active && "animate-pulse text-primary") }),
|
|
15265
15448
|
/* @__PURE__ */ jsx61("span", { className: "truncate font-mono", children: agent.currentTool ?? agent.lastTool })
|
|
15266
15449
|
] })
|
|
15267
15450
|
]
|
|
@@ -15272,7 +15455,7 @@ function AgentsPanel() {
|
|
|
15272
15455
|
const fleetAgents = useFleetStore((s) => s.agents);
|
|
15273
15456
|
const setCurrentView = useUIStore((s) => s.setCurrentView);
|
|
15274
15457
|
const [selectedAgentId, setSelectedAgentId] = useState36(null);
|
|
15275
|
-
const fleetList =
|
|
15458
|
+
const fleetList = useMemo14(() => {
|
|
15276
15459
|
const arr = Array.from(fleetAgents.values());
|
|
15277
15460
|
arr.sort((x, y) => {
|
|
15278
15461
|
const xa = x.status === "running" ? 0 : 1;
|
|
@@ -15331,7 +15514,7 @@ import {
|
|
|
15331
15514
|
Trash2 as Trash24,
|
|
15332
15515
|
X as X15
|
|
15333
15516
|
} from "lucide-react";
|
|
15334
|
-
import { useCallback as useCallback20, useEffect as useEffect32, useMemo as
|
|
15517
|
+
import { useCallback as useCallback20, useEffect as useEffect32, useMemo as useMemo15, useState as useState37 } from "react";
|
|
15335
15518
|
import { Fragment as Fragment15, jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
15336
15519
|
var formatRelative = (iso) => {
|
|
15337
15520
|
const ts = Date.parse(iso);
|
|
@@ -15378,7 +15561,7 @@ function SessionList({
|
|
|
15378
15561
|
},
|
|
15379
15562
|
[resumeSession]
|
|
15380
15563
|
);
|
|
15381
|
-
const emptySessionIds =
|
|
15564
|
+
const emptySessionIds = useMemo15(
|
|
15382
15565
|
() => getEmptySessionIds(historyEntries),
|
|
15383
15566
|
[historyEntries]
|
|
15384
15567
|
);
|
|
@@ -15644,7 +15827,7 @@ import {
|
|
|
15644
15827
|
Wifi as Wifi2,
|
|
15645
15828
|
WifiOff as WifiOff3
|
|
15646
15829
|
} from "lucide-react";
|
|
15647
|
-
import { useCallback as useCallback21, useEffect as useEffect34, useMemo as
|
|
15830
|
+
import { useCallback as useCallback21, useEffect as useEffect34, useMemo as useMemo16, useState as useState39 } from "react";
|
|
15648
15831
|
import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
15649
15832
|
function fmtCost4(v) {
|
|
15650
15833
|
if (v <= 0) return "$0.000";
|
|
@@ -15779,7 +15962,7 @@ function SessionPanel() {
|
|
|
15779
15962
|
const t = setInterval(() => setNow(Date.now()), 1e3);
|
|
15780
15963
|
return () => clearInterval(t);
|
|
15781
15964
|
}, [startedAt]);
|
|
15782
|
-
const runningAgents =
|
|
15965
|
+
const runningAgents = useMemo16(
|
|
15783
15966
|
() => Array.from(fleetAgents.values()).filter((a) => a.status === "running").length,
|
|
15784
15967
|
[fleetAgents]
|
|
15785
15968
|
);
|
|
@@ -16215,7 +16398,7 @@ function SidePanel() {
|
|
|
16215
16398
|
|
|
16216
16399
|
// src/components/WorkspaceDock.tsx
|
|
16217
16400
|
import { Bot as Bot11, GitBranch as GitBranch3, ListTodo as ListTodo2, Maximize2 as Maximize22, Rocket as Rocket4, Target as Target3, Users as Users3 } from "lucide-react";
|
|
16218
|
-
import { useCallback as useCallback26, useEffect as useEffect41, useMemo as
|
|
16401
|
+
import { useCallback as useCallback26, useEffect as useEffect41, useMemo as useMemo17, useRef as useRef24, useState as useState46 } from "react";
|
|
16219
16402
|
|
|
16220
16403
|
// src/components/CollabPanel.tsx
|
|
16221
16404
|
import { Eye as Eye2, LogIn, LogOut, MessageSquareWarning, Pause as Pause5, Play as Play6, Users as Users2 } from "lucide-react";
|
|
@@ -17248,7 +17431,7 @@ function WorkspaceDock({ sessionId }) {
|
|
|
17248
17431
|
);
|
|
17249
17432
|
const [worktreeView, setWorktreeView] = useState46("graph");
|
|
17250
17433
|
const fleetTotal = fleetAgents.size;
|
|
17251
|
-
const fleetRunning =
|
|
17434
|
+
const fleetRunning = useMemo17(
|
|
17252
17435
|
() => Array.from(fleetAgents.values()).filter((a) => a.status === "running").length,
|
|
17253
17436
|
[fleetAgents]
|
|
17254
17437
|
);
|
|
@@ -17398,8 +17581,8 @@ function WorkspaceDock({ sessionId }) {
|
|
|
17398
17581
|
}
|
|
17399
17582
|
|
|
17400
17583
|
// src/components/AgentsMonitor.tsx
|
|
17401
|
-
import { Bot as Bot12, ChevronLeft, ChevronRight as ChevronRight10, Cpu as Cpu14, Crown as Crown2, Loader2 as Loader211, Wrench as
|
|
17402
|
-
import { useCallback as useCallback27, useEffect as useEffect42, useMemo as
|
|
17584
|
+
import { Bot as Bot12, ChevronLeft, ChevronRight as ChevronRight10, Cpu as Cpu14, Crown as Crown2, Loader2 as Loader211, Wrench as Wrench9, X as X16, Zap as Zap10 } from "lucide-react";
|
|
17585
|
+
import { useCallback as useCallback27, useEffect as useEffect42, useMemo as useMemo18, useState as useState47 } from "react";
|
|
17403
17586
|
import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
17404
17587
|
function fmtCost5(v) {
|
|
17405
17588
|
if (v <= 0) return "$0";
|
|
@@ -17499,7 +17682,7 @@ function AgentCard2({ agent, isLeader }) {
|
|
|
17499
17682
|
] })
|
|
17500
17683
|
] }),
|
|
17501
17684
|
(agent.currentTool || agent.lastTool) && /* @__PURE__ */ jsxs67("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [
|
|
17502
|
-
/* @__PURE__ */ jsx73(
|
|
17685
|
+
/* @__PURE__ */ jsx73(Wrench9, { className: cn("h-3 w-3", active && "animate-pulse text-primary") }),
|
|
17503
17686
|
/* @__PURE__ */ jsx73("span", { className: "font-mono", children: agent.currentTool ?? agent.lastTool }),
|
|
17504
17687
|
active && /* @__PURE__ */ jsx73(Loader211, { className: "h-3 w-3 animate-spin" })
|
|
17505
17688
|
] }),
|
|
@@ -17525,7 +17708,7 @@ function AgentsMonitor({ onClose }) {
|
|
|
17525
17708
|
const fleetAgents = useFleetStore((s) => s.agents);
|
|
17526
17709
|
const leaderId = useFleetStore((s) => s.leaderId);
|
|
17527
17710
|
const [selectedIdx, setSelectedIdx] = useState47(0);
|
|
17528
|
-
const fleetList =
|
|
17711
|
+
const fleetList = useMemo18(() => {
|
|
17529
17712
|
const arr = Array.from(fleetAgents.values());
|
|
17530
17713
|
arr.sort((x, y) => {
|
|
17531
17714
|
if (x.id === leaderId) return -1;
|
|
@@ -17664,11 +17847,11 @@ import {
|
|
|
17664
17847
|
Loader2 as Loader212,
|
|
17665
17848
|
Timer as Timer2,
|
|
17666
17849
|
Users as Users4,
|
|
17667
|
-
Wrench as
|
|
17850
|
+
Wrench as Wrench10,
|
|
17668
17851
|
XCircle as XCircle9,
|
|
17669
17852
|
Zap as Zap11
|
|
17670
17853
|
} from "lucide-react";
|
|
17671
|
-
import { useCallback as useCallback28, useEffect as useEffect43, useMemo as
|
|
17854
|
+
import { useCallback as useCallback28, useEffect as useEffect43, useMemo as useMemo19, useState as useState48 } from "react";
|
|
17672
17855
|
|
|
17673
17856
|
// src/components/ui/dropdown-menu.tsx
|
|
17674
17857
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
@@ -17901,7 +18084,7 @@ function FleetAgentDetailPanel({
|
|
|
17901
18084
|
}, []);
|
|
17902
18085
|
const totalToolDuration = agent.toolLog.reduce((sum, t) => sum + t.durationMs, 0);
|
|
17903
18086
|
const avgToolDuration = agent.toolLog.length > 0 ? Math.round(totalToolDuration / agent.toolLog.length) : 0;
|
|
17904
|
-
const uniqueTools =
|
|
18087
|
+
const uniqueTools = useMemo19(() => {
|
|
17905
18088
|
const tools = /* @__PURE__ */ new Set();
|
|
17906
18089
|
agent.toolLog.forEach((t) => tools.add(t.name));
|
|
17907
18090
|
return tools.size;
|
|
@@ -18025,7 +18208,7 @@ function FleetAgentDetailPanel({
|
|
|
18025
18208
|
"rounded-lg border px-4 py-3 flex items-center gap-3",
|
|
18026
18209
|
active ? "border-primary/30 bg-primary/[0.04]" : "border-border bg-muted/30"
|
|
18027
18210
|
), children: [
|
|
18028
|
-
/* @__PURE__ */ jsx77(
|
|
18211
|
+
/* @__PURE__ */ jsx77(Wrench10, { className: cn("h-4 w-4", active ? "text-primary animate-pulse" : "text-muted-foreground") }),
|
|
18029
18212
|
/* @__PURE__ */ jsx77("span", { className: "text-sm font-mono font-medium", children: agent.currentTool }),
|
|
18030
18213
|
active ? /* @__PURE__ */ jsxs71("span", { className: "ml-auto flex items-center gap-1.5 text-[10px] text-primary", children: [
|
|
18031
18214
|
/* @__PURE__ */ jsx77(Loader212, { className: "h-3 w-3 animate-spin" }),
|
|
@@ -18111,7 +18294,7 @@ function FleetAgentDetailPanel({
|
|
|
18111
18294
|
className: "w-full flex items-center justify-between px-4 py-2 border-b bg-muted/30 hover:bg-muted/50 transition-colors",
|
|
18112
18295
|
children: [
|
|
18113
18296
|
/* @__PURE__ */ jsxs71("span", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
18114
|
-
/* @__PURE__ */ jsx77(
|
|
18297
|
+
/* @__PURE__ */ jsx77(Wrench10, { className: "h-3 w-3" }),
|
|
18115
18298
|
"Tool Log (",
|
|
18116
18299
|
agent.toolLog.length,
|
|
18117
18300
|
" calls)"
|
|
@@ -18216,7 +18399,7 @@ function FleetMonitor({
|
|
|
18216
18399
|
const t = setInterval(() => setNowTick(Date.now()), 1e3);
|
|
18217
18400
|
return () => clearInterval(t);
|
|
18218
18401
|
}, []);
|
|
18219
|
-
const fleetList =
|
|
18402
|
+
const fleetList = useMemo19(() => {
|
|
18220
18403
|
const arr = Array.from(fleetAgents.values());
|
|
18221
18404
|
arr.sort((x, y) => {
|
|
18222
18405
|
if (x.id === leaderId) return -1;
|
|
@@ -18228,7 +18411,7 @@ function FleetMonitor({
|
|
|
18228
18411
|
});
|
|
18229
18412
|
return arr;
|
|
18230
18413
|
}, [fleetAgents, leaderId]);
|
|
18231
|
-
const totalCost =
|
|
18414
|
+
const totalCost = useMemo19(
|
|
18232
18415
|
() => Array.from(fleetAgents.values()).reduce((sum, a) => sum + a.costUsd, 0),
|
|
18233
18416
|
[fleetAgents]
|
|
18234
18417
|
);
|