@tangle-network/sandbox-ui 0.20.3 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat.d.ts +111 -1
- package/dist/chat.js +17 -3
- package/dist/{chunk-QNVVKMEW.js → chunk-4KAPMTPU.js} +1 -542
- package/dist/chunk-DNZ4DTNA.js +547 -0
- package/dist/chunk-ESRYVGHF.js +147 -0
- package/dist/{chunk-R6QNJQRH.js → chunk-LA5GHELP.js} +446 -451
- package/dist/{chunk-CMY7W45U.js → chunk-MEDE37J5.js} +8 -2
- package/dist/{chunk-CP2L6B53.js → chunk-R6NONXFC.js} +12 -8
- package/dist/{chunk-76IQLPW2.js → chunk-SOKKTB7W.js} +29 -5
- package/dist/{chunk-MQ52AYJX.js → chunk-TAAYDQGM.js} +236 -24
- package/dist/dashboard.d.ts +37 -48
- package/dist/dashboard.js +14 -8
- package/dist/globals.css +33 -209
- package/dist/harness-picker-C1W3rTeb.d.ts +49 -0
- package/dist/hooks.d.ts +64 -3
- package/dist/hooks.js +2 -2
- package/dist/index.d.ts +6 -4
- package/dist/index.js +33 -15
- package/dist/{template-card-gf-InrfN.d.ts → model-picker-DUfMTQo5.d.ts} +1 -86
- package/dist/pages.d.ts +5 -37
- package/dist/pages.js +304 -396
- package/dist/sdk-hooks-jUbIngSV.d.ts +96 -0
- package/dist/sdk-hooks.d.ts +2 -77
- package/dist/sdk-hooks.js +1 -1
- package/dist/styles.css +33 -209
- package/dist/template-card-UhV3pmRC.d.ts +88 -0
- package/dist/workspace.d.ts +7 -0
- package/dist/workspace.js +1 -1
- package/package.json +8 -8
|
@@ -228,13 +228,19 @@ function useSessionStream({
|
|
|
228
228
|
}
|
|
229
229
|
}, [refetch]);
|
|
230
230
|
handleSSEEventRef.current = handleSSEEvent;
|
|
231
|
-
const send = useCallback(async (text) => {
|
|
231
|
+
const send = useCallback(async (text, options) => {
|
|
232
232
|
if (!token || !sessionId || !apiUrl) return;
|
|
233
233
|
try {
|
|
234
234
|
const url = `${apiUrl}/session/sessions/${encodeURIComponent(sessionId)}/messages`;
|
|
235
235
|
await fetchJson(url, token, {
|
|
236
236
|
method: "POST",
|
|
237
|
-
body: JSON.stringify({
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
parts: [{ type: "text", text }],
|
|
239
|
+
...options?.agent ? { agent: options.agent } : {},
|
|
240
|
+
...options?.model ? { model: options.model } : {},
|
|
241
|
+
...options?.system ? { system: options.system } : {},
|
|
242
|
+
...options?.reasoningEffort ? { reasoningEffort: options.reasoningEffort } : {}
|
|
243
|
+
})
|
|
238
244
|
});
|
|
239
245
|
setIsStreaming(true);
|
|
240
246
|
} catch (err) {
|
|
@@ -1474,6 +1474,7 @@ function SandboxWorkbench({
|
|
|
1474
1474
|
] })
|
|
1475
1475
|
] })
|
|
1476
1476
|
] });
|
|
1477
|
+
const { composerControls, ...chatSession } = session;
|
|
1477
1478
|
const center = /* @__PURE__ */ jsx9(
|
|
1478
1479
|
ArtifactPane2,
|
|
1479
1480
|
{
|
|
@@ -1484,14 +1485,17 @@ function SandboxWorkbench({
|
|
|
1484
1485
|
headerActions: session.headerActions,
|
|
1485
1486
|
className: "h-full",
|
|
1486
1487
|
contentClassName: "bg-background",
|
|
1487
|
-
children: /* @__PURE__ */
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1488
|
+
children: /* @__PURE__ */ jsxs9("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
1489
|
+
/* @__PURE__ */ jsx9(
|
|
1490
|
+
ChatContainer,
|
|
1491
|
+
{
|
|
1492
|
+
...chatSession,
|
|
1493
|
+
className: "min-h-0 flex-1",
|
|
1494
|
+
presentation: session.presentation ?? "timeline"
|
|
1495
|
+
}
|
|
1496
|
+
),
|
|
1497
|
+
composerControls && /* @__PURE__ */ jsx9("div", { className: "shrink-0 border-t border-border bg-muted/30 px-3 py-2", children: composerControls })
|
|
1498
|
+
] })
|
|
1495
1499
|
}
|
|
1496
1500
|
);
|
|
1497
1501
|
const artifactPanel = artifacts.length > 0 ? /* @__PURE__ */ jsxs9("section", { className: "flex h-full min-h-0 flex-col bg-background", children: [
|
|
@@ -22,9 +22,13 @@ function useSandboxMetrics({
|
|
|
22
22
|
sandboxId,
|
|
23
23
|
token,
|
|
24
24
|
enabled = true,
|
|
25
|
-
intervalMs = 3e3
|
|
25
|
+
intervalMs = 3e3,
|
|
26
|
+
historyLimit = 120
|
|
26
27
|
}) {
|
|
27
28
|
const [metrics, setMetrics] = React.useState(null);
|
|
29
|
+
const [system, setSystem] = React.useState(null);
|
|
30
|
+
const [latency, setLatency] = React.useState(null);
|
|
31
|
+
const [history, setHistory] = React.useState([]);
|
|
28
32
|
const [loading, setLoading] = React.useState(false);
|
|
29
33
|
const [error, setError] = React.useState(null);
|
|
30
34
|
const [lastUpdatedAt, setLastUpdatedAt] = React.useState(null);
|
|
@@ -38,6 +42,9 @@ function useSandboxMetrics({
|
|
|
38
42
|
sampleRef.current = null;
|
|
39
43
|
hasLoadedRef.current = false;
|
|
40
44
|
setMetrics(null);
|
|
45
|
+
setSystem(null);
|
|
46
|
+
setLatency(null);
|
|
47
|
+
setHistory([]);
|
|
41
48
|
setLastUpdatedAt(null);
|
|
42
49
|
setError(null);
|
|
43
50
|
if (sandboxCleared) setLoading(false);
|
|
@@ -69,8 +76,8 @@ function useSandboxMetrics({
|
|
|
69
76
|
}
|
|
70
77
|
const data = await res.json();
|
|
71
78
|
const user = data?.process?.cpuSeconds?.user ?? 0;
|
|
72
|
-
const
|
|
73
|
-
const cpuSeconds = user +
|
|
79
|
+
const system2 = data?.process?.cpuSeconds?.system ?? 0;
|
|
80
|
+
const cpuSeconds = user + system2;
|
|
74
81
|
const wallMs = Date.now();
|
|
75
82
|
if (cancelled) return;
|
|
76
83
|
let cpuPercent = null;
|
|
@@ -89,6 +96,23 @@ function useSandboxMetrics({
|
|
|
89
96
|
heapUsedBytes: data?.process?.memoryBytes?.heapUsed ?? 0,
|
|
90
97
|
heapTotalBytes: data?.process?.memoryBytes?.heapTotal ?? 0
|
|
91
98
|
});
|
|
99
|
+
const sys = data?.system ?? null;
|
|
100
|
+
setSystem(sys);
|
|
101
|
+
setLatency(data?.latency ?? null);
|
|
102
|
+
if (sys) {
|
|
103
|
+
const sample = {
|
|
104
|
+
at: wallMs,
|
|
105
|
+
cpuPercent: sys.cpuPercent,
|
|
106
|
+
memoryUsedBytes: sys.memory?.usedBytes ?? null,
|
|
107
|
+
memoryTotalBytes: sys.memory?.totalBytes ?? null,
|
|
108
|
+
diskUsedBytes: sys.disk?.usedBytes ?? null,
|
|
109
|
+
diskTotalBytes: sys.disk?.totalBytes ?? null
|
|
110
|
+
};
|
|
111
|
+
setHistory((prevHistory) => {
|
|
112
|
+
const next = [...prevHistory, sample];
|
|
113
|
+
return next.length > historyLimit ? next.slice(next.length - historyLimit) : next;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
92
116
|
setLastUpdatedAt(wallMs);
|
|
93
117
|
setError(null);
|
|
94
118
|
hasLoadedRef.current = true;
|
|
@@ -113,8 +137,8 @@ function useSandboxMetrics({
|
|
|
113
137
|
controller.abort();
|
|
114
138
|
if (timeoutId !== null) window.clearTimeout(timeoutId);
|
|
115
139
|
};
|
|
116
|
-
}, [apiBaseUrl, sandboxId, token, enabled, intervalMs]);
|
|
117
|
-
return { metrics, loading, error, lastUpdatedAt };
|
|
140
|
+
}, [apiBaseUrl, sandboxId, token, enabled, intervalMs, historyLimit]);
|
|
141
|
+
return { metrics, system, latency, history, loading, error, lastUpdatedAt };
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
// src/hooks/use-session-crud.ts
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HARNESS_OPTIONS
|
|
3
|
+
} from "./chunk-ESRYVGHF.js";
|
|
4
|
+
import {
|
|
5
|
+
ModelPicker,
|
|
6
|
+
canonicalModelId
|
|
7
|
+
} from "./chunk-4KAPMTPU.js";
|
|
1
8
|
import {
|
|
2
9
|
cn
|
|
3
10
|
} from "./chunk-EI44GEQ5.js";
|
|
@@ -92,11 +99,210 @@ function ReasoningLevelPicker({
|
|
|
92
99
|
] });
|
|
93
100
|
}
|
|
94
101
|
|
|
102
|
+
// src/chat/agent-session-controls.tsx
|
|
103
|
+
import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
|
|
104
|
+
import { Bot, ChevronDown as ChevronDown2, Lock } from "lucide-react";
|
|
105
|
+
|
|
106
|
+
// src/chat/harness-model-compat.ts
|
|
107
|
+
var HARNESS_MODEL_POLICIES = {
|
|
108
|
+
opencode: { providers: null, preferred: [] },
|
|
109
|
+
"claude-code": {
|
|
110
|
+
providers: ["anthropic"],
|
|
111
|
+
preferred: [
|
|
112
|
+
/^anthropic\/claude-opus-[\d.-]+$/,
|
|
113
|
+
/^anthropic\/claude-sonnet-[\d.-]+$/,
|
|
114
|
+
/^anthropic\//
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
codex: {
|
|
118
|
+
providers: ["openai"],
|
|
119
|
+
// Standard frontier tier first (gpt-N / gpt-N.N), then any gpt
|
|
120
|
+
// variant (mini/nano), then anything OpenAI.
|
|
121
|
+
preferred: [/^openai\/gpt-\d+(\.\d+)?$/, /^openai\/gpt/, /^openai\//]
|
|
122
|
+
},
|
|
123
|
+
amp: { providers: null, preferred: [] },
|
|
124
|
+
"factory-droids": { providers: null, preferred: [] },
|
|
125
|
+
"cli-base": { providers: null, preferred: [] }
|
|
126
|
+
};
|
|
127
|
+
var PROVIDER_PREFERRED_HARNESS = {
|
|
128
|
+
anthropic: "claude-code",
|
|
129
|
+
openai: "codex"
|
|
130
|
+
};
|
|
131
|
+
function modelProvider(modelId) {
|
|
132
|
+
const slash = modelId.indexOf("/");
|
|
133
|
+
return slash > 0 ? modelId.slice(0, slash) : null;
|
|
134
|
+
}
|
|
135
|
+
function isModelCompatibleWithHarness(harness, modelId) {
|
|
136
|
+
const policy = HARNESS_MODEL_POLICIES[harness];
|
|
137
|
+
if (!policy || policy.providers === null) return true;
|
|
138
|
+
const provider = modelProvider(modelId);
|
|
139
|
+
if (!provider) return true;
|
|
140
|
+
return policy.providers.includes(provider);
|
|
141
|
+
}
|
|
142
|
+
var numericDesc = new Intl.Collator(void 0, {
|
|
143
|
+
numeric: true,
|
|
144
|
+
sensitivity: "base"
|
|
145
|
+
});
|
|
146
|
+
function snapModelToHarness(harness, modelId, models) {
|
|
147
|
+
if (isModelCompatibleWithHarness(harness, modelId)) return modelId;
|
|
148
|
+
const ids = models.map(canonicalModelId);
|
|
149
|
+
const policy = HARNESS_MODEL_POLICIES[harness];
|
|
150
|
+
for (const pattern of policy.preferred) {
|
|
151
|
+
const matches = ids.filter((id) => pattern.test(id)).sort((a, b) => numericDesc.compare(b, a));
|
|
152
|
+
if (matches.length > 0) return matches[0];
|
|
153
|
+
}
|
|
154
|
+
const fallback = ids.find(
|
|
155
|
+
(id) => isModelCompatibleWithHarness(harness, id)
|
|
156
|
+
);
|
|
157
|
+
return fallback ?? modelId;
|
|
158
|
+
}
|
|
159
|
+
function snapHarnessToModel(harness, modelId) {
|
|
160
|
+
if (isModelCompatibleWithHarness(harness, modelId)) return harness;
|
|
161
|
+
const provider = modelProvider(modelId);
|
|
162
|
+
return provider && PROVIDER_PREFERRED_HARNESS[provider] || "opencode";
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/chat/agent-session-controls.tsx
|
|
166
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
167
|
+
function HarnessDropdown({
|
|
168
|
+
value,
|
|
169
|
+
onChange,
|
|
170
|
+
available,
|
|
171
|
+
disabled,
|
|
172
|
+
locked,
|
|
173
|
+
lockReason
|
|
174
|
+
}) {
|
|
175
|
+
const allowed = new Set(
|
|
176
|
+
available ?? HARNESS_OPTIONS.map((h) => h.type)
|
|
177
|
+
);
|
|
178
|
+
const options = HARNESS_OPTIONS.filter((h) => allowed.has(h.type));
|
|
179
|
+
const selected = options.find((option) => option.type === value);
|
|
180
|
+
return /* @__PURE__ */ jsxs2(DropdownMenu2.Root, { children: [
|
|
181
|
+
/* @__PURE__ */ jsx2(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
|
|
182
|
+
"button",
|
|
183
|
+
{
|
|
184
|
+
type: "button",
|
|
185
|
+
disabled: disabled || locked,
|
|
186
|
+
title: locked ? lockReason : void 0,
|
|
187
|
+
className: cn(
|
|
188
|
+
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-border bg-card px-2.5",
|
|
189
|
+
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
190
|
+
"hover:border-primary/30 hover:bg-accent/30 focus:outline-none focus:border-primary/40",
|
|
191
|
+
"data-[state=open]:border-primary/40 data-[state=open]:bg-accent/30",
|
|
192
|
+
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
193
|
+
),
|
|
194
|
+
"aria-label": "Agent harness",
|
|
195
|
+
children: [
|
|
196
|
+
locked ? /* @__PURE__ */ jsx2(Lock, { className: "h-3 w-3 text-muted-foreground" }) : /* @__PURE__ */ jsx2(Bot, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
197
|
+
/* @__PURE__ */ jsx2("span", { children: selected?.label ?? value }),
|
|
198
|
+
!locked && /* @__PURE__ */ jsx2(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
) }),
|
|
202
|
+
/* @__PURE__ */ jsx2(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx2(
|
|
203
|
+
DropdownMenu2.Content,
|
|
204
|
+
{
|
|
205
|
+
align: "start",
|
|
206
|
+
sideOffset: 6,
|
|
207
|
+
className: cn(
|
|
208
|
+
"z-50 w-72 overflow-hidden rounded-[var(--radius-md)] border border-border bg-card p-1",
|
|
209
|
+
"shadow-[var(--shadow-dropdown)]",
|
|
210
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
211
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
212
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
213
|
+
),
|
|
214
|
+
children: options.map((option) => /* @__PURE__ */ jsxs2(
|
|
215
|
+
DropdownMenu2.Item,
|
|
216
|
+
{
|
|
217
|
+
onSelect: (event) => {
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
onChange(option.type);
|
|
220
|
+
},
|
|
221
|
+
className: cn(
|
|
222
|
+
"flex cursor-pointer flex-col gap-0.5 rounded-md px-2.5 py-2 outline-none",
|
|
223
|
+
"transition-colors hover:bg-accent/40 focus:bg-accent/40",
|
|
224
|
+
option.type === value && "bg-[var(--accent-surface-soft)] text-[var(--accent-text)]"
|
|
225
|
+
),
|
|
226
|
+
children: [
|
|
227
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm font-medium", children: option.label }),
|
|
228
|
+
option.description && /* @__PURE__ */ jsx2("span", { className: "text-xs text-muted-foreground", children: option.description })
|
|
229
|
+
]
|
|
230
|
+
},
|
|
231
|
+
option.type
|
|
232
|
+
))
|
|
233
|
+
}
|
|
234
|
+
) })
|
|
235
|
+
] });
|
|
236
|
+
}
|
|
237
|
+
function AgentSessionControls({
|
|
238
|
+
harness,
|
|
239
|
+
model,
|
|
240
|
+
reasoning,
|
|
241
|
+
trailing,
|
|
242
|
+
className
|
|
243
|
+
}) {
|
|
244
|
+
if (!harness && !model && !reasoning && !trailing) return null;
|
|
245
|
+
const handleHarnessChange = (next) => {
|
|
246
|
+
harness?.onChange(next);
|
|
247
|
+
if (model) {
|
|
248
|
+
const snapped = snapModelToHarness(next, model.value, model.models);
|
|
249
|
+
if (snapped !== model.value) model.onChange(snapped);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const handleModelChange = (nextModelId) => {
|
|
253
|
+
model?.onChange(nextModelId);
|
|
254
|
+
if (harness && !harness.locked) {
|
|
255
|
+
const snapped = snapHarnessToModel(harness.value, nextModelId);
|
|
256
|
+
if (snapped !== harness.value) harness.onChange(snapped);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
const visibleModels = model && harness?.locked ? model.models.filter(
|
|
260
|
+
(entry) => isModelCompatibleWithHarness(
|
|
261
|
+
harness.value,
|
|
262
|
+
canonicalModelId(entry)
|
|
263
|
+
)
|
|
264
|
+
) : model?.models;
|
|
265
|
+
return /* @__PURE__ */ jsxs2(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
className: cn("flex flex-wrap items-center gap-2", className),
|
|
269
|
+
"data-testid": "agent-session-controls",
|
|
270
|
+
children: [
|
|
271
|
+
harness && /* @__PURE__ */ jsx2(HarnessDropdown, { ...harness, onChange: handleHarnessChange }),
|
|
272
|
+
model && /* @__PURE__ */ jsx2(
|
|
273
|
+
ModelPicker,
|
|
274
|
+
{
|
|
275
|
+
variant: "pill",
|
|
276
|
+
label: "",
|
|
277
|
+
value: model.value,
|
|
278
|
+
onChange: handleModelChange,
|
|
279
|
+
models: visibleModels ?? [],
|
|
280
|
+
loading: model.loading,
|
|
281
|
+
popular: model.popular,
|
|
282
|
+
recents: model.recents,
|
|
283
|
+
disabled: model.disabled || (visibleModels ?? []).length === 0
|
|
284
|
+
}
|
|
285
|
+
),
|
|
286
|
+
reasoning && /* @__PURE__ */ jsx2(
|
|
287
|
+
ReasoningLevelPicker,
|
|
288
|
+
{
|
|
289
|
+
value: reasoning.value,
|
|
290
|
+
onChange: reasoning.onChange,
|
|
291
|
+
options: reasoning.options,
|
|
292
|
+
disabled: reasoning.disabled
|
|
293
|
+
}
|
|
294
|
+
),
|
|
295
|
+
trailing && /* @__PURE__ */ jsx2("div", { className: "ml-auto flex items-center gap-2", children: trailing })
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
95
301
|
// src/chat/artifact-agent-dock.tsx
|
|
96
302
|
import * as React from "react";
|
|
97
303
|
import { Sparkles, Send, Square, X } from "lucide-react";
|
|
98
304
|
import { ChatMessage } from "@tangle-network/ui/chat";
|
|
99
|
-
import { jsx as
|
|
305
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
100
306
|
function defaultScopeLabel(scope) {
|
|
101
307
|
if (scope.label) return scope.label;
|
|
102
308
|
switch (scope.kind) {
|
|
@@ -262,7 +468,7 @@ function ArtifactAgentDock({
|
|
|
262
468
|
}, [threadId, transport]);
|
|
263
469
|
if (!open) return null;
|
|
264
470
|
const heading = defaultScopeLabel(scope);
|
|
265
|
-
return /* @__PURE__ */
|
|
471
|
+
return /* @__PURE__ */ jsxs3(
|
|
266
472
|
"aside",
|
|
267
473
|
{
|
|
268
474
|
className: cn(
|
|
@@ -271,38 +477,38 @@ function ArtifactAgentDock({
|
|
|
271
477
|
),
|
|
272
478
|
"aria-label": `Agent chat about ${heading}`,
|
|
273
479
|
children: [
|
|
274
|
-
/* @__PURE__ */
|
|
275
|
-
/* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
277
|
-
/* @__PURE__ */
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
-
/* @__PURE__ */
|
|
480
|
+
/* @__PURE__ */ jsxs3("header", { className: "flex items-center justify-between border-b border-border bg-background/60 px-4 py-3", children: [
|
|
481
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
482
|
+
/* @__PURE__ */ jsx3(Sparkles, { className: "h-4 w-4 shrink-0 text-primary" }),
|
|
483
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
484
|
+
/* @__PURE__ */ jsx3("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: "Discussing" }),
|
|
485
|
+
/* @__PURE__ */ jsx3("div", { className: "truncate text-sm font-semibold text-foreground", children: heading })
|
|
280
486
|
] })
|
|
281
487
|
] }),
|
|
282
|
-
/* @__PURE__ */
|
|
488
|
+
/* @__PURE__ */ jsx3(
|
|
283
489
|
"button",
|
|
284
490
|
{
|
|
285
491
|
type: "button",
|
|
286
492
|
onClick: () => onOpenChange(false),
|
|
287
493
|
"aria-label": "Close artifact chat",
|
|
288
494
|
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
289
|
-
children: /* @__PURE__ */
|
|
495
|
+
children: /* @__PURE__ */ jsx3(X, { className: "h-4 w-4" })
|
|
290
496
|
}
|
|
291
497
|
)
|
|
292
498
|
] }),
|
|
293
|
-
/* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
295
|
-
/* @__PURE__ */
|
|
499
|
+
/* @__PURE__ */ jsx3("div", { ref: scrollRef, className: "flex-1 overflow-y-auto px-3 py-4", children: loading ? /* @__PURE__ */ jsx3("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: "Loading conversation\u2026" }) : messages.length === 0 && !streamContent ? /* @__PURE__ */ jsxs3("div", { className: "px-3 py-12 text-center", children: [
|
|
500
|
+
/* @__PURE__ */ jsx3(Sparkles, { className: "mx-auto mb-3 h-5 w-5 text-muted-foreground/40" }),
|
|
501
|
+
/* @__PURE__ */ jsxs3("p", { className: "text-sm text-foreground", children: [
|
|
296
502
|
"Ask the agent about this ",
|
|
297
503
|
scope.kind === "vault-file" ? "document" : scope.kind,
|
|
298
504
|
"."
|
|
299
505
|
] }),
|
|
300
|
-
/* @__PURE__ */
|
|
301
|
-
] }) : /* @__PURE__ */
|
|
302
|
-
messages.map((m) => /* @__PURE__ */
|
|
303
|
-
streamContent && /* @__PURE__ */
|
|
506
|
+
/* @__PURE__ */ jsx3("p", { className: "mt-1 text-xs text-muted-foreground", children: "It can read the current contents and propose edits, rewrites, or follow-ups." })
|
|
507
|
+
] }) : /* @__PURE__ */ jsxs3("div", { className: "space-y-3", children: [
|
|
508
|
+
messages.map((m) => /* @__PURE__ */ jsx3(ChatMessage, { role: m.role, content: m.content, timestamp: m.createdAt }, m.id)),
|
|
509
|
+
streamContent && /* @__PURE__ */ jsx3(ChatMessage, { role: "assistant", content: streamContent, isStreaming: true })
|
|
304
510
|
] }) }),
|
|
305
|
-
/* @__PURE__ */
|
|
511
|
+
/* @__PURE__ */ jsx3(
|
|
306
512
|
"form",
|
|
307
513
|
{
|
|
308
514
|
className: "border-t border-border bg-background/60 p-3",
|
|
@@ -310,8 +516,8 @@ function ArtifactAgentDock({
|
|
|
310
516
|
e.preventDefault();
|
|
311
517
|
void send();
|
|
312
518
|
},
|
|
313
|
-
children: /* @__PURE__ */
|
|
314
|
-
/* @__PURE__ */
|
|
519
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "flex items-end gap-2", children: [
|
|
520
|
+
/* @__PURE__ */ jsx3(
|
|
315
521
|
"textarea",
|
|
316
522
|
{
|
|
317
523
|
value: composer,
|
|
@@ -328,23 +534,23 @@ function ArtifactAgentDock({
|
|
|
328
534
|
className: "min-h-[44px] flex-1 resize-none rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary/40 disabled:opacity-50"
|
|
329
535
|
}
|
|
330
536
|
),
|
|
331
|
-
sending ? /* @__PURE__ */
|
|
537
|
+
sending ? /* @__PURE__ */ jsx3(
|
|
332
538
|
"button",
|
|
333
539
|
{
|
|
334
540
|
type: "button",
|
|
335
541
|
onClick: cancel,
|
|
336
542
|
"aria-label": "Cancel",
|
|
337
543
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
338
|
-
children: /* @__PURE__ */
|
|
544
|
+
children: /* @__PURE__ */ jsx3(Square, { className: "h-4 w-4" })
|
|
339
545
|
}
|
|
340
|
-
) : /* @__PURE__ */
|
|
546
|
+
) : /* @__PURE__ */ jsx3(
|
|
341
547
|
"button",
|
|
342
548
|
{
|
|
343
549
|
type: "submit",
|
|
344
550
|
disabled: !composer.trim() || !threadId,
|
|
345
551
|
"aria-label": "Send",
|
|
346
552
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
347
|
-
children: /* @__PURE__ */
|
|
553
|
+
children: /* @__PURE__ */ jsx3(Send, { className: "h-4 w-4" })
|
|
348
554
|
}
|
|
349
555
|
)
|
|
350
556
|
] })
|
|
@@ -433,6 +639,12 @@ function createFetchTransport(opts) {
|
|
|
433
639
|
export {
|
|
434
640
|
DEFAULT_REASONING_LEVEL_OPTIONS,
|
|
435
641
|
ReasoningLevelPicker,
|
|
642
|
+
HARNESS_MODEL_POLICIES,
|
|
643
|
+
modelProvider,
|
|
644
|
+
isModelCompatibleWithHarness,
|
|
645
|
+
snapModelToHarness,
|
|
646
|
+
snapHarnessToModel,
|
|
647
|
+
AgentSessionControls,
|
|
436
648
|
ArtifactAgentDock,
|
|
437
649
|
createFetchTransport,
|
|
438
650
|
AgentTimeline,
|
package/dist/dashboard.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
export { B as
|
|
3
|
+
export { B as Backend, a as BackendSelector, b as BackendSelectorProps, H as HARNESS_OPTIONS, c as HarnessPicker, d as HarnessPickerProps, e as HarnessType } from './harness-picker-C1W3rTeb.js';
|
|
4
|
+
export { M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, f as formatContext, e as formatPricing } from './model-picker-DUfMTQo5.js';
|
|
5
|
+
export { B as BillingBalance, a as BillingDashboard, b as BillingDashboardProps, c as BillingSubscription, d as BillingUsage, P as PricingPage, e as PricingPageProps, f as PricingTier, T as TemplateCard, g as TemplateCardData, h as TemplateCardProps, U as UsageChart, i as UsageChartProps, j as UsageDataPoint, k as formatPrice } from './template-card-UhV3pmRC.js';
|
|
4
6
|
|
|
5
7
|
interface SidebarUser {
|
|
6
8
|
email: string;
|
|
@@ -344,52 +346,6 @@ interface PlanCardsProps {
|
|
|
344
346
|
}
|
|
345
347
|
declare function PlanCards({ plans, className }: PlanCardsProps): react_jsx_runtime.JSX.Element;
|
|
346
348
|
|
|
347
|
-
interface Backend {
|
|
348
|
-
type: string;
|
|
349
|
-
label: string;
|
|
350
|
-
description?: string;
|
|
351
|
-
}
|
|
352
|
-
interface BackendSelectorProps {
|
|
353
|
-
backends: Backend[];
|
|
354
|
-
selected: string;
|
|
355
|
-
onChange: (selected: string) => void;
|
|
356
|
-
label?: string;
|
|
357
|
-
placeholder?: string;
|
|
358
|
-
className?: string;
|
|
359
|
-
}
|
|
360
|
-
declare function BackendSelector({ backends, selected, onChange, label, placeholder, className, }: BackendSelectorProps): react_jsx_runtime.JSX.Element;
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Sandbox agent harness types — mirrors `BackendType` from
|
|
364
|
-
* `@tangle-network/sandbox` SDK. Kept in lockstep with that enum:
|
|
365
|
-
* if the SDK adds a backend, add it here too.
|
|
366
|
-
*/
|
|
367
|
-
type HarnessType = "opencode" | "claude-code" | "codex" | "amp" | "factory-droids" | "cli-base";
|
|
368
|
-
interface HarnessOption extends Backend {
|
|
369
|
-
type: HarnessType;
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Default option list with human-readable copy. Order is curated so the
|
|
373
|
-
* recommended choice (`opencode`) appears first; `cli-base` (no agent) last.
|
|
374
|
-
*/
|
|
375
|
-
declare const HARNESS_OPTIONS: readonly HarnessOption[];
|
|
376
|
-
interface HarnessPickerProps extends Omit<BackendSelectorProps, "backends" | "selected" | "onChange"> {
|
|
377
|
-
value: HarnessType;
|
|
378
|
-
onChange: (next: HarnessType) => void;
|
|
379
|
-
/** Filter the available harnesses (e.g. by plan tier). Defaults to all. */
|
|
380
|
-
available?: ReadonlyArray<HarnessType>;
|
|
381
|
-
/** Override or extend the option metadata. Keys are HarnessType. */
|
|
382
|
-
optionsOverride?: Partial<Record<HarnessType, Partial<Omit<HarnessOption, "type">>>>;
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Type-safe harness/backend selector for sandbox-backed agent products.
|
|
386
|
-
*
|
|
387
|
-
* Wraps the generic {@link BackendSelector} with the canonical harness list
|
|
388
|
-
* baked in, so consumers don't have to re-declare it (or risk drifting from
|
|
389
|
-
* the SDK enum).
|
|
390
|
-
*/
|
|
391
|
-
declare function HarnessPicker({ value, onChange, available, optionsOverride, label, ...rest }: HarnessPickerProps): react_jsx_runtime.JSX.Element;
|
|
392
|
-
|
|
393
349
|
type ProductVariant = "sandbox";
|
|
394
350
|
interface NavItem {
|
|
395
351
|
id: string;
|
|
@@ -495,6 +451,39 @@ interface ProfileComparisonProps {
|
|
|
495
451
|
}
|
|
496
452
|
declare function ProfileComparison({ profiles, className, }: ProfileComparisonProps): react_jsx_runtime.JSX.Element | null;
|
|
497
453
|
|
|
454
|
+
interface MetricChartPoint {
|
|
455
|
+
/** Wall-clock ms. */
|
|
456
|
+
at: number;
|
|
457
|
+
/** Null renders a gap in the series, never a zero. */
|
|
458
|
+
value: number | null;
|
|
459
|
+
}
|
|
460
|
+
type MetricChartTone = "primary" | "success" | "warning" | "danger";
|
|
461
|
+
interface MetricAreaChartProps {
|
|
462
|
+
points: MetricChartPoint[];
|
|
463
|
+
label: string;
|
|
464
|
+
/** Formats the current value and y-axis bounds (e.g. percent, bytes). */
|
|
465
|
+
formatValue: (value: number) => string;
|
|
466
|
+
/**
|
|
467
|
+
* Fixed y-axis maximum (100 for percents, memory total for bytes).
|
|
468
|
+
* Omitted = auto-scale to the observed maximum with 10% headroom.
|
|
469
|
+
*/
|
|
470
|
+
maxValue?: number;
|
|
471
|
+
/** Secondary line under the current value (e.g. "of 8 GiB"). */
|
|
472
|
+
detail?: React.ReactNode;
|
|
473
|
+
tone?: MetricChartTone;
|
|
474
|
+
/** Plot height in px. Defaults to 96. */
|
|
475
|
+
height?: number;
|
|
476
|
+
/** Shown instead of the plot while no point has a value yet. */
|
|
477
|
+
emptyState?: React.ReactNode;
|
|
478
|
+
className?: string;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Lightweight live time-series panel (Prometheus/Grafana idiom): big
|
|
482
|
+
* current value, area chart of the rolling window, dashed gridlines.
|
|
483
|
+
* Pure SVG — no chart dependency. Null samples render as gaps.
|
|
484
|
+
*/
|
|
485
|
+
declare function MetricAreaChart({ points, label, formatValue, maxValue, detail, tone, height, emptyState, className, }: MetricAreaChartProps): react_jsx_runtime.JSX.Element;
|
|
486
|
+
|
|
498
487
|
type VariantStatus = "pending" | "running" | "completed" | "failed" | "cancelled";
|
|
499
488
|
type VariantOutcome = "pending_review" | "accepted" | "rejected" | "merged_with_conflicts" | "expired";
|
|
500
489
|
interface Variant {
|
|
@@ -670,4 +659,4 @@ interface InfoPanelProps {
|
|
|
670
659
|
}
|
|
671
660
|
declare function InfoPanel({ label, title, description, className }: InfoPanelProps): react_jsx_runtime.JSX.Element;
|
|
672
661
|
|
|
673
|
-
export {
|
|
662
|
+
export { BackendConfig, type BackendConfigProps, type BackendStatusData, ClusterStatusBar, type ClusterStatusBarProps, type ClusterStatusItem, CreditBalance, type CreditBalanceProps, DashboardLayout, type DashboardLayoutProps, type Profile as DashboardProfile, type SnapshotInfo as DashboardSnapshotInfo, type DashboardUser, type ExposedPort, type GitCommitData, GitPanel, type GitPanelProps, type GitStatusData, INSUFFICIENT_BALANCE_CODE, InfoPanel, type InfoPanelProps, type InsufficientBalance, type Invoice, InvoiceTable, type InvoiceTableProps, type McpServer, MetricAreaChart, type MetricAreaChartProps, type MetricChartPoint, type MetricChartTone, type NavItem, NetworkConfig, type NetworkConfigData, type NetworkConfigProps, NewSandboxCard, type NewSandboxCardProps, OutOfCreditsModal, type OutOfCreditsModalProps, type PlanCardData, PlanCards, type PlanCardsProps, type PlanFeature, PortsList, type PortsListProps, type ProcessInfo, ProcessList, type ProcessListProps, type ProductVariant, ProfileAvatar, type ProfileAvatarProps, ProfileComparison, type ProfileComparisonProps, ProfileSelector, type ProfileSelectorProps, PromoBanner, type PromoBannerProps, RailButton, type RailButtonProps, RailModeButton, type RailModeButtonProps, RailSeparator, type RailSeparatorProps, ResourceMeter, type ResourceMeterProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, type SandboxCardData, type SandboxCardProps, type SandboxStatus, SandboxTable, type SandboxTableProps, Sidebar, SidebarContent, type SidebarContentProps, SidebarPanel, SidebarPanelContent, type SidebarPanelContentProps, SidebarPanelHeader, type SidebarPanelHeaderProps, type SidebarPanelProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailFooter, type SidebarRailFooterProps, SidebarRailHeader, type SidebarRailHeaderProps, SidebarRailNav, type SidebarRailNavProps, type SidebarRailProps, type SidebarUser, SnapshotList, type SnapshotListProps, SystemLogsViewer, type SystemLogsViewerProps, type TeamRole, UsageSummary, type UsageSummaryData, type UsageSummaryProps, type Variant, VariantList, type VariantListProps, type VariantOutcome, type VariantStatus, canAdminSandbox, parseInsufficientBalance, useSidebar };
|
package/dist/dashboard.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BackendConfig,
|
|
3
|
-
BackendSelector,
|
|
4
3
|
ClusterStatusBar,
|
|
5
4
|
CreditBalance,
|
|
6
5
|
DashboardLayout,
|
|
7
6
|
GitPanel,
|
|
8
|
-
HARNESS_OPTIONS,
|
|
9
|
-
HarnessPicker,
|
|
10
7
|
INSUFFICIENT_BALANCE_CODE,
|
|
11
8
|
InvoiceTable,
|
|
9
|
+
MetricAreaChart,
|
|
12
10
|
NetworkConfig,
|
|
13
11
|
NewSandboxCard,
|
|
14
12
|
OutOfCreditsModal,
|
|
@@ -46,20 +44,27 @@ import {
|
|
|
46
44
|
canAdminSandbox,
|
|
47
45
|
parseInsufficientBalance,
|
|
48
46
|
useSidebar
|
|
49
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-LA5GHELP.js";
|
|
50
48
|
import {
|
|
51
49
|
BillingDashboard,
|
|
52
50
|
InfoPanel,
|
|
53
|
-
ModelPicker,
|
|
54
51
|
PricingPage,
|
|
55
52
|
TemplateCard,
|
|
56
53
|
UsageChart,
|
|
54
|
+
formatPrice
|
|
55
|
+
} from "./chunk-DNZ4DTNA.js";
|
|
56
|
+
import "./chunk-7ZA5SEK3.js";
|
|
57
|
+
import {
|
|
58
|
+
BackendSelector,
|
|
59
|
+
HARNESS_OPTIONS,
|
|
60
|
+
HarnessPicker
|
|
61
|
+
} from "./chunk-ESRYVGHF.js";
|
|
62
|
+
import {
|
|
63
|
+
ModelPicker,
|
|
57
64
|
canonicalModelId,
|
|
58
65
|
formatContext,
|
|
59
|
-
formatPrice,
|
|
60
66
|
formatPricing
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import "./chunk-7ZA5SEK3.js";
|
|
67
|
+
} from "./chunk-4KAPMTPU.js";
|
|
63
68
|
import "./chunk-EI44GEQ5.js";
|
|
64
69
|
export {
|
|
65
70
|
BackendConfig,
|
|
@@ -74,6 +79,7 @@ export {
|
|
|
74
79
|
INSUFFICIENT_BALANCE_CODE,
|
|
75
80
|
InfoPanel,
|
|
76
81
|
InvoiceTable,
|
|
82
|
+
MetricAreaChart,
|
|
77
83
|
ModelPicker,
|
|
78
84
|
NetworkConfig,
|
|
79
85
|
NewSandboxCard,
|