@tangle-network/sandbox-ui 0.137.1 → 0.138.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.
Files changed (92) hide show
  1. package/dist/{WorkflowGraph-BcuJ0kgt.js → WorkflowGraph-DXmu60At.js} +4 -7
  2. package/dist/assets.d.ts +0 -18
  3. package/dist/assets.js +9 -17
  4. package/dist/{auth-CWe17Hly.js → auth-BDpoZ_2f.js} +1 -2
  5. package/dist/auth.d.ts +1 -1
  6. package/dist/auth.js +1 -2
  7. package/dist/{chat-_aHUfqtH.js → chat-BYTVLZQW.js} +9 -15
  8. package/dist/chat.d.ts +1 -1
  9. package/dist/chat.js +1 -2
  10. package/dist/{connections-C5DxYxvz.js → connections-DymjzHe_.js} +1 -2
  11. package/dist/connections.d.ts +1 -1
  12. package/dist/connections.js +1 -2
  13. package/dist/connectors.d.ts +0 -10
  14. package/dist/connectors.js +5 -9
  15. package/dist/{dashboard-SFakZEtu.js → dashboard-ClKA3opr.js} +31 -55
  16. package/dist/dashboard.d.ts +3 -3
  17. package/dist/dashboard.js +3 -3
  18. package/dist/diff-view-A0O0Z_SR.js +287 -0
  19. package/dist/diff-view-DDHWtR6X.d.ts +21 -0
  20. package/dist/editor.js +1 -2
  21. package/dist/{embedded-app-view-CYb9hevq.js → embedded-app-view-DXsoPale.js} +5 -8
  22. package/dist/{embedded-app-view-B_vMTtJn.d.ts → embedded-app-view-Ta5GI4hx.d.ts} +0 -4
  23. package/dist/files.js +1 -2
  24. package/dist/globals.css +43 -0
  25. package/dist/hooks.d.ts +3 -7
  26. package/dist/hooks.js +4 -6
  27. package/dist/{index-DsU8ts9f.d.ts → index-BAEvGqrn.d.ts} +0 -4
  28. package/dist/{index-DvmZLMT1.d.ts → index-BbfWVtZq.d.ts} +0 -2
  29. package/dist/index-C5h5T0nb.d.ts +91 -0
  30. package/dist/{index-ByzdHyte.d.ts → index-CvtEhIpk.d.ts} +25 -52
  31. package/dist/{index-ClRHbsoX.d.ts → index-DLX35YAa.d.ts} +0 -2
  32. package/dist/{index-AVDzT8Jw.d.ts → index-DRDtTgb0.d.ts} +2 -54
  33. package/dist/{index-C61CTrhx.d.ts → index-F42BOxUM.d.ts} +15 -37
  34. package/dist/{index-QBCEflyf.d.ts → index-ucJHuuVZ.d.ts} +2 -8
  35. package/dist/{index-DGil6iqm.d.ts → index-y2OPUSoY.d.ts} +0 -4
  36. package/dist/index.d.ts +17 -16
  37. package/dist/index.js +24 -20
  38. package/dist/integrations.d.ts +0 -14
  39. package/dist/integrations.js +6 -11
  40. package/dist/markdown.js +1 -2
  41. package/dist/{model-brand-B57CV8Lg.d.ts → model-brand-ZwVS49Fq.d.ts} +0 -2
  42. package/dist/{model-brand-BSr9on8C.js → model-brand-bTcMjQtB.js} +34 -67
  43. package/dist/{motion-D4njYpys.js → motion-Bn7ESHrj.js} +1 -2
  44. package/dist/{node-output-fuk0NV0V.js → node-output-udnwhShN.js} +9 -16
  45. package/dist/openui.js +1 -2
  46. package/dist/{page-layout-2IRtfx51.js → page-layout-CuOpvZys.js} +5 -9
  47. package/dist/pages.d.ts +2 -14
  48. package/dist/pages.js +9 -15
  49. package/dist/{primitives-CLOVnjWz.js → primitives-CiwDp4-0.js} +4 -7
  50. package/dist/primitives.d.ts +1 -1
  51. package/dist/primitives.js +1 -2
  52. package/dist/{provider-logo-BGCziCbM.js → provider-logo-CPKRPHcS.js} +1 -2
  53. package/dist/{rolldown-runtime-BBjsoOtd.js → rolldown-runtime-782esTHO.js} +1 -2
  54. package/dist/run-CliTxkfw.js +397 -0
  55. package/dist/run.d.ts +2 -2
  56. package/dist/run.js +1 -2
  57. package/dist/sdk-hooks.d.ts +1 -1
  58. package/dist/sdk-hooks.js +1 -1
  59. package/dist/{shell-header-CTh3oV_e.js → shell-header-CwqDzC4I.js} +2 -3
  60. package/dist/{sidecar-DgH_vQ6m.d.ts → sidecar-CNP4zXop.d.ts} +0 -2
  61. package/dist/stores.d.ts +0 -2
  62. package/dist/stores.js +1 -2
  63. package/dist/styles.css +43 -0
  64. package/dist/{terminal-X6r5pjgv.js → terminal-nUCznZRj.js} +3 -5
  65. package/dist/terminal.d.ts +1 -3
  66. package/dist/terminal.js +1 -2
  67. package/dist/{tree-data-DtoCNNBJ.js → tree-data-YXtcK6Ld.js} +2 -4
  68. package/dist/types.d.ts +1 -1
  69. package/dist/{usage-chart-BjM8ShvX.d.ts → usage-chart-BFpdkqNq.d.ts} +0 -6
  70. package/dist/{use-pty-session-B5Q_i9RI.js → use-pty-session-BHVQlSs-.js} +1 -2
  71. package/dist/{use-pty-session-DbAYO5uH.d.ts → use-pty-session-DSgtQyYX.d.ts} +0 -2
  72. package/dist/{use-sidecar-auth-CCTJcrq7.d.ts → use-sidecar-auth-CPevSSEj.d.ts} +0 -4
  73. package/dist/{use-sidecar-auth-DkdcufOz.js → use-sidecar-auth-DpG0aWQ3.js} +3 -6
  74. package/dist/utils-BER_bdgE.js +1 -0
  75. package/dist/utils.js +1 -2
  76. package/dist/vault-tree.d.ts +1 -1
  77. package/dist/vault-tree.js +1 -2
  78. package/dist/workbench/diff.d.ts +2 -0
  79. package/dist/workbench/diff.js +1 -0
  80. package/dist/workbench/embedded-app.d.ts +1 -1
  81. package/dist/workbench/embedded-app.js +1 -2
  82. package/dist/workbench-B3JL1qbt.js +892 -0
  83. package/dist/workbench.d.ts +4 -3
  84. package/dist/workbench.js +4 -3
  85. package/dist/workflows.d.ts +1 -13
  86. package/dist/workflows.js +4 -5
  87. package/dist/{workspace-cjk0axyT.js → workspace-DRhi6S3o.js} +325 -141
  88. package/dist/workspace.d.ts +1 -1
  89. package/dist/workspace.js +2 -2
  90. package/package.json +36 -28
  91. package/dist/utils-DzWbktWG.js +0 -2
  92. package/dist/workbench-DPZ6LXqf.js +0 -8136
@@ -1,9 +1,9 @@
1
- import { t as cn } from "./utils-DzWbktWG.js";
1
+ import { t as cn } from "./utils-BER_bdgE.js";
2
2
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, PageHeader, PageShell, Progress } from "@tangle-network/ui/primitives";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import * as React$1 from "react";
5
5
  import { Check, Zap } from "lucide-react";
6
- //#region src/dashboard/billing-dashboard.tsx
6
+ // src/dashboard/billing-dashboard.tsx
7
7
  const variantColors = { sandbox: {
8
8
  accent: "text-[var(--accent-text)]",
9
9
  accentBg: "bg-[var(--accent-surface-soft)]",
@@ -259,8 +259,7 @@ function BillingDashboard({ subscription, balance, usage, onManageSubscription,
259
259
  ]
260
260
  });
261
261
  }
262
- //#endregion
263
- //#region src/dashboard/pricing-page.tsx
262
+ // src/dashboard/pricing-page.tsx
264
263
  /**
265
264
  * Formats an integer cent amount as a human-readable USD price.
266
265
  * Whole-dollar amounts omit decimals ($10), fractional amounts show two ($10.99).
@@ -380,8 +379,7 @@ function PricingPage({ tiers, currentTierId, billingPeriod, onBillingPeriodChang
380
379
  })]
381
380
  });
382
381
  }
383
- //#endregion
384
- //#region src/dashboard/usage-chart.tsx
382
+ // src/dashboard/usage-chart.tsx
385
383
  const colors = {
386
384
  bar: "bg-[image:var(--accent-gradient-strong)]",
387
385
  barHover: "hover:brightness-110",
@@ -530,8 +528,7 @@ function UsageChart({ data, title, unit, className }) {
530
528
  })] }) })]
531
529
  });
532
530
  }
533
- //#endregion
534
- //#region src/dashboard/page-layout.tsx
531
+ // src/dashboard/page-layout.tsx
535
532
  /** Product page spacing; the generic UI PageShell remains an exact re-export. */
536
533
  function SandboxPageShell({ children, className }) {
537
534
  return /* @__PURE__ */ jsx(PageShell, {
@@ -547,5 +544,4 @@ function DashboardPageHeader({ title, description, actions, className }) {
547
544
  className: cn("gap-3 [&_h1]:text-2xl sm:[&_h1]:text-[28px] [&_h1]:font-semibold [&_p]:text-base [&_p]:leading-relaxed", className)
548
545
  });
549
546
  }
550
- //#endregion
551
547
  export { formatPrice as a, PricingPage as i, SandboxPageShell as n, BillingDashboard as o, UsageChart as r, DashboardPageHeader as t };
package/dist/pages.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { r as ModelInfo } from "./model-brand-B57CV8Lg.js";
2
- import { c as BillingBalance, d as BillingSubscription, f as BillingUsage, o as PricingTier, r as UsageDataPoint } from "./usage-chart-BjM8ShvX.js";
1
+ import { r as ModelInfo } from "./model-brand-ZwVS49Fq.js";
2
+ import { c as BillingBalance, d as BillingSubscription, f as BillingUsage, o as PricingTier, r as UsageDataPoint } from "./usage-chart-BFpdkqNq.js";
3
3
  import * as React$2 from "react";
4
4
  import { CSSProperties, ReactNode } from "react";
5
- //#region src/pages/auth-page.d.ts
6
5
  /**
7
6
  * Shared, self-contained sign-in / sign-up page for every Tangle vertical app.
8
7
  *
@@ -63,8 +62,6 @@ interface AuthPageProps {
63
62
  children?: ReactNode;
64
63
  }
65
64
  export declare function AuthPage({ product, tagline, mode, tangleAuthUrl, providers, socialHref, onEmailSubmit, collectName, altHref, accent, accentHover, accentForeground, logoSize, className, style, children }: AuthPageProps): import("react").JSX.Element;
66
- //#endregion
67
- //#region src/pages/billing-page.d.ts
68
65
  type ProductVariant = "sandbox";
69
66
  interface BillingPageData {
70
67
  subscription: BillingSubscription | null;
@@ -83,8 +80,6 @@ interface BillingPageProps {
83
80
  fetchBillingData?: () => Promise<BillingPageData>;
84
81
  }
85
82
  export declare function BillingPage({ variant, initialData, apiBasePath, onManageSubscription, onAddCredits, onSelectTier, fetchBillingData }: BillingPageProps): React$2.JSX.Element;
86
- //#endregion
87
- //#region src/pages/provisioning-types.d.ts
88
83
  interface EnvironmentOption {
89
84
  id: string;
90
85
  name: string;
@@ -168,8 +163,6 @@ interface ProvisioningConfig {
168
163
  bare: boolean;
169
164
  startupScriptIds?: string[];
170
165
  }
171
- //#endregion
172
- //#region src/pages/secrets-page.d.ts
173
166
  interface Secret {
174
167
  name: string;
175
168
  createdAt: string;
@@ -213,8 +206,6 @@ interface SecretsPageProps {
213
206
  };
214
207
  }
215
208
  export declare function SecretsPage({ apiClient, className, teamSecretsHint, title, description, createDescription, emptyDescription, deleteConsequence, variant }: SecretsPageProps): React$2.JSX.Element;
216
- //#endregion
217
- //#region src/pages/startup-scripts-page.d.ts
218
209
  type ScriptType = "bash" | "python" | "node" | "ruby" | "custom";
219
210
  interface StartupScript {
220
211
  id: string;
@@ -268,10 +259,7 @@ interface StartupScriptsPageProps {
268
259
  className?: string;
269
260
  }
270
261
  export declare function StartupScriptsPage({ apiClient, className }: StartupScriptsPageProps): React$2.JSX.Element;
271
- //#endregion
272
- //#region src/lib/template-presets.d.ts
273
262
  type TemplateCategory = "blockchain" | "ai-ml" | "frontend" | "infrastructure" | "general";
274
263
  type TemplatePreset = Omit<ProvisioningConfig, "name" | "gitUrl" | "envVars" | "driver" | "startupScriptIds">;
275
264
  export declare function getPresetForTemplate(id: string): TemplatePreset;
276
- //#endregion
277
265
  export type { AuthPageProps, BillingPageData, BillingPageProps, EnvironmentEntry, EnvironmentOption, ModelInfo, PlanTierInfo, PricingRates, PricingTier, ProductVariant, ProvisioningConfig, ResourceLimits, ScriptType, Secret, SecretsApiClient, SecretsPageProps, SocialProvider, SshAccessConfig, SshKeyOption, StartupScript, StartupScriptEntry, StartupScriptFormData, StartupScriptsApiClient, StartupScriptsPageProps, TemplateCategory, TemplatePreset };
package/dist/pages.js CHANGED
@@ -1,6 +1,6 @@
1
- import { t as cn$1 } from "./utils-DzWbktWG.js";
2
- import { r as ShellHeader } from "./shell-header-CTh3oV_e.js";
3
- import { i as PricingPage, o as BillingDashboard, r as UsageChart, t as DashboardPageHeader } from "./page-layout-2IRtfx51.js";
1
+ import { t as cn$1 } from "./utils-BER_bdgE.js";
2
+ import { r as ShellHeader } from "./shell-header-CwqDzC4I.js";
3
+ import { i as PricingPage, o as BillingDashboard, r as UsageChart, t as DashboardPageHeader } from "./page-layout-CuOpvZys.js";
4
4
  import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Skeleton, SkeletonCard, Tabs, TabsContent, TabsList, TabsTrigger } from "@tangle-network/ui/primitives";
5
5
  import { Logo, TangleKnot } from "@tangle-network/brand";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -8,7 +8,7 @@ import * as React$1 from "react";
8
8
  import { useState } from "react";
9
9
  import { AlertCircle, CheckCircle, ChevronDown, ChevronUp, Clock, Cpu, Eye, EyeOff, GripVertical, Key, Layers, Lock, MemoryStick, Pencil, Plus, Power, PowerOff, Terminal, Trash2, Upload } from "lucide-react";
10
10
  import { cn, focusField, focusRing, ixControl, ixControlSoft, ixField } from "@tangle-network/ui/utils";
11
- //#region src/pages/auth-page.tsx
11
+ // src/pages/auth-page.tsx
12
12
  const C = {
13
13
  pageBg: "hsl(var(--background, 240 5% 97%))",
14
14
  card: "hsl(var(--card, 0 0% 100%))",
@@ -312,8 +312,7 @@ function AuthPage({ product, tagline, mode = "signin", tangleAuthUrl = "/auth/ta
312
312
  })
313
313
  });
314
314
  }
315
- //#endregion
316
- //#region src/pages/billing-page.tsx
315
+ // src/pages/billing-page.tsx
317
316
  const defaultBillingData = {
318
317
  subscription: null,
319
318
  balance: {
@@ -596,8 +595,7 @@ function BillingPage({ variant = "sandbox", initialData, apiBasePath = "", onMan
596
595
  })
597
596
  });
598
597
  }
599
- //#endregion
600
- //#region src/pages/env-importer.ts
598
+ // src/pages/env-importer.ts
601
599
  const NORMALIZE_RE = /[^A-Z0-9_]/g;
602
600
  /** Mirrors the on-keystroke normalization used by the single-secret input. */
603
601
  function normalizeKey(rawKey) {
@@ -688,8 +686,7 @@ function parseEnvText(text) {
688
686
  errors
689
687
  };
690
688
  }
691
- //#endregion
692
- //#region src/pages/secrets-page.tsx
689
+ // src/pages/secrets-page.tsx
693
690
  /** Cap pasted/uploaded import sources so a pathological file cannot blow up the parser/UI. */
694
691
  const MAX_IMPORT_FILE_BYTES = 262144;
695
692
  const DEFAULT_DESCRIPTION = "Manage environment variables for your sandboxes.";
@@ -1482,8 +1479,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint, title = "Environme
1482
1479
  ]
1483
1480
  });
1484
1481
  }
1485
- //#endregion
1486
- //#region src/pages/startup-scripts-page.tsx
1482
+ // src/pages/startup-scripts-page.tsx
1487
1483
  const SCRIPT_TYPE_META = {
1488
1484
  bash: {
1489
1485
  label: "Bash",
@@ -2334,8 +2330,7 @@ function StartupScriptsPage({ apiClient, className }) {
2334
2330
  ]
2335
2331
  });
2336
2332
  }
2337
- //#endregion
2338
- //#region src/lib/template-presets.ts
2333
+ // src/lib/template-presets.ts
2339
2334
  const BLOCKCHAIN_PATTERNS = [
2340
2335
  "ethereum",
2341
2336
  "solana",
@@ -2478,5 +2473,4 @@ function getPresetForTemplate(id) {
2478
2473
  environment: id
2479
2474
  };
2480
2475
  }
2481
- //#endregion
2482
2476
  export { AuthPage, BillingPage, SecretsPage, StartupScriptsPage, getPresetForTemplate };
@@ -1,8 +1,8 @@
1
- import { n as __reExport, t as __exportAll } from "./rolldown-runtime-BBjsoOtd.js";
1
+ import { n as __reExport, t as __exportAll } from "./rolldown-runtime-782esTHO.js";
2
2
  import { PageHeader } from "@tangle-network/ui/primitives";
3
3
  import { Logo, TangleKnot as TangleKnot$1 } from "@tangle-network/brand";
4
4
  import { jsx } from "react/jsx-runtime";
5
- //#region src/primitives/logo.tsx
5
+ // src/primitives/logo.tsx
6
6
  /** Keep the Sandbox wordmark API while Brand owns the mark and layout. */
7
7
  function Logo$1({ variant = "sandbox", size = "md", className, iconOnly = false }) {
8
8
  return /* @__PURE__ */ jsx(Logo, {
@@ -13,8 +13,7 @@ function Logo$1({ variant = "sandbox", size = "md", className, iconOnly = false
13
13
  });
14
14
  }
15
15
  Logo$1.displayName = "Logo";
16
- //#endregion
17
- //#region src/primitives/heading.tsx
16
+ // src/primitives/heading.tsx
18
17
  /** Compatibility name for the canonical nested (h2) page header. */
19
18
  function SectionTitle(props) {
20
19
  return /* @__PURE__ */ jsx(PageHeader, {
@@ -22,8 +21,7 @@ function SectionTitle(props) {
22
21
  level: 2
23
22
  });
24
23
  }
25
- //#endregion
26
- //#region src/primitives/index.ts
24
+ // src/primitives/index.ts
27
25
  var primitives_exports = /* @__PURE__ */ __exportAll({
28
26
  Logo: () => Logo$1,
29
27
  SectionTitle: () => SectionTitle,
@@ -31,5 +29,4 @@ var primitives_exports = /* @__PURE__ */ __exportAll({
31
29
  });
32
30
  import * as import__tangle_network_ui_primitives from "@tangle-network/ui/primitives";
33
31
  __reExport(primitives_exports, import__tangle_network_ui_primitives);
34
- //#endregion
35
32
  export { TangleKnot$1 as i, SectionTitle as n, Logo$1 as r, primitives_exports as t };
@@ -1,3 +1,3 @@
1
- import { a as LogoProps, i as Logo, n as SectionTitle, o as TangleKnot, r as SectionTitleProps, t as HeadingProps } from "./index-DsU8ts9f.js";
1
+ import { a as LogoProps, i as Logo, n as SectionTitle, o as TangleKnot, r as SectionTitleProps, t as HeadingProps } from "./index-BAEvGqrn.js";
2
2
  export * from "@tangle-network/ui/primitives";
3
3
  export { type HeadingProps, Logo, type LogoProps, SectionTitle, type SectionTitleProps, TangleKnot };
@@ -1,3 +1,2 @@
1
- import { i as TangleKnot, n as SectionTitle, r as Logo } from "./primitives-CLOVnjWz.js";
1
+ export { r as Logo, n as SectionTitle, i as TangleKnot } from "./primitives-CiwDp4-0.js";
2
2
  export * from "@tangle-network/ui/primitives";
3
- export { Logo, SectionTitle, TangleKnot };
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import * as React$1 from "react";
3
- //#region src/integrations/provider-logo.tsx
3
+ // src/integrations/provider-logo.tsx
4
4
  /**
5
5
  * Provider branding: resolve a connector/provider slug to a logo and render it
6
6
  * with graceful fallbacks. Shared by the integrations catalog tiles and the
@@ -325,5 +325,4 @@ function ProviderIcon({ id, iconUrl, displayName, size = 24, className }) {
325
325
  onError: () => setIndex((i) => i + 1)
326
326
  });
327
327
  }
328
- //#endregion
329
328
  export { normalizeProviderId as n, providerLogoCandidates as r, ProviderIcon as t };
@@ -1,4 +1,4 @@
1
- //#region \0rolldown/runtime.js
1
+ // \0rolldown/runtime.js
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -23,5 +23,4 @@ var __copyProps = (to, from, except, desc) => {
23
23
  return to;
24
24
  };
25
25
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
26
- //#endregion
27
26
  export { __reExport as n, __exportAll as t };
@@ -0,0 +1,397 @@
1
+ import { t as cn } from "./utils-BER_bdgE.js";
2
+ import { i as modelBrandFor, t as ModelBrandStack } from "./model-brand-bTcMjQtB.js";
3
+ import { t as ProviderIcon } from "./provider-logo-CPKRPHcS.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
6
+ import { X } from "lucide-react";
7
+ import { AgentTimeline } from "@tangle-network/ui/chat";
8
+ import { ApprovalCard, ApprovalDiffSummary, ExpandedToolDetail, InlineThinkingItem, InlineThinkingItem as InlineThinkingItem$1, InlineToolItem, LiveDuration, RunGroup, RunPhaseList, RunRowShell, RunRowStatusDot, TaskList, ToolCallFeed, parseToolEvent, showsTaskPriority, taskProgress, taskStatus } from "@tangle-network/ui/run";
9
+ import { FlowWaterfall } from "@tangle-network/charts/react";
10
+ // src/run/trace-waterfall.tsx
11
+ /** Agent and model spans show their lab/host mark; tool spans show their provider's mark. Unknown keeps the kind glyph. */
12
+ function traceSpanMark(span) {
13
+ if (span.kind === "pipeline" || span.kind === "model") {
14
+ const identity = span.detail ? modelBrandFor(span.detail) : null;
15
+ return identity ? /* @__PURE__ */ jsx(ModelBrandStack, {
16
+ identity,
17
+ size: "sm"
18
+ }) : void 0;
19
+ }
20
+ const provider = span.icon ?? (span.kind === "tool" ? span.detail : void 0);
21
+ return provider ? /* @__PURE__ */ jsx(ProviderIcon, {
22
+ id: provider,
23
+ displayName: provider,
24
+ size: 14,
25
+ className: "rounded-[3px]"
26
+ }) : void 0;
27
+ }
28
+ /**
29
+ * The run inspector: the agent timeline (`defaultView="agents"`) and the span waterfall over one clock, from
30
+ * `@tangle-network/charts`, with Sandbox UI's brand marks. Feed it `otlpFlowTrace(spans)` from the
31
+ * `traces convert` contract. Import `@tangle-network/charts/react/flow-waterfall.css` once.
32
+ */
33
+ function TraceWaterfall({ renderIcon = traceSpanMark, ...props }) {
34
+ return /* @__PURE__ */ jsx(FlowWaterfall, {
35
+ renderIcon,
36
+ ...props
37
+ });
38
+ }
39
+ // src/run/agent-stream.ts
40
+ const TOOL_TYPES = /* @__PURE__ */ new Set([
41
+ "bash",
42
+ "read",
43
+ "write",
44
+ "edit",
45
+ "glob",
46
+ "grep",
47
+ "list",
48
+ "download",
49
+ "inspect",
50
+ "audit"
51
+ ]);
52
+ const toolType = (name) => {
53
+ const key = (name ?? "").toLowerCase();
54
+ return TOOL_TYPES.has(key) ? key : "unknown";
55
+ };
56
+ const brief = (value, max = 240) => {
57
+ if (value === void 0 || value === null) return void 0;
58
+ const text = typeof value === "string" ? value : JSON.stringify(value);
59
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
60
+ };
61
+ const failed = (result) => typeof result === "object" && result !== null && ("error" in result || result.is_error === true);
62
+ /** Fold stream rows into transcript entries: text of one turn merges, a tool call becomes a row its result completes. */
63
+ function foldAgentRows(entries, rows) {
64
+ const next = [...entries];
65
+ for (const row of rows) {
66
+ const at = Date.parse(row.at);
67
+ const { event } = row;
68
+ const last = next[next.length - 1];
69
+ if (event.kind === "text" && event.text) {
70
+ if (last?.kind === "message" && last.role === "assistant") next[next.length - 1] = {
71
+ ...last,
72
+ content: last.content + event.text
73
+ };
74
+ else next.push({
75
+ id: `m-${row.seq}`,
76
+ at,
77
+ kind: "message",
78
+ role: "assistant",
79
+ content: event.text
80
+ });
81
+ } else if (event.kind === "user" && event.text) next.push({
82
+ id: `u-${row.seq}`,
83
+ at,
84
+ kind: "message",
85
+ role: "user",
86
+ content: event.text
87
+ });
88
+ else if (event.kind === "reasoning" && event.text) {
89
+ if (last?.kind === "reasoning") next[next.length - 1] = {
90
+ ...last,
91
+ text: last.text + event.text
92
+ };
93
+ else next.push({
94
+ id: `r-${row.seq}`,
95
+ at,
96
+ kind: "reasoning",
97
+ text: event.text
98
+ });
99
+ } else if (event.kind === "tool-call") {
100
+ const id = event.toolCallId ?? `t-${row.seq}`;
101
+ next.push({
102
+ id,
103
+ at,
104
+ kind: "tool",
105
+ call: {
106
+ id,
107
+ type: toolType(event.toolName),
108
+ label: event.toolName ?? "tool",
109
+ status: "running",
110
+ detail: brief(event.args, 120)
111
+ }
112
+ });
113
+ } else if (event.kind === "tool-result") {
114
+ const index = next.findIndex((entry) => entry.kind === "tool" && entry.call.id === event.toolCallId);
115
+ const entry = next[index];
116
+ if (entry?.kind === "tool") next[index] = {
117
+ ...entry,
118
+ call: {
119
+ ...entry.call,
120
+ status: failed(event.result) ? "error" : "success",
121
+ output: brief(event.result),
122
+ duration: Math.max(0, at - entry.at)
123
+ }
124
+ };
125
+ }
126
+ }
127
+ return next;
128
+ }
129
+ function reduce(state, action) {
130
+ switch (action.type) {
131
+ case "reset": return {
132
+ generation: action.generation,
133
+ entries: [],
134
+ lastSeq: 0,
135
+ alive: true
136
+ };
137
+ case "rows": {
138
+ const base = action.generation !== void 0 && action.generation !== state.generation ? {
139
+ entries: [],
140
+ lastSeq: 0
141
+ } : state;
142
+ const fresh = action.rows.filter((row) => row.seq > base.lastSeq);
143
+ return {
144
+ generation: action.generation ?? state.generation,
145
+ entries: foldAgentRows(base.entries, fresh),
146
+ lastSeq: fresh.reduce((max, row) => Math.max(max, row.seq), base.lastSeq),
147
+ alive: action.alive ?? state.alive
148
+ };
149
+ }
150
+ case "end": return {
151
+ ...state,
152
+ alive: false
153
+ };
154
+ case "error": return {
155
+ ...state,
156
+ error: action.message
157
+ };
158
+ }
159
+ }
160
+ /**
161
+ * Follow one agent's message stream over Server-Sent Events: `rows`, `reset` and `end` events, reconnecting with
162
+ * `?after=<lastSeq>` when the server closes the connection, so a long turn streams without gaps or repeats.
163
+ */
164
+ function useAgentStream(url) {
165
+ const [state, dispatch] = useReducer(reduce, {
166
+ entries: [],
167
+ lastSeq: 0,
168
+ alive: false
169
+ });
170
+ useEffect(() => {
171
+ if (!url || typeof EventSource === "undefined") return;
172
+ dispatch({ type: "reset" });
173
+ let lastSeq = 0;
174
+ let closed = false;
175
+ let source;
176
+ let retry;
177
+ const open = () => {
178
+ const target = new URL(url, globalThis.location?.href);
179
+ if (lastSeq > 0) target.searchParams.set("after", String(lastSeq));
180
+ source = new EventSource(target.toString());
181
+ source.addEventListener("rows", (message) => {
182
+ const data = JSON.parse(message.data);
183
+ lastSeq = Math.max(lastSeq, data.lastSeq ?? 0, ...data.events.map((row) => row.seq));
184
+ dispatch({
185
+ type: "rows",
186
+ generation: data.generation,
187
+ rows: data.events,
188
+ alive: data.alive
189
+ });
190
+ });
191
+ source.addEventListener("reset", (message) => {
192
+ lastSeq = 0;
193
+ dispatch({
194
+ type: "reset",
195
+ generation: JSON.parse(message.data).generation
196
+ });
197
+ });
198
+ source.addEventListener("end", () => {
199
+ closed = true;
200
+ source?.close();
201
+ dispatch({ type: "end" });
202
+ });
203
+ source.onerror = () => {
204
+ source?.close();
205
+ if (!closed) retry = setTimeout(open, 1e3);
206
+ };
207
+ };
208
+ open();
209
+ return () => {
210
+ closed = true;
211
+ clearTimeout(retry);
212
+ source?.close();
213
+ };
214
+ }, [url]);
215
+ return state;
216
+ }
217
+ // src/run/trace-workspace.tsx
218
+ /** The agent that owns a span: the span itself when it is an agent, else its nearest agent ancestor. */
219
+ function agentOf(span, byId) {
220
+ for (let cursor = span; cursor; cursor = cursor.parentId ? byId.get(cursor.parentId) : void 0) if (cursor.kind === "pipeline") return cursor;
221
+ }
222
+ function timelineItems(entries, streaming) {
223
+ return entries.map((entry, index) => {
224
+ if (entry.kind === "message") return {
225
+ id: entry.id,
226
+ kind: "message",
227
+ role: entry.role,
228
+ content: entry.content,
229
+ isStreaming: streaming && index === entries.length - 1
230
+ };
231
+ if (entry.kind === "tool") return {
232
+ id: entry.id,
233
+ kind: "tool",
234
+ call: entry.call
235
+ };
236
+ return {
237
+ id: entry.id,
238
+ kind: "custom",
239
+ content: /* @__PURE__ */ jsx(InlineThinkingItem, {
240
+ part: {
241
+ type: "reasoning",
242
+ text: entry.text
243
+ },
244
+ defaultOpen: false,
245
+ openWhileActive: false
246
+ })
247
+ };
248
+ });
249
+ }
250
+ function NotTimeIndexed({ label }) {
251
+ return /* @__PURE__ */ jsxs("p", {
252
+ className: "p-4 text-sm text-muted-foreground",
253
+ children: [label, ": not time-indexed"]
254
+ });
255
+ }
256
+ /**
257
+ * The run workspace: the agent timeline and span waterfall over one clock, the selected agent's conversation
258
+ * streaming in a right-hand drawer, and the page's code workspace and scoreboard following the time cursor. Scrubbing is time travel:
259
+ * every panel shows what was true at the cursor, and the conversation shows what had been said by then.
260
+ */
261
+ function TraceWorkspace({ trace, streamUrl, events, onTimeChange, files, scoreboard, selectedAgentId, onSelectAgent, className, ...waterfall }) {
262
+ const byId = useMemo(() => new Map(trace.spans.flatMap((span) => span.id ? [[span.id, span]] : [])), [trace]);
263
+ const [ownSelection, setOwnSelection] = useState();
264
+ const selected = selectedAgentId ?? ownSelection;
265
+ const select = (agentId) => {
266
+ setOwnSelection(agentId);
267
+ onSelectAgent?.(agentId);
268
+ };
269
+ const agent = selected ? byId.get(selected) : void 0;
270
+ const [cursor, setCursor] = useState(null);
271
+ const stream = useAgentStream(selected && streamUrl ? streamUrl(selected) : void 0);
272
+ const origin = useMemo(() => {
273
+ if (waterfall.startedAt !== void 0) return waterfall.startedAt;
274
+ const first = stream.entries[0]?.at;
275
+ return agent && first !== void 0 ? first - agent.startMs : void 0;
276
+ }, [
277
+ waterfall.startedAt,
278
+ agent,
279
+ stream.entries
280
+ ]);
281
+ const shown = cursor === null || origin === void 0 ? stream.entries : stream.entries.filter((entry) => entry.at - origin <= cursor);
282
+ const items = useMemo(() => timelineItems(shown, cursor === null && stream.alive), [
283
+ shown,
284
+ cursor,
285
+ stream.alive
286
+ ]);
287
+ const scroller = useRef(null);
288
+ const pinned = useRef(true);
289
+ const [unseen, setUnseen] = useState(false);
290
+ useLayoutEffect(() => {
291
+ const element = scroller.current;
292
+ if (!element) return;
293
+ if (pinned.current) element.scrollTop = element.scrollHeight;
294
+ else setUnseen(true);
295
+ }, [items.length, items[items.length - 1]]);
296
+ useEffect(() => {
297
+ pinned.current = true;
298
+ setUnseen(false);
299
+ }, [selected]);
300
+ return /* @__PURE__ */ jsxs("div", {
301
+ className: cn("sandbox-trace-workspace flex min-h-0 flex-col gap-3", className),
302
+ children: [
303
+ /* @__PURE__ */ jsx(TraceWaterfall, {
304
+ ...waterfall,
305
+ trace,
306
+ markers: events,
307
+ selectedId: agent?.id,
308
+ onDeselect: () => select(void 0),
309
+ onSelect: (span) => {
310
+ const owner = agentOf(span, byId);
311
+ if (owner?.id) select(owner.id);
312
+ },
313
+ onTimeChange: (t) => {
314
+ setCursor(t);
315
+ onTimeChange?.(t);
316
+ }
317
+ }),
318
+ /* @__PURE__ */ jsx("section", {
319
+ "aria-label": "Code at the cursor",
320
+ className: "flex min-h-[70vh] flex-col overflow-hidden rounded-xl border border-border bg-card",
321
+ children: files ?? /* @__PURE__ */ jsx(NotTimeIndexed, { label: "Files" })
322
+ }),
323
+ scoreboard && /* @__PURE__ */ jsx("section", {
324
+ "aria-label": "Scoreboard at the cursor",
325
+ className: "overflow-hidden rounded-xl border border-border bg-card",
326
+ children: scoreboard
327
+ }),
328
+ agent && /* @__PURE__ */ jsxs("aside", {
329
+ "aria-label": `${agent.name} conversation`,
330
+ onKeyDown: (event) => {
331
+ if (event.key === "Escape") select(void 0);
332
+ },
333
+ className: "fixed inset-y-0 right-0 z-40 flex w-full max-w-[420px] flex-col border-l border-border bg-card shadow-2xl",
334
+ children: [
335
+ /* @__PURE__ */ jsxs("header", {
336
+ className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-2",
337
+ children: [
338
+ /* @__PURE__ */ jsx("span", {
339
+ className: cn("h-2 w-2 shrink-0 rounded-full", stream.alive && cursor === null ? "bg-[var(--status-running,#34c48c)]" : "bg-muted-foreground/50"),
340
+ "aria-hidden": true
341
+ }),
342
+ /* @__PURE__ */ jsx("h3", {
343
+ className: "min-w-0 flex-1 truncate text-sm font-semibold",
344
+ children: agent.name
345
+ }),
346
+ agent.detail && /* @__PURE__ */ jsx("span", {
347
+ className: "truncate text-xs text-muted-foreground",
348
+ children: agent.detail
349
+ }),
350
+ /* @__PURE__ */ jsx("button", {
351
+ type: "button",
352
+ "aria-label": "Close conversation",
353
+ title: "Close (Esc)",
354
+ onClick: () => select(void 0),
355
+ className: "shrink-0 rounded-md p-1 text-muted-foreground hover:bg-muted hover:text-foreground",
356
+ children: /* @__PURE__ */ jsx(X, {
357
+ "aria-hidden": true,
358
+ className: "h-4 w-4"
359
+ })
360
+ })
361
+ ]
362
+ }),
363
+ /* @__PURE__ */ jsx("div", {
364
+ ref: scroller,
365
+ onScroll: (event) => {
366
+ const element = event.currentTarget;
367
+ pinned.current = element.scrollHeight - element.scrollTop - element.clientHeight < 48;
368
+ if (pinned.current) setUnseen(false);
369
+ },
370
+ "data-primary-content": "",
371
+ className: "min-h-0 flex-1 overflow-y-auto px-3 py-2",
372
+ children: streamUrl ? /* @__PURE__ */ jsx(AgentTimeline, {
373
+ items,
374
+ isThinking: stream.alive && cursor === null && items.length === 0,
375
+ emptyState: /* @__PURE__ */ jsx("p", {
376
+ className: "p-4 text-sm text-muted-foreground",
377
+ children: stream.error ?? "No messages yet."
378
+ })
379
+ }) : /* @__PURE__ */ jsx(NotTimeIndexed, { label: "Conversation" })
380
+ }),
381
+ unseen && /* @__PURE__ */ jsx("button", {
382
+ type: "button",
383
+ onClick: () => {
384
+ const element = scroller.current;
385
+ if (element) element.scrollTop = element.scrollHeight;
386
+ pinned.current = true;
387
+ setUnseen(false);
388
+ },
389
+ className: "absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full border border-border bg-background px-3 py-1 text-xs shadow-sm",
390
+ children: "New output"
391
+ })
392
+ ]
393
+ })
394
+ ]
395
+ });
396
+ }
397
+ export { TraceWorkspace as _, InlineToolItem as a, TraceWaterfall as b, RunPhaseList as c, TaskList as d, ToolCallFeed as f, taskStatus as g, taskProgress as h, InlineThinkingItem$1 as i, RunRowShell as l, showsTaskPriority as m, ApprovalDiffSummary as n, LiveDuration as o, parseToolEvent as p, ExpandedToolDetail as r, RunGroup as s, ApprovalCard as t, RunRowStatusDot as u, foldAgentRows as v, traceSpanMark as x, useAgentStream as y };
package/dist/run.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { ApprovalCard, ApprovalCardProps, ApprovalDiffFile, ApprovalDiffSummary, ApprovalPlanStep, ExpandedToolDetail, ExpandedToolDetailProps, FeedSegment, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps, RunPhase, RunPhaseList, RunRowShell, RunRowShellProps, RunRowStatus, RunRowStatusDot, TaskList, TaskListItem, TaskListProps, TaskStatus, ToolCallData, ToolCallFeed, ToolCallFeedProps, ToolCallStatus, ToolCallType, parseToolEvent, showsTaskPriority, taskProgress, taskStatus } from "@tangle-network/ui/run";
2
- export { ApprovalCard, type ApprovalCardProps, type ApprovalDiffFile, ApprovalDiffSummary, type ApprovalPlanStep, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, LiveDuration, RunGroup, type RunGroupProps, type RunPhase, RunPhaseList, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, TaskList, type TaskListItem, type TaskListProps, type TaskStatus, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, parseToolEvent, showsTaskPriority, taskProgress, taskStatus };
1
+ import { A as ToolCallType, B as TraceEvent, C as TaskListItem, D as ToolCallFeed, E as ToolCallData, F as AgentStreamRow, G as traceSpanMark, H as TraceWorkspaceProps, I as AgentStreamState, L as AgentTranscriptEntry, M as showsTaskPriority, N as taskProgress, O as ToolCallFeedProps, P as taskStatus, R as foldAgentRows, S as TaskList, T as TaskStatus, U as TraceWaterfall, V as TraceWorkspace, W as TraceWaterfallProps, _ as RunPhaseList, a as ApprovalPlanStep, b as RunRowStatus, c as FeedSegment, d as InlineToolItem, f as InlineToolItemProps, g as RunPhase, h as RunGroupProps, i as ApprovalDiffSummary, j as parseToolEvent, k as ToolCallStatus, l as InlineThinkingItem, m as RunGroup, n as ApprovalCardProps, o as ExpandedToolDetail, p as LiveDuration, r as ApprovalDiffFile, s as ExpandedToolDetailProps, t as ApprovalCard, u as InlineThinkingItemProps, v as RunRowShell, w as TaskListProps, x as RunRowStatusDot, y as RunRowShellProps, z as useAgentStream } from "./index-C5h5T0nb.js";
2
+ export { type AgentStreamRow, type AgentStreamState, type AgentTranscriptEntry, ApprovalCard, type ApprovalCardProps, type ApprovalDiffFile, ApprovalDiffSummary, type ApprovalPlanStep, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, LiveDuration, RunGroup, type RunGroupProps, type RunPhase, RunPhaseList, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, TaskList, type TaskListItem, type TaskListProps, type TaskStatus, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, type TraceEvent, TraceWaterfall, type TraceWaterfallProps, TraceWorkspace, type TraceWorkspaceProps, foldAgentRows, parseToolEvent, showsTaskPriority, taskProgress, taskStatus, traceSpanMark, useAgentStream };
package/dist/run.js CHANGED
@@ -1,2 +1 @@
1
- import { ApprovalCard, ApprovalDiffSummary, ExpandedToolDetail, InlineThinkingItem, InlineToolItem, LiveDuration, RunGroup, RunPhaseList, RunRowShell, RunRowStatusDot, TaskList, ToolCallFeed, parseToolEvent, showsTaskPriority, taskProgress, taskStatus } from "@tangle-network/ui/run";
2
- export { ApprovalCard, ApprovalDiffSummary, ExpandedToolDetail, InlineThinkingItem, InlineToolItem, LiveDuration, RunGroup, RunPhaseList, RunRowShell, RunRowStatusDot, TaskList, ToolCallFeed, parseToolEvent, showsTaskPriority, taskProgress, taskStatus };
1
+ export { t as ApprovalCard, n as ApprovalDiffSummary, r as ExpandedToolDetail, i as InlineThinkingItem, a as InlineToolItem, o as LiveDuration, s as RunGroup, c as RunPhaseList, l as RunRowShell, u as RunRowStatusDot, d as TaskList, f as ToolCallFeed, b as TraceWaterfall, _ as TraceWorkspace, v as foldAgentRows, p as parseToolEvent, m as showsTaskPriority, h as taskProgress, g as taskStatus, x as traceSpanMark, y as useAgentStream } from "./run-CliTxkfw.js";