@tangle-network/sandbox-ui 0.115.7 → 0.116.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
  }
@@ -1319,6 +1319,9 @@
1319
1319
  .max-w-\[14rem\] {
1320
1320
  max-width: 14rem;
1321
1321
  }
1322
+ .max-w-\[35\%\] {
1323
+ max-width: 35%;
1324
+ }
1322
1325
  .max-w-\[45\%\] {
1323
1326
  max-width: 45%;
1324
1327
  }
@@ -1906,6 +1909,9 @@
1906
1909
  .overflow-hidden {
1907
1910
  overflow: hidden;
1908
1911
  }
1912
+ .overflow-visible {
1913
+ overflow: visible;
1914
+ }
1909
1915
  .overflow-x-auto {
1910
1916
  overflow-x: auto;
1911
1917
  }
@@ -2097,12 +2103,6 @@
2097
2103
  border-color: color-mix(in oklab, var(--brand-emerald) 50%, transparent);
2098
2104
  }
2099
2105
  }
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
2106
  .border-\[var\(--code-number\)\]\/20 {
2107
2107
  border-color: var(--code-number);
2108
2108
  @supports (color: color-mix(in lab, red, red)) {
@@ -2373,12 +2373,6 @@
2373
2373
  .bg-\[var\(--code-error\)\] {
2374
2374
  background-color: var(--code-error);
2375
2375
  }
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
2376
  .bg-\[var\(--code-number\)\] {
2383
2377
  background-color: var(--code-number);
2384
2378
  }
@@ -2921,9 +2915,6 @@
2921
2915
  .py-3 {
2922
2916
  padding-block: calc(var(--spacing) * 3);
2923
2917
  }
2924
- .py-3\.5 {
2925
- padding-block: calc(var(--spacing) * 3.5);
2926
- }
2927
2918
  .py-4 {
2928
2919
  padding-block: calc(var(--spacing) * 4);
2929
2920
  }
@@ -3155,9 +3146,6 @@
3155
3146
  .text-\[15px\] {
3156
3147
  font-size: 15px;
3157
3148
  }
3158
- .text-\[17px\] {
3159
- font-size: 17px;
3160
- }
3161
3149
  .text-\[calc\(var\(--font-size-xs\)-1px\)\] {
3162
3150
  font-size: calc(var(--font-size-xs) - 1px);
3163
3151
  }
@@ -3274,10 +3262,6 @@
3274
3262
  --tw-font-weight: var(--font-weight-semibold);
3275
3263
  font-weight: var(--font-weight-semibold);
3276
3264
  }
3277
- .tracking-\[0\.01em\] {
3278
- --tw-tracking: 0.01em;
3279
- letter-spacing: 0.01em;
3280
- }
3281
3265
  .tracking-\[0\.1em\] {
3282
3266
  --tw-tracking: 0.1em;
3283
3267
  letter-spacing: 0.1em;
@@ -3306,10 +3290,6 @@
3306
3290
  --tw-tracking: 0.16em;
3307
3291
  letter-spacing: 0.16em;
3308
3292
  }
3309
- .tracking-\[0\.18em\] {
3310
- --tw-tracking: 0.18em;
3311
- letter-spacing: 0.18em;
3312
- }
3313
3293
  .tracking-\[var\(--tracking-snug\,-0\.01em\)\] {
3314
3294
  --tw-tracking: var(--tracking-snug,-0.01em);
3315
3295
  letter-spacing: var(--tracking-snug,-0.01em);
@@ -3718,6 +3698,10 @@
3718
3698
  --tw-shadow: 0 6px 16px var(--tw-shadow-color, rgba(15,23,42,0.08));
3719
3699
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3720
3700
  }
3701
+ .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.18\)\] {
3702
+ --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.18));
3703
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3704
+ }
3721
3705
  .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.45\)\] {
3722
3706
  --tw-shadow: 0 8px 30px var(--tw-shadow-color, rgba(0,0,0,0.45));
3723
3707
  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 +3973,14 @@
3989
3973
  border-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
3990
3974
  }
3991
3975
  }
3976
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3977
+ background-color: color-mix(in srgb, hsl(var(--primary)) 20%, transparent);
3978
+ }
3979
+ @supports (color: color-mix(in lab, red, red)) {
3980
+ .group-hover\:bg-primary\/20:is(:where(.group):hover *) {
3981
+ background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
3982
+ }
3983
+ }
3992
3984
  .group-hover\:text-foreground:is(:where(.group):hover *) {
3993
3985
  color: var(--color-foreground);
3994
3986
  }
@@ -4016,6 +4008,12 @@
4016
4008
  opacity: 100%;
4017
4009
  }
4018
4010
  }
4011
+ .group-focus-visible\:bg-primary\/30:is(:where(.group):focus-visible *) {
4012
+ background-color: color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
4013
+ @supports (color: color-mix(in lab, red, red)) {
4014
+ background-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
4015
+ }
4016
+ }
4019
4017
  .peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled ~ *) {
4020
4018
  cursor: not-allowed;
4021
4019
  }
@@ -4348,14 +4346,6 @@
4348
4346
  background-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
4349
4347
  }
4350
4348
  }
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
4349
  .hover\:bg-primary\/90:hover {
4360
4350
  background-color: color-mix(in srgb, hsl(var(--primary)) 90%, transparent);
4361
4351
  }
@@ -4554,12 +4544,6 @@
4554
4544
  .focus-visible\:bg-background:focus-visible {
4555
4545
  background-color: var(--color-background);
4556
4546
  }
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
4547
  .focus-visible\:bg-surface-container:focus-visible {
4564
4548
  background-color: var(--color-surface-container);
4565
4549
  }
@@ -5004,9 +4988,6 @@
5004
4988
  .lg\:p-0 {
5005
4989
  padding: 0px;
5006
4990
  }
5007
- .lg\:p-4 {
5008
- padding: calc(var(--spacing) * 4);
5009
- }
5010
4991
  .lg\:px-8 {
5011
4992
  padding-inline: calc(var(--spacing) * 8);
5012
4993
  }
@@ -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 };