@tangle-network/agent-app 0.10.0 → 0.11.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/README.md +10 -0
- package/dist/agent-activity-C8ZG0F0M.d.ts +43 -0
- package/dist/chunk-5RT6KY4G.js +190 -0
- package/dist/chunk-5RT6KY4G.js.map +1 -0
- package/dist/chunk-AFDROJ64.js +218 -0
- package/dist/chunk-AFDROJ64.js.map +1 -0
- package/dist/{chunk-UIWB2F6N.js → chunk-UDXMR3AD.js} +80 -24
- package/dist/chunk-UDXMR3AD.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -1
- package/dist/missions/index.d.ts +38 -5
- package/dist/missions/index.js +3 -1
- package/dist/trace/index.d.ts +137 -1
- package/dist/trace/index.js +24 -138
- package/dist/trace/index.js.map +1 -1
- package/dist/web-react/index.d.ts +79 -1
- package/dist/web-react/index.js +417 -116
- package/dist/web-react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-UIWB2F6N.js.map +0 -1
package/dist/web-react/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stepActivityFlowTrace
|
|
3
|
+
} from "../chunk-AFDROJ64.js";
|
|
4
|
+
|
|
1
5
|
// src/web-react/index.tsx
|
|
2
|
-
import { useEffect as
|
|
6
|
+
import { useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
|
|
3
7
|
|
|
4
8
|
// src/web-react/provider-logo.tsx
|
|
5
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -206,23 +210,264 @@ async function streamChatTurn(opts) {
|
|
|
206
210
|
}
|
|
207
211
|
}
|
|
208
212
|
|
|
209
|
-
// src/web-react/
|
|
213
|
+
// src/web-react/mission-activity.tsx
|
|
214
|
+
import { useCallback, useEffect as useEffect2, useState as useState2 } from "react";
|
|
210
215
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
211
|
-
|
|
216
|
+
var LIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "running"]);
|
|
217
|
+
var OK_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "succeeded"]);
|
|
218
|
+
var ERROR_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "cancelled", "aborted"]);
|
|
219
|
+
function activityTone(status) {
|
|
220
|
+
const s = status.toLowerCase();
|
|
221
|
+
if (LIVE_STATUSES.has(s)) return "live";
|
|
222
|
+
if (OK_STATUSES.has(s)) return "ok";
|
|
223
|
+
if (ERROR_STATUSES.has(s)) return "error";
|
|
224
|
+
return "neutral";
|
|
225
|
+
}
|
|
226
|
+
function formatActivityCost(costUsd) {
|
|
227
|
+
if (costUsd === void 0 || !isFinite(costUsd) || costUsd <= 0) return null;
|
|
228
|
+
return costUsd < 0.01 ? `$${costUsd.toFixed(4)}` : `$${costUsd.toFixed(2)}`;
|
|
229
|
+
}
|
|
230
|
+
function formatActivityDuration(durationMs) {
|
|
231
|
+
if (durationMs === void 0 || !isFinite(durationMs) || durationMs < 0) return null;
|
|
232
|
+
const totalSeconds = Math.round(durationMs / 1e3);
|
|
233
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
234
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
235
|
+
const seconds = totalSeconds % 60;
|
|
236
|
+
if (minutes < 60) return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
|
|
237
|
+
return `${Math.floor(minutes / 60)}h ${String(minutes % 60).padStart(2, "0")}m`;
|
|
238
|
+
}
|
|
239
|
+
function mergeActivityPages(existing, incoming) {
|
|
240
|
+
const byTask = /* @__PURE__ */ new Map();
|
|
241
|
+
for (const row of existing) byTask.set(row.taskId, row);
|
|
242
|
+
for (const row of incoming) byTask.set(row.taskId, row);
|
|
243
|
+
return [...byTask.values()].sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt));
|
|
244
|
+
}
|
|
245
|
+
function waterfallLayout(trace) {
|
|
246
|
+
const total = trace.totalMs > 0 ? trace.totalMs : 1;
|
|
247
|
+
return [...trace.spans].sort((a, b) => a.startMs - b.startMs).map((span) => {
|
|
248
|
+
const meta = span.meta ?? {};
|
|
249
|
+
const failed = meta.ok === false || typeof meta.status === "string" && activityTone(meta.status) === "error";
|
|
250
|
+
return {
|
|
251
|
+
name: span.name,
|
|
252
|
+
kind: span.kind,
|
|
253
|
+
offsetPct: Math.max(0, Math.min(100, span.startMs / total * 100)),
|
|
254
|
+
widthPct: Math.max(0.5, Math.min(100, (span.endMs - span.startMs) / total * 100)),
|
|
255
|
+
durationLabel: `${((span.endMs - span.startMs) / 1e3).toFixed(1)}s${span.approx ? "~" : ""}`,
|
|
256
|
+
approx: span.approx === true,
|
|
257
|
+
ok: !failed
|
|
258
|
+
};
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function ChevronGlyph({ className }) {
|
|
212
262
|
return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }) });
|
|
213
263
|
}
|
|
264
|
+
function RefreshGlyph({ className }) {
|
|
265
|
+
return /* @__PURE__ */ jsx2("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx2("path", { d: "M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6" }) });
|
|
266
|
+
}
|
|
267
|
+
function StatusDot({ tone }) {
|
|
268
|
+
return /* @__PURE__ */ jsx2(
|
|
269
|
+
"span",
|
|
270
|
+
{
|
|
271
|
+
className: `h-2 w-2 shrink-0 rounded-full ${tone === "live" ? "animate-pulse bg-yellow-500" : tone === "ok" ? "bg-green-500" : tone === "error" ? "bg-red-500" : "bg-muted-foreground/40"}`
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
var BAR_CLASS = {
|
|
276
|
+
pipeline: "bg-muted-foreground/30",
|
|
277
|
+
model: "bg-primary/60",
|
|
278
|
+
tool: "bg-primary"
|
|
279
|
+
};
|
|
280
|
+
function FlowWaterfall({ trace }) {
|
|
281
|
+
const rows = waterfallLayout(trace);
|
|
282
|
+
if (rows.length === 0) return null;
|
|
283
|
+
const cost = formatActivityCost(trace.costUsd);
|
|
284
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
|
|
285
|
+
rows.map((row, i) => /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_auto] items-center gap-2", children: [
|
|
286
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate font-mono text-[11px] text-muted-foreground", title: row.name, children: row.name }),
|
|
287
|
+
/* @__PURE__ */ jsx2("div", { className: "relative h-2 rounded-sm bg-muted/40", children: /* @__PURE__ */ jsx2(
|
|
288
|
+
"div",
|
|
289
|
+
{
|
|
290
|
+
className: `absolute inset-y-0 rounded-sm ${row.ok ? BAR_CLASS[row.kind] : "bg-red-500/80"} ${row.approx ? "opacity-70" : ""}`,
|
|
291
|
+
style: { left: `${row.offsetPct}%`, width: `${row.widthPct}%` }
|
|
292
|
+
}
|
|
293
|
+
) }),
|
|
294
|
+
/* @__PURE__ */ jsx2("span", { className: "shrink-0 font-mono text-[10px] tabular-nums text-muted-foreground/70", children: row.durationLabel })
|
|
295
|
+
] }, i)),
|
|
296
|
+
/* @__PURE__ */ jsxs2("p", { className: "pt-0.5 text-right font-mono text-[10px] tabular-nums text-muted-foreground/60", children: [
|
|
297
|
+
(trace.totalMs / 1e3).toFixed(1),
|
|
298
|
+
"s",
|
|
299
|
+
cost ? ` \xB7 ${cost}` : ""
|
|
300
|
+
] })
|
|
301
|
+
] });
|
|
302
|
+
}
|
|
303
|
+
function MissionActivityLane({ activity, startedAt, nowMs }) {
|
|
304
|
+
const [expanded, setExpanded] = useState2(false);
|
|
305
|
+
if (activity.length === 0) return null;
|
|
306
|
+
return /* @__PURE__ */ jsxs2("div", { className: "mt-1 border-l border-border/50 pl-3", children: [
|
|
307
|
+
activity.map((run) => {
|
|
308
|
+
const tone = activityTone(run.status);
|
|
309
|
+
const cost = formatActivityCost(run.costUsd);
|
|
310
|
+
const duration = formatActivityDuration(run.durationMs);
|
|
311
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
|
|
312
|
+
/* @__PURE__ */ jsx2(StatusDot, { tone }),
|
|
313
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
314
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: run.tool }),
|
|
315
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-muted-foreground", children: [
|
|
316
|
+
" \u2014 ",
|
|
317
|
+
run.detail
|
|
318
|
+
] })
|
|
319
|
+
] }),
|
|
320
|
+
tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */ jsx2("span", { className: "shrink-0 rounded-full bg-yellow-500/10 px-1.5 py-0.5 font-mono text-[10px] text-yellow-700 dark:text-yellow-400", children: [run.iteration !== void 0 ? `iter ${run.iteration}` : null, run.phase ?? null].filter(Boolean).join(" \xB7 ") }),
|
|
321
|
+
/* @__PURE__ */ jsxs2("span", { className: "flex shrink-0 items-center gap-1.5 font-mono text-[10px] tabular-nums text-muted-foreground/70", children: [
|
|
322
|
+
tone !== "live" && tone !== "ok" && /* @__PURE__ */ jsx2("span", { children: run.status }),
|
|
323
|
+
cost && /* @__PURE__ */ jsx2("span", { children: cost }),
|
|
324
|
+
duration && /* @__PURE__ */ jsx2("span", { children: duration })
|
|
325
|
+
] })
|
|
326
|
+
] }, run.taskId);
|
|
327
|
+
}),
|
|
328
|
+
/* @__PURE__ */ jsxs2(
|
|
329
|
+
"button",
|
|
330
|
+
{
|
|
331
|
+
type: "button",
|
|
332
|
+
onClick: () => setExpanded((v) => !v),
|
|
333
|
+
className: "flex items-center gap-1 py-0.5 text-[10px] font-medium text-muted-foreground/70 transition hover:text-foreground",
|
|
334
|
+
children: [
|
|
335
|
+
/* @__PURE__ */ jsx2(ChevronGlyph, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` }),
|
|
336
|
+
"timeline"
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
),
|
|
340
|
+
expanded && /* @__PURE__ */ jsx2("div", { className: "rounded-md border border-border/50 bg-muted/10 p-2", children: /* @__PURE__ */ jsx2(
|
|
341
|
+
FlowWaterfall,
|
|
342
|
+
{
|
|
343
|
+
trace: stepActivityFlowTrace(activity, {
|
|
344
|
+
...startedAt !== void 0 ? { startedAt } : {},
|
|
345
|
+
...nowMs !== void 0 ? { nowMs } : {}
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
) })
|
|
349
|
+
] });
|
|
350
|
+
}
|
|
351
|
+
function ActivityRow({
|
|
352
|
+
record,
|
|
353
|
+
renderMissionRef
|
|
354
|
+
}) {
|
|
355
|
+
const [open, setOpen] = useState2(false);
|
|
356
|
+
const tone = activityTone(record.status);
|
|
357
|
+
const cost = formatActivityCost(record.costUsd);
|
|
358
|
+
const duration = formatActivityDuration(record.durationMs);
|
|
359
|
+
return /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-border/60 bg-card", children: [
|
|
360
|
+
/* @__PURE__ */ jsxs2("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm", children: [
|
|
361
|
+
/* @__PURE__ */ jsx2(StatusDot, { tone }),
|
|
362
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
363
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: record.tool }),
|
|
364
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-muted-foreground", children: [
|
|
365
|
+
" \u2014 ",
|
|
366
|
+
record.detail
|
|
367
|
+
] })
|
|
368
|
+
] }),
|
|
369
|
+
tone === "live" && (record.iteration !== void 0 || record.phase !== void 0) && /* @__PURE__ */ jsx2("span", { className: "shrink-0 rounded-full bg-yellow-500/10 px-2 py-0.5 font-mono text-[10px] text-yellow-700 dark:text-yellow-400", children: [record.iteration !== void 0 ? `iter ${record.iteration}` : null, record.phase ?? null].filter(Boolean).join(" \xB7 ") }),
|
|
370
|
+
/* @__PURE__ */ jsx2(
|
|
371
|
+
"span",
|
|
372
|
+
{
|
|
373
|
+
className: `shrink-0 rounded-full px-2 py-0.5 text-[10px] font-medium ${tone === "ok" ? "bg-green-500/10 text-green-700 dark:text-green-400" : tone === "error" ? "bg-red-500/10 text-red-700 dark:text-red-400" : tone === "live" ? "bg-yellow-500/10 text-yellow-700 dark:text-yellow-400" : "bg-muted/60 text-muted-foreground"}`,
|
|
374
|
+
children: record.status
|
|
375
|
+
}
|
|
376
|
+
),
|
|
377
|
+
cost && /* @__PURE__ */ jsx2("span", { className: "shrink-0 font-mono text-[11px] tabular-nums text-muted-foreground", children: cost }),
|
|
378
|
+
/* @__PURE__ */ jsx2(ChevronGlyph, { className: `h-3 w-3 shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })
|
|
379
|
+
] }),
|
|
380
|
+
open && /* @__PURE__ */ jsxs2("div", { className: "space-y-1.5 border-t border-border/40 px-3 py-2.5", children: [
|
|
381
|
+
/* @__PURE__ */ jsxs2("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 font-mono text-[11px]", children: [
|
|
382
|
+
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground/60", children: "task" }),
|
|
383
|
+
/* @__PURE__ */ jsx2("dd", { className: "truncate text-muted-foreground", children: record.taskId }),
|
|
384
|
+
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground/60", children: "started" }),
|
|
385
|
+
/* @__PURE__ */ jsx2("dd", { className: "text-muted-foreground", children: new Date(record.startedAt).toLocaleString() }),
|
|
386
|
+
duration && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
387
|
+
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground/60", children: "duration" }),
|
|
388
|
+
/* @__PURE__ */ jsx2("dd", { className: "text-muted-foreground", children: duration })
|
|
389
|
+
] }),
|
|
390
|
+
record.traceId && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
391
|
+
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground/60", children: "trace" }),
|
|
392
|
+
/* @__PURE__ */ jsx2("dd", { className: "truncate text-muted-foreground", children: record.traceId })
|
|
393
|
+
] })
|
|
394
|
+
] }),
|
|
395
|
+
record.missionRef && renderMissionRef?.(record.missionRef, record)
|
|
396
|
+
] })
|
|
397
|
+
] });
|
|
398
|
+
}
|
|
399
|
+
function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent activity", emptyLabel = "No agent runs yet." }) {
|
|
400
|
+
const [rows, setRows] = useState2([]);
|
|
401
|
+
const [cursor, setCursor] = useState2(void 0);
|
|
402
|
+
const [loading, setLoading] = useState2(false);
|
|
403
|
+
const [error, setError] = useState2(null);
|
|
404
|
+
const load = useCallback(
|
|
405
|
+
async (from) => {
|
|
406
|
+
setLoading(true);
|
|
407
|
+
setError(null);
|
|
408
|
+
try {
|
|
409
|
+
const page = await fetchActivity(from);
|
|
410
|
+
setRows((prev) => mergeActivityPages(from === void 0 ? [] : prev, page.items));
|
|
411
|
+
setCursor(page.nextCursor);
|
|
412
|
+
} catch (e) {
|
|
413
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
414
|
+
} finally {
|
|
415
|
+
setLoading(false);
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
[fetchActivity]
|
|
419
|
+
);
|
|
420
|
+
useEffect2(() => {
|
|
421
|
+
void load();
|
|
422
|
+
}, [load]);
|
|
423
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
424
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
425
|
+
/* @__PURE__ */ jsx2("h2", { className: "flex-1 text-sm font-semibold", children: title }),
|
|
426
|
+
/* @__PURE__ */ jsx2(
|
|
427
|
+
"button",
|
|
428
|
+
{
|
|
429
|
+
type: "button",
|
|
430
|
+
onClick: () => void load(),
|
|
431
|
+
disabled: loading,
|
|
432
|
+
"aria-label": "Refresh",
|
|
433
|
+
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground disabled:opacity-50",
|
|
434
|
+
children: /* @__PURE__ */ jsx2(RefreshGlyph, { className: `h-3.5 w-3.5 ${loading ? "animate-spin" : ""}` })
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
] }),
|
|
438
|
+
error && /* @__PURE__ */ jsx2("p", { className: "rounded-md border border-red-300/60 bg-red-500/5 px-3 py-2 text-xs text-red-600", children: error }),
|
|
439
|
+
!error && rows.length === 0 && !loading && /* @__PURE__ */ jsx2("p", { className: "px-1 text-sm text-muted-foreground", children: emptyLabel }),
|
|
440
|
+
/* @__PURE__ */ jsx2("div", { className: "space-y-1.5", children: rows.map((record) => /* @__PURE__ */ jsx2(ActivityRow, { record, renderMissionRef }, record.taskId)) }),
|
|
441
|
+
cursor && /* @__PURE__ */ jsx2(
|
|
442
|
+
"button",
|
|
443
|
+
{
|
|
444
|
+
type: "button",
|
|
445
|
+
onClick: () => void load(cursor),
|
|
446
|
+
disabled: loading,
|
|
447
|
+
className: "w-full rounded-md border border-border bg-card px-3 py-1.5 text-xs font-medium text-muted-foreground transition hover:bg-accent/30 disabled:opacity-50",
|
|
448
|
+
children: "Older runs"
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
] });
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/web-react/index.tsx
|
|
455
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
456
|
+
function ChevronDown({ className }) {
|
|
457
|
+
return /* @__PURE__ */ jsx3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" }) });
|
|
458
|
+
}
|
|
214
459
|
function SearchGlyph({ className }) {
|
|
215
|
-
return /* @__PURE__ */
|
|
216
|
-
/* @__PURE__ */
|
|
217
|
-
/* @__PURE__ */
|
|
460
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
461
|
+
/* @__PURE__ */ jsx3("circle", { cx: "11", cy: "11", r: "8" }),
|
|
462
|
+
/* @__PURE__ */ jsx3("path", { d: "m21 21-4.3-4.3" })
|
|
218
463
|
] });
|
|
219
464
|
}
|
|
220
465
|
function SparkleGlyph({ className }) {
|
|
221
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsx3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1M7.7 16.3l-2.1 2.1" }) });
|
|
222
467
|
}
|
|
223
468
|
function useClickOutside(onOutside) {
|
|
224
469
|
const ref = useRef2(null);
|
|
225
|
-
|
|
470
|
+
useEffect3(() => {
|
|
226
471
|
function handler(e) {
|
|
227
472
|
if (ref.current && !ref.current.contains(e.target)) onOutside();
|
|
228
473
|
}
|
|
@@ -257,7 +502,7 @@ function formatContext(len) {
|
|
|
257
502
|
return `${len} ctx`;
|
|
258
503
|
}
|
|
259
504
|
function SectionHeader({ children }) {
|
|
260
|
-
return /* @__PURE__ */
|
|
505
|
+
return /* @__PURE__ */ jsx3("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground/70", children });
|
|
261
506
|
}
|
|
262
507
|
function ModelRow({
|
|
263
508
|
model,
|
|
@@ -267,30 +512,30 @@ function ModelRow({
|
|
|
267
512
|
}) {
|
|
268
513
|
const price = formatPrice(model.pricing?.prompt);
|
|
269
514
|
const ctx = formatContext(model.contextLength);
|
|
270
|
-
return /* @__PURE__ */
|
|
515
|
+
return /* @__PURE__ */ jsxs3(
|
|
271
516
|
"button",
|
|
272
517
|
{
|
|
273
518
|
type: "button",
|
|
274
519
|
onClick: onSelect,
|
|
275
520
|
className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${selected ? "bg-primary/10 font-medium" : "hover:bg-accent/30"}`,
|
|
276
521
|
children: [
|
|
277
|
-
renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
-
!model.supportsTools && /* @__PURE__ */
|
|
280
|
-
/* @__PURE__ */
|
|
281
|
-
ctx && /* @__PURE__ */
|
|
282
|
-
price && /* @__PURE__ */
|
|
522
|
+
renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx3(ProviderLogo, { provider: model.provider, size: 16 }),
|
|
523
|
+
/* @__PURE__ */ jsx3("span", { className: "truncate", children: model.name }),
|
|
524
|
+
!model.supportsTools && /* @__PURE__ */ jsx3("span", { className: "shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: "no tools" }),
|
|
525
|
+
/* @__PURE__ */ jsxs3("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground", children: [
|
|
526
|
+
ctx && /* @__PURE__ */ jsx3("span", { children: ctx }),
|
|
527
|
+
price && /* @__PURE__ */ jsx3("span", { children: price })
|
|
283
528
|
] })
|
|
284
529
|
]
|
|
285
530
|
}
|
|
286
531
|
);
|
|
287
532
|
}
|
|
288
533
|
function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel = "Recommended" }) {
|
|
289
|
-
const [open, setOpen] =
|
|
290
|
-
const [query, setQuery] =
|
|
534
|
+
const [open, setOpen] = useState3(false);
|
|
535
|
+
const [query, setQuery] = useState3("");
|
|
291
536
|
const containerRef = useClickOutside(() => setOpen(false));
|
|
292
537
|
const inputRef = useRef2(null);
|
|
293
|
-
|
|
538
|
+
useEffect3(() => {
|
|
294
539
|
if (open) inputRef.current?.focus();
|
|
295
540
|
}, [open]);
|
|
296
541
|
const selected = models.find((m) => m.id === value);
|
|
@@ -317,24 +562,24 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
|
|
|
317
562
|
setOpen(false);
|
|
318
563
|
setQuery("");
|
|
319
564
|
};
|
|
320
|
-
return /* @__PURE__ */
|
|
321
|
-
/* @__PURE__ */
|
|
565
|
+
return /* @__PURE__ */ jsxs3("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
566
|
+
/* @__PURE__ */ jsxs3(
|
|
322
567
|
"button",
|
|
323
568
|
{
|
|
324
569
|
type: "button",
|
|
325
570
|
onClick: () => setOpen((v) => !v),
|
|
326
571
|
className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30",
|
|
327
572
|
children: [
|
|
328
|
-
selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */
|
|
329
|
-
/* @__PURE__ */
|
|
330
|
-
/* @__PURE__ */
|
|
573
|
+
selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */ jsx3(ProviderLogo, { provider: selected.provider, size: 16 }) : /* @__PURE__ */ jsx3(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
574
|
+
/* @__PURE__ */ jsx3("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
|
|
575
|
+
/* @__PURE__ */ jsx3(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
331
576
|
]
|
|
332
577
|
}
|
|
333
578
|
),
|
|
334
|
-
open && /* @__PURE__ */
|
|
335
|
-
/* @__PURE__ */
|
|
336
|
-
/* @__PURE__ */
|
|
337
|
-
/* @__PURE__ */
|
|
579
|
+
open && /* @__PURE__ */ jsxs3("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-[420px] overflow-hidden rounded-xl border border-border bg-card shadow-lg", children: [
|
|
580
|
+
/* @__PURE__ */ jsx3("div", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-2", children: [
|
|
581
|
+
/* @__PURE__ */ jsx3(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
582
|
+
/* @__PURE__ */ jsx3(
|
|
338
583
|
"input",
|
|
339
584
|
{
|
|
340
585
|
ref: inputRef,
|
|
@@ -346,20 +591,20 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
|
|
|
346
591
|
}
|
|
347
592
|
)
|
|
348
593
|
] }) }),
|
|
349
|
-
/* @__PURE__ */
|
|
350
|
-
loading && /* @__PURE__ */
|
|
351
|
-
!loading && filtered && /* @__PURE__ */
|
|
352
|
-
filtered.length === 0 && /* @__PURE__ */
|
|
353
|
-
filtered.map((m) => /* @__PURE__ */
|
|
594
|
+
/* @__PURE__ */ jsxs3("div", { className: "max-h-[400px] overflow-y-auto p-1 pb-2", children: [
|
|
595
|
+
loading && /* @__PURE__ */ jsx3("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
|
|
596
|
+
!loading && filtered && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
597
|
+
filtered.length === 0 && /* @__PURE__ */ jsx3("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
|
|
598
|
+
filtered.map((m) => /* @__PURE__ */ jsx3(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
354
599
|
] }),
|
|
355
|
-
!loading && !filtered && /* @__PURE__ */
|
|
356
|
-
sections.recommended.length > 0 && /* @__PURE__ */
|
|
357
|
-
/* @__PURE__ */
|
|
358
|
-
sections.recommended.map((m) => /* @__PURE__ */
|
|
600
|
+
!loading && !filtered && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
601
|
+
sections.recommended.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
602
|
+
/* @__PURE__ */ jsx3(SectionHeader, { children: recommendedLabel }),
|
|
603
|
+
sections.recommended.map((m) => /* @__PURE__ */ jsx3(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
359
604
|
] }),
|
|
360
|
-
sections.byProvider.map((g) => /* @__PURE__ */
|
|
361
|
-
/* @__PURE__ */
|
|
362
|
-
g.items.map((m) => /* @__PURE__ */
|
|
605
|
+
sections.byProvider.map((g) => /* @__PURE__ */ jsxs3("div", { children: [
|
|
606
|
+
/* @__PURE__ */ jsx3(SectionHeader, { children: g.provider }),
|
|
607
|
+
g.items.map((m) => /* @__PURE__ */ jsx3(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
363
608
|
] }, g.provider))
|
|
364
609
|
] })
|
|
365
610
|
] })
|
|
@@ -373,11 +618,11 @@ var EFFORT_LEVELS = [
|
|
|
373
618
|
{ id: "high", label: "High" }
|
|
374
619
|
];
|
|
375
620
|
function EffortPicker({ value, onChange }) {
|
|
376
|
-
const [open, setOpen] =
|
|
621
|
+
const [open, setOpen] = useState3(false);
|
|
377
622
|
const containerRef = useClickOutside(() => setOpen(false));
|
|
378
623
|
const selected = EFFORT_LEVELS.find((l) => l.id === value) ?? EFFORT_LEVELS[2];
|
|
379
|
-
return /* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
624
|
+
return /* @__PURE__ */ jsxs3("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
625
|
+
/* @__PURE__ */ jsxs3(
|
|
381
626
|
"button",
|
|
382
627
|
{
|
|
383
628
|
type: "button",
|
|
@@ -385,13 +630,13 @@ function EffortPicker({ value, onChange }) {
|
|
|
385
630
|
title: "Reasoning effort",
|
|
386
631
|
className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30",
|
|
387
632
|
children: [
|
|
388
|
-
/* @__PURE__ */
|
|
389
|
-
/* @__PURE__ */
|
|
390
|
-
/* @__PURE__ */
|
|
633
|
+
/* @__PURE__ */ jsx3(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
634
|
+
/* @__PURE__ */ jsx3("span", { children: selected.label }),
|
|
635
|
+
/* @__PURE__ */ jsx3(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
391
636
|
]
|
|
392
637
|
}
|
|
393
638
|
),
|
|
394
|
-
open && /* @__PURE__ */
|
|
639
|
+
open && /* @__PURE__ */ jsx3("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-36 overflow-hidden rounded-xl border border-border bg-card p-1 shadow-lg", children: EFFORT_LEVELS.map((l) => /* @__PURE__ */ jsx3(
|
|
395
640
|
"button",
|
|
396
641
|
{
|
|
397
642
|
type: "button",
|
|
@@ -407,41 +652,41 @@ function EffortPicker({ value, onChange }) {
|
|
|
407
652
|
] });
|
|
408
653
|
}
|
|
409
654
|
function RunDrillIn({ run, onClose }) {
|
|
410
|
-
return /* @__PURE__ */
|
|
411
|
-
/* @__PURE__ */
|
|
412
|
-
/* @__PURE__ */
|
|
655
|
+
return /* @__PURE__ */ jsxs3("div", { className: "fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-border bg-card shadow-xl", children: [
|
|
656
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
657
|
+
/* @__PURE__ */ jsx3(
|
|
413
658
|
"span",
|
|
414
659
|
{
|
|
415
660
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-yellow-500" : run.status === "error" ? "bg-red-500" : "bg-green-500"}`
|
|
416
661
|
}
|
|
417
662
|
),
|
|
418
|
-
/* @__PURE__ */
|
|
419
|
-
/* @__PURE__ */
|
|
420
|
-
/* @__PURE__ */
|
|
663
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
664
|
+
/* @__PURE__ */ jsx3("p", { className: "truncate text-sm font-semibold", children: run.title }),
|
|
665
|
+
/* @__PURE__ */ jsx3("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: run.toolName })
|
|
421
666
|
] }),
|
|
422
|
-
/* @__PURE__ */
|
|
667
|
+
/* @__PURE__ */ jsx3(
|
|
423
668
|
"button",
|
|
424
669
|
{
|
|
425
670
|
type: "button",
|
|
426
671
|
onClick: onClose,
|
|
427
672
|
"aria-label": "Close",
|
|
428
673
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground",
|
|
429
|
-
children: /* @__PURE__ */
|
|
674
|
+
children: /* @__PURE__ */ jsx3("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
430
675
|
}
|
|
431
676
|
)
|
|
432
677
|
] }),
|
|
433
|
-
/* @__PURE__ */
|
|
434
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
435
|
-
run.steps.map((step, i) => /* @__PURE__ */
|
|
436
|
-
/* @__PURE__ */
|
|
437
|
-
/* @__PURE__ */
|
|
438
|
-
/* @__PURE__ */
|
|
439
|
-
/* @__PURE__ */
|
|
678
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
|
|
679
|
+
run.steps.length === 0 && /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
|
|
680
|
+
run.steps.map((step, i) => /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-border/60 bg-background", children: [
|
|
681
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5", children: [
|
|
682
|
+
/* @__PURE__ */ jsx3("span", { className: `font-mono text-[11px] ${step.status === "error" ? "text-red-600" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
|
|
683
|
+
/* @__PURE__ */ jsx3("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
|
|
684
|
+
/* @__PURE__ */ jsx3("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: new Date(step.at).toLocaleTimeString() })
|
|
440
685
|
] }),
|
|
441
|
-
step.detail && /* @__PURE__ */
|
|
686
|
+
step.detail && /* @__PURE__ */ jsx3("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: step.detail })
|
|
442
687
|
] }, i))
|
|
443
688
|
] }),
|
|
444
|
-
/* @__PURE__ */
|
|
689
|
+
/* @__PURE__ */ jsx3("p", { className: "border-t border-border px-4 py-2 text-[11px] text-muted-foreground/60", children: "Readonly drill-in. Follow up in the main chat." })
|
|
445
690
|
] });
|
|
446
691
|
}
|
|
447
692
|
function pendingApprovalOf(call) {
|
|
@@ -449,6 +694,30 @@ function pendingApprovalOf(call) {
|
|
|
449
694
|
if (!outcome?.ok || outcome.result?.status !== "queued_for_approval" || !outcome.result.proposalId) return null;
|
|
450
695
|
return { proposalId: outcome.result.proposalId };
|
|
451
696
|
}
|
|
697
|
+
function ToolGlyph({ name, className }) {
|
|
698
|
+
if (name.startsWith("sandbox_")) {
|
|
699
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
700
|
+
/* @__PURE__ */ jsx3("polyline", { points: "4 17 10 11 4 5" }),
|
|
701
|
+
/* @__PURE__ */ jsx3("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
|
|
702
|
+
] });
|
|
703
|
+
}
|
|
704
|
+
if (name === "submit_proposal") {
|
|
705
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
706
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
707
|
+
/* @__PURE__ */ jsx3("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
|
|
708
|
+
] });
|
|
709
|
+
}
|
|
710
|
+
if (name === "schedule_followup") {
|
|
711
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
|
|
712
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "9" }),
|
|
713
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 7v5l3 3" })
|
|
714
|
+
] });
|
|
715
|
+
}
|
|
716
|
+
return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
717
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
|
|
718
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "4" })
|
|
719
|
+
] });
|
|
720
|
+
}
|
|
452
721
|
function toolOutcomeOf(call) {
|
|
453
722
|
return call.result;
|
|
454
723
|
}
|
|
@@ -480,21 +749,36 @@ function truncate(v, max = 240) {
|
|
|
480
749
|
function KvRows({ data }) {
|
|
481
750
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
482
751
|
if (!entries.length) return null;
|
|
483
|
-
return /* @__PURE__ */
|
|
484
|
-
/* @__PURE__ */
|
|
485
|
-
/* @__PURE__ */
|
|
752
|
+
return /* @__PURE__ */ jsx3("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs3("div", { className: "contents", children: [
|
|
753
|
+
/* @__PURE__ */ jsx3("dt", { className: "font-mono text-[11px] text-muted-foreground/70", children: k }),
|
|
754
|
+
/* @__PURE__ */ jsx3("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-[11px] text-muted-foreground", children: truncate(v) })
|
|
486
755
|
] }, k)) });
|
|
487
756
|
}
|
|
757
|
+
function ShellDetail({ call }) {
|
|
758
|
+
const outcome = toolOutcomeOf(call);
|
|
759
|
+
const r = outcome?.result ?? {};
|
|
760
|
+
return /* @__PURE__ */ jsxs3("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-[11px] leading-relaxed", children: [
|
|
761
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
|
|
762
|
+
/* @__PURE__ */ jsx3("span", { className: "select-none text-zinc-500", children: "$" }),
|
|
763
|
+
/* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
|
|
764
|
+
r.exitCode != null && /* @__PURE__ */ jsxs3("span", { className: r.exitCode === 0 ? "text-emerald-400" : "text-red-400", children: [
|
|
765
|
+
"exit ",
|
|
766
|
+
r.exitCode
|
|
767
|
+
] })
|
|
768
|
+
] }),
|
|
769
|
+
/* @__PURE__ */ jsx3("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
|
|
770
|
+
] });
|
|
771
|
+
}
|
|
488
772
|
function DefaultToolDetail({ call }) {
|
|
489
773
|
const outcome = toolOutcomeOf(call);
|
|
490
|
-
return /* @__PURE__ */
|
|
491
|
-
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */
|
|
492
|
-
/* @__PURE__ */
|
|
493
|
-
/* @__PURE__ */
|
|
774
|
+
return /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
|
|
775
|
+
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
|
|
776
|
+
/* @__PURE__ */ jsx3("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/50", children: "Called with" }),
|
|
777
|
+
/* @__PURE__ */ jsx3(KvRows, { data: call.args })
|
|
494
778
|
] }),
|
|
495
|
-
outcome && /* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
497
|
-
outcome.ok === false ? /* @__PURE__ */
|
|
779
|
+
outcome && /* @__PURE__ */ jsxs3("div", { children: [
|
|
780
|
+
/* @__PURE__ */ jsx3("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/50", children: outcome.ok === false ? "Failed" : "Result" }),
|
|
781
|
+
outcome.ok === false ? /* @__PURE__ */ jsx3("p", { className: "text-xs text-red-600", children: outcome.message ?? "Tool failed" }) : outcome.result && typeof outcome.result === "object" ? /* @__PURE__ */ jsx3(KvRows, { data: outcome.result }) : /* @__PURE__ */ jsx3("p", { className: "font-mono text-[11px] text-muted-foreground", children: truncate(outcome.result) })
|
|
498
782
|
] })
|
|
499
783
|
] });
|
|
500
784
|
}
|
|
@@ -505,31 +789,32 @@ function ToolCallCard({
|
|
|
505
789
|
onOpenRun,
|
|
506
790
|
renderers
|
|
507
791
|
}) {
|
|
508
|
-
const [expanded, setExpanded] =
|
|
792
|
+
const [expanded, setExpanded] = useState3(false);
|
|
509
793
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
510
794
|
const failed = call.status === "error" || toolOutcomeOf(call)?.ok === false;
|
|
511
795
|
const custom = renderers?.[call.name]?.(call, message);
|
|
512
|
-
return /* @__PURE__ */
|
|
796
|
+
return /* @__PURE__ */ jsxs3(
|
|
513
797
|
"div",
|
|
514
798
|
{
|
|
515
799
|
className: `w-fit min-w-[280px] max-w-full rounded-lg border text-xs transition ${pending ? "border-amber-300/60 bg-amber-500/5" : failed ? "border-red-300/60 bg-red-500/5" : "border-border/60 bg-muted/20"}`,
|
|
516
800
|
children: [
|
|
517
|
-
/* @__PURE__ */
|
|
801
|
+
/* @__PURE__ */ jsxs3(
|
|
518
802
|
"button",
|
|
519
803
|
{
|
|
520
804
|
type: "button",
|
|
521
805
|
onClick: () => setExpanded((v) => !v),
|
|
522
806
|
className: "flex w-full items-center gap-2 px-3 py-2 text-left",
|
|
523
807
|
children: [
|
|
524
|
-
/* @__PURE__ */
|
|
808
|
+
/* @__PURE__ */ jsx3(
|
|
525
809
|
"span",
|
|
526
810
|
{
|
|
527
811
|
className: `h-2 w-2 shrink-0 rounded-full ${call.status === "running" ? "animate-pulse bg-yellow-500" : pending ? "bg-amber-500" : failed ? "bg-red-500" : "bg-green-500"}`
|
|
528
812
|
}
|
|
529
813
|
),
|
|
530
|
-
/* @__PURE__ */
|
|
531
|
-
|
|
532
|
-
|
|
814
|
+
/* @__PURE__ */ jsx3(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
815
|
+
/* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate font-medium", children: friendlyToolTitle(call) }),
|
|
816
|
+
pending && approval && /* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-1", onClick: (e) => e.stopPropagation(), children: [
|
|
817
|
+
/* @__PURE__ */ jsx3(
|
|
533
818
|
"button",
|
|
534
819
|
{
|
|
535
820
|
type: "button",
|
|
@@ -538,7 +823,7 @@ function ToolCallCard({
|
|
|
538
823
|
children: "Approve"
|
|
539
824
|
}
|
|
540
825
|
),
|
|
541
|
-
/* @__PURE__ */
|
|
826
|
+
/* @__PURE__ */ jsx3(
|
|
542
827
|
"button",
|
|
543
828
|
{
|
|
544
829
|
type: "button",
|
|
@@ -548,14 +833,14 @@ function ToolCallCard({
|
|
|
548
833
|
}
|
|
549
834
|
)
|
|
550
835
|
] }),
|
|
551
|
-
/* @__PURE__ */
|
|
552
|
-
/* @__PURE__ */
|
|
836
|
+
/* @__PURE__ */ jsx3("span", { className: "shrink-0 text-[11px] text-muted-foreground/70", children: call.status === "running" ? "running\u2026" : pending ? "awaiting approval" : failed ? "failed" : "done" }),
|
|
837
|
+
/* @__PURE__ */ jsx3(ChevronDown, { className: `h-3 w-3 shrink-0 text-muted-foreground transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
553
838
|
]
|
|
554
839
|
}
|
|
555
840
|
),
|
|
556
|
-
expanded && /* @__PURE__ */
|
|
557
|
-
custom ?? /* @__PURE__ */
|
|
558
|
-
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */
|
|
841
|
+
expanded && /* @__PURE__ */ jsxs3("div", { className: "border-t border-border/40 px-3 py-2.5", children: [
|
|
842
|
+
custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx3(ShellDetail, { call }) : /* @__PURE__ */ jsx3(DefaultToolDetail, { call })),
|
|
843
|
+
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */ jsx3(
|
|
559
844
|
"button",
|
|
560
845
|
{
|
|
561
846
|
type: "button",
|
|
@@ -583,26 +868,34 @@ function AssistantMessage({
|
|
|
583
868
|
const content = useSmoothText(msg.content, streaming);
|
|
584
869
|
const reasoning = useSmoothText(msg.reasoning ?? "", streaming);
|
|
585
870
|
const reasoningScrollRef = useRef2(null);
|
|
586
|
-
|
|
871
|
+
const thinkStartRef = useRef2(null);
|
|
872
|
+
const thinkMsRef = useRef2(null);
|
|
873
|
+
if (streaming && reasoning && !content && thinkStartRef.current === null) {
|
|
874
|
+
thinkStartRef.current = performance.now();
|
|
875
|
+
}
|
|
876
|
+
if (content && thinkStartRef.current !== null && thinkMsRef.current === null) {
|
|
877
|
+
thinkMsRef.current = performance.now() - thinkStartRef.current;
|
|
878
|
+
}
|
|
879
|
+
useEffect3(() => {
|
|
587
880
|
const el = reasoningScrollRef.current;
|
|
588
881
|
if (el && streaming && !content) el.scrollTop = el.scrollHeight;
|
|
589
882
|
}, [reasoning, streaming, content]);
|
|
590
|
-
return /* @__PURE__ */
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
593
|
-
msg.modelUsed && /* @__PURE__ */
|
|
594
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
595
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
883
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
884
|
+
/* @__PURE__ */ jsxs3("div", { className: "mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground/60", children: [
|
|
885
|
+
/* @__PURE__ */ jsx3("span", { className: "font-semibold uppercase", children: agentLabel }),
|
|
886
|
+
msg.modelUsed && /* @__PURE__ */ jsx3("span", { className: "font-mono normal-case", children: msg.modelUsed }),
|
|
887
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx3("span", { children: formatTokensPerSecond(msg) }),
|
|
888
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx3("span", { children: formatModelCost(msg, models) })
|
|
596
889
|
] }),
|
|
597
|
-
reasoning && /* @__PURE__ */
|
|
598
|
-
/* @__PURE__ */
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
890
|
+
reasoning && /* @__PURE__ */ jsxs3("details", { className: "mb-2 rounded-lg border-l-2 border-border/70 bg-muted/20 px-3 py-2", open: !content, children: [
|
|
891
|
+
/* @__PURE__ */ jsx3("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !content ? /* @__PURE__ */ jsx3("span", { className: "animate-pulse", children: "Thinking\u2026" }) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process" }),
|
|
892
|
+
/* @__PURE__ */ jsx3("div", { ref: reasoningScrollRef, className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-[13px] leading-relaxed text-muted-foreground/70", children: reasoning })
|
|
893
|
+
] }),
|
|
894
|
+
/* @__PURE__ */ jsxs3("div", { className: "text-base leading-[1.75]", children: [
|
|
895
|
+
renderBody(content),
|
|
896
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx3("span", { className: "ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-pulse rounded-sm bg-foreground/70", "aria-hidden": true })
|
|
603
897
|
] }),
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx2("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx2(
|
|
898
|
+
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx3("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx3(
|
|
606
899
|
ToolCallCard,
|
|
607
900
|
{
|
|
608
901
|
call: tc,
|
|
@@ -617,15 +910,15 @@ function AssistantMessage({
|
|
|
617
910
|
] });
|
|
618
911
|
}
|
|
619
912
|
function ThinkingRow({ agentLabel }) {
|
|
620
|
-
const [seconds, setSeconds] =
|
|
621
|
-
|
|
913
|
+
const [seconds, setSeconds] = useState3(0);
|
|
914
|
+
useEffect3(() => {
|
|
622
915
|
const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
|
|
623
916
|
return () => clearInterval(id);
|
|
624
917
|
}, []);
|
|
625
|
-
return /* @__PURE__ */
|
|
626
|
-
/* @__PURE__ */
|
|
627
|
-
/* @__PURE__ */
|
|
628
|
-
/* @__PURE__ */
|
|
918
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
919
|
+
/* @__PURE__ */ jsx3("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: agentLabel }),
|
|
920
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-base text-muted-foreground", children: [
|
|
921
|
+
/* @__PURE__ */ jsx3("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
|
|
629
922
|
"Thinking",
|
|
630
923
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
631
924
|
] })
|
|
@@ -643,14 +936,14 @@ function ChatMessages({
|
|
|
643
936
|
onToolCallClick,
|
|
644
937
|
toolRenderers
|
|
645
938
|
}) {
|
|
646
|
-
const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
939
|
+
const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */ jsx3("p", { className: "whitespace-pre-wrap", children: content }));
|
|
647
940
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
648
|
-
return /* @__PURE__ */
|
|
941
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
649
942
|
messages.map(
|
|
650
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
651
|
-
/* @__PURE__ */
|
|
652
|
-
/* @__PURE__ */
|
|
653
|
-
] }) }, msg.id) : /* @__PURE__ */
|
|
943
|
+
(msg) => msg.role === "user" ? /* @__PURE__ */ jsx3("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs3("div", { className: "ml-auto w-fit max-w-[85%]", children: [
|
|
944
|
+
/* @__PURE__ */ jsx3("p", { className: "mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: userLabel }),
|
|
945
|
+
/* @__PURE__ */ jsx3("div", { className: "rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed", children: /* @__PURE__ */ jsx3("p", { className: "whitespace-pre-wrap", children: msg.content }) })
|
|
946
|
+
] }) }, msg.id) : /* @__PURE__ */ jsx3(
|
|
654
947
|
AssistantMessage,
|
|
655
948
|
{
|
|
656
949
|
msg,
|
|
@@ -666,22 +959,30 @@ function ChatMessages({
|
|
|
666
959
|
msg.id
|
|
667
960
|
)
|
|
668
961
|
),
|
|
669
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
962
|
+
loading && lastIsUser && /* @__PURE__ */ jsx3(ThinkingRow, { agentLabel })
|
|
670
963
|
] });
|
|
671
964
|
}
|
|
672
965
|
export {
|
|
966
|
+
AgentActivityPanel,
|
|
673
967
|
ChatMessages,
|
|
674
968
|
EffortPicker,
|
|
969
|
+
FlowWaterfall,
|
|
970
|
+
MissionActivityLane,
|
|
675
971
|
ModelPicker,
|
|
676
972
|
ProviderLogo,
|
|
677
973
|
RunDrillIn,
|
|
974
|
+
activityTone,
|
|
678
975
|
consumeChatStream,
|
|
679
976
|
dispatchChatStreamLine,
|
|
977
|
+
formatActivityCost,
|
|
978
|
+
formatActivityDuration,
|
|
680
979
|
formatModelCost,
|
|
681
980
|
formatTokensPerSecond,
|
|
981
|
+
mergeActivityPages,
|
|
682
982
|
nextRevealCount,
|
|
683
983
|
pendingApprovalOf,
|
|
684
984
|
streamChatTurn,
|
|
685
|
-
useSmoothText
|
|
985
|
+
useSmoothText,
|
|
986
|
+
waterfallLayout
|
|
686
987
|
};
|
|
687
988
|
//# sourceMappingURL=index.js.map
|