@tangle-network/sandbox-ui 0.28.0 → 0.29.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.
- package/dist/{chunk-I3IVCGND.js → chunk-AUFV7766.js} +118 -26
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -2
- package/dist/workspace.d.ts +153 -3
- package/dist/workspace.js +13 -3
- package/package.json +1 -1
|
@@ -813,10 +813,69 @@ function RuntimePane({
|
|
|
813
813
|
}
|
|
814
814
|
|
|
815
815
|
// src/workspace/session-sidebar.tsx
|
|
816
|
-
import { useCallback, useMemo as useMemo3, useRef as
|
|
816
|
+
import { useCallback as useCallback2, useImperativeHandle, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
817
817
|
import { ArrowLeft, FolderTree, MessageSquareText, Plus, Search as Search2, Settings, Sparkles } from "lucide-react";
|
|
818
818
|
import { useNavbarSessions } from "@tangle-network/ui/stores";
|
|
819
|
+
|
|
820
|
+
// src/workspace/session-optimistic.ts
|
|
821
|
+
import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
822
|
+
var SESSION_CREATED_EVENT = "sandbox-thread-created";
|
|
823
|
+
function dispatchSessionCreated(detail, eventName = SESSION_CREATED_EVENT) {
|
|
824
|
+
if (typeof window === "undefined") return;
|
|
825
|
+
window.dispatchEvent(new CustomEvent(eventName, { detail }));
|
|
826
|
+
}
|
|
827
|
+
function toItem(detail) {
|
|
828
|
+
return { updatedAt: /* @__PURE__ */ new Date(), ...detail };
|
|
829
|
+
}
|
|
830
|
+
function useOptimisticSessionItems(items, options = {}) {
|
|
831
|
+
const { listenForCreate = true, eventName = SESSION_CREATED_EVENT } = options;
|
|
832
|
+
const [optimisticItems, setOptimisticItems] = useState3(items);
|
|
833
|
+
useEffect3(() => {
|
|
834
|
+
setOptimisticItems(items);
|
|
835
|
+
}, [items]);
|
|
836
|
+
const add = useCallback((detail) => {
|
|
837
|
+
const next = toItem(detail);
|
|
838
|
+
setOptimisticItems((prev) => [next, ...prev.filter((item) => item.id !== next.id)]);
|
|
839
|
+
}, []);
|
|
840
|
+
const update = useCallback((id, patch) => {
|
|
841
|
+
setOptimisticItems(
|
|
842
|
+
(prev) => prev.map((item) => item.id === id ? { ...item, ...patch } : item)
|
|
843
|
+
);
|
|
844
|
+
}, []);
|
|
845
|
+
const remove = useCallback((id) => {
|
|
846
|
+
setOptimisticItems((prev) => prev.filter((item) => item.id !== id));
|
|
847
|
+
}, []);
|
|
848
|
+
const reset = useCallback(() => setOptimisticItems(items), [items]);
|
|
849
|
+
const addRef = useRef3(add);
|
|
850
|
+
addRef.current = add;
|
|
851
|
+
useEffect3(() => {
|
|
852
|
+
if (!listenForCreate || typeof window === "undefined") return;
|
|
853
|
+
function onCreated(event) {
|
|
854
|
+
const detail = event.detail;
|
|
855
|
+
if (!detail?.id || !detail.title) return;
|
|
856
|
+
addRef.current(detail);
|
|
857
|
+
}
|
|
858
|
+
window.addEventListener(eventName, onCreated);
|
|
859
|
+
return () => window.removeEventListener(eventName, onCreated);
|
|
860
|
+
}, [listenForCreate, eventName]);
|
|
861
|
+
return {
|
|
862
|
+
items: optimisticItems,
|
|
863
|
+
controller: { add, update, remove, reset }
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// src/workspace/session-sidebar.tsx
|
|
819
868
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
869
|
+
var NO_CONTROLLER = {
|
|
870
|
+
add: () => {
|
|
871
|
+
},
|
|
872
|
+
update: () => {
|
|
873
|
+
},
|
|
874
|
+
remove: () => {
|
|
875
|
+
},
|
|
876
|
+
reset: () => {
|
|
877
|
+
}
|
|
878
|
+
};
|
|
820
879
|
function statusDot(status) {
|
|
821
880
|
switch (status) {
|
|
822
881
|
case "running":
|
|
@@ -888,24 +947,24 @@ function navigateToHref(href) {
|
|
|
888
947
|
window.location.assign(href);
|
|
889
948
|
}
|
|
890
949
|
function useResizable(defaultWidth, min, max, onChange) {
|
|
891
|
-
const [width, setWidth] =
|
|
892
|
-
const dragging =
|
|
893
|
-
const startX =
|
|
894
|
-
const startW =
|
|
895
|
-
const onPointerDown =
|
|
950
|
+
const [width, setWidth] = useState4(defaultWidth);
|
|
951
|
+
const dragging = useRef4(false);
|
|
952
|
+
const startX = useRef4(0);
|
|
953
|
+
const startW = useRef4(0);
|
|
954
|
+
const onPointerDown = useCallback2((e) => {
|
|
896
955
|
dragging.current = true;
|
|
897
956
|
startX.current = e.clientX;
|
|
898
957
|
startW.current = width;
|
|
899
958
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
900
959
|
}, [width]);
|
|
901
|
-
const onPointerMove =
|
|
960
|
+
const onPointerMove = useCallback2((e) => {
|
|
902
961
|
if (!dragging.current) return;
|
|
903
962
|
const delta = e.clientX - startX.current;
|
|
904
963
|
const next = Math.min(max, Math.max(min, startW.current + delta));
|
|
905
964
|
setWidth(next);
|
|
906
965
|
onChange?.(next);
|
|
907
966
|
}, [min, max, onChange]);
|
|
908
|
-
const onPointerUp =
|
|
967
|
+
const onPointerUp = useCallback2(() => {
|
|
909
968
|
dragging.current = false;
|
|
910
969
|
}, []);
|
|
911
970
|
return { width, onPointerDown, onPointerMove, onPointerUp };
|
|
@@ -933,18 +992,32 @@ function SessionSidebar({
|
|
|
933
992
|
minWidth = 200,
|
|
934
993
|
maxWidth = 400,
|
|
935
994
|
onWidthChange,
|
|
936
|
-
renderItemActions
|
|
995
|
+
renderItemActions,
|
|
996
|
+
optimistic = false,
|
|
997
|
+
optimisticRef
|
|
937
998
|
}) {
|
|
938
|
-
const [query, setQuery] =
|
|
939
|
-
const [activeFilterId, setActiveFilterId] =
|
|
999
|
+
const [query, setQuery] = useState4("");
|
|
1000
|
+
const [activeFilterId, setActiveFilterId] = useState4(defaultFilterId ?? filters[0]?.id ?? "all");
|
|
1001
|
+
const optimisticOptions = typeof optimistic === "object" ? optimistic : void 0;
|
|
1002
|
+
const optimisticState = useOptimisticSessionItems(
|
|
1003
|
+
items,
|
|
1004
|
+
optimistic === false ? { listenForCreate: false } : optimisticOptions
|
|
1005
|
+
);
|
|
1006
|
+
const optimisticEnabled = optimistic !== false;
|
|
1007
|
+
const effectiveItems = optimisticEnabled ? optimisticState.items : items;
|
|
1008
|
+
useImperativeHandle(
|
|
1009
|
+
optimisticRef,
|
|
1010
|
+
() => optimisticEnabled ? optimisticState.controller : NO_CONTROLLER,
|
|
1011
|
+
[optimisticEnabled, optimisticState.controller]
|
|
1012
|
+
);
|
|
940
1013
|
const activeSessions = useNavbarSessions(projectId);
|
|
941
1014
|
const sessionsById = useMemo3(
|
|
942
1015
|
() => new Map(activeSessions.map((session) => [session.sessionId, session])),
|
|
943
1016
|
[activeSessions]
|
|
944
1017
|
);
|
|
945
1018
|
const orderedItems = useMemo3(
|
|
946
|
-
() => sortItems(
|
|
947
|
-
[
|
|
1019
|
+
() => sortItems(effectiveItems, sessionsById),
|
|
1020
|
+
[effectiveItems, sessionsById]
|
|
948
1021
|
);
|
|
949
1022
|
const visibleItems = useMemo3(() => {
|
|
950
1023
|
const normalizedQuery = query.trim().toLowerCase();
|
|
@@ -998,7 +1071,7 @@ function SessionSidebar({
|
|
|
998
1071
|
] })
|
|
999
1072
|
] }) }),
|
|
1000
1073
|
(enableSearch && items.length > 0 || filters.length > 0) && /* @__PURE__ */ jsxs7("div", { className: "shrink-0 border-b border-border px-3 py-2.5", children: [
|
|
1001
|
-
enableSearch &&
|
|
1074
|
+
enableSearch && effectiveItems.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
|
|
1002
1075
|
/* @__PURE__ */ jsx7(Search2, { className: "pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
|
|
1003
1076
|
/* @__PURE__ */ jsx7(
|
|
1004
1077
|
"input",
|
|
@@ -1136,6 +1209,20 @@ function SessionSidebar({
|
|
|
1136
1209
|
);
|
|
1137
1210
|
}
|
|
1138
1211
|
|
|
1212
|
+
// src/workspace/shell-revalidation.ts
|
|
1213
|
+
function createShellShouldRevalidate(options = {}) {
|
|
1214
|
+
const appPathPrefix = options.appPathPrefix ?? "/app";
|
|
1215
|
+
return function shouldRevalidate(args) {
|
|
1216
|
+
const { currentUrl, nextUrl, formMethod, defaultShouldRevalidate } = args;
|
|
1217
|
+
if (formMethod && formMethod !== "GET") return true;
|
|
1218
|
+
if (currentUrl.pathname !== nextUrl.pathname && currentUrl.pathname.startsWith(appPathPrefix) && nextUrl.pathname.startsWith(appPathPrefix)) {
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
return defaultShouldRevalidate;
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
var shellShouldRevalidate = createShellShouldRevalidate();
|
|
1225
|
+
|
|
1139
1226
|
// src/workspace/session-activity-monitor.tsx
|
|
1140
1227
|
import { Activity, AlertCircle as AlertCircle2, LoaderCircle, MessageSquareText as MessageSquareText2 } from "lucide-react";
|
|
1141
1228
|
import {
|
|
@@ -1238,7 +1325,7 @@ function SessionActivityMonitor({
|
|
|
1238
1325
|
}
|
|
1239
1326
|
|
|
1240
1327
|
// src/workspace/sandbox-workbench.tsx
|
|
1241
|
-
import { useEffect as
|
|
1328
|
+
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState5 } from "react";
|
|
1242
1329
|
import {
|
|
1243
1330
|
Bot,
|
|
1244
1331
|
Boxes,
|
|
@@ -1438,10 +1525,10 @@ function SandboxWorkbench({
|
|
|
1438
1525
|
emptyArtifactState,
|
|
1439
1526
|
className
|
|
1440
1527
|
}) {
|
|
1441
|
-
const [uncontrolledArtifactId, setUncontrolledArtifactId] =
|
|
1528
|
+
const [uncontrolledArtifactId, setUncontrolledArtifactId] = useState5(
|
|
1442
1529
|
activeArtifactId ?? artifacts[0]?.id
|
|
1443
1530
|
);
|
|
1444
|
-
|
|
1531
|
+
useEffect4(() => {
|
|
1445
1532
|
if (activeArtifactId !== void 0) return;
|
|
1446
1533
|
setUncontrolledArtifactId((current) => {
|
|
1447
1534
|
if (artifacts.length === 0) return void 0;
|
|
@@ -1593,7 +1680,7 @@ function AgentWorkbench(props) {
|
|
|
1593
1680
|
}
|
|
1594
1681
|
|
|
1595
1682
|
// src/workspace/audit-results.tsx
|
|
1596
|
-
import { useState as
|
|
1683
|
+
import { useState as useState6 } from "react";
|
|
1597
1684
|
import { CheckCircle as CheckCircle2, XCircle, ChevronRight, Shield } from "lucide-react";
|
|
1598
1685
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1599
1686
|
function AuditResults({ forms, crossFormChecks = [], overallScore, className }) {
|
|
@@ -1624,7 +1711,7 @@ function AuditResults({ forms, crossFormChecks = [], overallScore, className })
|
|
|
1624
1711
|
] });
|
|
1625
1712
|
}
|
|
1626
1713
|
function FormAuditCard({ form }) {
|
|
1627
|
-
const [expanded, setExpanded] =
|
|
1714
|
+
const [expanded, setExpanded] = useState6(form.failed > 0);
|
|
1628
1715
|
const allPassed = form.failed === 0 && form.found;
|
|
1629
1716
|
return /* @__PURE__ */ jsxs10("div", { className: "rounded-[var(--radius-md)] border border-border overflow-hidden", children: [
|
|
1630
1717
|
/* @__PURE__ */ jsxs10(
|
|
@@ -1762,7 +1849,7 @@ function TaskBoard({
|
|
|
1762
1849
|
}
|
|
1763
1850
|
|
|
1764
1851
|
// src/workspace/calendar-view.tsx
|
|
1765
|
-
import { useState as
|
|
1852
|
+
import { useState as useState7, useMemo as useMemo6 } from "react";
|
|
1766
1853
|
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1767
1854
|
function toDateKey(d) {
|
|
1768
1855
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
@@ -1806,11 +1893,11 @@ function CalendarView({
|
|
|
1806
1893
|
}) {
|
|
1807
1894
|
const today = /* @__PURE__ */ new Date();
|
|
1808
1895
|
const todayKey = toDateKey(today);
|
|
1809
|
-
const [internalMonth, setInternalMonth] =
|
|
1896
|
+
const [internalMonth, setInternalMonth] = useState7({
|
|
1810
1897
|
year: today.getFullYear(),
|
|
1811
1898
|
month: today.getMonth()
|
|
1812
1899
|
});
|
|
1813
|
-
const [internalSelectedDay, setInternalSelectedDay] =
|
|
1900
|
+
const [internalSelectedDay, setInternalSelectedDay] = useState7(
|
|
1814
1901
|
todayKey
|
|
1815
1902
|
);
|
|
1816
1903
|
const viewYear = controlledYear ?? internalMonth.year;
|
|
@@ -1983,7 +2070,7 @@ function CalendarView({
|
|
|
1983
2070
|
}
|
|
1984
2071
|
|
|
1985
2072
|
// src/workspace/approval-queue.tsx
|
|
1986
|
-
import { useState as
|
|
2073
|
+
import { useState as useState8, useMemo as useMemo7 } from "react";
|
|
1987
2074
|
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1988
2075
|
function ApprovalQueue({
|
|
1989
2076
|
items,
|
|
@@ -1998,9 +2085,9 @@ function ApprovalQueue({
|
|
|
1998
2085
|
emptyState,
|
|
1999
2086
|
showResolved: controlledShowResolved
|
|
2000
2087
|
}) {
|
|
2001
|
-
const [rejectingId, setRejectingId] =
|
|
2002
|
-
const [rejectReason, setRejectReason] =
|
|
2003
|
-
const [showResolved, setShowResolved] =
|
|
2088
|
+
const [rejectingId, setRejectingId] = useState8(null);
|
|
2089
|
+
const [rejectReason, setRejectReason] = useState8("");
|
|
2090
|
+
const [showResolved, setShowResolved] = useState8(controlledShowResolved ?? false);
|
|
2004
2091
|
const pending = useMemo7(
|
|
2005
2092
|
() => items.filter((a) => a.status === "pending"),
|
|
2006
2093
|
[items]
|
|
@@ -2209,7 +2296,12 @@ export {
|
|
|
2209
2296
|
StatusBar,
|
|
2210
2297
|
TerminalPanel,
|
|
2211
2298
|
RuntimePane,
|
|
2299
|
+
SESSION_CREATED_EVENT,
|
|
2300
|
+
dispatchSessionCreated,
|
|
2301
|
+
useOptimisticSessionItems,
|
|
2212
2302
|
SessionSidebar,
|
|
2303
|
+
createShellShouldRevalidate,
|
|
2304
|
+
shellShouldRevalidate,
|
|
2213
2305
|
SessionActivityMonitor,
|
|
2214
2306
|
SandboxWorkbench,
|
|
2215
2307
|
AgentWorkbench,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { ArtifactPane, ArtifactPaneProps, Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Button, ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CodeBlock, CodeBlockProps, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalDisplay, TerminalCursor as TerminalDisplayCursor, TerminalInput as TerminalDisplayInput, TerminalLine as TerminalDisplayLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, buttonVariants, useTheme, useToast } from '@tangle-network/ui/primitives';
|
|
2
2
|
export { Logo, LogoProps, TangleKnot } from './primitives.js';
|
|
3
3
|
export { CodeBlock as CodeBlockDisplay, Markdown, MarkdownProps } from '@tangle-network/ui/markdown';
|
|
4
|
-
export { AgentWorkbench, ApprovalConfidenceStat, ApprovalItem, ApprovalQueue, ApprovalQueueProps, AuditCheck, AuditResults, AuditResultsProps, BannerType, CalendarEvent, CalendarView, CalendarViewProps, ContextBadge, DirectoryPane, DirectoryPaneProps, FormAudit, RuntimePane, RuntimePaneProps, SandboxWorkbench, SandboxWorkbenchArtifact, SandboxWorkbenchCustomArtifact, SandboxWorkbenchFileArtifact, SandboxWorkbenchLayoutOptions, SandboxWorkbenchMarkdownArtifact, SandboxWorkbenchOpenUIArtifact, SandboxWorkbenchProps, SandboxWorkbenchSessionProps, SessionActivityMonitor, SessionActivityMonitorProps, SessionSidebar, SessionSidebarBadge, SessionSidebarFilter, SessionSidebarItem, SessionSidebarLink, SessionSidebarProps, StatusBanner, StatusBannerProps, StatusBar, StatusBarProps, TaskBoard, TaskBoardColumn, TaskBoardItem, TaskBoardProps, TerminalLine, TerminalPanel, TerminalProps, WorkspaceLayout, WorkspaceLayoutProps } from './workspace.js';
|
|
4
|
+
export { AgentWorkbench, ApprovalConfidenceStat, ApprovalItem, ApprovalQueue, ApprovalQueueProps, AuditCheck, AuditResults, AuditResultsProps, BannerType, CalendarEvent, CalendarView, CalendarViewProps, ContextBadge, DirectoryPane, DirectoryPaneProps, FormAudit, RuntimePane, RuntimePaneProps, SESSION_CREATED_EVENT, SandboxWorkbench, SandboxWorkbenchArtifact, SandboxWorkbenchCustomArtifact, SandboxWorkbenchFileArtifact, SandboxWorkbenchLayoutOptions, SandboxWorkbenchMarkdownArtifact, SandboxWorkbenchOpenUIArtifact, SandboxWorkbenchProps, SandboxWorkbenchSessionProps, SessionActivityMonitor, SessionActivityMonitorProps, SessionCreatedDetail, SessionOptimisticController, SessionSidebar, SessionSidebarBadge, SessionSidebarFilter, SessionSidebarItem, SessionSidebarLink, SessionSidebarProps, ShellShouldRevalidateArgs, ShellShouldRevalidateOptions, StatusBanner, StatusBannerProps, StatusBar, StatusBarProps, TaskBoard, TaskBoardColumn, TaskBoardItem, TaskBoardProps, TerminalLine, TerminalPanel, TerminalProps, UseOptimisticSessionItemsOptions, WorkspaceLayout, WorkspaceLayoutProps, createShellShouldRevalidate, dispatchSessionCreated, shellShouldRevalidate, useOptimisticSessionItems } from './workspace.js';
|
|
5
5
|
export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from '@tangle-network/ui/openui';
|
|
6
6
|
export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from '@tangle-network/ui/chat';
|
|
7
7
|
export { AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessControl, AgentSessionModelControl, AgentSessionReasoningControl, ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport, ArtifactDockMessage, ArtifactDockStreamEvent, ArtifactKind, ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, HARNESS_MODEL_POLICIES, ReasoningLevel, ReasoningLevelOption, ReasoningLevelPicker, ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, modelProvider, snapHarnessToModel, snapModelToHarness } from './chat.js';
|
package/dist/index.js
CHANGED
|
@@ -120,6 +120,7 @@ import {
|
|
|
120
120
|
CalendarView,
|
|
121
121
|
DirectoryPane,
|
|
122
122
|
RuntimePane,
|
|
123
|
+
SESSION_CREATED_EVENT,
|
|
123
124
|
SandboxWorkbench,
|
|
124
125
|
SessionActivityMonitor,
|
|
125
126
|
SessionSidebar,
|
|
@@ -127,8 +128,12 @@ import {
|
|
|
127
128
|
StatusBar,
|
|
128
129
|
TaskBoard,
|
|
129
130
|
TerminalPanel,
|
|
130
|
-
WorkspaceLayout
|
|
131
|
-
|
|
131
|
+
WorkspaceLayout,
|
|
132
|
+
createShellShouldRevalidate,
|
|
133
|
+
dispatchSessionCreated,
|
|
134
|
+
shellShouldRevalidate,
|
|
135
|
+
useOptimisticSessionItems
|
|
136
|
+
} from "./chunk-AUFV7766.js";
|
|
132
137
|
import {
|
|
133
138
|
OpenUIArtifactRenderer
|
|
134
139
|
} from "./chunk-AZ3AWMTM.js";
|
|
@@ -442,6 +447,7 @@ export {
|
|
|
442
447
|
RichFileTree,
|
|
443
448
|
RunGroup,
|
|
444
449
|
RuntimePane,
|
|
450
|
+
SESSION_CREATED_EVENT,
|
|
445
451
|
SIDEBAR_MOBILE_WIDTH,
|
|
446
452
|
SIDEBAR_PANEL_WIDTH,
|
|
447
453
|
SIDEBAR_RAIL_WIDTH,
|
|
@@ -534,8 +540,10 @@ export {
|
|
|
534
540
|
copyText,
|
|
535
541
|
createAuthFetcher,
|
|
536
542
|
createFetchTransport,
|
|
543
|
+
createShellShouldRevalidate,
|
|
537
544
|
dedupeModels,
|
|
538
545
|
disconnectSession,
|
|
546
|
+
dispatchSessionCreated,
|
|
539
547
|
filterFileTree,
|
|
540
548
|
formatBytes,
|
|
541
549
|
formatContext,
|
|
@@ -569,6 +577,7 @@ export {
|
|
|
569
577
|
setActiveSessionError,
|
|
570
578
|
setActiveSessionRunning,
|
|
571
579
|
setForegroundActiveSession,
|
|
580
|
+
shellShouldRevalidate,
|
|
572
581
|
snapHarnessToModel,
|
|
573
582
|
snapModelToHarness,
|
|
574
583
|
timeAgo,
|
|
@@ -588,6 +597,7 @@ export {
|
|
|
588
597
|
useHasBackgroundRunningSessions,
|
|
589
598
|
useLiveTime,
|
|
590
599
|
useNavbarSessions,
|
|
600
|
+
useOptimisticSessionItems,
|
|
591
601
|
useProjectActivity,
|
|
592
602
|
useProjectSessions,
|
|
593
603
|
usePtySession,
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
2
|
+
import { ReactNode, Ref } from 'react';
|
|
3
3
|
export { ArtifactPane, ArtifactPaneProps } from '@tangle-network/ui/primitives';
|
|
4
4
|
import { FileNode, FileTreeVisibilityOptions, FileTabData } from '@tangle-network/ui/files';
|
|
5
5
|
import { SessionProjectKey, ActiveSessionStatus, ActiveSessionRecord } from '@tangle-network/ui/stores';
|
|
@@ -160,6 +160,67 @@ interface RuntimePaneProps {
|
|
|
160
160
|
*/
|
|
161
161
|
declare function RuntimePane({ title, subtitle, statusBanner, statusBar, content, terminal, audit, inspector, footer, className, }: RuntimePaneProps): react_jsx_runtime.JSX.Element;
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Optimistic session/thread list: reflect a just-created / renamed / deleted
|
|
165
|
+
* item in the sidebar INSTANTLY, before the server loader round-trips.
|
|
166
|
+
*
|
|
167
|
+
* The shell loader is the source of truth and reconciles in the background
|
|
168
|
+
* (typically the app calls `useRevalidator().revalidate()` after its mutation
|
|
169
|
+
* fetch settles). Until that lands, a local mirror of the loader items carries
|
|
170
|
+
* the optimistic edit so a delete / rename / new-thread does not feel broken
|
|
171
|
+
* for the duration of a D1 round-trip.
|
|
172
|
+
*
|
|
173
|
+
* Two ways to drive it, usable together:
|
|
174
|
+
* 1. A window `CustomEvent` (default name {@link SESSION_CREATED_EVENT}) — the
|
|
175
|
+
* surface that creates a thread (often a different route from the sidebar's
|
|
176
|
+
* route) dispatches it; the sidebar prepends the item with no prop wiring.
|
|
177
|
+
* 2. The imperative {@link SessionOptimisticController} returned here — the
|
|
178
|
+
* sidebar's own action handlers (rename / delete / pin) call it directly.
|
|
179
|
+
*/
|
|
180
|
+
/** Default window-event name for "a session/thread was just created". */
|
|
181
|
+
declare const SESSION_CREATED_EVENT = "sandbox-thread-created";
|
|
182
|
+
/**
|
|
183
|
+
* Payload of a {@link SESSION_CREATED_EVENT}. Only `id` + `title` are required;
|
|
184
|
+
* everything else mirrors {@link SessionSidebarItem}. `updatedAt` defaults to
|
|
185
|
+
* now so the new item sorts to the top.
|
|
186
|
+
*/
|
|
187
|
+
interface SessionCreatedDetail extends Partial<Omit<SessionSidebarItem, "id" | "title">> {
|
|
188
|
+
id: string;
|
|
189
|
+
title: string;
|
|
190
|
+
}
|
|
191
|
+
/** Dispatch the shared "session created" event so any mounted sidebar updates. */
|
|
192
|
+
declare function dispatchSessionCreated(detail: SessionCreatedDetail, eventName?: string): void;
|
|
193
|
+
/** Imperative handle for driving optimistic edits from a mutation handler. */
|
|
194
|
+
interface SessionOptimisticController {
|
|
195
|
+
/** Prepend (or move to top) an item — call before the create fetch settles. */
|
|
196
|
+
add: (item: SessionCreatedDetail) => void;
|
|
197
|
+
/** Patch an existing item in place — e.g. a rename or category change. */
|
|
198
|
+
update: (id: string, patch: Partial<SessionSidebarItem>) => void;
|
|
199
|
+
/** Drop an item — call before the delete fetch settles. */
|
|
200
|
+
remove: (id: string) => void;
|
|
201
|
+
/** Discard all optimistic edits and snap back to the loader items. */
|
|
202
|
+
reset: () => void;
|
|
203
|
+
}
|
|
204
|
+
interface UseOptimisticSessionItemsOptions {
|
|
205
|
+
/**
|
|
206
|
+
* Listen for the shared window create-event and prepend its item. Set `false`
|
|
207
|
+
* to drive optimistic state purely through the imperative controller.
|
|
208
|
+
* Defaults to `true`.
|
|
209
|
+
*/
|
|
210
|
+
listenForCreate?: boolean;
|
|
211
|
+
/** Override the window event name to listen for. */
|
|
212
|
+
eventName?: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Mirror `items` with optimistic add/update/remove on top. The mirror re-syncs
|
|
216
|
+
* whenever `items` changes (the loader is authoritative), so an optimistic edit
|
|
217
|
+
* is naturally superseded once the server result arrives.
|
|
218
|
+
*/
|
|
219
|
+
declare function useOptimisticSessionItems(items: SessionSidebarItem[], options?: UseOptimisticSessionItemsOptions): {
|
|
220
|
+
items: SessionSidebarItem[];
|
|
221
|
+
controller: SessionOptimisticController;
|
|
222
|
+
};
|
|
223
|
+
|
|
163
224
|
interface SessionSidebarItem {
|
|
164
225
|
id: string;
|
|
165
226
|
title: string;
|
|
@@ -218,8 +279,97 @@ interface SessionSidebarProps {
|
|
|
218
279
|
session: ActiveSessionRecord | null;
|
|
219
280
|
isActive: boolean;
|
|
220
281
|
}) => ReactNode;
|
|
282
|
+
/**
|
|
283
|
+
* Opt into optimistic item updates: the sidebar keeps a local mirror of
|
|
284
|
+
* `items` so a just-created / renamed / deleted thread shows instantly,
|
|
285
|
+
* before the loader round-trips. Pass `true` for defaults, or an options
|
|
286
|
+
* object to tune the window create-event. Off by default — existing callers
|
|
287
|
+
* render `items` verbatim and are unaffected.
|
|
288
|
+
*/
|
|
289
|
+
optimistic?: boolean | UseOptimisticSessionItemsOptions;
|
|
290
|
+
/**
|
|
291
|
+
* Ref to the imperative optimistic controller (`add` / `update` / `remove` /
|
|
292
|
+
* `reset`). Drive optimistic edits from the consumer's own rename/delete/pin
|
|
293
|
+
* handlers. Only populated when `optimistic` is enabled.
|
|
294
|
+
*/
|
|
295
|
+
optimisticRef?: Ref<SessionOptimisticController | null>;
|
|
221
296
|
}
|
|
222
|
-
declare function SessionSidebar({ title, subtitle, projectId, items, currentItemId, createLabel, onCreate, onSelectItem, onSelectLink, links, className, emptyMessage, searchPlaceholder, enableSearch, activityMonitor, filters, defaultFilterId, resizable, defaultWidth, minWidth, maxWidth, onWidthChange, renderItemActions, }: SessionSidebarProps): react_jsx_runtime.JSX.Element;
|
|
297
|
+
declare function SessionSidebar({ title, subtitle, projectId, items, currentItemId, createLabel, onCreate, onSelectItem, onSelectLink, links, className, emptyMessage, searchPlaceholder, enableSearch, activityMonitor, filters, defaultFilterId, resizable, defaultWidth, minWidth, maxWidth, onWidthChange, renderItemActions, optimistic, optimisticRef, }: SessionSidebarProps): react_jsx_runtime.JSX.Element;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Snappy in-app navigation: a shared `shouldRevalidate` rule for the agent-app
|
|
301
|
+
* shell route(s) that own the workspace-list / sidebar loader.
|
|
302
|
+
*
|
|
303
|
+
* The shell loader (user + workspace list, sidebar state) runs on every
|
|
304
|
+
* navigation, but its data does not change just by moving between in-app pages.
|
|
305
|
+
* Refetching it on every internal GET nav adds a loader round-trip to each
|
|
306
|
+
* click — on Cloudflare Workers + D1 (HTTP-proxied) that is a visible stall.
|
|
307
|
+
*
|
|
308
|
+
* This helper encodes the rule that makes nav feel instant WITHOUT stranding
|
|
309
|
+
* freshly-mutated data:
|
|
310
|
+
*
|
|
311
|
+
* - Non-GET navigation (form submit / action) → always revalidate.
|
|
312
|
+
* - Internal app→app navigation that CHANGES the path → skip revalidation.
|
|
313
|
+
* - Imperative `useRevalidator().revalidate()` (which targets the SAME url,
|
|
314
|
+
* so `currentUrl.pathname === nextUrl.pathname`) → revalidate. Creating a
|
|
315
|
+
* project / thread typically goes through a raw `fetch`, so a same-url
|
|
316
|
+
* revalidate is the ONLY way the new row reaches the shell loader; the
|
|
317
|
+
* same-path carve-out below is what keeps that working. Suppressing it is
|
|
318
|
+
* the project-switcher regression — do not "simplify" it away.
|
|
319
|
+
* - Anything else (cross-path-prefix nav, entering/leaving the app) →
|
|
320
|
+
* defer to `defaultShouldRevalidate`.
|
|
321
|
+
*
|
|
322
|
+
* Framework-agnostic by design: sandbox-ui does not depend on react-router, so
|
|
323
|
+
* this takes a plain args object. The shape is a structural subset of
|
|
324
|
+
* react-router's `ShouldRevalidateFunctionArgs`, so an app can wire it as a
|
|
325
|
+
* route export with no adapter:
|
|
326
|
+
*
|
|
327
|
+
* ```ts
|
|
328
|
+
* // app/routes/app.tsx
|
|
329
|
+
* import { shellShouldRevalidate } from "@tangle-network/sandbox-ui/workspace";
|
|
330
|
+
* export const shouldRevalidate = shellShouldRevalidate;
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* `shouldRevalidate` MUST be a per-app react-router route export — it cannot be
|
|
334
|
+
* exported FROM a library on the app's behalf — so the "out of the box" win is
|
|
335
|
+
* the one-line re-export above instead of every app re-deriving the rule (and
|
|
336
|
+
* re-introducing the same-url bug).
|
|
337
|
+
*/
|
|
338
|
+
/**
|
|
339
|
+
* The subset of react-router's `ShouldRevalidateFunctionArgs` this rule reads.
|
|
340
|
+
* Kept structural so callers can pass the full react-router args object as-is.
|
|
341
|
+
*/
|
|
342
|
+
interface ShellShouldRevalidateArgs {
|
|
343
|
+
currentUrl: URL;
|
|
344
|
+
nextUrl: URL;
|
|
345
|
+
formMethod?: string;
|
|
346
|
+
defaultShouldRevalidate: boolean;
|
|
347
|
+
}
|
|
348
|
+
interface ShellShouldRevalidateOptions {
|
|
349
|
+
/**
|
|
350
|
+
* Path prefix that marks "inside the app shell". Internal navigation between
|
|
351
|
+
* two paths under this prefix skips the shell-loader refetch. Defaults to
|
|
352
|
+
* `"/app"`.
|
|
353
|
+
*/
|
|
354
|
+
appPathPrefix?: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Build a `shouldRevalidate` function for the shell route under `appPathPrefix`.
|
|
358
|
+
* Use this when the app mounts under a non-default prefix; otherwise prefer the
|
|
359
|
+
* ready-made {@link shellShouldRevalidate} export.
|
|
360
|
+
*/
|
|
361
|
+
declare function createShellShouldRevalidate(options?: ShellShouldRevalidateOptions): (args: ShellShouldRevalidateArgs) => boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Ready-made shell `shouldRevalidate` for apps mounted under `/app`. Wire it as
|
|
364
|
+
* a one-line route export:
|
|
365
|
+
*
|
|
366
|
+
* ```ts
|
|
367
|
+
* export const shouldRevalidate = shellShouldRevalidate;
|
|
368
|
+
* ```
|
|
369
|
+
*
|
|
370
|
+
* For a non-`/app` prefix, use {@link createShellShouldRevalidate}.
|
|
371
|
+
*/
|
|
372
|
+
declare const shellShouldRevalidate: (args: ShellShouldRevalidateArgs) => boolean;
|
|
223
373
|
|
|
224
374
|
interface SessionActivityMonitorProps {
|
|
225
375
|
className?: string;
|
|
@@ -478,4 +628,4 @@ interface ApprovalQueueProps {
|
|
|
478
628
|
*/
|
|
479
629
|
declare function ApprovalQueue({ items, className, onApprove, onReject, renderItemDetail, renderTypeBadge, renderStats, canResolve, header, emptyState, showResolved: controlledShowResolved, }: ApprovalQueueProps): react_jsx_runtime.JSX.Element;
|
|
480
630
|
|
|
481
|
-
export { AgentWorkbench, type ApprovalConfidenceStat, type ApprovalItem, ApprovalQueue, type ApprovalQueueProps, type AuditCheck, AuditResults, type AuditResultsProps, type BannerType, type CalendarEvent, CalendarView, type CalendarViewProps, type ContextBadge, DirectoryPane, type DirectoryPaneProps, type FormAudit, RuntimePane, type RuntimePaneProps, SandboxWorkbench, type SandboxWorkbenchArtifact, type SandboxWorkbenchCustomArtifact, type SandboxWorkbenchFileArtifact, type SandboxWorkbenchLayoutOptions, type SandboxWorkbenchMarkdownArtifact, type SandboxWorkbenchOpenUIArtifact, type SandboxWorkbenchProps, type SandboxWorkbenchSessionProps, SessionActivityMonitor, type SessionActivityMonitorProps, SessionSidebar, type SessionSidebarBadge, type SessionSidebarFilter, type SessionSidebarItem, type SessionSidebarLink, type SessionSidebarProps, StatusBanner, type StatusBannerProps, StatusBar, type StatusBarProps, TaskBoard, type TaskBoardColumn, type TaskBoardItem, type TaskBoardProps, type TerminalLine, TerminalPanel, type TerminalProps, WorkspaceLayout, type WorkspaceLayoutProps };
|
|
631
|
+
export { AgentWorkbench, type ApprovalConfidenceStat, type ApprovalItem, ApprovalQueue, type ApprovalQueueProps, type AuditCheck, AuditResults, type AuditResultsProps, type BannerType, type CalendarEvent, CalendarView, type CalendarViewProps, type ContextBadge, DirectoryPane, type DirectoryPaneProps, type FormAudit, RuntimePane, type RuntimePaneProps, SESSION_CREATED_EVENT, SandboxWorkbench, type SandboxWorkbenchArtifact, type SandboxWorkbenchCustomArtifact, type SandboxWorkbenchFileArtifact, type SandboxWorkbenchLayoutOptions, type SandboxWorkbenchMarkdownArtifact, type SandboxWorkbenchOpenUIArtifact, type SandboxWorkbenchProps, type SandboxWorkbenchSessionProps, SessionActivityMonitor, type SessionActivityMonitorProps, type SessionCreatedDetail, type SessionOptimisticController, SessionSidebar, type SessionSidebarBadge, type SessionSidebarFilter, type SessionSidebarItem, type SessionSidebarLink, type SessionSidebarProps, type ShellShouldRevalidateArgs, type ShellShouldRevalidateOptions, StatusBanner, type StatusBannerProps, StatusBar, type StatusBarProps, TaskBoard, type TaskBoardColumn, type TaskBoardItem, type TaskBoardProps, type TerminalLine, TerminalPanel, type TerminalProps, type UseOptimisticSessionItemsOptions, WorkspaceLayout, type WorkspaceLayoutProps, createShellShouldRevalidate, dispatchSessionCreated, shellShouldRevalidate, useOptimisticSessionItems };
|
package/dist/workspace.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CalendarView,
|
|
7
7
|
DirectoryPane,
|
|
8
8
|
RuntimePane,
|
|
9
|
+
SESSION_CREATED_EVENT,
|
|
9
10
|
SandboxWorkbench,
|
|
10
11
|
SessionActivityMonitor,
|
|
11
12
|
SessionSidebar,
|
|
@@ -13,8 +14,12 @@ import {
|
|
|
13
14
|
StatusBar,
|
|
14
15
|
TaskBoard,
|
|
15
16
|
TerminalPanel,
|
|
16
|
-
WorkspaceLayout
|
|
17
|
-
|
|
17
|
+
WorkspaceLayout,
|
|
18
|
+
createShellShouldRevalidate,
|
|
19
|
+
dispatchSessionCreated,
|
|
20
|
+
shellShouldRevalidate,
|
|
21
|
+
useOptimisticSessionItems
|
|
22
|
+
} from "./chunk-AUFV7766.js";
|
|
18
23
|
import "./chunk-EI44GEQ5.js";
|
|
19
24
|
export {
|
|
20
25
|
AgentWorkbench,
|
|
@@ -24,6 +29,7 @@ export {
|
|
|
24
29
|
CalendarView,
|
|
25
30
|
DirectoryPane,
|
|
26
31
|
RuntimePane,
|
|
32
|
+
SESSION_CREATED_EVENT,
|
|
27
33
|
SandboxWorkbench,
|
|
28
34
|
SessionActivityMonitor,
|
|
29
35
|
SessionSidebar,
|
|
@@ -31,5 +37,9 @@ export {
|
|
|
31
37
|
StatusBar,
|
|
32
38
|
TaskBoard,
|
|
33
39
|
TerminalPanel,
|
|
34
|
-
WorkspaceLayout
|
|
40
|
+
WorkspaceLayout,
|
|
41
|
+
createShellShouldRevalidate,
|
|
42
|
+
dispatchSessionCreated,
|
|
43
|
+
shellShouldRevalidate,
|
|
44
|
+
useOptimisticSessionItems
|
|
35
45
|
};
|
package/package.json
CHANGED