@tangle-network/sandbox-ui 0.115.7 → 0.116.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,5 +1,5 @@
1
1
  import { t as cn$1 } from "./utils-DzWbktWG.js";
2
- import { t as WorkspacePaneHeader } from "./workspace-pane-header-C5e7sPaS.js";
2
+ import { t as WorkspacePaneHeader } from "./workspace-pane-header-Bg1cCcHX.js";
3
3
  import { Button } from "@tangle-network/ui/primitives";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import * as React$1 from "react";
package/dist/globals.css CHANGED
@@ -839,8 +839,8 @@
839
839
  .h-\[1em\] {
840
840
  height: 1em;
841
841
  }
842
- .h-\[3px\] {
843
- height: 3px;
842
+ .h-\[9px\] {
843
+ height: 9px;
844
844
  }
845
845
  .h-\[17px\] {
846
846
  height: 17px;
@@ -1190,12 +1190,12 @@
1190
1190
  .w-\[1\.375rem\] {
1191
1191
  width: 1.375rem;
1192
1192
  }
1193
- .w-\[3px\] {
1194
- width: 3px;
1195
- }
1196
1193
  .w-\[5\.5rem\] {
1197
1194
  width: 5.5rem;
1198
1195
  }
1196
+ .w-\[9px\] {
1197
+ width: 9px;
1198
+ }
1199
1199
  .w-\[17px\] {
1200
1200
  width: 17px;
1201
1201
  }
@@ -1906,6 +1906,9 @@
1906
1906
  .overflow-hidden {
1907
1907
  overflow: hidden;
1908
1908
  }
1909
+ .overflow-visible {
1910
+ overflow: visible;
1911
+ }
1909
1912
  .overflow-x-auto {
1910
1913
  overflow-x: auto;
1911
1914
  }
@@ -2097,12 +2100,6 @@
2097
2100
  border-color: color-mix(in oklab, var(--brand-emerald) 50%, transparent);
2098
2101
  }
2099
2102
  }
2100
- .border-\[var\(--code-error\)\]\/20 {
2101
- border-color: var(--code-error);
2102
- @supports (color: color-mix(in lab, red, red)) {
2103
- border-color: color-mix(in oklab, var(--code-error) 20%, transparent);
2104
- }
2105
- }
2106
2103
  .border-\[var\(--code-number\)\]\/20 {
2107
2104
  border-color: var(--code-number);
2108
2105
  @supports (color: color-mix(in lab, red, red)) {
@@ -2373,12 +2370,6 @@
2373
2370
  .bg-\[var\(--code-error\)\] {
2374
2371
  background-color: var(--code-error);
2375
2372
  }
2376
- .bg-\[var\(--code-error\)\]\/5 {
2377
- background-color: var(--code-error);
2378
- @supports (color: color-mix(in lab, red, red)) {
2379
- background-color: color-mix(in oklab, var(--code-error) 5%, transparent);
2380
- }
2381
- }
2382
2373
  .bg-\[var\(--code-number\)\] {
2383
2374
  background-color: var(--code-number);
2384
2375
  }
@@ -3718,6 +3709,10 @@
3718
3709
  --tw-shadow: 0 6px 16px var(--tw-shadow-color, rgba(15,23,42,0.08));
3719
3710
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3720
3711
  }
3712
+ .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.18\)\] {
3713
+ --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.18));
3714
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3715
+ }
3721
3716
  .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.45\)\] {
3722
3717
  --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.45));
3723
3718
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -3989,6 +3984,14 @@
3989
3984
  border-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
3990
3985
  }
3991
3986
  }
3987
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3988
+ background-color: color-mix(in srgb, hsl(var(--primary)) 20%, transparent);
3989
+ }
3990
+ @supports (color: color-mix(in lab, red, red)) {
3991
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3992
+ background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
3993
+ }
3994
+ }
3992
3995
  .group-hover\:text-foreground:is(:where(.group):hover *) {
3993
3996
  color: var(--color-foreground);
3994
3997
  }
@@ -4016,6 +4019,12 @@
4016
4019
  opacity: 100%;
4017
4020
  }
4018
4021
  }
4022
+ .group-focus-visible\:bg-primary\/30:is(:where(.group):focus-visible *) {
4023
+ background-color: color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
4024
+ @supports (color: color-mix(in lab, red, red)) {
4025
+ background-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
4026
+ }
4027
+ }
4019
4028
  .peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled ~ *) {
4020
4029
  cursor: not-allowed;
4021
4030
  }
@@ -4348,14 +4357,6 @@
4348
4357
  background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
4349
4358
  }
4350
4359
  }
4351
- .hover\:bg-primary\/30:hover {
4352
- background-color: color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
4353
- }
4354
- @supports (color: color-mix(in lab, red, red)) {
4355
- .hover\:bg-primary\/30:hover {
4356
- background-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
4357
- }
4358
- }
4359
4360
  .hover\:bg-primary\/90:hover {
4360
4361
  background-color: color-mix(in srgb, hsl(var(--primary)) 90%, transparent);
4361
4362
  }
@@ -4554,12 +4555,6 @@
4554
4555
  .focus-visible\:bg-background:focus-visible {
4555
4556
  background-color: var(--color-background);
4556
4557
  }
4557
- .focus-visible\:bg-primary\/40:focus-visible {
4558
- background-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
4559
- @supports (color: color-mix(in lab, red, red)) {
4560
- background-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
4561
- }
4562
- }
4563
4558
  .focus-visible\:bg-surface-container:focus-visible {
4564
4559
  background-color: var(--color-surface-container);
4565
4560
  }
@@ -5004,9 +4999,6 @@
5004
4999
  .lg\:p-0 {
5005
5000
  padding: 0px;
5006
5001
  }
5007
- .lg\:p-4 {
5008
- padding: calc(var(--spacing) * 4);
5009
- }
5010
5002
  .lg\:px-8 {
5011
5003
  padding-inline: calc(var(--spacing) * 8);
5012
5004
  }
package/dist/hooks.d.ts CHANGED
@@ -1,69 +1,7 @@
1
+ import { n as UsePtySessionReturn, r as usePtySession, t as UsePtySessionOptions } from "./use-pty-session-DbAYO5uH.js";
1
2
  import { t as Session } from "./sidecar-DgH_vQ6m.js";
2
3
  import { a as SendMessageOptions, c as SessionStreamError, d as useSessionStream, i as SESSION_STREAM_RECONNECT_DELAY_MS, l as UseSessionStreamOptions, n as UseSidecarAuthOptions, o as SessionDegradation, r as useSidecarAuth, s as SessionInfo, t as SidecarAuth, u as UseSessionStreamResult } from "./use-sidecar-auth-CCTJcrq7.js";
3
- import { AgentInteractiveSessionControlClaim } from "@tangle-network/agent-interface";
4
4
  import { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AuthUser, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, ConnectionState, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, TaskStreamEvent, TerminalStreamEvent, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from "@tangle-network/ui/hooks";
5
- //#region src/hooks/use-pty-session.d.ts
6
- export interface UsePtySessionOptions {
7
- /** Base URL of the sidecar (e.g. "http://localhost:9100"). */
8
- apiUrl: string;
9
- /** Bearer token for authentication. */
10
- token: string;
11
- /** Called with raw PTY output (may contain ANSI escape codes). */
12
- onData: (data: string) => void;
13
- /**
14
- * Stable id identifying this terminal connection to the sidecar.
15
- * Reused on every connect/reconnect so the sidecar restores the same
16
- * PTY session (within its reconnect window) instead of spawning a
17
- * fresh shell. When omitted, a random id is generated per connect —
18
- * so the session does not survive a remount.
19
- */
20
- connectionId?: string;
21
- /**
22
- * Exact incarnation issued for an interactive agent session. When present,
23
- * it must be sent with `control` on every WebSocket init frame.
24
- */
25
- incarnationId?: string;
26
- /** Write claim for the exact interactive agent session. */
27
- control?: AgentInteractiveSessionControlClaim;
28
- }
29
- export interface UsePtySessionReturn {
30
- /** Whether the underlying transport is connected and receiving data. */
31
- isConnected: boolean;
32
- /** Connection or API error, if any. */
33
- error: string | null;
34
- /** Send a command to the PTY session. */
35
- sendCommand: (command: string) => Promise<void>;
36
- /** Safely resize the remote PTY. */
37
- resizeTerminal: (cols: number, rows: number) => Promise<void>;
38
- /** Tear down and reconnect. */
39
- reconnect: () => void;
40
- }
41
- /**
42
- * Manages a PTY session against the sidecar terminal API.
43
- *
44
- * Transport:
45
- * 1. Try the current sidecar WebSocket contract directly:
46
- * GET /terminals/:id/ws, then send `{"type":"init",...}`.
47
- * - Server → client: BINARY frames carrying PTY output; TEXT frames
48
- * carrying lifecycle/control messages.
49
- * - Client → server: TEXT frames carrying JSON input/resize messages.
50
- * 2. If direct WS does not reach server `ready` within
51
- * WS_READY_TIMEOUT_MS, or it errors before ready, fall back to the older
52
- * terminal contract:
53
- * - POST /terminals creates the session.
54
- * - GET /terminals/:id/ws tries the older WS transport.
55
- * - GET /terminals/:id/stream (SSE for output)
56
- * - POST /terminals/:id/input (one batched POST at a time)
57
- * - PATCH /terminals/:id (resize)
58
- * 3. DELETE /terminals/:id closes sessions created by the older REST API.
59
- *
60
- * The WS path eliminates the per-keystroke HTTP round-trip that
61
- * dominates typing latency through edge proxies; the HTTP+SSE path is
62
- * preserved as a fallback so the hook keeps working against
63
- * deployments that have not yet shipped the WS endpoint.
64
- */
65
- export declare function usePtySession({ apiUrl, token, onData, connectionId: providedConnectionId, incarnationId, control }: UsePtySessionOptions): UsePtySessionReturn;
66
- //#endregion
67
5
  //#region src/hooks/use-sandbox-metrics.d.ts
68
6
  /**
69
7
  * Sandbox-level telemetry collected by the sidecar from cgroup v2
@@ -173,14 +111,12 @@ export interface UseSandboxMetricsResult {
173
111
  */
174
112
  history: SandboxMetricsSample[];
175
113
  /**
176
- * True only until the first successful sample has arrived (or the
177
- * first one after the target `sandboxId` changes). Subsequent polls
178
- * do not flip this back to true, so consumers can gate a spinner
179
- * on it without it flashing on every cycle.
114
+ * True while waiting for the first successful metrics response for this
115
+ * sandbox. Errors clear it so consumers can show the failure state.
180
116
  */
181
117
  loading: boolean;
182
118
  error: Error | null;
183
- /** Wall-clock ms of the last successful sample, or null. */
119
+ /** Wall-clock ms of the last successful metrics response, or null. */
184
120
  lastUpdatedAt: number | null;
185
121
  }
186
122
  /**
@@ -203,4 +139,4 @@ export declare function useRenameSession(apiUrl: string, token: string | null):
203
139
  title: string;
204
140
  }, unknown>;
205
141
  //#endregion
206
- export { type AgentStreamEvent, type AppendUserMessageOptions, type ApplySdkEventOptions, type AuthUser, type AutomationStreamEvent, type BeginAssistantMessageOptions, type BotStreamEvent, type CompleteAssistantMessageOptions, type ConnectionState, type RealtimeSessionOptions, RealtimeSessionRegistry, type RealtimeSessionRegistryProps, type RealtimeSessionState, type RealtimeSessionTarget, SESSION_STREAM_RECONNECT_DELAY_MS, type SSEEvent, type SdkSessionAttachment, type SdkSessionEvent, type SdkSessionSeed, SendMessageOptions, SessionDegradation, SessionInfo, SessionStreamError, SidecarAuth, type TaskStreamEvent, type TerminalStreamEvent, type UseAuthOptions, type UseAuthResult, type UseRunGroupsOptions, type UseSSEStreamOptions, type UseSSEStreamResult, type UseSdkSessionOptions, type UseSdkSessionReturn, UseSessionStreamOptions, UseSessionStreamResult, UseSidecarAuthOptions, type UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionStream, useSidecarAuth, useToolCallStream };
142
+ export { type AgentStreamEvent, type AppendUserMessageOptions, type ApplySdkEventOptions, type AuthUser, type AutomationStreamEvent, type BeginAssistantMessageOptions, type BotStreamEvent, type CompleteAssistantMessageOptions, type ConnectionState, type RealtimeSessionOptions, RealtimeSessionRegistry, type RealtimeSessionRegistryProps, type RealtimeSessionState, type RealtimeSessionTarget, SESSION_STREAM_RECONNECT_DELAY_MS, type SSEEvent, type SdkSessionAttachment, type SdkSessionEvent, type SdkSessionSeed, SendMessageOptions, SessionDegradation, SessionInfo, SessionStreamError, SidecarAuth, type TaskStreamEvent, type TerminalStreamEvent, type UseAuthOptions, type UseAuthResult, UsePtySessionOptions, UsePtySessionReturn, type UseRunGroupsOptions, type UseSSEStreamOptions, type UseSSEStreamResult, type UseSdkSessionOptions, type UseSdkSessionReturn, UseSessionStreamOptions, UseSessionStreamResult, UseSidecarAuthOptions, type UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, usePtySession, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionStream, useSidecarAuth, useToolCallStream };
package/dist/hooks.js CHANGED
@@ -1,9 +1,10 @@
1
- import { t as usePtySession } from "./use-pty-session-C8cE0adT.js";
1
+ import { t as usePtySession } from "./use-pty-session-Bf4hBLXJ.js";
2
2
  import { i as useSessionStream, n as SESSION_STREAM_RECONNECT_DELAY_MS, r as SessionStreamError, t as useSidecarAuth } from "./use-sidecar-auth-DkdcufOz.js";
3
3
  import * as React$1 from "react";
4
4
  import { RealtimeSessionRegistry, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from "@tangle-network/ui/hooks";
5
5
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6
6
  //#region src/hooks/use-sandbox-metrics.ts
7
+ const METRICS_REQUEST_TIMEOUT_MS = 15e3;
7
8
  /**
8
9
  * Polls the sandbox's sidecar metrics through the API proxy and
9
10
  * derives a CPU% value from consecutive cumulative-CPU samples. Used
@@ -36,12 +37,19 @@ function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled = true, inter
36
37
  }
37
38
  prevSandboxIdRef.current = sandboxId ?? null;
38
39
  if (!enabled || sandboxCleared) return;
39
- const controller = new AbortController();
40
40
  let cancelled = false;
41
41
  let timeoutId = null;
42
+ let activeRequestController = null;
42
43
  const delay = Math.max(intervalMs, 500);
43
44
  const fetchOnce = async () => {
44
45
  if (!hasLoadedRef.current) setLoading(true);
46
+ const requestController = new AbortController();
47
+ activeRequestController = requestController;
48
+ let requestTimedOut = false;
49
+ const requestTimeoutId = window.setTimeout(() => {
50
+ requestTimedOut = true;
51
+ requestController.abort();
52
+ }, METRICS_REQUEST_TIMEOUT_MS);
45
53
  try {
46
54
  const headers = {};
47
55
  if (token) headers.Authorization = `Bearer ${token}`;
@@ -49,7 +57,7 @@ function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled = true, inter
49
57
  method: "GET",
50
58
  credentials: "include",
51
59
  headers,
52
- signal: controller.signal
60
+ signal: requestController.signal
53
61
  });
54
62
  if (!res.ok) throw new Error(`Metrics request failed (HTTP ${res.status})`);
55
63
  const data = await res.json();
@@ -96,9 +104,14 @@ function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled = true, inter
96
104
  hasLoadedRef.current = true;
97
105
  setLoading(false);
98
106
  } catch (err) {
99
- if (cancelled || err instanceof DOMException && err.name === "AbortError") return;
100
- setError(err instanceof Error ? err : new Error(String(err)));
107
+ if (cancelled) return;
108
+ if (requestTimedOut) setError(/* @__PURE__ */ new Error(`Metrics request timed out after ${METRICS_REQUEST_TIMEOUT_MS / 1e3} seconds`));
109
+ else if (err instanceof DOMException && err.name === "AbortError") return;
110
+ else setError(err instanceof Error ? err : new Error(String(err)));
101
111
  if (!hasLoadedRef.current) setLoading(false);
112
+ } finally {
113
+ window.clearTimeout(requestTimeoutId);
114
+ if (activeRequestController === requestController) activeRequestController = null;
102
115
  }
103
116
  };
104
117
  const runLoop = async () => {
@@ -110,7 +123,7 @@ function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled = true, inter
110
123
  runLoop();
111
124
  return () => {
112
125
  cancelled = true;
113
- controller.abort();
126
+ activeRequestController?.abort();
114
127
  if (timeoutId !== null) window.clearTimeout(timeoutId);
115
128
  };
116
129
  }, [
@@ -136,7 +136,7 @@ declare function DirectoryPane({ root, selectedPath, onSelect, onRefresh, onUplo
136
136
  //#endregion
137
137
  //#region src/workspace/status-banner.d.ts
138
138
  /**
139
- * StatusBanner — full-width notification banner for connection/provisioning states.
139
+ * StatusBanner — inline notice for connection and provisioning states.
140
140
  */
141
141
  type BannerType = "provisioning" | "connecting" | "error" | "warning" | "success" | "info";
142
142
  interface StatusBannerProps {
@@ -542,7 +542,7 @@ interface SandboxWorkbenchSessionProps extends Omit<ChatContainerProps, "classNa
542
542
  meta?: ReactNode;
543
543
  headerActions?: ReactNode;
544
544
  /**
545
- * Controls rendered as a strip attached beneath the chat composer —
545
+ * Controls rendered above the composer in the same centered column —
546
546
  * harness/model/effort pickers, token meters, etc. Use
547
547
  * `AgentSessionControls` from `@tangle-network/agent-app/web-react` for the
548
548
  * standard set.
@@ -564,15 +564,14 @@ interface SandboxWorkbenchProps {
564
564
  /**
565
565
  * Header above the transcript. `undefined` keeps the branded session card
566
566
  * (`Tangle Sandbox` / `title` / `status`), a node replaces it, and `null`
567
- * removes it: the transcript then renders directly on `bg-surface` with no
567
+ * removes it: the transcript then renders directly on `bg-background` with no
568
568
  * eyebrow/title frame around it, and the shell's center header row appears
569
569
  * only while it holds an open-pane toggle.
570
570
  */
571
571
  centerHeader?: ReactNode | null;
572
572
  /**
573
- * Composer rendered under the transcript on the panel background, inside the
574
- * transcript's own `max-w-3xl` column. `session.composerControls`, when
575
- * also given, sits above it as before.
573
+ * Composer rendered under the transcript in the same centered column as
574
+ * `session.composerControls`.
576
575
  */
577
576
  composer?: ReactNode;
578
577
  /**
package/dist/index.d.ts CHANGED
@@ -4,11 +4,12 @@ import { $ as HARNESS_BRAND, $t as useSidebar, A as Variant, An as SidebarProps,
4
4
  import { a as modelBrandFor, i as canonicalModelId, n as ModelBrandStack, r as ModelInfo, t as ModelBrandIdentity } from "./model-brand-B9A4H9pJ.js";
5
5
  import { a as UsageChartProps, c as PricingPageProps, d as BillingBalance, f as BillingDashboard, h as BillingUsage, i as UsageChart, l as PricingTier, m as BillingSubscription, n as TemplateCardData, o as UsageDataPoint, p as BillingDashboardProps, r as TemplateCardProps, s as PricingPage, t as TemplateCard, u as formatPrice } from "./template-card-L-4gmjx2.js";
6
6
  import { C as getCodeLanguage, D as resolveFilePreviewKind, E as parseCsv, S as filterFileTree, T as getSyntaxLanguage, _ as RichFileTreeGitStatus, a as FileNode, b as detectFileFormat, c as FilePreviewProps, d as FileTabsProps, f as FileTree, g as RichFileTreeGitEntry, h as RichFileTree, i as FileFormat, l as FileTabData, m as FileTreeVisibilityOptions, n as FileArtifactPane, o as FilePreview, p as FileTreeProps, r as FileArtifactPaneProps, s as FilePreviewKind, t as CSV_PREVIEW_ROW_LIMIT, u as FileTabs, v as RichFileTreeProps, w as getFormatLabel, x as fileExtension, y as RichFileTreeThemeVars } from "./index-CXX5IpH2.js";
7
+ import { n as UsePtySessionReturn, r as usePtySession, t as UsePtySessionOptions } from "./use-pty-session-DbAYO5uH.js";
7
8
  import { t as Session } from "./sidecar-DgH_vQ6m.js";
8
9
  import { d as useSessionStream, l as UseSessionStreamOptions, n as UseSidecarAuthOptions, o as SessionDegradation, r as useSidecarAuth, s as SessionInfo, t as SidecarAuth, u as UseSessionStreamResult } from "./use-sidecar-auth-CCTJcrq7.js";
9
- import { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AuthUser, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SandboxMetrics, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SidecarMetricsPayload, TaskStreamEvent, TerminalStreamEvent, UseAuthOptions, UseAuthResult, UsePtySessionOptions, UsePtySessionReturn, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSandboxMetricsOptions, UseSandboxMetricsResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useCreateSession, useDeleteSession, useDropdownMenu, useLiveTime, usePtySession, useRealtimeSession, useRenameSession, useRunCollapseState, useRunGroups, useSSEStream, useSandboxMetrics, useSdkSession, useSessions, useToolCallStream } from "./hooks.js";
10
+ import { AgentStreamEvent, AppendUserMessageOptions, ApplySdkEventOptions, AuthUser, AutomationStreamEvent, BeginAssistantMessageOptions, BotStreamEvent, CompleteAssistantMessageOptions, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, SSEEvent, SandboxMetrics, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SidecarMetricsPayload, TaskStreamEvent, TerminalStreamEvent, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSandboxMetricsOptions, UseSandboxMetricsResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useCreateSession, useDeleteSession, useDropdownMenu, useLiveTime, useRealtimeSession, useRenameSession, useRunCollapseState, useRunGroups, useSSEStream, useSandboxMetrics, useSdkSession, useSessions, useToolCallStream } from "./hooks.js";
10
11
  import { $ as InputProps, $t as ToastProvider, A as DropZoneProps, At as Table, B as DropdownMenuSeparator, Bt as TabsList, C as DialogFooter, Ct as SkeletonTable, D as DialogTitle, Dt as StatusPillProps, E as DialogPortal, Et as StatusPill, F as DropdownMenuItem, Ft as TableHead, G as DropdownMenuTrigger, H as DropdownMenuSub, I as DropdownMenuLabel, It as TableHeader, J as FilterField, Jt as Textarea, K as EmptyState, Kt as TextShimmer, L as DropdownMenuPortal, Lt as TableRow, M as DropdownMenuCheckboxItem, Mt as TableCaption, N as DropdownMenuContent, Nt as TableCell, O as DialogTrigger, Ot as StatusTone, P as DropdownMenuGroup, Pt as TableFooter, Q as Input, Qt as ToastContainer, R as DropdownMenuRadioGroup, Rt as Tabs, S as DialogDescription, St as SkeletonCard, T as DialogOverlay, Tt as StatCardProps, U as DropdownMenuSubContent, Ut as TerminalDisplay, V as DropdownMenuShortcut, Vt as TabsTrigger, W as DropdownMenuSubTrigger, X as InlineCode, Xt as ThemeToggle, Y as FilterFieldProps, Yt as TextareaProps, Z as InlineCodeProps, Zt as Toast, _ as CodeBlockProps, _t as SelectTrigger, a as AvatarImage, an as badgeVariants, at as Progress, b as DialogClose, bn as TangleKnot, bt as SidebarDropZoneProps, c as Button, cn as useToast, ct as SegmentedControlProps, d as CardContent, dt as SelectGroup, en as Toolbar, et as Label, f as CardDescription, ft as SelectItem, g as CodeBlock, gt as SelectSeparator, h as CardTitle, ht as SelectScrollUpButton, i as AvatarFallback, in as UploadProgressProps, it as MetricStripProps, j as DropdownMenu, jt as TableBody, k as DropZone, kt as Switch, l as ButtonProps, lt as Select, m as CardHeader, mt as SelectScrollDownButton, nn as UploadFile, nt as MetricProps, o as Badge, on as buttonVariants, ot as SegmentedControl, p as CardFooter, pt as SelectLabel, q as EmptyStateProps, qt as TextShimmerProps, r as Avatar, rn as UploadProgress, rt as MetricStrip, s as BadgeProps, sn as useTheme, st as SegmentedControlOption, tn as ToolbarProps, tt as Metric, u as Card, ut as SelectContent, v as CopyButton, vn as Logo, vt as SelectValue, w as DialogHeader, wt as StatCard, x as DialogContent, xt as Skeleton, y as Dialog, yn as LogoProps, yt as SidebarDropZone, z as DropdownMenuRadioItem, zt as TabsContent } from "./index-PRM636Ex.js";
11
- import { $ as TerminalProps, A as ShellShouldRevalidateArgs, B as SessionSidebarLink, C as SandboxWorkbenchLayoutOptions, D as SandboxWorkbenchSessionProps, E as SandboxWorkbenchProps, F as SessionSidebar, G as SessionOptimisticController, H as SessionSidebarVariant, I as SessionSidebarBadge, J as useOptimisticSessionItems, K as UseOptimisticSessionItemsOptions, L as SessionSidebarFilter, M as createShellShouldRevalidate, N as shellShouldRevalidate, O as SessionActivityMonitor, P as formatRelativeAge, Q as TerminalPanel, R as SessionSidebarGroupBy, S as SandboxWorkbenchFileArtifact, T as SandboxWorkbenchOpenUIArtifact, U as SESSION_CREATED_EVENT, V as SessionSidebarProps, W as SessionCreatedDetail, X as RuntimePaneProps, Y as RuntimePane, Z as TerminalLine, _ as FormAudit, a as ApprovalQueue, at as StatusBannerProps, b as SandboxWorkbenchArtifact, c as CalendarView, ct as WorkspacePaneHeader, d as TaskBoardColumn, dt as WorkspaceLayoutProps, et as ContextBadge, f as TaskBoardItem, g as AuditResultsProps, h as AuditResults, i as ApprovalItem, it as StatusBanner, j as ShellShouldRevalidateOptions, k as SessionActivityMonitorProps, l as CalendarViewProps, lt as WorkspacePaneHeaderProps, m as AuditCheck, n as ArtifactPaneProps, nt as StatusBarProps, o as ApprovalQueueProps, ot as DirectoryPane, p as TaskBoardProps, q as dispatchSessionCreated, r as ApprovalConfidenceStat, rt as BannerType, s as CalendarEvent, st as DirectoryPaneProps, t as ArtifactPane, tt as StatusBar, u as TaskBoard, ut as WorkspaceLayout, v as AgentWorkbench, w as SandboxWorkbenchMarkdownArtifact, x as SandboxWorkbenchCustomArtifact, y as SandboxWorkbench, z as SessionSidebarItem } from "./index-CKRaj1pM.js";
12
+ import { $ as TerminalProps, A as ShellShouldRevalidateArgs, B as SessionSidebarLink, C as SandboxWorkbenchLayoutOptions, D as SandboxWorkbenchSessionProps, E as SandboxWorkbenchProps, F as SessionSidebar, G as SessionOptimisticController, H as SessionSidebarVariant, I as SessionSidebarBadge, J as useOptimisticSessionItems, K as UseOptimisticSessionItemsOptions, L as SessionSidebarFilter, M as createShellShouldRevalidate, N as shellShouldRevalidate, O as SessionActivityMonitor, P as formatRelativeAge, Q as TerminalPanel, R as SessionSidebarGroupBy, S as SandboxWorkbenchFileArtifact, T as SandboxWorkbenchOpenUIArtifact, U as SESSION_CREATED_EVENT, V as SessionSidebarProps, W as SessionCreatedDetail, X as RuntimePaneProps, Y as RuntimePane, Z as TerminalLine, _ as FormAudit, a as ApprovalQueue, at as StatusBannerProps, b as SandboxWorkbenchArtifact, c as CalendarView, ct as WorkspacePaneHeader, d as TaskBoardColumn, dt as WorkspaceLayoutProps, et as ContextBadge, f as TaskBoardItem, g as AuditResultsProps, h as AuditResults, i as ApprovalItem, it as StatusBanner, j as ShellShouldRevalidateOptions, k as SessionActivityMonitorProps, l as CalendarViewProps, lt as WorkspacePaneHeaderProps, m as AuditCheck, n as ArtifactPaneProps, nt as StatusBarProps, o as ApprovalQueueProps, ot as DirectoryPane, p as TaskBoardProps, q as dispatchSessionCreated, r as ApprovalConfidenceStat, rt as BannerType, s as CalendarEvent, st as DirectoryPaneProps, t as ArtifactPane, tt as StatusBar, u as TaskBoard, ut as WorkspaceLayout, v as AgentWorkbench, w as SandboxWorkbenchMarkdownArtifact, x as SandboxWorkbenchCustomArtifact, y as SandboxWorkbench, z as SessionSidebarItem } from "./index-D8XVXO94.js";
12
13
  import { A as SandboxArtifactTerminal, C as ChangesPane, D as ChangesPaneProps, E as ChangedFile, O as SandboxArtifact, S as PillTabsProps, T as ArtifactView, _ as DiffStats, a as PreviewView, b as PillTabItem, c as DiffViewProps, d as FileBreadcrumb, f as FileBreadcrumbProps, g as PanelHeaderProps, h as PanelHeader, i as resolveLanguage, k as SandboxArtifactPaneProps, l as CodeView, m as GitStatusBadge, n as CodeSurface, o as PreviewViewProps, p as DiffStatsBadge, r as CodeSurfaceProps, s as DiffView, t as BRAND_PRISM_THEME, u as CodeViewProps, v as buildUnifiedPatch, w as SandboxArtifactPane, x as PillTabs, y as computeDiffStats } from "./index-D_G-wF6u.js";
13
14
  import { a as PreviewReadiness, i as PreviewAccess, n as EmbeddedAppView, r as EmbeddedAppViewProps, t as EmbeddedApp } from "./embedded-app-view-B_vMTtJn.js";
14
15
  import { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from "./openui.js";
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { a as computeDiffStats, c as BRAND_PRISM_THEME, d as DiffStatsBadge, f as GitStatusBadge, i as buildUnifiedPatch, l as CodeSurface, m as PillTabs, n as SandboxArtifactPane, o as CodeView, p as PanelHeader, r as DiffView, s as FileBreadcrumb, t as ChangesPane, u as resolveLanguage } from "./workbench-CBfynLzB.js";
1
+ import { a as computeDiffStats, c as BRAND_PRISM_THEME, d as DiffStatsBadge, f as GitStatusBadge, i as buildUnifiedPatch, l as CodeSurface, m as PillTabs, n as SandboxArtifactPane, o as CodeView, p as PanelHeader, r as DiffView, s as FileBreadcrumb, t as ChangesPane, u as resolveLanguage } from "./workbench-DJlOqodW.js";
2
2
  import { $ as SelectItem, A as DropdownMenuItem, At as Textarea, B as DropdownMenuTrigger, C as DialogTitle, Ct as TabsList, D as DropdownMenuCheckboxItem, E as DropdownMenu, Et as TerminalDisplay, F as DropdownMenuSeparator, Ft as UploadProgress, G as Label, Gt as TangleKnot, H as FilterField, I as DropdownMenuShortcut, It as badgeVariants, J as Progress, K as Metric, L as DropdownMenuSub, Lt as buttonVariants, M as DropdownMenuPortal, Mt as ToastContainer, N as DropdownMenuRadioGroup, Nt as ToastProvider, O as DropdownMenuContent, P as DropdownMenuRadioItem, Pt as Toolbar, Q as SelectGroup, R as DropdownMenuSubContent, Rt as useTheme, S as DialogPortal, St as TabsContent, T as DropZone, U as InlineCode, V as EmptyState, W as Input, Wt as Logo, X as Select, Y as SegmentedControl, Z as SelectContent, _ as DialogContent, _t as TableFooter, a as Badge, at as SelectValue, b as DialogHeader, bt as TableRow, c as CardContent, ct as SkeletonCard, d as CardHeader, dt as StatusPill, et as SelectLabel, f as CardTitle, ft as Switch, g as DialogClose, gt as TableCell, h as Dialog, ht as TableCaption, i as AvatarImage, it as SelectTrigger, j as DropdownMenuLabel, jt as ThemeToggle, k as DropdownMenuGroup, kt as TextShimmer, l as CardDescription, lt as SkeletonTable, m as CopyButton, mt as TableBody, n as Avatar, nt as SelectScrollUpButton, o as Button, ot as SidebarDropZone, p as CodeBlock, pt as Table, q as MetricStrip, r as AvatarFallback, rt as SelectSeparator, s as Card, st as Skeleton, tt as SelectScrollDownButton, u as CardFooter, ut as StatCard, v as DialogDescription, vt as TableHead, w as DialogTrigger, wt as TabsTrigger, x as DialogOverlay, xt as Tabs, y as DialogFooter, yt as TableHeader, z as DropdownMenuSubTrigger, zt as useToast } from "./primitives-Dh1vG6J3.js";
3
- import { t as WorkspacePaneHeader } from "./workspace-pane-header-C5e7sPaS.js";
4
- import { _ as TerminalPanel, a as AuditResults, b as DirectoryPane, c as SessionActivityMonitor, d as SessionSidebar, f as SESSION_CREATED_EVENT, g as RuntimePane, h as formatRelativeAge, i as TaskBoard, l as createShellShouldRevalidate, m as useOptimisticSessionItems, n as ApprovalQueue, o as AgentWorkbench, p as dispatchSessionCreated, r as CalendarView, s as SandboxWorkbench, t as ArtifactPane, u as shellShouldRevalidate, v as StatusBar, x as WorkspaceLayout, y as StatusBanner } from "./workspace-DoEZpkfF.js";
3
+ import { t as WorkspacePaneHeader } from "./workspace-pane-header-Bg1cCcHX.js";
4
+ import { _ as TerminalPanel, a as AuditResults, b as DirectoryPane, c as SessionActivityMonitor, d as SessionSidebar, f as SESSION_CREATED_EVENT, g as RuntimePane, h as formatRelativeAge, i as TaskBoard, l as createShellShouldRevalidate, m as useOptimisticSessionItems, n as ApprovalQueue, o as AgentWorkbench, p as dispatchSessionCreated, r as CalendarView, s as SandboxWorkbench, t as ArtifactPane, u as shellShouldRevalidate, v as StatusBar, x as WorkspaceLayout, y as StatusBanner } from "./workspace-CT4aDUE5.js";
5
5
  import { $ as SidebarRailNav, A as ResourceMeter, B as RailFlyout, C as InvoiceTable, D as canAdminSandbox, E as SandboxCard, F as CreditBalance, G as Sidebar, H as RailModeButton, I as ProfileAvatar, J as SidebarPanelContent, K as SidebarContent, L as RailButton, M as INSUFFICIENT_BALANCE_CODE, N as OutOfCreditsModal, O as ActivityFeed, P as parseInsufficientBalance, Q as SidebarRailHeader, R as RailCollapseToggle, S as PlanCards, T as NewSandboxCard, U as RailSeparator, V as RailHeader, W as RailThemeToggle, X as SidebarRail, Y as SidebarPanelHeader, Z as SidebarRailFooter, _ as HarnessPicker, a as ProcessList, at as SIDEBAR_TOTAL_WIDTH, b as HarnessLogo, c as UsageSummary, d as MetricAreaChart, et as RailTooltip, f as ProfileComparison, g as HARNESS_OPTIONS, h as DashboardLayout, i as NetworkConfig, it as SIDEBAR_RAIL_WIDTH, j as ClusterStatusBar, k as ResourceSnapshot, l as SystemLogsViewer, m as SidebarLayout, n as SnapshotList, nt as SIDEBAR_PANEL_WIDTH, o as PortsList, ot as SidebarProvider, p as ProfileSelector, q as SidebarPanel, r as BackendConfig, rt as SIDEBAR_RAIL_LABELED_WIDTH, s as GitPanel, st as useSidebar, t as PromoBanner, tt as SIDEBAR_MOBILE_WIDTH, u as VariantList, v as chatCapableHarnesses, w as SandboxTable, x as BackendSelector, y as HARNESS_BRAND, z as RailExpandable } from "./dashboard-CqyJQc7V.js";
6
6
  import { n as canonicalModelId, r as modelBrandFor, t as ModelBrandStack } from "./model-brand-hMyDTUqB.js";
7
7
  import { a as formatPrice, i as PricingPage, n as TemplateCard, o as BillingDashboard, r as UsageChart, t as InfoPanel } from "./info-panel-C9cqDzOL.js";
8
- import { t as usePtySession } from "./use-pty-session-C8cE0adT.js";
8
+ import { t as usePtySession } from "./use-pty-session-Bf4hBLXJ.js";
9
9
  import { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FilePreview, FileTabs, FileTree, RichFileTree, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind } from "./files.js";
10
- import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-CNWKeod5.js";
10
+ import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-CoiS_kfY.js";
11
11
  import { OpenUIArtifactRenderer } from "./openui.js";
12
12
  import { a as ThinkingIndicator, c as createFetchTransport, d as AgentProfilePicker, f as DEFAULT_REASONING_LEVEL_OPTIONS, i as MessageList, l as modelProvider, m as ReasoningLevelPicker, n as ChatContainer, o as UserMessage, p as HARNESS_REASONING_OPTIONS, r as ChatMessage, s as ArtifactAgentDock, t as AgentTimeline, u as snapHarnessToModel } from "./chat-BOvFAe6p.js";
13
13
  import { ExpandedToolDetail, InlineThinkingItem, InlineToolItem, LiveDuration, RunGroup, RunRowShell, RunRowStatusDot, ToolCallFeed, parseToolEvent } from "./run.js";
package/dist/styles.css CHANGED
@@ -839,8 +839,8 @@
839
839
  .h-\[1em\] {
840
840
  height: 1em;
841
841
  }
842
- .h-\[3px\] {
843
- height: 3px;
842
+ .h-\[9px\] {
843
+ height: 9px;
844
844
  }
845
845
  .h-\[17px\] {
846
846
  height: 17px;
@@ -1190,12 +1190,12 @@
1190
1190
  .w-\[1\.375rem\] {
1191
1191
  width: 1.375rem;
1192
1192
  }
1193
- .w-\[3px\] {
1194
- width: 3px;
1195
- }
1196
1193
  .w-\[5\.5rem\] {
1197
1194
  width: 5.5rem;
1198
1195
  }
1196
+ .w-\[9px\] {
1197
+ width: 9px;
1198
+ }
1199
1199
  .w-\[17px\] {
1200
1200
  width: 17px;
1201
1201
  }
@@ -1906,6 +1906,9 @@
1906
1906
  .overflow-hidden {
1907
1907
  overflow: hidden;
1908
1908
  }
1909
+ .overflow-visible {
1910
+ overflow: visible;
1911
+ }
1909
1912
  .overflow-x-auto {
1910
1913
  overflow-x: auto;
1911
1914
  }
@@ -2097,12 +2100,6 @@
2097
2100
  border-color: color-mix(in oklab, var(--brand-emerald) 50%, transparent);
2098
2101
  }
2099
2102
  }
2100
- .border-\[var\(--code-error\)\]\/20 {
2101
- border-color: var(--code-error);
2102
- @supports (color: color-mix(in lab, red, red)) {
2103
- border-color: color-mix(in oklab, var(--code-error) 20%, transparent);
2104
- }
2105
- }
2106
2103
  .border-\[var\(--code-number\)\]\/20 {
2107
2104
  border-color: var(--code-number);
2108
2105
  @supports (color: color-mix(in lab, red, red)) {
@@ -2373,12 +2370,6 @@
2373
2370
  .bg-\[var\(--code-error\)\] {
2374
2371
  background-color: var(--code-error);
2375
2372
  }
2376
- .bg-\[var\(--code-error\)\]\/5 {
2377
- background-color: var(--code-error);
2378
- @supports (color: color-mix(in lab, red, red)) {
2379
- background-color: color-mix(in oklab, var(--code-error) 5%, transparent);
2380
- }
2381
- }
2382
2373
  .bg-\[var\(--code-number\)\] {
2383
2374
  background-color: var(--code-number);
2384
2375
  }
@@ -3718,6 +3709,10 @@
3718
3709
  --tw-shadow: 0 6px 16px var(--tw-shadow-color, rgba(15,23,42,0.08));
3719
3710
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3720
3711
  }
3712
+ .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.18\)\] {
3713
+ --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.18));
3714
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3715
+ }
3721
3716
  .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.45\)\] {
3722
3717
  --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.45));
3723
3718
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -3989,6 +3984,14 @@
3989
3984
  border-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
3990
3985
  }
3991
3986
  }
3987
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3988
+ background-color: color-mix(in srgb, hsl(var(--primary)) 20%, transparent);
3989
+ }
3990
+ @supports (color: color-mix(in lab, red, red)) {
3991
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3992
+ background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
3993
+ }
3994
+ }
3992
3995
  .group-hover\:text-foreground:is(:where(.group):hover *) {
3993
3996
  color: var(--color-foreground);
3994
3997
  }
@@ -4016,6 +4019,12 @@
4016
4019
  opacity: 100%;
4017
4020
  }
4018
4021
  }
4022
+ .group-focus-visible\:bg-primary\/30:is(:where(.group):focus-visible *) {
4023
+ background-color: color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
4024
+ @supports (color: color-mix(in lab, red, red)) {
4025
+ background-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
4026
+ }
4027
+ }
4019
4028
  .peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled ~ *) {
4020
4029
  cursor: not-allowed;
4021
4030
  }
@@ -4348,14 +4357,6 @@
4348
4357
  background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
4349
4358
  }
4350
4359
  }
4351
- .hover\:bg-primary\/30:hover {
4352
- background-color: color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
4353
- }
4354
- @supports (color: color-mix(in lab, red, red)) {
4355
- .hover\:bg-primary\/30:hover {
4356
- background-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
4357
- }
4358
- }
4359
4360
  .hover\:bg-primary\/90:hover {
4360
4361
  background-color: color-mix(in srgb, hsl(var(--primary)) 90%, transparent);
4361
4362
  }
@@ -4554,12 +4555,6 @@
4554
4555
  .focus-visible\:bg-background:focus-visible {
4555
4556
  background-color: var(--color-background);
4556
4557
  }
4557
- .focus-visible\:bg-primary\/40:focus-visible {
4558
- background-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
4559
- @supports (color: color-mix(in lab, red, red)) {
4560
- background-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
4561
- }
4562
- }
4563
4558
  .focus-visible\:bg-surface-container:focus-visible {
4564
4559
  background-color: var(--color-surface-container);
4565
4560
  }
@@ -5004,9 +4999,6 @@
5004
4999
  .lg\:p-0 {
5005
5000
  padding: 0px;
5006
5001
  }
5007
- .lg\:p-4 {
5008
- padding: calc(var(--spacing) * 4);
5009
- }
5010
5002
  .lg\:px-8 {
5011
5003
  padding-inline: calc(var(--spacing) * 8);
5012
5004
  }
@@ -1,4 +1,4 @@
1
- import { t as usePtySession } from "./use-pty-session-C8cE0adT.js";
1
+ import { t as usePtySession } from "./use-pty-session-Bf4hBLXJ.js";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useMemo, useRef } from "react";
4
4
  import "@xterm/xterm/css/xterm.css";
@@ -30,7 +30,7 @@ const DEFAULT_TERMINAL_THEME = {
30
30
  brightCyan: "#67e8f9",
31
31
  brightWhite: "#fafafa"
32
32
  };
33
- function TerminalView({ apiUrl, token, theme, title = "Terminal", subtitle = "Connected to PTY session", isActive = true, connectionId, incarnationId, control, fontSize = 13 }) {
33
+ function TerminalView({ session, apiUrl, token, theme, title = "Terminal", subtitle = "Connected to PTY session", isActive = true, connectionId, incarnationId, control, fontSize = 13 }) {
34
34
  const resolvedTheme = useMemo(() => ({
35
35
  ...DEFAULT_TERMINAL_THEME,
36
36
  ...theme
@@ -55,7 +55,9 @@ function TerminalView({ apiUrl, token, theme, title = "Terminal", subtitle = "Co
55
55
  termRef.current?.write(chunks.length === 1 ? chunks[0] : chunks.join(""));
56
56
  });
57
57
  }, []);
58
- const { isConnected, error, sendCommand, resizeTerminal, reconnect } = usePtySession({
58
+ const usesCallerSession = session !== void 0;
59
+ const shellSession = usePtySession({
60
+ enabled: !usesCallerSession,
59
61
  apiUrl,
60
62
  token,
61
63
  onData,
@@ -63,6 +65,9 @@ function TerminalView({ apiUrl, token, theme, title = "Terminal", subtitle = "Co
63
65
  incarnationId,
64
66
  control
65
67
  });
68
+ const { isConnected, error, sendCommand, resizeTerminal, reconnect } = session ?? shellSession;
69
+ const subscribeData = session?.subscribeData;
70
+ useEffect(() => subscribeData?.(onData), [subscribeData, onData]);
66
71
  useEffect(() => {
67
72
  if (!containerRef.current) return;
68
73
  const term = new Terminal({
@@ -104,7 +109,7 @@ function TerminalView({ apiUrl, token, theme, title = "Terminal", subtitle = "Co
104
109
  termRef.current = term;
105
110
  fitAddonRef.current = fitAddon;
106
111
  term.onData((data) => {
107
- if (data === "\f") {
112
+ if (!usesCallerSession && data === "\f") {
108
113
  termRef.current?.clear();
109
114
  sendCommand("\r").catch(console.error);
110
115
  return;
@@ -139,7 +144,8 @@ function TerminalView({ apiUrl, token, theme, title = "Terminal", subtitle = "Co
139
144
  sendCommand,
140
145
  resizeTerminal,
141
146
  title,
142
- subtitle
147
+ subtitle,
148
+ usesCallerSession
143
149
  ]);
144
150
  useEffect(() => {
145
151
  if (termRef.current) termRef.current.options.theme = resolvedTheme;
@@ -1,3 +1,4 @@
1
+ import { n as UsePtySessionReturn } from "./use-pty-session-DbAYO5uH.js";
1
2
  import "@xterm/xterm/css/xterm.css";
2
3
  import { AgentInteractiveSessionControlClaim } from "@tangle-network/agent-interface";
3
4
  //#region src/terminal/terminal-view.d.ts
@@ -25,7 +26,13 @@ interface TerminalTheme {
25
26
  brightCyan: string;
26
27
  brightWhite: string;
27
28
  }
29
+ /** A caller-owned terminal connection, rendered without opening a shell. */
30
+ interface TerminalSession extends UsePtySessionReturn {
31
+ subscribeData(listener: (data: string) => void): () => void;
32
+ }
28
33
  interface TerminalViewProps {
34
+ /** Native session transport. The built-in shell transport stays disabled. */
35
+ session?: TerminalSession;
29
36
  /** Base URL of the sidecar. */
30
37
  apiUrl: string;
31
38
  /** Bearer token for authentication. */
@@ -59,6 +66,6 @@ interface TerminalViewProps {
59
66
  control?: AgentInteractiveSessionControlClaim;
60
67
  }
61
68
  export declare const DEFAULT_TERMINAL_THEME: TerminalTheme;
62
- declare function TerminalView({ apiUrl, token, theme, title, subtitle, isActive, connectionId, incarnationId, control, fontSize }: TerminalViewProps): import("react").JSX.Element;
69
+ declare function TerminalView({ session, apiUrl, token, theme, title, subtitle, isActive, connectionId, incarnationId, control, fontSize }: TerminalViewProps): import("react").JSX.Element;
63
70
  //#endregion
64
- export { type TerminalTheme, TerminalView, type TerminalViewProps };
71
+ export { type TerminalSession, type TerminalTheme, TerminalView, type TerminalViewProps };
package/dist/terminal.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as TerminalView, t as DEFAULT_TERMINAL_THEME } from "./terminal-CN9ZgHRt.js";
1
+ import { n as TerminalView, t as DEFAULT_TERMINAL_THEME } from "./terminal-DmSUfGha.js";
2
2
  export { DEFAULT_TERMINAL_THEME, TerminalView };
@@ -117,7 +117,7 @@ function interactiveIdentityKey(incarnationId, control) {
117
117
  * preserved as a fallback so the hook keeps working against
118
118
  * deployments that have not yet shipped the WS endpoint.
119
119
  */
120
- function usePtySession({ apiUrl, token, onData, connectionId: providedConnectionId, incarnationId, control }) {
120
+ function usePtySession({ enabled = true, apiUrl, token, onData, connectionId: providedConnectionId, incarnationId, control }) {
121
121
  const [isConnected, setIsConnected] = useState(false);
122
122
  const [error, setError] = useState(null);
123
123
  const sessionIdRef = useRef(null);
@@ -650,13 +650,18 @@ function usePtySession({ apiUrl, token, onData, connectionId: providedConnection
650
650
  });
651
651
  }, [ensureDrainRunning]);
652
652
  useEffect(() => {
653
+ if (!enabled) return;
653
654
  mountedRef.current = true;
654
655
  connect();
655
656
  return () => {
656
657
  mountedRef.current = false;
657
658
  cleanup();
658
659
  };
659
- }, [connect, cleanup]);
660
+ }, [
661
+ enabled,
662
+ connect,
663
+ cleanup
664
+ ]);
660
665
  return {
661
666
  isConnected,
662
667
  error,
@@ -0,0 +1,66 @@
1
+ import { AgentInteractiveSessionControlClaim } from "@tangle-network/agent-interface";
2
+ //#region src/hooks/use-pty-session.d.ts
3
+ interface UsePtySessionOptions {
4
+ /** Disable the built-in shell transport when a caller supplies a session. */
5
+ enabled?: boolean;
6
+ /** Base URL of the sidecar (e.g. "http://localhost:9100"). */
7
+ apiUrl: string;
8
+ /** Bearer token for authentication. */
9
+ token: string;
10
+ /** Called with raw PTY output (may contain ANSI escape codes). */
11
+ onData: (data: string) => void;
12
+ /**
13
+ * Stable id identifying this terminal connection to the sidecar.
14
+ * Reused on every connect/reconnect so the sidecar restores the same
15
+ * PTY session (within its reconnect window) instead of spawning a
16
+ * fresh shell. When omitted, a random id is generated per connect —
17
+ * so the session does not survive a remount.
18
+ */
19
+ connectionId?: string;
20
+ /**
21
+ * Exact incarnation issued for an interactive agent session. When present,
22
+ * it must be sent with `control` on every WebSocket init frame.
23
+ */
24
+ incarnationId?: string;
25
+ /** Write claim for the exact interactive agent session. */
26
+ control?: AgentInteractiveSessionControlClaim;
27
+ }
28
+ interface UsePtySessionReturn {
29
+ /** Whether the underlying transport is connected and receiving data. */
30
+ isConnected: boolean;
31
+ /** Connection or API error, if any. */
32
+ error: string | null;
33
+ /** Send a command to the PTY session. */
34
+ sendCommand: (command: string) => Promise<void>;
35
+ /** Safely resize the remote PTY. */
36
+ resizeTerminal: (cols: number, rows: number) => Promise<void>;
37
+ /** Tear down and reconnect. */
38
+ reconnect: () => void;
39
+ }
40
+ /**
41
+ * Manages a PTY session against the sidecar terminal API.
42
+ *
43
+ * Transport:
44
+ * 1. Try the current sidecar WebSocket contract directly:
45
+ * GET /terminals/:id/ws, then send `{"type":"init",...}`.
46
+ * - Server → client: BINARY frames carrying PTY output; TEXT frames
47
+ * carrying lifecycle/control messages.
48
+ * - Client → server: TEXT frames carrying JSON input/resize messages.
49
+ * 2. If direct WS does not reach server `ready` within
50
+ * WS_READY_TIMEOUT_MS, or it errors before ready, fall back to the older
51
+ * terminal contract:
52
+ * - POST /terminals creates the session.
53
+ * - GET /terminals/:id/ws tries the older WS transport.
54
+ * - GET /terminals/:id/stream (SSE for output)
55
+ * - POST /terminals/:id/input (one batched POST at a time)
56
+ * - PATCH /terminals/:id (resize)
57
+ * 3. DELETE /terminals/:id closes sessions created by the older REST API.
58
+ *
59
+ * The WS path eliminates the per-keystroke HTTP round-trip that
60
+ * dominates typing latency through edge proxies; the HTTP+SSE path is
61
+ * preserved as a fallback so the hook keeps working against
62
+ * deployments that have not yet shipped the WS endpoint.
63
+ */
64
+ declare function usePtySession({ enabled, apiUrl, token, onData, connectionId: providedConnectionId, incarnationId, control }: UsePtySessionOptions): UsePtySessionReturn;
65
+ //#endregion
66
+ export { UsePtySessionReturn as n, usePtySession as r, UsePtySessionOptions as t };
@@ -1,2 +1,2 @@
1
- import { t as EmbeddedAppView } from "../embedded-app-view-CNWKeod5.js";
1
+ import { t as EmbeddedAppView } from "../embedded-app-view-CoiS_kfY.js";
2
2
  export { EmbeddedAppView };
@@ -1,8 +1,8 @@
1
1
  import { t as cn$1 } from "./utils-DzWbktWG.js";
2
2
  import { o as PortsList } from "./dashboard-CqyJQc7V.js";
3
- import { n as TerminalView } from "./terminal-CN9ZgHRt.js";
3
+ import { n as TerminalView } from "./terminal-DmSUfGha.js";
4
4
  import { RichFileTree } from "./files.js";
5
- import { n as PreviewView } from "./embedded-app-view-CNWKeod5.js";
5
+ import { n as PreviewView } from "./embedded-app-view-CoiS_kfY.js";
6
6
  import { Button, Skeleton, Textarea } from "@tangle-network/ui/primitives";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import * as React$1 from "react";
package/dist/workbench.js CHANGED
@@ -1,3 +1,3 @@
1
- import { a as computeDiffStats, c as BRAND_PRISM_THEME, d as DiffStatsBadge, f as GitStatusBadge, i as buildUnifiedPatch, l as CodeSurface, m as PillTabs, n as SandboxArtifactPane, o as CodeView, p as PanelHeader, r as DiffView, s as FileBreadcrumb, t as ChangesPane, u as resolveLanguage } from "./workbench-CBfynLzB.js";
2
- import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-CNWKeod5.js";
1
+ import { a as computeDiffStats, c as BRAND_PRISM_THEME, d as DiffStatsBadge, f as GitStatusBadge, i as buildUnifiedPatch, l as CodeSurface, m as PillTabs, n as SandboxArtifactPane, o as CodeView, p as PanelHeader, r as DiffView, s as FileBreadcrumb, t as ChangesPane, u as resolveLanguage } from "./workbench-DJlOqodW.js";
2
+ import { n as PreviewView, t as EmbeddedAppView } from "./embedded-app-view-CoiS_kfY.js";
3
3
  export { BRAND_PRISM_THEME, ChangesPane, CodeSurface, CodeView, DiffStatsBadge, DiffView, EmbeddedAppView, FileBreadcrumb, GitStatusBadge, PanelHeader, PillTabs, PreviewView, SandboxArtifactPane, buildUnifiedPatch, computeDiffStats, resolveLanguage };
@@ -1,5 +1,5 @@
1
1
  import { t as cn$1 } from "./utils-DzWbktWG.js";
2
- import { t as WorkspacePaneHeader } from "./workspace-pane-header-C5e7sPaS.js";
2
+ import { t as WorkspacePaneHeader } from "./workspace-pane-header-Bg1cCcHX.js";
3
3
  import { t as MOTION_CONTROL } from "./motion-DkyBRJb9.js";
4
4
  import { ArtifactPane, ArtifactPane as ArtifactPane$1, Badge, EmptyState, Input } from "@tangle-network/ui/primitives";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -88,8 +88,14 @@ function ResizeHandle({ label, onDragStart, onStep, className }) {
88
88
  "aria-orientation": "vertical",
89
89
  onPointerDown: handlePointerDown,
90
90
  onKeyDown: handleKeyDown,
91
- className: cn$1("relative hidden w-3 shrink-0 cursor-col-resize lg:flex", "items-stretch justify-center bg-transparent touch-none", focusRing, className),
92
- children: [/* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-[var(--md3-outline-variant)] transition-colors" }), /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 left-1/2 w-[3px] -translate-x-1/2 rounded-full bg-transparent hover:bg-primary/30 focus-visible:bg-primary/40" })]
91
+ className: cn$1("group relative z-10 hidden w-px shrink-0 cursor-col-resize overflow-visible bg-transparent p-0 touch-none lg:flex", focusRing, className),
92
+ children: [/* @__PURE__ */ jsx("span", {
93
+ "aria-hidden": "true",
94
+ className: "absolute inset-y-0 left-1/2 z-10 w-[9px] -translate-x-1/2 cursor-col-resize bg-transparent"
95
+ }), /* @__PURE__ */ jsx("span", {
96
+ "aria-hidden": "true",
97
+ className: "absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-border transition-colors group-hover:bg-primary/20 group-focus-visible:bg-primary/30"
98
+ })]
93
99
  });
94
100
  }
95
101
  function HorizontalResizeHandle({ label, onDragStart, onStep, className }) {
@@ -114,8 +120,14 @@ function HorizontalResizeHandle({ label, onDragStart, onStep, className }) {
114
120
  "aria-orientation": "horizontal",
115
121
  onPointerDown: handlePointerDown,
116
122
  onKeyDown: handleKeyDown,
117
- className: cn$1("relative hidden h-3 shrink-0 cursor-row-resize lg:flex", "items-center justify-center bg-transparent touch-none w-full", focusRing, className),
118
- children: [/* @__PURE__ */ jsx("span", { className: "absolute inset-x-0 top-1/2 h-px -translate-y-1/2 bg-[var(--md3-outline-variant)] transition-colors" }), /* @__PURE__ */ jsx("span", { className: "absolute inset-x-0 top-1/2 h-[3px] -translate-y-1/2 rounded-full bg-transparent hover:bg-primary/30 focus-visible:bg-primary/40" })]
123
+ className: cn$1("group relative z-10 hidden h-px w-full shrink-0 cursor-row-resize overflow-visible bg-transparent p-0 touch-none lg:flex", focusRing, className),
124
+ children: [/* @__PURE__ */ jsx("span", {
125
+ "aria-hidden": "true",
126
+ className: "absolute inset-x-0 top-1/2 z-10 h-[9px] w-full -translate-y-1/2 cursor-row-resize bg-transparent"
127
+ }), /* @__PURE__ */ jsx("span", {
128
+ "aria-hidden": "true",
129
+ className: "absolute inset-x-0 top-1/2 h-px -translate-y-1/2 bg-border transition-colors group-hover:bg-primary/20 group-focus-visible:bg-primary/30"
130
+ })]
119
131
  });
120
132
  }
121
133
  function MobileDrawer({ side, title, header, onClose, children }) {
@@ -130,7 +142,7 @@ function MobileDrawer({ side, title, header, onClose, children }) {
130
142
  onClick: onClose,
131
143
  className: "absolute inset-0 bg-black/80 backdrop-blur-sm"
132
144
  }), /* @__PURE__ */ jsxs("aside", {
133
- className: cn$1("relative flex h-full w-[min(88vw,24rem)] flex-col border-[var(--md3-outline-variant)] bg-surface-container-highest shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]", side === "left" ? "border-r" : "ml-auto border-l"),
145
+ className: cn$1("relative flex h-full w-[min(88vw,24rem)] flex-col border-border bg-card shadow-[0_8px_30px_rgba(0,0,0,0.18)]", side === "left" ? "border-r" : "ml-auto border-l"),
134
146
  children: [/* @__PURE__ */ jsxs(WorkspacePaneHeader, {
135
147
  className: "justify-between gap-3",
136
148
  children: [/* @__PURE__ */ jsx("div", {
@@ -335,7 +347,7 @@ function WorkspaceLayout({ left, leftHeader, center, centerHeader, centerFooter,
335
347
  "data-sandbox-theme": theme
336
348
  } : {},
337
349
  "data-density": density,
338
- className: cn$1("flex h-screen flex-col overflow-hidden bg-[var(--bg-root)] text-foreground font-sans", className),
350
+ className: cn$1("flex h-screen flex-col overflow-hidden bg-background text-foreground font-sans", className),
339
351
  children: [
340
352
  /* @__PURE__ */ jsxs("div", {
341
353
  ref: shellRef,
@@ -344,7 +356,7 @@ function WorkspaceLayout({ left, leftHeader, center, centerHeader, centerFooter,
344
356
  desktop && left && leftOpen && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("aside", {
345
357
  "aria-label": leftLabel,
346
358
  style: leftStyle,
347
- className: "hidden shrink-0 border-r border-[var(--md3-outline-variant)] bg-surface-container-low lg:flex lg:flex-col",
359
+ className: cn$1("hidden shrink-0 bg-card lg:flex lg:flex-col", !resizable && "border-r border-border"),
348
360
  children: [leftHeader && /* @__PURE__ */ jsxs(WorkspacePaneHeader, {
349
361
  className: "justify-between gap-2",
350
362
  children: [/* @__PURE__ */ jsx("div", {
@@ -409,12 +421,12 @@ function WorkspaceLayout({ left, leftHeader, center, centerHeader, centerFooter,
409
421
  onStep: stepBottomHeight
410
422
  }), /* @__PURE__ */ jsx("section", {
411
423
  "aria-label": bottomLabel,
412
- className: "border-t border-[var(--md3-outline-variant)] bg-surface-container shrink-0",
424
+ className: cn$1("shrink-0 bg-card", !resizable && "border-t border-border"),
413
425
  style: { height: `${bottomHeight}px` },
414
426
  children: /* @__PURE__ */ jsxs("div", {
415
427
  className: "flex h-full flex-col",
416
428
  children: [/* @__PURE__ */ jsxs("div", {
417
- className: "flex items-center justify-between gap-2 border-b border-[var(--md3-outline-variant)] px-3 py-1.5 bg-surface-container-high shrink-0",
429
+ className: "flex items-center justify-between gap-2 border-b border-border bg-background px-3 py-1.5 shrink-0",
418
430
  children: [/* @__PURE__ */ jsx("div", {
419
431
  className: "min-w-0 flex-1",
420
432
  children: bottomHeader ?? /* @__PURE__ */ jsx("span", {
@@ -435,7 +447,7 @@ function WorkspaceLayout({ left, leftHeader, center, centerHeader, centerFooter,
435
447
  })
436
448
  })] }),
437
449
  centerFooter && /* @__PURE__ */ jsx("div", {
438
- className: "shrink-0 border-t border-[var(--md3-outline-variant)] bg-surface-container-low",
450
+ className: "shrink-0 border-t border-border bg-card",
439
451
  children: centerFooter
440
452
  })
441
453
  ]
@@ -447,7 +459,7 @@ function WorkspaceLayout({ left, leftHeader, center, centerHeader, centerFooter,
447
459
  }), /* @__PURE__ */ jsxs("aside", {
448
460
  "aria-label": rightLabel,
449
461
  style: rightStyle,
450
- className: "hidden shrink-0 border-l border-[var(--md3-outline-variant)] bg-surface-container-low lg:flex lg:flex-col",
462
+ className: cn$1("hidden shrink-0 bg-card lg:flex lg:flex-col", !resizable && "border-l border-border"),
451
463
  children: [/* @__PURE__ */ jsxs(WorkspacePaneHeader, {
452
464
  className: "justify-between gap-2",
453
465
  children: [/* @__PURE__ */ jsx("div", {
@@ -586,7 +598,7 @@ function DirectoryPane({ root, selectedPath, onSelect, onRefresh, onUpload, titl
586
598
  //#endregion
587
599
  //#region src/workspace/status-banner.tsx
588
600
  /**
589
- * StatusBanner — full-width notification banner for connection/provisioning states.
601
+ * StatusBanner — inline notice for connection and provisioning states.
590
602
  */
591
603
  const BANNER_STYLES = {
592
604
  provisioning: {
@@ -602,9 +614,9 @@ const BANNER_STYLES = {
602
614
  icon: Wifi
603
615
  },
604
616
  error: {
605
- bg: "bg-[var(--code-error)]/5",
606
- border: "border-[var(--code-error)]/20",
607
- text: "text-[var(--code-error)]",
617
+ bg: "bg-[var(--surface-danger-bg)]",
618
+ border: "border-[var(--surface-danger-border)]",
619
+ text: "text-[var(--surface-danger-text)]",
608
620
  icon: AlertCircle
609
621
  },
610
622
  warning: {
@@ -620,8 +632,8 @@ const BANNER_STYLES = {
620
632
  icon: CheckCircle
621
633
  },
622
634
  info: {
623
- bg: "bg-surface-container-high",
624
- border: "border-[var(--md3-outline-variant)]",
635
+ bg: "bg-background",
636
+ border: "border-border",
625
637
  text: "text-muted-foreground",
626
638
  icon: AlertCircle
627
639
  }
@@ -632,27 +644,27 @@ function StatusBanner({ type, message, detail, onDismiss, className }) {
632
644
  const isAnimated = type === "provisioning" || type === "connecting";
633
645
  const role = type === "error" ? "alert" : "status";
634
646
  return /* @__PURE__ */ jsxs("div", {
635
- className: cn$1("flex items-center gap-2.5 px-4 py-2 border-b font-sans text-sm", style.bg, style.border, className),
647
+ className: cn$1("flex items-start gap-3 rounded-lg border px-3 py-2.5 font-sans text-sm", style.bg, style.border, className),
636
648
  children: [/* @__PURE__ */ jsxs("div", {
637
649
  role,
638
- className: "flex min-w-0 items-center gap-2.5",
639
- children: [
640
- /* @__PURE__ */ jsx(Icon, {
641
- className: cn$1("h-4 w-4 shrink-0", style.text, isAnimated && "animate-spin"),
642
- ...isAnimated ? { "data-motion": "essential" } : {}
643
- }),
644
- /* @__PURE__ */ jsx("span", {
645
- className: "font-medium text-foreground",
650
+ className: "flex min-w-0 flex-1 items-start gap-2.5",
651
+ children: [/* @__PURE__ */ jsx(Icon, {
652
+ className: cn$1("mt-0.5 h-4 w-4 shrink-0", style.text, isAnimated && "animate-spin"),
653
+ ...isAnimated ? { "data-motion": "essential" } : {}
654
+ }), /* @__PURE__ */ jsxs("div", {
655
+ className: "min-w-0 flex-1",
656
+ children: [/* @__PURE__ */ jsx("p", {
657
+ className: "break-words font-medium text-foreground",
646
658
  children: message
647
- }),
648
- detail && /* @__PURE__ */ jsx("span", {
649
- className: "font-mono text-xs text-muted-foreground tabular-nums",
659
+ }), detail && /* @__PURE__ */ jsx("p", {
660
+ className: "mt-0.5 break-words font-mono text-xs text-muted-foreground tabular-nums",
650
661
  children: detail
651
- })
652
- ]
662
+ })]
663
+ })]
653
664
  }), onDismiss && /* @__PURE__ */ jsx("button", {
665
+ type: "button",
654
666
  onClick: onDismiss,
655
- className: "ml-auto font-sans text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
667
+ className: `ml-auto mt-0.5 shrink-0 font-sans text-xs font-medium text-muted-foreground transition-colors hover:text-foreground ${focusRing}`,
656
668
  children: "Dismiss"
657
669
  })]
658
670
  });
@@ -1541,12 +1553,12 @@ function ArtifactTabs({ artifacts, activeArtifactId, onSelect, onClose, tabIdPre
1541
1553
  return /* @__PURE__ */ jsx("div", {
1542
1554
  role: "tablist",
1543
1555
  "aria-label": "Artifacts",
1544
- className: "flex items-center overflow-x-auto border-b border-[var(--md3-outline-variant)] bg-surface-container-high",
1556
+ className: "flex items-center overflow-x-auto border-b border-border bg-background",
1545
1557
  children: artifacts.map((artifact) => {
1546
1558
  const Icon = artifact.icon ?? getArtifactTabIcon(artifact.kind);
1547
1559
  const isActive = artifact.id === activeArtifactId;
1548
1560
  return /* @__PURE__ */ jsxs("div", {
1549
- className: cn$1("group flex shrink-0 items-center border-r border-[var(--md3-outline-variant)] bg-surface-container relative", isActive ? "text-foreground after:absolute after:top-0 after:left-0 after:right-0 after:h-[2px] after:bg-primary" : "text-muted-foreground hover:bg-surface-container-high cursor-pointer"),
1561
+ className: cn$1("group relative flex shrink-0 items-center border-r border-border bg-card", isActive ? "text-foreground after:absolute after:top-0 after:left-0 after:right-0 after:h-[2px] after:bg-primary" : "cursor-pointer text-muted-foreground hover:bg-muted"),
1550
1562
  children: [/* @__PURE__ */ jsxs("button", {
1551
1563
  type: "button",
1552
1564
  ref: (element) => {
@@ -1602,7 +1614,7 @@ function ArtifactTabs({ artifacts, activeArtifactId, onSelect, onClose, tabIdPre
1602
1614
  function renderArtifact(artifact) {
1603
1615
  switch (artifact.kind) {
1604
1616
  case "file": return /* @__PURE__ */ jsx(FileArtifactPane, {
1605
- path: artifact.path,
1617
+ path: artifact.path === artifact.filename ? void 0 : artifact.path,
1606
1618
  filename: artifact.filename,
1607
1619
  content: artifact.content,
1608
1620
  blobUrl: artifact.blobUrl,
@@ -1612,10 +1624,11 @@ function renderArtifact(artifact) {
1612
1624
  activeTabId: artifact.activeTabId,
1613
1625
  onTabSelect: artifact.onTabSelect,
1614
1626
  onTabClose: artifact.onTabClose,
1615
- eyebrow: artifact.eyebrow,
1627
+ eyebrow: artifact.eyebrow ?? null,
1616
1628
  meta: artifact.meta,
1617
1629
  toolbar: artifact.toolbar,
1618
- footer: artifact.footer
1630
+ footer: artifact.footer,
1631
+ hideTitleBlock: typeof artifact.title === "string" && artifact.title === artifact.filename && artifact.path === artifact.filename && !artifact.eyebrow && !artifact.meta
1619
1632
  });
1620
1633
  case "markdown": return /* @__PURE__ */ jsx(ArtifactPane, {
1621
1634
  eyebrow: artifact.eyebrow ?? "Document",
@@ -1713,7 +1726,7 @@ function SandboxWorkbench({ title = "Sandbox session", subtitle, status, centerH
1713
1726
  onArtifactChange?.(artifactId);
1714
1727
  };
1715
1728
  const brandedHeader = /* @__PURE__ */ jsxs("div", {
1716
- className: "flex min-w-0 items-start justify-between gap-4 rounded-[var(--radius-xl)] border border-[var(--md3-outline-variant)] bg-surface-container px-4 py-3.5",
1729
+ className: "flex min-w-0 items-start justify-between gap-4 rounded-[var(--radius-xl)] border border-border bg-card px-4 py-3.5",
1717
1730
  children: [/* @__PURE__ */ jsxs("div", {
1718
1731
  className: "min-w-0",
1719
1732
  children: [
@@ -1742,25 +1755,15 @@ function SandboxWorkbench({ title = "Sandbox session", subtitle, status, centerH
1742
1755
  const centerHeader = centerHeaderProp === void 0 ? brandedHeader : centerHeaderProp ?? void 0;
1743
1756
  const { composerControls, ...chatSession } = session;
1744
1757
  const transcript = /* @__PURE__ */ jsxs("div", {
1745
- className: cn$1("flex h-full min-h-0 flex-col", quiet && "bg-surface"),
1746
- children: [
1747
- /* @__PURE__ */ jsx(ChatContainer, {
1748
- ...chatSession,
1749
- className: "min-h-0 flex-1",
1750
- presentation: session.presentation ?? "timeline"
1751
- }),
1752
- composerControls && /* @__PURE__ */ jsx("div", {
1753
- className: "shrink-0 border-t border-[var(--md3-outline-variant)] bg-surface-container-high px-3 py-2",
1754
- children: composerControls
1755
- }),
1756
- composer && /* @__PURE__ */ jsx("div", {
1757
- className: "shrink-0",
1758
- children: /* @__PURE__ */ jsx("div", {
1759
- className: "mx-auto w-full max-w-3xl px-3 pb-3",
1760
- children: composer
1761
- })
1762
- })
1763
- ]
1758
+ className: cn$1("flex h-full min-h-0 flex-col", quiet && "bg-background"),
1759
+ children: [/* @__PURE__ */ jsx(ChatContainer, {
1760
+ ...chatSession,
1761
+ className: "min-h-0 flex-1",
1762
+ presentation: session.presentation ?? "timeline"
1763
+ }), (composerControls || composer) && /* @__PURE__ */ jsxs("div", {
1764
+ className: "mx-auto flex w-full max-w-3xl shrink-0 flex-col gap-2 px-3 py-3",
1765
+ children: [composerControls, composer]
1766
+ })]
1764
1767
  });
1765
1768
  const center = quiet ? transcript : /* @__PURE__ */ jsx(ArtifactPane, {
1766
1769
  eyebrow: session.eyebrow ?? "Agent Session",
@@ -1769,11 +1772,11 @@ function SandboxWorkbench({ title = "Sandbox session", subtitle, status, centerH
1769
1772
  meta: session.meta,
1770
1773
  headerActions: session.headerActions,
1771
1774
  className: "h-full",
1772
- contentClassName: "bg-surface-container",
1775
+ contentClassName: "bg-background",
1773
1776
  children: transcript
1774
1777
  });
1775
1778
  const artifactPanel = artifacts.length > 0 || emptyArtifactState ? /* @__PURE__ */ jsxs("section", {
1776
- className: "flex h-full min-h-0 flex-col bg-surface-container",
1779
+ className: "flex h-full min-h-0 flex-col bg-background",
1777
1780
  children: [/* @__PURE__ */ jsx(ArtifactTabs, {
1778
1781
  artifacts,
1779
1782
  activeArtifactId: resolvedArtifactId,
@@ -1787,7 +1790,7 @@ function SandboxWorkbench({ title = "Sandbox session", subtitle, status, centerH
1787
1790
  "aria-labelledby": activeArtifact ? `${artifactTabsId}-${activeArtifact.id}` : void 0,
1788
1791
  "aria-label": activeArtifact ? void 0 : "Artifact content",
1789
1792
  tabIndex: 0,
1790
- className: `min-h-0 flex-1 overflow-auto bg-surface-container ${focusRingInset}`,
1793
+ className: `min-h-0 flex-1 overflow-auto bg-background ${focusRingInset}`,
1791
1794
  children: activeArtifact ? renderArtifact(activeArtifact) : /* @__PURE__ */ jsx("div", {
1792
1795
  className: "flex h-full items-center justify-center p-6",
1793
1796
  children: emptyArtifactState ?? /* @__PURE__ */ jsx(EmptyState, {
@@ -1866,7 +1869,7 @@ function SandboxWorkbench({ title = "Sandbox session", subtitle, status, centerH
1866
1869
  leftCollapsedControl: layout?.leftCollapsedControl,
1867
1870
  leftContentClassName: railOnly ? "py-0" : void 0,
1868
1871
  centerHeaderVisibility: quiet ? "auto" : "always",
1869
- className: cn$1("p-3 lg:p-4", className)
1872
+ className: cn$1("p-2", className)
1870
1873
  });
1871
1874
  }
1872
1875
  function AgentWorkbench(props) {
@@ -7,7 +7,7 @@ import { jsx } from "react/jsx-runtime";
7
7
  */
8
8
  function WorkspacePaneHeader({ className, ...props }) {
9
9
  return /* @__PURE__ */ jsx("div", {
10
- className: cn("flex h-14 shrink-0 items-center border-b border-[var(--md3-outline-variant)] bg-surface-container-high px-3", className),
10
+ className: cn("flex h-14 shrink-0 items-center border-b border-border bg-card px-3", className),
11
11
  ...props
12
12
  });
13
13
  }
@@ -1,2 +1,2 @@
1
- import { $ as TerminalProps, A as ShellShouldRevalidateArgs, B as SessionSidebarLink, C as SandboxWorkbenchLayoutOptions, D as SandboxWorkbenchSessionProps, E as SandboxWorkbenchProps, F as SessionSidebar, G as SessionOptimisticController, H as SessionSidebarVariant, I as SessionSidebarBadge, J as useOptimisticSessionItems, K as UseOptimisticSessionItemsOptions, L as SessionSidebarFilter, M as createShellShouldRevalidate, N as shellShouldRevalidate, O as SessionActivityMonitor, P as formatRelativeAge, Q as TerminalPanel, R as SessionSidebarGroupBy, S as SandboxWorkbenchFileArtifact, T as SandboxWorkbenchOpenUIArtifact, U as SESSION_CREATED_EVENT, V as SessionSidebarProps, W as SessionCreatedDetail, X as RuntimePaneProps, Y as RuntimePane, Z as TerminalLine, _ as FormAudit, a as ApprovalQueue, at as StatusBannerProps, b as SandboxWorkbenchArtifact, c as CalendarView, ct as WorkspacePaneHeader, d as TaskBoardColumn, dt as WorkspaceLayoutProps, et as ContextBadge, f as TaskBoardItem, g as AuditResultsProps, h as AuditResults, i as ApprovalItem, it as StatusBanner, j as ShellShouldRevalidateOptions, k as SessionActivityMonitorProps, l as CalendarViewProps, lt as WorkspacePaneHeaderProps, m as AuditCheck, n as ArtifactPaneProps, nt as StatusBarProps, o as ApprovalQueueProps, ot as DirectoryPane, p as TaskBoardProps, q as dispatchSessionCreated, r as ApprovalConfidenceStat, rt as BannerType, s as CalendarEvent, st as DirectoryPaneProps, t as ArtifactPane, tt as StatusBar, u as TaskBoard, ut as WorkspaceLayout, v as AgentWorkbench, w as SandboxWorkbenchMarkdownArtifact, x as SandboxWorkbenchCustomArtifact, y as SandboxWorkbench, z as SessionSidebarItem } from "./index-CKRaj1pM.js";
1
+ import { $ as TerminalProps, A as ShellShouldRevalidateArgs, B as SessionSidebarLink, C as SandboxWorkbenchLayoutOptions, D as SandboxWorkbenchSessionProps, E as SandboxWorkbenchProps, F as SessionSidebar, G as SessionOptimisticController, H as SessionSidebarVariant, I as SessionSidebarBadge, J as useOptimisticSessionItems, K as UseOptimisticSessionItemsOptions, L as SessionSidebarFilter, M as createShellShouldRevalidate, N as shellShouldRevalidate, O as SessionActivityMonitor, P as formatRelativeAge, Q as TerminalPanel, R as SessionSidebarGroupBy, S as SandboxWorkbenchFileArtifact, T as SandboxWorkbenchOpenUIArtifact, U as SESSION_CREATED_EVENT, V as SessionSidebarProps, W as SessionCreatedDetail, X as RuntimePaneProps, Y as RuntimePane, Z as TerminalLine, _ as FormAudit, a as ApprovalQueue, at as StatusBannerProps, b as SandboxWorkbenchArtifact, c as CalendarView, ct as WorkspacePaneHeader, d as TaskBoardColumn, dt as WorkspaceLayoutProps, et as ContextBadge, f as TaskBoardItem, g as AuditResultsProps, h as AuditResults, i as ApprovalItem, it as StatusBanner, j as ShellShouldRevalidateOptions, k as SessionActivityMonitorProps, l as CalendarViewProps, lt as WorkspacePaneHeaderProps, m as AuditCheck, n as ArtifactPaneProps, nt as StatusBarProps, o as ApprovalQueueProps, ot as DirectoryPane, p as TaskBoardProps, q as dispatchSessionCreated, r as ApprovalConfidenceStat, rt as BannerType, s as CalendarEvent, st as DirectoryPaneProps, t as ArtifactPane, tt as StatusBar, u as TaskBoard, ut as WorkspaceLayout, v as AgentWorkbench, w as SandboxWorkbenchMarkdownArtifact, x as SandboxWorkbenchCustomArtifact, y as SandboxWorkbench, z as SessionSidebarItem } from "./index-D8XVXO94.js";
2
2
  export { AgentWorkbench, type ApprovalConfidenceStat, type ApprovalItem, ApprovalQueue, type ApprovalQueueProps, ArtifactPane, type ArtifactPaneProps, type AuditCheck, AuditResults, type AuditResultsProps, type BannerType, type CalendarEvent, CalendarView, type CalendarViewProps, type ContextBadge, DirectoryPane, type DirectoryPaneProps, type FormAudit, RuntimePane, type RuntimePaneProps, SESSION_CREATED_EVENT, SandboxWorkbench, type SandboxWorkbenchArtifact, type SandboxWorkbenchCustomArtifact, type SandboxWorkbenchFileArtifact, type SandboxWorkbenchLayoutOptions, type SandboxWorkbenchMarkdownArtifact, type SandboxWorkbenchOpenUIArtifact, type SandboxWorkbenchProps, type SandboxWorkbenchSessionProps, SessionActivityMonitor, type SessionActivityMonitorProps, type SessionCreatedDetail, type SessionOptimisticController, SessionSidebar, type SessionSidebarBadge, type SessionSidebarFilter, type SessionSidebarGroupBy, type SessionSidebarItem, type SessionSidebarLink, type SessionSidebarProps, type SessionSidebarVariant, type ShellShouldRevalidateArgs, type ShellShouldRevalidateOptions, StatusBanner, type StatusBannerProps, StatusBar, type StatusBarProps, TaskBoard, type TaskBoardColumn, type TaskBoardItem, type TaskBoardProps, type TerminalLine, TerminalPanel, type TerminalProps, type UseOptimisticSessionItemsOptions, WorkspaceLayout, type WorkspaceLayoutProps, WorkspacePaneHeader, type WorkspacePaneHeaderProps, createShellShouldRevalidate, dispatchSessionCreated, formatRelativeAge, shellShouldRevalidate, useOptimisticSessionItems };
package/dist/workspace.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as WorkspacePaneHeader } from "./workspace-pane-header-C5e7sPaS.js";
2
- import { _ as TerminalPanel, a as AuditResults, b as DirectoryPane, c as SessionActivityMonitor, d as SessionSidebar, f as SESSION_CREATED_EVENT, g as RuntimePane, h as formatRelativeAge, i as TaskBoard, l as createShellShouldRevalidate, m as useOptimisticSessionItems, n as ApprovalQueue, o as AgentWorkbench, p as dispatchSessionCreated, r as CalendarView, s as SandboxWorkbench, t as ArtifactPane, u as shellShouldRevalidate, v as StatusBar, x as WorkspaceLayout, y as StatusBanner } from "./workspace-DoEZpkfF.js";
1
+ import { t as WorkspacePaneHeader } from "./workspace-pane-header-Bg1cCcHX.js";
2
+ import { _ as TerminalPanel, a as AuditResults, b as DirectoryPane, c as SessionActivityMonitor, d as SessionSidebar, f as SESSION_CREATED_EVENT, g as RuntimePane, h as formatRelativeAge, i as TaskBoard, l as createShellShouldRevalidate, m as useOptimisticSessionItems, n as ApprovalQueue, o as AgentWorkbench, p as dispatchSessionCreated, r as CalendarView, s as SandboxWorkbench, t as ArtifactPane, u as shellShouldRevalidate, v as StatusBar, x as WorkspaceLayout, y as StatusBanner } from "./workspace-CT4aDUE5.js";
3
3
  export { AgentWorkbench, ApprovalQueue, ArtifactPane, AuditResults, CalendarView, DirectoryPane, RuntimePane, SESSION_CREATED_EVENT, SandboxWorkbench, SessionActivityMonitor, SessionSidebar, StatusBanner, StatusBar, TaskBoard, TerminalPanel, WorkspaceLayout, WorkspacePaneHeader, createShellShouldRevalidate, dispatchSessionCreated, formatRelativeAge, shellShouldRevalidate, useOptimisticSessionItems };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.115.7",
3
+ "version": "0.116.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",