@tangle-network/sandbox-ui 2.0.18 → 2.0.19

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/README.md CHANGED
@@ -530,4 +530,4 @@ Retheming is absolutely supported, but the documentation was thinner than it sho
530
530
 
531
531
  Apache-2.0
532
532
 
533
- The native Runtime viewer is `LiveRun` from `@tangle-network/sandbox-ui/run/live`. It composes the same trace workspace, selected-agent conversation, retained files and capture coverage. Hosts may supply the existing fetch/EventSource transport for their authenticated session; an API change resets the selected run, while frames on one API preserve selection and the camera. `@tangle-network/sandbox-ui/workspace-viewer.js` is the self-contained browser entry for Runtime's existing asset-directory contract, with `styles.css` beside it. Generic same-origin ETag document reads are shared as `useDocument` from the hooks entry; producers retain their format validation and accounting.
533
+ The native Runtime viewer is `LiveRun` from `@tangle-network/sandbox-ui/run/live`. It composes the same trace workspace, selected-agent conversation, retained files and capture coverage. Hosts may supply the existing fetch/EventSource transport for their authenticated session; an API or authenticated transport change clears the previous view, while frames within one stable transport preserve selection and the camera. Keep the transport object stable for that account. `@tangle-network/sandbox-ui/workspace-viewer.js` is the self-contained browser entry for Runtime's existing asset-directory contract, with `styles.css` beside it. Generic same-origin ETag document reads are shared as `useDocument` from `/hooks/use-document` without unrelated optional peers; producers retain their format validation and accounting.
@@ -0,0 +1,2 @@
1
+ import { t as useDocument } from "../use-document-DCXGpk0q.js";
2
+ export { useDocument };
@@ -13,21 +13,27 @@ const NETWORK_RETRIES = 4;
13
13
  function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch) {
14
14
  const [state, setState] = useState({
15
15
  url,
16
+ fetcher,
16
17
  loading: !!url
17
18
  });
18
19
  const etag = useRef(null);
19
20
  const shown = useRef(void 0);
20
21
  useEffect(() => {
21
- if (shown.current !== url) {
22
- shown.current = url;
22
+ const sameAccount = shown.current?.fetcher === fetcher;
23
+ if (shown.current?.url !== url || !sameAccount) {
24
+ shown.current = {
25
+ url,
26
+ fetcher
27
+ };
23
28
  etag.current = null;
24
- setState((current) => keepPrevious && url && current.data !== void 0 ? {
29
+ setState((current) => sameAccount && keepPrevious && url && current.data !== void 0 ? {
25
30
  ...current,
26
31
  url,
27
32
  loading: true,
28
33
  error: void 0
29
34
  } : {
30
35
  url,
36
+ fetcher,
31
37
  loading: !!url
32
38
  });
33
39
  }
@@ -44,6 +50,7 @@ function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch
44
50
  try {
45
51
  const response = await fetcher(url, {
46
52
  credentials: "same-origin",
53
+ cache: "no-store",
47
54
  signal: controller.signal,
48
55
  headers: etag.current ? { "If-None-Match": etag.current } : {}
49
56
  });
@@ -53,8 +60,11 @@ function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch
53
60
  const failing = response.headers.get("X-Workspace-Compose-Error") ?? void 0;
54
61
  if (!stale && (response.ok || response.status === 304)) retries = 0;
55
62
  if (response.status === 304) {
56
- setState((current) => current.stale === stale && current.failing === failing ? current : {
63
+ setState((current) => !current.error && current.stale === stale && current.failing === failing ? current : {
57
64
  ...current,
65
+ loading: false,
66
+ error: void 0,
67
+ status: 304,
58
68
  stale,
59
69
  failing
60
70
  });
@@ -66,8 +76,18 @@ function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch
66
76
  const body = await response.json();
67
77
  if (body && typeof body === "object" && typeof body.reason === "string") reason = body.reason;
68
78
  } catch {}
79
+ if (!alive) return;
80
+ const refused = [
81
+ 401,
82
+ 403,
83
+ 404
84
+ ].includes(response.status);
85
+ if (refused) etag.current = null;
69
86
  setState((current) => ({
70
- ...current,
87
+ ...refused ? {
88
+ url,
89
+ fetcher
90
+ } : current,
71
91
  loading: false,
72
92
  error: reason,
73
93
  status: response.status
@@ -78,6 +98,7 @@ function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch
78
98
  const data = await response.json();
79
99
  if (alive) setState({
80
100
  url,
101
+ fetcher,
81
102
  data,
82
103
  loading: false,
83
104
  status: response.status,
@@ -112,9 +133,10 @@ function useDocument(url, poll, keepPrevious = false, fetcher = globalThis.fetch
112
133
  poll,
113
134
  fetcher
114
135
  ]);
115
- return keepPrevious || state.url === url ? state : {
136
+ return state.fetcher === fetcher && (keepPrevious || state.url === url) ? state : {
116
137
  url,
138
+ fetcher,
117
139
  loading: !!url
118
140
  };
119
141
  }
120
- export { useDocument as t };
142
+ export { useDocument };
package/dist/hooks.d.ts CHANGED
@@ -1,4 +1,142 @@
1
1
  import { n as UsePtySessionReturn, r as usePtySession, t as UsePtySessionOptions } from "./use-pty-session-DSgtQyYX.js";
2
- import { $ as UseSandboxMetricsResult, A as useApiKey, B as useToolCallStream, C as UseRunGroupsOptions, D as UseSdkSessionReturn, E as UseSdkSessionOptions, F as useRealtimeSession, G as useSessions, H as useCreateSession, I as useRunCollapseState, J as SandboxMetrics, K as LatencyPercentiles, L as useRunGroups, M as useAutoScroll, N as useDropdownMenu, O as UseToolCallStreamReturn, P as useLiveTime, Q as UseSandboxMetricsOptions, R as useSSEStream, S as UseAuthResult, T as UseSSEStreamResult, U as useDeleteSession, V as useDocument, W as useRenameSession, X as SidecarMetricsPayload, Y as SandboxMetricsSample, Z as SystemMetricsSnapshot, _ as SdkSessionEvent, a as AutomationStreamEvent, b as TerminalStreamEvent, c as CompleteAssistantMessageOptions, d as RealtimeSessionRegistry, et as useSandboxMetrics, f as RealtimeSessionRegistryProps, g as SdkSessionAttachment, h as SSEEvent, i as AuthUser, j as useAuth, k as createAuthFetcher, l as ConnectionState, m as RealtimeSessionTarget, n as AppendUserMessageOptions, o as BeginAssistantMessageOptions, p as RealtimeSessionState, q as SandboxLatencyMetrics, r as ApplySdkEventOptions, s as BotStreamEvent, t as AgentStreamEvent, u as RealtimeSessionOptions, v as SdkSessionSeed, w as UseSSEStreamOptions, x as UseAuthOptions, y as TaskStreamEvent, z as useSdkSession } from "./index-D5Hig-j9.js";
2
+ import { t as Session } from "./sidecar-CNP4zXop.js";
3
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-CPevSSEj.js";
4
- export { type AgentStreamEvent, type AppendUserMessageOptions, type ApplySdkEventOptions, type AuthUser, type AutomationStreamEvent, type BeginAssistantMessageOptions, type BotStreamEvent, type CompleteAssistantMessageOptions, type ConnectionState, LatencyPercentiles, type RealtimeSessionOptions, RealtimeSessionRegistry, type RealtimeSessionRegistryProps, type RealtimeSessionState, type RealtimeSessionTarget, SESSION_STREAM_RECONNECT_DELAY_MS, type SSEEvent, SandboxLatencyMetrics, SandboxMetrics, SandboxMetricsSample, type SdkSessionAttachment, type SdkSessionEvent, type SdkSessionSeed, SendMessageOptions, SessionDegradation, SessionInfo, SessionStreamError, SidecarAuth, SidecarMetricsPayload, SystemMetricsSnapshot, type TaskStreamEvent, type TerminalStreamEvent, type UseAuthOptions, type UseAuthResult, UsePtySessionOptions, UsePtySessionReturn, type UseRunGroupsOptions, type UseSSEStreamOptions, type UseSSEStreamResult, UseSandboxMetricsOptions, UseSandboxMetricsResult, type UseSdkSessionOptions, type UseSdkSessionReturn, UseSessionStreamOptions, UseSessionStreamResult, UseSidecarAuthOptions, type UseToolCallStreamReturn, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useCreateSession, useDeleteSession, useDocument, useDropdownMenu, useLiveTime, usePtySession, useRealtimeSession, useRenameSession, useRunCollapseState, useRunGroups, useSSEStream, useSandboxMetrics, useSdkSession, useSessionStream, useSessions, useSidecarAuth, useToolCallStream };
4
+ import { t as useDocument } from "./use-document-DCXGpk0q.js";
5
+ 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";
6
+ /**
7
+ * Sandbox-level telemetry collected by the sidecar from cgroup v2
8
+ * (Docker) or /proc (Firecracker guest). `cpuPercent` is computed
9
+ * server-side from consecutive samples; sections are null when the
10
+ * source cannot provide them.
11
+ */
12
+ export interface SystemMetricsSnapshot {
13
+ cpuPercent: number | null;
14
+ cpuCores: number;
15
+ memory: {
16
+ usedBytes: number;
17
+ totalBytes: number;
18
+ } | null;
19
+ disk: {
20
+ usedBytes: number;
21
+ totalBytes: number;
22
+ path: string;
23
+ } | null;
24
+ source: "cgroup-v2" | "proc";
25
+ }
26
+ export interface LatencyPercentiles {
27
+ p50: number | null;
28
+ p95: number | null;
29
+ sampleCount: number;
30
+ }
31
+ export interface SandboxLatencyMetrics {
32
+ ttftMs: LatencyPercentiles;
33
+ firstResponseMs: LatencyPercentiles;
34
+ runDurationMs: LatencyPercentiles;
35
+ }
36
+ /**
37
+ * Shape returned by the sidecar `/metrics/json` endpoint. Only the
38
+ * fields read by this hook are modeled; the sidecar may add more.
39
+ */
40
+ export interface SidecarMetricsPayload {
41
+ process?: {
42
+ memoryBytes?: {
43
+ rss?: number;
44
+ heapTotal?: number;
45
+ heapUsed?: number;
46
+ external?: number;
47
+ arrayBuffers?: number;
48
+ };
49
+ cpuSeconds?: {
50
+ user?: number;
51
+ system?: number;
52
+ };
53
+ };
54
+ system?: SystemMetricsSnapshot | null;
55
+ latency?: SandboxLatencyMetrics;
56
+ }
57
+ /**
58
+ * One polled time-series point, sourced from the sandbox-level
59
+ * `system` section. Null values mean the sidecar could not provide
60
+ * that reading — charts must render a gap, not a zero.
61
+ */
62
+ export interface SandboxMetricsSample {
63
+ /** Wall-clock ms when the sample was committed client-side. */
64
+ at: number;
65
+ cpuPercent: number | null;
66
+ memoryUsedBytes: number | null;
67
+ memoryTotalBytes: number | null;
68
+ diskUsedBytes: number | null;
69
+ diskTotalBytes: number | null;
70
+ }
71
+ export interface SandboxMetrics {
72
+ /**
73
+ * CPU% derived from consecutive samples. `null` on the first sample
74
+ * because a delta is required. Can exceed 100 on multi-core hosts.
75
+ */
76
+ cpuPercent: number | null;
77
+ rssBytes: number;
78
+ heapUsedBytes: number;
79
+ heapTotalBytes: number;
80
+ }
81
+ export interface UseSandboxMetricsOptions {
82
+ /**
83
+ * Sandbox API base URL, e.g. `https://api.tangle.tools`.
84
+ * Use an empty string for same-origin requests.
85
+ */
86
+ apiBaseUrl: string;
87
+ /** Sandbox id; when falsy the hook stays idle. */
88
+ sandboxId?: string | null;
89
+ /**
90
+ * Optional bearer token. When omitted the fetch still sends
91
+ * credentials so a cookie session can authenticate the proxy.
92
+ */
93
+ token?: string | null;
94
+ /** Pause polling when false. Defaults to true. */
95
+ enabled?: boolean;
96
+ /** Poll cadence; clamped to a 500ms floor. Defaults to 3000. */
97
+ intervalMs?: number;
98
+ /** Max retained history samples for charting. Defaults to 120. */
99
+ historyLimit?: number;
100
+ }
101
+ export interface UseSandboxMetricsResult {
102
+ metrics: SandboxMetrics | null;
103
+ /**
104
+ * Sandbox-level (container/VM) telemetry. Null until the sidecar
105
+ * reports a `system` section — older sidecars never will, and
106
+ * consumers must surface that as "unavailable", not zeros.
107
+ */
108
+ system: SystemMetricsSnapshot | null;
109
+ /** Agent latency percentiles (TTFT, first response, run duration). */
110
+ latency: SandboxLatencyMetrics | null;
111
+ /**
112
+ * Rolling window of system samples (oldest first), capped at
113
+ * `historyLimit`. Cleared when the target sandbox changes.
114
+ */
115
+ history: SandboxMetricsSample[];
116
+ /**
117
+ * True while waiting for the first successful metrics response for this
118
+ * sandbox. Errors clear it so consumers can show the failure state.
119
+ */
120
+ loading: boolean;
121
+ error: Error | null;
122
+ /** Wall-clock ms of the last successful metrics response, or null. */
123
+ lastUpdatedAt: number | null;
124
+ }
125
+ /**
126
+ * Polls the sandbox's sidecar metrics through the API proxy and
127
+ * derives a CPU% value from consecutive cumulative-CPU samples. Used
128
+ * by the sandbox overview dashboard to drive live CPU/memory panels.
129
+ */
130
+ export declare function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled, intervalMs, historyLimit }: UseSandboxMetricsOptions): UseSandboxMetricsResult;
131
+ /** List all sessions for a sidecar. */
132
+ export declare function useSessions(apiUrl: string, token: string | null): import("@tanstack/react-query").UseQueryResult<Session[], Error>;
133
+ /** Create a new session. */
134
+ export declare function useCreateSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<Session, Error, string, unknown>;
135
+ /** Delete a session by ID. */
136
+ export declare function useDeleteSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<unknown, Error, string, unknown>;
137
+ /** Rename a session. */
138
+ export declare function useRenameSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<Session, Error, {
139
+ sessionId: string;
140
+ title: string;
141
+ }, unknown>;
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, useDocument, useDropdownMenu, useLiveTime, usePtySession, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionStream, useSidecarAuth, useToolCallStream };
package/dist/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as usePtySession } from "./use-pty-session-BHVQlSs-.js";
2
2
  import { i as useSessionStream, n as SESSION_STREAM_RECONNECT_DELAY_MS, r as SessionStreamError, t as useSidecarAuth } from "./use-sidecar-auth-D9BrWCg1.js";
3
- import { t as useDocument } from "./use-document-D6Z9oFLm.js";
3
+ import { useDocument } from "./hooks/use-document.js";
4
4
  import * as React$1 from "react";
5
5
  import { RealtimeSessionRegistry, createAuthFetcher, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useLiveTime, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream } from "@tangle-network/ui/hooks";
6
6
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
package/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@ import { a as canonicalModelId, i as ProviderMark, n as ModelBrandStack, o as mo
6
6
  import { a as PricingPageProps, c as BillingBalance, d as BillingSubscription, f as BillingUsage, i as PricingPage, l as BillingDashboard, n as UsageChartProps, o as PricingTier, r as UsageDataPoint, s as formatPrice, t as UsageChart, u as BillingDashboardProps } from "./usage-chart-BFpdkqNq.js";
7
7
  import { A as configurePdfViewer, C as PdfViewerConfig, D as RichFileTreeGitStatus, E as RichFileTreeGitEntry, F as getFormatLabel, I as getSyntaxLanguage, L as parseCsv, M as fileExtension, N as filterFileTree, O as RichFileTreeProps, P as getCodeLanguage, R as resolveFilePreviewKind, S as PdfViewer, T as RichFileTree, _ as FileTabsProps, a as FileCardProps, b as FileTreeVisibilityOptions, c as FileList, d as FileNode, f as FilePreview, g as FileTabs, h as FileTabData, i as FileCard, j as detectFileFormat, k as RichFileTreeThemeVars, l as FileListItem, m as FilePreviewProps, n as FileArtifactPane, o as FileDetails, p as FilePreviewKind, r as FileArtifactPaneProps, s as FileFormat, t as CSV_PREVIEW_ROW_LIMIT, u as FileListProps, v as FileTree, w as PdfViewerProps, x as FileUploader, y as FileTreeProps } from "./index-BZJKLu3k.js";
8
8
  import { n as UsePtySessionReturn, r as usePtySession, t as UsePtySessionOptions } from "./use-pty-session-DSgtQyYX.js";
9
- import { $ as UseSandboxMetricsResult, A as useApiKey, B as useToolCallStream, C as UseRunGroupsOptions, D as UseSdkSessionReturn, E as UseSdkSessionOptions, F as useRealtimeSession, G as useSessions, H as useCreateSession, I as useRunCollapseState, J as SandboxMetrics, L as useRunGroups, M as useAutoScroll, N as useDropdownMenu, O as UseToolCallStreamReturn, P as useLiveTime, Q as UseSandboxMetricsOptions, R as useSSEStream, S as UseAuthResult, T as UseSSEStreamResult, U as useDeleteSession, W as useRenameSession, X as SidecarMetricsPayload, _ as SdkSessionEvent, a as AutomationStreamEvent, b as TerminalStreamEvent, c as CompleteAssistantMessageOptions, d as RealtimeSessionRegistry, et as useSandboxMetrics, f as RealtimeSessionRegistryProps, g as SdkSessionAttachment, h as SSEEvent, i as AuthUser, j as useAuth, k as createAuthFetcher, m as RealtimeSessionTarget, n as AppendUserMessageOptions, o as BeginAssistantMessageOptions, p as RealtimeSessionState, r as ApplySdkEventOptions, s as BotStreamEvent, t as AgentStreamEvent, u as RealtimeSessionOptions, v as SdkSessionSeed, w as UseSSEStreamOptions, x as UseAuthOptions, y as TaskStreamEvent, z as useSdkSession } from "./index-D5Hig-j9.js";
10
9
  import { t as Session } from "./sidecar-CNP4zXop.js";
11
10
  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-CPevSSEj.js";
11
+ 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";
12
12
  import { $ as CollapsibleContent, $i as Logo, $n as Separator, $r as TabsContent, $t as FieldProps, A as BreadcrumbPage, Ai as WizardProps, An as PaginationProps, Ar as SidebarDropZone, At as DialogPortal, B as CardDescription, Bi as parseCalendarDate, Bn as SegmentedControl, Br as StatusTone, Bt as DropdownMenuLabel, C as Badge, Ci as TooltipContent, Cn as MetricStrip, Cr as SheetDescription, Ct as Dialog, D as BreadcrumbItem, Di as UploadProgress, Dn as PageShell, Dr as SheetPortal, Dt as DialogFooter, E as BreadcrumbEllipsis, Ei as UploadFile, En as PageHeaderProps, Er as SheetOverlay, Et as DialogDescription, F as Calendar, Fi as fieldMessageId, Fn as PopoverContent, Fr as Slider, Ft as DropdownMenu, G as CategoryTone, Gi as seriesMean, Gn as SelectGroup, Gr as TableCaption, Gt as DropdownMenuShortcut, H as CardHeader, Hi as seriesAreaPath, Hn as SegmentedControlProps, Hr as TONE_CLASSES, Ht as DropdownMenuRadioGroup, I as CalendarDate, Ii as formatCalendarDate, In as PopoverTrigger, Ir as StatCard, It as DropdownMenuCheckboxItem, J as Chip, Ji as useTheme, Jn as SelectScrollDownButton, Jr as TableHead, Jt as DropdownMenuSubTrigger, K as ChartReferenceLine, Ki as seriesScale, Kn as SelectItem, Kr as TableCell, Kt as DropdownMenuSub, L as CalendarProps, Li as initialsOf, Ln as Progress, Lr as StatCardProps, Lt as DropdownMenuContent, M as Button, Mi as WizardStepProps, Mn as Popover, Mr as Skeleton, Mt as DialogTrigger, N as ButtonProps, Ni as badgeVariants, Nn as PopoverAnchor, Nr as SkeletonCard, Nt as DropZone, O as BreadcrumbLink, Oi as UploadProgressProps, On as PageShellProps, Or as SheetTitle, Ot as DialogHeader, P as CATEGORY_TONES, Pi as buttonVariants, Pn as PopoverClose, Pr as SkeletonTable, Pt as DropZoneProps, Q as Collapsible, Qi as SectionTitleProps, Qn as SelectValue, Qr as Tabs, Qt as Field, R as Card, Ri as localToday, Rn as RadioGroup, Rr as StatusPill, Rt as DropdownMenuGroup, S as AvatarProps, Si as Tooltip, Sn as MetricProps, Sr as SheetContent, St as DatePickerProps, T as Breadcrumb, Ti as TooltipTrigger, Tn as PageHeader, Tr as SheetHeader, Tt as DialogContent, U as CardTitle, Ui as seriesExtent, Un as Select, Ur as Table, Ut as DropdownMenuRadioItem, V as CardFooter, Vi as periodDelta, Vn as SegmentedControlOption, Vr as Switch, Vt as DropdownMenuPortal, W as CardTitleProps, Wi as seriesLinePath, Wn as SelectContent, Wr as TableBody, Wt as DropdownMenuSeparator, X as CodeBlock, Xi as HeadingProps, Xn as SelectSeparator, Xr as TableProps, Xt as EmptyState, Y as ChipProps, Yi as useToast, Yn as SelectScrollUpButton, Yr as TableHeader, Yt as DropdownMenuTrigger, Z as CodeBlockProps, Zi as SectionTitle, Zn as SelectTrigger, Zr as TableRow, Zt as EmptyStateProps, _ as ArtifactPane, _i as ToastProvider, _n as InputProps, _r as SettingsRowProps, _t as ContextMenuSubContent, a as AlertDialogCancel, ai as TerminalDisplay, an as HelpTextProps, ar as SeriesSparklineProps, at as ContextMenu, b as AvatarFallback, bi as Toolbar, bn as MetricChart, br as Sheet, bt as CopyButton, c as AlertDialogFooter, ci as TextShimmer, cn as HoverCardDescription, cr as SettingsListColumns, ct as ContextMenuGroup, d as AlertDialogPortal, di as TextareaProps, dn as HoverCardTrigger, dr as SettingsListMenuItem, dt as ContextMenuPortal, ea as LogoProps, ei as TabsList, en as FilterField, er as SeriesExtent, et as CollapsibleTrigger, f as AlertDialogTitle, fi as ThemeToggle, fn as IconTile, fr as SettingsListProps, ft as ContextMenuRadioGroup, g as AlertTone, gi as ToastContainer, gn as Input, gr as SettingsRowLayout, gt as ContextMenuSub, h as AlertTitle, hi as Toast, hn as InlineCodeProps, hr as SettingsRow, ht as ContextMenuShortcut, i as AlertDialogAction, ii as TerminalCursor, in as HelpText, ir as SeriesSparkline, it as ComplianceStatus, j as BreadcrumbSeparator, ji as WizardStep, jn as PeriodDelta, jr as SidebarDropZoneProps, jt as DialogTitle, k as BreadcrumbList, ki as Wizard, kn as Pagination, kr as SheetTrigger, kt as DialogOverlay, l as AlertDialogHeader, li as TextShimmerProps, ln as HoverCardHeader, lr as SettingsListItem, lt as ContextMenuItem, m as AlertProps, mi as TimeSelectProps, mn as InlineCode, mr as SettingsNoteProps, mt as ContextMenuSeparator, n as AlertDescription, ni as Tag, nn as Heading, nr as SeriesPointInput, nt as ComplianceBadgeProps, o as AlertDialogContent, oi as TerminalInput, on as HoverCard, or as SettingsList, ot as ContextMenuCheckboxItem, p as AlertDialogTrigger, pi as TimeSelect, pn as IconTileProps, pr as SettingsNote, pt as ContextMenuRadioItem, q as Checkbox, qi as toneFor, qn as SelectLabel, qr as TableFooter, qt as DropdownMenuSubContent, r as AlertDialog, ri as TagProps, rn as HeadingVariant, rr as SeriesScale, rt as ComplianceProduct, s as AlertDialogDescription, sn as HoverCardContent, sr as SettingsListAction, st as ContextMenuContent, t as Alert, ta as TangleKnot, ti as TabsTrigger, tn as FilterFieldProps, tr as SeriesPoint, tt as ComplianceBadge, u as AlertDialogOverlay, ui as Textarea, un as HoverCardTitle, ur as SettingsListItemProps, ut as ContextMenuLabel, v as ArtifactPaneProps, vi as Tone, vn as Label, vr as SettingsSection, vt as ContextMenuSubTrigger, w as BadgeProps, wi as TooltipProvider, wn as MetricStripProps, wr as SheetFooter, wt as DialogClose, x as AvatarImage, xi as ToolbarProps, xn as MetricChartProps, xr as SheetClose, xt as DatePicker, y as Avatar, yi as ToneClasses, yn as Metric, yr as SettingsSectionProps, yt as ContextMenuTrigger, z as CardContent, zi as normalizeSeries, zn as RadioGroupItem, zr as StatusPillProps, zt as DropdownMenuItem } from "./index-CEtc2U5v.js";
13
13
  import { $ as StatusBar, A as createShellShouldRevalidate, B as SessionSidebarVariant, C as SandboxWorkbenchLayoutOptions, D as SandboxWorkbenchSessionProps, E as SandboxWorkbenchProps, F as SessionSidebarFilter, G as dispatchSessionCreated, H as SessionCreatedDetail, I as SessionSidebarGroupBy, J as RuntimePaneProps, K as useOptimisticSessionItems, L as SessionSidebarItem, M as formatRelativeAge, N as SessionSidebar, O as ShellShouldRevalidateArgs, P as SessionSidebarBadge, Q as ContextBadge, R as SessionSidebarLink, S as SandboxWorkbenchFileArtifact, T as SandboxWorkbenchOpenUIArtifact, U as SessionOptimisticController, V as SESSION_CREATED_EVENT, W as UseOptimisticSessionItemsOptions, X as TerminalPanel, Y as TerminalLine, Z as TerminalProps, _ as TaskBoardItem, _t as WorkspaceSurfaceTitle, a as WorkspaceFilesPane, at as DirectoryPaneProps, b as SandboxWorkbenchArtifact, bt as WorkspaceLayoutProps, c as ApprovalConfidenceStat, ct as ShellHeader, d as ApprovalQueueProps, dt as WorkspacePaneHeaderProps, et as StatusBarProps, f as CalendarEvent, ft as WorkspaceSurface, g as TaskBoardColumn, gt as WorkspaceSurfaceProps, h as TaskBoard, ht as WorkspaceSurfaceHeadingLevel, i as WorkspaceArtifactViewProps, it as DirectoryPane, j as shellShouldRevalidate, k as ShellShouldRevalidateOptions, l as ApprovalItem, lt as ShellHeaderProps, m as CalendarViewProps, mt as WorkspaceSurfaceFrameProps, nt as StatusBanner, o as WorkspaceFilesPaneProps, ot as SHELL_HEADER_HEIGHT, p as CalendarView, pt as WorkspaceSurfaceFrame, q as RuntimePane, r as WorkspaceArtifactView, rt as StatusBannerProps, s as WorkspaceFilesPreview, st as SHELL_INSET_GUTTER, tt as BannerType, u as ApprovalQueue, ut as WorkspacePaneHeader, v as TaskBoardProps, vt as WorkspaceSurfaceTitleProps, w as SandboxWorkbenchMarkdownArtifact, x as SandboxWorkbenchCustomArtifact, y as SandboxWorkbench, yt as WorkspaceLayout, z as SessionSidebarProps } from "./index-D2_4ONCz.js";
14
14
  import { i as VaultTreeProps, n as VAULT_TREE_CHILD_PAGE, r as VaultTree, t as FileChange } from "./vault-tree-CBS8qGT-.js";
@@ -1,4 +1,5 @@
1
1
  import { t as AgentStreamOpener } from "../agent-stream-CBZ2fXJ2.js";
2
+ /** Keep one transport identity per authenticated account; changing it discards the previous view. */
2
3
  export interface LiveRunTransport {
3
4
  fetch?: typeof globalThis.fetch;
4
5
  openEventSource?: AgentStreamOpener;
package/dist/run/live.js CHANGED
@@ -2,9 +2,9 @@ import { t as WorkspaceFilesPane } from "../workspace-files-pane-DB9Nvwh4.js";
2
2
  import { t as DiffView } from "../diff-view-B9mNeTLF.js";
3
3
  import { t as CodeView } from "../code-view-BlhCS1SD.js";
4
4
  import { t as TraceWorkspace } from "../trace-workspace-C8dHRBDV.js";
5
- import { t as useDocument } from "../use-document-D6Z9oFLm.js";
5
+ import { useDocument } from "../hooks/use-document.js";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
- import { useEffect, useMemo, useState } from "react";
7
+ import { useEffect, useMemo, useRef, useState } from "react";
8
8
  import { runStatus } from "@tangle-network/ui/run";
9
9
  // src/run/live-inspection.tsx
10
10
  /** The graph, conversation and files share one selected agent and one product-owned API. */
@@ -12,12 +12,12 @@ function useLiveInspection(url, live, fetcher) {
12
12
  const inventory = useDocument(url ?? null, live ? 3e3 : void 0, false, fetcher);
13
13
  const [selected, select] = useState();
14
14
  const [download, setDownload] = useState();
15
- const files = inventory.data?.files?.entries ?? [];
15
+ const files = inventory.error ? [] : inventory.data?.files?.entries ?? [];
16
16
  const entry = files.find((file) => file.path === selected) ?? files[0];
17
17
  const fileUrl = entry && url ? `${url}/file?path=${encodeURIComponent(entry.path)}` : null;
18
18
  const content = useDocument(fileUrl, live ? 3e3 : void 0, false, fetcher);
19
19
  const file = content.data?.file;
20
- const valid = file && entry && file.path === entry.path && file.sha256 === entry.sha256 && file.byteLength === entry.byteLength;
20
+ const valid = !inventory.error && !content.error && file && entry && file.path === entry.path && file.sha256 === entry.sha256 && file.byteLength === entry.byteLength;
21
21
  const fileKey = valid ? `${entry.path}:${entry.sha256}` : void 0;
22
22
  useEffect(() => {
23
23
  if (!fileKey || !file) return;
@@ -29,7 +29,11 @@ function useLiveInspection(url, live, fetcher) {
29
29
  return () => URL.revokeObjectURL(href);
30
30
  }, [fileKey, file?.content]);
31
31
  const coverage = inventory.data?.coverage;
32
- const scoreboard = inventory.status === 404 ? void 0 : coverage ? /* @__PURE__ */ jsxs("details", {
32
+ const scoreboard = inventory.error ? /* @__PURE__ */ jsxs("p", {
33
+ className: "ws-status",
34
+ role: "alert",
35
+ children: ["Conversation inspection unavailable: ", inventory.error]
36
+ }) : coverage ? /* @__PURE__ */ jsxs("details", {
33
37
  className: "ws-status",
34
38
  open: coverage.status !== "complete",
35
39
  "data-capture-status": coverage.status,
@@ -42,10 +46,6 @@ function useLiveInspection(url, live, fetcher) {
42
46
  }, `${row.at}:${index}`))] }),
43
47
  inventory.data?.files?.scope === "none" && /* @__PURE__ */ jsx("p", { children: inventory.data.files.reason ?? "No workspace inventory was captured." })
44
48
  ]
45
- }) : inventory.error ? /* @__PURE__ */ jsxs("p", {
46
- className: "ws-status",
47
- role: "alert",
48
- children: ["Conversation inspection unavailable: ", inventory.error]
49
49
  }) : void 0;
50
50
  return {
51
51
  scoreboard: /* @__PURE__ */ jsxs(Fragment, { children: [scoreboard, inventory.data?.files && !inventory.data.files.complete && /* @__PURE__ */ jsxs("p", {
@@ -88,14 +88,23 @@ function useLiveInspection(url, live, fetcher) {
88
88
  className: "ws-status",
89
89
  children: [
90
90
  /* @__PURE__ */ jsx("summary", { children: "Provenance" }),
91
- /* @__PURE__ */ jsx("code", { children: entry.sha256 }),
91
+ /* @__PURE__ */ jsx("code", {
92
+ className: "break-all",
93
+ children: entry.sha256
94
+ }),
92
95
  file.before && /* @__PURE__ */ jsxs("p", { children: [
93
96
  "Compared with ",
94
97
  file.before.source.kind,
95
98
  " ",
96
- /* @__PURE__ */ jsx("code", { children: file.before.source.ref }),
99
+ /* @__PURE__ */ jsx("code", {
100
+ className: "break-all",
101
+ children: file.before.source.ref
102
+ }),
97
103
  ": ",
98
- /* @__PURE__ */ jsx("code", { children: file.before.sha256 })
104
+ /* @__PURE__ */ jsx("code", {
105
+ className: "break-all",
106
+ children: file.before.sha256
107
+ })
99
108
  ] }),
100
109
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("a", {
101
110
  href: download && download.key === fileKey ? download.href : void 0,
@@ -146,7 +155,21 @@ const isOpen = (status) => [
146
155
  ].includes(flowStatus(status));
147
156
  /** Both the Discovery host and agent-runtime-top mount this same stream consumer and shared run workspace. */
148
157
  function LiveRun(props) {
149
- return /* @__PURE__ */ jsx(LiveRunView, { ...props }, props.api);
158
+ const scope = useRef({
159
+ api: props.api,
160
+ transport: props.transport,
161
+ fetcher: props.transport?.fetch,
162
+ opener: props.transport?.openEventSource,
163
+ revision: 0
164
+ });
165
+ if (scope.current.api !== props.api || scope.current.transport !== props.transport || scope.current.fetcher !== props.transport?.fetch || scope.current.opener !== props.transport?.openEventSource) scope.current = {
166
+ api: props.api,
167
+ transport: props.transport,
168
+ fetcher: props.transport?.fetch,
169
+ opener: props.transport?.openEventSource,
170
+ revision: scope.current.revision + 1
171
+ };
172
+ return /* @__PURE__ */ jsx(LiveRunView, { ...props }, scope.current.revision);
150
173
  }
151
174
  function LiveRunView({ api, transport }) {
152
175
  const [snapshots, setSnapshots] = useState([]);
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Same-origin JSON with ETag revalidation. `poll` refetches every `poll` ms while set; turning polling on or off keeps
3
+ * the document. With `keepPrevious`, a new URL (a record's next digest) keeps showing the previous document until the
4
+ * new one arrives, so a run being written never blanks between versions. A response marked stale is refetched until it is current.
5
+ */
6
+ declare function useDocument<T>(url: string | null, poll?: number, keepPrevious?: boolean, fetcher?: typeof fetch): {
7
+ url: string | null;
8
+ fetcher: typeof fetcher;
9
+ data?: T;
10
+ error?: string;
11
+ status?: number;
12
+ loading: boolean;
13
+ stale?: boolean;
14
+ failing?: string;
15
+ };
16
+ export { useDocument as t };
@@ -43989,91 +43989,112 @@ function SU({ trace: e, streamUrl: t, openEventSource: n, events: r, onTimeChang
43989
43989
  ]
43990
43990
  });
43991
43991
  }
43992
- // dist/use-document-D6Z9oFLm.js
43992
+ // dist/hooks/use-document.js
43993
43993
  var CU = 2500, wU = 6, TU = 4;
43994
43994
  function EU(e, t, n = !1, r = globalThis.fetch) {
43995
43995
  let [i, a] = (0, G.useState)({
43996
43996
  url: e,
43997
+ fetcher: r,
43997
43998
  loading: !!e
43998
43999
  }), o = (0, G.useRef)(null), s = (0, G.useRef)(void 0);
43999
44000
  return (0, G.useEffect)(() => {
44000
- if (s.current !== e && (s.current = e, o.current = null, a((t) => n && e && t.data !== void 0 ? {
44001
+ let i = s.current?.fetcher === r;
44002
+ if (s.current?.url === e && i || (s.current = {
44003
+ url: e,
44004
+ fetcher: r
44005
+ }, o.current = null, a((t) => i && n && e && t.data !== void 0 ? {
44001
44006
  ...t,
44002
44007
  url: e,
44003
44008
  loading: !0,
44004
44009
  error: void 0
44005
44010
  } : {
44006
44011
  url: e,
44012
+ fetcher: r,
44007
44013
  loading: !!e
44008
44014
  })), !e) return;
44009
- let i = !0, c = 0, l = !1, u = 0, d = 0, f = !1, p = new AbortController(), m = async () => {
44010
- f = !1;
44015
+ let c = !0, l = 0, u = !1, d = 0, f = 0, p = !1, m = new AbortController(), h = async () => {
44016
+ p = !1;
44011
44017
  try {
44012
44018
  let t = await r(e, {
44013
44019
  credentials: "same-origin",
44014
- signal: p.signal,
44020
+ cache: "no-store",
44021
+ signal: m.signal,
44015
44022
  headers: o.current ? { "If-None-Match": o.current } : {}
44016
44023
  });
44017
- if (!i) return;
44018
- d = 0, l = t.headers.get("X-Workspace-Stale") === "1";
44024
+ if (!c) return;
44025
+ f = 0, u = t.headers.get("X-Workspace-Stale") === "1";
44019
44026
  let n = t.headers.get("X-Workspace-Compose-Error") ?? void 0;
44020
- if (!l && (t.ok || t.status === 304) && (u = 0), t.status === 304) {
44021
- a((e) => e.stale === l && e.failing === n ? e : {
44027
+ if (!u && (t.ok || t.status === 304) && (d = 0), t.status === 304) {
44028
+ a((e) => !e.error && e.stale === u && e.failing === n ? e : {
44022
44029
  ...e,
44023
- stale: l,
44030
+ loading: !1,
44031
+ error: void 0,
44032
+ status: 304,
44033
+ stale: u,
44024
44034
  failing: n
44025
44035
  });
44026
44036
  return;
44027
44037
  }
44028
44038
  if (!t.ok) {
44029
- let e = `HTTP ${t.status}`;
44039
+ let n = `HTTP ${t.status}`;
44030
44040
  try {
44031
- let n = await t.json();
44032
- n && typeof n == "object" && typeof n.reason == "string" && (e = n.reason);
44041
+ let e = await t.json();
44042
+ e && typeof e == "object" && typeof e.reason == "string" && (n = e.reason);
44033
44043
  } catch {}
44034
- a((n) => ({
44035
- ...n,
44044
+ if (!c) return;
44045
+ let i = [
44046
+ 401,
44047
+ 403,
44048
+ 404
44049
+ ].includes(t.status);
44050
+ i && (o.current = null), a((a) => ({
44051
+ ...i ? {
44052
+ url: e,
44053
+ fetcher: r
44054
+ } : a,
44036
44055
  loading: !1,
44037
- error: e,
44056
+ error: n,
44038
44057
  status: t.status
44039
44058
  }));
44040
44059
  return;
44041
44060
  }
44042
44061
  o.current = t.headers.get("ETag");
44043
- let s = await t.json();
44044
- i && a({
44062
+ let i = await t.json();
44063
+ c && a({
44045
44064
  url: e,
44046
- data: s,
44065
+ fetcher: r,
44066
+ data: i,
44047
44067
  loading: !1,
44048
44068
  status: t.status,
44049
- stale: l,
44069
+ stale: u,
44050
44070
  failing: n
44051
44071
  });
44052
44072
  } catch (e) {
44053
- i && !p.signal.aborted && d < TU ? f = !0 : i && !p.signal.aborted && a((t) => ({
44073
+ c && !m.signal.aborted && f < TU ? p = !0 : c && !m.signal.aborted && a((t) => ({
44054
44074
  ...t,
44055
44075
  loading: !1,
44056
44076
  error: e instanceof Error ? e.message : "Request failed"
44057
44077
  }));
44058
44078
  } finally {
44059
- i && f ? (c = window.setTimeout(m, 1e3 * 2 ** d), d += 1) : i && l && u < wU ? (c = window.setTimeout(m, CU * 1.5 ** u), u += 1) : i && t && (c = window.setTimeout(m, t));
44079
+ c && p ? (l = window.setTimeout(h, 1e3 * 2 ** f), f += 1) : c && u && d < wU ? (l = window.setTimeout(h, CU * 1.5 ** d), d += 1) : c && t && (l = window.setTimeout(h, t));
44060
44080
  }
44061
44081
  };
44062
- return m(), () => {
44063
- i = !1, p.abort(), window.clearTimeout(c);
44082
+ return h(), () => {
44083
+ c = !1, m.abort(), window.clearTimeout(l);
44064
44084
  };
44065
44085
  }, [
44066
44086
  e,
44067
44087
  t,
44068
44088
  r
44069
- ]), n || i.url === e ? i : {
44089
+ ]), i.fetcher === r && (n || i.url === e) ? i : {
44070
44090
  url: e,
44091
+ fetcher: r,
44071
44092
  loading: !!e
44072
44093
  };
44073
44094
  }
44074
44095
  // dist/run/live.js
44075
44096
  function DU(e, t, n) {
44076
- let r = EU(e ?? null, t ? 3e3 : void 0, !1, n), [i, a] = (0, G.useState)(), [o, s] = (0, G.useState)(), c = r.data?.files?.entries ?? [], l = c.find((e) => e.path === i) ?? c[0], u = EU(l && e ? `${e}/file?path=${encodeURIComponent(l.path)}` : null, t ? 3e3 : void 0, !1, n), d = u.data?.file, f = d && l && d.path === l.path && d.sha256 === l.sha256 && d.byteLength === l.byteLength, p = f ? `${l.path}:${l.sha256}` : void 0;
44097
+ let r = EU(e ?? null, t ? 3e3 : void 0, !1, n), [i, a] = (0, G.useState)(), [o, s] = (0, G.useState)(), c = r.error ? [] : r.data?.files?.entries ?? [], l = c.find((e) => e.path === i) ?? c[0], u = EU(l && e ? `${e}/file?path=${encodeURIComponent(l.path)}` : null, t ? 3e3 : void 0, !1, n), d = u.data?.file, f = !r.error && !u.error && d && l && d.path === l.path && d.sha256 === l.sha256 && d.byteLength === l.byteLength, p = f ? `${l.path}:${l.sha256}` : void 0;
44077
44098
  (0, G.useEffect)(() => {
44078
44099
  if (!p || !d) return;
44079
44100
  let e = URL.createObjectURL(new Blob([d.content], { type: "text/plain;charset=utf-8" }));
@@ -44082,7 +44103,11 @@ function DU(e, t, n) {
44082
44103
  href: e
44083
44104
  }), () => URL.revokeObjectURL(e);
44084
44105
  }, [p, d?.content]);
44085
- let m = r.data?.coverage, h = r.status === 404 ? void 0 : m ? /* @__PURE__ */ (0, q.jsxs)("details", {
44106
+ let m = r.data?.coverage, h = r.error ? /* @__PURE__ */ (0, q.jsxs)("p", {
44107
+ className: "ws-status",
44108
+ role: "alert",
44109
+ children: ["Conversation inspection unavailable: ", r.error]
44110
+ }) : m ? /* @__PURE__ */ (0, q.jsxs)("details", {
44086
44111
  className: "ws-status",
44087
44112
  open: m.status !== "complete",
44088
44113
  "data-capture-status": m.status,
@@ -44095,10 +44120,6 @@ function DU(e, t, n) {
44095
44120
  }, `${e.at}:${t}`))] }),
44096
44121
  r.data?.files?.scope === "none" && /* @__PURE__ */ (0, q.jsx)("p", { children: r.data.files.reason ?? "No workspace inventory was captured." })
44097
44122
  ]
44098
- }) : r.error ? /* @__PURE__ */ (0, q.jsxs)("p", {
44099
- className: "ws-status",
44100
- role: "alert",
44101
- children: ["Conversation inspection unavailable: ", r.error]
44102
44123
  }) : void 0;
44103
44124
  return {
44104
44125
  scoreboard: /* @__PURE__ */ (0, q.jsxs)(q.Fragment, { children: [h, r.data?.files && !r.data.files.complete && /* @__PURE__ */ (0, q.jsxs)("p", {
@@ -44141,14 +44162,23 @@ function DU(e, t, n) {
44141
44162
  className: "ws-status",
44142
44163
  children: [
44143
44164
  /* @__PURE__ */ (0, q.jsx)("summary", { children: "Provenance" }),
44144
- /* @__PURE__ */ (0, q.jsx)("code", { children: l.sha256 }),
44165
+ /* @__PURE__ */ (0, q.jsx)("code", {
44166
+ className: "break-all",
44167
+ children: l.sha256
44168
+ }),
44145
44169
  d.before && /* @__PURE__ */ (0, q.jsxs)("p", { children: [
44146
44170
  "Compared with ",
44147
44171
  d.before.source.kind,
44148
44172
  " ",
44149
- /* @__PURE__ */ (0, q.jsx)("code", { children: d.before.source.ref }),
44173
+ /* @__PURE__ */ (0, q.jsx)("code", {
44174
+ className: "break-all",
44175
+ children: d.before.source.ref
44176
+ }),
44150
44177
  ": ",
44151
- /* @__PURE__ */ (0, q.jsx)("code", { children: d.before.sha256 })
44178
+ /* @__PURE__ */ (0, q.jsx)("code", {
44179
+ className: "break-all",
44180
+ children: d.before.sha256
44181
+ })
44152
44182
  ] }),
44153
44183
  /* @__PURE__ */ (0, q.jsx)("p", { children: /* @__PURE__ */ (0, q.jsx)("a", {
44154
44184
  href: o && o.key === p ? o.href : void 0,
@@ -44191,7 +44221,20 @@ var OU = (e) => {
44191
44221
  "needs-you"
44192
44222
  ].includes(MU(e));
44193
44223
  function FU(e) {
44194
- return /* @__PURE__ */ (0, q.jsx)(IU, { ...e }, e.api);
44224
+ let t = (0, G.useRef)({
44225
+ api: e.api,
44226
+ transport: e.transport,
44227
+ fetcher: e.transport?.fetch,
44228
+ opener: e.transport?.openEventSource,
44229
+ revision: 0
44230
+ });
44231
+ return (t.current.api !== e.api || t.current.transport !== e.transport || t.current.fetcher !== e.transport?.fetch || t.current.opener !== e.transport?.openEventSource) && (t.current = {
44232
+ api: e.api,
44233
+ transport: e.transport,
44234
+ fetcher: e.transport?.fetch,
44235
+ opener: e.transport?.openEventSource,
44236
+ revision: t.current.revision + 1
44237
+ }), /* @__PURE__ */ (0, q.jsx)(IU, { ...e }, t.current.revision);
44195
44238
  }
44196
44239
  function IU({ api: e, transport: t }) {
44197
44240
  let [n, r] = (0, G.useState)([]), [i, a] = (0, G.useState)(null), [o, s] = (0, G.useState)(!1), [c, l] = (0, G.useState)(!1), [u, d] = (0, G.useState)(""), [f, p] = (0, G.useState)(0), [m, h] = (0, G.useState)(), [g, _] = (0, G.useState)(!0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "2.0.18",
3
+ "version": "2.0.19",
4
4
  "license": "MIT",
5
5
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
6
6
  "repository": {
@@ -99,6 +99,10 @@
99
99
  "import": "./dist/pages.js",
100
100
  "types": "./dist/pages.d.ts"
101
101
  },
102
+ "./hooks/use-document": {
103
+ "import": "./dist/hooks/use-document.js",
104
+ "types": "./dist/hooks/use-document.d.ts"
105
+ },
102
106
  "./hooks": {
103
107
  "import": "./dist/hooks.js",
104
108
  "types": "./dist/hooks.d.ts"
@@ -1,155 +0,0 @@
1
- import "./use-pty-session-DSgtQyYX.js";
2
- import { t as Session } from "./sidecar-CNP4zXop.js";
3
- import "./use-sidecar-auth-CPevSSEj.js";
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
- /**
6
- * Sandbox-level telemetry collected by the sidecar from cgroup v2
7
- * (Docker) or /proc (Firecracker guest). `cpuPercent` is computed
8
- * server-side from consecutive samples; sections are null when the
9
- * source cannot provide them.
10
- */
11
- interface SystemMetricsSnapshot {
12
- cpuPercent: number | null;
13
- cpuCores: number;
14
- memory: {
15
- usedBytes: number;
16
- totalBytes: number;
17
- } | null;
18
- disk: {
19
- usedBytes: number;
20
- totalBytes: number;
21
- path: string;
22
- } | null;
23
- source: "cgroup-v2" | "proc";
24
- }
25
- interface LatencyPercentiles {
26
- p50: number | null;
27
- p95: number | null;
28
- sampleCount: number;
29
- }
30
- interface SandboxLatencyMetrics {
31
- ttftMs: LatencyPercentiles;
32
- firstResponseMs: LatencyPercentiles;
33
- runDurationMs: LatencyPercentiles;
34
- }
35
- /**
36
- * Shape returned by the sidecar `/metrics/json` endpoint. Only the
37
- * fields read by this hook are modeled; the sidecar may add more.
38
- */
39
- interface SidecarMetricsPayload {
40
- process?: {
41
- memoryBytes?: {
42
- rss?: number;
43
- heapTotal?: number;
44
- heapUsed?: number;
45
- external?: number;
46
- arrayBuffers?: number;
47
- };
48
- cpuSeconds?: {
49
- user?: number;
50
- system?: number;
51
- };
52
- };
53
- system?: SystemMetricsSnapshot | null;
54
- latency?: SandboxLatencyMetrics;
55
- }
56
- /**
57
- * One polled time-series point, sourced from the sandbox-level
58
- * `system` section. Null values mean the sidecar could not provide
59
- * that reading — charts must render a gap, not a zero.
60
- */
61
- interface SandboxMetricsSample {
62
- /** Wall-clock ms when the sample was committed client-side. */
63
- at: number;
64
- cpuPercent: number | null;
65
- memoryUsedBytes: number | null;
66
- memoryTotalBytes: number | null;
67
- diskUsedBytes: number | null;
68
- diskTotalBytes: number | null;
69
- }
70
- interface SandboxMetrics {
71
- /**
72
- * CPU% derived from consecutive samples. `null` on the first sample
73
- * because a delta is required. Can exceed 100 on multi-core hosts.
74
- */
75
- cpuPercent: number | null;
76
- rssBytes: number;
77
- heapUsedBytes: number;
78
- heapTotalBytes: number;
79
- }
80
- interface UseSandboxMetricsOptions {
81
- /**
82
- * Sandbox API base URL, e.g. `https://api.tangle.tools`.
83
- * Use an empty string for same-origin requests.
84
- */
85
- apiBaseUrl: string;
86
- /** Sandbox id; when falsy the hook stays idle. */
87
- sandboxId?: string | null;
88
- /**
89
- * Optional bearer token. When omitted the fetch still sends
90
- * credentials so a cookie session can authenticate the proxy.
91
- */
92
- token?: string | null;
93
- /** Pause polling when false. Defaults to true. */
94
- enabled?: boolean;
95
- /** Poll cadence; clamped to a 500ms floor. Defaults to 3000. */
96
- intervalMs?: number;
97
- /** Max retained history samples for charting. Defaults to 120. */
98
- historyLimit?: number;
99
- }
100
- interface UseSandboxMetricsResult {
101
- metrics: SandboxMetrics | null;
102
- /**
103
- * Sandbox-level (container/VM) telemetry. Null until the sidecar
104
- * reports a `system` section — older sidecars never will, and
105
- * consumers must surface that as "unavailable", not zeros.
106
- */
107
- system: SystemMetricsSnapshot | null;
108
- /** Agent latency percentiles (TTFT, first response, run duration). */
109
- latency: SandboxLatencyMetrics | null;
110
- /**
111
- * Rolling window of system samples (oldest first), capped at
112
- * `historyLimit`. Cleared when the target sandbox changes.
113
- */
114
- history: SandboxMetricsSample[];
115
- /**
116
- * True while waiting for the first successful metrics response for this
117
- * sandbox. Errors clear it so consumers can show the failure state.
118
- */
119
- loading: boolean;
120
- error: Error | null;
121
- /** Wall-clock ms of the last successful metrics response, or null. */
122
- lastUpdatedAt: number | null;
123
- }
124
- /**
125
- * Polls the sandbox's sidecar metrics through the API proxy and
126
- * derives a CPU% value from consecutive cumulative-CPU samples. Used
127
- * by the sandbox overview dashboard to drive live CPU/memory panels.
128
- */
129
- declare function useSandboxMetrics({ apiBaseUrl, sandboxId, token, enabled, intervalMs, historyLimit }: UseSandboxMetricsOptions): UseSandboxMetricsResult;
130
- /** List all sessions for a sidecar. */
131
- declare function useSessions(apiUrl: string, token: string | null): import("@tanstack/react-query").UseQueryResult<Session[], Error>;
132
- /** Create a new session. */
133
- declare function useCreateSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<Session, Error, string, unknown>;
134
- /** Delete a session by ID. */
135
- declare function useDeleteSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<unknown, Error, string, unknown>;
136
- /** Rename a session. */
137
- declare function useRenameSession(apiUrl: string, token: string | null): import("@tanstack/react-query").UseMutationResult<Session, Error, {
138
- sessionId: string;
139
- title: string;
140
- }, unknown>;
141
- /**
142
- * Same-origin JSON with ETag revalidation. `poll` refetches every `poll` ms while set; turning polling on or off keeps
143
- * the document. With `keepPrevious`, a new URL (a record's next digest) keeps showing the previous document until the
144
- * new one arrives, so a run being written never blanks between versions. A response marked stale is refetched until it is current.
145
- */
146
- declare function useDocument<T>(url: string | null, poll?: number, keepPrevious?: boolean, fetcher?: typeof fetch): {
147
- url: string | null;
148
- data?: T;
149
- error?: string;
150
- status?: number;
151
- loading: boolean;
152
- stale?: boolean;
153
- failing?: string;
154
- };
155
- export { UseSandboxMetricsResult as $, useApiKey as A, useToolCallStream as B, UseRunGroupsOptions as C, UseSdkSessionReturn as D, UseSdkSessionOptions as E, useRealtimeSession as F, useSessions as G, useCreateSession as H, useRunCollapseState as I, SandboxMetrics as J, LatencyPercentiles as K, useRunGroups as L, useAutoScroll as M, useDropdownMenu as N, UseToolCallStreamReturn as O, useLiveTime as P, UseSandboxMetricsOptions as Q, useSSEStream as R, UseAuthResult as S, UseSSEStreamResult as T, useDeleteSession as U, useDocument as V, useRenameSession as W, SidecarMetricsPayload as X, SandboxMetricsSample as Y, SystemMetricsSnapshot as Z, SdkSessionEvent as _, AutomationStreamEvent as a, TerminalStreamEvent as b, CompleteAssistantMessageOptions as c, RealtimeSessionRegistry as d, useSandboxMetrics as et, RealtimeSessionRegistryProps as f, SdkSessionAttachment as g, SSEEvent as h, AuthUser as i, useAuth as j, createAuthFetcher as k, ConnectionState as l, RealtimeSessionTarget as m, AppendUserMessageOptions as n, BeginAssistantMessageOptions as o, RealtimeSessionState as p, SandboxLatencyMetrics as q, ApplySdkEventOptions as r, BotStreamEvent as s, AgentStreamEvent as t, RealtimeSessionOptions as u, SdkSessionSeed as v, UseSSEStreamOptions as w, UseAuthOptions as x, TaskStreamEvent as y, useSdkSession as z };