@tangle-network/sandbox-ui 0.3.7 → 0.3.10

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 (39) hide show
  1. package/dist/active-sessions-store-CeOmXgv5.d.ts +85 -0
  2. package/dist/artifact-pane-Bh45Ssco.d.ts +24 -0
  3. package/dist/{chat-container-B34uj-J1.d.ts → chat-container-Dn1jWtWo.d.ts} +15 -3
  4. package/dist/chat.d.ts +16 -4
  5. package/dist/chat.js +2 -2
  6. package/dist/{chunk-PXRPYAMM.js → chunk-6H3EFUUC.js} +96 -74
  7. package/dist/{chunk-WUR652Y3.js → chunk-72UEKFZ2.js} +113 -89
  8. package/dist/{chunk-5LV6DZZF.js → chunk-FOQTE67I.js} +278 -21
  9. package/dist/chunk-MGCVTFKB.js +10910 -0
  10. package/dist/chunk-OEX7NZE3.js +321 -0
  11. package/dist/chunk-Q56BYXQF.js +61 -0
  12. package/dist/{chunk-ZSNOGOUX.js → chunk-RQOX5JRR.js} +541 -76
  13. package/dist/{chunk-PDV7W4NY.js → chunk-SULQQJPB.js} +1 -56
  14. package/dist/chunk-W4LM3QYZ.js +54 -0
  15. package/dist/{chunk-JF6E2DS5.js → chunk-ZYGWTIWO.js} +171 -155
  16. package/dist/document-editor-pane-Bk-9MQmw.d.ts +116 -0
  17. package/dist/document-editor-pane-GRIQOJHB.js +11 -0
  18. package/dist/editor.d.ts +7 -84
  19. package/dist/editor.js +18 -699
  20. package/dist/{expanded-tool-detail-BDi_h_dZ.d.ts → expanded-tool-detail-DM5M_T9h.d.ts} +10 -2
  21. package/dist/{file-tabs-CmaoDVBI.d.ts → file-tabs-BLfxfmAH.d.ts} +1 -22
  22. package/dist/files.d.ts +25 -3
  23. package/dist/files.js +2 -1
  24. package/dist/hooks.d.ts +3 -1
  25. package/dist/hooks.js +6 -1
  26. package/dist/index.d.ts +12 -6
  27. package/dist/index.js +21 -8
  28. package/dist/pages.js +4 -2
  29. package/dist/primitives.js +4 -2
  30. package/dist/run.d.ts +1 -1
  31. package/dist/run.js +1 -1
  32. package/dist/sdk-hooks.d.ts +32 -1
  33. package/dist/sdk-hooks.js +6 -1
  34. package/dist/stores.d.ts +1 -0
  35. package/dist/stores.js +60 -1
  36. package/dist/types.d.ts +2 -0
  37. package/dist/workspace.d.ts +84 -6
  38. package/dist/workspace.js +10 -4
  39. package/package.json +17 -6
@@ -1,25 +1,36 @@
1
+ import {
2
+ useActiveSessions,
3
+ useNavbarSessions,
4
+ useProjectActivity,
5
+ useTotalRunningSessions
6
+ } from "./chunk-OEX7NZE3.js";
1
7
  import {
2
8
  EmptyState,
3
9
  Input
4
10
  } from "./chunk-MUOL44AE.js";
5
11
  import {
6
12
  ChatContainer
7
- } from "./chunk-PXRPYAMM.js";
13
+ } from "./chunk-6H3EFUUC.js";
8
14
  import {
9
15
  OpenUIArtifactRenderer
10
16
  } from "./chunk-YDBXQQLC.js";
11
17
  import {
12
- ArtifactPane,
13
18
  FileArtifactPane,
14
19
  FileTree,
15
20
  filterFileTree
16
- } from "./chunk-JF6E2DS5.js";
21
+ } from "./chunk-ZYGWTIWO.js";
22
+ import {
23
+ ArtifactPane
24
+ } from "./chunk-W4LM3QYZ.js";
17
25
  import {
18
26
  Markdown
19
27
  } from "./chunk-LTFK464G.js";
20
28
  import {
21
29
  Badge
22
30
  } from "./chunk-MXCSSOGH.js";
31
+ import {
32
+ Button
33
+ } from "./chunk-HWLX5NME.js";
23
34
  import {
24
35
  cn
25
36
  } from "./chunk-RQHJBTEU.js";
@@ -157,6 +168,7 @@ function WorkspaceLayout({
157
168
  right,
158
169
  rightHeader,
159
170
  bottom,
171
+ bottomHeader,
160
172
  defaultLeftOpen = true,
161
173
  defaultRightOpen = false,
162
174
  defaultBottomOpen = false,
@@ -329,7 +341,7 @@ function WorkspaceLayout({
329
341
  className: "border-t border-[var(--border-subtle)] bg-[var(--bg-card)]",
330
342
  children: [
331
343
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-b border-[var(--border-subtle)] px-3 py-2", children: [
332
- /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: "Runtime" }),
344
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: bottomHeader ?? /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: "Runtime" }) }),
333
345
  /* @__PURE__ */ jsx(
334
346
  "button",
335
347
  {
@@ -749,18 +761,406 @@ function RuntimePane({
749
761
  );
750
762
  }
751
763
 
764
+ // src/workspace/session-sidebar.tsx
765
+ import { useMemo as useMemo3, useState as useState4 } from "react";
766
+ import { ArrowLeft, FolderTree, MessageSquareText, Plus, Search as Search2, Settings, Sparkles } from "lucide-react";
767
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
768
+ function statusClasses(status) {
769
+ switch (status) {
770
+ case "running":
771
+ return "bg-[var(--brand-cool)] shadow-[0_0_0_4px_color-mix(in_srgb,var(--brand-cool)_18%,transparent)]";
772
+ case "error":
773
+ return "bg-[var(--status-danger)]";
774
+ case "attention-needed":
775
+ return "bg-[var(--status-warning)]";
776
+ default:
777
+ return "bg-[var(--text-dim)]";
778
+ }
779
+ }
780
+ function iconForLink(icon) {
781
+ switch (icon) {
782
+ case "vault":
783
+ return FolderTree;
784
+ case "settings":
785
+ return Settings;
786
+ case "back":
787
+ return ArrowLeft;
788
+ default:
789
+ return Sparkles;
790
+ }
791
+ }
792
+ function sortItems(items, sessionStatusById) {
793
+ return [...items].sort((left, right) => {
794
+ if (Boolean(left.isPinned) !== Boolean(right.isPinned)) {
795
+ return left.isPinned ? -1 : 1;
796
+ }
797
+ const leftSession = sessionStatusById.get(left.id);
798
+ const rightSession = sessionStatusById.get(right.id);
799
+ if (Boolean(leftSession) !== Boolean(rightSession)) {
800
+ return leftSession ? -1 : 1;
801
+ }
802
+ if (leftSession && rightSession) {
803
+ if (leftSession.isForeground !== rightSession.isForeground) {
804
+ return Number(rightSession.isForeground) - Number(leftSession.isForeground);
805
+ }
806
+ const leftRunning = Number(leftSession.status === "running");
807
+ const rightRunning = Number(rightSession.status === "running");
808
+ if (leftRunning !== rightRunning) {
809
+ return rightRunning - leftRunning;
810
+ }
811
+ if (leftSession.lastActivityAt !== rightSession.lastActivityAt) {
812
+ return rightSession.lastActivityAt - leftSession.lastActivityAt;
813
+ }
814
+ }
815
+ const leftUpdated = left.updatedAt ? new Date(left.updatedAt).getTime() : 0;
816
+ const rightUpdated = right.updatedAt ? new Date(right.updatedAt).getTime() : 0;
817
+ return rightUpdated - leftUpdated;
818
+ });
819
+ }
820
+ function badgeClasses(tone = "neutral") {
821
+ switch (tone) {
822
+ case "accent":
823
+ return "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)]";
824
+ case "success":
825
+ return "border-emerald-500/30 bg-emerald-500/10 text-emerald-200";
826
+ case "warning":
827
+ return "border-amber-500/30 bg-amber-500/10 text-amber-100";
828
+ case "danger":
829
+ return "border-red-500/30 bg-red-500/10 text-red-200";
830
+ default:
831
+ return "border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-secondary)]";
832
+ }
833
+ }
834
+ function navigateToHref(href) {
835
+ if (!href || typeof window === "undefined") return;
836
+ window.location.assign(href);
837
+ }
838
+ function SessionSidebar({
839
+ title,
840
+ subtitle,
841
+ projectId = null,
842
+ items,
843
+ currentItemId,
844
+ createLabel = "New Session",
845
+ onCreate,
846
+ onSelectItem,
847
+ onSelectLink,
848
+ links = [],
849
+ className,
850
+ emptyMessage = "No sessions yet. Start a conversation.",
851
+ searchPlaceholder = "Search sessions",
852
+ enableSearch = true,
853
+ activityMonitor,
854
+ filters = [],
855
+ defaultFilterId,
856
+ renderItemActions
857
+ }) {
858
+ const [query, setQuery] = useState4("");
859
+ const [activeFilterId, setActiveFilterId] = useState4(defaultFilterId ?? filters[0]?.id ?? "all");
860
+ const activeSessions = useNavbarSessions(projectId);
861
+ const sessionsById = useMemo3(
862
+ () => new Map(activeSessions.map((session) => [session.sessionId, session])),
863
+ [activeSessions]
864
+ );
865
+ const orderedItems = useMemo3(
866
+ () => sortItems(items, sessionsById),
867
+ [items, sessionsById]
868
+ );
869
+ const visibleItems = useMemo3(() => {
870
+ const normalizedQuery = query.trim().toLowerCase();
871
+ const selectedFilter = filters.find((filter) => filter.id === activeFilterId) ?? null;
872
+ return orderedItems.filter((item) => {
873
+ const session = sessionsById.get(item.id) ?? null;
874
+ const isActive = currentItemId === item.id;
875
+ if (selectedFilter && !selectedFilter.matches(item, { session, isActive })) {
876
+ return false;
877
+ }
878
+ if (!normalizedQuery) return true;
879
+ const haystack = `${item.title} ${item.subtitle ?? ""} ${item.category ?? ""} ${(item.badges ?? []).map((badge) => badge.label).join(" ")}`.toLowerCase();
880
+ return haystack.includes(normalizedQuery);
881
+ });
882
+ }, [activeFilterId, currentItemId, filters, orderedItems, query, sessionsById]);
883
+ const runningCount = activeSessions.filter((session) => session.status === "running").length;
884
+ const filterCounts = useMemo3(() => Object.fromEntries(filters.map((filter) => [
885
+ filter.id,
886
+ orderedItems.filter((item) => filter.matches(item, {
887
+ session: sessionsById.get(item.id) ?? null,
888
+ isActive: currentItemId === item.id
889
+ })).length
890
+ ])), [currentItemId, filters, orderedItems, sessionsById]);
891
+ return /* @__PURE__ */ jsxs7("aside", { className: cn("flex w-72 shrink-0 flex-col border-r border-[var(--border-subtle)] bg-[radial-gradient(circle_at_top,rgba(96,165,250,0.12),transparent_26%),var(--bg-card)]/94 backdrop-blur-xl", className), children: [
892
+ /* @__PURE__ */ jsxs7("div", { className: "border-b border-[var(--border-subtle)] px-4 py-4", children: [
893
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
894
+ /* @__PURE__ */ jsx7("div", { className: "flex h-11 w-11 items-center justify-center rounded-2xl border border-[var(--border-subtle)] bg-[linear-gradient(135deg,rgba(82,164,255,0.22),rgba(82,164,255,0.08))] text-[var(--accent-text)] shadow-[var(--shadow-accent)]", children: /* @__PURE__ */ jsx7(MessageSquareText, { className: "h-4 w-4" }) }),
895
+ /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
896
+ /* @__PURE__ */ jsx7("div", { className: "truncate text-sm font-semibold tracking-[0.01em] text-[var(--text-primary)]", children: title }),
897
+ subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-xs text-[var(--text-muted)]", children: subtitle })
898
+ ] })
899
+ ] }),
900
+ /* @__PURE__ */ jsxs7("div", { className: "mt-4 grid grid-cols-2 gap-2", children: [
901
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] px-3 py-2", children: [
902
+ /* @__PURE__ */ jsx7("div", { className: "text-[10px] font-semibold uppercase tracking-[0.16em] text-[var(--text-muted)]", children: "Tracked" }),
903
+ /* @__PURE__ */ jsx7("div", { className: "mt-1 text-sm font-semibold text-[var(--text-primary)]", children: items.length })
904
+ ] }),
905
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] px-3 py-2", children: [
906
+ /* @__PURE__ */ jsx7("div", { className: "text-[10px] font-semibold uppercase tracking-[0.16em] text-[var(--text-muted)]", children: "Running" }),
907
+ /* @__PURE__ */ jsx7("div", { className: "mt-1 text-sm font-semibold text-[var(--text-primary)]", children: runningCount })
908
+ ] })
909
+ ] }),
910
+ /* @__PURE__ */ jsxs7(
911
+ Button,
912
+ {
913
+ type: "button",
914
+ onClick: onCreate,
915
+ className: "mt-4 w-full justify-center gap-2 rounded-xl bg-[linear-gradient(135deg,var(--brand-cool),var(--brand-glow))] text-white shadow-[var(--shadow-accent)] hover:translate-y-[-1px] hover:brightness-105",
916
+ children: [
917
+ /* @__PURE__ */ jsx7(Plus, { className: "h-4 w-4" }),
918
+ createLabel
919
+ ]
920
+ }
921
+ ),
922
+ enableSearch && items.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "relative mt-3", children: [
923
+ /* @__PURE__ */ jsx7(Search2, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--text-dim)]" }),
924
+ /* @__PURE__ */ jsx7(
925
+ "input",
926
+ {
927
+ value: query,
928
+ onChange: (event) => setQuery(event.target.value),
929
+ placeholder: searchPlaceholder,
930
+ "aria-label": searchPlaceholder,
931
+ className: "h-10 w-full rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] pl-9 pr-3 text-sm text-[var(--text-primary)] placeholder:text-[var(--text-dim)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand-cool)]/45"
932
+ }
933
+ )
934
+ ] }),
935
+ filters.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mt-3 flex flex-wrap gap-2", children: filters.map((filter) => {
936
+ const isSelected = activeFilterId === filter.id;
937
+ return /* @__PURE__ */ jsxs7(
938
+ "button",
939
+ {
940
+ type: "button",
941
+ onClick: () => setActiveFilterId(filter.id),
942
+ className: cn(
943
+ "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors",
944
+ isSelected ? "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-muted)] hover:text-[var(--text-primary)]"
945
+ ),
946
+ children: [
947
+ /* @__PURE__ */ jsx7("span", { children: filter.label }),
948
+ /* @__PURE__ */ jsx7("span", { className: "rounded-full bg-[var(--bg-card)] px-1.5 py-0.5 text-[10px] text-[var(--text-secondary)]", children: filterCounts[filter.id] ?? 0 })
949
+ ]
950
+ },
951
+ filter.id
952
+ );
953
+ }) })
954
+ ] }),
955
+ /* @__PURE__ */ jsx7("nav", { "aria-label": "Sessions", className: "flex-1 overflow-y-auto px-3 py-3", children: visibleItems.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "rounded-[var(--radius-lg)] border border-dashed border-[var(--border-subtle)] bg-[var(--bg-section)] px-4 py-5 text-sm text-[var(--text-muted)]", children: query.trim() ? `No sessions match "${query.trim()}".` : emptyMessage }) : /* @__PURE__ */ jsx7("ul", { className: "space-y-1.5", children: visibleItems.map((item) => {
956
+ const session = sessionsById.get(item.id) ?? null;
957
+ const isActive = currentItemId === item.id;
958
+ const status = session?.status ?? item.status;
959
+ const visibleBadges = [
960
+ ...item.isPinned ? [{ id: `${item.id}-pinned`, label: "Pinned", tone: "accent" }] : [],
961
+ ...item.badges ?? []
962
+ ];
963
+ return /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsxs7(
964
+ "div",
965
+ {
966
+ className: cn(
967
+ "group flex items-start gap-2 rounded-[calc(var(--radius-lg)+2px)] border px-2 py-2 transition-colors backdrop-blur-sm",
968
+ isActive ? "border-[var(--border-accent)] bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.16),transparent_40%),var(--accent-surface-soft)] shadow-[var(--shadow-card)]" : "border-transparent bg-transparent hover:border-[var(--border-subtle)] hover:bg-[linear-gradient(180deg,rgba(255,255,255,0.03),transparent)]"
969
+ ),
970
+ children: [
971
+ /* @__PURE__ */ jsxs7(
972
+ "button",
973
+ {
974
+ type: "button",
975
+ onClick: () => {
976
+ if (onSelectItem) {
977
+ onSelectItem(item);
978
+ return;
979
+ }
980
+ navigateToHref(item.href);
981
+ },
982
+ "aria-current": isActive ? "page" : void 0,
983
+ className: "min-w-0 flex flex-1 items-start gap-3 rounded-[var(--radius-lg)] px-1 py-1 text-left",
984
+ children: [
985
+ /* @__PURE__ */ jsx7("span", { className: cn("mt-1 h-2.5 w-2.5 shrink-0 rounded-full", statusClasses(status)) }),
986
+ /* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
987
+ /* @__PURE__ */ jsx7("div", { className: "truncate text-sm font-medium text-[var(--text-primary)]", children: item.title }),
988
+ item.subtitle && /* @__PURE__ */ jsx7("div", { className: "mt-0.5 truncate text-xs text-[var(--text-muted)]", children: item.subtitle }),
989
+ visibleBadges.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: visibleBadges.map((badge) => /* @__PURE__ */ jsx7(
990
+ "span",
991
+ {
992
+ className: cn(
993
+ "inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.08em]",
994
+ badgeClasses(badge.tone)
995
+ ),
996
+ children: badge.label
997
+ },
998
+ badge.id
999
+ )) })
1000
+ ] })
1001
+ ]
1002
+ }
1003
+ ),
1004
+ /* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-2", children: [
1005
+ session?.isForeground && /* @__PURE__ */ jsx7(Badge, { className: "rounded-full border-[var(--border-subtle)] bg-[var(--bg-section)] text-[10px] uppercase tracking-[0.14em] text-[var(--text-secondary)]", children: "Live" }),
1006
+ renderItemActions ? /* @__PURE__ */ jsx7(
1007
+ "div",
1008
+ {
1009
+ className: "opacity-70 transition-opacity hover:opacity-100 group-hover:opacity-100",
1010
+ onClick: (event) => event.stopPropagation(),
1011
+ children: renderItemActions(item, {
1012
+ session,
1013
+ isActive
1014
+ })
1015
+ }
1016
+ ) : null
1017
+ ] })
1018
+ ]
1019
+ }
1020
+ ) }, item.id);
1021
+ }) }) }),
1022
+ activityMonitor && /* @__PURE__ */ jsx7("div", { className: "border-t border-[var(--border-subtle)] px-3 py-3", children: activityMonitor }),
1023
+ links.length > 0 && /* @__PURE__ */ jsx7("nav", { "aria-label": "Workspace sections", className: "border-t border-[var(--border-subtle)] px-3 py-3", children: /* @__PURE__ */ jsx7("div", { className: "space-y-1", children: links.map((link) => {
1024
+ const Icon = iconForLink(link.icon);
1025
+ return /* @__PURE__ */ jsxs7(
1026
+ "button",
1027
+ {
1028
+ type: "button",
1029
+ onClick: () => {
1030
+ if (onSelectLink) {
1031
+ onSelectLink(link);
1032
+ return;
1033
+ }
1034
+ navigateToHref(link.href);
1035
+ },
1036
+ className: "flex w-full items-center gap-2 rounded-[var(--radius-md)] px-3 py-2 text-left text-sm text-[var(--text-secondary)] transition-colors hover:bg-[var(--bg-section)] hover:text-[var(--text-primary)]",
1037
+ children: [
1038
+ /* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4 shrink-0" }),
1039
+ /* @__PURE__ */ jsx7("span", { className: "truncate", children: link.label })
1040
+ ]
1041
+ },
1042
+ link.id
1043
+ );
1044
+ }) }) })
1045
+ ] });
1046
+ }
1047
+
1048
+ // src/workspace/session-activity-monitor.tsx
1049
+ import { Activity, AlertCircle as AlertCircle2, LoaderCircle, MessageSquareText as MessageSquareText2 } from "lucide-react";
1050
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1051
+ function SessionStatusDot({ session }) {
1052
+ if (session.status === "error") {
1053
+ return /* @__PURE__ */ jsx8(AlertCircle2, { className: "h-3.5 w-3.5 text-[var(--status-danger)]" });
1054
+ }
1055
+ if (session.status === "running") {
1056
+ return /* @__PURE__ */ jsx8(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin text-[var(--brand-cool)]" });
1057
+ }
1058
+ if (session.status === "attention-needed") {
1059
+ return /* @__PURE__ */ jsx8(Activity, { className: "h-3.5 w-3.5 text-[var(--status-warning)]" });
1060
+ }
1061
+ return /* @__PURE__ */ jsx8("span", { className: "h-2 w-2 rounded-full bg-[var(--text-dim)]" });
1062
+ }
1063
+ function navigateToSession(session) {
1064
+ if (!session.href || typeof window === "undefined") return;
1065
+ window.location.assign(session.href);
1066
+ }
1067
+ function SessionActivityMonitor({
1068
+ className,
1069
+ compact = false,
1070
+ sessionsById = {},
1071
+ emptyMessage = "No active sessions",
1072
+ resolveProjectLabel,
1073
+ onSelectSession
1074
+ }) {
1075
+ const trackedSessions = useActiveSessions();
1076
+ const projectActivity = useProjectActivity();
1077
+ const totalRunning = useTotalRunningSessions();
1078
+ const sessionLookup = Object.keys(sessionsById).length > 0 ? sessionsById : Object.fromEntries(trackedSessions.map((session) => [session.sessionId, session]));
1079
+ if (projectActivity.length === 0) {
1080
+ if (compact) return null;
1081
+ return /* @__PURE__ */ jsx8("div", { className: cn("rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[linear-gradient(180deg,rgba(255,255,255,0.04),transparent)] p-3 text-sm text-[var(--text-muted)]", className), children: emptyMessage });
1082
+ }
1083
+ return /* @__PURE__ */ jsxs8("div", { className: cn("space-y-3", className), children: [
1084
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between px-1", children: [
1085
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-[var(--text-muted)]", children: [
1086
+ /* @__PURE__ */ jsx8(Activity, { className: "h-3.5 w-3.5" }),
1087
+ "Active Sessions"
1088
+ ] }),
1089
+ totalRunning > 0 && /* @__PURE__ */ jsxs8("span", { className: "rounded-full border border-[var(--border-accent)] bg-[var(--accent-surface-soft)] px-2 py-0.5 text-[11px] font-medium text-[var(--accent-text)]", children: [
1090
+ totalRunning,
1091
+ " running"
1092
+ ] })
1093
+ ] }),
1094
+ /* @__PURE__ */ jsx8("div", { className: "space-y-2", children: projectActivity.map((project) => {
1095
+ const label = resolveProjectLabel?.(project.projectId, project.projectLabel) ?? project.projectLabel ?? String(project.projectId);
1096
+ return /* @__PURE__ */ jsxs8(
1097
+ "div",
1098
+ {
1099
+ className: "rounded-[calc(var(--radius-lg)+2px)] border border-[var(--border-subtle)] bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.12),transparent_34%),linear-gradient(180deg,rgba(255,255,255,0.04),transparent),var(--bg-card)]/96 p-3 shadow-[var(--shadow-card)]",
1100
+ children: [
1101
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
1102
+ /* @__PURE__ */ jsxs8("div", { children: [
1103
+ /* @__PURE__ */ jsx8("div", { className: "text-sm font-semibold text-[var(--text-primary)]", children: label }),
1104
+ /* @__PURE__ */ jsxs8("div", { className: "text-xs text-[var(--text-muted)]", children: [
1105
+ project.activeSessionCount,
1106
+ " tracked session",
1107
+ project.activeSessionCount === 1 ? "" : "s"
1108
+ ] })
1109
+ ] }),
1110
+ project.runningSessionIds.length > 0 && /* @__PURE__ */ jsxs8("span", { className: "rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] px-2 py-0.5 text-[11px] text-[var(--text-secondary)]", children: [
1111
+ project.runningSessionIds.length,
1112
+ " live"
1113
+ ] })
1114
+ ] }),
1115
+ !compact && project.runningSessionIds.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-3 space-y-2", children: project.runningSessionIds.map((sessionId) => {
1116
+ const session = sessionLookup[sessionId];
1117
+ if (!session) return null;
1118
+ return /* @__PURE__ */ jsxs8(
1119
+ "button",
1120
+ {
1121
+ type: "button",
1122
+ onClick: () => {
1123
+ if (onSelectSession) {
1124
+ onSelectSession(session);
1125
+ return;
1126
+ }
1127
+ navigateToSession(session);
1128
+ },
1129
+ className: "flex w-full items-center justify-between rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)] px-3 py-2 text-left transition-colors hover:border-[var(--border-accent)] hover:bg-[var(--bg-elevated)]",
1130
+ children: [
1131
+ /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 items-center gap-2", children: [
1132
+ /* @__PURE__ */ jsx8(SessionStatusDot, { session }),
1133
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1134
+ /* @__PURE__ */ jsx8("div", { className: "truncate text-sm font-medium text-[var(--text-primary)]", children: session.title ?? "Untitled Session" }),
1135
+ /* @__PURE__ */ jsx8("div", { className: "truncate text-xs text-[var(--text-muted)]", children: session.href ?? session.sessionId })
1136
+ ] })
1137
+ ] }),
1138
+ /* @__PURE__ */ jsx8(MessageSquareText2, { className: "h-4 w-4 shrink-0 text-[var(--text-dim)]" })
1139
+ ]
1140
+ },
1141
+ sessionId
1142
+ );
1143
+ }) })
1144
+ ]
1145
+ },
1146
+ String(project.projectId)
1147
+ );
1148
+ }) })
1149
+ ] });
1150
+ }
1151
+
752
1152
  // src/workspace/sandbox-workbench.tsx
753
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState4 } from "react";
1153
+ import { useEffect as useEffect3, useMemo as useMemo4, useState as useState5 } from "react";
754
1154
  import {
755
1155
  Bot,
756
1156
  Boxes,
757
1157
  FileCode2,
758
1158
  FileText as FileText2,
759
- FolderTree,
1159
+ FolderTree as FolderTree2,
760
1160
  LayoutPanelTop,
761
1161
  X as X4
762
1162
  } from "lucide-react";
763
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1163
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
764
1164
  function getArtifactTabIcon(kind) {
765
1165
  switch (kind) {
766
1166
  case "file":
@@ -785,10 +1185,10 @@ function ArtifactTabs({
785
1185
  onClose
786
1186
  }) {
787
1187
  if (artifacts.length === 0) return null;
788
- return /* @__PURE__ */ jsx7("div", { className: "flex items-center overflow-x-auto border-b border-[var(--border-subtle)] bg-[var(--bg-dark)]", children: artifacts.map((artifact) => {
1188
+ return /* @__PURE__ */ jsx9("div", { className: "flex items-center overflow-x-auto border-b border-[var(--border-subtle)] bg-[var(--bg-dark)]", children: artifacts.map((artifact) => {
789
1189
  const Icon = getArtifactTabIcon(artifact.kind);
790
1190
  const isActive = artifact.id === activeArtifactId;
791
- return /* @__PURE__ */ jsxs7(
1191
+ return /* @__PURE__ */ jsxs9(
792
1192
  "div",
793
1193
  {
794
1194
  className: cn(
@@ -796,26 +1196,26 @@ function ArtifactTabs({
796
1196
  isActive ? "border-b-2 border-b-[var(--brand-cool)] bg-[var(--bg-card)] text-[var(--text-primary)]" : "text-[var(--text-muted)] hover:bg-[var(--bg-elevated)]"
797
1197
  ),
798
1198
  children: [
799
- /* @__PURE__ */ jsxs7(
1199
+ /* @__PURE__ */ jsxs9(
800
1200
  "button",
801
1201
  {
802
1202
  type: "button",
803
1203
  onClick: () => onSelect(artifact.id),
804
1204
  className: "flex min-w-0 items-center gap-2 px-3 py-2 text-xs transition-colors hover:text-[var(--text-secondary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--brand-cool)]/60",
805
1205
  children: [
806
- /* @__PURE__ */ jsx7(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
807
- /* @__PURE__ */ jsx7("span", { className: "max-w-[14rem] truncate", children: artifactTabLabel(artifact) })
1206
+ /* @__PURE__ */ jsx9(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
1207
+ /* @__PURE__ */ jsx9("span", { className: "max-w-[14rem] truncate", children: artifactTabLabel(artifact) })
808
1208
  ]
809
1209
  }
810
1210
  ),
811
- onClose && /* @__PURE__ */ jsx7(
1211
+ onClose && /* @__PURE__ */ jsx9(
812
1212
  "button",
813
1213
  {
814
1214
  type: "button",
815
1215
  "aria-label": `Close ${artifactTabLabel(artifact)}`,
816
1216
  onClick: () => onClose(artifact.id),
817
1217
  className: "mr-1 rounded p-1 opacity-0 transition-opacity hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)] focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand-cool)]/60 group-hover:opacity-100",
818
- children: /* @__PURE__ */ jsx7(X4, { className: "h-3 w-3" })
1218
+ children: /* @__PURE__ */ jsx9(X4, { className: "h-3 w-3" })
819
1219
  }
820
1220
  )
821
1221
  ]
@@ -827,7 +1227,7 @@ function ArtifactTabs({
827
1227
  function renderArtifact(artifact) {
828
1228
  switch (artifact.kind) {
829
1229
  case "file":
830
- return /* @__PURE__ */ jsx7(
1230
+ return /* @__PURE__ */ jsx9(
831
1231
  FileArtifactPane,
832
1232
  {
833
1233
  path: artifact.path,
@@ -847,7 +1247,7 @@ function renderArtifact(artifact) {
847
1247
  }
848
1248
  );
849
1249
  case "markdown":
850
- return /* @__PURE__ */ jsx7(
1250
+ return /* @__PURE__ */ jsx9(
851
1251
  ArtifactPane,
852
1252
  {
853
1253
  eyebrow: artifact.eyebrow ?? "Document",
@@ -857,11 +1257,11 @@ function renderArtifact(artifact) {
857
1257
  headerActions: artifact.headerActions,
858
1258
  toolbar: artifact.toolbar,
859
1259
  footer: artifact.footer,
860
- children: /* @__PURE__ */ jsx7("div", { className: "p-5", children: /* @__PURE__ */ jsx7(Markdown, { className: "prose-sm max-w-none", children: artifact.content }) })
1260
+ children: /* @__PURE__ */ jsx9("div", { className: "p-5", children: /* @__PURE__ */ jsx9(Markdown, { className: "prose-sm max-w-none", children: artifact.content }) })
861
1261
  }
862
1262
  );
863
1263
  case "openui":
864
- return /* @__PURE__ */ jsx7(
1264
+ return /* @__PURE__ */ jsx9(
865
1265
  ArtifactPane,
866
1266
  {
867
1267
  eyebrow: artifact.eyebrow ?? "Structured Artifact",
@@ -871,11 +1271,11 @@ function renderArtifact(artifact) {
871
1271
  headerActions: artifact.headerActions,
872
1272
  toolbar: artifact.toolbar,
873
1273
  footer: artifact.footer,
874
- children: /* @__PURE__ */ jsx7(OpenUIArtifactRenderer, { schema: artifact.schema, onAction: artifact.onAction })
1274
+ children: /* @__PURE__ */ jsx9(OpenUIArtifactRenderer, { schema: artifact.schema, onAction: artifact.onAction })
875
1275
  }
876
1276
  );
877
1277
  case "custom":
878
- return /* @__PURE__ */ jsx7(
1278
+ return /* @__PURE__ */ jsx9(
879
1279
  ArtifactPane,
880
1280
  {
881
1281
  eyebrow: artifact.eyebrow ?? "Artifact",
@@ -890,6 +1290,44 @@ function renderArtifact(artifact) {
890
1290
  );
891
1291
  }
892
1292
  }
1293
+ function regionHeader(sections, fallback) {
1294
+ if (sections.length !== 1) {
1295
+ return fallback;
1296
+ }
1297
+ switch (sections[0]?.key) {
1298
+ case "directory":
1299
+ return /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: [
1300
+ /* @__PURE__ */ jsx9(FolderTree2, { className: "h-3.5 w-3.5" }),
1301
+ "Directory"
1302
+ ] });
1303
+ case "artifacts":
1304
+ return /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: [
1305
+ /* @__PURE__ */ jsx9(LayoutPanelTop, { className: "h-3.5 w-3.5" }),
1306
+ "Artifacts"
1307
+ ] });
1308
+ case "runtime":
1309
+ return /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: [
1310
+ /* @__PURE__ */ jsx9(Bot, { className: "h-3.5 w-3.5" }),
1311
+ "Runtime"
1312
+ ] });
1313
+ default:
1314
+ return fallback;
1315
+ }
1316
+ }
1317
+ function renderRegion(sections, region) {
1318
+ if (sections.length === 0) return void 0;
1319
+ if (sections.length === 1) return sections[0]?.content;
1320
+ return /* @__PURE__ */ jsx9(
1321
+ "div",
1322
+ {
1323
+ className: cn(
1324
+ "flex min-h-0 h-full gap-3 p-3",
1325
+ region === "bottom" ? "flex-col" : "flex-col"
1326
+ ),
1327
+ children: sections.map((section) => /* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-hidden", children: section.content }, section.key))
1328
+ }
1329
+ );
1330
+ }
893
1331
  function SandboxWorkbench({
894
1332
  title = "Sandbox session",
895
1333
  subtitle,
@@ -905,7 +1343,7 @@ function SandboxWorkbench({
905
1343
  emptyArtifactState,
906
1344
  className
907
1345
  }) {
908
- const [uncontrolledArtifactId, setUncontrolledArtifactId] = useState4(
1346
+ const [uncontrolledArtifactId, setUncontrolledArtifactId] = useState5(
909
1347
  activeArtifactId ?? artifacts[0]?.id
910
1348
  );
911
1349
  useEffect3(() => {
@@ -917,7 +1355,7 @@ function SandboxWorkbench({
917
1355
  });
918
1356
  }, [activeArtifactId, artifacts]);
919
1357
  const resolvedArtifactId = activeArtifactId ?? uncontrolledArtifactId;
920
- const activeArtifact = useMemo3(
1358
+ const activeArtifact = useMemo4(
921
1359
  () => artifacts.find((artifact) => artifact.id === resolvedArtifactId),
922
1360
  [artifacts, resolvedArtifactId]
923
1361
  );
@@ -927,21 +1365,21 @@ function SandboxWorkbench({
927
1365
  }
928
1366
  onArtifactChange?.(artifactId);
929
1367
  };
930
- const centerHeader = /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 items-start justify-between gap-4 rounded-[var(--radius-xl)] border border-[var(--border-subtle)] bg-[linear-gradient(135deg,rgba(98,114,243,0.12),rgba(255,255,255,0.02)_38%,transparent_72%)] px-4 py-3 shadow-[var(--shadow-card)]", children: [
931
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
932
- /* @__PURE__ */ jsx7("div", { className: "text-[10px] font-semibold uppercase tracking-[0.18em] text-[var(--brand-cool)]", children: "Tangle Sandbox" }),
933
- /* @__PURE__ */ jsx7("div", { className: "truncate text-base font-semibold text-[var(--text-primary)]", children: title }),
934
- subtitle && /* @__PURE__ */ jsx7("div", { className: "truncate text-sm text-[var(--text-muted)]", children: subtitle })
1368
+ const centerHeader = /* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 items-start justify-between gap-4 rounded-[calc(var(--radius-xl)+2px)] border border-[var(--border-subtle)] bg-[radial-gradient(circle_at_top_left,rgba(96,165,250,0.16),transparent_34%),linear-gradient(135deg,rgba(98,114,243,0.14),rgba(255,255,255,0.03)_42%,transparent_76%)] px-4 py-3.5 shadow-[var(--shadow-accent)] backdrop-blur-sm", children: [
1369
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
1370
+ /* @__PURE__ */ jsx9("div", { className: "text-[10px] font-semibold uppercase tracking-[0.18em] text-[var(--brand-cool)]", children: "Tangle Sandbox" }),
1371
+ /* @__PURE__ */ jsx9("div", { className: "truncate text-[17px] font-semibold tracking-[0.01em] text-[var(--text-primary)]", children: title }),
1372
+ subtitle && /* @__PURE__ */ jsx9("div", { className: "truncate text-sm text-[var(--text-muted)]", children: subtitle })
935
1373
  ] }),
936
- /* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 flex-wrap items-center justify-end gap-2", children: [
1374
+ /* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 flex-wrap items-center justify-end gap-2", children: [
937
1375
  status,
938
- artifacts.length > 0 && /* @__PURE__ */ jsxs7(Badge, { variant: "outline", children: [
1376
+ artifacts.length > 0 && /* @__PURE__ */ jsxs9(Badge, { variant: "outline", children: [
939
1377
  artifacts.length,
940
1378
  " artifacts"
941
1379
  ] })
942
1380
  ] })
943
1381
  ] });
944
- const center = /* @__PURE__ */ jsx7(
1382
+ const center = /* @__PURE__ */ jsx9(
945
1383
  ArtifactPane,
946
1384
  {
947
1385
  eyebrow: session.eyebrow ?? "Agent Session",
@@ -951,7 +1389,7 @@ function SandboxWorkbench({
951
1389
  headerActions: session.headerActions,
952
1390
  className: "h-full",
953
1391
  contentClassName: "bg-[radial-gradient(circle_at_top,rgba(82,164,255,0.1),transparent_34%),linear-gradient(180deg,rgba(255,255,255,0.02),transparent_22%)]",
954
- children: /* @__PURE__ */ jsx7(
1392
+ children: /* @__PURE__ */ jsx9(
955
1393
  ChatContainer,
956
1394
  {
957
1395
  ...session,
@@ -961,8 +1399,8 @@ function SandboxWorkbench({
961
1399
  )
962
1400
  }
963
1401
  );
964
- const right = artifacts.length > 0 ? /* @__PURE__ */ jsxs7("section", { className: "flex h-full min-h-0 flex-col bg-[var(--bg-dark)]", children: [
965
- /* @__PURE__ */ jsx7(
1402
+ const artifactPanel = artifacts.length > 0 ? /* @__PURE__ */ jsxs9("section", { className: "flex h-full min-h-0 flex-col bg-[var(--bg-dark)]", children: [
1403
+ /* @__PURE__ */ jsx9(
966
1404
  ArtifactTabs,
967
1405
  {
968
1406
  artifacts,
@@ -971,37 +1409,62 @@ function SandboxWorkbench({
971
1409
  onClose: onArtifactClose
972
1410
  }
973
1411
  ),
974
- /* @__PURE__ */ jsx7("div", { className: "min-h-0 flex-1 overflow-auto bg-[linear-gradient(180deg,rgba(255,255,255,0.02),transparent)]", children: activeArtifact ? renderArtifact(activeArtifact) : /* @__PURE__ */ jsx7("div", { className: "flex h-full items-center justify-center p-6", children: emptyArtifactState ?? /* @__PURE__ */ jsx7(
1412
+ /* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-auto bg-[linear-gradient(180deg,rgba(255,255,255,0.02),transparent)]", children: activeArtifact ? renderArtifact(activeArtifact) : /* @__PURE__ */ jsx9("div", { className: "flex h-full items-center justify-center p-6", children: emptyArtifactState ?? /* @__PURE__ */ jsx9(
975
1413
  EmptyState,
976
1414
  {
977
- icon: /* @__PURE__ */ jsx7(Boxes, { className: "h-8 w-8" }),
1415
+ icon: /* @__PURE__ */ jsx9(Boxes, { className: "h-8 w-8" }),
978
1416
  title: "No artifact selected",
979
1417
  description: "Select a generated artifact, file preview, or OpenUI panel to inspect it here."
980
1418
  }
981
1419
  ) }) })
982
1420
  ] }) : null;
983
- return /* @__PURE__ */ jsx7(
1421
+ const directoryPlacement = layout?.directoryPlacement ?? (directory ? "left" : "hidden");
1422
+ const artifactPlacement = layout?.artifactPlacement ?? (artifacts.length > 0 ? "right" : "hidden");
1423
+ const runtimePlacement = layout?.runtimePlacement ?? (runtime ? "bottom" : "hidden");
1424
+ const regionSections = {
1425
+ left: [],
1426
+ right: [],
1427
+ bottom: []
1428
+ };
1429
+ if (directory && directoryPlacement !== "hidden") {
1430
+ regionSections[directoryPlacement].push({
1431
+ key: "directory",
1432
+ content: /* @__PURE__ */ jsx9(DirectoryPane, { ...directory, className: "h-full" })
1433
+ });
1434
+ }
1435
+ if (artifactPanel && artifactPlacement !== "hidden") {
1436
+ regionSections[artifactPlacement].push({
1437
+ key: "artifacts",
1438
+ content: artifactPanel
1439
+ });
1440
+ }
1441
+ if (runtime && runtimePlacement !== "hidden") {
1442
+ regionSections[runtimePlacement].push({
1443
+ key: "runtime",
1444
+ content: /* @__PURE__ */ jsx9(RuntimePane, { ...runtime, className: "h-full" })
1445
+ });
1446
+ }
1447
+ const left = renderRegion(regionSections.left, "left");
1448
+ const right = renderRegion(regionSections.right, "right");
1449
+ const bottom = renderRegion(regionSections.bottom, "bottom");
1450
+ const genericPanelsHeader = /* @__PURE__ */ jsx9("span", { className: "text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: "Workspace Panels" });
1451
+ return /* @__PURE__ */ jsx9(
984
1452
  WorkspaceLayout,
985
1453
  {
986
- left: directory ? /* @__PURE__ */ jsx7(DirectoryPane, { ...directory, className: "h-full" }) : void 0,
987
- leftHeader: directory ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: [
988
- /* @__PURE__ */ jsx7(FolderTree, { className: "h-3.5 w-3.5" }),
989
- "Directory"
990
- ] }) : void 0,
1454
+ left,
1455
+ leftHeader: left ? regionHeader(regionSections.left, genericPanelsHeader) : void 0,
991
1456
  center,
992
1457
  centerHeader,
993
1458
  right,
994
- rightHeader: right ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-muted)]", children: [
995
- /* @__PURE__ */ jsx7(LayoutPanelTop, { className: "h-3.5 w-3.5" }),
996
- "Artifacts"
997
- ] }) : void 0,
998
- bottom: runtime ? /* @__PURE__ */ jsx7(RuntimePane, { ...runtime, className: "h-full" }) : void 0,
1459
+ rightHeader: right ? regionHeader(regionSections.right, genericPanelsHeader) : void 0,
1460
+ bottom,
1461
+ bottomHeader: bottom ? regionHeader(regionSections.bottom, genericPanelsHeader) : void 0,
999
1462
  theme: layout?.theme ?? "operator",
1000
1463
  density: layout?.density ?? "comfortable",
1001
1464
  persistenceKey: layout?.persistenceKey,
1002
- defaultLeftOpen: layout?.defaultLeftOpen ?? Boolean(directory),
1003
- defaultRightOpen: layout?.defaultRightOpen ?? artifacts.length > 0,
1004
- defaultBottomOpen: layout?.defaultBottomOpen ?? Boolean(runtime),
1465
+ defaultLeftOpen: layout?.defaultLeftOpen ?? Boolean(left),
1466
+ defaultRightOpen: layout?.defaultRightOpen ?? Boolean(right),
1467
+ defaultBottomOpen: layout?.defaultBottomOpen ?? Boolean(bottom),
1005
1468
  defaultLeftWidth: layout?.defaultLeftWidth,
1006
1469
  defaultRightWidth: layout?.defaultRightWidth,
1007
1470
  minLeftWidth: layout?.minLeftWidth,
@@ -1014,15 +1477,15 @@ function SandboxWorkbench({
1014
1477
  );
1015
1478
  }
1016
1479
  function AgentWorkbench(props) {
1017
- return /* @__PURE__ */ jsx7(
1480
+ return /* @__PURE__ */ jsx9(
1018
1481
  SandboxWorkbench,
1019
1482
  {
1020
1483
  ...props,
1021
1484
  session: {
1022
1485
  ...props.session,
1023
1486
  eyebrow: props.session.eyebrow ?? "Agent Session",
1024
- title: props.session.title ?? /* @__PURE__ */ jsxs7("span", { className: "inline-flex items-center gap-2", children: [
1025
- /* @__PURE__ */ jsx7(Bot, { className: "h-4 w-4 text-[var(--brand-cool)]" }),
1487
+ title: props.session.title ?? /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-2", children: [
1488
+ /* @__PURE__ */ jsx9(Bot, { className: "h-4 w-4 text-[var(--brand-cool)]" }),
1026
1489
  "Execution timeline"
1027
1490
  ] })
1028
1491
  }
@@ -1031,65 +1494,65 @@ function AgentWorkbench(props) {
1031
1494
  }
1032
1495
 
1033
1496
  // src/workspace/audit-results.tsx
1034
- import { useState as useState5 } from "react";
1497
+ import { useState as useState6 } from "react";
1035
1498
  import { CheckCircle as CheckCircle2, XCircle, ChevronRight, Shield } from "lucide-react";
1036
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1499
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1037
1500
  function AuditResults({ forms, crossFormChecks = [], overallScore, className }) {
1038
1501
  const totalPassed = forms.reduce((s, f) => s + f.passed, 0);
1039
1502
  const totalChecks = forms.reduce((s, f) => s + f.passed + f.failed, 0);
1040
- return /* @__PURE__ */ jsxs8("div", { className: cn("space-y-3 p-3", className), children: [
1041
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 px-3 py-2 rounded-[var(--radius-md)] bg-[var(--bg-input)] border border-[var(--border-subtle)]", children: [
1042
- /* @__PURE__ */ jsx8(Shield, { className: cn("h-5 w-5", totalChecks === totalPassed ? "text-[var(--code-success)]" : "text-[var(--code-number)]") }),
1043
- /* @__PURE__ */ jsxs8("div", { children: [
1044
- /* @__PURE__ */ jsxs8("div", { className: "text-sm font-semibold text-[var(--text-primary)]", children: [
1503
+ return /* @__PURE__ */ jsxs10("div", { className: cn("space-y-3 p-3", className), children: [
1504
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-3 px-3 py-2 rounded-[var(--radius-md)] bg-[var(--bg-input)] border border-[var(--border-subtle)]", children: [
1505
+ /* @__PURE__ */ jsx10(Shield, { className: cn("h-5 w-5", totalChecks === totalPassed ? "text-[var(--code-success)]" : "text-[var(--code-number)]") }),
1506
+ /* @__PURE__ */ jsxs10("div", { children: [
1507
+ /* @__PURE__ */ jsxs10("div", { className: "text-sm font-semibold text-[var(--text-primary)]", children: [
1045
1508
  totalPassed,
1046
1509
  "/",
1047
1510
  totalChecks,
1048
1511
  " checks passed"
1049
1512
  ] }),
1050
- overallScore !== void 0 && /* @__PURE__ */ jsxs8("div", { className: "text-xs text-[var(--text-muted)]", children: [
1513
+ overallScore !== void 0 && /* @__PURE__ */ jsxs10("div", { className: "text-xs text-[var(--text-muted)]", children: [
1051
1514
  "Score: ",
1052
1515
  overallScore,
1053
1516
  "/100"
1054
1517
  ] })
1055
1518
  ] })
1056
1519
  ] }),
1057
- forms.map((form) => /* @__PURE__ */ jsx8(FormAuditCard, { form }, form.formId)),
1058
- crossFormChecks.length > 0 && /* @__PURE__ */ jsxs8("div", { children: [
1059
- /* @__PURE__ */ jsx8("div", { className: "text-xs font-semibold text-[var(--text-muted)] uppercase tracking-wider mb-1", children: "Cross-Form Checks" }),
1060
- crossFormChecks.map((check, i) => /* @__PURE__ */ jsx8(CheckRow, { check }, i))
1520
+ forms.map((form) => /* @__PURE__ */ jsx10(FormAuditCard, { form }, form.formId)),
1521
+ crossFormChecks.length > 0 && /* @__PURE__ */ jsxs10("div", { children: [
1522
+ /* @__PURE__ */ jsx10("div", { className: "text-xs font-semibold text-[var(--text-muted)] uppercase tracking-wider mb-1", children: "Cross-Form Checks" }),
1523
+ crossFormChecks.map((check, i) => /* @__PURE__ */ jsx10(CheckRow, { check }, i))
1061
1524
  ] })
1062
1525
  ] });
1063
1526
  }
1064
1527
  function FormAuditCard({ form }) {
1065
- const [expanded, setExpanded] = useState5(form.failed > 0);
1528
+ const [expanded, setExpanded] = useState6(form.failed > 0);
1066
1529
  const allPassed = form.failed === 0 && form.found;
1067
- return /* @__PURE__ */ jsxs8("div", { className: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] overflow-hidden", children: [
1068
- /* @__PURE__ */ jsxs8(
1530
+ return /* @__PURE__ */ jsxs10("div", { className: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] overflow-hidden", children: [
1531
+ /* @__PURE__ */ jsxs10(
1069
1532
  "button",
1070
1533
  {
1071
1534
  onClick: () => setExpanded(!expanded),
1072
1535
  className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-[var(--bg-hover)] transition-colors",
1073
1536
  children: [
1074
- allPassed ? /* @__PURE__ */ jsx8(CheckCircle2, { className: "h-4 w-4 text-[var(--code-success)] shrink-0" }) : !form.found ? /* @__PURE__ */ jsx8(XCircle, { className: "h-4 w-4 text-[var(--code-error)] shrink-0" }) : /* @__PURE__ */ jsx8(XCircle, { className: "h-4 w-4 text-[var(--code-number)] shrink-0" }),
1075
- /* @__PURE__ */ jsx8("span", { className: "text-sm font-medium text-[var(--text-primary)] flex-1", children: form.formName || form.formId }),
1076
- /* @__PURE__ */ jsxs8("span", { className: cn("text-xs tabular-nums", allPassed ? "text-[var(--code-success)]" : "text-[var(--text-muted)]"), children: [
1537
+ allPassed ? /* @__PURE__ */ jsx10(CheckCircle2, { className: "h-4 w-4 text-[var(--code-success)] shrink-0" }) : !form.found ? /* @__PURE__ */ jsx10(XCircle, { className: "h-4 w-4 text-[var(--code-error)] shrink-0" }) : /* @__PURE__ */ jsx10(XCircle, { className: "h-4 w-4 text-[var(--code-number)] shrink-0" }),
1538
+ /* @__PURE__ */ jsx10("span", { className: "text-sm font-medium text-[var(--text-primary)] flex-1", children: form.formName || form.formId }),
1539
+ /* @__PURE__ */ jsxs10("span", { className: cn("text-xs tabular-nums", allPassed ? "text-[var(--code-success)]" : "text-[var(--text-muted)]"), children: [
1077
1540
  form.passed,
1078
1541
  "/",
1079
1542
  form.passed + form.failed
1080
1543
  ] }),
1081
- /* @__PURE__ */ jsx8(ChevronRight, { className: cn("h-3 w-3 text-[var(--text-muted)] transition-transform", expanded && "rotate-90") })
1544
+ /* @__PURE__ */ jsx10(ChevronRight, { className: cn("h-3 w-3 text-[var(--text-muted)] transition-transform", expanded && "rotate-90") })
1082
1545
  ]
1083
1546
  }
1084
1547
  ),
1085
- expanded && /* @__PURE__ */ jsx8("div", { className: "border-t border-[var(--border-subtle)] px-3 py-1.5 space-y-0.5", children: form.checks.map((check, i) => /* @__PURE__ */ jsx8(CheckRow, { check }, i)) })
1548
+ expanded && /* @__PURE__ */ jsx10("div", { className: "border-t border-[var(--border-subtle)] px-3 py-1.5 space-y-0.5", children: form.checks.map((check, i) => /* @__PURE__ */ jsx10(CheckRow, { check }, i)) })
1086
1549
  ] });
1087
1550
  }
1088
1551
  function CheckRow({ check }) {
1089
- return /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
1090
- check.passed ? /* @__PURE__ */ jsx8(CheckCircle2, { className: "h-3 w-3 text-[var(--code-success)] shrink-0" }) : /* @__PURE__ */ jsx8(XCircle, { className: "h-3 w-3 text-[var(--code-error)] shrink-0" }),
1091
- /* @__PURE__ */ jsx8("span", { className: "text-[var(--text-secondary)] flex-1 truncate", children: check.label }),
1092
- /* @__PURE__ */ jsx8("span", { className: "text-[var(--text-muted)] tabular-nums shrink-0", children: check.passed ? String(check.actual ?? check.expected) : `${check.actual ?? "missing"} \u2260 ${check.expected}` })
1552
+ return /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
1553
+ check.passed ? /* @__PURE__ */ jsx10(CheckCircle2, { className: "h-3 w-3 text-[var(--code-success)] shrink-0" }) : /* @__PURE__ */ jsx10(XCircle, { className: "h-3 w-3 text-[var(--code-error)] shrink-0" }),
1554
+ /* @__PURE__ */ jsx10("span", { className: "text-[var(--text-secondary)] flex-1 truncate", children: check.label }),
1555
+ /* @__PURE__ */ jsx10("span", { className: "text-[var(--text-muted)] tabular-nums shrink-0", children: check.passed ? String(check.actual ?? check.expected) : `${check.actual ?? "missing"} \u2260 ${check.expected}` })
1093
1556
  ] });
1094
1557
  }
1095
1558
 
@@ -1100,6 +1563,8 @@ export {
1100
1563
  StatusBar,
1101
1564
  TerminalPanel,
1102
1565
  RuntimePane,
1566
+ SessionSidebar,
1567
+ SessionActivityMonitor,
1103
1568
  SandboxWorkbench,
1104
1569
  AgentWorkbench,
1105
1570
  AuditResults