@tangle-network/sandbox-ui 0.20.3 → 0.21.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.
@@ -1,3 +1,9 @@
1
+ import {
2
+ HARNESS_OPTIONS
3
+ } from "./chunk-ESRYVGHF.js";
4
+ import {
5
+ ModelPicker
6
+ } from "./chunk-4KAPMTPU.js";
1
7
  import {
2
8
  cn
3
9
  } from "./chunk-EI44GEQ5.js";
@@ -92,11 +98,126 @@ function ReasoningLevelPicker({
92
98
  ] });
93
99
  }
94
100
 
101
+ // src/chat/agent-session-controls.tsx
102
+ import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
103
+ import { Bot, ChevronDown as ChevronDown2 } from "lucide-react";
104
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
105
+ function HarnessDropdown({
106
+ value,
107
+ onChange,
108
+ available,
109
+ disabled
110
+ }) {
111
+ const allowed = new Set(
112
+ available ?? HARNESS_OPTIONS.map((h) => h.type)
113
+ );
114
+ const options = HARNESS_OPTIONS.filter((h) => allowed.has(h.type));
115
+ const selected = options.find((option) => option.type === value);
116
+ return /* @__PURE__ */ jsxs2(DropdownMenu2.Root, { children: [
117
+ /* @__PURE__ */ jsx2(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
118
+ "button",
119
+ {
120
+ type: "button",
121
+ disabled,
122
+ className: cn(
123
+ "inline-flex h-8 items-center gap-1.5 rounded-lg border border-border bg-card px-2.5",
124
+ "text-xs font-medium text-foreground shadow-sm transition-colors",
125
+ "hover:border-primary/30 hover:bg-accent/30 focus:outline-none focus:border-primary/40",
126
+ "data-[state=open]:border-primary/40 data-[state=open]:bg-accent/30",
127
+ "disabled:cursor-not-allowed disabled:opacity-50"
128
+ ),
129
+ "aria-label": "Agent harness",
130
+ children: [
131
+ /* @__PURE__ */ jsx2(Bot, { className: "h-3.5 w-3.5 text-muted-foreground" }),
132
+ /* @__PURE__ */ jsx2("span", { children: selected?.label ?? value }),
133
+ /* @__PURE__ */ jsx2(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
134
+ ]
135
+ }
136
+ ) }),
137
+ /* @__PURE__ */ jsx2(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx2(
138
+ DropdownMenu2.Content,
139
+ {
140
+ align: "start",
141
+ sideOffset: 6,
142
+ className: cn(
143
+ "z-50 w-72 overflow-hidden rounded-[var(--radius-md)] border border-border bg-card p-1",
144
+ "shadow-[var(--shadow-dropdown)]",
145
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
146
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
147
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
148
+ ),
149
+ children: options.map((option) => /* @__PURE__ */ jsxs2(
150
+ DropdownMenu2.Item,
151
+ {
152
+ onSelect: (event) => {
153
+ event.preventDefault();
154
+ onChange(option.type);
155
+ },
156
+ className: cn(
157
+ "flex cursor-pointer flex-col gap-0.5 rounded-md px-2.5 py-2 outline-none",
158
+ "transition-colors hover:bg-accent/40 focus:bg-accent/40",
159
+ option.type === value && "bg-[var(--accent-surface-soft)] text-[var(--accent-text)]"
160
+ ),
161
+ children: [
162
+ /* @__PURE__ */ jsx2("span", { className: "text-sm font-medium", children: option.label }),
163
+ option.description && /* @__PURE__ */ jsx2("span", { className: "text-xs text-muted-foreground", children: option.description })
164
+ ]
165
+ },
166
+ option.type
167
+ ))
168
+ }
169
+ ) })
170
+ ] });
171
+ }
172
+ function AgentSessionControls({
173
+ harness,
174
+ model,
175
+ reasoning,
176
+ trailing,
177
+ className
178
+ }) {
179
+ if (!harness && !model && !reasoning && !trailing) return null;
180
+ return /* @__PURE__ */ jsxs2(
181
+ "div",
182
+ {
183
+ className: cn("flex flex-wrap items-center gap-2", className),
184
+ "data-testid": "agent-session-controls",
185
+ children: [
186
+ harness && /* @__PURE__ */ jsx2(HarnessDropdown, { ...harness }),
187
+ model && /* @__PURE__ */ jsx2(
188
+ ModelPicker,
189
+ {
190
+ variant: "pill",
191
+ label: "",
192
+ value: model.value,
193
+ onChange: model.onChange,
194
+ models: model.models,
195
+ loading: model.loading,
196
+ popular: model.popular,
197
+ recents: model.recents,
198
+ disabled: model.disabled || model.models.length === 0
199
+ }
200
+ ),
201
+ reasoning && /* @__PURE__ */ jsx2(
202
+ ReasoningLevelPicker,
203
+ {
204
+ value: reasoning.value,
205
+ onChange: reasoning.onChange,
206
+ options: reasoning.options,
207
+ disabled: reasoning.disabled
208
+ }
209
+ ),
210
+ trailing && /* @__PURE__ */ jsx2("div", { className: "ml-auto flex items-center gap-2", children: trailing })
211
+ ]
212
+ }
213
+ );
214
+ }
215
+
95
216
  // src/chat/artifact-agent-dock.tsx
96
217
  import * as React from "react";
97
218
  import { Sparkles, Send, Square, X } from "lucide-react";
98
219
  import { ChatMessage } from "@tangle-network/ui/chat";
99
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
220
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
100
221
  function defaultScopeLabel(scope) {
101
222
  if (scope.label) return scope.label;
102
223
  switch (scope.kind) {
@@ -262,7 +383,7 @@ function ArtifactAgentDock({
262
383
  }, [threadId, transport]);
263
384
  if (!open) return null;
264
385
  const heading = defaultScopeLabel(scope);
265
- return /* @__PURE__ */ jsxs2(
386
+ return /* @__PURE__ */ jsxs3(
266
387
  "aside",
267
388
  {
268
389
  className: cn(
@@ -271,38 +392,38 @@ function ArtifactAgentDock({
271
392
  ),
272
393
  "aria-label": `Agent chat about ${heading}`,
273
394
  children: [
274
- /* @__PURE__ */ jsxs2("header", { className: "flex items-center justify-between border-b border-border bg-background/60 px-4 py-3", children: [
275
- /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 items-center gap-2", children: [
276
- /* @__PURE__ */ jsx2(Sparkles, { className: "h-4 w-4 shrink-0 text-primary" }),
277
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
278
- /* @__PURE__ */ jsx2("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: "Discussing" }),
279
- /* @__PURE__ */ jsx2("div", { className: "truncate text-sm font-semibold text-foreground", children: heading })
395
+ /* @__PURE__ */ jsxs3("header", { className: "flex items-center justify-between border-b border-border bg-background/60 px-4 py-3", children: [
396
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
397
+ /* @__PURE__ */ jsx3(Sparkles, { className: "h-4 w-4 shrink-0 text-primary" }),
398
+ /* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
399
+ /* @__PURE__ */ jsx3("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: "Discussing" }),
400
+ /* @__PURE__ */ jsx3("div", { className: "truncate text-sm font-semibold text-foreground", children: heading })
280
401
  ] })
281
402
  ] }),
282
- /* @__PURE__ */ jsx2(
403
+ /* @__PURE__ */ jsx3(
283
404
  "button",
284
405
  {
285
406
  type: "button",
286
407
  onClick: () => onOpenChange(false),
287
408
  "aria-label": "Close artifact chat",
288
409
  className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
289
- children: /* @__PURE__ */ jsx2(X, { className: "h-4 w-4" })
410
+ children: /* @__PURE__ */ jsx3(X, { className: "h-4 w-4" })
290
411
  }
291
412
  )
292
413
  ] }),
293
- /* @__PURE__ */ jsx2("div", { ref: scrollRef, className: "flex-1 overflow-y-auto px-3 py-4", children: loading ? /* @__PURE__ */ jsx2("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: "Loading conversation\u2026" }) : messages.length === 0 && !streamContent ? /* @__PURE__ */ jsxs2("div", { className: "px-3 py-12 text-center", children: [
294
- /* @__PURE__ */ jsx2(Sparkles, { className: "mx-auto mb-3 h-5 w-5 text-muted-foreground/40" }),
295
- /* @__PURE__ */ jsxs2("p", { className: "text-sm text-foreground", children: [
414
+ /* @__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: [
415
+ /* @__PURE__ */ jsx3(Sparkles, { className: "mx-auto mb-3 h-5 w-5 text-muted-foreground/40" }),
416
+ /* @__PURE__ */ jsxs3("p", { className: "text-sm text-foreground", children: [
296
417
  "Ask the agent about this ",
297
418
  scope.kind === "vault-file" ? "document" : scope.kind,
298
419
  "."
299
420
  ] }),
300
- /* @__PURE__ */ jsx2("p", { className: "mt-1 text-xs text-muted-foreground", children: "It can read the current contents and propose edits, rewrites, or follow-ups." })
301
- ] }) : /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
302
- messages.map((m) => /* @__PURE__ */ jsx2(ChatMessage, { role: m.role, content: m.content, timestamp: m.createdAt }, m.id)),
303
- streamContent && /* @__PURE__ */ jsx2(ChatMessage, { role: "assistant", content: streamContent, isStreaming: true })
421
+ /* @__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." })
422
+ ] }) : /* @__PURE__ */ jsxs3("div", { className: "space-y-3", children: [
423
+ messages.map((m) => /* @__PURE__ */ jsx3(ChatMessage, { role: m.role, content: m.content, timestamp: m.createdAt }, m.id)),
424
+ streamContent && /* @__PURE__ */ jsx3(ChatMessage, { role: "assistant", content: streamContent, isStreaming: true })
304
425
  ] }) }),
305
- /* @__PURE__ */ jsx2(
426
+ /* @__PURE__ */ jsx3(
306
427
  "form",
307
428
  {
308
429
  className: "border-t border-border bg-background/60 p-3",
@@ -310,8 +431,8 @@ function ArtifactAgentDock({
310
431
  e.preventDefault();
311
432
  void send();
312
433
  },
313
- children: /* @__PURE__ */ jsxs2("div", { className: "flex items-end gap-2", children: [
314
- /* @__PURE__ */ jsx2(
434
+ children: /* @__PURE__ */ jsxs3("div", { className: "flex items-end gap-2", children: [
435
+ /* @__PURE__ */ jsx3(
315
436
  "textarea",
316
437
  {
317
438
  value: composer,
@@ -328,23 +449,23 @@ function ArtifactAgentDock({
328
449
  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
450
  }
330
451
  ),
331
- sending ? /* @__PURE__ */ jsx2(
452
+ sending ? /* @__PURE__ */ jsx3(
332
453
  "button",
333
454
  {
334
455
  type: "button",
335
456
  onClick: cancel,
336
457
  "aria-label": "Cancel",
337
458
  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__ */ jsx2(Square, { className: "h-4 w-4" })
459
+ children: /* @__PURE__ */ jsx3(Square, { className: "h-4 w-4" })
339
460
  }
340
- ) : /* @__PURE__ */ jsx2(
461
+ ) : /* @__PURE__ */ jsx3(
341
462
  "button",
342
463
  {
343
464
  type: "submit",
344
465
  disabled: !composer.trim() || !threadId,
345
466
  "aria-label": "Send",
346
467
  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__ */ jsx2(Send, { className: "h-4 w-4" })
468
+ children: /* @__PURE__ */ jsx3(Send, { className: "h-4 w-4" })
348
469
  }
349
470
  )
350
471
  ] })
@@ -433,6 +554,7 @@ function createFetchTransport(opts) {
433
554
  export {
434
555
  DEFAULT_REASONING_LEVEL_OPTIONS,
435
556
  ReasoningLevelPicker,
557
+ AgentSessionControls,
436
558
  ArtifactAgentDock,
437
559
  createFetchTransport,
438
560
  AgentTimeline,