@tangle-network/sandbox-ui 0.26.0 → 0.27.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/chat.d.ts +19 -3
- package/dist/chat.js +3 -3
- package/dist/{chunk-JDMX4HHN.js → chunk-6NQBODYV.js} +66 -8
- package/dist/{chunk-KANKBACI.js → chunk-BJFWPP5T.js} +139 -35
- package/dist/{chunk-HXIYUQN2.js → chunk-ELGN7DPS.js} +23 -11
- package/dist/{chunk-BP6ZTBI6.js → chunk-I3IVCGND.js} +35 -35
- package/dist/dashboard.d.ts +3 -3
- package/dist/dashboard.js +12 -4
- package/dist/globals.css +29 -15
- package/dist/{harness-picker-ppDe7ap-.d.ts → harness-picker-lyeEncN4.d.ts} +10 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -6
- package/dist/integrations.d.ts +17 -5
- package/dist/integrations.js +344 -121
- package/dist/{model-picker-DUfMTQo5.d.ts → model-picker-Cmisf9Y8.d.ts} +33 -1
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +1 -1
- package/dist/styles.css +29 -15
- package/dist/workspace.js +1 -1
- package/package.json +1 -1
package/dist/chat.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { MessageRole } from '@tangle-network/ui/chat';
|
|
|
2
2
|
export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from '@tangle-network/ui/chat';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import { M as ModelInfo } from './model-picker-
|
|
6
|
-
import { e as HarnessType } from './harness-picker-
|
|
5
|
+
import { M as ModelInfo } from './model-picker-Cmisf9Y8.js';
|
|
6
|
+
import { e as HarnessType } from './harness-picker-lyeEncN4.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Thinking-effort ladder — the superset of the per-harness reasoning scales so
|
|
@@ -77,6 +77,22 @@ interface AgentSessionControlsProps {
|
|
|
77
77
|
/** Right-aligned extra content (token meter, cost, status). */
|
|
78
78
|
trailing?: React.ReactNode;
|
|
79
79
|
className?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Which surface these controls live on. `"chat"` (default) restricts the
|
|
82
|
+
* harness list to chat-capable backends — shell-only `cli-base` is hidden
|
|
83
|
+
* because it has no conversational agent. `"all"` keeps every harness for
|
|
84
|
+
* scheduled / non-chat surfaces. An explicit `harness.available` list still
|
|
85
|
+
* wins; this only trims the default-everything set.
|
|
86
|
+
*/
|
|
87
|
+
context?: "chat" | "all";
|
|
88
|
+
/**
|
|
89
|
+
* Trigger layout. `"inline"` (default) lays the pickers out in a row — the
|
|
90
|
+
* existing behavior. `"gear"` collapses them behind a single compact gear
|
|
91
|
+
* button whose menu opens up-and-left, for right-anchored copilots where
|
|
92
|
+
* the composer is tight. Nested model/harness/effort menus render adjacent
|
|
93
|
+
* on the left of the gear menu.
|
|
94
|
+
*/
|
|
95
|
+
layout?: "inline" | "gear";
|
|
80
96
|
}
|
|
81
97
|
/**
|
|
82
98
|
* Compact control strip for an agent chat composer: harness, model, and
|
|
@@ -92,7 +108,7 @@ interface AgentSessionControlsProps {
|
|
|
92
108
|
*
|
|
93
109
|
* Designed to slot into `SandboxWorkbench`'s `session.composerControls`.
|
|
94
110
|
*/
|
|
95
|
-
declare function AgentSessionControls({ harness, model, reasoning, trailing, className, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
|
|
111
|
+
declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
|
|
96
112
|
|
|
97
113
|
/**
|
|
98
114
|
* Harness ↔ model compatibility policy.
|
package/dist/chat.js
CHANGED
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
modelProvider,
|
|
17
17
|
snapHarnessToModel,
|
|
18
18
|
snapModelToHarness
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-BJFWPP5T.js";
|
|
20
|
+
import "./chunk-ELGN7DPS.js";
|
|
21
|
+
import "./chunk-6NQBODYV.js";
|
|
22
22
|
import "./chunk-EI44GEQ5.js";
|
|
23
23
|
export {
|
|
24
24
|
AgentSessionControls,
|
|
@@ -145,6 +145,38 @@ function canonicalModelId(model) {
|
|
|
145
145
|
const provider = model._provider ?? model.provider;
|
|
146
146
|
return provider ? `${provider}/${id}` : id;
|
|
147
147
|
}
|
|
148
|
+
function modelDedupKey(model) {
|
|
149
|
+
const canonical = canonicalModelId(model).toLowerCase();
|
|
150
|
+
const segments = canonical.split("/").filter(Boolean);
|
|
151
|
+
const modelId = segments[segments.length - 1] ?? canonical;
|
|
152
|
+
const lab = resolveModelBrandIdentity(model).lab.key;
|
|
153
|
+
return lab === "unknown" ? canonical : `${lab}/${modelId}`;
|
|
154
|
+
}
|
|
155
|
+
function dedupeModels(models) {
|
|
156
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
157
|
+
const result = [];
|
|
158
|
+
for (const model of models) {
|
|
159
|
+
const key = modelDedupKey(model);
|
|
160
|
+
const existingIndex = byKey.get(key);
|
|
161
|
+
if (existingIndex === void 0) {
|
|
162
|
+
byKey.set(key, result.length);
|
|
163
|
+
result.push(model);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const existing = result[existingIndex];
|
|
167
|
+
if (!existing.featured && model.featured) {
|
|
168
|
+
result[existingIndex] = model;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
var DEFAULT_FEATURED_MODEL_IDS = [
|
|
174
|
+
"anthropic/claude-opus-4-8",
|
|
175
|
+
"anthropic/claude-sonnet-4-6",
|
|
176
|
+
"openai/gpt-5.4",
|
|
177
|
+
"google/gemini-2.5-pro",
|
|
178
|
+
"deepseek/deepseek-v3"
|
|
179
|
+
];
|
|
148
180
|
function formatPricing(pricing) {
|
|
149
181
|
const prompt = Number(pricing?.prompt ?? 0);
|
|
150
182
|
const completion = Number(pricing?.completion ?? 0);
|
|
@@ -229,11 +261,12 @@ function ModelPicker({
|
|
|
229
261
|
});
|
|
230
262
|
return () => cancelAnimationFrame(frame);
|
|
231
263
|
}, [open]);
|
|
264
|
+
const deduped = React.useMemo(() => dedupeModels(models), [models]);
|
|
232
265
|
const filtered = React.useMemo(() => {
|
|
233
266
|
const excluded = new Set((excludeProviders ?? []).map((p) => p.toLowerCase()));
|
|
234
267
|
const allowedModalities = modalities ? new Set(modalities) : null;
|
|
235
268
|
const q = query.trim().toLowerCase();
|
|
236
|
-
return
|
|
269
|
+
return deduped.filter((m) => {
|
|
237
270
|
const provider = (m._provider ?? m.provider ?? "").toLowerCase();
|
|
238
271
|
if (excluded.has(provider)) return false;
|
|
239
272
|
if (allowedModalities && m.architecture?.modality && !allowedModalities.has(m.architecture.modality)) return false;
|
|
@@ -243,7 +276,7 @@ function ModelPicker({
|
|
|
243
276
|
const identity = resolveModelBrandIdentity(m);
|
|
244
277
|
return id.includes(q) || name.includes(q) || provider.includes(q) || identity.host.label.toLowerCase().includes(q) || identity.lab.label.toLowerCase().includes(q);
|
|
245
278
|
});
|
|
246
|
-
}, [
|
|
279
|
+
}, [deduped, query, modalities, excludeProviders]);
|
|
247
280
|
const grouped = React.useMemo(() => {
|
|
248
281
|
const groups = /* @__PURE__ */ new Map();
|
|
249
282
|
for (const m of filtered) {
|
|
@@ -270,6 +303,18 @@ function ModelPicker({
|
|
|
270
303
|
const lookup = new Map(models.map((m) => [canonicalModelId(m), m]));
|
|
271
304
|
return popular.map((id) => lookup.get(id)).filter((m) => Boolean(m));
|
|
272
305
|
}, [popular, models]);
|
|
306
|
+
const featuredModels = React.useMemo(() => {
|
|
307
|
+
const flagged = deduped.filter((m) => m.featured);
|
|
308
|
+
if (flagged.length > 0) return flagged;
|
|
309
|
+
const seedKeys = new Set(
|
|
310
|
+
DEFAULT_FEATURED_MODEL_IDS.map((id) => modelDedupKey({ id }))
|
|
311
|
+
);
|
|
312
|
+
const seeded = deduped.filter((m) => seedKeys.has(modelDedupKey(m)));
|
|
313
|
+
const order = DEFAULT_FEATURED_MODEL_IDS.map((id) => modelDedupKey({ id }));
|
|
314
|
+
return seeded.sort(
|
|
315
|
+
(a, b) => order.indexOf(modelDedupKey(a)) - order.indexOf(modelDedupKey(b))
|
|
316
|
+
);
|
|
317
|
+
}, [deduped]);
|
|
273
318
|
const handleSelect = (id) => {
|
|
274
319
|
onChange(id);
|
|
275
320
|
setOpen(false);
|
|
@@ -363,6 +408,16 @@ function ModelPicker({
|
|
|
363
408
|
loading && /* @__PURE__ */ jsx2(Loader2, { className: "h-3.5 w-3.5 animate-spin text-muted-foreground" })
|
|
364
409
|
] }),
|
|
365
410
|
/* @__PURE__ */ jsxs2("div", { className: "flex-1 overflow-y-auto", children: [
|
|
411
|
+
!query && featuredModels.length > 0 && /* @__PURE__ */ jsx2(Section, { label: "Recommended", tone: "featured", children: featuredModels.map((m) => /* @__PURE__ */ jsx2(
|
|
412
|
+
ModelRow,
|
|
413
|
+
{
|
|
414
|
+
model: m,
|
|
415
|
+
active: canonicalModelId(m) === value,
|
|
416
|
+
onSelect: handleSelect,
|
|
417
|
+
featured: true
|
|
418
|
+
},
|
|
419
|
+
`featured-${canonicalModelId(m)}`
|
|
420
|
+
)) }),
|
|
366
421
|
!query && popularModels.length > 0 && /* @__PURE__ */ jsx2(Section, { label: "Top models", tone: "featured", children: popularModels.map((m) => /* @__PURE__ */ jsx2(
|
|
367
422
|
ModelRow,
|
|
368
423
|
{
|
|
@@ -395,9 +450,9 @@ function ModelPicker({
|
|
|
395
450
|
/* @__PURE__ */ jsxs2("div", { className: "border-t border-border px-3 py-1.5 text-[10px] text-muted-foreground", children: [
|
|
396
451
|
filtered.length,
|
|
397
452
|
" of ",
|
|
398
|
-
|
|
453
|
+
deduped.length,
|
|
399
454
|
" model",
|
|
400
|
-
|
|
455
|
+
deduped.length === 1 ? "" : "s"
|
|
401
456
|
] })
|
|
402
457
|
]
|
|
403
458
|
}
|
|
@@ -438,11 +493,11 @@ function PickerItem({
|
|
|
438
493
|
onSelect();
|
|
439
494
|
},
|
|
440
495
|
className: cn(
|
|
441
|
-
"flex cursor-pointer items-start gap-2 px-3 py-2 outline-none",
|
|
496
|
+
"flex cursor-pointer items-start gap-2 rounded-md px-3 py-2 outline-none",
|
|
442
497
|
"transition-colors duration-[var(--transition-fast)]",
|
|
443
|
-
"hover:bg-accent/
|
|
444
|
-
featured && "mx-1
|
|
445
|
-
active && "bg-
|
|
498
|
+
"hover:bg-accent/50 focus:bg-accent/50",
|
|
499
|
+
featured && "mx-1 border border-primary/10 bg-primary/[0.04] px-2.5",
|
|
500
|
+
active && "bg-primary/10 font-medium text-foreground ring-1 ring-inset ring-primary/25 hover:bg-primary/15 focus:bg-primary/15"
|
|
446
501
|
),
|
|
447
502
|
children
|
|
448
503
|
}
|
|
@@ -715,6 +770,9 @@ var BRAND_INFO = {
|
|
|
715
770
|
export {
|
|
716
771
|
moonshot_default,
|
|
717
772
|
canonicalModelId,
|
|
773
|
+
modelDedupKey,
|
|
774
|
+
dedupeModels,
|
|
775
|
+
DEFAULT_FEATURED_MODEL_IDS,
|
|
718
776
|
formatPricing,
|
|
719
777
|
formatContext,
|
|
720
778
|
ModelPicker
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HARNESS_OPTIONS,
|
|
3
|
-
HarnessLogo
|
|
4
|
-
|
|
3
|
+
HarnessLogo,
|
|
4
|
+
chatCapableHarnesses
|
|
5
|
+
} from "./chunk-ELGN7DPS.js";
|
|
5
6
|
import {
|
|
6
7
|
ModelPicker,
|
|
7
8
|
canonicalModelId
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-6NQBODYV.js";
|
|
9
10
|
import {
|
|
10
11
|
cn
|
|
11
12
|
} from "./chunk-EI44GEQ5.js";
|
|
@@ -145,7 +146,7 @@ function ReasoningLevelPicker({
|
|
|
145
146
|
|
|
146
147
|
// src/chat/agent-session-controls.tsx
|
|
147
148
|
import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
|
|
148
|
-
import { ChevronDown as ChevronDown2, Lock } from "lucide-react";
|
|
149
|
+
import { ChevronDown as ChevronDown2, Lock, SlidersHorizontal } from "lucide-react";
|
|
149
150
|
|
|
150
151
|
// src/chat/harness-model-compat.ts
|
|
151
152
|
var HARNESS_MODEL_POLICIES = {
|
|
@@ -222,7 +223,9 @@ function HarnessDropdown({
|
|
|
222
223
|
available,
|
|
223
224
|
disabled,
|
|
224
225
|
locked,
|
|
225
|
-
lockReason
|
|
226
|
+
lockReason,
|
|
227
|
+
side = "bottom",
|
|
228
|
+
align = "start"
|
|
226
229
|
}) {
|
|
227
230
|
const allowed = new Set(
|
|
228
231
|
available ?? HARNESS_OPTIONS.map((h) => h.type)
|
|
@@ -239,8 +242,8 @@ function HarnessDropdown({
|
|
|
239
242
|
className: cn(
|
|
240
243
|
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-border bg-card px-2.5",
|
|
241
244
|
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
242
|
-
"hover:border-primary/30 hover:bg-accent/
|
|
243
|
-
"data-[state=open]:border-primary/40 data-[state=open]:bg-accent/
|
|
245
|
+
"hover:border-primary/30 hover:bg-accent/40 focus:outline-none focus:border-primary/40",
|
|
246
|
+
"data-[state=open]:border-primary/40 data-[state=open]:bg-accent/40",
|
|
244
247
|
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
245
248
|
),
|
|
246
249
|
"aria-label": "Agent harness",
|
|
@@ -254,7 +257,8 @@ function HarnessDropdown({
|
|
|
254
257
|
/* @__PURE__ */ jsx2(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx2(
|
|
255
258
|
DropdownMenu2.Content,
|
|
256
259
|
{
|
|
257
|
-
|
|
260
|
+
side,
|
|
261
|
+
align,
|
|
258
262
|
sideOffset: 6,
|
|
259
263
|
className: cn(
|
|
260
264
|
"z-50 w-72 overflow-hidden rounded-[var(--radius-md)] border border-border bg-card p-1",
|
|
@@ -272,8 +276,8 @@ function HarnessDropdown({
|
|
|
272
276
|
},
|
|
273
277
|
className: cn(
|
|
274
278
|
"flex cursor-pointer items-start gap-2.5 rounded-md px-2.5 py-2 outline-none",
|
|
275
|
-
"transition-colors hover:bg-accent/
|
|
276
|
-
option.type === value && "bg-
|
|
279
|
+
"transition-colors hover:bg-accent/50 focus:bg-accent/50",
|
|
280
|
+
option.type === value && "bg-primary/10 font-medium text-foreground ring-1 ring-inset ring-primary/25 hover:bg-primary/15 focus:bg-primary/15"
|
|
277
281
|
),
|
|
278
282
|
children: [
|
|
279
283
|
/* @__PURE__ */ jsx2(HarnessLogo, { type: option.type, size: 20, className: "mt-0.5" }),
|
|
@@ -294,7 +298,9 @@ function AgentSessionControls({
|
|
|
294
298
|
model,
|
|
295
299
|
reasoning,
|
|
296
300
|
trailing,
|
|
297
|
-
className
|
|
301
|
+
className,
|
|
302
|
+
context = "chat",
|
|
303
|
+
layout = "inline"
|
|
298
304
|
}) {
|
|
299
305
|
if (!harness && !model && !reasoning && !trailing) return null;
|
|
300
306
|
const handleHarnessChange = (next) => {
|
|
@@ -317,41 +323,139 @@ function AgentSessionControls({
|
|
|
317
323
|
canonicalModelId(entry)
|
|
318
324
|
)
|
|
319
325
|
) : model?.models;
|
|
326
|
+
const harnessAvailable = harness?.available ?? (context === "chat" ? chatCapableHarnesses : void 0);
|
|
327
|
+
const menuSide = layout === "gear" ? "left" : "bottom";
|
|
328
|
+
const menuAlign = layout === "gear" ? "end" : "start";
|
|
329
|
+
const harnessNode = harness && /* @__PURE__ */ jsx2(
|
|
330
|
+
HarnessDropdown,
|
|
331
|
+
{
|
|
332
|
+
...harness,
|
|
333
|
+
available: harnessAvailable,
|
|
334
|
+
onChange: handleHarnessChange,
|
|
335
|
+
side: menuSide,
|
|
336
|
+
align: menuAlign
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
const modelNode = model && /* @__PURE__ */ jsx2(
|
|
340
|
+
ModelPicker,
|
|
341
|
+
{
|
|
342
|
+
variant: "pill",
|
|
343
|
+
label: "",
|
|
344
|
+
value: model.value,
|
|
345
|
+
onChange: handleModelChange,
|
|
346
|
+
models: visibleModels ?? [],
|
|
347
|
+
loading: model.loading,
|
|
348
|
+
popular: model.popular,
|
|
349
|
+
recents: model.recents,
|
|
350
|
+
disabled: model.disabled || (visibleModels ?? []).length === 0
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
const reasoningNode = reasoning && /* @__PURE__ */ jsx2(
|
|
354
|
+
ReasoningLevelPicker,
|
|
355
|
+
{
|
|
356
|
+
value: reasoning.value,
|
|
357
|
+
onChange: reasoning.onChange,
|
|
358
|
+
options: reasoning.options,
|
|
359
|
+
disabled: reasoning.disabled
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
if (layout === "gear") {
|
|
363
|
+
return /* @__PURE__ */ jsx2(
|
|
364
|
+
GearControls,
|
|
365
|
+
{
|
|
366
|
+
className,
|
|
367
|
+
harnessNode,
|
|
368
|
+
modelNode,
|
|
369
|
+
reasoningNode,
|
|
370
|
+
trailing
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
}
|
|
320
374
|
return /* @__PURE__ */ jsxs2(
|
|
321
375
|
"div",
|
|
322
376
|
{
|
|
323
377
|
className: cn("flex flex-wrap items-center gap-2", className),
|
|
324
378
|
"data-testid": "agent-session-controls",
|
|
325
379
|
children: [
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
{
|
|
330
|
-
variant: "pill",
|
|
331
|
-
label: "",
|
|
332
|
-
value: model.value,
|
|
333
|
-
onChange: handleModelChange,
|
|
334
|
-
models: visibleModels ?? [],
|
|
335
|
-
loading: model.loading,
|
|
336
|
-
popular: model.popular,
|
|
337
|
-
recents: model.recents,
|
|
338
|
-
disabled: model.disabled || (visibleModels ?? []).length === 0
|
|
339
|
-
}
|
|
340
|
-
),
|
|
341
|
-
reasoning && /* @__PURE__ */ jsx2(
|
|
342
|
-
ReasoningLevelPicker,
|
|
343
|
-
{
|
|
344
|
-
value: reasoning.value,
|
|
345
|
-
onChange: reasoning.onChange,
|
|
346
|
-
options: reasoning.options,
|
|
347
|
-
disabled: reasoning.disabled
|
|
348
|
-
}
|
|
349
|
-
),
|
|
380
|
+
harnessNode,
|
|
381
|
+
modelNode,
|
|
382
|
+
reasoningNode,
|
|
350
383
|
trailing && /* @__PURE__ */ jsx2("div", { className: "ml-auto flex items-center gap-2", children: trailing })
|
|
351
384
|
]
|
|
352
385
|
}
|
|
353
386
|
);
|
|
354
387
|
}
|
|
388
|
+
function GearControls({
|
|
389
|
+
className,
|
|
390
|
+
harnessNode,
|
|
391
|
+
modelNode,
|
|
392
|
+
reasoningNode,
|
|
393
|
+
trailing
|
|
394
|
+
}) {
|
|
395
|
+
return /* @__PURE__ */ jsxs2(
|
|
396
|
+
"div",
|
|
397
|
+
{
|
|
398
|
+
className: cn("flex items-center gap-2", className),
|
|
399
|
+
"data-testid": "agent-session-controls",
|
|
400
|
+
children: [
|
|
401
|
+
trailing && /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2", children: trailing }),
|
|
402
|
+
/* @__PURE__ */ jsxs2(DropdownMenu2.Root, { children: [
|
|
403
|
+
/* @__PURE__ */ jsx2(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
404
|
+
"button",
|
|
405
|
+
{
|
|
406
|
+
type: "button",
|
|
407
|
+
"aria-label": "Session controls",
|
|
408
|
+
className: cn(
|
|
409
|
+
"inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border bg-card",
|
|
410
|
+
"text-foreground shadow-sm transition-colors",
|
|
411
|
+
"hover:border-primary/30 hover:bg-accent/40 focus:outline-none focus:border-primary/40",
|
|
412
|
+
"data-[state=open]:border-primary/40 data-[state=open]:bg-accent/40"
|
|
413
|
+
),
|
|
414
|
+
children: /* @__PURE__ */ jsx2(SlidersHorizontal, { className: "h-4 w-4 text-muted-foreground" })
|
|
415
|
+
}
|
|
416
|
+
) }),
|
|
417
|
+
/* @__PURE__ */ jsx2(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs2(
|
|
418
|
+
DropdownMenu2.Content,
|
|
419
|
+
{
|
|
420
|
+
side: "top",
|
|
421
|
+
align: "end",
|
|
422
|
+
sideOffset: 8,
|
|
423
|
+
onInteractOutside: (event) => {
|
|
424
|
+
const target = event.target;
|
|
425
|
+
if (target?.closest(
|
|
426
|
+
"[data-radix-popper-content-wrapper],[data-radix-menu-content],[role=menu],[role=listbox]"
|
|
427
|
+
)) {
|
|
428
|
+
event.preventDefault();
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
className: cn(
|
|
432
|
+
"z-50 flex w-56 flex-col gap-2 rounded-[var(--radius-md)] border border-border bg-card p-2",
|
|
433
|
+
"shadow-[var(--shadow-dropdown)]",
|
|
434
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
435
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
436
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
437
|
+
),
|
|
438
|
+
children: [
|
|
439
|
+
harnessNode && /* @__PURE__ */ jsx2(GearSection, { label: "Harness", children: harnessNode }),
|
|
440
|
+
modelNode && /* @__PURE__ */ jsx2(GearSection, { label: "Model", children: modelNode }),
|
|
441
|
+
reasoningNode && /* @__PURE__ */ jsx2(GearSection, { label: "Effort", children: reasoningNode })
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
) })
|
|
445
|
+
] })
|
|
446
|
+
]
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
function GearSection({
|
|
451
|
+
label,
|
|
452
|
+
children
|
|
453
|
+
}) {
|
|
454
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", children: [
|
|
455
|
+
/* @__PURE__ */ jsx2("span", { className: "px-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70", children: label }),
|
|
456
|
+
children
|
|
457
|
+
] });
|
|
458
|
+
}
|
|
355
459
|
|
|
356
460
|
// src/chat/artifact-agent-dock.tsx
|
|
357
461
|
import * as React from "react";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
moonshot_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6NQBODYV.js";
|
|
4
4
|
import {
|
|
5
5
|
cn
|
|
6
6
|
} from "./chunk-EI44GEQ5.js";
|
|
@@ -166,54 +166,65 @@ var HARNESS_OPTIONS = [
|
|
|
166
166
|
{
|
|
167
167
|
type: "opencode",
|
|
168
168
|
label: "OpenCode",
|
|
169
|
-
description: "Default agent \u2014 broad model support, deterministic streaming"
|
|
169
|
+
description: "Default agent \u2014 broad model support, deterministic streaming",
|
|
170
|
+
chatCapable: true
|
|
170
171
|
},
|
|
171
172
|
{
|
|
172
173
|
type: "claude-code",
|
|
173
174
|
label: "Claude Code",
|
|
174
|
-
description: "Native Claude skills and tools (requires ANTHROPIC_API_KEY)"
|
|
175
|
+
description: "Native Claude skills and tools (requires ANTHROPIC_API_KEY)",
|
|
176
|
+
chatCapable: true
|
|
175
177
|
},
|
|
176
178
|
{
|
|
177
179
|
type: "codex",
|
|
178
180
|
label: "Codex",
|
|
179
|
-
description: "OpenAI Codex CLI (requires OPENAI_API_KEY)"
|
|
181
|
+
description: "OpenAI Codex CLI (requires OPENAI_API_KEY)",
|
|
182
|
+
chatCapable: true
|
|
180
183
|
},
|
|
181
184
|
{
|
|
182
185
|
type: "amp",
|
|
183
186
|
label: "AMP",
|
|
184
|
-
description: "Sourcegraph AMP agent"
|
|
187
|
+
description: "Sourcegraph AMP agent",
|
|
188
|
+
chatCapable: true
|
|
185
189
|
},
|
|
186
190
|
{
|
|
187
191
|
type: "factory-droids",
|
|
188
192
|
label: "Factory Droids",
|
|
189
|
-
description: "Factory Droid agent"
|
|
193
|
+
description: "Factory Droid agent",
|
|
194
|
+
chatCapable: true
|
|
190
195
|
},
|
|
191
196
|
{
|
|
192
197
|
type: "kimi-code",
|
|
193
198
|
label: "Kimi Code",
|
|
194
|
-
description: "Moonshot Kimi Code CLI (Kimi subscription OAuth or MOONSHOT_API_KEY)"
|
|
199
|
+
description: "Moonshot Kimi Code CLI (Kimi subscription OAuth or MOONSHOT_API_KEY)",
|
|
200
|
+
chatCapable: true
|
|
195
201
|
},
|
|
196
202
|
{
|
|
197
203
|
type: "openclaw",
|
|
198
204
|
label: "OpenClaw",
|
|
199
|
-
description: "Dispatcher routing to Claude / Codex / Gemini CLIs"
|
|
205
|
+
description: "Dispatcher routing to Claude / Codex / Gemini CLIs",
|
|
206
|
+
chatCapable: true
|
|
200
207
|
},
|
|
201
208
|
{
|
|
202
209
|
type: "nanoclaw",
|
|
203
210
|
label: "NanoClaw",
|
|
204
|
-
description: "Local socket-bridge agent backend"
|
|
211
|
+
description: "Local socket-bridge agent backend",
|
|
212
|
+
chatCapable: true
|
|
205
213
|
},
|
|
206
214
|
{
|
|
207
215
|
type: "hermes",
|
|
208
216
|
label: "Hermes",
|
|
209
|
-
description: "Hermes inference-router agent"
|
|
217
|
+
description: "Hermes inference-router agent",
|
|
218
|
+
chatCapable: true
|
|
210
219
|
},
|
|
211
220
|
{
|
|
212
221
|
type: "cli-base",
|
|
213
222
|
label: "CLI base (no agent)",
|
|
214
|
-
description: "Shell tools only \u2014 for non-AI scheduled tasks"
|
|
223
|
+
description: "Shell tools only \u2014 for non-AI scheduled tasks",
|
|
224
|
+
chatCapable: false
|
|
215
225
|
}
|
|
216
226
|
];
|
|
227
|
+
var chatCapableHarnesses = HARNESS_OPTIONS.filter((h) => h.chatCapable).map((h) => h.type);
|
|
217
228
|
function HarnessPicker({
|
|
218
229
|
value,
|
|
219
230
|
onChange,
|
|
@@ -249,5 +260,6 @@ export {
|
|
|
249
260
|
HARNESS_BRAND,
|
|
250
261
|
HarnessLogo,
|
|
251
262
|
HARNESS_OPTIONS,
|
|
263
|
+
chatCapableHarnesses,
|
|
252
264
|
HarnessPicker
|
|
253
265
|
};
|
|
@@ -975,31 +975,31 @@ function SessionSidebar({
|
|
|
975
975
|
className: cn("relative flex shrink-0 flex-col border-r border-border bg-card", className),
|
|
976
976
|
style: { width: resizable ? resize.width : defaultWidth },
|
|
977
977
|
children: [
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center
|
|
980
|
-
/* @__PURE__ */
|
|
981
|
-
|
|
982
|
-
/* @__PURE__ */
|
|
983
|
-
|
|
984
|
-
subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-[10px] text-muted-foreground", children: subtitle })
|
|
985
|
-
] })
|
|
986
|
-
] }),
|
|
987
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 shrink-0", children: [
|
|
988
|
-
runningCount > 0 && /* @__PURE__ */ jsx7("span", { className: "rounded-full border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] px-1.5 py-px text-[10px] font-medium text-primary", children: runningCount }),
|
|
989
|
-
onCreate && /* @__PURE__ */ jsx7(
|
|
990
|
-
"button",
|
|
991
|
-
{
|
|
992
|
-
type: "button",
|
|
993
|
-
onClick: onCreate,
|
|
994
|
-
title: createLabel,
|
|
995
|
-
className: "flex h-6 w-6 items-center justify-center rounded-[var(--radius-sm)] border border-border text-muted-foreground transition-colors hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
996
|
-
children: /* @__PURE__ */ jsx7(Plus, { className: "h-3 w-3" })
|
|
997
|
-
}
|
|
998
|
-
)
|
|
978
|
+
/* @__PURE__ */ jsx7("div", { className: "flex h-14 shrink-0 items-center border-b border-border px-3", children: /* @__PURE__ */ jsxs7("div", { className: "flex w-full items-center justify-between gap-2", children: [
|
|
979
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
980
|
+
/* @__PURE__ */ jsx7("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-primary", children: /* @__PURE__ */ jsx7(MessageSquareText, { className: "h-3.5 w-3.5" }) }),
|
|
981
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
982
|
+
/* @__PURE__ */ jsx7("div", { className: "truncate text-sm font-semibold text-foreground", children: title }),
|
|
983
|
+
subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-xs text-muted-foreground", children: subtitle })
|
|
999
984
|
] })
|
|
1000
985
|
] }),
|
|
1001
|
-
|
|
1002
|
-
/* @__PURE__ */ jsx7(
|
|
986
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
987
|
+
runningCount > 0 && /* @__PURE__ */ jsx7("span", { className: "rounded-full border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] px-1.5 py-px text-xs font-medium text-primary", children: runningCount }),
|
|
988
|
+
onCreate && /* @__PURE__ */ jsx7(
|
|
989
|
+
"button",
|
|
990
|
+
{
|
|
991
|
+
type: "button",
|
|
992
|
+
onClick: onCreate,
|
|
993
|
+
title: createLabel,
|
|
994
|
+
className: "flex h-7 w-7 items-center justify-center rounded-[var(--radius-sm)] border border-border text-muted-foreground transition-colors hover:bg-[var(--accent-surface-soft)] hover:text-foreground",
|
|
995
|
+
children: /* @__PURE__ */ jsx7(Plus, { className: "h-3.5 w-3.5" })
|
|
996
|
+
}
|
|
997
|
+
)
|
|
998
|
+
] })
|
|
999
|
+
] }) }),
|
|
1000
|
+
(enableSearch && items.length > 0 || filters.length > 0) && /* @__PURE__ */ jsxs7("div", { className: "shrink-0 border-b border-border px-3 py-2.5", children: [
|
|
1001
|
+
enableSearch && items.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
|
|
1002
|
+
/* @__PURE__ */ jsx7(Search2, { className: "pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
|
|
1003
1003
|
/* @__PURE__ */ jsx7(
|
|
1004
1004
|
"input",
|
|
1005
1005
|
{
|
|
@@ -1007,11 +1007,11 @@ function SessionSidebar({
|
|
|
1007
1007
|
onChange: (event) => setQuery(event.target.value),
|
|
1008
1008
|
placeholder: searchPlaceholder,
|
|
1009
1009
|
"aria-label": searchPlaceholder,
|
|
1010
|
-
className: "h-
|
|
1010
|
+
className: "h-8 w-full rounded-[var(--radius-sm)] border border-border bg-muted pl-7 pr-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--border-accent)]"
|
|
1011
1011
|
}
|
|
1012
1012
|
)
|
|
1013
1013
|
] }),
|
|
1014
|
-
filters.length > 0 && /* @__PURE__ */ jsx7("div", { className: "
|
|
1014
|
+
filters.length > 0 && /* @__PURE__ */ jsx7("div", { className: cn("flex flex-wrap gap-1", enableSearch && items.length > 0 && "mt-2"), children: filters.map((filter) => {
|
|
1015
1015
|
const isSelected = activeFilterId === filter.id;
|
|
1016
1016
|
return /* @__PURE__ */ jsxs7(
|
|
1017
1017
|
"button",
|
|
@@ -1019,19 +1019,19 @@ function SessionSidebar({
|
|
|
1019
1019
|
type: "button",
|
|
1020
1020
|
onClick: () => setActiveFilterId(filter.id),
|
|
1021
1021
|
className: cn(
|
|
1022
|
-
"inline-flex items-center gap-1 rounded-full border px-2 py-
|
|
1022
|
+
"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-colors",
|
|
1023
1023
|
isSelected ? "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-primary" : "border-border text-muted-foreground hover:text-foreground"
|
|
1024
1024
|
),
|
|
1025
1025
|
children: [
|
|
1026
1026
|
/* @__PURE__ */ jsx7("span", { children: filter.label }),
|
|
1027
|
-
/* @__PURE__ */ jsx7("span", { className: "text-[
|
|
1027
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[11px] opacity-60", children: filterCounts[filter.id] ?? 0 })
|
|
1028
1028
|
]
|
|
1029
1029
|
},
|
|
1030
1030
|
filter.id
|
|
1031
1031
|
);
|
|
1032
1032
|
}) })
|
|
1033
1033
|
] }),
|
|
1034
|
-
/* @__PURE__ */ jsx7("nav", { "aria-label": "Sessions", className: "flex-1 overflow-y-auto px-1.5 py-1.5", children: visibleItems.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "rounded-[var(--radius-lg)] border border-dashed border-border px-3 py-3 text-
|
|
1034
|
+
/* @__PURE__ */ jsx7("nav", { "aria-label": "Sessions", className: "flex-1 overflow-y-auto px-1.5 py-1.5", children: visibleItems.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "rounded-[var(--radius-lg)] border border-dashed border-border px-3 py-3 text-sm text-muted-foreground", children: query.trim() ? `No sessions match "${query.trim()}".` : emptyMessage }) : /* @__PURE__ */ jsx7("ul", { className: "space-y-px", children: visibleItems.map((item) => {
|
|
1035
1035
|
const session = sessionsById.get(item.id) ?? null;
|
|
1036
1036
|
const isActive = currentItemId === item.id;
|
|
1037
1037
|
const status = session?.status ?? item.status;
|
|
@@ -1043,8 +1043,8 @@ function SessionSidebar({
|
|
|
1043
1043
|
"div",
|
|
1044
1044
|
{
|
|
1045
1045
|
className: cn(
|
|
1046
|
-
"group relative flex items-center gap-2 rounded-[var(--radius-sm)] px-
|
|
1047
|
-
isActive ? "bg-
|
|
1046
|
+
"group relative flex items-center gap-2 rounded-[var(--radius-sm)] px-3 py-2 transition-colors",
|
|
1047
|
+
isActive ? "bg-primary/10 font-medium text-foreground" : "text-muted-foreground hover:bg-accent/30"
|
|
1048
1048
|
),
|
|
1049
1049
|
children: [
|
|
1050
1050
|
/* @__PURE__ */ jsxs7(
|
|
@@ -1064,10 +1064,10 @@ function SessionSidebar({
|
|
|
1064
1064
|
/* @__PURE__ */ jsx7("span", { className: cn("h-1.5 w-1.5 shrink-0 rounded-full", statusDot(status)) }),
|
|
1065
1065
|
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
1066
1066
|
/* @__PURE__ */ jsx7("div", { className: cn(
|
|
1067
|
-
"truncate text-
|
|
1068
|
-
isActive
|
|
1067
|
+
"truncate text-sm font-medium",
|
|
1068
|
+
isActive && "text-foreground"
|
|
1069
1069
|
), children: item.title }),
|
|
1070
|
-
item.subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-
|
|
1070
|
+
item.subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-xs leading-tight text-muted-foreground", children: item.subtitle })
|
|
1071
1071
|
] })
|
|
1072
1072
|
]
|
|
1073
1073
|
}
|
|
@@ -1112,9 +1112,9 @@ function SessionSidebar({
|
|
|
1112
1112
|
}
|
|
1113
1113
|
navigateToHref(link.href);
|
|
1114
1114
|
},
|
|
1115
|
-
className: "flex w-full items-center gap-2 rounded-[var(--radius-sm)] px-
|
|
1115
|
+
className: "flex w-full items-center gap-2 rounded-[var(--radius-sm)] px-3 py-2 text-left text-sm text-muted-foreground transition-colors hover:bg-accent/30 hover:text-foreground",
|
|
1116
1116
|
children: [
|
|
1117
|
-
/* @__PURE__ */ jsx7(Icon, { className: "h-
|
|
1117
|
+
/* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4 shrink-0" }),
|
|
1118
1118
|
/* @__PURE__ */ jsx7("span", { className: "truncate", children: link.label })
|
|
1119
1119
|
]
|
|
1120
1120
|
},
|