@tangle-network/sandbox-ui 0.55.0 → 0.57.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.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-GTJ5PSK5.js";
4
4
  import {
5
5
  buildWorkflowGraph
6
- } from "./chunk-DEN4GUA7.js";
6
+ } from "./chunk-WEYFEMIN.js";
7
7
  import {
8
8
  providerLabel
9
9
  } from "./chunk-7JLB7UZ3.js";
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,9 @@ 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
+ import * as Popover from '@radix-ui/react-dropdown-menu';
5
6
  import * as React from 'react';
6
- import { M as ModelInfo } from './model-picker-NOWFpRY4.js';
7
+ import { M as ModelInfo } from './model-picker-COjPVMzg.js';
7
8
 
8
9
  /**
9
10
  * A reasoning selection: `auto` is a UI-only sentinel ("let the harness/model default decide",
@@ -33,9 +34,18 @@ interface ReasoningLevelPickerProps {
33
34
  * Omit to show every option.
34
35
  */
35
36
  available?: ReadonlyArray<ReasoningEffort>;
37
+ /** Side the menu opens toward. Defaults to Radix's "bottom". */
38
+ side?: Popover.DropdownMenuContentProps["side"];
39
+ /**
40
+ * Let Radix flip the menu to the opposite side when it would overflow the
41
+ * viewport. Defaults to `true` (Radix default). Pass `false` to pin the menu
42
+ * to `side` — e.g. a composer floating in open space that should always open
43
+ * downward rather than flipping up over the heading.
44
+ */
45
+ avoidCollisions?: boolean;
36
46
  }
37
47
  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;
48
+ declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, available, side, avoidCollisions, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
39
49
 
40
50
  interface AgentSessionHarnessControl {
41
51
  value: HarnessType;
@@ -104,6 +114,15 @@ interface AgentSessionControlsProps {
104
114
  * on the left of the gear menu.
105
115
  */
106
116
  layout?: "inline" | "gear";
117
+ /**
118
+ * Where the inline pickers open. `"auto"` (default) keeps Radix's
119
+ * collision-aware behavior: the menus open downward but flip up when the
120
+ * composer is docked at the bottom of the viewport. `"down"` pins them open
121
+ * downward — for a composer floating in open space (e.g. a centered new-chat
122
+ * surface) where flipping up would cover the heading. Only affects the
123
+ * `"inline"` layout; the gear menu is unchanged.
124
+ */
125
+ menuPlacement?: "auto" | "down";
107
126
  }
108
127
  /**
109
128
  * Compact control strip for an agent chat composer: harness, model, and
@@ -119,7 +138,7 @@ interface AgentSessionControlsProps {
119
138
  *
120
139
  * Designed to slot into `SandboxWorkbench`'s `session.composerControls`.
121
140
  */
122
- declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
141
+ declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
123
142
 
124
143
  /**
125
144
  * 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-KOUYJ6QP.js";
20
- import "./chunk-BR2LMUAE.js";
21
- import "./chunk-LQHTCM56.js";
19
+ } from "./chunk-NHHYPID3.js";
20
+ import "./chunk-HU4B2M4K.js";
21
+ import "./chunk-SF6LPMMN.js";
22
22
  import "./chunk-EI44GEQ5.js";
23
23
  import "./chunk-U67V476Y.js";
24
24
  export {
@@ -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";
@@ -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",
@@ -219,7 +226,8 @@ function HarnessDropdown({
219
226
  locked,
220
227
  lockReason,
221
228
  side = "bottom",
222
- align = "start"
229
+ align = "start",
230
+ avoidCollisions
223
231
  }) {
224
232
  const allowed = new Set(
225
233
  available ?? HARNESS_OPTIONS.map((h) => h.type)
@@ -253,9 +261,14 @@ function HarnessDropdown({
253
261
  {
254
262
  side,
255
263
  align,
264
+ avoidCollisions,
265
+ collisionPadding: 24,
256
266
  sideOffset: 6,
257
267
  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",
268
+ // Cap to the viewport space on the open side and scroll, so a tall
269
+ // backend list pinned downward (floating composer) never runs off
270
+ // the bottom edge.
271
+ "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
272
  "shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
260
273
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
261
274
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
@@ -294,7 +307,8 @@ function AgentSessionControls({
294
307
  trailing,
295
308
  className,
296
309
  context = "chat",
297
- layout = "inline"
310
+ layout = "inline",
311
+ menuPlacement = "auto"
298
312
  }) {
299
313
  if (!harness && !model && !reasoning && !trailing) return null;
300
314
  const handleHarnessChange = (next) => {
@@ -320,6 +334,8 @@ function AgentSessionControls({
320
334
  const harnessAvailable = harness?.available ?? (context === "chat" ? chatCapableHarnesses : void 0);
321
335
  const menuSide = layout === "gear" ? "left" : "bottom";
322
336
  const menuAlign = layout === "gear" ? "end" : "start";
337
+ const inlineForceDown = menuPlacement === "down" && layout !== "gear";
338
+ const avoidCollisions = inlineForceDown ? false : void 0;
323
339
  const harnessNode = harness && /* @__PURE__ */ jsx2(
324
340
  HarnessDropdown,
325
341
  {
@@ -327,7 +343,8 @@ function AgentSessionControls({
327
343
  available: harnessAvailable,
328
344
  onChange: handleHarnessChange,
329
345
  side: menuSide,
330
- align: menuAlign
346
+ align: menuAlign,
347
+ avoidCollisions
331
348
  }
332
349
  );
333
350
  const modelNode = model && /* @__PURE__ */ jsx2(
@@ -341,7 +358,9 @@ function AgentSessionControls({
341
358
  loading: model.loading,
342
359
  popular: model.popular,
343
360
  recents: model.recents,
344
- disabled: model.disabled || (visibleModels ?? []).length === 0
361
+ disabled: model.disabled || (visibleModels ?? []).length === 0,
362
+ side: layout === "gear" ? void 0 : "bottom",
363
+ avoidCollisions
345
364
  }
346
365
  );
347
366
  const selectedModel = model?.models.find(
@@ -358,7 +377,9 @@ function AgentSessionControls({
358
377
  onChange: reasoning.onChange,
359
378
  options: reasoning.options,
360
379
  disabled: reasoning.disabled,
361
- available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available
380
+ available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available,
381
+ side: layout === "gear" ? void 0 : "bottom",
382
+ avoidCollisions
362
383
  }
363
384
  );
364
385
  if (layout === "gear") {
@@ -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",
@@ -43,7 +43,7 @@ function pickDetail(cfg, keys) {
43
43
  }
44
44
  return Object.keys(out).length > 0 ? out : void 0;
45
45
  }
46
- function describeAction(action) {
46
+ function describeActionBase(action) {
47
47
  const rec = asRecord(action);
48
48
  const [kind] = Object.keys(rec);
49
49
  const cfg = asRecord(rec[kind]);
@@ -134,6 +134,41 @@ function describeAction(action) {
134
134
  };
135
135
  }
136
136
  }
137
+ var MAX_CONFIG_DEPTH = 100;
138
+ function toJsonSafe(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
139
+ if (value === null) return null;
140
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
141
+ if (typeof value === "string" || typeof value === "boolean") return value;
142
+ if (typeof value !== "object") return void 0;
143
+ if (value instanceof Date) return value.toISOString();
144
+ if (seen.has(value)) return "[Circular]";
145
+ if (depth >= MAX_CONFIG_DEPTH) return "[Max depth exceeded]";
146
+ seen.add(value);
147
+ let out;
148
+ if (Array.isArray(value)) {
149
+ out = value.map((v) => {
150
+ const s = toJsonSafe(v, seen, depth + 1);
151
+ return s === void 0 ? null : s;
152
+ });
153
+ } else {
154
+ const obj = {};
155
+ for (const [k, v] of Object.entries(value)) {
156
+ const s = toJsonSafe(v, seen, depth + 1);
157
+ if (s !== void 0) obj[k] = s;
158
+ }
159
+ out = obj;
160
+ }
161
+ seen.delete(value);
162
+ return out;
163
+ }
164
+ function withConfig(base, cfg) {
165
+ return Object.keys(cfg).length > 0 ? { ...base, config: toJsonSafe(cfg) } : base;
166
+ }
167
+ function describeAction(action) {
168
+ const rec = asRecord(action);
169
+ const [kind] = Object.keys(rec);
170
+ return withConfig(describeActionBase(action), asRecord(rec[kind]));
171
+ }
137
172
  function describeTrigger(on) {
138
173
  const rec = asRecord(on);
139
174
  if (rec.provider_event) {
@@ -146,36 +181,46 @@ function describeTrigger(on) {
146
181
  if (event) subtitle += ` \xB7 ${event}`;
147
182
  if (actions.length > 0) subtitle += ` (${actions.join("/")})`;
148
183
  if (repo) subtitle += ` on ${repo}`;
149
- return {
150
- title: "Trigger",
151
- kind: "provider_event",
152
- subtitle,
153
- provider: connection,
154
- hasBranches: false,
155
- isRoot: true,
156
- tone: "trigger"
157
- };
184
+ return withConfig(
185
+ {
186
+ title: "Trigger",
187
+ kind: "provider_event",
188
+ subtitle,
189
+ provider: connection,
190
+ hasBranches: false,
191
+ isRoot: true,
192
+ tone: "trigger"
193
+ },
194
+ ev
195
+ );
158
196
  }
159
197
  if (rec.schedule) {
160
198
  const sch = asRecord(rec.schedule);
161
199
  const cron = str(sch.cron);
162
200
  const tz = str(sch.timezone);
163
- return {
164
- title: "Schedule",
165
- kind: "schedule",
166
- subtitle: cron ? tz ? `${cron} (${tz})` : cron : void 0,
201
+ return withConfig(
202
+ {
203
+ title: "Schedule",
204
+ kind: "schedule",
205
+ subtitle: cron ? tz ? `${cron} (${tz})` : cron : void 0,
206
+ hasBranches: false,
207
+ isRoot: true,
208
+ tone: "trigger"
209
+ },
210
+ sch
211
+ );
212
+ }
213
+ const [kind] = Object.keys(rec);
214
+ return withConfig(
215
+ {
216
+ title: "Trigger",
217
+ kind: "trigger",
167
218
  hasBranches: false,
168
219
  isRoot: true,
169
220
  tone: "trigger"
170
- };
171
- }
172
- return {
173
- title: "Trigger",
174
- kind: "trigger",
175
- hasBranches: false,
176
- isRoot: true,
177
- tone: "trigger"
178
- };
221
+ },
222
+ asRecord(kind ? rec[kind] : void 0)
223
+ );
179
224
  }
180
225
  function buildWorkflowGraph(yaml, options) {
181
226
  const reserveRunState = options?.reserveRunState ?? false;
@@ -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
@@ -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
@@ -10,7 +10,7 @@ export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, Inline
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';
@@ -26,6 +26,7 @@ export { TOOL_CATEGORY_ICONS, cn, copyText, formatBytes, formatDuration, formatU
26
26
  export { HarnessType } 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
@@ -91,7 +91,7 @@ import {
91
91
  modelProvider,
92
92
  snapHarnessToModel,
93
93
  snapModelToHarness
94
- } from "./chunk-KOUYJ6QP.js";
94
+ } from "./chunk-NHHYPID3.js";
95
95
  import {
96
96
  TOOL_CATEGORY_ICONS,
97
97
  cn,
@@ -320,7 +320,7 @@ import {
320
320
  HarnessLogo,
321
321
  HarnessPicker,
322
322
  chatCapableHarnesses
323
- } from "./chunk-BR2LMUAE.js";
323
+ } from "./chunk-HU4B2M4K.js";
324
324
  import {
325
325
  DEFAULT_FEATURED_MODEL_IDS,
326
326
  ModelPicker,
@@ -329,7 +329,7 @@ import {
329
329
  formatContext,
330
330
  formatPricing,
331
331
  modelDedupKey
332
- } from "./chunk-LQHTCM56.js";
332
+ } from "./chunk-SF6LPMMN.js";
333
333
  import "./chunk-EI44GEQ5.js";
334
334
  import "./chunk-U67V476Y.js";
335
335
 
@@ -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
@@ -19,8 +19,8 @@ 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 {
@@ -58,6 +58,14 @@ interface WfNodeData extends Record<string, unknown> {
58
58
  path?: string;
59
59
  /** Notable config fields for the expand drawer (kept small + stringified). */
60
60
  detail?: Record<string, string>;
61
+ /** The raw, UNTRUNCATED config for this node — the action/trigger config from
62
+ * the definition. The compact card reads {@link detail}; a full-detail view
63
+ * (e.g. a node drawer) reads this to render every field — the complete prompt,
64
+ * all profile/source/input keys — without the card-sized clamp. It is a
65
+ * JSON-safe deep copy of the config (cycles and non-JSON values normalized),
66
+ * so a consumer can serialize or render it freely. Omitted when the node has
67
+ * no config. */
68
+ config?: Record<string, unknown>;
61
69
  /** Connector slug (e.g. `github`) for the provider chip, when one applies. */
62
70
  provider?: string;
63
71
  /** Small corner tag, e.g. "×3" for a parallel fan-out. */
package/dist/workflows.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildWorkflowGraph
3
- } from "./chunk-DEN4GUA7.js";
3
+ } from "./chunk-WEYFEMIN.js";
4
4
  import "./chunk-7JLB7UZ3.js";
5
5
  import "./chunk-U67V476Y.js";
6
6
 
@@ -27,7 +27,7 @@ function retryImport(factory, retries = 2, delayMs = 350) {
27
27
  function lazyWorkflowGraph() {
28
28
  return lazy(
29
29
  () => retryImport(
30
- () => import("./WorkflowGraph-FSS7GW5O.js").then((m) => ({ default: m.WorkflowGraph }))
30
+ () => import("./WorkflowGraph-VMG2ZEAN.js").then((m) => ({ default: m.WorkflowGraph }))
31
31
  )
32
32
  );
33
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.55.0",
3
+ "version": "0.57.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",