@tangle-network/agent-app 0.22.0 → 0.24.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/{DesignCanvasEditor-YPVETLZG.js → DesignCanvasEditor-C5SOZHF5.js} +2 -2
- package/dist/{chunk-NSKJFV4Y.js → chunk-GCIQVSNW.js} +4 -17
- package/dist/chunk-GCIQVSNW.js.map +1 -0
- package/dist/chunk-XDCHKFBX.js +897 -0
- package/dist/chunk-XDCHKFBX.js.map +1 -0
- package/dist/design-canvas-react/index.d.ts +90 -4
- package/dist/design-canvas-react/index.js +354 -28
- package/dist/design-canvas-react/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +78 -0
- package/dist/sandbox/index.d.ts +183 -1
- package/dist/sandbox/index.js +54 -532
- package/dist/sandbox/index.js.map +1 -1
- package/dist/web-react/index.d.ts +62 -1
- package/dist/web-react/index.js +435 -142
- package/dist/web-react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-NSKJFV4Y.js.map +0 -1
- /package/dist/{DesignCanvasEditor-YPVETLZG.js.map → DesignCanvasEditor-C5SOZHF5.js.map} +0 -0
package/dist/web-react/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
stepActivityFlowTrace
|
|
3
3
|
} from "../chunk-AFDROJ64.js";
|
|
4
|
+
import {
|
|
5
|
+
snapHarnessToModel,
|
|
6
|
+
snapModelToHarness
|
|
7
|
+
} from "../chunk-5VXPDXZJ.js";
|
|
4
8
|
|
|
5
9
|
// src/web-react/index.tsx
|
|
6
|
-
import { useEffect as
|
|
10
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef3, useState as useState5 } from "react";
|
|
7
11
|
|
|
8
12
|
// src/web-react/provider-logo.tsx
|
|
9
13
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -451,6 +455,132 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
451
455
|
] });
|
|
452
456
|
}
|
|
453
457
|
|
|
458
|
+
// src/web-react/sandbox-terminal.ts
|
|
459
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useState as useState3 } from "react";
|
|
460
|
+
var DEFAULT_PROVISION_POLL_INTERVAL_MS = 2e3;
|
|
461
|
+
var DEFAULT_PROVISION_POLL_TIMEOUT_MS = 9e4;
|
|
462
|
+
var DEFAULT_TOKEN_REFRESH_SKEW_MS = 12e4;
|
|
463
|
+
var EMPTY_CONNECTION = {
|
|
464
|
+
runtimeUrl: null,
|
|
465
|
+
sidecarUrl: null,
|
|
466
|
+
token: null,
|
|
467
|
+
expiresAt: null,
|
|
468
|
+
status: "idle",
|
|
469
|
+
error: null,
|
|
470
|
+
loading: false
|
|
471
|
+
};
|
|
472
|
+
function useSandboxTerminalConnection(opts) {
|
|
473
|
+
const [conn, setConn] = useState3(EMPTY_CONNECTION);
|
|
474
|
+
const fetcher = opts.fetcher ?? fetch;
|
|
475
|
+
const pollIntervalMs = opts.provisionPollIntervalMs ?? DEFAULT_PROVISION_POLL_INTERVAL_MS;
|
|
476
|
+
const pollTimeoutMs = opts.provisionPollTimeoutMs ?? DEFAULT_PROVISION_POLL_TIMEOUT_MS;
|
|
477
|
+
const refreshSkewMs = opts.tokenRefreshSkewMs ?? DEFAULT_TOKEN_REFRESH_SKEW_MS;
|
|
478
|
+
const connectionUrl = useCallback2(() => {
|
|
479
|
+
if (typeof opts.connectionUrl === "function") return opts.connectionUrl(opts.workspaceId);
|
|
480
|
+
return opts.connectionUrl ?? `/api/workspaces/${encodeURIComponent(opts.workspaceId)}/sandbox/connection`;
|
|
481
|
+
}, [opts.connectionUrl, opts.workspaceId]);
|
|
482
|
+
const connect = useCallback2(async () => {
|
|
483
|
+
setConn((current) => ({ ...current, loading: true, error: null }));
|
|
484
|
+
const deadline = Date.now() + pollTimeoutMs;
|
|
485
|
+
while (true) {
|
|
486
|
+
try {
|
|
487
|
+
const res = await fetcher(connectionUrl());
|
|
488
|
+
const data = await res.json();
|
|
489
|
+
const runtimeUrl = data.runtimeUrl ?? data.sidecarUrl;
|
|
490
|
+
if (res.ok && runtimeUrl && data.token && data.expiresAt) {
|
|
491
|
+
setConn({
|
|
492
|
+
runtimeUrl,
|
|
493
|
+
sidecarUrl: runtimeUrl,
|
|
494
|
+
token: data.token,
|
|
495
|
+
expiresAt: data.expiresAt,
|
|
496
|
+
status: data.status ?? "running",
|
|
497
|
+
error: null,
|
|
498
|
+
loading: false,
|
|
499
|
+
...data.sandboxId ? { sandboxId: data.sandboxId } : {}
|
|
500
|
+
});
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (res.ok) {
|
|
504
|
+
setConn({
|
|
505
|
+
runtimeUrl: null,
|
|
506
|
+
sidecarUrl: null,
|
|
507
|
+
token: null,
|
|
508
|
+
expiresAt: null,
|
|
509
|
+
loading: false,
|
|
510
|
+
error: "Sandbox connection response is missing required fields",
|
|
511
|
+
status: data.status ?? "error",
|
|
512
|
+
...data.sandboxId ? { sandboxId: data.sandboxId } : {}
|
|
513
|
+
});
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (res.status === 503 && Date.now() < deadline) {
|
|
517
|
+
setConn((current) => ({
|
|
518
|
+
...current,
|
|
519
|
+
loading: true,
|
|
520
|
+
status: data.status ?? "provisioning",
|
|
521
|
+
error: null
|
|
522
|
+
}));
|
|
523
|
+
await sleep(pollIntervalMs);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
setConn((current) => ({
|
|
527
|
+
...current,
|
|
528
|
+
runtimeUrl: null,
|
|
529
|
+
sidecarUrl: null,
|
|
530
|
+
token: null,
|
|
531
|
+
expiresAt: null,
|
|
532
|
+
loading: false,
|
|
533
|
+
error: data.error ?? "Sandbox not available",
|
|
534
|
+
status: data.status ?? "error"
|
|
535
|
+
}));
|
|
536
|
+
return;
|
|
537
|
+
} catch (err) {
|
|
538
|
+
if (Date.now() < deadline) {
|
|
539
|
+
await sleep(pollIntervalMs);
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
setConn((current) => ({
|
|
543
|
+
...current,
|
|
544
|
+
runtimeUrl: null,
|
|
545
|
+
sidecarUrl: null,
|
|
546
|
+
token: null,
|
|
547
|
+
expiresAt: null,
|
|
548
|
+
loading: false,
|
|
549
|
+
error: err instanceof Error ? err.message : "Connection failed"
|
|
550
|
+
}));
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}, [connectionUrl, fetcher, pollIntervalMs, pollTimeoutMs]);
|
|
555
|
+
useEffect3(() => {
|
|
556
|
+
void connect();
|
|
557
|
+
}, [connect]);
|
|
558
|
+
useEffect3(() => {
|
|
559
|
+
if (!conn.runtimeUrl || !conn.token || !conn.expiresAt) return;
|
|
560
|
+
const refreshAt = Date.parse(conn.expiresAt) - Date.now() - refreshSkewMs;
|
|
561
|
+
if (!Number.isFinite(refreshAt)) {
|
|
562
|
+
setConn((current) => ({
|
|
563
|
+
...current,
|
|
564
|
+
runtimeUrl: null,
|
|
565
|
+
sidecarUrl: null,
|
|
566
|
+
token: null,
|
|
567
|
+
expiresAt: null,
|
|
568
|
+
status: "error",
|
|
569
|
+
error: "Sandbox token expiry is invalid"
|
|
570
|
+
}));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const timer = window.setTimeout(() => {
|
|
574
|
+
void connect();
|
|
575
|
+
}, Math.max(1e3, refreshAt));
|
|
576
|
+
return () => window.clearTimeout(timer);
|
|
577
|
+
}, [conn.runtimeUrl, conn.token, conn.expiresAt, connect, refreshSkewMs]);
|
|
578
|
+
return { ...conn, connect };
|
|
579
|
+
}
|
|
580
|
+
function sleep(ms) {
|
|
581
|
+
return new Promise((resolve) => window.setTimeout(resolve, ms));
|
|
582
|
+
}
|
|
583
|
+
|
|
454
584
|
// src/web-react/seat-paywall.tsx
|
|
455
585
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
456
586
|
function CheckGlyph() {
|
|
@@ -527,23 +657,184 @@ function SeatPaywall({
|
|
|
527
657
|
] }) });
|
|
528
658
|
}
|
|
529
659
|
|
|
530
|
-
// src/web-react/
|
|
531
|
-
import {
|
|
660
|
+
// src/web-react/agent-session-controls.tsx
|
|
661
|
+
import { useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState4 } from "react";
|
|
662
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
663
|
+
var HARNESS_LABELS = {
|
|
664
|
+
opencode: "OpenCode (any model)",
|
|
665
|
+
"claude-code": "Claude Code (Anthropic)",
|
|
666
|
+
codex: "Codex (OpenAI)",
|
|
667
|
+
"kimi-code": "Kimi (Moonshot)",
|
|
668
|
+
amp: "Amp",
|
|
669
|
+
"factory-droids": "Factory Droids",
|
|
670
|
+
cursor: "Cursor",
|
|
671
|
+
hermes: "Hermes",
|
|
672
|
+
forge: "Forge",
|
|
673
|
+
pi: "Pi",
|
|
674
|
+
openclaw: "OpenClaw",
|
|
675
|
+
acp: "ACP",
|
|
676
|
+
"cli-base": "CLI"
|
|
677
|
+
};
|
|
678
|
+
function harnessLabel(h) {
|
|
679
|
+
return HARNESS_LABELS[h] ?? h;
|
|
680
|
+
}
|
|
532
681
|
function ChevronDown({ className }) {
|
|
533
682
|
return /* @__PURE__ */ jsx4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" }) });
|
|
534
683
|
}
|
|
535
|
-
function
|
|
684
|
+
function GearGlyph({ className }) {
|
|
536
685
|
return /* @__PURE__ */ jsxs4("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
537
|
-
/* @__PURE__ */ jsx4("circle", { cx: "
|
|
538
|
-
/* @__PURE__ */ jsx4("path", { d: "
|
|
686
|
+
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "3" }),
|
|
687
|
+
/* @__PURE__ */ jsx4("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
|
|
688
|
+
] });
|
|
689
|
+
}
|
|
690
|
+
function useClickOutside(active, onOutside) {
|
|
691
|
+
const ref = useRef2(null);
|
|
692
|
+
useEffect4(() => {
|
|
693
|
+
if (!active) return;
|
|
694
|
+
function handler(e) {
|
|
695
|
+
if (ref.current && !ref.current.contains(e.target)) onOutside();
|
|
696
|
+
}
|
|
697
|
+
document.addEventListener("mousedown", handler);
|
|
698
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
699
|
+
}, [active, onOutside]);
|
|
700
|
+
return ref;
|
|
701
|
+
}
|
|
702
|
+
function HarnessPicker({
|
|
703
|
+
value,
|
|
704
|
+
onChange,
|
|
705
|
+
available
|
|
706
|
+
}) {
|
|
707
|
+
const [open, setOpen] = useState4(false);
|
|
708
|
+
const containerRef = useClickOutside(open, () => setOpen(false));
|
|
709
|
+
const options = available ?? Object.keys(HARNESS_LABELS);
|
|
710
|
+
return /* @__PURE__ */ jsxs4("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
711
|
+
/* @__PURE__ */ jsxs4(
|
|
712
|
+
"button",
|
|
713
|
+
{
|
|
714
|
+
type: "button",
|
|
715
|
+
onClick: () => setOpen((v) => !v),
|
|
716
|
+
title: "Agent backend",
|
|
717
|
+
className: "inline-flex w-full items-center justify-between gap-1.5 rounded-lg border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30",
|
|
718
|
+
children: [
|
|
719
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate", children: harnessLabel(value) }),
|
|
720
|
+
/* @__PURE__ */ jsx4(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
),
|
|
724
|
+
open && /* @__PURE__ */ jsx4("div", { className: "absolute bottom-full left-0 z-50 mb-2 max-h-64 w-full min-w-[220px] overflow-y-auto rounded-xl border border-border bg-card p-1 shadow-lg", children: options.map((h) => /* @__PURE__ */ jsx4(
|
|
725
|
+
"button",
|
|
726
|
+
{
|
|
727
|
+
type: "button",
|
|
728
|
+
onClick: () => {
|
|
729
|
+
onChange(h);
|
|
730
|
+
setOpen(false);
|
|
731
|
+
},
|
|
732
|
+
className: `flex w-full items-center rounded-md px-3 py-2 text-left text-sm transition ${h === value ? "bg-primary/10 font-medium" : "hover:bg-accent/30"}`,
|
|
733
|
+
children: harnessLabel(h)
|
|
734
|
+
},
|
|
735
|
+
h
|
|
736
|
+
)) })
|
|
737
|
+
] });
|
|
738
|
+
}
|
|
739
|
+
function useCoherentHandlers(props) {
|
|
740
|
+
const { model, models, harness, onModelChange, onHarnessChange } = props;
|
|
741
|
+
const canonicalIds = useMemo(() => models.map((m) => m.id), [models]);
|
|
742
|
+
const onModel = (next) => {
|
|
743
|
+
onModelChange(next);
|
|
744
|
+
const nextHarness = snapHarnessToModel(harness, next);
|
|
745
|
+
if (nextHarness !== harness) onHarnessChange(nextHarness);
|
|
746
|
+
};
|
|
747
|
+
const onHarness = (next) => {
|
|
748
|
+
onHarnessChange(next);
|
|
749
|
+
const snapped = snapModelToHarness(next, model, canonicalIds);
|
|
750
|
+
if (snapped !== model) onModelChange(snapped);
|
|
751
|
+
};
|
|
752
|
+
return { onModel, onHarness };
|
|
753
|
+
}
|
|
754
|
+
function AgentSessionControls(props) {
|
|
755
|
+
const {
|
|
756
|
+
models,
|
|
757
|
+
modelsLoading,
|
|
758
|
+
model,
|
|
759
|
+
harness,
|
|
760
|
+
availableHarnesses,
|
|
761
|
+
effort,
|
|
762
|
+
onEffortChange,
|
|
763
|
+
layout = "inline",
|
|
764
|
+
showHarness = true,
|
|
765
|
+
renderProviderBadge,
|
|
766
|
+
className
|
|
767
|
+
} = props;
|
|
768
|
+
const { onModel, onHarness } = useCoherentHandlers(props);
|
|
769
|
+
const [open, setOpen] = useState4(false);
|
|
770
|
+
const popoverRef = useClickOutside(open, () => setOpen(false));
|
|
771
|
+
const selectedModel = models.find((m) => m.id === model);
|
|
772
|
+
const showEffort = selectedModel?.supportsReasoning ?? true;
|
|
773
|
+
const modelPicker = /* @__PURE__ */ jsx4(
|
|
774
|
+
ModelPicker,
|
|
775
|
+
{
|
|
776
|
+
value: model,
|
|
777
|
+
onChange: onModel,
|
|
778
|
+
models,
|
|
779
|
+
loading: modelsLoading,
|
|
780
|
+
renderProviderBadge
|
|
781
|
+
}
|
|
782
|
+
);
|
|
783
|
+
if (layout === "inline") {
|
|
784
|
+
return /* @__PURE__ */ jsxs4("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
785
|
+
modelPicker,
|
|
786
|
+
showHarness && /* @__PURE__ */ jsx4(HarnessPicker, { value: harness, onChange: onHarness, available: availableHarnesses }),
|
|
787
|
+
showEffort && /* @__PURE__ */ jsx4(EffortPicker, { value: effort, onChange: onEffortChange })
|
|
788
|
+
] });
|
|
789
|
+
}
|
|
790
|
+
const hasAdvanced = showHarness || showEffort;
|
|
791
|
+
return /* @__PURE__ */ jsxs4("div", { className: `flex items-center gap-1.5 ${className ?? ""}`, children: [
|
|
792
|
+
modelPicker,
|
|
793
|
+
hasAdvanced && /* @__PURE__ */ jsxs4("div", { ref: popoverRef, className: "relative inline-flex", children: [
|
|
794
|
+
/* @__PURE__ */ jsx4(
|
|
795
|
+
"button",
|
|
796
|
+
{
|
|
797
|
+
type: "button",
|
|
798
|
+
onClick: () => setOpen((v) => !v),
|
|
799
|
+
title: "Model settings \u2014 pick the agent backend and how hard it thinks",
|
|
800
|
+
className: "flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground data-[state=open]:bg-muted",
|
|
801
|
+
"data-state": open ? "open" : "closed",
|
|
802
|
+
children: /* @__PURE__ */ jsx4(GearGlyph, { className: "h-4 w-4" })
|
|
803
|
+
}
|
|
804
|
+
),
|
|
805
|
+
open && /* @__PURE__ */ jsxs4("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-72 space-y-3 rounded-xl border border-border bg-card p-3 shadow-lg", children: [
|
|
806
|
+
showHarness && /* @__PURE__ */ jsxs4("div", { className: "space-y-1.5", children: [
|
|
807
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs font-medium text-foreground", children: "Agent backend" }),
|
|
808
|
+
/* @__PURE__ */ jsx4(HarnessPicker, { value: harness, onChange: onHarness, available: availableHarnesses }),
|
|
809
|
+
/* @__PURE__ */ jsx4("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "The engine that runs the agent. Switching it keeps your model choice compatible." })
|
|
810
|
+
] }),
|
|
811
|
+
showEffort && /* @__PURE__ */ jsxs4("div", { className: "space-y-1.5", children: [
|
|
812
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs font-medium text-foreground", children: "Reasoning effort" }),
|
|
813
|
+
/* @__PURE__ */ jsx4(EffortPicker, { value: effort, onChange: onEffortChange }),
|
|
814
|
+
/* @__PURE__ */ jsx4("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "How hard the agent thinks before answering. Higher is slower but more thorough." })
|
|
815
|
+
] })
|
|
816
|
+
] })
|
|
817
|
+
] })
|
|
818
|
+
] });
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/web-react/index.tsx
|
|
822
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
823
|
+
function ChevronDown2({ className }) {
|
|
824
|
+
return /* @__PURE__ */ jsx5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx5("path", { d: "m6 9 6 6 6-6" }) });
|
|
825
|
+
}
|
|
826
|
+
function SearchGlyph({ className }) {
|
|
827
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
828
|
+
/* @__PURE__ */ jsx5("circle", { cx: "11", cy: "11", r: "8" }),
|
|
829
|
+
/* @__PURE__ */ jsx5("path", { d: "m21 21-4.3-4.3" })
|
|
539
830
|
] });
|
|
540
831
|
}
|
|
541
832
|
function SparkleGlyph({ className }) {
|
|
542
|
-
return /* @__PURE__ */
|
|
833
|
+
return /* @__PURE__ */ jsx5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx5("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" }) });
|
|
543
834
|
}
|
|
544
|
-
function
|
|
545
|
-
const ref =
|
|
546
|
-
|
|
835
|
+
function useClickOutside2(onOutside) {
|
|
836
|
+
const ref = useRef3(null);
|
|
837
|
+
useEffect5(() => {
|
|
547
838
|
function handler(e) {
|
|
548
839
|
if (ref.current && !ref.current.contains(e.target)) onOutside();
|
|
549
840
|
}
|
|
@@ -578,7 +869,7 @@ function formatContext(len) {
|
|
|
578
869
|
return `${len} ctx`;
|
|
579
870
|
}
|
|
580
871
|
function SectionHeader({ children }) {
|
|
581
|
-
return /* @__PURE__ */
|
|
872
|
+
return /* @__PURE__ */ jsx5("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground/70", children });
|
|
582
873
|
}
|
|
583
874
|
function ModelRow({
|
|
584
875
|
model,
|
|
@@ -588,41 +879,41 @@ function ModelRow({
|
|
|
588
879
|
}) {
|
|
589
880
|
const price = formatPrice(model.pricing?.prompt);
|
|
590
881
|
const ctx = formatContext(model.contextLength);
|
|
591
|
-
return /* @__PURE__ */
|
|
882
|
+
return /* @__PURE__ */ jsxs5(
|
|
592
883
|
"button",
|
|
593
884
|
{
|
|
594
885
|
type: "button",
|
|
595
886
|
onClick: onSelect,
|
|
596
887
|
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"}`,
|
|
597
888
|
children: [
|
|
598
|
-
renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */
|
|
599
|
-
/* @__PURE__ */
|
|
600
|
-
!model.supportsTools && /* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
ctx && /* @__PURE__ */
|
|
603
|
-
price && /* @__PURE__ */
|
|
889
|
+
renderProviderBadge ? renderProviderBadge(model.provider) : /* @__PURE__ */ jsx5(ProviderLogo, { provider: model.provider, size: 16 }),
|
|
890
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: model.name }),
|
|
891
|
+
!model.supportsTools && /* @__PURE__ */ jsx5("span", { className: "shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: "no tools" }),
|
|
892
|
+
/* @__PURE__ */ jsxs5("span", { className: "ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground", children: [
|
|
893
|
+
ctx && /* @__PURE__ */ jsx5("span", { children: ctx }),
|
|
894
|
+
price && /* @__PURE__ */ jsx5("span", { children: price })
|
|
604
895
|
] })
|
|
605
896
|
]
|
|
606
897
|
}
|
|
607
898
|
);
|
|
608
899
|
}
|
|
609
900
|
function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel = "Recommended" }) {
|
|
610
|
-
const [open, setOpen] =
|
|
611
|
-
const [query, setQuery] =
|
|
612
|
-
const containerRef =
|
|
613
|
-
const inputRef =
|
|
614
|
-
|
|
901
|
+
const [open, setOpen] = useState5(false);
|
|
902
|
+
const [query, setQuery] = useState5("");
|
|
903
|
+
const containerRef = useClickOutside2(() => setOpen(false));
|
|
904
|
+
const inputRef = useRef3(null);
|
|
905
|
+
useEffect5(() => {
|
|
615
906
|
if (open) inputRef.current?.focus();
|
|
616
907
|
}, [open]);
|
|
617
908
|
const selected = models.find((m) => m.id === value);
|
|
618
|
-
const filtered =
|
|
909
|
+
const filtered = useMemo2(() => {
|
|
619
910
|
const q = query.trim().toLowerCase();
|
|
620
911
|
if (!q) return null;
|
|
621
912
|
return models.filter(
|
|
622
913
|
(m) => m.id.toLowerCase().includes(q) || m.name.toLowerCase().includes(q) || (m.description?.toLowerCase() ?? "").includes(q) || m.provider.toLowerCase().includes(q)
|
|
623
914
|
);
|
|
624
915
|
}, [models, query]);
|
|
625
|
-
const sections =
|
|
916
|
+
const sections = useMemo2(() => {
|
|
626
917
|
const recommended = models.filter((m) => m.featured);
|
|
627
918
|
const byProvider = [];
|
|
628
919
|
for (const m of models) {
|
|
@@ -638,24 +929,24 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
|
|
|
638
929
|
setOpen(false);
|
|
639
930
|
setQuery("");
|
|
640
931
|
};
|
|
641
|
-
return /* @__PURE__ */
|
|
642
|
-
/* @__PURE__ */
|
|
932
|
+
return /* @__PURE__ */ jsxs5("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
933
|
+
/* @__PURE__ */ jsxs5(
|
|
643
934
|
"button",
|
|
644
935
|
{
|
|
645
936
|
type: "button",
|
|
646
937
|
onClick: () => setOpen((v) => !v),
|
|
647
938
|
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",
|
|
648
939
|
children: [
|
|
649
|
-
selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */
|
|
650
|
-
/* @__PURE__ */
|
|
651
|
-
/* @__PURE__ */
|
|
940
|
+
selected ? renderProviderBadge ? renderProviderBadge(selected.provider) : /* @__PURE__ */ jsx5(ProviderLogo, { provider: selected.provider, size: 16 }) : /* @__PURE__ */ jsx5(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
941
|
+
/* @__PURE__ */ jsx5("span", { className: "max-w-[160px] truncate", children: selected?.name ?? value }),
|
|
942
|
+
/* @__PURE__ */ jsx5(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
652
943
|
]
|
|
653
944
|
}
|
|
654
945
|
),
|
|
655
|
-
open && /* @__PURE__ */
|
|
656
|
-
/* @__PURE__ */
|
|
657
|
-
/* @__PURE__ */
|
|
658
|
-
/* @__PURE__ */
|
|
946
|
+
open && /* @__PURE__ */ jsxs5("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: [
|
|
947
|
+
/* @__PURE__ */ jsx5("div", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-2", children: [
|
|
948
|
+
/* @__PURE__ */ jsx5(SearchGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
949
|
+
/* @__PURE__ */ jsx5(
|
|
659
950
|
"input",
|
|
660
951
|
{
|
|
661
952
|
ref: inputRef,
|
|
@@ -667,20 +958,20 @@ function ModelPicker({ value, onChange, models, loading, renderProviderBadge, re
|
|
|
667
958
|
}
|
|
668
959
|
)
|
|
669
960
|
] }) }),
|
|
670
|
-
/* @__PURE__ */
|
|
671
|
-
loading && /* @__PURE__ */
|
|
672
|
-
!loading && filtered && /* @__PURE__ */
|
|
673
|
-
filtered.length === 0 && /* @__PURE__ */
|
|
674
|
-
filtered.map((m) => /* @__PURE__ */
|
|
961
|
+
/* @__PURE__ */ jsxs5("div", { className: "max-h-[400px] overflow-y-auto p-1 pb-2", children: [
|
|
962
|
+
loading && /* @__PURE__ */ jsx5("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading models..." }),
|
|
963
|
+
!loading && filtered && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
964
|
+
filtered.length === 0 && /* @__PURE__ */ jsx5("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No models match your search" }),
|
|
965
|
+
filtered.map((m) => /* @__PURE__ */ jsx5(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
675
966
|
] }),
|
|
676
|
-
!loading && !filtered && /* @__PURE__ */
|
|
677
|
-
sections.recommended.length > 0 && /* @__PURE__ */
|
|
678
|
-
/* @__PURE__ */
|
|
679
|
-
sections.recommended.map((m) => /* @__PURE__ */
|
|
967
|
+
!loading && !filtered && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
968
|
+
sections.recommended.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
969
|
+
/* @__PURE__ */ jsx5(SectionHeader, { children: recommendedLabel }),
|
|
970
|
+
sections.recommended.map((m) => /* @__PURE__ */ jsx5(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
680
971
|
] }),
|
|
681
|
-
sections.byProvider.map((g) => /* @__PURE__ */
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
g.items.map((m) => /* @__PURE__ */
|
|
972
|
+
sections.byProvider.map((g) => /* @__PURE__ */ jsxs5("div", { children: [
|
|
973
|
+
/* @__PURE__ */ jsx5(SectionHeader, { children: g.provider }),
|
|
974
|
+
g.items.map((m) => /* @__PURE__ */ jsx5(ModelRow, { model: m, selected: m.id === value, onSelect: () => select(m.id), renderProviderBadge }, m.id))
|
|
684
975
|
] }, g.provider))
|
|
685
976
|
] })
|
|
686
977
|
] })
|
|
@@ -694,11 +985,11 @@ var EFFORT_LEVELS = [
|
|
|
694
985
|
{ id: "high", label: "High" }
|
|
695
986
|
];
|
|
696
987
|
function EffortPicker({ value, onChange }) {
|
|
697
|
-
const [open, setOpen] =
|
|
698
|
-
const containerRef =
|
|
988
|
+
const [open, setOpen] = useState5(false);
|
|
989
|
+
const containerRef = useClickOutside2(() => setOpen(false));
|
|
699
990
|
const selected = EFFORT_LEVELS.find((l) => l.id === value) ?? EFFORT_LEVELS[2];
|
|
700
|
-
return /* @__PURE__ */
|
|
701
|
-
/* @__PURE__ */
|
|
991
|
+
return /* @__PURE__ */ jsxs5("div", { ref: containerRef, className: "relative inline-flex", children: [
|
|
992
|
+
/* @__PURE__ */ jsxs5(
|
|
702
993
|
"button",
|
|
703
994
|
{
|
|
704
995
|
type: "button",
|
|
@@ -706,13 +997,13 @@ function EffortPicker({ value, onChange }) {
|
|
|
706
997
|
title: "Reasoning effort",
|
|
707
998
|
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",
|
|
708
999
|
children: [
|
|
709
|
-
/* @__PURE__ */
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
/* @__PURE__ */
|
|
1000
|
+
/* @__PURE__ */ jsx5(SparkleGlyph, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
1001
|
+
/* @__PURE__ */ jsx5("span", { children: selected.label }),
|
|
1002
|
+
/* @__PURE__ */ jsx5(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
712
1003
|
]
|
|
713
1004
|
}
|
|
714
1005
|
),
|
|
715
|
-
open && /* @__PURE__ */
|
|
1006
|
+
open && /* @__PURE__ */ jsx5("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__ */ jsx5(
|
|
716
1007
|
"button",
|
|
717
1008
|
{
|
|
718
1009
|
type: "button",
|
|
@@ -728,41 +1019,41 @@ function EffortPicker({ value, onChange }) {
|
|
|
728
1019
|
] });
|
|
729
1020
|
}
|
|
730
1021
|
function RunDrillIn({ run, onClose }) {
|
|
731
|
-
return /* @__PURE__ */
|
|
732
|
-
/* @__PURE__ */
|
|
733
|
-
/* @__PURE__ */
|
|
1022
|
+
return /* @__PURE__ */ jsxs5("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: [
|
|
1023
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
1024
|
+
/* @__PURE__ */ jsx5(
|
|
734
1025
|
"span",
|
|
735
1026
|
{
|
|
736
1027
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-yellow-500" : run.status === "error" ? "bg-red-500" : "bg-green-500"}`
|
|
737
1028
|
}
|
|
738
1029
|
),
|
|
739
|
-
/* @__PURE__ */
|
|
740
|
-
/* @__PURE__ */
|
|
741
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1", children: [
|
|
1031
|
+
/* @__PURE__ */ jsx5("p", { className: "truncate text-sm font-semibold", children: run.title }),
|
|
1032
|
+
/* @__PURE__ */ jsx5("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: run.toolName })
|
|
742
1033
|
] }),
|
|
743
|
-
/* @__PURE__ */
|
|
1034
|
+
/* @__PURE__ */ jsx5(
|
|
744
1035
|
"button",
|
|
745
1036
|
{
|
|
746
1037
|
type: "button",
|
|
747
1038
|
onClick: onClose,
|
|
748
1039
|
"aria-label": "Close",
|
|
749
1040
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground",
|
|
750
|
-
children: /* @__PURE__ */
|
|
1041
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
751
1042
|
}
|
|
752
1043
|
)
|
|
753
1044
|
] }),
|
|
754
|
-
/* @__PURE__ */
|
|
755
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
756
|
-
run.steps.map((step, i) => /* @__PURE__ */
|
|
757
|
-
/* @__PURE__ */
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
/* @__PURE__ */
|
|
1045
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
|
|
1046
|
+
run.steps.length === 0 && /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
|
|
1047
|
+
run.steps.map((step, i) => /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-border/60 bg-background", children: [
|
|
1048
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5", children: [
|
|
1049
|
+
/* @__PURE__ */ jsx5("span", { className: `font-mono text-[11px] ${step.status === "error" ? "text-red-600" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
|
|
1050
|
+
/* @__PURE__ */ jsx5("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
|
|
1051
|
+
/* @__PURE__ */ jsx5("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: new Date(step.at).toLocaleTimeString() })
|
|
761
1052
|
] }),
|
|
762
|
-
step.detail && /* @__PURE__ */
|
|
1053
|
+
step.detail && /* @__PURE__ */ jsx5("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 })
|
|
763
1054
|
] }, i))
|
|
764
1055
|
] }),
|
|
765
|
-
/* @__PURE__ */
|
|
1056
|
+
/* @__PURE__ */ jsx5("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." })
|
|
766
1057
|
] });
|
|
767
1058
|
}
|
|
768
1059
|
function pendingApprovalOf(call) {
|
|
@@ -772,26 +1063,26 @@ function pendingApprovalOf(call) {
|
|
|
772
1063
|
}
|
|
773
1064
|
function ToolGlyph({ name, className }) {
|
|
774
1065
|
if (name.startsWith("sandbox_")) {
|
|
775
|
-
return /* @__PURE__ */
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
1066
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1067
|
+
/* @__PURE__ */ jsx5("polyline", { points: "4 17 10 11 4 5" }),
|
|
1068
|
+
/* @__PURE__ */ jsx5("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
|
|
778
1069
|
] });
|
|
779
1070
|
}
|
|
780
1071
|
if (name === "submit_proposal") {
|
|
781
|
-
return /* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
783
|
-
/* @__PURE__ */
|
|
1072
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1073
|
+
/* @__PURE__ */ jsx5("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1074
|
+
/* @__PURE__ */ jsx5("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
|
|
784
1075
|
] });
|
|
785
1076
|
}
|
|
786
1077
|
if (name === "schedule_followup") {
|
|
787
|
-
return /* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
789
|
-
/* @__PURE__ */
|
|
1078
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
|
|
1079
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "9" }),
|
|
1080
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 7v5l3 3" })
|
|
790
1081
|
] });
|
|
791
1082
|
}
|
|
792
|
-
return /* @__PURE__ */
|
|
793
|
-
/* @__PURE__ */
|
|
794
|
-
/* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1084
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
|
|
1085
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "4" })
|
|
795
1086
|
] });
|
|
796
1087
|
}
|
|
797
1088
|
function toolOutcomeOf(call) {
|
|
@@ -825,36 +1116,36 @@ function truncate(v, max = 240) {
|
|
|
825
1116
|
function KvRows({ data }) {
|
|
826
1117
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
827
1118
|
if (!entries.length) return null;
|
|
828
|
-
return /* @__PURE__ */
|
|
829
|
-
/* @__PURE__ */
|
|
830
|
-
/* @__PURE__ */
|
|
1119
|
+
return /* @__PURE__ */ jsx5("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs5("div", { className: "contents", children: [
|
|
1120
|
+
/* @__PURE__ */ jsx5("dt", { className: "font-mono text-[11px] text-muted-foreground/70", children: k }),
|
|
1121
|
+
/* @__PURE__ */ jsx5("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-[11px] text-muted-foreground", children: truncate(v) })
|
|
831
1122
|
] }, k)) });
|
|
832
1123
|
}
|
|
833
1124
|
function ShellDetail({ call }) {
|
|
834
1125
|
const outcome = toolOutcomeOf(call);
|
|
835
1126
|
const r = outcome?.result ?? {};
|
|
836
|
-
return /* @__PURE__ */
|
|
837
|
-
/* @__PURE__ */
|
|
838
|
-
/* @__PURE__ */
|
|
839
|
-
/* @__PURE__ */
|
|
840
|
-
r.exitCode != null && /* @__PURE__ */
|
|
1127
|
+
return /* @__PURE__ */ jsxs5("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-[11px] leading-relaxed", children: [
|
|
1128
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
|
|
1129
|
+
/* @__PURE__ */ jsx5("span", { className: "select-none text-zinc-500", children: "$" }),
|
|
1130
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
|
|
1131
|
+
r.exitCode != null && /* @__PURE__ */ jsxs5("span", { className: r.exitCode === 0 ? "text-emerald-400" : "text-red-400", children: [
|
|
841
1132
|
"exit ",
|
|
842
1133
|
r.exitCode
|
|
843
1134
|
] })
|
|
844
1135
|
] }),
|
|
845
|
-
/* @__PURE__ */
|
|
1136
|
+
/* @__PURE__ */ jsx5("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)" })
|
|
846
1137
|
] });
|
|
847
1138
|
}
|
|
848
1139
|
function DefaultToolDetail({ call }) {
|
|
849
1140
|
const outcome = toolOutcomeOf(call);
|
|
850
|
-
return /* @__PURE__ */
|
|
851
|
-
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */
|
|
852
|
-
/* @__PURE__ */
|
|
853
|
-
/* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
1142
|
+
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs5("div", { children: [
|
|
1143
|
+
/* @__PURE__ */ jsx5("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/50", children: "Called with" }),
|
|
1144
|
+
/* @__PURE__ */ jsx5(KvRows, { data: call.args })
|
|
854
1145
|
] }),
|
|
855
|
-
outcome && /* @__PURE__ */
|
|
856
|
-
/* @__PURE__ */
|
|
857
|
-
outcome.ok === false ? /* @__PURE__ */
|
|
1146
|
+
outcome && /* @__PURE__ */ jsxs5("div", { children: [
|
|
1147
|
+
/* @__PURE__ */ jsx5("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/50", children: outcome.ok === false ? "Failed" : "Result" }),
|
|
1148
|
+
outcome.ok === false ? /* @__PURE__ */ jsx5("p", { className: "text-xs text-red-600", children: outcome.message ?? "Tool failed" }) : outcome.result && typeof outcome.result === "object" ? /* @__PURE__ */ jsx5(KvRows, { data: outcome.result }) : /* @__PURE__ */ jsx5("p", { className: "font-mono text-[11px] text-muted-foreground", children: truncate(outcome.result) })
|
|
858
1149
|
] })
|
|
859
1150
|
] });
|
|
860
1151
|
}
|
|
@@ -865,32 +1156,32 @@ function ToolCallCard({
|
|
|
865
1156
|
onOpenRun,
|
|
866
1157
|
renderers
|
|
867
1158
|
}) {
|
|
868
|
-
const [expanded, setExpanded] =
|
|
1159
|
+
const [expanded, setExpanded] = useState5(false);
|
|
869
1160
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
870
1161
|
const failed = call.status === "error" || toolOutcomeOf(call)?.ok === false;
|
|
871
1162
|
const custom = renderers?.[call.name]?.(call, message);
|
|
872
|
-
return /* @__PURE__ */
|
|
1163
|
+
return /* @__PURE__ */ jsxs5(
|
|
873
1164
|
"div",
|
|
874
1165
|
{
|
|
875
1166
|
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"}`,
|
|
876
1167
|
children: [
|
|
877
|
-
/* @__PURE__ */
|
|
1168
|
+
/* @__PURE__ */ jsxs5(
|
|
878
1169
|
"button",
|
|
879
1170
|
{
|
|
880
1171
|
type: "button",
|
|
881
1172
|
onClick: () => setExpanded((v) => !v),
|
|
882
1173
|
className: "flex w-full items-center gap-2 px-3 py-2 text-left",
|
|
883
1174
|
children: [
|
|
884
|
-
/* @__PURE__ */
|
|
1175
|
+
/* @__PURE__ */ jsx5(
|
|
885
1176
|
"span",
|
|
886
1177
|
{
|
|
887
1178
|
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"}`
|
|
888
1179
|
}
|
|
889
1180
|
),
|
|
890
|
-
/* @__PURE__ */
|
|
891
|
-
/* @__PURE__ */
|
|
892
|
-
pending && approval && /* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */
|
|
1181
|
+
/* @__PURE__ */ jsx5(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
1182
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate font-medium", children: friendlyToolTitle(call) }),
|
|
1183
|
+
pending && approval && /* @__PURE__ */ jsxs5("span", { className: "flex shrink-0 items-center gap-1", onClick: (e) => e.stopPropagation(), children: [
|
|
1184
|
+
/* @__PURE__ */ jsx5(
|
|
894
1185
|
"button",
|
|
895
1186
|
{
|
|
896
1187
|
type: "button",
|
|
@@ -899,7 +1190,7 @@ function ToolCallCard({
|
|
|
899
1190
|
children: "Approve"
|
|
900
1191
|
}
|
|
901
1192
|
),
|
|
902
|
-
/* @__PURE__ */
|
|
1193
|
+
/* @__PURE__ */ jsx5(
|
|
903
1194
|
"button",
|
|
904
1195
|
{
|
|
905
1196
|
type: "button",
|
|
@@ -909,14 +1200,14 @@ function ToolCallCard({
|
|
|
909
1200
|
}
|
|
910
1201
|
)
|
|
911
1202
|
] }),
|
|
912
|
-
/* @__PURE__ */
|
|
913
|
-
/* @__PURE__ */
|
|
1203
|
+
/* @__PURE__ */ jsx5("span", { className: "shrink-0 text-[11px] text-muted-foreground/70", children: call.status === "running" ? "running\u2026" : pending ? "awaiting approval" : failed ? "failed" : "done" }),
|
|
1204
|
+
/* @__PURE__ */ jsx5(ChevronDown2, { className: `h-3 w-3 shrink-0 text-muted-foreground transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
914
1205
|
]
|
|
915
1206
|
}
|
|
916
1207
|
),
|
|
917
|
-
expanded && /* @__PURE__ */
|
|
918
|
-
custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */
|
|
919
|
-
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */
|
|
1208
|
+
expanded && /* @__PURE__ */ jsxs5("div", { className: "border-t border-border/40 px-3 py-2.5", children: [
|
|
1209
|
+
custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx5(ShellDetail, { call }) : /* @__PURE__ */ jsx5(DefaultToolDetail, { call })),
|
|
1210
|
+
onOpenRun && call.name.startsWith("sandbox_") && /* @__PURE__ */ jsx5(
|
|
920
1211
|
"button",
|
|
921
1212
|
{
|
|
922
1213
|
type: "button",
|
|
@@ -943,35 +1234,35 @@ function AssistantMessage({
|
|
|
943
1234
|
}) {
|
|
944
1235
|
const content = useSmoothText(msg.content, streaming);
|
|
945
1236
|
const reasoning = useSmoothText(msg.reasoning ?? "", streaming);
|
|
946
|
-
const reasoningScrollRef =
|
|
947
|
-
const thinkStartRef =
|
|
948
|
-
const thinkMsRef =
|
|
1237
|
+
const reasoningScrollRef = useRef3(null);
|
|
1238
|
+
const thinkStartRef = useRef3(null);
|
|
1239
|
+
const thinkMsRef = useRef3(null);
|
|
949
1240
|
if (streaming && reasoning && !content && thinkStartRef.current === null) {
|
|
950
1241
|
thinkStartRef.current = performance.now();
|
|
951
1242
|
}
|
|
952
1243
|
if (content && thinkStartRef.current !== null && thinkMsRef.current === null) {
|
|
953
1244
|
thinkMsRef.current = performance.now() - thinkStartRef.current;
|
|
954
1245
|
}
|
|
955
|
-
|
|
1246
|
+
useEffect5(() => {
|
|
956
1247
|
const el = reasoningScrollRef.current;
|
|
957
1248
|
if (el && streaming && !content) el.scrollTop = el.scrollHeight;
|
|
958
1249
|
}, [reasoning, streaming, content]);
|
|
959
|
-
return /* @__PURE__ */
|
|
960
|
-
/* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
962
|
-
msg.modelUsed && /* @__PURE__ */
|
|
963
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
964
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
1250
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
1251
|
+
/* @__PURE__ */ jsxs5("div", { className: "mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground/60", children: [
|
|
1252
|
+
/* @__PURE__ */ jsx5("span", { className: "font-semibold uppercase", children: agentLabel }),
|
|
1253
|
+
msg.modelUsed && /* @__PURE__ */ jsx5("span", { className: "font-mono normal-case", children: msg.modelUsed }),
|
|
1254
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx5("span", { children: formatTokensPerSecond(msg) }),
|
|
1255
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx5("span", { children: formatModelCost(msg, models) })
|
|
965
1256
|
] }),
|
|
966
|
-
reasoning && /* @__PURE__ */
|
|
967
|
-
/* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
1257
|
+
reasoning && /* @__PURE__ */ jsxs5("details", { className: "mb-2 rounded-lg border-l-2 border-border/70 bg-muted/20 px-3 py-2", open: !content, children: [
|
|
1258
|
+
/* @__PURE__ */ jsx5("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !content ? /* @__PURE__ */ jsx5("span", { className: "animate-pulse", children: "Thinking\u2026" }) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process" }),
|
|
1259
|
+
/* @__PURE__ */ jsx5("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 })
|
|
969
1260
|
] }),
|
|
970
|
-
/* @__PURE__ */
|
|
1261
|
+
/* @__PURE__ */ jsxs5("div", { className: "text-base leading-[1.75]", children: [
|
|
971
1262
|
renderBody(content),
|
|
972
|
-
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */
|
|
1263
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx5("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 })
|
|
973
1264
|
] }),
|
|
974
|
-
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */
|
|
1265
|
+
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx5("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx5(
|
|
975
1266
|
ToolCallCard,
|
|
976
1267
|
{
|
|
977
1268
|
call: tc,
|
|
@@ -986,15 +1277,15 @@ function AssistantMessage({
|
|
|
986
1277
|
] });
|
|
987
1278
|
}
|
|
988
1279
|
function ThinkingRow({ agentLabel }) {
|
|
989
|
-
const [seconds, setSeconds] =
|
|
990
|
-
|
|
1280
|
+
const [seconds, setSeconds] = useState5(0);
|
|
1281
|
+
useEffect5(() => {
|
|
991
1282
|
const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
|
|
992
1283
|
return () => clearInterval(id);
|
|
993
1284
|
}, []);
|
|
994
|
-
return /* @__PURE__ */
|
|
995
|
-
/* @__PURE__ */
|
|
996
|
-
/* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
1286
|
+
/* @__PURE__ */ jsx5("p", { className: "mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: agentLabel }),
|
|
1287
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 text-base text-muted-foreground", children: [
|
|
1288
|
+
/* @__PURE__ */ jsx5("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx5("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
|
|
998
1289
|
"Thinking",
|
|
999
1290
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
1000
1291
|
] })
|
|
@@ -1012,14 +1303,14 @@ function ChatMessages({
|
|
|
1012
1303
|
onToolCallClick,
|
|
1013
1304
|
toolRenderers
|
|
1014
1305
|
}) {
|
|
1015
|
-
const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
1306
|
+
const renderBody = renderMarkdown ?? ((content) => /* @__PURE__ */ jsx5("p", { className: "whitespace-pre-wrap", children: content }));
|
|
1016
1307
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
1017
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1018
1309
|
messages.map(
|
|
1019
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
1020
|
-
/* @__PURE__ */
|
|
1021
|
-
/* @__PURE__ */
|
|
1022
|
-
] }) }, msg.id) : /* @__PURE__ */
|
|
1310
|
+
(msg) => msg.role === "user" ? /* @__PURE__ */ jsx5("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs5("div", { className: "ml-auto w-fit max-w-[85%]", children: [
|
|
1311
|
+
/* @__PURE__ */ jsx5("p", { className: "mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground/60", children: userLabel }),
|
|
1312
|
+
/* @__PURE__ */ jsx5("div", { className: "rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed", children: /* @__PURE__ */ jsx5("p", { className: "whitespace-pre-wrap", children: msg.content }) })
|
|
1313
|
+
] }) }, msg.id) : /* @__PURE__ */ jsx5(
|
|
1023
1314
|
AssistantMessage,
|
|
1024
1315
|
{
|
|
1025
1316
|
msg,
|
|
@@ -1035,11 +1326,12 @@ function ChatMessages({
|
|
|
1035
1326
|
msg.id
|
|
1036
1327
|
)
|
|
1037
1328
|
),
|
|
1038
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
1329
|
+
loading && lastIsUser && /* @__PURE__ */ jsx5(ThinkingRow, { agentLabel })
|
|
1039
1330
|
] });
|
|
1040
1331
|
}
|
|
1041
1332
|
export {
|
|
1042
1333
|
AgentActivityPanel,
|
|
1334
|
+
AgentSessionControls,
|
|
1043
1335
|
ChatMessages,
|
|
1044
1336
|
EffortPicker,
|
|
1045
1337
|
FlowWaterfall,
|
|
@@ -1059,6 +1351,7 @@ export {
|
|
|
1059
1351
|
nextRevealCount,
|
|
1060
1352
|
pendingApprovalOf,
|
|
1061
1353
|
streamChatTurn,
|
|
1354
|
+
useSandboxTerminalConnection,
|
|
1062
1355
|
useSmoothText,
|
|
1063
1356
|
waterfallLayout
|
|
1064
1357
|
};
|