@tangle-network/sandbox-ui 0.56.0 → 0.58.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/assistant.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-7JLB7UZ3.js";
10
10
  import {
11
11
  ModelPicker
12
- } from "./chunk-LQHTCM56.js";
12
+ } from "./chunk-SF6LPMMN.js";
13
13
  import "./chunk-EI44GEQ5.js";
14
14
  import "./chunk-U67V476Y.js";
15
15
 
package/dist/chat.d.ts CHANGED
@@ -2,8 +2,10 @@ 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 { ReasoningEffort, HarnessType } from '@tangle-network/agent-interface';
5
+ export { modelProvider, snapHarnessToModel } from '@tangle-network/agent-interface';
6
+ import * as Popover from '@radix-ui/react-dropdown-menu';
5
7
  import * as React from 'react';
6
- import { M as ModelInfo } from './model-picker-NOWFpRY4.js';
8
+ import { M as ModelInfo } from './model-picker-COjPVMzg.js';
7
9
 
8
10
  /**
9
11
  * A reasoning selection: `auto` is a UI-only sentinel ("let the harness/model default decide",
@@ -33,9 +35,18 @@ interface ReasoningLevelPickerProps {
33
35
  * Omit to show every option.
34
36
  */
35
37
  available?: ReadonlyArray<ReasoningEffort>;
38
+ /** Side the menu opens toward. Defaults to Radix's "bottom". */
39
+ side?: Popover.DropdownMenuContentProps["side"];
40
+ /**
41
+ * Let Radix flip the menu to the opposite side when it would overflow the
42
+ * viewport. Defaults to `true` (Radix default). Pass `false` to pin the menu
43
+ * to `side` — e.g. a composer floating in open space that should always open
44
+ * downward rather than flipping up over the heading.
45
+ */
46
+ avoidCollisions?: boolean;
36
47
  }
37
48
  declare const DEFAULT_REASONING_LEVEL_OPTIONS: ReadonlyArray<ReasoningLevelOption>;
38
- declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, available, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
49
+ declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, available, side, avoidCollisions, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
39
50
 
40
51
  interface AgentSessionHarnessControl {
41
52
  value: HarnessType;
@@ -104,6 +115,15 @@ interface AgentSessionControlsProps {
104
115
  * on the left of the gear menu.
105
116
  */
106
117
  layout?: "inline" | "gear";
118
+ /**
119
+ * Where the inline pickers open. `"auto"` (default) keeps Radix's
120
+ * collision-aware behavior: the menus open downward but flip up when the
121
+ * composer is docked at the bottom of the viewport. `"down"` pins them open
122
+ * downward — for a composer floating in open space (e.g. a centered new-chat
123
+ * surface) where flipping up would cover the heading. Only affects the
124
+ * `"inline"` layout; the gear menu is unchanged.
125
+ */
126
+ menuPlacement?: "auto" | "down";
107
127
  }
108
128
  /**
109
129
  * Compact control strip for an agent chat composer: harness, model, and
@@ -119,51 +139,22 @@ interface AgentSessionControlsProps {
119
139
  *
120
140
  * Designed to slot into `SandboxWorkbench`'s `session.composerControls`.
121
141
  */
122
- declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
142
+ declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
123
143
 
124
144
  /**
125
- * Harness ↔ model compatibility policy.
126
- *
127
- * Native CLI harnesses are vendor-locked: claude-code only drives
128
- * Anthropic models, codex only OpenAI models. Router-backed harnesses
129
- * (opencode) accept any catalog model. The pickers use this policy to
130
- * keep the pair coherent: changing one side snaps the other to its
131
- * nearest compatible choice instead of letting the user assemble a
132
- * combination that fails at inference time.
133
- */
134
- interface HarnessModelPolicy {
135
- /** Canonical-id provider prefixes the harness can run; null = any. */
136
- providers: ReadonlyArray<string> | null;
137
- /**
138
- * Patterns ranking snap targets, best first. Within one pattern's
139
- * matches the highest version (numeric-aware descending sort) wins,
140
- * so "latest standard frontier" stays correct as catalogs rotate.
141
- */
142
- preferred: ReadonlyArray<RegExp>;
143
- }
144
- declare const HARNESS_MODEL_POLICIES: Partial<Record<HarnessType, HarnessModelPolicy>>;
145
- /** Provider prefix of a canonical id ("anthropic/claude-…" → "anthropic"). */
146
- declare function modelProvider(modelId: string): string | null;
147
- /**
148
- * Ids without a provider prefix (consumer sentinels like "default",
149
- * or an empty selection) are treated as compatible everywhere — they
150
- * mean "the session's own configuration", which every harness honors.
145
+ * Whether `harness` can run `modelId`. Router-backed harnesses, and provider-less
146
+ * sentinel ids (like "default" or an empty selection — "the session's own
147
+ * configuration"), are compatible with everything.
151
148
  */
152
149
  declare function isModelCompatibleWithHarness(harness: HarnessType, modelId: string): boolean;
153
150
  /**
154
- * Keeps `modelId` when the harness can run it; otherwise returns the
155
- * harness's best compatible catalog model (preferred patterns in order,
156
- * highest version within a pattern). When the catalog holds nothing
157
- * compatible the original id is returned unchanged — the caller sees
158
- * the incompatibility instead of a silent wrong substitution.
151
+ * Keeps `modelId` when the harness can run it; otherwise returns the harness's
152
+ * best compatible model from the loaded catalog (preferred patterns in order,
153
+ * highest version within a pattern). Adapts the picker's `ModelInfo[]` to the
154
+ * canonical id list `agent-interface` ranks over; when the catalog holds nothing
155
+ * compatible the original id is returned unchanged.
159
156
  */
160
157
  declare function snapModelToHarness(harness: HarnessType, modelId: string, models: ReadonlyArray<ModelInfo>): string;
161
- /**
162
- * Keeps the harness when it can run `modelId`; otherwise returns the
163
- * model's native harness (anthropic → claude-code, openai → codex),
164
- * falling back to the router-backed opencode for everything else.
165
- */
166
- declare function snapHarnessToModel(harness: HarnessType, modelId: string): HarnessType;
167
158
 
168
159
  type ArtifactKind = string;
169
160
  interface ArtifactScope {
@@ -262,4 +253,4 @@ declare function createFetchTransport(opts: {
262
253
  fetchImpl?: typeof fetch;
263
254
  }): ArtifactAgentDockTransport;
264
255
 
265
- export { AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, HARNESS_MODEL_POLICIES, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, modelProvider, snapHarnessToModel, snapModelToHarness };
256
+ export { AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness };
package/dist/chat.js CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  ChatInput,
7
7
  ChatMessage,
8
8
  DEFAULT_REASONING_LEVEL_OPTIONS,
9
- HARNESS_MODEL_POLICIES,
10
9
  MessageList,
11
10
  ReasoningLevelPicker,
12
11
  ThinkingIndicator,
@@ -16,9 +15,9 @@ import {
16
15
  modelProvider,
17
16
  snapHarnessToModel,
18
17
  snapModelToHarness
19
- } from "./chunk-KOUYJ6QP.js";
20
- import "./chunk-BR2LMUAE.js";
21
- import "./chunk-LQHTCM56.js";
18
+ } from "./chunk-WLMLD2CZ.js";
19
+ import "./chunk-HU4B2M4K.js";
20
+ import "./chunk-SF6LPMMN.js";
22
21
  import "./chunk-EI44GEQ5.js";
23
22
  import "./chunk-U67V476Y.js";
24
23
  export {
@@ -29,7 +28,6 @@ export {
29
28
  ChatInput,
30
29
  ChatMessage,
31
30
  DEFAULT_REASONING_LEVEL_OPTIONS,
32
- HARNESS_MODEL_POLICIES,
33
31
  MessageList,
34
32
  ReasoningLevelPicker,
35
33
  ThinkingIndicator,
@@ -2014,7 +2014,7 @@ function DashboardLayoutInner({
2014
2014
  /* @__PURE__ */ jsx14(
2015
2015
  RailHeader,
2016
2016
  {
2017
- brand: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: true }),
2017
+ brand: /* @__PURE__ */ jsx14(Logo, { variant, size: "sm", iconOnly: !showLabels }),
2018
2018
  brandHref: logoHref,
2019
2019
  collapsed: !showLabels,
2020
2020
  onToggle: toggleRail,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  moonshot_default
3
- } from "./chunk-LQHTCM56.js";
3
+ } from "./chunk-SF6LPMMN.js";
4
4
  import {
5
5
  cn
6
6
  } from "./chunk-EI44GEQ5.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-3J6FG3FJ.js";
4
4
  import {
5
5
  PortsList
6
- } from "./chunk-SVNWL3ZR.js";
6
+ } from "./chunk-D7JJLG4L.js";
7
7
  import {
8
8
  TerminalView
9
9
  } from "./chunk-VIREDUBF.js";
@@ -262,7 +262,9 @@ function ModelPicker({
262
262
  placeholder = "Choose a model",
263
263
  className,
264
264
  triggerClassName,
265
- disabled
265
+ disabled,
266
+ side,
267
+ avoidCollisions
266
268
  }) {
267
269
  const [query, setQuery] = React.useState("");
268
270
  const [open, setOpen] = React.useState(false);
@@ -394,11 +396,16 @@ function ModelPicker({
394
396
  /* @__PURE__ */ jsx2(Popover.Portal, { children: /* @__PURE__ */ jsxs2(
395
397
  Popover.Content,
396
398
  {
399
+ side,
397
400
  sideOffset: 4,
398
401
  align: variant === "pill" ? "start" : "start",
402
+ avoidCollisions,
403
+ collisionPadding: 24,
399
404
  className: cn(
400
405
  "z-50 w-[var(--radix-dropdown-menu-trigger-width)] min-w-[320px] max-w-[460px]",
401
- "max-h-[440px] overflow-hidden flex flex-col",
406
+ // Cap to the smaller of the fixed height and the viewport space on
407
+ // the open side, so a list pinned downward never runs off-screen.
408
+ "max-h-[min(440px,var(--radix-dropdown-menu-content-available-height))] overflow-hidden flex flex-col",
402
409
  "rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
403
410
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
404
411
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
@@ -2,11 +2,11 @@ import {
2
2
  HARNESS_OPTIONS,
3
3
  HarnessLogo,
4
4
  chatCapableHarnesses
5
- } from "./chunk-BR2LMUAE.js";
5
+ } from "./chunk-HU4B2M4K.js";
6
6
  import {
7
7
  ModelPicker,
8
8
  canonicalModelId
9
- } from "./chunk-LQHTCM56.js";
9
+ } from "./chunk-SF6LPMMN.js";
10
10
  import {
11
11
  cn
12
12
  } from "./chunk-EI44GEQ5.js";
@@ -72,7 +72,9 @@ function ReasoningLevelPicker({
72
72
  className,
73
73
  triggerClassName,
74
74
  options = DEFAULT_REASONING_LEVEL_OPTIONS,
75
- available
75
+ available,
76
+ side,
77
+ avoidCollisions
76
78
  }) {
77
79
  const shown = available ? options.filter((o) => o.value === "auto" || available.includes(o.value)) : options;
78
80
  const selected = shown.find((option) => option.value === value);
@@ -103,10 +105,15 @@ function ReasoningLevelPicker({
103
105
  /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(
104
106
  DropdownMenu.Content,
105
107
  {
108
+ side,
106
109
  align: "start",
110
+ avoidCollisions,
111
+ collisionPadding: 24,
107
112
  sideOffset: 6,
108
113
  className: cn(
109
- "z-50 w-64 overflow-hidden rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
114
+ // Cap to the viewport space on the open side and scroll, so the menu
115
+ // pinned downward (floating composer) never runs off the bottom edge.
116
+ "z-50 w-64 max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
110
117
  "shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
111
118
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
112
119
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
@@ -142,71 +149,16 @@ import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
142
149
  import { ChevronDown as ChevronDown2, Lock, SlidersHorizontal } from "lucide-react";
143
150
 
144
151
  // src/chat/harness-model-compat.ts
145
- var HARNESS_MODEL_POLICIES = {
146
- opencode: { providers: null, preferred: [] },
147
- "claude-code": {
148
- providers: ["anthropic"],
149
- preferred: [
150
- /^anthropic\/claude-opus-[\d.-]+$/,
151
- /^anthropic\/claude-sonnet-[\d.-]+$/,
152
- /^anthropic\//
153
- ]
154
- },
155
- codex: {
156
- providers: ["openai"],
157
- // Standard frontier tier first (gpt-N / gpt-N.N), then any gpt
158
- // variant (mini/nano), then anything OpenAI.
159
- preferred: [/^openai\/gpt-\d+(\.\d+)?$/, /^openai\/gpt/, /^openai\//]
160
- },
161
- amp: { providers: null, preferred: [] },
162
- "factory-droids": { providers: null, preferred: [] },
163
- "cli-base": { providers: null, preferred: [] },
164
- "kimi-code": {
165
- providers: ["moonshot"],
166
- preferred: [/^moonshot\//]
167
- },
168
- openclaw: { providers: null, preferred: [] },
169
- nanoclaw: { providers: null, preferred: [] },
170
- hermes: { providers: null, preferred: [] }
171
- };
172
- var PROVIDER_PREFERRED_HARNESS = {
173
- anthropic: "claude-code",
174
- openai: "codex",
175
- moonshot: "kimi-code"
176
- };
177
- function modelProvider(modelId) {
178
- const slash = modelId.indexOf("/");
179
- return slash > 0 ? modelId.slice(0, slash) : null;
180
- }
152
+ import {
153
+ harnessSupportsModel,
154
+ snapModelToHarness as snapModelIdToHarness
155
+ } from "@tangle-network/agent-interface";
156
+ import { modelProvider, snapHarnessToModel } from "@tangle-network/agent-interface";
181
157
  function isModelCompatibleWithHarness(harness, modelId) {
182
- const policy = HARNESS_MODEL_POLICIES[harness];
183
- if (!policy || policy.providers === null) return true;
184
- const provider = modelProvider(modelId);
185
- if (!provider) return true;
186
- return policy.providers.includes(provider);
158
+ return harnessSupportsModel(harness, modelId);
187
159
  }
188
- var numericDesc = new Intl.Collator(void 0, {
189
- numeric: true,
190
- sensitivity: "base"
191
- });
192
160
  function snapModelToHarness(harness, modelId, models) {
193
- if (isModelCompatibleWithHarness(harness, modelId)) return modelId;
194
- const ids = models.map(canonicalModelId);
195
- const policy = HARNESS_MODEL_POLICIES[harness];
196
- if (!policy) return modelId;
197
- for (const pattern of policy.preferred) {
198
- const matches = ids.filter((id) => pattern.test(id)).sort((a, b) => numericDesc.compare(b, a));
199
- if (matches.length > 0) return matches[0];
200
- }
201
- const fallback = ids.find(
202
- (id) => isModelCompatibleWithHarness(harness, id)
203
- );
204
- return fallback ?? modelId;
205
- }
206
- function snapHarnessToModel(harness, modelId) {
207
- if (isModelCompatibleWithHarness(harness, modelId)) return harness;
208
- const provider = modelProvider(modelId);
209
- return provider && PROVIDER_PREFERRED_HARNESS[provider] || "opencode";
161
+ return snapModelIdToHarness(harness, modelId, models.map(canonicalModelId));
210
162
  }
211
163
 
212
164
  // src/chat/agent-session-controls.tsx
@@ -219,7 +171,8 @@ function HarnessDropdown({
219
171
  locked,
220
172
  lockReason,
221
173
  side = "bottom",
222
- align = "start"
174
+ align = "start",
175
+ avoidCollisions
223
176
  }) {
224
177
  const allowed = new Set(
225
178
  available ?? HARNESS_OPTIONS.map((h) => h.type)
@@ -253,9 +206,14 @@ function HarnessDropdown({
253
206
  {
254
207
  side,
255
208
  align,
209
+ avoidCollisions,
210
+ collisionPadding: 24,
256
211
  sideOffset: 6,
257
212
  className: cn(
258
- "z-50 w-72 overflow-hidden rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
213
+ // Cap to the viewport space on the open side and scroll, so a tall
214
+ // backend list pinned downward (floating composer) never runs off
215
+ // the bottom edge.
216
+ "z-50 w-72 max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
259
217
  "shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
260
218
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
261
219
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
@@ -294,7 +252,8 @@ function AgentSessionControls({
294
252
  trailing,
295
253
  className,
296
254
  context = "chat",
297
- layout = "inline"
255
+ layout = "inline",
256
+ menuPlacement = "auto"
298
257
  }) {
299
258
  if (!harness && !model && !reasoning && !trailing) return null;
300
259
  const handleHarnessChange = (next) => {
@@ -320,6 +279,8 @@ function AgentSessionControls({
320
279
  const harnessAvailable = harness?.available ?? (context === "chat" ? chatCapableHarnesses : void 0);
321
280
  const menuSide = layout === "gear" ? "left" : "bottom";
322
281
  const menuAlign = layout === "gear" ? "end" : "start";
282
+ const inlineForceDown = menuPlacement === "down" && layout !== "gear";
283
+ const avoidCollisions = inlineForceDown ? false : void 0;
323
284
  const harnessNode = harness && /* @__PURE__ */ jsx2(
324
285
  HarnessDropdown,
325
286
  {
@@ -327,7 +288,8 @@ function AgentSessionControls({
327
288
  available: harnessAvailable,
328
289
  onChange: handleHarnessChange,
329
290
  side: menuSide,
330
- align: menuAlign
291
+ align: menuAlign,
292
+ avoidCollisions
331
293
  }
332
294
  );
333
295
  const modelNode = model && /* @__PURE__ */ jsx2(
@@ -341,7 +303,9 @@ function AgentSessionControls({
341
303
  loading: model.loading,
342
304
  popular: model.popular,
343
305
  recents: model.recents,
344
- disabled: model.disabled || (visibleModels ?? []).length === 0
306
+ disabled: model.disabled || (visibleModels ?? []).length === 0,
307
+ side: layout === "gear" ? void 0 : "bottom",
308
+ avoidCollisions
345
309
  }
346
310
  );
347
311
  const selectedModel = model?.models.find(
@@ -358,7 +322,9 @@ function AgentSessionControls({
358
322
  onChange: reasoning.onChange,
359
323
  options: reasoning.options,
360
324
  disabled: reasoning.disabled,
361
- available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available
325
+ available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available,
326
+ side: layout === "gear" ? void 0 : "bottom",
327
+ avoidCollisions
362
328
  }
363
329
  );
364
330
  if (layout === "gear") {
@@ -800,10 +766,9 @@ function createFetchTransport(opts) {
800
766
  export {
801
767
  DEFAULT_REASONING_LEVEL_OPTIONS,
802
768
  ReasoningLevelPicker,
803
- HARNESS_MODEL_POLICIES,
804
- modelProvider,
805
769
  isModelCompatibleWithHarness,
806
770
  snapModelToHarness,
771
+ modelProvider,
807
772
  snapHarnessToModel,
808
773
  AgentSessionControls,
809
774
  ArtifactAgentDock,
@@ -3,9 +3,10 @@ import * as React from 'react';
3
3
  import { ReactNode } from 'react';
4
4
  import { HarnessType } from '@tangle-network/agent-interface';
5
5
  export { HarnessType } from '@tangle-network/agent-interface';
6
- export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-NOWFpRY4.js';
6
+ export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-COjPVMzg.js';
7
7
  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';
8
8
  export { E as ExposedPort, P as PortsList, a as PortsListProps } from './ports-list-DfG0VfPt.js';
9
+ import '@radix-ui/react-dropdown-menu';
9
10
 
10
11
  interface SidebarUser {
11
12
  email: string;
package/dist/dashboard.js CHANGED
@@ -54,7 +54,7 @@ import {
54
54
  canAdminSandbox,
55
55
  parseInsufficientBalance,
56
56
  useSidebar
57
- } from "./chunk-SVNWL3ZR.js";
57
+ } from "./chunk-D7JJLG4L.js";
58
58
  import {
59
59
  BillingDashboard,
60
60
  InfoPanel,
@@ -71,7 +71,7 @@ import {
71
71
  HarnessLogo,
72
72
  HarnessPicker,
73
73
  chatCapableHarnesses
74
- } from "./chunk-BR2LMUAE.js";
74
+ } from "./chunk-HU4B2M4K.js";
75
75
  import {
76
76
  DEFAULT_FEATURED_MODEL_IDS,
77
77
  ModelPicker,
@@ -80,7 +80,7 @@ import {
80
80
  formatContext,
81
81
  formatPricing,
82
82
  modelDedupKey
83
- } from "./chunk-LQHTCM56.js";
83
+ } from "./chunk-SF6LPMMN.js";
84
84
  import "./chunk-EI44GEQ5.js";
85
85
  import "./chunk-U67V476Y.js";
86
86
  export {
package/dist/globals.css CHANGED
@@ -825,8 +825,11 @@
825
825
  .max-h-\[160px\] {
826
826
  max-height: 160px;
827
827
  }
828
- .max-h-\[440px\] {
829
- max-height: 440px;
828
+ .max-h-\[min\(440px\,var\(--radix-dropdown-menu-content-available-height\)\)\] {
829
+ max-height: min(440px, var(--radix-dropdown-menu-content-available-height));
830
+ }
831
+ .max-h-\[var\(--radix-dropdown-menu-content-available-height\)\] {
832
+ max-height: var(--radix-dropdown-menu-content-available-height);
830
833
  }
831
834
  .min-h-0 {
832
835
  min-height: calc(var(--spacing) * 0);
package/dist/index.d.ts CHANGED
@@ -5,12 +5,12 @@ export { AgentWorkbench, ApprovalConfidenceStat, ApprovalItem, ApprovalQueue, Ap
5
5
  export { ArtifactView, BRAND_PRISM_THEME, CodeSurface, CodeSurfaceProps, CodeView, CodeViewProps, DiffStats, DiffView, DiffViewProps, FileBreadcrumb, FileBreadcrumbProps, GitStatusBadge, PanelHeader, PanelHeaderProps, PillTabItem, PillTabs, PillTabsProps, PreviewView, PreviewViewProps, SandboxArtifact, SandboxArtifactPane, SandboxArtifactPaneProps, SandboxArtifactTerminal, buildUnifiedPatch, computeDiffStats, resolveLanguage } from './workbench.js';
6
6
  export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from '@tangle-network/ui/openui';
7
7
  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';
8
- export { AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessControl, AgentSessionModelControl, AgentSessionReasoningControl, ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport, ArtifactDockMessage, ArtifactDockStreamEvent, ArtifactKind, ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, HARNESS_MODEL_POLICIES, ReasoningLevel, ReasoningLevelOption, ReasoningLevelPicker, ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, modelProvider, snapHarnessToModel, snapModelToHarness } from './chat.js';
8
+ export { AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessControl, AgentSessionModelControl, AgentSessionReasoningControl, ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport, ArtifactDockMessage, ArtifactDockStreamEvent, ArtifactKind, ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, ReasoningLevel, ReasoningLevelOption, ReasoningLevelPicker, ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness } from './chat.js';
9
9
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from '@tangle-network/ui/run';
10
10
  export { CommandPreview, DiffPreview, GlobResultsPreview, GrepResultsPreview, QuestionPreview, WebSearchPreview, WriteFilePreview } from '@tangle-network/ui/tool-previews';
11
11
  export { FileArtifactPane, FileArtifactPaneProps, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, filterFileTree } from '@tangle-network/ui/files';
12
12
  export { ActivityFeed, ActivityFeedProps, ActivityItem, AppearanceController, Backend, BackendConfig, BackendConfigProps, BackendSelector, BackendSelectorProps, BackendStatusData, ClusterStatusBar, ClusterStatusBarProps, ClusterStatusItem, CreditBalance, CreditBalanceProps, DashboardLayout, DashboardLayoutProps, DashboardProfile, DashboardSnapshotInfo, DashboardUser, GitCommitData, GitPanel, GitPanelProps, GitStatusData, HARNESS_BRAND, HARNESS_OPTIONS, HarnessBrand, HarnessLogo, HarnessLogoProps, HarnessPicker, HarnessPickerProps, INSUFFICIENT_BALANCE_CODE, InfoPanel, InfoPanelProps, InsufficientBalance, Invoice, InvoiceTable, InvoiceTableProps, McpServer, MetricAreaChart, MetricAreaChartProps, MetricChartPoint, MetricChartTone, NavItem, NetworkConfig, NetworkConfigData, NetworkConfigProps, NewSandboxCard, NewSandboxCardProps, OutOfCreditsModal, OutOfCreditsModalProps, PlanCardData, PlanCards, PlanCardsProps, PlanFeature, ProcessInfo, ProcessList, ProcessListProps, ProductVariant, ProfileAvatar, ProfileAvatarProps, ProfileComparison, ProfileComparisonProps, ProfileSelector, ProfileSelectorProps, PromoBanner, PromoBannerProps, RailButton, RailButtonProps, RailCollapseToggle, RailCollapseToggleProps, RailExpandable, RailExpandableProps, RailExpandableSubItem, RailFlyout, RailFlyoutProps, RailHeader, RailHeaderProps, RailModeButton, RailModeButtonProps, RailSeparator, RailSeparatorProps, RailThemeToggle, RailTooltip, RailTooltipProps, ResourceMeter, ResourceMeterProps, ResourceSnapshot, ResourceSnapshotItem, ResourceSnapshotProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_LABELED_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxCardData, SandboxCardProps, SandboxStatus, SandboxTable, SandboxTableProps, Sidebar, SidebarContent, SidebarContentProps, SidebarLayout, SidebarLayoutFlyoutItem, SidebarLayoutNavItem, SidebarLayoutProps, SidebarPanel, SidebarPanelContent, SidebarPanelContentProps, SidebarPanelHeader, SidebarPanelHeaderProps, SidebarPanelProps, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailFooter, SidebarRailFooterProps, SidebarRailHeader, SidebarRailHeaderProps, SidebarRailNav, SidebarRailNavProps, SidebarRailProps, SidebarUser, SnapshotList, SnapshotListProps, SystemLogsViewer, SystemLogsViewerProps, TeamRole, ThemeMode, UsageSummary, UsageSummaryData, UsageSummaryProps, Variant, VariantList, VariantListProps, VariantOutcome, VariantStatus, canAdminSandbox, chatCapableHarnesses, parseInsufficientBalance, useSidebar } from './dashboard.js';
13
- export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-NOWFpRY4.js';
13
+ export { D as DEFAULT_FEATURED_MODEL_IDS, M as ModelInfo, a as ModelPicker, b as ModelPickerProps, c as ModelPickerVariant, d as canonicalModelId, e as dedupeModels, f as formatContext, g as formatPricing, m as modelDedupKey } from './model-picker-COjPVMzg.js';
14
14
  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';
15
15
  export { E as ExposedPort, P as PortsList, a as PortsListProps } from './ports-list-DfG0VfPt.js';
16
16
  export { AuthHeader, AuthHeaderProps, GitHubLoginButton, GitHubLoginButtonProps, LoginLayout, LoginLayoutProps, SessionUser, UserMenu, UserMenuProps } from '@tangle-network/ui/auth';
@@ -23,9 +23,10 @@ export { ChatSession, connectSession, disconnectSession, sessionAtom } from './s
23
23
  export { AgentBranding, CustomToolRenderer, DisplayVariant, FinalTextPart, GroupedMessage, MessageRun, MessageUser, ReasoningPart, Run, RunStats, SessionMessage, SessionPart, TextPart, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime } from '@tangle-network/ui/types';
24
24
  export { Session } from './types.js';
25
25
  export { TOOL_CATEGORY_ICONS, cn, copyText, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText } from '@tangle-network/ui/utils';
26
- export { HarnessType } from '@tangle-network/agent-interface';
26
+ export { HarnessType, modelProvider, snapHarnessToModel } from '@tangle-network/agent-interface';
27
27
  import 'react/jsx-runtime';
28
28
  import 'react';
29
+ import '@radix-ui/react-dropdown-menu';
29
30
  import '@tanstack/react-query';
30
31
  import '@tangle-network/ui/sdk-hooks';
31
32
  import 'nanostores';
package/dist/index.js CHANGED
@@ -81,7 +81,6 @@ import {
81
81
  ChatInput,
82
82
  ChatMessage,
83
83
  DEFAULT_REASONING_LEVEL_OPTIONS,
84
- HARNESS_MODEL_POLICIES,
85
84
  MessageList,
86
85
  ReasoningLevelPicker,
87
86
  ThinkingIndicator,
@@ -91,7 +90,7 @@ import {
91
90
  modelProvider,
92
91
  snapHarnessToModel,
93
92
  snapModelToHarness
94
- } from "./chunk-KOUYJ6QP.js";
93
+ } from "./chunk-WLMLD2CZ.js";
95
94
  import {
96
95
  TOOL_CATEGORY_ICONS,
97
96
  cn,
@@ -148,7 +147,7 @@ import {
148
147
  buildUnifiedPatch,
149
148
  computeDiffStats,
150
149
  resolveLanguage
151
- } from "./chunk-DLKDWMFM.js";
150
+ } from "./chunk-MKX3F55O.js";
152
151
  import {
153
152
  FileArtifactPane,
154
153
  FilePreview,
@@ -213,7 +212,7 @@ import {
213
212
  canAdminSandbox,
214
213
  parseInsufficientBalance,
215
214
  useSidebar
216
- } from "./chunk-SVNWL3ZR.js";
215
+ } from "./chunk-D7JJLG4L.js";
217
216
  import {
218
217
  BillingDashboard,
219
218
  InfoPanel,
@@ -320,7 +319,7 @@ import {
320
319
  HarnessLogo,
321
320
  HarnessPicker,
322
321
  chatCapableHarnesses
323
- } from "./chunk-BR2LMUAE.js";
322
+ } from "./chunk-HU4B2M4K.js";
324
323
  import {
325
324
  DEFAULT_FEATURED_MODEL_IDS,
326
325
  ModelPicker,
@@ -329,7 +328,7 @@ import {
329
328
  formatContext,
330
329
  formatPricing,
331
330
  modelDedupKey
332
- } from "./chunk-LQHTCM56.js";
331
+ } from "./chunk-SF6LPMMN.js";
333
332
  import "./chunk-EI44GEQ5.js";
334
333
  import "./chunk-U67V476Y.js";
335
334
 
@@ -432,7 +431,6 @@ export {
432
431
  GlobResultsPreview,
433
432
  GrepResultsPreview,
434
433
  HARNESS_BRAND,
435
- HARNESS_MODEL_POLICIES,
436
434
  HARNESS_OPTIONS,
437
435
  HarnessLogo,
438
436
  HarnessPicker,
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReasoningEffort } from '@tangle-network/agent-interface';
3
+ import * as Popover from '@radix-ui/react-dropdown-menu';
3
4
 
4
5
  /**
5
6
  * Wire-format model entry as returned by `/v1/models` on the Tangle Router
@@ -93,6 +94,15 @@ interface ModelPickerProps {
93
94
  */
94
95
  triggerClassName?: string;
95
96
  disabled?: boolean;
97
+ /** Side the menu opens toward. Defaults to Radix's "bottom". */
98
+ side?: Popover.DropdownMenuContentProps["side"];
99
+ /**
100
+ * Let Radix flip the menu to the opposite side when it would overflow the
101
+ * viewport. Defaults to `true` (Radix default). Pass `false` to pin the menu
102
+ * to `side` — e.g. a composer floating in open space that should always open
103
+ * downward rather than flipping up over the heading.
104
+ */
105
+ avoidCollisions?: boolean;
96
106
  }
97
107
  /**
98
108
  * Resolve the canonical id for a model. Some upstreams already prefix the
@@ -130,6 +140,6 @@ declare const DEFAULT_FEATURED_MODEL_IDS: ReadonlyArray<string>;
130
140
  declare function formatPricing(pricing: ModelInfo["pricing"]): string | null;
131
141
  /** Format context length compactly (e.g. 200_000 → "200k"). */
132
142
  declare function formatContext(ctx: number | undefined): string | null;
133
- declare function ModelPicker({ value, onChange, models, loading, recents, popular, excludeProviders, modalities, variant, label, placeholder, className, triggerClassName, disabled, }: ModelPickerProps): react_jsx_runtime.JSX.Element;
143
+ declare function ModelPicker({ value, onChange, models, loading, recents, popular, excludeProviders, modalities, variant, label, placeholder, className, triggerClassName, disabled, side, avoidCollisions, }: ModelPickerProps): react_jsx_runtime.JSX.Element;
134
144
 
135
145
  export { DEFAULT_FEATURED_MODEL_IDS as D, type ModelInfo as M, ModelPicker as a, type ModelPickerProps as b, type ModelPickerVariant as c, canonicalModelId as d, dedupeModels as e, formatContext as f, formatPricing as g, modelDedupKey as m };
package/dist/pages.d.ts CHANGED
@@ -2,8 +2,9 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { CSSProperties, ReactNode } from 'react';
4
4
  import { c as BillingSubscription, B as BillingBalance, d as BillingUsage, j as UsageDataPoint, f as PricingTier, g as TemplateCardData } from './template-card-UhV3pmRC.js';
5
- export { M as ModelInfo } from './model-picker-NOWFpRY4.js';
5
+ export { M as ModelInfo } from './model-picker-COjPVMzg.js';
6
6
  import '@tangle-network/agent-interface';
7
+ import '@radix-ui/react-dropdown-menu';
7
8
 
8
9
  /**
9
10
  * Shared, self-contained sign-in / sign-up page for every Tangle vertical app.
package/dist/pages.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  Switch,
25
25
  Textarea
26
26
  } from "./chunk-4ZZUMXPX.js";
27
- import "./chunk-LQHTCM56.js";
27
+ import "./chunk-SF6LPMMN.js";
28
28
  import {
29
29
  cn
30
30
  } from "./chunk-EI44GEQ5.js";
package/dist/styles.css CHANGED
@@ -825,8 +825,11 @@
825
825
  .max-h-\[160px\] {
826
826
  max-height: 160px;
827
827
  }
828
- .max-h-\[440px\] {
829
- max-height: 440px;
828
+ .max-h-\[min\(440px\,var\(--radix-dropdown-menu-content-available-height\)\)\] {
829
+ max-height: min(440px, var(--radix-dropdown-menu-content-available-height));
830
+ }
831
+ .max-h-\[var\(--radix-dropdown-menu-content-available-height\)\] {
832
+ max-height: var(--radix-dropdown-menu-content-available-height);
830
833
  }
831
834
  .min-h-0 {
832
835
  min-height: calc(var(--spacing) * 0);
package/dist/workbench.js CHANGED
@@ -12,15 +12,15 @@ import {
12
12
  buildUnifiedPatch,
13
13
  computeDiffStats,
14
14
  resolveLanguage
15
- } from "./chunk-DLKDWMFM.js";
15
+ } from "./chunk-MKX3F55O.js";
16
16
  import "./chunk-3J6FG3FJ.js";
17
- import "./chunk-SVNWL3ZR.js";
17
+ import "./chunk-D7JJLG4L.js";
18
18
  import "./chunk-OMUIPJQZ.js";
19
19
  import "./chunk-VIREDUBF.js";
20
20
  import "./chunk-77WVVJA4.js";
21
21
  import "./chunk-4ZZUMXPX.js";
22
- import "./chunk-BR2LMUAE.js";
23
- import "./chunk-LQHTCM56.js";
22
+ import "./chunk-HU4B2M4K.js";
23
+ import "./chunk-SF6LPMMN.js";
24
24
  import "./chunk-EI44GEQ5.js";
25
25
  import "./chunk-U67V476Y.js";
26
26
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.56.0",
3
+ "version": "0.58.0",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -126,7 +126,7 @@
126
126
  "test:bridge": "pnpm build && vitest run src/__tests__/re-export-identity.test.ts"
127
127
  },
128
128
  "peerDependencies": {
129
- "@tangle-network/agent-interface": ">=0.10.0 <1.0.0",
129
+ "@tangle-network/agent-interface": ">=0.15.0 <1.0.0",
130
130
  "@tangle-network/brand": "^0.6.0",
131
131
  "@tangle-network/ui": "^4.0.0",
132
132
  "@xyflow/react": "^12.0.0",
@@ -181,7 +181,7 @@
181
181
  "@storybook/react-vite": "^8.6.18",
182
182
  "@tailwindcss/postcss": "^4.2.2",
183
183
  "@tailwindcss/vite": "^4.2.2",
184
- "@tangle-network/agent-interface": ">=0.10.0 <1.0.0",
184
+ "@tangle-network/agent-interface": ">=0.15.0 <1.0.0",
185
185
  "@tangle-network/brand": "^0.6.0",
186
186
  "@tangle-network/ui": "^4.1.0",
187
187
  "@tanstack/react-query": "^5.91.0",