@alivault/pico 0.7.4 → 0.9.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.
@@ -2,7 +2,7 @@ import { i as __toESM } from "../_runtime.mjs";
2
2
  import { A as DialogRoot, C as MenuPortal, D as TabsTab, E as TabsList$1, F as DialogBackdrop, I as Separator, K as mergeProps, L as Input, M as DialogPopup, N as DialogDescription$1, O as TabsRoot, P as DialogClose, R as Button, S as MenuPositioner, T as MenuItem, X as require_react, Y as require_jsx_runtime, _ as AccordionRoot, a as CollapsiblePanel, b as MenuSubmenuRoot, c as PopoverPopup, d as PopoverTrigger$1, f as PopoverRoot, g as AccordionItem$1, h as AccordionHeader, i as ContextMenuRoot, j as DialogPortal$1, k as DialogTitle$1, l as PopoverPositioner, m as AccordionTrigger$1, n as Toggle, o as CollapsibleTrigger$1, p as AccordionPanel, r as ContextMenuTrigger$1, s as CollapsibleRoot, t as ToggleGroup, u as PopoverPortal, v as MenuSubmenuTrigger, w as MenuPopup, x as MenuRoot, y as MenuTrigger, z as useRender } from "../_libs/@base-ui/react+[...].mjs";
3
3
  import { t as cva } from "../_libs/class-variance-authority+clsx.mjs";
4
4
  import { A as Command, C as Folder, D as EllipsisVertical, E as Ellipsis, F as ChevronRight, H as ArrowDown, I as ChevronDown, L as Check, M as ChevronsUpDown, N as ChevronsDownUp, O as Download, R as ArrowUp, S as GitCommitHorizontal, T as FileInput, V as ArrowLeft, _ as ListStart, b as ImagePlus, c as Settings2, d as PanelRight, f as PanelLeft, g as OctagonX, i as Undo2, k as Copy, l as Search, m as PanelLeftClose, n as WandSparkles, o as Square, p as PanelLeftOpen, r as Upload, s as SquarePen, t as X, u as Plus, v as ListEnd, w as FolderPlus, x as GitBranch, z as ArrowUpToLine } from "../_libs/lucide-react.mjs";
5
- import { $ as readStoredCenterMessages, A as TooltipTrigger, C as THEME_COLOR_MODE_STORAGE_KEY, D as Tooltip$1, E as TitleTooltip, F as cn, G as normalizePromptImage, H as flattenTree, J as normalizeThemeColorMode, K as normalizeSessionSelectionKeys, L as createContextId, M as appliedThemeClass, O as TooltipContent, P as buildItemsFromSync, Q as readStoredAutoScrollEnabled, R as createInitialSessionState, S as THEME_COLOR_MODES, T as THEME_STORAGE_KEY, U as getSessionTitle, X as previewUrlForImage, Y as normalizeThemeFamily, Z as promptDraftKey, _ as Route, _t as themeColorModeLabel, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as readStoredRecentDirectories, b as SIDEBAR_DIRECTORIES_STORAGE_KEY, c as Kbd, ct as readStoredSessionDoneSoundEnabled, d as RECENT_DIRECTORIES_STORAGE_KEY, dt as readStoredThemeColorMode, et as readStoredCollapsedDirectories, f as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ft as rememberStoredPromptDraft, g as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, gt as sessionListEntryKey, h as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, ht as sameContextUsage, i as CENTER_MESSAGES_STORAGE_KEY, it as readStoredPromptDraft, j as VIEWER_CONTEXT_STORAGE_KEY, l as KeyboardShortcutContent, lt as readStoredSidebarDirectories, m as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, mt as safeLocalStorageSetItem, n as APPLIED_THEME_STORAGE_KEY, nt as readStoredHideToolBlocks, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as readStoredRightSidebarOpen, p as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, pt as safeLocalStorageGetItem, q as normalizeStoredDirectoryList, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as readStoredPinnedSessionKeys, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredSessionDoneDesktopNotificationsEnabled, tt as readStoredDraftDirectory, u as PINNED_SESSIONS_STORAGE_KEY, ut as readStoredTheme, v as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, vt as themeFamilyLabel, w as THEME_FAMILIES, x as Spinner, y as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, yt as thinkingSummaryText } from "./routes-CWyvexcp.mjs";
5
+ import { $ as readStoredCenterMessages, A as TooltipTrigger, C as THEME_COLOR_MODE_STORAGE_KEY, D as Tooltip$1, E as TitleTooltip, F as cn, G as normalizePromptImage, H as flattenTree, J as normalizeThemeColorMode, K as normalizeSessionSelectionKeys, L as createContextId, M as appliedThemeClass, O as TooltipContent, P as buildItemsFromSync, Q as readStoredAutoScrollEnabled, R as createInitialSessionState, S as THEME_COLOR_MODES, T as THEME_STORAGE_KEY, U as getSessionTitle, X as previewUrlForImage, Y as normalizeThemeFamily, Z as promptDraftKey, _ as Route, _t as themeColorModeLabel, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as readStoredRecentDirectories, b as SIDEBAR_DIRECTORIES_STORAGE_KEY, c as Kbd, ct as readStoredSessionDoneSoundEnabled, d as RECENT_DIRECTORIES_STORAGE_KEY, dt as readStoredThemeColorMode, et as readStoredCollapsedDirectories, f as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ft as rememberStoredPromptDraft, g as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, gt as sessionListEntryKey, h as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, ht as sameContextUsage, i as CENTER_MESSAGES_STORAGE_KEY, it as readStoredPromptDraft, j as VIEWER_CONTEXT_STORAGE_KEY, l as KeyboardShortcutContent, lt as readStoredSidebarDirectories, m as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, mt as safeLocalStorageSetItem, n as APPLIED_THEME_STORAGE_KEY, nt as readStoredHideToolBlocks, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as readStoredRightSidebarOpen, p as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, pt as safeLocalStorageGetItem, q as normalizeStoredDirectoryList, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as readStoredPinnedSessionKeys, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredSessionDoneDesktopNotificationsEnabled, tt as readStoredDraftDirectory, u as PINNED_SESSIONS_STORAGE_KEY, ut as readStoredTheme, v as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, vt as themeFamilyLabel, w as THEME_FAMILIES, x as Spinner, y as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, yt as thinkingSummaryText } from "./routes-bPw2DezY.mjs";
6
6
  import { i as useQuery, n as useIsMutating, o as useQueryClient, r as useIsFetching, t as useMutation } from "../_libs/tanstack__react-query.mjs";
7
7
  import { t as useHotkeys } from "../_libs/tanstack__react-hotkeys.mjs";
8
8
  import { a as matchesKeyboardEvent, i as batch, o as formatForDisplay, r as createStore } from "../_libs/@tanstack/hotkeys+[...].mjs";
@@ -20,9 +20,9 @@ import { n as defaultSchema } from "../_libs/hast-util-sanitize.mjs";
20
20
  import { t as rehypeSanitize } from "../_libs/rehype-sanitize.mjs";
21
21
  import { t as remarkGfm } from "../_libs/remark-gfm.mjs";
22
22
  import { a as getBuiltInSpriteSheet, i as getBuiltInFileIconColor, n as FileTree, r as createFileTreeIconResolver, t as useFileTree } from "../_libs/@pierre/trees+[...].mjs";
23
- import { a as closestCenter, d as useSensors, f as CSS$1, i as PointerSensor, n as DragOverlay, t as DndContext, u as useSensor } from "../_libs/@dnd-kit/core+[...].mjs";
23
+ import { a as closestCenter, c as useDraggable, d as useSensors, f as CSS$1, i as PointerSensor, n as DragOverlay, t as DndContext, u as useSensor } from "../_libs/@dnd-kit/core+[...].mjs";
24
24
  import { a as verticalListSortingStrategy, i as useSortable, n as arrayMove, r as horizontalListSortingStrategy, t as SortableContext } from "../_libs/dnd-kit__sortable.mjs";
25
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-CeiPDe0r.js
25
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-7x8dHcec.js
26
26
  var import_react = /* @__PURE__ */ __toESM(require_react());
27
27
  var import_jsx_runtime = require_jsx_runtime();
28
28
  var MOBILE_BREAKPOINT = 768;
@@ -1083,7 +1083,7 @@ function directoryCompletionInputValue(item) {
1083
1083
  const displayPath = formatDirectoryDisplayPath(item.value);
1084
1084
  return displayPath.endsWith("/") ? displayPath : `${displayPath}/`;
1085
1085
  }
1086
- function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDirectoryInputChange, openedDirectories, currentDirectory, recentDirectories, knownDirectories, useForNewSession = false, onAddDirectoryPath, onRequestPathCompletions, onSearchDirectories }) {
1086
+ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDirectoryInputChange, openedDirectories, currentDirectory, recentDirectories, knownDirectories, useForNewSession = false, useForMoveSession = false, onAddDirectoryPath, onRequestPathCompletions, onSearchDirectories }) {
1087
1087
  const isMobile = useIsMobile();
1088
1088
  const directoryInputRef = import_react.useRef(directoryInput);
1089
1089
  const pathCompletionRequestIdRef = import_react.useRef(0);
@@ -1138,10 +1138,14 @@ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDire
1138
1138
  const hasPathCompletionResults = shouldShowPathCompletions && (pathCompletionLoading || pathCompletionItems.length > 0);
1139
1139
  const hasDirectorySearchResults = shouldShowDirectorySearch && (directorySearchLoading || directorySearchItems.length > 0);
1140
1140
  const hasDirectoryResults = Boolean(manualPath) || hasDirectoryMatches || hasPathCompletionResults || hasDirectorySearchResults;
1141
- const addPathDescription = useForNewSession ? "Add to sidebar and use for this new session." : "Resolve and add this path to the sidebar.";
1142
- const openedDescription = useForNewSession ? "Use for this new session." : "Expand and show it in the sidebar.";
1143
- const currentDescription = useForNewSession ? "Use the current Pico working directory for this new session." : "Use the current Pico working directory.";
1144
- const addKnownDescription = useForNewSession ? "Add to sidebar and use for this new session." : "";
1141
+ const addPathDescription = useForMoveSession ? "Resolve and move this session to this directory." : useForNewSession ? "Add to sidebar and use for this new session." : "Resolve and add this path to the sidebar.";
1142
+ const openedDescription = useForMoveSession ? "Move this session here." : useForNewSession ? "Use for this new session." : "Expand and show it in the sidebar.";
1143
+ const currentDescription = useForMoveSession ? "Move this session to the current Pico working directory." : useForNewSession ? "Use the current Pico working directory for this new session." : "Use the current Pico working directory.";
1144
+ const addKnownDescription = useForMoveSession ? "Move this session here." : useForNewSession ? "Add to sidebar and use for this new session." : "";
1145
+ const manualGroupHeading = useForMoveSession ? "Move to path" : "Add path";
1146
+ const manualPathPrefix = useForMoveSession ? "Move to" : "Add";
1147
+ const dialogTitle = useForMoveSession ? "Move session" : "Add directory";
1148
+ const dialogDescription = useForMoveSession ? "Search recent and known directories or paste any path to move this session." : "Search recent and known directories or add a new path to the sidebar.";
1145
1149
  import_react.useEffect(() => {
1146
1150
  if (!shouldShowPathCompletions) {
1147
1151
  pathCompletionRequestIdRef.current += 1;
@@ -1325,7 +1329,7 @@ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDire
1325
1329
  }, `directory-search:${completion.value}`))]
1326
1330
  }) : null,
1327
1331
  manualPath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandGroup, {
1328
- heading: "Add path",
1332
+ heading: manualGroupHeading,
1329
1333
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandItem, {
1330
1334
  value: `add ${manualPath}`,
1331
1335
  onSelect: () => onAddDirectoryPath(manualPath),
@@ -1333,7 +1337,7 @@ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDire
1333
1337
  className: "flex min-w-0 flex-1 flex-col gap-0.5",
1334
1338
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryPathLabel$1, {
1335
1339
  path: manualPath,
1336
- prefix: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: "Add\xA0" })
1340
+ prefix: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [manualPathPrefix, "\xA0"] })
1337
1341
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
1338
1342
  className: "truncate text-xs text-muted-foreground",
1339
1343
  children: addPathDescription
@@ -1428,7 +1432,7 @@ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDire
1428
1432
  autoFocus: false,
1429
1433
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
1430
1434
  className: "max-h-[90svh] overflow-hidden",
1431
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerTitle, { children: "Add directory" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerDescription, { children: "Search recent and known directories or add a new path to the sidebar." })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
1435
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerTitle, { children: dialogTitle }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerDescription, { children: dialogDescription })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
1432
1436
  className: "flex min-h-0 flex-1 flex-col overflow-hidden px-4 pb-4",
1433
1437
  children: directoryPicker
1434
1438
  })]
@@ -1437,14 +1441,14 @@ function AppShellAddDirectoryDialog({ open, onOpenChange, directoryInput, onDire
1437
1441
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandDialog, {
1438
1442
  open,
1439
1443
  onOpenChange,
1440
- title: "Add directory",
1441
- description: "Search recent and known directories or add a new path to the sidebar.",
1444
+ title: dialogTitle,
1445
+ description: dialogDescription,
1442
1446
  className: "sm:max-w-2xl",
1443
1447
  initialFocus: true,
1444
1448
  children: directoryPicker
1445
1449
  });
1446
1450
  }
1447
- function AppShellAddDirectoryDialogController({ ref, openStateRef, openedDirectories, currentDirectory, recentDirectories, knownDirectories, useForNewSession, onAddDirectoryPath, onRequestPathCompletions, onSearchDirectories }) {
1451
+ function AppShellAddDirectoryDialogController({ ref, openStateRef, openedDirectories, currentDirectory, recentDirectories, knownDirectories, useForNewSession, useForMoveSession, onAddDirectoryPath, onRequestPathCompletions, onSearchDirectories }) {
1448
1452
  const [open, setOpen] = import_react.useState(false);
1449
1453
  const [directoryInput, setDirectoryInput] = import_react.useState("");
1450
1454
  const openRef = import_react.useRef(open);
@@ -1478,6 +1482,7 @@ function AppShellAddDirectoryDialogController({ ref, openStateRef, openedDirecto
1478
1482
  recentDirectories,
1479
1483
  knownDirectories,
1480
1484
  useForNewSession,
1485
+ useForMoveSession,
1481
1486
  onAddDirectoryPath: (path) => {
1482
1487
  addDirectoryPath(path);
1483
1488
  },
@@ -7143,6 +7148,42 @@ var AppShellAddDirectoryDialogHost = import_react.memo(function AppShellAddDirec
7143
7148
  })
7144
7149
  });
7145
7150
  });
7151
+ var AppShellMoveSessionDirectoryDialogHost = import_react.memo(function AppShellMoveSessionDirectoryDialogHost({ activeSessionId, baseSidebarDirectories, knownDirectories, moveSessionDirectoryDialogRef, moveSessionDirectoryOpenRef, moveSessionDirectoryTargetToPath, recentDirectoriesStore, sessionCwd, viewerContextId }) {
7152
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellAddDirectoryDialogController, {
7153
+ ref: moveSessionDirectoryDialogRef,
7154
+ openStateRef: moveSessionDirectoryOpenRef,
7155
+ openedDirectories: baseSidebarDirectories,
7156
+ currentDirectory: sessionCwd,
7157
+ recentDirectories: useSelector(recentDirectoriesStore),
7158
+ knownDirectories,
7159
+ useForMoveSession: true,
7160
+ onAddDirectoryPath: moveSessionDirectoryTargetToPath,
7161
+ onRequestPathCompletions: useStableEvent(async (prefix) => {
7162
+ if (!viewerContextId) return [];
7163
+ const response = await fetchJson(buildRequestUrl("/api/path-completions", {
7164
+ contextId: viewerContextId,
7165
+ sessionId: activeSessionId
7166
+ }), {
7167
+ method: "POST",
7168
+ headers: { "content-type": "application/json" },
7169
+ body: JSON.stringify({ prefix })
7170
+ });
7171
+ return isApiErrorResponse(response) ? [] : response.items;
7172
+ }),
7173
+ onSearchDirectories: useStableEvent(async (query) => {
7174
+ if (!viewerContextId) return [];
7175
+ const response = await fetchJson(buildRequestUrl("/api/directory-search", {
7176
+ contextId: viewerContextId,
7177
+ sessionId: activeSessionId
7178
+ }), {
7179
+ method: "POST",
7180
+ headers: { "content-type": "application/json" },
7181
+ body: JSON.stringify({ query })
7182
+ });
7183
+ return isApiErrorResponse(response) ? [] : response.items;
7184
+ })
7185
+ });
7186
+ });
7146
7187
  var AppShellRenameSessionDialogHost = import_react.memo(function AppShellRenameSessionDialogHost({ renameDialogRef, renameOpenRef, renameSessionPath }) {
7147
7188
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RenameSessionDialogController, {
7148
7189
  ref: renameDialogRef,
@@ -7231,7 +7272,7 @@ var AppShellUiRequestDialogHost = import_react.memo(function AppShellUiRequestDi
7231
7272
  onAuthBack: () => authDialogRef.current?.open("login")
7232
7273
  });
7233
7274
  });
7234
- var AppShellFloatingControllers = import_react.memo(function AppShellFloatingControllers({ activeSessionId, addDirectoryDialogRef, addDirectoryOpenRef, addDirectoryPath, baseSidebarDirectories, commandPaletteCommandsRef, commandPaletteOpenRef, commandPaletteRef, currentSessionQueryScope, currentTheme, currentThemeColorMode, authDialogRef, authOpenRef, deleteDialogRef, deleteOpenRef, deleteSessions, deleteOldDirectorySessionsDialogRef, deleteOldDirectorySessionsOpenRef, notificationStore, forkDialogRef, forkOpenRef, gitCommitDialogRef, gitCommitOpenRef, displaySettingsStore, knownDirectories, onAutoScrollEnabledChange, onCenterMessagesChange, onHideThinkingBlocksChange, onHideToolBlocksChange, onSessionDoneDesktopNotificationsEnabledChange, onSessionDoneSoundEnabledChange, onSessionDialogSelect, onThemeChange, onThemeColorModeChange, onThemePreviewChange, recentDirectoriesStore, renameDialogRef, renameOpenRef, renameSessionPath, sessionCwd, sessionsDialogDirectory, sessionsDialogRef, sessionsOpenRef, sessionStore, settingsDialogRef, settingsOpenRef, sidebarStore, treeDialogRef, treeOpenRef, uiRequestDialogRef, uiRequestOpenRef, viewerContextId, systemTheme }) {
7275
+ var AppShellFloatingControllers = import_react.memo(function AppShellFloatingControllers({ activeSessionId, addDirectoryDialogRef, addDirectoryOpenRef, addDirectoryPath, baseSidebarDirectories, commandPaletteCommandsRef, commandPaletteOpenRef, commandPaletteRef, currentSessionQueryScope, currentTheme, currentThemeColorMode, authDialogRef, authOpenRef, deleteDialogRef, deleteOpenRef, deleteSessions, deleteOldDirectorySessionsDialogRef, deleteOldDirectorySessionsOpenRef, notificationStore, forkDialogRef, forkOpenRef, gitCommitDialogRef, gitCommitOpenRef, displaySettingsStore, knownDirectories, moveSessionDirectoryDialogRef, moveSessionDirectoryOpenRef, moveSessionDirectoryTargetToPath, onAutoScrollEnabledChange, onCenterMessagesChange, onHideThinkingBlocksChange, onHideToolBlocksChange, onSessionDoneDesktopNotificationsEnabledChange, onSessionDoneSoundEnabledChange, onSessionDialogSelect, onThemeChange, onThemeColorModeChange, onThemePreviewChange, recentDirectoriesStore, renameDialogRef, renameOpenRef, renameSessionPath, sessionCwd, sessionsDialogDirectory, sessionsDialogRef, sessionsOpenRef, sessionStore, settingsDialogRef, settingsOpenRef, sidebarStore, treeDialogRef, treeOpenRef, uiRequestDialogRef, uiRequestOpenRef, viewerContextId, systemTheme }) {
7235
7276
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
7236
7277
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellCommandPaletteHost, {
7237
7278
  commandPaletteCommandsRef,
@@ -7274,6 +7315,17 @@ var AppShellFloatingControllers = import_react.memo(function AppShellFloatingCon
7274
7315
  sessionStore,
7275
7316
  viewerContextId
7276
7317
  }),
7318
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellMoveSessionDirectoryDialogHost, {
7319
+ activeSessionId,
7320
+ baseSidebarDirectories,
7321
+ knownDirectories,
7322
+ moveSessionDirectoryDialogRef,
7323
+ moveSessionDirectoryOpenRef,
7324
+ moveSessionDirectoryTargetToPath,
7325
+ recentDirectoriesStore,
7326
+ sessionCwd,
7327
+ viewerContextId
7328
+ }),
7277
7329
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellRenameSessionDialogHost, {
7278
7330
  renameDialogRef,
7279
7331
  renameOpenRef,
@@ -13288,6 +13340,32 @@ function ContextMenuItem({ className, inset, variant = "default", ...props }) {
13288
13340
  ...props
13289
13341
  });
13290
13342
  }
13343
+ function ContextMenuSub({ ...props }) {
13344
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuSubmenuRoot, {
13345
+ "data-slot": "context-menu-sub",
13346
+ ...props
13347
+ });
13348
+ }
13349
+ function ContextMenuSubTrigger({ className, inset, children, ...props }) {
13350
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MenuSubmenuTrigger, {
13351
+ "data-slot": "context-menu-sub-trigger",
13352
+ "data-inset": inset,
13353
+ className: cn("flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
13354
+ ...props,
13355
+ children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "ml-auto" })]
13356
+ });
13357
+ }
13358
+ function ContextMenuSubContent({ align = "start", alignOffset = -3, side = "right", sideOffset = 0, className, ...props }) {
13359
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuContent, {
13360
+ "data-slot": "context-menu-sub-content",
13361
+ className: cn("w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
13362
+ align,
13363
+ alignOffset,
13364
+ side,
13365
+ sideOffset,
13366
+ ...props
13367
+ });
13368
+ }
13291
13369
  function ContextMenuSeparator({ className, ...props }) {
13292
13370
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {
13293
13371
  "data-slot": "context-menu-separator",
@@ -16726,6 +16804,7 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
16726
16804
  const { isMobile: sidebarIsMobile, openMobile: sidebarOpenMobile, state: sidebarState } = useSidebar();
16727
16805
  const showCollapsedNewSessionButton = !(sidebarIsMobile ? sidebarOpenMobile : sidebarState === "expanded");
16728
16806
  const displaySessionTitle = isSessionViewLoading ? loadingDisplaySessionTitle : getCurrentSessionTitleFromState(sessionHeaderState);
16807
+ const moveSessionDirectoryOptions = newSessionDirectoryOptions.filter((option) => option.path !== displaySessionCwd);
16729
16808
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16730
16809
  className: "sticky top-0 z-50 flex h-[var(--header-height)] w-full shrink-0 items-center border-b border-border/70 bg-background p-2",
16731
16810
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -16827,6 +16906,29 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
16827
16906
  },
16828
16907
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: currentSessionPinned ? "Unpin from sidebar" : "Pin to sidebar" })
16829
16908
  }),
16909
+ sessionHeaderState.sessionHasFile ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuSub, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSubTrigger, { children: "Move to…" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuSubContent, {
16910
+ className: "w-72",
16911
+ children: [moveSessionDirectoryOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuItem, {
16912
+ onClick: () => {
16913
+ actionsRef.current.onMoveCurrentSession(option.path);
16914
+ },
16915
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16916
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
16917
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16918
+ className: "text-xs text-muted-foreground",
16919
+ children: option.label
16920
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16921
+ className: "truncate",
16922
+ children: formatDisplayPath$1(option.path)
16923
+ })]
16924
+ })
16925
+ }, option.path)), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuItem, {
16926
+ onClick: () => {
16927
+ actionsRef.current.onMoveCurrentSessionToAnyDirectory();
16928
+ },
16929
+ children: "Other directory…"
16930
+ })]
16931
+ })] }) : null,
16830
16932
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuItem, {
16831
16933
  onClick: () => {
16832
16934
  actionsRef.current.onRunCompact();
@@ -17117,7 +17219,10 @@ function useAllDirectoriesCollapsed(store, directories) {
17117
17219
  function SortableDirectoryGroup({ id, disabled, children }) {
17118
17220
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
17119
17221
  id,
17120
- disabled
17222
+ data: {
17223
+ type: "directory",
17224
+ directory: id
17225
+ }
17121
17226
  });
17122
17227
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17123
17228
  ref: setNodeRef,
@@ -17126,9 +17231,9 @@ function SortableDirectoryGroup({ id, disabled, children }) {
17126
17231
  transition
17127
17232
  },
17128
17233
  children: children({
17129
- attributes,
17130
- listeners,
17131
- isDragging
17234
+ attributes: disabled ? {} : attributes,
17235
+ listeners: disabled ? {} : listeners,
17236
+ isDragging: disabled ? false : isDragging
17132
17237
  })
17133
17238
  });
17134
17239
  }
@@ -17178,10 +17283,20 @@ function useSidebarSessionActive(store, entryKey, sessionId) {
17178
17283
  return Boolean(active.sessionId && sessionId === active.sessionId);
17179
17284
  });
17180
17285
  }
17181
- function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionStore, selectedSessionKeyStore, isPinned, isMobile, overlay, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession }) {
17286
+ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionStore, selectedSessionKeyStore, isPinned, isMobile, overlay, moveTargetDirectories, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onMoveSessionAnyDirectory, onTogglePinnedSession }) {
17182
17287
  const entry = useDirectorySessionEntry(directorySessionsStore, entryKey);
17183
17288
  const isSelected = useSidebarSessionSelected(selectedSessionKeyStore, entryKey);
17184
17289
  const isActive = useSidebarSessionActive(activeSessionStore, entryKey, entry?.id);
17290
+ const draggable = useDraggable({
17291
+ id: `session:${entryKey}`,
17292
+ disabled: overlay || !entry?.path,
17293
+ data: {
17294
+ type: "session",
17295
+ entry,
17296
+ entryKey,
17297
+ sourceDirectory: entry?.cwd || ""
17298
+ }
17299
+ });
17185
17300
  if (!entry) return null;
17186
17301
  const timestamp = entry.lastMessageAt || entry.modified || entry.lastUserMessageAt;
17187
17302
  const hasTimestamp = isValidSidebarTimestamp(timestamp);
@@ -17189,69 +17304,78 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
17189
17304
  const pinnedDirectoryLabel = isPinned ? formatDisplayPath$1(entry.cwd?.trim() || entry.path?.trim() || "") : "";
17190
17305
  const exactTimestamp = hasTimestamp && timestamp ? new Date(timestamp).toLocaleString() : void 0;
17191
17306
  const showUnread = Boolean(entry.unread) && !entry.streaming;
17192
- const hasSessionActions = Boolean(onTogglePinnedSession || entry.path && (onRenameSession || onDeleteSession)) && !overlay;
17193
- const sessionRow = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17194
- className: "group/session relative",
17195
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenuButton, {
17196
- type: "button",
17197
- "data-sidebar-session-item": true,
17198
- "data-session-key": entryKey,
17199
- isActive: isActive || isSelected,
17200
- className: cn("relative h-auto min-w-0 items-start gap-2 py-2 pr-2 pl-8 not-data-active:hover:bg-transparent! not-data-active:hover:text-sidebar-foreground! not-data-active:data-open:hover:bg-transparent! not-data-active:data-open:hover:text-sidebar-foreground!", (isActive || isSelected) && "bg-sidebar-accent text-sidebar-accent-foreground"),
17201
- onClick: (event) => {
17202
- onSessionClick?.(entry, {
17203
- multiSelectKey: isSidebarMultiSelectModifier(event),
17204
- shiftKey: event.shiftKey
17205
- });
17206
- if (isMobile) setOpenMobile(false);
17207
- },
17208
- children: [entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17209
- className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17210
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
17211
- className: "size-3.5",
17212
- "aria-label": "Session streaming"
17213
- })
17214
- }) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17215
- className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17216
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17217
- className: "size-2 rounded-full bg-primary",
17218
- "aria-label": "Session done"
17219
- })
17220
- }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17221
- className: "flex min-w-0 flex-1 items-start gap-2",
17222
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
17223
- className: "flex min-w-0 flex-1 flex-col gap-0.5",
17224
- children: [
17225
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17226
- className: "flex min-w-0 items-center gap-2",
17227
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17228
- className: "min-w-0 flex-1 truncate pr-16 font-medium",
17229
- children: entry.title
17230
- })
17231
- }),
17232
- lastMessagePreview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17233
- className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17234
- children: lastMessagePreview
17235
- }) : null,
17236
- pinnedDirectoryLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17237
- className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17238
- children: pinnedDirectoryLabel
17239
- }) : null
17240
- ]
17241
- })
17242
- })]
17243
- }), hasTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17244
- className: "absolute top-2.5 right-2 z-10 flex min-w-4 items-center justify-end",
17245
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
17246
- title: isMobile ? void 0 : exactTimestamp,
17247
- side: "right",
17248
- align: "center",
17249
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarSessionTime, {
17250
- value: timestamp,
17251
- className: "shrink-0 text-[11px] font-normal text-sidebar-foreground/50"
17252
- })
17307
+ const availableMoveTargetDirectories = moveTargetDirectories.filter((directory) => directory && directory !== entry.cwd);
17308
+ const canMoveAnyDirectory = Boolean(entry.path && onMoveSessionAnyDirectory);
17309
+ const hasMoveActions = Boolean(entry.path && onMoveSession) && availableMoveTargetDirectories.length > 0 || canMoveAnyDirectory;
17310
+ const hasSessionActions = Boolean(onTogglePinnedSession || entry.path && (onRenameSession || onDeleteSession) || hasMoveActions) && !overlay;
17311
+ const sessionButton = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenuButton, {
17312
+ type: "button",
17313
+ "data-sidebar-session-item": true,
17314
+ "data-session-key": entryKey,
17315
+ isActive: isActive || isSelected,
17316
+ className: cn("relative h-auto min-w-0 items-start gap-2 py-2 pr-2 pl-8 not-data-active:hover:bg-transparent! not-data-active:hover:text-sidebar-foreground! not-data-active:data-open:hover:bg-transparent! not-data-active:data-open:hover:text-sidebar-foreground!", (isActive || isSelected) && "bg-sidebar-accent text-sidebar-accent-foreground"),
17317
+ onClick: (event) => {
17318
+ onSessionClick?.(entry, {
17319
+ multiSelectKey: isSidebarMultiSelectModifier(event),
17320
+ shiftKey: event.shiftKey
17321
+ });
17322
+ if (isMobile) setOpenMobile(false);
17323
+ },
17324
+ children: [entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17325
+ className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17326
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
17327
+ className: "size-3.5",
17328
+ "aria-label": "Session streaming"
17253
17329
  })
17254
- }) : null]
17330
+ }) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17331
+ className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17332
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17333
+ className: "size-2 rounded-full bg-primary",
17334
+ "aria-label": "Session done"
17335
+ })
17336
+ }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17337
+ className: "flex min-w-0 flex-1 items-start gap-2",
17338
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
17339
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
17340
+ children: [
17341
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17342
+ className: "flex min-w-0 items-center gap-2",
17343
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17344
+ className: "min-w-0 flex-1 truncate pr-16 font-medium",
17345
+ children: entry.title
17346
+ })
17347
+ }),
17348
+ lastMessagePreview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17349
+ className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17350
+ children: lastMessagePreview
17351
+ }) : null,
17352
+ pinnedDirectoryLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17353
+ className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17354
+ children: pinnedDirectoryLabel
17355
+ }) : null
17356
+ ]
17357
+ })
17358
+ })]
17359
+ });
17360
+ const sessionTrailingControls = hasTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17361
+ className: "absolute top-2.5 right-2 z-10 flex min-w-4 items-center justify-end",
17362
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
17363
+ title: isMobile ? void 0 : exactTimestamp,
17364
+ side: "right",
17365
+ align: "center",
17366
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarSessionTime, {
17367
+ value: timestamp,
17368
+ className: "shrink-0 text-[11px] font-normal text-sidebar-foreground/50"
17369
+ })
17370
+ })
17371
+ }) : null;
17372
+ const sessionRow = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17373
+ ref: draggable.setNodeRef,
17374
+ className: cn("group/session relative", draggable.isDragging && !overlay && "opacity-40"),
17375
+ style: { transform: CSS$1.Translate.toString(draggable.transform) },
17376
+ ...draggable.attributes,
17377
+ ...draggable.listeners,
17378
+ children: [sessionButton, sessionTrailingControls]
17255
17379
  });
17256
17380
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarMenuItem, { children: hasSessionActions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenu$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuTrigger, { render: sessionRow }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuContent, {
17257
17381
  className: "w-44",
@@ -17260,6 +17384,19 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
17260
17384
  onClick: () => onTogglePinnedSession(entry),
17261
17385
  children: isPinned ? "Unpin" : "Pin to sidebar"
17262
17386
  }) : null,
17387
+ hasMoveActions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuSub, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuSubTrigger, { children: "Move to…" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuSubContent, {
17388
+ className: "w-72",
17389
+ children: [availableMoveTargetDirectories.map((directory) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
17390
+ onClick: () => onMoveSession?.(entry, directory),
17391
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17392
+ className: "truncate",
17393
+ children: formatDisplayPath$1(directory)
17394
+ })
17395
+ }, directory)), canMoveAnyDirectory ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
17396
+ onClick: () => onMoveSessionAnyDirectory?.(entry),
17397
+ children: "Other directory…"
17398
+ }) : null]
17399
+ })] }) : null,
17263
17400
  onRenameSession && entry.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
17264
17401
  onClick: () => onRenameSession(entry),
17265
17402
  children: "Rename"
@@ -17330,7 +17467,7 @@ function useDirectorySessions(store, directory) {
17330
17467
  function useDirectorySessionEntry(store, entryKey) {
17331
17468
  return useSelector(store, (state) => state.entriesByKey.get(entryKey), { compare: sameDirectorySessionEntry });
17332
17469
  }
17333
- var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ directory, directorySessionsStore, collapsedDirectoryStore, searchActive, directoryOrderingEnabled, activeSessionStore, selectedSessionKeyStore, pinnedSessionKeys, isMobile, setOpenMobile, isDragging, overlay = false, attributes, listeners, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory }) {
17470
+ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ directory, directorySessionsStore, collapsedDirectoryStore, searchActive, directoryOrderingEnabled, moveTargetDirectories, activeSessionStore, selectedSessionKeyStore, pinnedSessionKeys, isMobile, setOpenMobile, isDragging, isSessionDropTarget, overlay = false, attributes, listeners, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onMoveSessionAnyDirectory, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory }) {
17334
17471
  const [renderCount, setRenderCount] = import_react.useState(5);
17335
17472
  const { isLoadingSessions, sessionKeys } = useDirectorySessions(directorySessionsStore, directory);
17336
17473
  const collapsed = useDirectoryCollapsed(collapsedDirectoryStore, directory, searchActive);
@@ -17407,7 +17544,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17407
17544
  if (searchActive || overlay) return;
17408
17545
  collapsedDirectoryStore.setCollapsed(directory, !open);
17409
17546
  },
17410
- className: cn("rounded-lg py-1", overlay && "bg-sidebar shadow-lg ring-1 ring-sidebar-border/70", isDragging && !overlay && "opacity-0"),
17547
+ className: cn("rounded-lg py-1", overlay && "bg-sidebar shadow-lg ring-1 ring-sidebar-border/70", isSessionDropTarget && !overlay && "bg-sidebar-accent/40 ring-1 ring-sidebar-ring/50", isDragging && !overlay && "opacity-0"),
17411
17548
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarGroup, {
17412
17549
  className: "py-0",
17413
17550
  children: [hasDirectoryActions && !isMobile ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenu$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuTrigger, { render: directoryHeader }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuContent, {
@@ -17443,10 +17580,13 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17443
17580
  isPinned: pinnedSessionKeys.includes(entryKey),
17444
17581
  isMobile,
17445
17582
  overlay,
17583
+ moveTargetDirectories,
17446
17584
  setOpenMobile,
17447
17585
  onSessionClick,
17448
17586
  onRenameSession,
17449
17587
  onDeleteSession,
17588
+ onMoveSession,
17589
+ onMoveSessionAnyDirectory,
17450
17590
  onTogglePinnedSession
17451
17591
  }, entryKey)) }), hasMoreSessions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
17452
17592
  variant: "ghost",
@@ -17469,7 +17609,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17469
17609
  })
17470
17610
  });
17471
17611
  });
17472
- function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collapsedDirectoryStore, searchActive, activeSessionStore, selectedSessionKeyStore, isMobile, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession }) {
17612
+ function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collapsedDirectoryStore, searchActive, activeSessionStore, selectedSessionKeyStore, isMobile, moveTargetDirectories, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onMoveSessionAnyDirectory, onTogglePinnedSession }) {
17473
17613
  const collapsed = useDirectoryCollapsed(collapsedDirectoryStore, PINNED_SESSION_GROUP_COLLAPSE_KEY, searchActive);
17474
17614
  if (pinnedSessionKeys.length === 0) return null;
17475
17615
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collapsible$1, {
@@ -17500,10 +17640,13 @@ function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collaps
17500
17640
  isPinned: true,
17501
17641
  isMobile,
17502
17642
  overlay: false,
17643
+ moveTargetDirectories,
17503
17644
  setOpenMobile,
17504
17645
  onSessionClick,
17505
17646
  onRenameSession,
17506
17647
  onDeleteSession,
17648
+ onMoveSession,
17649
+ onMoveSessionAnyDirectory,
17507
17650
  onTogglePinnedSession
17508
17651
  }, entryKey)) }) }) })]
17509
17652
  })
@@ -17590,11 +17733,13 @@ function AppSidebarDirectoriesHeader({ sessionSearch, visibleDirectories, matchi
17590
17733
  })]
17591
17734
  });
17592
17735
  }
17593
- function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, directorySessionsStore, matchingSessionCount, selectedSessionKeys, activeSessionId, activeSessionKey, pinnedSessionKeys, emptyStateText, onCreateSession, onOpenAddDirectoryDialog, onOpenCommandPalette, onOpenSettings, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory, onReorderDirectories }) {
17736
+ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, directorySessionsStore, matchingSessionCount, selectedSessionKeys, activeSessionId, activeSessionKey, pinnedSessionKeys, emptyStateText, onCreateSession, onOpenAddDirectoryDialog, onOpenCommandPalette, onOpenSettings, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onMoveSessionAnyDirectory, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory, onReorderDirectories }) {
17594
17737
  const { isMobile, setOpenMobile } = useSidebar();
17595
17738
  const searchActive = sessionSearch.trim().length > 0;
17596
17739
  const directoryOrderingEnabled = !searchActive && visibleDirectories.length > 1;
17597
17740
  const [activeDirectory, setActiveDirectory] = import_react.useState(null);
17741
+ const [activeSessionDrag, setActiveSessionDrag] = import_react.useState(null);
17742
+ const [sessionDropDirectory, setSessionDropDirectory] = import_react.useState(null);
17598
17743
  const [previewDirectoryOrder, setPreviewDirectoryOrder] = import_react.useState(null);
17599
17744
  const [collapsedDirectoryStore] = import_react.useState(createCollapsedDirectoryStore);
17600
17745
  const [selectedSessionKeyStore] = import_react.useState(createSelectedSessionKeyStore);
@@ -17652,24 +17797,52 @@ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, d
17652
17797
  });
17653
17798
  };
17654
17799
  const handleDragStart = (event) => {
17800
+ const activeData = event.active.data.current;
17801
+ if (activeData?.type === "session" && activeData.entry) {
17802
+ setActiveSessionDrag({
17803
+ entryKey: activeData.entryKey || String(event.active.id),
17804
+ entry: activeData.entry,
17805
+ sourceDirectory: activeData.sourceDirectory || activeData.entry.cwd || ""
17806
+ });
17807
+ setSessionDropDirectory(null);
17808
+ return;
17809
+ }
17810
+ if (activeData?.type !== "directory" || !directoryOrderingEnabled) return;
17655
17811
  setActiveDirectory(String(event.active.id));
17656
17812
  setPreviewDirectoryOrder(visibleDirectories);
17657
17813
  };
17658
17814
  const handleDragOver = (event) => {
17815
+ const activeData = event.active.data.current;
17659
17816
  const activeId = String(event.active.id);
17660
17817
  const overId = event.over ? String(event.over.id) : "";
17818
+ if (activeData?.type === "session") {
17819
+ const overDirectory = visibleDirectories.includes(overId) ? overId : "";
17820
+ setSessionDropDirectory(overDirectory && overDirectory !== activeData.sourceDirectory ? overDirectory : null);
17821
+ return;
17822
+ }
17823
+ if (!directoryOrderingEnabled) return;
17661
17824
  if (!activeId || !overId || activeId === overId) return;
17662
17825
  movePreviewDirectory(activeId, overId);
17663
17826
  };
17664
17827
  const handleDragCancel = () => {
17665
17828
  setActiveDirectory(null);
17829
+ setActiveSessionDrag(null);
17830
+ setSessionDropDirectory(null);
17666
17831
  setPreviewDirectoryOrder(null);
17667
17832
  };
17668
17833
  const handleDragEnd = (event) => {
17834
+ const activeData = event.active.data.current;
17669
17835
  const activeId = String(event.active.id);
17670
17836
  const overId = event.over ? String(event.over.id) : "";
17837
+ if (activeData?.type === "session") {
17838
+ const targetDirectory = visibleDirectories.includes(overId) ? overId : "";
17839
+ if (activeData.entry && targetDirectory && targetDirectory !== activeData.sourceDirectory) onMoveSession?.(activeData.entry, targetDirectory);
17840
+ setActiveSessionDrag(null);
17841
+ setSessionDropDirectory(null);
17842
+ return;
17843
+ }
17671
17844
  let nextOrder = previewDirectoryOrder;
17672
- if ((!nextOrder || nextOrder.length === 0) && activeId && overId && activeId !== overId) {
17845
+ if (directoryOrderingEnabled && (!nextOrder || nextOrder.length === 0) && activeId && overId && activeId !== overId) {
17673
17846
  const oldIndex = visibleDirectories.indexOf(activeId);
17674
17847
  const newIndex = visibleDirectories.indexOf(overId);
17675
17848
  if (oldIndex !== -1 && newIndex !== -1) nextOrder = arrayMove(visibleDirectories, oldIndex, newIndex);
@@ -17686,104 +17859,136 @@ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, d
17686
17859
  onOpenSessionsDialog,
17687
17860
  onCreateSession
17688
17861
  }),
17689
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinnedSessionGroup, {
17690
- pinnedSessionKeys,
17691
- directorySessionsStore,
17692
- collapsedDirectoryStore,
17693
- searchActive,
17694
- activeSessionStore,
17695
- selectedSessionKeyStore,
17696
- isMobile,
17697
- setOpenMobile,
17698
- onSessionClick,
17699
- onRenameSession,
17700
- onDeleteSession,
17701
- onTogglePinnedSession
17702
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collapsible$1, {
17703
- open: !directoriesCollapsed,
17704
- onOpenChange: (open) => {
17705
- if (searchActive) return;
17706
- collapsedDirectoryStore.setCollapsed(DIRECTORIES_SESSION_GROUP_COLLAPSE_KEY, !open);
17707
- },
17708
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarGroup, {
17709
- className: "py-1",
17710
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppSidebarDirectoriesHeader, {
17711
- sessionSearch,
17712
- visibleDirectories,
17713
- matchingSessionCount,
17714
- collapsed: directoriesCollapsed,
17862
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DndContext, {
17863
+ sensors,
17864
+ collisionDetection: closestCenter,
17865
+ onDragStart: handleDragStart,
17866
+ onDragOver: handleDragOver,
17867
+ onDragEnd: handleDragEnd,
17868
+ onDragCancel: handleDragCancel,
17869
+ children: [
17870
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinnedSessionGroup, {
17871
+ pinnedSessionKeys,
17872
+ directorySessionsStore,
17715
17873
  collapsedDirectoryStore,
17716
- onOpenAddDirectoryDialog
17717
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarGroupContent, { children: visibleDirectories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17718
- className: "px-2 py-2",
17719
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, {
17720
- className: "rounded-xl border border-dashed bg-sidebar-accent/10 py-10",
17721
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyMedia, {
17722
- variant: "icon",
17723
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Folder, {})
17724
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: emptyStateText })] })
17874
+ searchActive,
17875
+ activeSessionStore,
17876
+ selectedSessionKeyStore,
17877
+ isMobile,
17878
+ moveTargetDirectories: visibleDirectories,
17879
+ setOpenMobile,
17880
+ onSessionClick,
17881
+ onRenameSession,
17882
+ onDeleteSession,
17883
+ onMoveSession,
17884
+ onTogglePinnedSession
17885
+ }),
17886
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collapsible$1, {
17887
+ open: !directoriesCollapsed,
17888
+ onOpenChange: (open) => {
17889
+ if (searchActive) return;
17890
+ collapsedDirectoryStore.setCollapsed(DIRECTORIES_SESSION_GROUP_COLLAPSE_KEY, !open);
17891
+ },
17892
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarGroup, {
17893
+ className: "py-1",
17894
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppSidebarDirectoriesHeader, {
17895
+ sessionSearch,
17896
+ visibleDirectories,
17897
+ matchingSessionCount,
17898
+ collapsed: directoriesCollapsed,
17899
+ collapsedDirectoryStore,
17900
+ onOpenAddDirectoryDialog
17901
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarGroupContent, { children: visibleDirectories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17902
+ className: "px-2 py-2",
17903
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, {
17904
+ className: "rounded-xl border border-dashed bg-sidebar-accent/10 py-10",
17905
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyMedia, {
17906
+ variant: "icon",
17907
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Folder, {})
17908
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: emptyStateText })] })
17909
+ })
17910
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableContext, {
17911
+ items: orderedVisibleDirectories,
17912
+ strategy: verticalListSortingStrategy,
17913
+ children: orderedVisibleDirectories.map((directory) => {
17914
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableDirectoryGroup, {
17915
+ id: directory,
17916
+ disabled: !directoryOrderingEnabled,
17917
+ children: ({ attributes, listeners, isDragging }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17918
+ directory,
17919
+ directorySessionsStore,
17920
+ collapsedDirectoryStore,
17921
+ searchActive,
17922
+ directoryOrderingEnabled,
17923
+ moveTargetDirectories: visibleDirectories,
17924
+ activeSessionStore,
17925
+ selectedSessionKeyStore,
17926
+ pinnedSessionKeys,
17927
+ isMobile,
17928
+ setOpenMobile,
17929
+ isDragging,
17930
+ isSessionDropTarget: sessionDropDirectory === directory,
17931
+ attributes,
17932
+ listeners,
17933
+ onSessionClick,
17934
+ onRenameSession,
17935
+ onDeleteSession,
17936
+ onMoveSession,
17937
+ onMoveSessionAnyDirectory,
17938
+ onTogglePinnedSession,
17939
+ onCreateSessionInDirectory,
17940
+ onDeleteOldSessionsInDirectory,
17941
+ onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17942
+ })
17943
+ }, directory);
17944
+ })
17945
+ }) }) })]
17725
17946
  })
17726
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DndContext, {
17727
- sensors,
17728
- collisionDetection: closestCenter,
17729
- onDragStart: directoryOrderingEnabled ? handleDragStart : void 0,
17730
- onDragOver: directoryOrderingEnabled ? handleDragOver : void 0,
17731
- onDragEnd: directoryOrderingEnabled ? handleDragEnd : void 0,
17732
- onDragCancel: directoryOrderingEnabled ? handleDragCancel : void 0,
17733
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableContext, {
17734
- items: orderedVisibleDirectories,
17735
- strategy: verticalListSortingStrategy,
17736
- children: orderedVisibleDirectories.map((directory) => {
17737
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableDirectoryGroup, {
17738
- id: directory,
17739
- disabled: !directoryOrderingEnabled,
17740
- children: ({ attributes, listeners, isDragging }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17741
- directory,
17742
- directorySessionsStore,
17743
- collapsedDirectoryStore,
17744
- searchActive,
17745
- directoryOrderingEnabled,
17746
- activeSessionStore,
17747
- selectedSessionKeyStore,
17748
- pinnedSessionKeys,
17749
- isMobile,
17750
- setOpenMobile,
17751
- isDragging,
17752
- attributes,
17753
- listeners,
17754
- onSessionClick,
17755
- onRenameSession,
17756
- onDeleteSession,
17757
- onTogglePinnedSession,
17758
- onCreateSessionInDirectory,
17759
- onDeleteOldSessionsInDirectory,
17760
- onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17761
- })
17762
- }, directory);
17763
- })
17764
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragOverlay, { children: activeDirectory ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17765
- directory: activeDirectory,
17947
+ }),
17948
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragOverlay, { children: activeDirectory ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17949
+ directory: activeDirectory,
17950
+ directorySessionsStore,
17951
+ collapsedDirectoryStore,
17952
+ searchActive,
17953
+ directoryOrderingEnabled,
17954
+ moveTargetDirectories: visibleDirectories,
17955
+ activeSessionStore,
17956
+ selectedSessionKeyStore,
17957
+ pinnedSessionKeys,
17958
+ isMobile,
17959
+ setOpenMobile,
17960
+ overlay: true,
17961
+ onSessionClick,
17962
+ onRenameSession,
17963
+ onDeleteSession,
17964
+ onMoveSession,
17965
+ onMoveSessionAnyDirectory,
17966
+ onTogglePinnedSession,
17967
+ onCreateSessionInDirectory,
17968
+ onDeleteOldSessionsInDirectory,
17969
+ onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17970
+ }) : activeSessionDrag ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarMenu, {
17971
+ className: "w-64 rounded-lg bg-sidebar p-1 shadow-lg ring-1 ring-sidebar-border/70",
17972
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarSessionItem, {
17973
+ entryKey: activeSessionDrag.entryKey,
17766
17974
  directorySessionsStore,
17767
- collapsedDirectoryStore,
17768
- searchActive,
17769
- directoryOrderingEnabled,
17770
17975
  activeSessionStore,
17771
17976
  selectedSessionKeyStore,
17772
- pinnedSessionKeys,
17977
+ isPinned: pinnedSessionKeys.includes(activeSessionDrag.entryKey),
17773
17978
  isMobile,
17774
- setOpenMobile,
17775
17979
  overlay: true,
17980
+ moveTargetDirectories: visibleDirectories,
17981
+ setOpenMobile,
17776
17982
  onSessionClick,
17777
17983
  onRenameSession,
17778
17984
  onDeleteSession,
17779
- onTogglePinnedSession,
17780
- onCreateSessionInDirectory,
17781
- onDeleteOldSessionsInDirectory,
17782
- onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17783
- }) : null })]
17784
- }) }) })]
17785
- })
17786
- })] }),
17985
+ onMoveSession,
17986
+ onMoveSessionAnyDirectory,
17987
+ onTogglePinnedSession
17988
+ })
17989
+ }) : null })
17990
+ ]
17991
+ }) }),
17787
17992
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarFooter, {
17788
17993
  className: "gap-2 border-t border-sidebar-border/70",
17789
17994
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenu, {
@@ -18193,6 +18398,12 @@ function AppShellSidebarController({ viewerContextId, sidebarStore, sessionWorks
18193
18398
  onDeleteSession: (entry) => {
18194
18399
  sessionWorkspaceRef.current?.openDeleteDialog([entry]);
18195
18400
  },
18401
+ onMoveSession: (entry, directory) => {
18402
+ sessionWorkspaceRef.current?.moveSessionToDirectory(entry, directory);
18403
+ },
18404
+ onMoveSessionAnyDirectory: (entry) => {
18405
+ sessionWorkspaceRef.current?.openMoveSessionDirectoryDialogForEntry(entry);
18406
+ },
18196
18407
  onTogglePinnedSession: togglePinnedSession,
18197
18408
  onCreateSessionInDirectory: (directory) => {
18198
18409
  sessionWorkspaceRef.current?.createSession(directory, { closeMobileSidebar: true });
@@ -19369,7 +19580,21 @@ function optimisticSelectionAfterDelete(selection, deletedKeys) {
19369
19580
  sidebarSessionSelectionAnchor: selection.sidebarSessionSelectionAnchor && deletedKeys.has(selection.sidebarSessionSelectionAnchor) ? "" : selection.sidebarSessionSelectionAnchor
19370
19581
  };
19371
19582
  }
19372
- function useAppShellSessionMutations({ viewerContextId, activeSessionId, sessionStateRef, setSessionState, getDirectoryIndexDataByPath, setDirectoryIndexDataByPath, getSessionsEvent, setSessionsEvent, getSidebarSelection, optimisticallyClearActiveDeletedSession, setSelectedSidebarSessionKeys, setSidebarSessionSelectionAnchor, setCompactWorkingState, isCompactAbortRequested }) {
19583
+ function replaceSessionKey(keys, previousKey, nextKey) {
19584
+ if (!previousKey || !nextKey || previousKey === nextKey) return keys;
19585
+ let changed = false;
19586
+ const seen = /* @__PURE__ */ new Set();
19587
+ const nextKeys = [];
19588
+ for (const key of keys) {
19589
+ const nextValue = key === previousKey ? nextKey : key;
19590
+ if (nextValue !== key) changed = true;
19591
+ if (!nextValue || seen.has(nextValue)) continue;
19592
+ seen.add(nextValue);
19593
+ nextKeys.push(nextValue);
19594
+ }
19595
+ return changed ? nextKeys : keys;
19596
+ }
19597
+ function useAppShellSessionMutations({ viewerContextId, activeSessionId, sessionStateRef, setSessionState, getDirectoryIndexDataByPath, setDirectoryIndexDataByPath, getSessionsEvent, setSessionsEvent, getSidebarSelection, optimisticallyClearActiveDeletedSession, setSelectedSidebarSessionKeys, setSidebarSessionSelectionAnchor, setPinnedSidebarSessionKeys, setCompactWorkingState, isCompactAbortRequested }) {
19373
19598
  const thinkingLevelRequestIdRef = import_react.useRef(0);
19374
19599
  const thinkingLevelSyncTimerRef = import_react.useRef(null);
19375
19600
  import_react.useEffect(() => {
@@ -19593,6 +19818,64 @@ function useAppShellSessionMutations({ viewerContextId, activeSessionId, session
19593
19818
  setSessionsEvent,
19594
19819
  viewerContextId
19595
19820
  ]);
19821
+ const moveSessionMutation = useMutation({ mutationFn: async ({ path, cwd }) => {
19822
+ if (!viewerContextId) throw new Error("Viewer context unavailable");
19823
+ return await fetchJson(buildRequestUrl("/api/session/move", {
19824
+ contextId: viewerContextId,
19825
+ sessionId: activeSessionId
19826
+ }), {
19827
+ method: "POST",
19828
+ headers: { "content-type": "application/json" },
19829
+ body: JSON.stringify({
19830
+ path,
19831
+ cwd
19832
+ })
19833
+ });
19834
+ } });
19835
+ const moveSessionPath = import_react.useCallback(async (entry, directory) => {
19836
+ if (!viewerContextId || !entry.path) return false;
19837
+ const nextDirectory = directory.trim();
19838
+ if (!nextDirectory) {
19839
+ toast.error("Directory is required");
19840
+ return false;
19841
+ }
19842
+ if (entry.cwd === nextDirectory) return false;
19843
+ try {
19844
+ const response = await moveSessionMutation.mutateAsync({
19845
+ path: entry.path,
19846
+ cwd: nextDirectory
19847
+ });
19848
+ const previousKey = sessionListEntryKey({ path: response.previousPath || entry.path });
19849
+ const nextKey = sessionListEntryKey({
19850
+ path: response.path,
19851
+ id: response.sessionId || entry.id
19852
+ });
19853
+ setSelectedSidebarSessionKeys((current) => replaceSessionKey(current, previousKey, nextKey));
19854
+ setSidebarSessionSelectionAnchor((current) => current === previousKey ? nextKey : current);
19855
+ setPinnedSidebarSessionKeys((current) => {
19856
+ const next = replaceSessionKey(current, previousKey, nextKey);
19857
+ if (next !== current) safeLocalStorageSetItem(PINNED_SESSIONS_STORAGE_KEY, JSON.stringify(next));
19858
+ return next;
19859
+ });
19860
+ setSessionState((current) => current.sessionFile === response.previousPath ? {
19861
+ ...current,
19862
+ cwd: response.cwd,
19863
+ sessionFile: response.path
19864
+ } : current);
19865
+ toast.success("Moved session");
19866
+ return true;
19867
+ } catch (error) {
19868
+ toast.error(error instanceof Error ? error.message : "Failed to move session");
19869
+ return false;
19870
+ }
19871
+ }, [
19872
+ moveSessionMutation,
19873
+ setPinnedSidebarSessionKeys,
19874
+ setSelectedSidebarSessionKeys,
19875
+ setSessionState,
19876
+ setSidebarSessionSelectionAnchor,
19877
+ viewerContextId
19878
+ ]);
19596
19879
  const deleteSessionMutation = useMutation({ mutationFn: async (paths) => {
19597
19880
  if (!viewerContextId) throw new Error("Viewer context unavailable");
19598
19881
  await fetchJson(buildRequestUrl("/api/sessions/delete", {
@@ -19660,6 +19943,7 @@ function useAppShellSessionMutations({ viewerContextId, activeSessionId, session
19660
19943
  setSidebarSessionSelectionAnchor,
19661
19944
  viewerContextId
19662
19945
  ]),
19946
+ moveSessionPath,
19663
19947
  renameSessionPath,
19664
19948
  runClone,
19665
19949
  runCompact,
@@ -20209,12 +20493,12 @@ function hasSelectedText(target) {
20209
20493
  }
20210
20494
  return false;
20211
20495
  }
20212
- function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, compactRunningRef, deleteOpenRef, forkOpenRef, gitCommitOpenRef, pendingUiRequestOpenRef, renameOpenRef, sessionSearchInputRef, sessionsOpenRef, settingsOpenRef, shortcutActionsRef, shortcutStateRef, treeOpenRef }) {
20496
+ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, compactRunningRef, deleteOpenRef, forkOpenRef, gitCommitOpenRef, moveSessionDirectoryOpenRef, pendingUiRequestOpenRef, renameOpenRef, sessionSearchInputRef, sessionsOpenRef, settingsOpenRef, shortcutActionsRef, shortcutStateRef, treeOpenRef }) {
20213
20497
  const lastEscapeKeyDownAtRef = import_react.useRef(0);
20214
20498
  const getShortcutContext = (event) => {
20215
20499
  const shortcutState = shortcutStateRef.current;
20216
20500
  const commandPaletteOpen = commandPaletteOpenRef.current;
20217
- const blockingModalOpen = addDirectoryOpenRef.current || renameOpenRef.current || deleteOpenRef.current || forkOpenRef.current || gitCommitOpenRef.current || treeOpenRef.current || sessionsOpenRef.current || settingsOpenRef.current || pendingUiRequestOpenRef.current;
20501
+ const blockingModalOpen = addDirectoryOpenRef.current || renameOpenRef.current || deleteOpenRef.current || forkOpenRef.current || gitCommitOpenRef.current || moveSessionDirectoryOpenRef.current || treeOpenRef.current || sessionsOpenRef.current || settingsOpenRef.current || pendingUiRequestOpenRef.current;
20218
20502
  const activeElement = document.activeElement;
20219
20503
  const activeElementIsConversationViewport = activeElement instanceof HTMLElement && activeElement.closest("[data-conversation-viewport=\"true\"]") !== null;
20220
20504
  const focusedSidebarSessionKey = activeElement instanceof HTMLElement ? activeElement.dataset.sessionKey?.trim() ?? "" : "";
@@ -20742,6 +21026,9 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
20742
21026
  const commandPaletteOpenRef = import_react.useRef(false);
20743
21027
  const addDirectoryDialogRef = import_react.useRef(null);
20744
21028
  const addDirectoryOpenRef = import_react.useRef(false);
21029
+ const moveSessionDirectoryDialogRef = import_react.useRef(null);
21030
+ const moveSessionDirectoryOpenRef = import_react.useRef(false);
21031
+ const moveSessionDirectoryTargetRef = import_react.useRef(null);
20745
21032
  const renameDialogRef = import_react.useRef(null);
20746
21033
  const renameOpenRef = import_react.useRef(false);
20747
21034
  const deleteDialogRef = import_react.useRef(null);
@@ -21270,20 +21557,36 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
21270
21557
  const openDeleteOldDirectorySessionsDialog = (directory) => {
21271
21558
  deleteOldDirectorySessionsDialogRef.current?.open(directory);
21272
21559
  };
21273
- const openDeleteDialogForCurrentSession = () => {
21560
+ const currentSessionListEntry = () => {
21274
21561
  const currentState = sessionStateRef.current;
21275
- if (!currentState.sessionFile) return;
21276
- openDeleteDialog([{
21562
+ if (!currentState.sessionFile) return void 0;
21563
+ return {
21277
21564
  path: currentState.sessionFile,
21278
21565
  id: currentState.sessionId,
21566
+ cwd: currentState.cwd,
21279
21567
  title: getCurrentSessionTitleFromState(currentState),
21280
21568
  name: currentState.sessionName,
21281
21569
  modified: currentState.modified
21282
- }]);
21570
+ };
21571
+ };
21572
+ const openDeleteDialogForCurrentSession = () => {
21573
+ const currentEntry = currentSessionListEntry();
21574
+ if (!currentEntry) return;
21575
+ openDeleteDialog([currentEntry]);
21283
21576
  };
21284
21577
  const openAddDirectoryDialog = () => {
21285
21578
  addDirectoryDialogRef.current?.open();
21286
21579
  };
21580
+ const openMoveSessionDirectoryDialogForEntry = (entry) => {
21581
+ if (!entry.path) return;
21582
+ moveSessionDirectoryTargetRef.current = entry;
21583
+ moveSessionDirectoryDialogRef.current?.open();
21584
+ };
21585
+ const openMoveSessionDirectoryDialogForCurrentSession = () => {
21586
+ const currentEntry = currentSessionListEntry();
21587
+ if (!currentEntry) return;
21588
+ openMoveSessionDirectoryDialogForEntry(currentEntry);
21589
+ };
21287
21590
  const openForkDialog = async () => {
21288
21591
  await forkDialogRef.current?.open();
21289
21592
  };
@@ -21713,7 +22016,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
21713
22016
  if (workingStateStore.state?.label === "Compacting context...") setStoreState(workingStateStore, null);
21714
22017
  }, [setCompactRunningState, workingStateStore]);
21715
22018
  const isCompactAbortRequested = import_react.useCallback(() => compactAbortRequestedRef.current, []);
21716
- const { cycleThinkingLevel, deleteSessions, renameSessionPath, runClone, runCompact, setModel, setThinkingBlocksHidden, setThinkingLevel, toggleHideThinking } = useAppShellSessionMutations({
22019
+ const { cycleThinkingLevel, deleteSessions, moveSessionPath, renameSessionPath, runClone, runCompact, setModel, setThinkingBlocksHidden, setThinkingLevel, toggleHideThinking } = useAppShellSessionMutations({
21717
22020
  viewerContextId,
21718
22021
  activeSessionId,
21719
22022
  sessionStateRef,
@@ -21756,9 +22059,34 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
21756
22059
  },
21757
22060
  setSelectedSidebarSessionKeys: sidebarStore.setSelectedSidebarSessionKeys,
21758
22061
  setSidebarSessionSelectionAnchor: sidebarStore.setSidebarSessionSelectionAnchor,
22062
+ setPinnedSidebarSessionKeys: sidebarStore.setPinnedSidebarSessionKeys,
21759
22063
  setCompactWorkingState,
21760
22064
  isCompactAbortRequested
21761
22065
  });
22066
+ const moveSessionToDirectory = async (entry, directory) => {
22067
+ const moved = await moveSessionPath(entry, directory);
22068
+ if (moved) rememberRecentDirectory(directory);
22069
+ return moved;
22070
+ };
22071
+ const moveSessionDirectoryTargetToPath = async (directory) => {
22072
+ const target = moveSessionDirectoryTargetRef.current;
22073
+ if (!target) return false;
22074
+ const moved = await moveSessionToDirectory(target, directory);
22075
+ if (moved) moveSessionDirectoryTargetRef.current = null;
22076
+ return moved;
22077
+ };
22078
+ const moveCurrentSessionToDirectory = async (directory) => {
22079
+ const currentState = sessionStateRef.current;
22080
+ if (!currentState.sessionFile) return false;
22081
+ return await moveSessionToDirectory({
22082
+ path: currentState.sessionFile,
22083
+ id: currentState.sessionId,
22084
+ cwd: currentState.cwd,
22085
+ title: getCurrentSessionTitleFromState(currentState),
22086
+ name: currentState.sessionName,
22087
+ modified: currentState.modified
22088
+ }, directory);
22089
+ };
21762
22090
  const setToolBlocksHidden = (hidden) => {
21763
22091
  setHideToolBlocks(hidden);
21764
22092
  safeLocalStorageSetItem(HIDE_TOOL_BLOCKS_STORAGE_KEY, hidden ? "1" : "0");
@@ -22371,6 +22699,8 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22371
22699
  createSession,
22372
22700
  onDeleteCurrentSession: openDeleteDialogForCurrentSession,
22373
22701
  onForkSession: openForkDialog,
22702
+ onMoveCurrentSession: moveCurrentSessionToDirectory,
22703
+ onMoveCurrentSessionToAnyDirectory: openMoveSessionDirectoryDialogForCurrentSession,
22374
22704
  onRenameSession: openRenameDialog,
22375
22705
  onRunCompact: runCompact,
22376
22706
  onToggleCurrentSessionPinned: toggleCurrentSessionPinned,
@@ -22385,6 +22715,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22385
22715
  deleteOpenRef,
22386
22716
  forkOpenRef,
22387
22717
  gitCommitOpenRef,
22718
+ moveSessionDirectoryOpenRef,
22388
22719
  pendingUiRequestOpenRef: uiRequestOpenRef,
22389
22720
  renameOpenRef,
22390
22721
  sessionSearchInputRef,
@@ -22424,7 +22755,9 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22424
22755
  openAddDirectoryDialog,
22425
22756
  openCommandPalette,
22426
22757
  openDeleteDialog,
22758
+ moveSessionToDirectory,
22427
22759
  openDeleteOldDirectorySessionsDialog,
22760
+ openMoveSessionDirectoryDialogForEntry,
22428
22761
  openRenameDialogForEntry,
22429
22762
  openSessionsDialog,
22430
22763
  openSettingsDialog,
@@ -22439,6 +22772,8 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22439
22772
  openCommandPalette: actions?.openCommandPalette ?? openCommandPalette,
22440
22773
  openDeleteDialog: actions?.openDeleteDialog ?? openDeleteDialog,
22441
22774
  openDeleteOldDirectorySessionsDialog: actions?.openDeleteOldDirectorySessionsDialog ?? openDeleteOldDirectorySessionsDialog,
22775
+ moveSessionToDirectory: actions?.moveSessionToDirectory ?? moveSessionToDirectory,
22776
+ openMoveSessionDirectoryDialogForEntry: actions?.openMoveSessionDirectoryDialogForEntry ?? openMoveSessionDirectoryDialogForEntry,
22442
22777
  openRenameDialogForEntry: actions?.openRenameDialogForEntry ?? openRenameDialogForEntry,
22443
22778
  openSessionsDialog: actions?.openSessionsDialog ?? openSessionsDialog,
22444
22779
  openSettingsDialog: actions?.openSettingsDialog ?? openSettingsDialog,
@@ -22449,8 +22784,10 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22449
22784
  handleSelectSession,
22450
22785
  openAddDirectoryDialog,
22451
22786
  openCommandPalette,
22787
+ moveSessionToDirectory,
22452
22788
  openDeleteDialog,
22453
22789
  openDeleteOldDirectorySessionsDialog,
22790
+ openMoveSessionDirectoryDialogForEntry,
22454
22791
  openRenameDialogForEntry,
22455
22792
  openSessionsDialog,
22456
22793
  openSettingsDialog
@@ -22545,6 +22882,9 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22545
22882
  gitCommitOpenRef,
22546
22883
  displaySettingsStore,
22547
22884
  knownDirectories,
22885
+ moveSessionDirectoryDialogRef,
22886
+ moveSessionDirectoryOpenRef,
22887
+ moveSessionDirectoryTargetToPath,
22548
22888
  onAutoScrollEnabledChange: setAutoScroll,
22549
22889
  onCenterMessagesChange: setMessagesCentered,
22550
22890
  onHideThinkingBlocksChange: (hidden) => {