@alivault/pico 0.7.4 → 0.8.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-D25nKlrc.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-BJQYLalK.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;
@@ -13288,6 +13288,32 @@ function ContextMenuItem({ className, inset, variant = "default", ...props }) {
13288
13288
  ...props
13289
13289
  });
13290
13290
  }
13291
+ function ContextMenuSub({ ...props }) {
13292
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuSubmenuRoot, {
13293
+ "data-slot": "context-menu-sub",
13294
+ ...props
13295
+ });
13296
+ }
13297
+ function ContextMenuSubTrigger({ className, inset, children, ...props }) {
13298
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MenuSubmenuTrigger, {
13299
+ "data-slot": "context-menu-sub-trigger",
13300
+ "data-inset": inset,
13301
+ 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),
13302
+ ...props,
13303
+ children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "ml-auto" })]
13304
+ });
13305
+ }
13306
+ function ContextMenuSubContent({ align = "start", alignOffset = -3, side = "right", sideOffset = 0, className, ...props }) {
13307
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuContent, {
13308
+ "data-slot": "context-menu-sub-content",
13309
+ 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),
13310
+ align,
13311
+ alignOffset,
13312
+ side,
13313
+ sideOffset,
13314
+ ...props
13315
+ });
13316
+ }
13291
13317
  function ContextMenuSeparator({ className, ...props }) {
13292
13318
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {
13293
13319
  "data-slot": "context-menu-separator",
@@ -16726,6 +16752,7 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
16726
16752
  const { isMobile: sidebarIsMobile, openMobile: sidebarOpenMobile, state: sidebarState } = useSidebar();
16727
16753
  const showCollapsedNewSessionButton = !(sidebarIsMobile ? sidebarOpenMobile : sidebarState === "expanded");
16728
16754
  const displaySessionTitle = isSessionViewLoading ? loadingDisplaySessionTitle : getCurrentSessionTitleFromState(sessionHeaderState);
16755
+ const moveSessionDirectoryOptions = newSessionDirectoryOptions.filter((option) => option.path !== displaySessionCwd);
16729
16756
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16730
16757
  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
16758
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -16827,6 +16854,27 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
16827
16854
  },
16828
16855
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: currentSessionPinned ? "Unpin from sidebar" : "Pin to sidebar" })
16829
16856
  }),
16857
+ moveSessionDirectoryOptions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuSub, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSubTrigger, {
16858
+ disabled: !sessionHeaderState.sessionHasFile,
16859
+ children: "Move to…"
16860
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSubContent, {
16861
+ className: "w-72",
16862
+ children: moveSessionDirectoryOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuItem, {
16863
+ onClick: () => {
16864
+ actionsRef.current.onMoveCurrentSession(option.path);
16865
+ },
16866
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16867
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
16868
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16869
+ className: "text-xs text-muted-foreground",
16870
+ children: option.label
16871
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16872
+ className: "truncate",
16873
+ children: formatDisplayPath$1(option.path)
16874
+ })]
16875
+ })
16876
+ }, option.path))
16877
+ })] }) : null,
16830
16878
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuItem, {
16831
16879
  onClick: () => {
16832
16880
  actionsRef.current.onRunCompact();
@@ -17117,7 +17165,10 @@ function useAllDirectoriesCollapsed(store, directories) {
17117
17165
  function SortableDirectoryGroup({ id, disabled, children }) {
17118
17166
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
17119
17167
  id,
17120
- disabled
17168
+ data: {
17169
+ type: "directory",
17170
+ directory: id
17171
+ }
17121
17172
  });
17122
17173
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
17123
17174
  ref: setNodeRef,
@@ -17126,9 +17177,9 @@ function SortableDirectoryGroup({ id, disabled, children }) {
17126
17177
  transition
17127
17178
  },
17128
17179
  children: children({
17129
- attributes,
17130
- listeners,
17131
- isDragging
17180
+ attributes: disabled ? {} : attributes,
17181
+ listeners: disabled ? {} : listeners,
17182
+ isDragging: disabled ? false : isDragging
17132
17183
  })
17133
17184
  });
17134
17185
  }
@@ -17178,10 +17229,20 @@ function useSidebarSessionActive(store, entryKey, sessionId) {
17178
17229
  return Boolean(active.sessionId && sessionId === active.sessionId);
17179
17230
  });
17180
17231
  }
17181
- function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionStore, selectedSessionKeyStore, isPinned, isMobile, overlay, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession }) {
17232
+ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionStore, selectedSessionKeyStore, isPinned, isMobile, overlay, moveTargetDirectories, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onTogglePinnedSession }) {
17182
17233
  const entry = useDirectorySessionEntry(directorySessionsStore, entryKey);
17183
17234
  const isSelected = useSidebarSessionSelected(selectedSessionKeyStore, entryKey);
17184
17235
  const isActive = useSidebarSessionActive(activeSessionStore, entryKey, entry?.id);
17236
+ const draggable = useDraggable({
17237
+ id: `session:${entryKey}`,
17238
+ disabled: overlay || !entry?.path,
17239
+ data: {
17240
+ type: "session",
17241
+ entry,
17242
+ entryKey,
17243
+ sourceDirectory: entry?.cwd || ""
17244
+ }
17245
+ });
17185
17246
  if (!entry) return null;
17186
17247
  const timestamp = entry.lastMessageAt || entry.modified || entry.lastUserMessageAt;
17187
17248
  const hasTimestamp = isValidSidebarTimestamp(timestamp);
@@ -17189,69 +17250,77 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
17189
17250
  const pinnedDirectoryLabel = isPinned ? formatDisplayPath$1(entry.cwd?.trim() || entry.path?.trim() || "") : "";
17190
17251
  const exactTimestamp = hasTimestamp && timestamp ? new Date(timestamp).toLocaleString() : void 0;
17191
17252
  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
- })
17253
+ const availableMoveTargetDirectories = moveTargetDirectories.filter((directory) => directory && directory !== entry.cwd);
17254
+ const hasMoveTargets = Boolean(entry.path && onMoveSession) && availableMoveTargetDirectories.length > 0;
17255
+ const hasSessionActions = Boolean(onTogglePinnedSession || entry.path && (onRenameSession || onDeleteSession) || hasMoveTargets) && !overlay;
17256
+ const sessionButton = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenuButton, {
17257
+ type: "button",
17258
+ "data-sidebar-session-item": true,
17259
+ "data-session-key": entryKey,
17260
+ isActive: isActive || isSelected,
17261
+ 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"),
17262
+ onClick: (event) => {
17263
+ onSessionClick?.(entry, {
17264
+ multiSelectKey: isSidebarMultiSelectModifier(event),
17265
+ shiftKey: event.shiftKey
17266
+ });
17267
+ if (isMobile) setOpenMobile(false);
17268
+ },
17269
+ children: [entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17270
+ className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17271
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
17272
+ className: "size-3.5",
17273
+ "aria-label": "Session streaming"
17253
17274
  })
17254
- }) : null]
17275
+ }) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17276
+ className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
17277
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17278
+ className: "size-2 rounded-full bg-primary",
17279
+ "aria-label": "Session done"
17280
+ })
17281
+ }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17282
+ className: "flex min-w-0 flex-1 items-start gap-2",
17283
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
17284
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
17285
+ children: [
17286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17287
+ className: "flex min-w-0 items-center gap-2",
17288
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17289
+ className: "min-w-0 flex-1 truncate pr-16 font-medium",
17290
+ children: entry.title
17291
+ })
17292
+ }),
17293
+ lastMessagePreview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17294
+ className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17295
+ children: lastMessagePreview
17296
+ }) : null,
17297
+ pinnedDirectoryLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17298
+ className: "min-w-0 truncate text-[11px] font-normal text-sidebar-foreground/50",
17299
+ children: pinnedDirectoryLabel
17300
+ }) : null
17301
+ ]
17302
+ })
17303
+ })]
17304
+ });
17305
+ const sessionTrailingControls = hasTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17306
+ className: "absolute top-2.5 right-2 z-10 flex min-w-4 items-center justify-end",
17307
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
17308
+ title: isMobile ? void 0 : exactTimestamp,
17309
+ side: "right",
17310
+ align: "center",
17311
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarSessionTime, {
17312
+ value: timestamp,
17313
+ className: "shrink-0 text-[11px] font-normal text-sidebar-foreground/50"
17314
+ })
17315
+ })
17316
+ }) : null;
17317
+ const sessionRow = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
17318
+ ref: draggable.setNodeRef,
17319
+ className: cn("group/session relative", draggable.isDragging && !overlay && "opacity-40"),
17320
+ style: { transform: CSS$1.Translate.toString(draggable.transform) },
17321
+ ...draggable.attributes,
17322
+ ...draggable.listeners,
17323
+ children: [sessionButton, sessionTrailingControls]
17255
17324
  });
17256
17325
  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
17326
  className: "w-44",
@@ -17260,6 +17329,16 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
17260
17329
  onClick: () => onTogglePinnedSession(entry),
17261
17330
  children: isPinned ? "Unpin" : "Pin to sidebar"
17262
17331
  }) : null,
17332
+ hasMoveTargets ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuSub, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuSubTrigger, { children: "Move to…" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuSubContent, {
17333
+ className: "w-72",
17334
+ children: availableMoveTargetDirectories.map((directory) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
17335
+ onClick: () => onMoveSession?.(entry, directory),
17336
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
17337
+ className: "truncate",
17338
+ children: formatDisplayPath$1(directory)
17339
+ })
17340
+ }, directory))
17341
+ })] }) : null,
17263
17342
  onRenameSession && entry.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
17264
17343
  onClick: () => onRenameSession(entry),
17265
17344
  children: "Rename"
@@ -17330,7 +17409,7 @@ function useDirectorySessions(store, directory) {
17330
17409
  function useDirectorySessionEntry(store, entryKey) {
17331
17410
  return useSelector(store, (state) => state.entriesByKey.get(entryKey), { compare: sameDirectorySessionEntry });
17332
17411
  }
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 }) {
17412
+ 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, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory }) {
17334
17413
  const [renderCount, setRenderCount] = import_react.useState(5);
17335
17414
  const { isLoadingSessions, sessionKeys } = useDirectorySessions(directorySessionsStore, directory);
17336
17415
  const collapsed = useDirectoryCollapsed(collapsedDirectoryStore, directory, searchActive);
@@ -17407,7 +17486,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17407
17486
  if (searchActive || overlay) return;
17408
17487
  collapsedDirectoryStore.setCollapsed(directory, !open);
17409
17488
  },
17410
- className: cn("rounded-lg py-1", overlay && "bg-sidebar shadow-lg ring-1 ring-sidebar-border/70", isDragging && !overlay && "opacity-0"),
17489
+ 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
17490
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarGroup, {
17412
17491
  className: "py-0",
17413
17492
  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 +17522,12 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17443
17522
  isPinned: pinnedSessionKeys.includes(entryKey),
17444
17523
  isMobile,
17445
17524
  overlay,
17525
+ moveTargetDirectories,
17446
17526
  setOpenMobile,
17447
17527
  onSessionClick,
17448
17528
  onRenameSession,
17449
17529
  onDeleteSession,
17530
+ onMoveSession,
17450
17531
  onTogglePinnedSession
17451
17532
  }, entryKey)) }), hasMoreSessions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
17452
17533
  variant: "ghost",
@@ -17469,7 +17550,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
17469
17550
  })
17470
17551
  });
17471
17552
  });
17472
- function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collapsedDirectoryStore, searchActive, activeSessionStore, selectedSessionKeyStore, isMobile, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onTogglePinnedSession }) {
17553
+ function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collapsedDirectoryStore, searchActive, activeSessionStore, selectedSessionKeyStore, isMobile, moveTargetDirectories, setOpenMobile, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onTogglePinnedSession }) {
17473
17554
  const collapsed = useDirectoryCollapsed(collapsedDirectoryStore, PINNED_SESSION_GROUP_COLLAPSE_KEY, searchActive);
17474
17555
  if (pinnedSessionKeys.length === 0) return null;
17475
17556
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collapsible$1, {
@@ -17500,10 +17581,12 @@ function PinnedSessionGroup({ pinnedSessionKeys, directorySessionsStore, collaps
17500
17581
  isPinned: true,
17501
17582
  isMobile,
17502
17583
  overlay: false,
17584
+ moveTargetDirectories,
17503
17585
  setOpenMobile,
17504
17586
  onSessionClick,
17505
17587
  onRenameSession,
17506
17588
  onDeleteSession,
17589
+ onMoveSession,
17507
17590
  onTogglePinnedSession
17508
17591
  }, entryKey)) }) }) })]
17509
17592
  })
@@ -17590,11 +17673,13 @@ function AppSidebarDirectoriesHeader({ sessionSearch, visibleDirectories, matchi
17590
17673
  })]
17591
17674
  });
17592
17675
  }
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 }) {
17676
+ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, directorySessionsStore, matchingSessionCount, selectedSessionKeys, activeSessionId, activeSessionKey, pinnedSessionKeys, emptyStateText, onCreateSession, onOpenAddDirectoryDialog, onOpenCommandPalette, onOpenSettings, onSessionClick, onRenameSession, onDeleteSession, onMoveSession, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory, onReorderDirectories }) {
17594
17677
  const { isMobile, setOpenMobile } = useSidebar();
17595
17678
  const searchActive = sessionSearch.trim().length > 0;
17596
17679
  const directoryOrderingEnabled = !searchActive && visibleDirectories.length > 1;
17597
17680
  const [activeDirectory, setActiveDirectory] = import_react.useState(null);
17681
+ const [activeSessionDrag, setActiveSessionDrag] = import_react.useState(null);
17682
+ const [sessionDropDirectory, setSessionDropDirectory] = import_react.useState(null);
17598
17683
  const [previewDirectoryOrder, setPreviewDirectoryOrder] = import_react.useState(null);
17599
17684
  const [collapsedDirectoryStore] = import_react.useState(createCollapsedDirectoryStore);
17600
17685
  const [selectedSessionKeyStore] = import_react.useState(createSelectedSessionKeyStore);
@@ -17652,24 +17737,52 @@ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, d
17652
17737
  });
17653
17738
  };
17654
17739
  const handleDragStart = (event) => {
17740
+ const activeData = event.active.data.current;
17741
+ if (activeData?.type === "session" && activeData.entry) {
17742
+ setActiveSessionDrag({
17743
+ entryKey: activeData.entryKey || String(event.active.id),
17744
+ entry: activeData.entry,
17745
+ sourceDirectory: activeData.sourceDirectory || activeData.entry.cwd || ""
17746
+ });
17747
+ setSessionDropDirectory(null);
17748
+ return;
17749
+ }
17750
+ if (activeData?.type !== "directory" || !directoryOrderingEnabled) return;
17655
17751
  setActiveDirectory(String(event.active.id));
17656
17752
  setPreviewDirectoryOrder(visibleDirectories);
17657
17753
  };
17658
17754
  const handleDragOver = (event) => {
17755
+ const activeData = event.active.data.current;
17659
17756
  const activeId = String(event.active.id);
17660
17757
  const overId = event.over ? String(event.over.id) : "";
17758
+ if (activeData?.type === "session") {
17759
+ const overDirectory = visibleDirectories.includes(overId) ? overId : "";
17760
+ setSessionDropDirectory(overDirectory && overDirectory !== activeData.sourceDirectory ? overDirectory : null);
17761
+ return;
17762
+ }
17763
+ if (!directoryOrderingEnabled) return;
17661
17764
  if (!activeId || !overId || activeId === overId) return;
17662
17765
  movePreviewDirectory(activeId, overId);
17663
17766
  };
17664
17767
  const handleDragCancel = () => {
17665
17768
  setActiveDirectory(null);
17769
+ setActiveSessionDrag(null);
17770
+ setSessionDropDirectory(null);
17666
17771
  setPreviewDirectoryOrder(null);
17667
17772
  };
17668
17773
  const handleDragEnd = (event) => {
17774
+ const activeData = event.active.data.current;
17669
17775
  const activeId = String(event.active.id);
17670
17776
  const overId = event.over ? String(event.over.id) : "";
17777
+ if (activeData?.type === "session") {
17778
+ const targetDirectory = visibleDirectories.includes(overId) ? overId : "";
17779
+ if (activeData.entry && targetDirectory && targetDirectory !== activeData.sourceDirectory) onMoveSession?.(activeData.entry, targetDirectory);
17780
+ setActiveSessionDrag(null);
17781
+ setSessionDropDirectory(null);
17782
+ return;
17783
+ }
17671
17784
  let nextOrder = previewDirectoryOrder;
17672
- if ((!nextOrder || nextOrder.length === 0) && activeId && overId && activeId !== overId) {
17785
+ if (directoryOrderingEnabled && (!nextOrder || nextOrder.length === 0) && activeId && overId && activeId !== overId) {
17673
17786
  const oldIndex = visibleDirectories.indexOf(activeId);
17674
17787
  const newIndex = visibleDirectories.indexOf(overId);
17675
17788
  if (oldIndex !== -1 && newIndex !== -1) nextOrder = arrayMove(visibleDirectories, oldIndex, newIndex);
@@ -17686,104 +17799,133 @@ function AppSidebar({ sessionSearch, onOpenSessionsDialog, visibleDirectories, d
17686
17799
  onOpenSessionsDialog,
17687
17800
  onCreateSession
17688
17801
  }),
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,
17802
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DndContext, {
17803
+ sensors,
17804
+ collisionDetection: closestCenter,
17805
+ onDragStart: handleDragStart,
17806
+ onDragOver: handleDragOver,
17807
+ onDragEnd: handleDragEnd,
17808
+ onDragCancel: handleDragCancel,
17809
+ children: [
17810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinnedSessionGroup, {
17811
+ pinnedSessionKeys,
17812
+ directorySessionsStore,
17715
17813
  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 })] })
17814
+ searchActive,
17815
+ activeSessionStore,
17816
+ selectedSessionKeyStore,
17817
+ isMobile,
17818
+ moveTargetDirectories: visibleDirectories,
17819
+ setOpenMobile,
17820
+ onSessionClick,
17821
+ onRenameSession,
17822
+ onDeleteSession,
17823
+ onMoveSession,
17824
+ onTogglePinnedSession
17825
+ }),
17826
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collapsible$1, {
17827
+ open: !directoriesCollapsed,
17828
+ onOpenChange: (open) => {
17829
+ if (searchActive) return;
17830
+ collapsedDirectoryStore.setCollapsed(DIRECTORIES_SESSION_GROUP_COLLAPSE_KEY, !open);
17831
+ },
17832
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarGroup, {
17833
+ className: "py-1",
17834
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppSidebarDirectoriesHeader, {
17835
+ sessionSearch,
17836
+ visibleDirectories,
17837
+ matchingSessionCount,
17838
+ collapsed: directoriesCollapsed,
17839
+ collapsedDirectoryStore,
17840
+ onOpenAddDirectoryDialog
17841
+ }), /* @__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", {
17842
+ className: "px-2 py-2",
17843
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, {
17844
+ className: "rounded-xl border border-dashed bg-sidebar-accent/10 py-10",
17845
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyMedia, {
17846
+ variant: "icon",
17847
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Folder, {})
17848
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: emptyStateText })] })
17849
+ })
17850
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableContext, {
17851
+ items: orderedVisibleDirectories,
17852
+ strategy: verticalListSortingStrategy,
17853
+ children: orderedVisibleDirectories.map((directory) => {
17854
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SortableDirectoryGroup, {
17855
+ id: directory,
17856
+ disabled: !directoryOrderingEnabled,
17857
+ children: ({ attributes, listeners, isDragging }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17858
+ directory,
17859
+ directorySessionsStore,
17860
+ collapsedDirectoryStore,
17861
+ searchActive,
17862
+ directoryOrderingEnabled,
17863
+ moveTargetDirectories: visibleDirectories,
17864
+ activeSessionStore,
17865
+ selectedSessionKeyStore,
17866
+ pinnedSessionKeys,
17867
+ isMobile,
17868
+ setOpenMobile,
17869
+ isDragging,
17870
+ isSessionDropTarget: sessionDropDirectory === directory,
17871
+ attributes,
17872
+ listeners,
17873
+ onSessionClick,
17874
+ onRenameSession,
17875
+ onDeleteSession,
17876
+ onMoveSession,
17877
+ onTogglePinnedSession,
17878
+ onCreateSessionInDirectory,
17879
+ onDeleteOldSessionsInDirectory,
17880
+ onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17881
+ })
17882
+ }, directory);
17883
+ })
17884
+ }) }) })]
17725
17885
  })
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,
17886
+ }),
17887
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragOverlay, { children: activeDirectory ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectorySessionGroup, {
17888
+ directory: activeDirectory,
17889
+ directorySessionsStore,
17890
+ collapsedDirectoryStore,
17891
+ searchActive,
17892
+ directoryOrderingEnabled,
17893
+ moveTargetDirectories: visibleDirectories,
17894
+ activeSessionStore,
17895
+ selectedSessionKeyStore,
17896
+ pinnedSessionKeys,
17897
+ isMobile,
17898
+ setOpenMobile,
17899
+ overlay: true,
17900
+ onSessionClick,
17901
+ onRenameSession,
17902
+ onDeleteSession,
17903
+ onMoveSession,
17904
+ onTogglePinnedSession,
17905
+ onCreateSessionInDirectory,
17906
+ onDeleteOldSessionsInDirectory,
17907
+ onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17908
+ }) : activeSessionDrag ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarMenu, {
17909
+ className: "w-64 rounded-lg bg-sidebar p-1 shadow-lg ring-1 ring-sidebar-border/70",
17910
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarSessionItem, {
17911
+ entryKey: activeSessionDrag.entryKey,
17766
17912
  directorySessionsStore,
17767
- collapsedDirectoryStore,
17768
- searchActive,
17769
- directoryOrderingEnabled,
17770
17913
  activeSessionStore,
17771
17914
  selectedSessionKeyStore,
17772
- pinnedSessionKeys,
17915
+ isPinned: pinnedSessionKeys.includes(activeSessionDrag.entryKey),
17773
17916
  isMobile,
17774
- setOpenMobile,
17775
17917
  overlay: true,
17918
+ moveTargetDirectories: visibleDirectories,
17919
+ setOpenMobile,
17776
17920
  onSessionClick,
17777
17921
  onRenameSession,
17778
17922
  onDeleteSession,
17779
- onTogglePinnedSession,
17780
- onCreateSessionInDirectory,
17781
- onDeleteOldSessionsInDirectory,
17782
- onRemoveDirectory: onRemoveDirectory ? removeDirectory : void 0
17783
- }) : null })]
17784
- }) }) })]
17785
- })
17786
- })] }),
17923
+ onMoveSession,
17924
+ onTogglePinnedSession
17925
+ })
17926
+ }) : null })
17927
+ ]
17928
+ }) }),
17787
17929
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarFooter, {
17788
17930
  className: "gap-2 border-t border-sidebar-border/70",
17789
17931
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenu, {
@@ -18193,6 +18335,9 @@ function AppShellSidebarController({ viewerContextId, sidebarStore, sessionWorks
18193
18335
  onDeleteSession: (entry) => {
18194
18336
  sessionWorkspaceRef.current?.openDeleteDialog([entry]);
18195
18337
  },
18338
+ onMoveSession: (entry, directory) => {
18339
+ sessionWorkspaceRef.current?.moveSessionToDirectory(entry, directory);
18340
+ },
18196
18341
  onTogglePinnedSession: togglePinnedSession,
18197
18342
  onCreateSessionInDirectory: (directory) => {
18198
18343
  sessionWorkspaceRef.current?.createSession(directory, { closeMobileSidebar: true });
@@ -19369,7 +19514,21 @@ function optimisticSelectionAfterDelete(selection, deletedKeys) {
19369
19514
  sidebarSessionSelectionAnchor: selection.sidebarSessionSelectionAnchor && deletedKeys.has(selection.sidebarSessionSelectionAnchor) ? "" : selection.sidebarSessionSelectionAnchor
19370
19515
  };
19371
19516
  }
19372
- function useAppShellSessionMutations({ viewerContextId, activeSessionId, sessionStateRef, setSessionState, getDirectoryIndexDataByPath, setDirectoryIndexDataByPath, getSessionsEvent, setSessionsEvent, getSidebarSelection, optimisticallyClearActiveDeletedSession, setSelectedSidebarSessionKeys, setSidebarSessionSelectionAnchor, setCompactWorkingState, isCompactAbortRequested }) {
19517
+ function replaceSessionKey(keys, previousKey, nextKey) {
19518
+ if (!previousKey || !nextKey || previousKey === nextKey) return keys;
19519
+ let changed = false;
19520
+ const seen = /* @__PURE__ */ new Set();
19521
+ const nextKeys = [];
19522
+ for (const key of keys) {
19523
+ const nextValue = key === previousKey ? nextKey : key;
19524
+ if (nextValue !== key) changed = true;
19525
+ if (!nextValue || seen.has(nextValue)) continue;
19526
+ seen.add(nextValue);
19527
+ nextKeys.push(nextValue);
19528
+ }
19529
+ return changed ? nextKeys : keys;
19530
+ }
19531
+ function useAppShellSessionMutations({ viewerContextId, activeSessionId, sessionStateRef, setSessionState, getDirectoryIndexDataByPath, setDirectoryIndexDataByPath, getSessionsEvent, setSessionsEvent, getSidebarSelection, optimisticallyClearActiveDeletedSession, setSelectedSidebarSessionKeys, setSidebarSessionSelectionAnchor, setPinnedSidebarSessionKeys, setCompactWorkingState, isCompactAbortRequested }) {
19373
19532
  const thinkingLevelRequestIdRef = import_react.useRef(0);
19374
19533
  const thinkingLevelSyncTimerRef = import_react.useRef(null);
19375
19534
  import_react.useEffect(() => {
@@ -19593,6 +19752,64 @@ function useAppShellSessionMutations({ viewerContextId, activeSessionId, session
19593
19752
  setSessionsEvent,
19594
19753
  viewerContextId
19595
19754
  ]);
19755
+ const moveSessionMutation = useMutation({ mutationFn: async ({ path, cwd }) => {
19756
+ if (!viewerContextId) throw new Error("Viewer context unavailable");
19757
+ return await fetchJson(buildRequestUrl("/api/session/move", {
19758
+ contextId: viewerContextId,
19759
+ sessionId: activeSessionId
19760
+ }), {
19761
+ method: "POST",
19762
+ headers: { "content-type": "application/json" },
19763
+ body: JSON.stringify({
19764
+ path,
19765
+ cwd
19766
+ })
19767
+ });
19768
+ } });
19769
+ const moveSessionPath = import_react.useCallback(async (entry, directory) => {
19770
+ if (!viewerContextId || !entry.path) return false;
19771
+ const nextDirectory = directory.trim();
19772
+ if (!nextDirectory) {
19773
+ toast.error("Directory is required");
19774
+ return false;
19775
+ }
19776
+ if (entry.cwd === nextDirectory) return false;
19777
+ try {
19778
+ const response = await moveSessionMutation.mutateAsync({
19779
+ path: entry.path,
19780
+ cwd: nextDirectory
19781
+ });
19782
+ const previousKey = sessionListEntryKey({ path: response.previousPath || entry.path });
19783
+ const nextKey = sessionListEntryKey({
19784
+ path: response.path,
19785
+ id: response.sessionId || entry.id
19786
+ });
19787
+ setSelectedSidebarSessionKeys((current) => replaceSessionKey(current, previousKey, nextKey));
19788
+ setSidebarSessionSelectionAnchor((current) => current === previousKey ? nextKey : current);
19789
+ setPinnedSidebarSessionKeys((current) => {
19790
+ const next = replaceSessionKey(current, previousKey, nextKey);
19791
+ if (next !== current) safeLocalStorageSetItem(PINNED_SESSIONS_STORAGE_KEY, JSON.stringify(next));
19792
+ return next;
19793
+ });
19794
+ setSessionState((current) => current.sessionFile === response.previousPath ? {
19795
+ ...current,
19796
+ cwd: response.cwd,
19797
+ sessionFile: response.path
19798
+ } : current);
19799
+ toast.success("Moved session");
19800
+ return true;
19801
+ } catch (error) {
19802
+ toast.error(error instanceof Error ? error.message : "Failed to move session");
19803
+ return false;
19804
+ }
19805
+ }, [
19806
+ moveSessionMutation,
19807
+ setPinnedSidebarSessionKeys,
19808
+ setSelectedSidebarSessionKeys,
19809
+ setSessionState,
19810
+ setSidebarSessionSelectionAnchor,
19811
+ viewerContextId
19812
+ ]);
19596
19813
  const deleteSessionMutation = useMutation({ mutationFn: async (paths) => {
19597
19814
  if (!viewerContextId) throw new Error("Viewer context unavailable");
19598
19815
  await fetchJson(buildRequestUrl("/api/sessions/delete", {
@@ -19660,6 +19877,7 @@ function useAppShellSessionMutations({ viewerContextId, activeSessionId, session
19660
19877
  setSidebarSessionSelectionAnchor,
19661
19878
  viewerContextId
19662
19879
  ]),
19880
+ moveSessionPath,
19663
19881
  renameSessionPath,
19664
19882
  runClone,
19665
19883
  runCompact,
@@ -21713,7 +21931,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
21713
21931
  if (workingStateStore.state?.label === "Compacting context...") setStoreState(workingStateStore, null);
21714
21932
  }, [setCompactRunningState, workingStateStore]);
21715
21933
  const isCompactAbortRequested = import_react.useCallback(() => compactAbortRequestedRef.current, []);
21716
- const { cycleThinkingLevel, deleteSessions, renameSessionPath, runClone, runCompact, setModel, setThinkingBlocksHidden, setThinkingLevel, toggleHideThinking } = useAppShellSessionMutations({
21934
+ const { cycleThinkingLevel, deleteSessions, moveSessionPath, renameSessionPath, runClone, runCompact, setModel, setThinkingBlocksHidden, setThinkingLevel, toggleHideThinking } = useAppShellSessionMutations({
21717
21935
  viewerContextId,
21718
21936
  activeSessionId,
21719
21937
  sessionStateRef,
@@ -21756,9 +21974,23 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
21756
21974
  },
21757
21975
  setSelectedSidebarSessionKeys: sidebarStore.setSelectedSidebarSessionKeys,
21758
21976
  setSidebarSessionSelectionAnchor: sidebarStore.setSidebarSessionSelectionAnchor,
21977
+ setPinnedSidebarSessionKeys: sidebarStore.setPinnedSidebarSessionKeys,
21759
21978
  setCompactWorkingState,
21760
21979
  isCompactAbortRequested
21761
21980
  });
21981
+ const moveSessionToDirectory = async (entry, directory) => await moveSessionPath(entry, directory);
21982
+ const moveCurrentSessionToDirectory = async (directory) => {
21983
+ const currentState = sessionStateRef.current;
21984
+ if (!currentState.sessionFile) return false;
21985
+ return await moveSessionToDirectory({
21986
+ path: currentState.sessionFile,
21987
+ id: currentState.sessionId,
21988
+ cwd: currentState.cwd,
21989
+ title: getCurrentSessionTitleFromState(currentState),
21990
+ name: currentState.sessionName,
21991
+ modified: currentState.modified
21992
+ }, directory);
21993
+ };
21762
21994
  const setToolBlocksHidden = (hidden) => {
21763
21995
  setHideToolBlocks(hidden);
21764
21996
  safeLocalStorageSetItem(HIDE_TOOL_BLOCKS_STORAGE_KEY, hidden ? "1" : "0");
@@ -22371,6 +22603,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22371
22603
  createSession,
22372
22604
  onDeleteCurrentSession: openDeleteDialogForCurrentSession,
22373
22605
  onForkSession: openForkDialog,
22606
+ onMoveCurrentSession: moveCurrentSessionToDirectory,
22374
22607
  onRenameSession: openRenameDialog,
22375
22608
  onRunCompact: runCompact,
22376
22609
  onToggleCurrentSessionPinned: toggleCurrentSessionPinned,
@@ -22424,6 +22657,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22424
22657
  openAddDirectoryDialog,
22425
22658
  openCommandPalette,
22426
22659
  openDeleteDialog,
22660
+ moveSessionToDirectory,
22427
22661
  openDeleteOldDirectorySessionsDialog,
22428
22662
  openRenameDialogForEntry,
22429
22663
  openSessionsDialog,
@@ -22439,6 +22673,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22439
22673
  openCommandPalette: actions?.openCommandPalette ?? openCommandPalette,
22440
22674
  openDeleteDialog: actions?.openDeleteDialog ?? openDeleteDialog,
22441
22675
  openDeleteOldDirectorySessionsDialog: actions?.openDeleteOldDirectorySessionsDialog ?? openDeleteOldDirectorySessionsDialog,
22676
+ moveSessionToDirectory: actions?.moveSessionToDirectory ?? moveSessionToDirectory,
22442
22677
  openRenameDialogForEntry: actions?.openRenameDialogForEntry ?? openRenameDialogForEntry,
22443
22678
  openSessionsDialog: actions?.openSessionsDialog ?? openSessionsDialog,
22444
22679
  openSettingsDialog: actions?.openSettingsDialog ?? openSettingsDialog,
@@ -22449,6 +22684,7 @@ var AppShellSessionWorkspace = import_react.forwardRef(function AppShellSessionW
22449
22684
  handleSelectSession,
22450
22685
  openAddDirectoryDialog,
22451
22686
  openCommandPalette,
22687
+ moveSessionToDirectory,
22452
22688
  openDeleteDialog,
22453
22689
  openDeleteOldDirectorySessionsDialog,
22454
22690
  openRenameDialogForEntry,