dsh-group-status 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["createSnapshotStore","assertNever","assertNever","defineStore","Service","createSnapshotStore","StateDot","IconClockOutlineRegular","IconListPenOutlineRegular","css","useRef","useMemo","relativeTime","css","StateDot","useState","IconEditOutlineRegular","IconTrashOutlineRegular","IconFolderOpenRegular","IconFolderCloseRegular","IconTriangleRightFillRegular","Menu","IconEllipsisOutlineRegular","Tooltip","IconNewChatOutlineRegular","HoverCard","IconPinFillRegular","IconArchiveOutlineRegular","IconUnarchiveOutlineRegular","Component","createRef","css","useCallback","useState","IconPlusOutlineRegular","IconFolderCloseRegular","Menu","css","Modal","Button","useState","Menu","IconFolderCloseRegular","IconWorkspaceTreeOutlineRegular","IconFlatListOutlineRegular","IconChevronsUpDownOutlineRegular","IconClockOutlineRegular","IconArchiveOffOutlineRegular","IconQueueOutlineRegular","IconArchiveCheckOutlineRegular","css","Tooltip","IconSlidersTwoOutlineRegular","IconArchiveOutlineRegular","useRef","useMemo","IconSearchOutlineRegular","IconCloseFillRegular","IconProjectAddOutlineRegular","Modal","Button","Toast","MenuItemButton","IconUnarchiveOutlineRegular","IconArchiveOutlineRegular","Tooltip","css","useState","Modal","Button","browserCss","MenuItemButton","IconBranchOutlineRegular","MenuItemButton","IconPinFillRegular","IconPinOutlineRegular","Tooltip","css","MenuItemButton","IconEditOutlineRegular","useState","useRef","Modal","Button","css","Toast","IconWarningOutlineRegular","assertNever","createSnapshotStore"],"sources":["../src/client/contract/slots.ts","../src/client/shortcuts.ts","../src/client/badge-settings.ts","../node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.2.0-rc.2_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-values/lib/index.js","../node_modules/.pnpm/@deepseek-ai+dsh-util-workspace-path@0.2.0-rc.2_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-workspace-path/lib/index.js","../src/client/group-status.ts","../src/client/tree.ts","../src/client/stores.ts","../src/client/pin-order.ts","../src/client/navigation.ts","../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs","../node_modules/.pnpm/@deepseek-ai+dsh-api-workspace-controller@0.2.0-rc.2_7b1cc3b3e03980f49f8901a2ede23841/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/default-workspace.js","../src/client/rows/GroupBadge.tsx","../src/client/rows/Rows.tsx","../src/client/rows/AnimatedRows.tsx","../src/client/WorkspacePicker.tsx","../src/client/rows/WorkspaceBrowser.tsx","../src/client/session-actions/ArchiveSession.tsx","../src/client/session-actions/derived.ts","../src/client/session-actions/ForkSession.tsx","../src/client/session-actions/PinSession.tsx","../src/client/session-actions/RenameSession.tsx","../src/client/session-actions/RowActionToast.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * ui-workspace contracts. Two registrations share this package:\n *\n * - WorkspaceBrowser fills the sidebar shell's `sidebar.workspaces` hole —\n * the whole browsing region (section header, search, grouped/flat session\n * list, workspace dialogs). It registers this package's viewing store and\n * consumes the shell's two-fact owner share (wide / expandSidebar).\n * - WorkspacePicker fills the conversation empty-state hole (menu + error\n * dialog shared with the browser).\n *\n * Both registrations declare a **directory-flow hole** (`single` kind): the\n * slot a composed picker package's client half fills with its\n * picking interaction — a renderless native-chooser driver or an in-app\n * browsing dialog. ui-workspace owns the trigger (the \"Add workspace…\"\n * entry, present only while the hole is occupied) and the adoption\n * semantics (`createWorkspace({ path })`, the retryable error dialog,\n * Choose again); the occupant owns everything between `open` and the picked path,\n * including creating a new directory to hand back. That occupant-owned\n * creation is why adding a workspace has a single route: an unoccupied hole\n * leaves the surface with no add affordance at all.\n * Two holes exist because the two menu surfaces are independent slot entries\n * and a hole has exactly one declaring entry — they carry the same owner\n * contract and the same occupant.\n *\n * WorkspaceBrowser also declares the two **Session row action lists**: every\n * row of a Session's \"...\" menu is an entry of\n * `sidebar.workspaces.session.menu.item`, and every hover button at the row's\n * end is an entry of `sidebar.workspaces.session.row.action`. The shipped\n * actions — pin, rename, fork, archive — are ordinary entries this package\n * registers from `apply`, each carrying its own behavior in its own inject\n * face and reading its own Host state through hooks that face injects, so a\n * client plugin's action lands beside them by `order` and needs nothing from\n * the browser beyond the row identity.\n *\n * The browser entry additionally declares two `list` seats per Session row\n * (`sidebar.session.row.leading` / `sidebar.session.row.hover`) for ambient\n * row decorations. Both take the row's Session identity and nothing else: a\n * session-scoped seat would force a Session binding, which would activate and\n * retain every listed Session.\n */\nimport type {\n HostObservable, InjectFace, PropsHooks, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore, SlotHookFactory,\n} from '@deepseek-ai/dsh-client-ui-slots'\n// Type-only: pull the owner SlotMap merges into programs that resolve the\n// runtime shares below.\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type { SessionSearchResultItem } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client'\nimport type { SessionActivity, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { ShortcutCatalogEntry } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { WorkspaceShortcutState } from '../shortcuts.ts'\nimport type { createWorkspaceViewStore } from '../stores.ts'\n\n/**\n * Owner share of the directory-flow holes: the complete conversation between\n * the trigger surface and the picking interaction. The occupant reads `open`\n * to run/render its interaction and reports exactly one outcome per open.\n */\nexport interface DirectoryFlowOwnerProps {\n /** True while a picking interaction is requested; flipping back to false withdraws the request. */\n open: boolean\n /** True while the owner adopts a picked path (`createWorkspace` in flight); occupants disable their commit affordances. */\n busy: boolean\n /** The operator picked a directory (absolute host path); the owner adopts it. */\n onPicked: (path: string) => void\n /** The operator dismissed the interaction; the owner just closes the flow. */\n onCancel: () => void\n /** The interaction itself failed (chooser missing, listing denied); the owner shows its error surface. */\n onError: (message: string) => void\n}\n\n/** Owner share of one Session row action occurrence: the row the action belongs to. */\nexport interface SessionRowOwnerProps {\n /** Session the row shows. */\n sessionId: SessionId\n /** Row display title: persisted title, or empty when the Session has none. */\n displayTitle: string\n}\n\n/** The row menu's open state as its owner holds it: the `useState` pair. */\nexport type MenuOpenState = readonly [open: boolean, setOpen: (open: boolean) => void]\n\n/**\n * Hook every row-menu entry receives. Rows only render while the menu is\n * open, so an entry reads it for the setter: `setOpen(false)` dismisses the\n * menu the entry sits in — the same state the owner's `onClose` sets.\n */\nexport type UseMenuOpenState = () => MenuOpenState\n\n/**\n * Bind the row's render occurrence into the entries' `useMenuOpenState` hook:\n * the owner supplies its open-state pair as the occurrence's `hookContext`,\n * and the hook hands that pair back.\n * @param _standard - framework standard props (unused).\n * @param state - the menu's open-state pair from the render occurrence.\n * @returns the hook the entry calls.\n */\nexport const menuOpenStateFactory: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState> =\n (_standard, state) => () => state\n\n/**\n * Owner share of the two Session-row schedule seats. Both receive only the\n * row's Session identity: the occupant reads that Session's own scheduled\n * tasks, and reading them activates nothing.\n */\nexport interface SessionRowScheduleOwnerProps {\n /** Session this row shows; the occupant addresses its own data by this id. */\n readonly sessionId: SessionId\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** Directory-flow hole under the conversation empty-state picker (declared by the WorkspacePicker entry). */\n 'conversation.hero.workspace.directoryFlow': { kind: 'single'; scope: 'root'; owner: DirectoryFlowOwnerProps }\n /** Directory-flow hole under the sidebar browsing region (declared by the WorkspaceBrowser entry). */\n 'sidebar.workspaces.directoryFlow': { kind: 'single'; scope: 'root'; owner: DirectoryFlowOwnerProps }\n /**\n * Leading decoration of one Session row, in the 16px cell before the title\n * that the row's own state dot otherwise occupies. A higher-priority state\n * (a pending interaction, a new message, live activity) replaces the seat\n * with that dot for the same row, so an occupant here never renders beside\n * a status dot and is mounted only by a row whose primary state is idle.\n * An archived row keeps that cell blank — neither its status dot nor this\n * seat renders there, and its live status appears on the hover card only.\n */\n 'sidebar.session.row.leading': { kind: 'list'; scope: 'root'; owner: SessionRowScheduleOwnerProps }\n /**\n * Section of the Session row's hover card between its relative time and\n * its trailing status line. Mounted only while that card is open.\n */\n 'sidebar.session.row.hover': { kind: 'list'; scope: 'root'; owner: SessionRowScheduleOwnerProps }\n /**\n * The rows of one Session's \"...\" menu, in ascending `order`. ui-workspace\n * registers the shipped rows here — `pin` (100), `rename` (200), `fork`\n * (300), `archive` (400) — so a plugin row is placed by its own `order`\n * among them. Use a package-namespaced `id`; reusing a shipped id at\n * another `priority` shadows that row. Each entry renders one\n * `role=\"menuitem\"` `<button>` (the shipped rows use ui-primitives'\n * `MenuItemButton`, which adds the host styling and `separatorBefore`),\n * decides its own visibility from its own state, and dismisses the menu\n * through the injected `useMenuOpenState` hook after acting; the list's\n * keyboard walk and focus return read the DOM, so any such button joins\n * them. Labels come from the contributing package's locale namespace.\n * @example\n * return {\n * inject: ['slots'],\n * apply(ctx) {\n * const copyLabel = 'Copy Session ID' // Localize in the contributing package.\n * ctx.slots.inject('sidebar.workspaces.session.menu.item', () => ctx.slots.register(\n * { name: 'sidebar.workspaces.session.menu.item', id: 'copy-session-id', order: 500 },\n * ({ sessionId, useMenuOpenState }) => {\n * const [, setMenuOpen] = useMenuOpenState()\n * return React.createElement(\n * 'button',\n * { type: 'button', role: 'menuitem', onClick: () => { setMenuOpen(false); void navigator.clipboard.writeText(sessionId) } },\n * copyLabel,\n * )\n * },\n * ))\n * },\n * }\n */\n 'sidebar.workspaces.session.menu.item': {\n kind: 'list'\n scope: 'root'\n owner: SessionRowOwnerProps\n hookContext: MenuOpenState\n inject: { hooks: {\n menuOpenState: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState>\n shortcuts: HostObservable<readonly ShortcutCatalogEntry[]>\n } }\n }\n /**\n * The hover buttons at the end of one Session row, in ascending `order`,\n * after the \"...\" menu trigger. ui-workspace registers `archive` (100) and\n * `pin` (200) here. An entry renders one icon button (or nothing, when its\n * action does not apply to the row) and owns the action it performs. Clicks\n * inside the strip stay in the strip, so the button needs no propagation\n * handling to keep the row from opening.\n */\n 'sidebar.workspaces.session.row.action': { kind: 'list'; scope: 'root'; owner: SessionRowOwnerProps }\n }\n}\n\n/** The two directory-flow holes; a flow package's client half registers its one component into both. */\nexport type DirectoryFlowSlotName =\n | 'conversation.hero.workspace.directoryFlow'\n | 'sidebar.workspaces.directoryFlow'\n\n/**\n * Directory-picking share both trigger surfaces consume. Occupancy rides the\n * inject face's reserved `hooks` compartment: the renderer binds the source\n * into the `useDirectoryFlow` selector hook, so an empty hole hides the\n * \"Add workspace…\" entry reactively and the surface withdraws an open\n * flow whose occupant unloaded mid-interaction (nobody is left to cancel).\n */\nexport type DirectoryPickingInjected = {\n hooks: {\n /** True while this surface's directory-flow hole is occupied. */\n directoryFlow: HostObservable<boolean>\n }\n}\n\n/** Component-side view of the picking share: the bound occupancy selector hook. */\nexport type DirectoryPickingHooks = PropsHooks<DirectoryPickingInjected['hooks']>\n\n/**\n * Browser-private injected share (arrives via the register inject factory).\n * Data reads use the global framework hooks; these are the Host actions the\n * browsing region drives.\n */\nexport type WorkspaceBrowserInjected = {\n hooks: DirectoryPickingInjected['hooks'] & {\n /**\n * Fixed Host facts, reached through a hook rather than injected as values:\n * the renderer memoizes an entry's inject result for the registration's\n * lifetime, so facts read there would freeze at whatever the first render\n * saw. Select the field the surface needs (`info => info.home`).\n */\n hostInfo: HostObservable<RemoteHostFacts>\n workspaceShortcuts: HostObservable<WorkspaceShortcutState>\n shortcuts: HostObservable<readonly ShortcutCatalogEntry[]>\n }\n /** Open the browser search and focus its input. */\n requestSearch: () => void\n /** Request the existing directory picker. */\n requestAddWorkspace: () => void\n /** Consume the directory-picker opening request. */\n closeAddWorkspace: () => void\n /** Publish directory interaction occupancy for command availability. */\n setDirectoryBusy: (busy: boolean) => void\n /** Dismiss the shortcut's fork-failure notification. */\n dismissForkError: () => void\n /**\n * Start a New Session in a Workspace: reuse-or-create its blank session and\n * open it; without an explicit workspace, inherit the current Session\n * Workspace, then the recent Workspace, or clear into the New Session view.\n */\n startSession: (workspaceId?: WorkspaceId) => void\n /** Open a real Session. */\n open: (sessionId: SessionId) => void\n /**\n * Search current visible conversation messages. The Host fixes the result\n * bound; `hasMore` means the query needs narrowing.\n */\n searchSessions: (\n query: string,\n signal: AbortSignal,\n ) => Promise<{ items: readonly SessionSearchResultItem[]; hasMore: boolean }>\n /** Maximum number of merged rows rendered for one search. */\n searchResultLimit: number\n /** Open the Session rename dialog (a row title double-click); the rename action entry raises the same request. */\n requestSessionRename: (sessionId: SessionId, currentTitle: string) => void\n /** Tell the user an archived row cannot be opened (a click on it). */\n notifyArchivedNotOpenable: () => void\n /** Rename a Host Workspace (rejects on name conflict; resolves on durability). */\n renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>\n /** Delete only a Host Workspace registration; directory and Session logs remain. */\n deleteWorkspace: (workspaceId: WorkspaceId) => Promise<void>\n /**\n * Reorder a Workspace in the durable registry display order.\n * Omitted anchor appends to the end.\n */\n insertWorkspaceBefore: (workspaceId: WorkspaceId, beforeWorkspaceId?: WorkspaceId) => Promise<void>\n /** Remove a Session from the registry-global archived set (the search results' restore button). */\n unarchiveSession: (sessionId: SessionId) => Promise<void>\n /** Adopt a picked host directory as a real Workspace before targeting a Session. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n}\n\n/** The browser's declared viewing store handle, shared with the row actions that write view state. */\nexport type WorkspaceViewStoreHandle = ReturnType<typeof createWorkspaceViewStore>\n\n/** Props of one shipped row-menu entry: owner share + locale seat + the entry's own injected share. */\nexport type SessionMenuItemProps<Injected extends object = object> =\n PropsRuntime<'sidebar.workspaces.session.menu.item'>\n & PropsLocale<'workspace'>\n & InjectFace<Injected>\n\n/** Props of one shipped row hover button: owner share + locale seat + the entry's own injected share. */\nexport type SessionRowActionProps<Injected extends object = object> =\n PropsRuntime<'sidebar.workspaces.session.row.action'>\n & PropsLocale<'workspace'>\n & InjectFace<Injected>\n\n/** One transient Workspace notice rendered by the overlay toast entry. */\nexport type RowToast =\n | { kind: 'archived'; sessionId: SessionId }\n | { kind: 'stoppedAndArchived'; sessionId: SessionId }\n | { kind: 'pinFailed' }\n | { kind: 'unpinFailed' }\n | { kind: 'archivedNotOpenable' }\n | { kind: 'defaultWorkspaceFailed' }\n /**\n * An explicit New Session request that failed. `message` is untranslated:\n * a Host refusal as `code: message` — the stable code stays in the copy so\n * a report can be searched by it — and any other failure's own message.\n */\n | { kind: 'createFailed'; message: string }\n\n/** The notice on display; `seq` keys remounts so a repeated notice restarts its hold. */\nexport type RowToastState = RowToast & { seq: number }\n\n/**\n * Pin action share (menu row and hover button). The callbacks carry the whole\n * behavior: the Host call, fronting the Session in its saved orders after a\n * pin, and the failure notice. The hooks are the registry-global sets as\n * Sets, so a row reads its own membership with one lookup.\n */\nexport interface PinSessionInjected {\n hooks: {\n /** Pinned Session ids. */\n pinned: HostObservable<ReadonlySet<SessionId>>\n /** Archived Session ids (pin does not apply to an archived row). */\n archived: HostObservable<ReadonlySet<SessionId>>\n }\n /** Pin a Session; on success it leads its accounts' saved orders, on failure the notice says so. */\n pinSession: (sessionId: SessionId) => void\n /** Unpin a Session; saved positions stay as they are. */\n unpinSession: (sessionId: SessionId) => void\n}\n\n/**\n * Archive action share (menu row and hover button). The callbacks carry the\n * whole behavior: the Host call, the notice a success raises, the\n * stop-and-archive confirmation a Host refusal for running work raises, and\n * the diagnostics for any other rejection.\n */\nexport interface ArchiveSessionInjected {\n hooks: {\n /** Archived Session ids. */\n archived: HostObservable<ReadonlySet<SessionId>>\n }\n /**\n * Archive a Session into the registry-global set: the row keeps its\n * account position and shows per the archived filter; archiving the\n * current session clears the selection into the New Session view state.\n * A Session with running work is not archived by this call: the Host's\n * refusal opens the stop-and-archive confirmation instead.\n */\n archiveSession: (sessionId: SessionId) => void\n /** Remove a Session from the registry-global archived set. */\n unarchiveSession: (sessionId: SessionId) => void\n}\n\n/**\n * A stop-and-archive confirmation the archive action asked for: the Host\n * refused the plain archive because this work still runs.\n */\nexport interface SessionArchiveConfirmRequest {\n /** Session to stop and archive. */\n sessionId: SessionId\n /** The row's display title, named in the dialog. */\n displayTitle: string\n /** What the Host reported running, in family order. */\n activity: readonly SessionActivity[]\n}\n\n/**\n * Stop-and-archive dialog share: the pending confirmation, its settlement,\n * and the archive hop that asks the Host to stop the work first.\n */\nexport interface SessionArchiveConfirmInjected {\n hooks: {\n /** The confirmation asked for, until the dialog consumes or cancels it. */\n archiveRequest: HostObservable<SessionArchiveConfirmRequest | null>\n }\n /** Consume or cancel the pending confirmation. */\n settleSessionArchive: () => void\n /**\n * Archive a Session after the Host stops its running work; resolves once\n * the archive set is durable (the stops settle in the background) and\n * raises the stopped-and-archived notice.\n */\n stopAndArchiveSession: (sessionId: SessionId) => Promise<void>\n}\n\n/** Fork action share. */\nexport interface ForkSessionInjected {\n /** Fork a Session at its last completed turn; the child arrives through the Host list. */\n forkSession: (sessionId: SessionId) => void\n}\n\n/** Rename action share: the row only raises the request; the dialog entry answers it. */\nexport interface RenameSessionInjected {\n /** Ask for the rename dialog, seeded with the row's current title. */\n requestSessionRename: (sessionId: SessionId, currentTitle: string) => void\n}\n\n/** A Session rename the rename action asked for; the dialog entry opens on it. */\nexport interface SessionRenameTarget {\n /** Session to rename. */\n sessionId: SessionId\n /** Title the dialog seeds its draft from. */\n currentTitle: string\n}\n\n/** Rename dialog share: the pending request, its settlement, and the rename hop the dialog confirms with. */\nexport interface SessionRenameDialogInjected {\n hooks: {\n /** The rename asked for, until the dialog consumes or cancels it. */\n renameRequest: HostObservable<SessionRenameTarget | null>\n }\n /** Consume or cancel the pending request. */\n settleSessionRename: () => void\n /** Rename a Session (explicit user title; resolves on host acceptance). */\n renameSession: (sessionId: SessionId, title: string) => Promise<void>\n}\n\n/** Row toast share: the notice on display, its dismissal, and the two actions the archived notice offers. */\nexport interface RowToastInjected {\n hooks: {\n /** The notice on display, or none. */\n toast: HostObservable<RowToastState | null>\n }\n /** Take the notice down. */\n dismissToast: () => void\n /** Undo an archive from its notice. */\n undoArchive: (sessionId: SessionId) => void\n /** Switch the archived filter to \"show\" so the archived row is back in view. */\n showArchived: () => void\n}\n\n/** Props of the rename dialog entry in `shell.overlay`. */\nexport type SessionRenameDialogProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & Omit<SessionRenameDialogInjected, 'hooks'>\n & PropsHooks<SessionRenameDialogInjected['hooks']>\n\n/** Props of the stop-and-archive dialog entry in `shell.overlay`. */\nexport type SessionArchiveConfirmProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & Omit<SessionArchiveConfirmInjected, 'hooks'>\n & PropsHooks<SessionArchiveConfirmInjected['hooks']>\n\n/**\n * Props of the row toast entry in `shell.overlay`. The declared viewing store\n * carries the archived filter; the archived notice omits its filter action\n * when archived rows are already visible.\n */\nexport type RowToastProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & PropsStore<WorkspaceViewStoreHandle>\n & Omit<RowToastInjected, 'hooks'>\n & PropsHooks<RowToastInjected['hooks']>\n\n/** Full browser props: shell owner share + viewing store + injected actions + the locale seat. */\nexport type WorkspaceBrowserProps =\n PropsRuntime<'sidebar.workspaces'>\n & PropsRenderSlots<\n | 'sidebar.workspaces.directoryFlow'\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n >\n & PropsStore<WorkspaceViewStoreHandle>\n & Omit<WorkspaceBrowserInjected, 'hooks'>\n & PropsHooks<WorkspaceBrowserInjected['hooks']>\n & PropsLocale<'workspace'>\n\n/**\n * Picker-private injected share. Pick semantics remain in the owner's onPick\n * callback; this callback creates only the real Host Workspace. A type alias\n * supplies the implicit index signature required by the registry.\n */\nexport type WorkspacePickerInjected = DirectoryPickingInjected & {\n /** Adopt a picked host directory as a real Workspace before targeting a Session. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n}\n\n/**\n * Full picker props: the owner share plus the creation callback and the\n * locale seat. The two picker holes (blank-session hero / New-Session view)\n * share one owner currency, so one composed type serves both registrations.\n */\nexport type WorkspacePickerProps =\n PropsRuntime<'conversation.hero.workspace'>\n & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'>\n & Omit<WorkspacePickerInjected, 'hooks'>\n & PropsHooks<WorkspacePickerInjected['hooks']>\n & PropsLocale<'workspace'>\n","/** Workspace command registration and browser-owned opening requests. */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { SessionForkError } from '@deepseek-ai/dsh-api-session-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { ShortcutCommand, ShortcutCommandId } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { UiWorkspace } from './navigation.ts'\n\n/** Transient requests consumed by the existing workspace browser. */\nexport interface WorkspaceShortcutState {\n readonly searchRequest: number\n readonly addRequested: boolean\n readonly directoryBusy: boolean\n readonly renameTarget: { readonly sessionId: SessionId; readonly currentTitle: string } | null\n readonly forkError: { readonly reason: 'unavailable' | 'failed'; readonly seq: number } | null\n}\n\ninterface WorkspaceShortcutControls {\n state: SnapshotStore<WorkspaceShortcutState>\n search: () => void\n add: () => void\n closeAdd: () => void\n directoryBusy: (busy: boolean) => void\n rename: (sessionId: SessionId, currentTitle: string) => void\n closeRename: () => void\n forkFailed: (reason: 'unavailable' | 'failed') => void\n dismissForkError: () => void\n}\n\n/**\n * Create the private browser request source shared by commands and controls.\n * @returns observable state and its complete mutation callbacks.\n */\nexport function createWorkspaceShortcutControls(): WorkspaceShortcutControls {\n const state = createSnapshotStore<WorkspaceShortcutState>({\n searchRequest: 0, addRequested: false, directoryBusy: false, renameTarget: null, forkError: null,\n })\n let forkErrorSeq = 0\n return {\n state,\n search: () => { state.set({ ...state.getSnapshot(), searchRequest: state.getSnapshot().searchRequest + 1 }) },\n add: () => { state.set(state.getSnapshot().directoryBusy ? state.getSnapshot() : { ...state.getSnapshot(), addRequested: true }) },\n closeAdd: () => { state.set({ ...state.getSnapshot(), addRequested: false }) },\n directoryBusy: (busy: boolean) => { state.set({ ...state.getSnapshot(), directoryBusy: busy }) },\n rename: (sessionId: SessionId, currentTitle: string) => {\n state.set({ ...state.getSnapshot(), renameTarget: { sessionId, currentTitle } })\n },\n closeRename: () => { state.set({ ...state.getSnapshot(), renameTarget: null }) },\n forkFailed: (reason) => {\n forkErrorSeq += 1\n state.set({ ...state.getSnapshot(), forkError: { reason, seq: forkErrorSeq } })\n },\n dismissForkError: () => { state.set({ ...state.getSnapshot(), forkError: null }) },\n }\n}\n\n/**\n * Register navigation commands against the existing workspace owner.\n * Rename requires a nonblank main Conversation with no modal obscuring it.\n * @param ctx - plugin context with the shortcut, locale, and model services.\n * @param navigation - session creation and forking from the pointer controls' navigation service.\n * @param controls - browser-owned opening requests.\n * @param archiveSession - shared archive action, including running-work confirmation and notices.\n */\nexport function installWorkspaceShortcuts(\n ctx: Context,\n navigation: Pick<UiWorkspace, 'startSession' | 'forkSession'>,\n controls: ReturnType<typeof createWorkspaceShortcutControls>,\n archiveSession: (sessionId: SessionId) => void,\n): void {\n const t = ctx.locale.bind('workspace')\n const current = () => Object.values(ctx.sessions.list.getSnapshot().byId)\n .find(row => (row.retainedBy.mainView ?? 0) > 0)\n const addReason = () => ctx.slots.entries('sidebar.workspaces.directoryFlow').length === 0\n ? t('shortcut.noPicker')\n : controls.state.getSnapshot().directoryBusy ? t('shortcut.directoryBusy') : null\n const register = (id: string, label: () => string, aliases: string[], code: string,\n modifiers: ('primary' | 'alt' | 'shift')[], webModifiers: ('primary' | 'alt' | 'shift')[], resolve: ShortcutCommand['resolve']): void => {\n ctx.effect(() => ctx.shortcuts.register({\n id: id as ShortcutCommandId, label, aliases, defaults: {\n 'desktop:macos': { code, modifiers }, 'desktop:windows': { code, modifiers }, 'desktop:linux': { code, modifiers },\n 'web:macos': { code, modifiers: webModifiers }, 'web:windows': { code, modifiers: webModifiers },\n },\n regions: ['page', 'editable'], modals: [], resolve,\n }), `ui-workspace: ${id}`)\n }\n register('session.new', () => t('session.new'), ['new session', 'new chat'], 'KeyN', ['primary'], ['primary', 'alt'],\n () => ({ status: 'handled', run: () => { navigation.startSession() } }))\n register('session.search', () => t('search.sessions.aria'), ['search sessions'], 'KeyK', ['primary'], ['primary', 'alt'],\n () => ({ status: 'handled', run: controls.search }))\n register('workspace.add', () => t('workspace.add'), ['add workspace', 'open folder'], 'KeyO', ['primary'], ['primary', 'alt'],\n () => {\n const reason = addReason()\n return reason === null ? { status: 'handled', run: controls.add } : { status: 'blocked', reason }\n })\n register('session.rename', () => t('rename.session.title'), ['rename session'], 'KeyG', ['primary', 'alt'], ['primary', 'alt'], (context) => {\n const target = current()\n return target === undefined || target.blank || context.modal !== null || ctx.layout.panelInfo.getSnapshot().activePanelId !== null\n ? { status: 'blocked', reason: t('shortcut.noSession') }\n : { status: 'handled', run: () => { controls.rename(target.id, target.title?.trim() ?? '') } }\n })\n register('session.fork', () => t('menu.fork'), ['fork session'], 'KeyF', ['primary', 'alt'], ['primary', 'shift'], () => {\n const target = current()\n if (target === undefined) return { status: 'blocked', reason: t('shortcut.noSession') }\n if (target.blank) return { status: 'blocked', reason: t('shortcut.noCompletedTurn') }\n return { status: 'handled', run: () => {\n void navigation.forkSession(target.id).catch((error: unknown) => {\n // Client plugin bundles do not share error-class identity.\n const unavailable = error instanceof Error && error.name === 'SessionForkError'\n && (error as SessionForkError).rpcError.code === 'session/fork-unavailable'\n controls.forkFailed(unavailable ? 'unavailable' : 'failed')\n if (!unavailable) console.warn('session fork rejected:', error)\n })\n } }\n })\n register('session.archive', () => t('menu.archiveSession'), ['archive session'], 'KeyA', ['primary', 'shift'], ['primary', 'alt'], () => {\n const target = current()\n return target === undefined ? { status: 'blocked', reason: t('shortcut.noSession') }\n : { status: 'handled', run: () => {\n archiveSession(target.id)\n } }\n })\n}\n","/**\n * 插件设置读取(折叠徽标显示偏好)。\n *\n * 数据流:apply 时先建一个**稳定**的标准 props 源并经 `provideRoot` 挂上(此时还不知道\n * 设置面在不在),再用 `ctx.inject(['configForms'], …)` 等宿主设置服务就绪——就绪后\n * 订阅本条目设置面,把快照推给源。设置页保存 → 宿主替换快照 → 源通知 → 徽标即时重渲染。\n *\n * 为什么不在 apply 里直接 `ctx.get('configForms')`:服务可能在**本插件之后**才注册,\n * 那时读到的 undefined 会永久生效(设置被静默忽略,直到刷新)。`ctx.inject` 是非阻塞的\n * 嵌套插件,服务永不到达也不会影响本插件其余功能。\n *\n * 为什么源必须一开始就存在:标准 props 的 hook 调用顺序必须稳定——挂上/摘掉\n * `useBadgeSettings` 会改变调用顺序而崩渲染。故源恒在,只有它的**值**随设置变化。\n *\n * 稳定性约定(React 外部存储,见 dsh-later 的同名 hook):`getSnapshot` 必须返回稳定\n * 引用——每次都构造新对象会让选择器的 `Object.is` 比较永不成立,触发\n * 「Maximum update depth exceeded」死循环(React #185),折叠行徽标会整块崩掉。\n *\n * 设置面缺席或未就绪时,回落到**默认显示已完成**,与 `Config.showCompletedInBadge` 的\n * schema 默认值同源:读不到配置不是「关掉」。\n */\n\n/** Loader 条目 id —— 设置页的寻址键,也是宿主 `describe()` 的 ns。 */\nexport const ENTRY_ID = 'dsh-group-status'\n\n/** 设置面快照的最小结构面(与宿主 `ConfigFormSnapshot` 兼容)。 */\nexport interface SettingsSnapshotLike {\n readonly status: string\n readonly value?: unknown\n}\n\n/** 设置面的最小结构面(与宿主 `ConfigForm` 兼容)。 */\nexport interface SettingsScopeLike {\n getSnapshot(): SettingsSnapshotLike\n subscribe(listener: () => void): () => void\n}\n\n/** 本插件在浏览器半关心的设置项。 */\nexport interface ResolvedBadgeSettings {\n /** 折叠徽标是否显示「已完成」绿点;缺失/非法一律回落 true。 */\n showCompletedInBadge: boolean\n}\n\n/** 标准 props 源的结构面(与 `HostObservable<ResolvedBadgeSettings>` 兼容)。 */\nexport interface BadgeSettingsSource {\n getSnapshot(): ResolvedBadgeSettings\n subscribe(listener: () => void): () => void\n}\n\n/** 始终存在的源:由 {@link createBadgeSettingsSource} 创建。 */\nexport interface MutableBadgeSettingsSource extends BadgeSettingsSource {\n /**\n * 采纳一条新快照(设置面就绪或宿主变更时推入)。\n *\n * 引用或取值都没变则**不通知**:宿主会为无关变更替换快照,无谓通知会让折叠行整列\n * 重渲染。\n * @param snapshot - 设置面快照;undefined 表示设置面缺失/收回。\n */\n publish(snapshot: SettingsSnapshotLike | undefined): void\n}\n\n/** 默认值:与 `Config.showCompletedInBadge` 的 schema 默认同源(true)。 */\nexport const DEFAULT_BADGE_SETTINGS: ResolvedBadgeSettings = Object.freeze({\n showCompletedInBadge: true,\n})\n\n/** 从原始快照派生:只有**显式 false** 才隐藏,缺失/非法一律显示。 */\nfunction resolveFromSnapshot(snap: SettingsSnapshotLike | undefined): ResolvedBadgeSettings {\n if (snap === undefined || snap.status !== 'ready') return DEFAULT_BADGE_SETTINGS\n const value = snap.value as Record<string, unknown> | undefined\n if (value === undefined || value === null || typeof value !== 'object') return DEFAULT_BADGE_SETTINGS\n return { showCompletedInBadge: value['showCompletedInBadge'] !== false }\n}\n\n/**\n * 建一个恒在、取值稳定的徽标设置源。\n *\n * `getSnapshot` 是**纯读**(无副作用、无订阅),因此可以安全地在渲染期间被反复调用,\n * 也满足外部存储的引用稳定要求;订阅只由 {@link MutableBadgeSettingsSource.publish}\n * 在取值真正变化时触发。\n * @returns 源;调用方持有它并在设置面就绪后 `publish`。\n */\nexport function createBadgeSettingsSource(): MutableBadgeSettingsSource {\n const listeners = new Set<() => void>()\n let resolved: ResolvedBadgeSettings = DEFAULT_BADGE_SETTINGS\n let seen: SettingsSnapshotLike | undefined\n let seenSet = false\n return {\n getSnapshot: () => resolved,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n },\n publish: (snapshot) => {\n // 同一快照引用重复推入(含 undefined ↔ undefined)直接丢弃。\n if (seenSet && snapshot === seen) return\n seen = snapshot\n seenSet = true\n const next = resolveFromSnapshot(snapshot)\n // 取值没变就不替换引用、不通知:宿主为无关字段替换快照时不该惊动折叠行。\n if (next.showCompletedInBadge === resolved.showCompletedInBadge) return\n resolved = next\n for (const listener of [...listeners]) listener()\n },\n }\n}\n\n/** 旧口径的纯解析函数,保留给测试与 `publish` 复用。 */\nexport function resolveBadgeSettings(snapshot: SettingsSnapshotLike | undefined): ResolvedBadgeSettings {\n return resolveFromSnapshot(snapshot)\n}","//#region lib/types/index.js\n/** Duplicate-install-safe JSON and immutable-value helpers. @module @deepseek-ai/dsh-util-values */\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n\tconst rendered = JSON.stringify(value) ?? String(value);\n\tthrow new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype has a native constructor matching this engine's representation. */\nfunction hasIntrinsicConstructor(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name === \"Array\" ? Array : Object);\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n\tconst keys = Reflect.ownKeys(value);\n\tif (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n\treturn keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n\tconst ancestors = /* @__PURE__ */ new Set();\n\tlet root;\n\tconst assign = (destination, item) => {\n\t\tif (destination === void 0) return;\n\t\tif (destination.kind === \"root\") root = item;\n\t\telse if (destination.kind === \"array\") destination.target[destination.index] = item;\n\t\telse Object.defineProperty(destination.target, destination.key, {\n\t\t\tvalue: item,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t\twritable: true\n\t\t});\n\t};\n\tconst tasks = [{\n\t\tkind: \"visit\",\n\t\tvalue,\n\t\t...detach ? { destination: { kind: \"root\" } } : {}\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tancestors.delete(task.source);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"array-item\") {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.index],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"array\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tindex: task.index\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-property\") {\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.key],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"object\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tkey: task.key\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst current = task.value;\n\t\tif (current === null) {\n\t\t\tassign(task.destination, null);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"boolean\" || typeof current === \"string\") {\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"number\") {\n\t\t\tif (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current !== \"object\") return void 0;\n\t\tif (ancestors.has(current)) return void 0;\n\t\tif (Array.isArray(current)) {\n\t\t\tif (!hasPlainArrayPrototype(current)) return void 0;\n\t\t\tconst length = current.length;\n\t\t\tif (Reflect.ownKeys(current).length !== length + 1) return void 0;\n\t\t\tconst target = detach ? [] : void 0;\n\t\t\tif (target !== void 0) assign(task.destination, target);\n\t\t\tancestors.add(current);\n\t\t\ttasks.push({\n\t\t\t\tkind: \"leave\",\n\t\t\t\tsource: current\n\t\t\t});\n\t\t\tfor (let index = length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"array-item\",\n\t\t\t\tsource: current,\n\t\t\t\tindex,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasPlainObjectPrototype(current)) return void 0;\n\t\tconst keys = enumerableStringKeys(current);\n\t\tif (keys === void 0) return void 0;\n\t\tconst target = detach ? {} : void 0;\n\t\tif (target !== void 0) assign(task.destination, target);\n\t\tancestors.add(current);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tsource: current\n\t\t});\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"object-property\",\n\t\t\t\tsource: current,\n\t\t\t\tkey,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t}\n\t}\n\treturn detach ? root : true;\n}\n/**\n* Validate and detach lossless JSON in one read per property.\n* @param value - candidate value to validate and detach.\n* @returns the detached snapshot, or `undefined` when the value is not losslessly JSON-serializable.\n*/\nfunction snapshotJsonValue(value) {\n\treturn walkJsonValue(value, true);\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n\treturn walkJsonValue(value, false) === true;\n}\n/**\n* Compare JSON-compatible values structurally.\n* @param a - one JSON-compatible value.\n* @param b - the other JSON-compatible value.\n* @returns whether both values contain the same JSON data.\n*/\nfunction deepEqualJson(a, b) {\n\tif (a === b) return true;\n\tif (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false;\n\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\tif (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n\t\treturn a.every((entry, index) => deepEqualJson(entry, b[index]));\n\t}\n\tconst left = a;\n\tconst right = b;\n\tconst keys = Object.keys(left);\n\tif (keys.length !== Object.keys(right).length) return false;\n\treturn keys.every((key) => key in right && deepEqualJson(left[key], right[key]));\n}\n/**\n* Deep-freeze an object graph in place while leaving live AbortSignal objects mutable.\n* @param value - value to freeze.\n* @returns the same value after every reachable enumerable child is frozen.\n*/\nfunction deepFreeze(value) {\n\tconst seen = /* @__PURE__ */ new WeakSet();\n\tconst pending = [{\n\t\tkind: \"visit\",\n\t\tnode: value\n\t}];\n\twhile (pending.length > 0) {\n\t\tconst task = pending.pop();\n\t\t/* v8 ignore next -- the loop condition guarantees one pending task. */\n\t\tif (task === void 0) continue;\n\t\tif (task.kind === \"property\") {\n\t\t\tpending.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tnode: task.source[task.key]\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst node = task.node;\n\t\tif (node === null || typeof node !== \"object\") continue;\n\t\tif (node instanceof AbortSignal) continue;\n\t\tif (seen.has(node)) continue;\n\t\tseen.add(node);\n\t\tObject.freeze(node);\n\t\tconst keys = Object.keys(node);\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) continue;\n\t\t\tpending.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tsource: node,\n\t\t\t\tkey\n\t\t\t});\n\t\t}\n\t}\n\treturn value;\n}\n/**\n* Weak-key lookup with a strongly retained iterable set of associated values.\n*\n* Each value must belong to only one key. The container performs no automatic\n* cleanup; owners delete associations or clear the container at lifecycle end.\n*/\nvar WeakMapWithValues = class {\n\tkeys = /* @__PURE__ */ new WeakMap();\n\tvalueSet = /* @__PURE__ */ new Set();\n\t/** Live strongly retained values in insertion order. */\n\tvalues = this.valueSet;\n\t/**\n\t* Read the value associated with a key.\n\t* @param key - weakly held lookup key.\n\t* @returns the associated value, or absence.\n\t*/\n\tget(key) {\n\t\treturn this.keys.get(key);\n\t}\n\t/**\n\t* Test whether a key has an association.\n\t* @param key - weakly held lookup key.\n\t* @returns whether the key is present.\n\t*/\n\thas(key) {\n\t\treturn this.keys.has(key);\n\t}\n\t/**\n\t* Associate one key with one caller-unique value.\n\t* @param key - weakly held lookup key.\n\t* @param value - strongly retained value that belongs to no other key.\n\t* @returns this container.\n\t*/\n\tset(key, value) {\n\t\tif (this.keys.has(key)) {\n\t\t\tconst previous = this.keys.get(key);\n\t\t\tif (previous === value) return this;\n\t\t\tthis.valueSet.delete(previous);\n\t\t}\n\t\tthis.keys.set(key, value);\n\t\tthis.valueSet.add(value);\n\t\treturn this;\n\t}\n\t/**\n\t* Remove one association and its strongly retained value.\n\t* @param key - weakly held lookup key.\n\t* @returns whether an association was removed.\n\t*/\n\tdelete(key) {\n\t\tif (!this.keys.has(key)) return false;\n\t\tconst value = this.keys.get(key);\n\t\tconst deleted = this.keys.delete(key);\n\t\tthis.valueSet.delete(value);\n\t\treturn deleted;\n\t}\n\t/** Remove every association and strongly retained value. */\n\tclear() {\n\t\tthis.keys = /* @__PURE__ */ new WeakMap();\n\t\tthis.valueSet.clear();\n\t}\n};\n//#endregion\nexport { WeakMapWithValues, assertNever, deepEqualJson, deepFreeze, isJsonValue, snapshotJsonValue };\n","//#region lib/types/file-address.js\n/**\n* The `dsh-resource://file/…` address grammar: how a file is named across the\n* Sidebar and the resource model, built and parsed without touching a\n* filesystem.\n* @module\n*/\n/** The scheme and type every file address opens with. */\nconst FILE_ADDRESS_PREFIX = \"dsh-resource://file/\";\n/** Component-encode one id or path segment, keeping `:` literal for drive letters. */\nfunction encodeSegment(segment) {\n\treturn encodeURIComponent(segment).replace(/%3A/gi, \":\");\n}\n/** Encode a `/`-separated path segment by segment. */\nfunction encodePath(path) {\n\treturn path.split(\"/\").map(encodeSegment).join(\"/\");\n}\n/** Whether a decoded first path segment is a Windows drive (`C:`). */\nfunction isDriveSegment(segment) {\n\treturn segment !== void 0 && /^[A-Za-z]:$/.test(segment);\n}\n/**\n* Build the address of a file read through one Session.\n* @param sessionId - the Session whose Host workspace resolves the path.\n* @param path - absolute or workspace-relative path; backslashes are normalized to `/`, and leading `./` prefixes are dropped.\n* @returns the `dsh-resource://file/session/<sessionId>/<path>` address.\n*/\nfunction sessionFileAddress(sessionId, path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\").replace(/^(?:\\.\\/)+/, \"\");\n\treturn `${FILE_ADDRESS_PREFIX}session/${encodeSegment(sessionId)}/${encodePath(normalized)}`;\n}\n/**\n* Build the address of a file by its absolute path.\n* @param path - absolute path; backslashes are normalized to `/` and the leading `/` is dropped,\n* except that a UNC path (`\\\\server\\share`) keeps one empty first segment.\n* @returns the `dsh-resource://file/absolute/<path>` address.\n*/\nfunction absoluteFileAddress(path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\");\n\tconst unc = normalized.startsWith(\"//\");\n\tconst absolute = normalized.replace(/^\\/+/, \"\");\n\treturn `${FILE_ADDRESS_PREFIX}absolute/${unc ? \"/\" : \"\"}${encodePath(absolute)}`;\n}\n/**\n* Read a file address back into its parts without resolving `.` or `..`.\n* Query and fragment suffixes are ignored; encoded path segments are decoded.\n* @param address - a candidate address.\n* @returns the parts, or `undefined` when the string is not a `dsh-resource://file/` URI in a known scope with a path, or a segment is not validly encoded.\n*/\nfunction parseFileAddress(address) {\n\ttry {\n\t\tif (!address.startsWith(FILE_ADDRESS_PREFIX)) return void 0;\n\t\tconst end = address.search(/[?#]/);\n\t\tconst [scope, ...rest] = address.slice(20, end === -1 ? void 0 : end).split(\"/\");\n\t\tif (scope === \"session\") {\n\t\t\tconst [id, ...segments] = rest;\n\t\t\tif (id === void 0 || id === \"\" || segments.length === 0) return void 0;\n\t\t\treturn {\n\t\t\t\tscope,\n\t\t\t\tsessionId: decodeURIComponent(id),\n\t\t\t\tpath: segments.map(decodeURIComponent).join(\"/\")\n\t\t\t};\n\t\t}\n\t\tif (scope === \"absolute\") {\n\t\t\tconst unc = rest[0] === \"\" && rest.length > 1;\n\t\t\tconst segments = (unc ? rest.slice(1) : rest).map(decodeURIComponent);\n\t\t\tif (segments.length === 0 || segments[0] === \"\") return void 0;\n\t\t\tif (unc) return {\n\t\t\t\tscope,\n\t\t\t\tpath: `//${segments.join(\"/\")}`\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tscope,\n\t\t\t\tpath: isDriveSegment(segments[0]) ? segments.join(\"/\") : `/${segments.join(\"/\")}`\n\t\t\t};\n\t\t}\n\t\treturn;\n\t} catch {\n\t\treturn;\n\t}\n}\n//#endregion\n//#region lib/types/index.js\n/**\n* Browser-safe Workspace path and display helpers.\n* @module @deepseek-ai/dsh-util-workspace-path\n*/\n/** Whether a path uses a Windows drive or UNC prefix. */\nfunction isWindowsStylePath(value) {\n\treturn /^[A-Za-z]:[/\\\\]/.test(value) || value.startsWith(\"\\\\\\\\\");\n}\n/**\n* Whether a path is absolute in either spelling the Host accepts: POSIX (`/a/b`) or Windows drive or UNC.\n* @param path - the path to classify.\n* @returns `true` for an absolute path; `false` for a Workspace-relative one.\n*/\nfunction isAbsoluteWorkspacePath(path) {\n\treturn path.startsWith(\"/\") || isWindowsStylePath(path);\n}\n/**\n* Resolve a Workspace-relative path into the Host-facing spelling used by path operations.\n* @param cwd - Session Workspace root, when known.\n* @param path - Absolute or Workspace-relative path.\n* @returns an absolute path when a Workspace root is available, otherwise the original path.\n*/\nfunction resolveWorkspacePath(cwd, path) {\n\tif (isAbsoluteWorkspacePath(path)) return path;\n\tif (cwd === void 0 || cwd === \"\") return path;\n\tconst separator = isWindowsStylePath(cwd) && cwd.includes(\"\\\\\") ? \"\\\\\" : \"/\";\n\treturn `${cwd.replace(/[/\\\\]+$/, \"\")}${separator}${path.replace(/^[/\\\\]+/, \"\")}`;\n}\n/**\n* Abbreviate a POSIX home directory for display.\n* @param path - Absolute or already-short display path.\n* @param home - Host account home; absent skips abbreviation.\n* @returns `~` or `~/…` for the POSIX home and its descendants, otherwise `path`.\n*/\nfunction abbreviateHomePath(path, home) {\n\tif (home === void 0 || home === \"\") return path;\n\tif (isWindowsStylePath(path) || isWindowsStylePath(home)) return path;\n\tconst root = home.replace(/\\/+$/, \"\");\n\tif (root === \"\" || root === \"/\") return path;\n\tif (path.replace(/\\/+$/, \"\") === root) return \"~\";\n\tif (path.startsWith(`${root}/`)) return `~${path.slice(root.length)}`;\n\treturn path;\n}\n/**\n* Read the final non-empty segment of a Workspace path for display.\n* Workspace-label surfaces use this helper instead of deriving another basename.\n* @param path - Workspace directory path using POSIX or Windows separators.\n* @returns the final segment, or an empty string for a separator-only path.\n*/\nfunction workspaceTitleOf(path) {\n\tconst trimmed = path.replace(/[/\\\\]+$/, \"\");\n\tconst separator = Math.max(trimmed.lastIndexOf(\"/\"), trimmed.lastIndexOf(\"\\\\\"));\n\treturn trimmed.slice(separator + 1);\n}\n/**\n* Split a path for display: the directories through their last separator, and\n* the final segment after it. Both `/` and `\\` separate, so a Windows path\n* splits where its own segments end; trailing separators are dropped first, so\n* a directory path names its own last segment. A path with no separator, or a\n* separator-only path, is all name.\n* @param path - file or directory path using POSIX or Windows separators.\n* @returns the directory prefix (possibly empty) and the final segment.\n*/\nfunction pathPartsOf(path) {\n\tconst trimmed = path.replace(/[/\\\\]+$/, \"\");\n\tif (trimmed === \"\") return {\n\t\tdirectory: \"\",\n\t\tname: path\n\t};\n\tconst cut = Math.max(trimmed.lastIndexOf(\"/\"), trimmed.lastIndexOf(\"\\\\\")) + 1;\n\treturn {\n\t\tdirectory: trimmed.slice(0, cut),\n\t\tname: trimmed.slice(cut)\n\t};\n}\n/**\n* The address for a path as a caller holds it: a relative path, or an absolute\n* path inside the Session's workspace, becomes a `session`-scoped address; an\n* absolute path outside it, or one whose workspace root is unknown, keeps its\n* absolute path in that Session's address.\n* @param sessionId - the Session the path is read in.\n* @param cwd - that Session's workspace root, when known.\n* @param path - absolute or workspace-relative path, in either separator spelling.\n* @returns the `dsh-resource://file/…` address.\n*/\nfunction fileAddressFor(sessionId, cwd, path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\");\n\tif (!isAbsoluteWorkspacePath(normalized)) return sessionFileAddress(sessionId, normalized);\n\tconst root = cwd === void 0 ? \"\" : cwd.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n\tif (root !== \"\" && normalized === root) return sessionFileAddress(sessionId, \"\");\n\tif (root !== \"\" && normalized.startsWith(`${root}/`)) return sessionFileAddress(sessionId, normalized.slice(root.length + 1));\n\treturn sessionFileAddress(sessionId, normalized);\n}\n/**\n* Strip the workspace root from a workspace-rooted absolute path (display only).\n* @param text - the path to shorten.\n* @param cwd - session workspace root; absent or empty leaves the path unchanged.\n* @returns the path relative to the workspace root, or unchanged when it is not rooted there.\n*/\nfunction relativizeToCwd(text, cwd) {\n\tif (cwd === void 0 || cwd === \"\") return text;\n\tconst root = cwd.replace(/[/\\\\]+$/, \"\");\n\tif (text.startsWith(`${root}/`) || text.startsWith(`${root}\\\\`)) return text.slice(root.length + 1);\n\treturn text;\n}\n/**\n* Address a decoded absolute file path through the authenticated file route.\n* @param base - HTTP(S) application base, including its deployment prefix, or `dsh-app://app/`.\n* @param path - Native file path; URL escapes in authored Markdown must already be decoded.\n* @returns File URL, or undefined for unsupported transports and non-absolute paths.\n*/\nfunction fileMediaUrl(base, path) {\n\tif (!/^https?:/u.test(base) && !base.startsWith(\"dsh-app://app/\") || !isAbsoluteWorkspacePath(path) || /^[/\\\\]{2}/u.test(path) || /[\\u0000-\\u001f\\u007f]/u.test(path)) return void 0;\n\treturn new URL(`api/file?path=${encodeURIComponent(path)}`, base).href;\n}\n//#endregion\nexport { abbreviateHomePath, absoluteFileAddress, fileAddressFor, fileMediaUrl, isAbsoluteWorkspacePath, parseFileAddress, pathPartsOf, relativizeToCwd, resolveWorkspacePath, sessionFileAddress, workspaceTitleOf };\n","/**\n * Fork-owned: aggregated live-status computation for collapsed workspace groups.\n *\n * Extracted from `tree.ts` so the upstream diff surface is minimal — the\n * vendored file only needs one import line and one field assignment to wire\n * the badge aggregation in. Everything fork-specific lives here.\n *\n * @module\n */\nimport type { SessionNode } from './tree.ts'\n\n// ── Types (structurally typed to avoid compile-time dependency on cross-plugin packages) ──\n\n/**\n * One session's waiting-review fact, as published by dsh-gitea-dispatch's\n * `useWaitingSummary()` (issue: dsh-gitea-dispatch#16).\n */\nexport interface WaitingReviewSummaryEntry {\n readonly prNumber: number\n readonly state: 'waiting' | 'overdue'\n}\n\n/** Session id → that session's waiting-review fact (no entry = not waiting). */\nexport type WaitingReviewSummaryMap = ReadonlyMap<string, WaitingReviewSummaryEntry>\n\n/**\n * One session's schedule fact, as published by dsh-later's `useScheduleSummary()`.\n */\nexport interface ScheduleSummaryEntry {\n readonly count: number\n readonly pausedCount: number\n readonly nextAt?: number\n readonly state: 'scheduled' | 'urgent' | 'overdue'\n}\n\n/** Session id → that session's schedule fact (no entry = no scheduled tasks). */\nexport type ScheduleSummaryMap = ReadonlyMap<string, ScheduleSummaryEntry>\n\n// ── Aggregated status ──\n\n/**\n * Aggregated live-session counts for one group, computed over all members so a\n * folded folder row can hint at hidden activity.\n */\nexport interface GroupLiveStatus {\n /** Members currently running. */\n running: number\n /** Members awaiting tool approval. */\n approval: number\n /** Members awaiting plan review. */\n planReview: number\n /** Members awaiting a question answer. */\n question: number\n /** Members finished and not yet opened (the green \"done\" reminder). */\n done: number\n /** Running direct children across members. */\n subagents: number\n /** Members with scheduled tasks (from dsh-later). */\n scheduledSessions: number\n /** Total scheduled tasks across members (including paused). */\n scheduledCount: number\n /** Highest-priority schedule state: overdue > urgent > scheduled. */\n scheduleState: 'scheduled' | 'urgent' | 'overdue' | undefined\n /** Members waiting for CI review of their PR (from dsh-gitea-dispatch). */\n waitingReviewCount: number\n /** Highest-priority waiting state across members: overdue > waiting. */\n waitingReviewState: 'waiting' | 'overdue' | undefined\n}\n\n/**\n * Zero-valued sentinel for {@link GroupLiveStatus}.\n *\n * Used when a group is expanded (badge is hidden, so aggregation is wasted\n * work) or when no cross-plugin data is available. Kept as a frozen constant\n * so the reference is stable across renders — `Object.is` comparisons in\n * React selectors never trigger spurious re-renders on it.\n */\nexport const EMPTY_LIVE_STATUS: GroupLiveStatus = Object.freeze({\n running: 0, approval: 0, planReview: 0, question: 0, done: 0, subagents: 0,\n scheduledSessions: 0, scheduledCount: 0, scheduleState: undefined,\n waitingReviewCount: 0, waitingReviewState: undefined,\n}) as GroupLiveStatus\n\n// ── Helpers ──\n\n/**\n * Strip the `session-` / `webhook-` prefix from a Session id.\n *\n * dsh-gitea-dispatch publishes its waiting map keyed by the host SessionId, but\n * its HTTP endpoints key by this normalized form. Accepting both here keeps the\n * badge working across that publisher's conventions without knowing which is in\n * play.\n */\nfunction stripSessionPrefix(id: string): string {\n return id.replace(/^(?:session|webhook)-/, '')\n}\n\n// ── Main computation ──\n\n/**\n * Fold every member row of a group into counts so a collapsed folder can hint at\n * hidden live sessions. Mirrors the session-row status priority (pending\n * outranks running outranks completed) at the counting level; labels resolve with\n * locale at render time.\n * @param nodes - member rows of the group.\n * @param sessionIds - the same members' Session ids (schedule and waiting facts are keyed by id).\n * @param waitingReviewSummary - dsh-gitea-dispatch waiting map, when that plugin is loaded.\n * @param scheduleSummary - dsh-later schedule map, when that plugin is loaded.\n */\nexport function summarizeGroupStatus(\n nodes: readonly SessionNode[],\n sessionIds: readonly string[],\n waitingReviewSummary?: WaitingReviewSummaryMap,\n scheduleSummary?: ScheduleSummaryMap,\n): GroupLiveStatus {\n let running = 0\n let approval = 0\n let planReview = 0\n let question = 0\n let done = 0\n let subagents = 0\n for (const n of nodes) {\n if (n.blank || n.archived) continue\n if (n.pendingInteraction === 'approval') { approval += 1; continue }\n if (n.pendingInteraction === 'plan-review') { planReview += 1; continue }\n if (n.pendingInteraction === 'question') { question += 1; continue }\n if (n.running) running += 1\n else if (n.completed) done += 1\n subagents += n.runningSubagentCount\n }\n\n // Aggregate schedule summary from dsh-later\n let scheduledSessions = 0\n let scheduledCount = 0\n let scheduleState: 'scheduled' | 'urgent' | 'overdue' | undefined = undefined\n\n if (scheduleSummary && sessionIds.length > 0) {\n let totalSessions = 0\n let totalCount = 0\n let highestPriority = 0 // 0=none, 1=scheduled, 2=urgent, 3=overdue\n\n for (const id of sessionIds) {\n const entry = scheduleSummary.get(id)\n if (entry) {\n totalSessions += 1\n totalCount += entry.count\n const priority = entry.state === 'overdue' ? 3 : entry.state === 'urgent' ? 2 : 1\n if (priority > highestPriority) highestPriority = priority\n }\n }\n\n scheduledSessions = totalSessions\n scheduledCount = totalCount\n scheduleState = highestPriority === 3 ? 'overdue' : highestPriority === 2 ? 'urgent' : highestPriority === 1 ? 'scheduled' : undefined\n }\n\n // Aggregate waiting-review summary from dsh-gitea-dispatch (its #16).\n //\n // Counts **members**, not PRs: one session waits on exactly one PR, and the\n // badge's number must mean \"how many sessions in this folder need attention\".\n // `overdue` outranks `waiting` for the dot color, mirroring the schedule rule.\n let waitingReviewCount = 0\n let waitingReviewState: 'waiting' | 'overdue' | undefined = undefined\n if (waitingReviewSummary && sessionIds.length > 0) {\n for (const id of sessionIds) {\n const entry = waitingReviewSummary.get(id) ?? waitingReviewSummary.get(stripSessionPrefix(id))\n if (entry === undefined) continue\n waitingReviewCount += 1\n if (entry.state === 'overdue') waitingReviewState = 'overdue'\n else if (waitingReviewState === undefined) waitingReviewState = 'waiting'\n }\n }\n\n return {\n running, approval, planReview, question, done, subagents,\n scheduledSessions, scheduledCount, scheduleState,\n waitingReviewCount, waitingReviewState,\n }\n}\n","/**\n * Derives the workspace browser tree from caller-projected Workspace and\n * Session order. Unassigned Sessions trail under Ungrouped; only the selected\n * blank Session remains visible.\n */\nimport {\n type SessionListState, type SessionSearchResultItem, type SessionSummary,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {\n SessionStatusSnapshot,\n} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { assertNever } from '@deepseek-ai/dsh-util-values'\nimport { workspaceTitleOf } from '@deepseek-ai/dsh-util-workspace-path'\n// Fork-owned: aggregated status computation extracted to keep upstream diff minimal.\n// Re-exported below so existing imports from `tree.ts` keep working.\nimport {\n EMPTY_LIVE_STATUS,\n summarizeGroupStatus,\n type GroupLiveStatus,\n type ScheduleSummaryEntry,\n type ScheduleSummaryMap,\n type WaitingReviewSummaryEntry,\n type WaitingReviewSummaryMap,\n} from './group-status.ts'\n\n// Re-export fork-owned types and values so consumers importing from `tree.ts`\n// don't need to change their import paths.\nexport {\n EMPTY_LIVE_STATUS,\n summarizeGroupStatus,\n type GroupLiveStatus,\n type ScheduleSummaryEntry,\n type ScheduleSummaryMap,\n type WaitingReviewSummaryEntry,\n type WaitingReviewSummaryMap,\n}\n\n/** Group key for Sessions outside every Workspace. */\nexport const UNGROUPED_KEY = ''\n\n/**\n * Resolve the Workspace browser group that owns one Session.\n * @param workspaces - authoritative Workspace membership.\n * @param sessionId - Session whose browser group is required.\n * @returns owning Workspace id, or {@link UNGROUPED_KEY} when no Workspace accounts for it.\n */\nexport function owningGroupKey(\n workspaces: readonly WorkspaceView[],\n sessionId: SessionId,\n): string {\n return (workspaces.find(workspace => workspace.sessionIds.includes(sessionId))\n ?.workspaceId as string | undefined) ?? UNGROUPED_KEY\n}\n\n/** Pending interaction kinds with dedicated Workspace-row presentation. */\nexport type SessionPendingInteractionStatus = 'approval' | 'plan-review' | 'question'\ntype SessionStatuses = SessionStatusSnapshot\n\nfunction mainSessionId(list: SessionListState): SessionId | undefined {\n return Object.values(list.byId)\n .find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n}\n\n/** One top-level session row in a group or the flat list. */\nexport interface SessionNode {\n id: SessionId\n /** Stored title, or empty; the renderer localizes blank and unnamed row labels. */\n title: string\n /** The provisional blank session (renderer shows the localized New Session title). */\n blank: boolean\n /** A Session-scoped UI consumer is awaiting this user. */\n pendingInteraction?: SessionPendingInteractionStatus\n running: boolean\n /** Running direct children in the loaded subagent catalog. */\n runningSubagentCount: number\n /** Finished running while not selected and not yet opened (the green \"done\" reminder dot). */\n completed: boolean\n /** In the registry-global pin set: leads its section, reorderable only among pinned rows. */\n pinned: boolean\n /** In the registry-global archive set: shown grayed in place and not openable. */\n archived: boolean\n updatedAt: number\n}\n\n/** Session order selected by the Workspace browser. */\nexport type SessionOrderBy = 'manual' | 'updated'\n\n// ── GroupLiveStatus, EMPTY_LIVE_STATUS, and cross-plugin summary types ──\n// Imported from ./group-status.ts and re-exported above (lines 16-32).\n// Keeping them in a separate file minimises the upstream diff surface.\n\n/** One workspace group section: header row facts + visible top-level session rows. */\nexport interface GroupNode {\n /** Group key: the workspace id or {@link UNGROUPED_KEY}. */\n key: string\n /** Backing Workspace id; absent only for the ungrouped bucket. */\n workspaceId: WorkspaceId | undefined\n cwd: string | undefined\n /** Workspace creation time (epoch ms); absent only for the ungrouped bucket. */\n createdAt: number | undefined\n label: string\n /** Total visible sessions in the group. */\n sessionCount: number\n expanded: boolean\n /** The group contains the selected session (active folder tint; supplied here so the renderer never scans). */\n containsCurrent: boolean\n /** Aggregated member status; present even while folded, for the folder badge. */\n liveStatus: GroupLiveStatus\n /** Visible session rows (empty while the group is folded). */\n sessions: readonly SessionNode[]\n}\n\n/** One flat search row combining list metadata with an optional content match. */\nexport interface SearchResultNode {\n id: SessionId\n title: string\n workspace: string\n /** A Session-scoped UI consumer is awaiting this user. */\n pendingInteraction?: SessionPendingInteractionStatus\n running: boolean\n /** Running direct children in the loaded subagent catalog. */\n runningSubagentCount: number\n /** Finished running while not selected and not yet opened (the green \"done\" reminder dot). */\n completed: boolean\n /** In the registry-global archive set: shown grayed and not openable. */\n archived: boolean\n snippet?: string\n}\n\n/** Bounded merged search projection plus the refine-query hint bit. */\nexport interface SearchResultSet {\n items: readonly SearchResultNode[]\n hasMore: boolean\n}\n\n/** Viewing state consumed by the derivation. */\nexport interface TreeView {\n expandedGroups: readonly string[]\n /** Browser-local order for Sessions without a backing Workspace account. */\n ungroupedOrder?: readonly string[]\n}\n\ninterface Group {\n key: string\n workspaceId: WorkspaceId | undefined\n cwd: string | undefined\n createdAt: number | undefined\n label: string\n sessions: SessionSummary[]\n}\n\n/**\n * Directory display label: basename of the path (both separators accepted).\n * Ungrouped-bucket fallback for surfaces without a workspace title.\n * @param cwd - directory path, or undefined for the ungrouped bucket.\n * @returns basename, the raw cwd when it has no basename, or an empty ungrouped marker.\n */\nexport function workspaceLabel(cwd: string | undefined): string {\n if (cwd === undefined || cwd === '') return ''\n const base = workspaceTitleOf(cwd)\n return base !== '' ? base : cwd\n}\n\n/**\n * Project known account members by current Session recency.\n * @param sessionIds - authoritative account membership.\n * @param summaries - current Session summaries; members without a summary are omitted until it arrives.\n * @returns known members newest first, with Session identity as the deterministic tie-break.\n */\nexport function orderByRecency(\n sessionIds: readonly SessionId[],\n summaries: SessionListState['byId'],\n): SessionId[] {\n return sessionIds.flatMap((id) => {\n const summary = summaries[id]\n if (summary === undefined) return []\n return [{ id, rank: summary.updatedAt }]\n })\n .sort((a, b) => {\n if (a.rank !== b.rank) return b.rank - a.rank\n return a.id < b.id ? -1 : 1\n })\n .map(member => member.id)\n}\n\n/**\n * Reconcile a browser-local manual order with current account membership.\n * New ordinary forks precede their sources without changing saved entries' relative order.\n * @param memberIds - authoritative account membership.\n * @param savedOrder - previously saved browser-local order.\n * @param summaries - current Session metadata; unknown new members wait for their summaries.\n * @param rowState - global pin and archive membership; only account members can supplement the order.\n * @returns saved relative positions plus missing members ordered by pin, fork source, recency, and archive status.\n */\nexport function reconcileManualOrder(\n memberIds: readonly SessionId[],\n savedOrder: readonly string[] | undefined,\n summaries: SessionListState['byId'],\n rowState?: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>,\n): SessionId[] {\n const members = new Map(memberIds.map(id => [id as string, id]))\n const included = new Set<string>()\n const ordered: SessionId[] = []\n for (const key of savedOrder ?? []) {\n const id = members.get(key)\n if (id === undefined || included.has(key)) continue\n ordered.push(id)\n included.add(key)\n }\n const archived = new Set(rowState?.archivedSessionIds)\n const pins: SessionId[] = []\n for (const sessionId of rowState?.pinnedSessionIds ?? []) {\n const id = members.get(sessionId)\n if (id === undefined || included.has(id) || archived.has(id) || summaries[id] === undefined) continue\n pins.push(id)\n included.add(id)\n }\n const ordinary: SessionId[] = []\n const archives: SessionId[] = []\n for (const id of orderByRecency([...members.values()].filter(id => !included.has(id)), summaries)) {\n if (archived.has(id)) archives.push(id)\n else ordinary.push(id)\n }\n const result = [...pins, ...ordered, ...ordinary, ...archives]\n const pending = new Set(ordinary)\n const placeFork = (id: SessionId): void => {\n if (!pending.delete(id)) return\n const parentId = summaries[id]?.parentId\n if (parentId === undefined || parentId === id || !result.includes(parentId)) return\n placeFork(parentId)\n result.splice(result.indexOf(id), 1)\n result.splice(result.indexOf(parentId), 0, id)\n }\n for (const id of [...ordinary].reverse()) placeFork(id)\n return result\n}\n\n/**\n * Keep the selected provisional New Session ahead of either base order.\n * @param order - recency or reconciled manual order.\n * @param currentBlank - selected blank Session in this account, when present.\n * @returns a copy with the selected blank first and no duplicate slot.\n */\nexport function pinCurrentBlank(\n order: readonly SessionId[],\n currentBlank: SessionId | undefined,\n): SessionId[] {\n if (currentBlank === undefined) return [...order]\n return [currentBlank, ...order.filter(id => id !== currentBlank)]\n}\n\n/**\n * Archived-row visibility choice: the default hides archived rows, `show`\n * mixes them into their kept slots, and `only` restricts the view (and\n * search) to archived rows.\n */\nexport type ArchivedFilter = 'default' | 'show' | 'only'\n\n/**\n * Ordinary sessions are visible; among blank sessions, only the current one\n * is visible. Subagent children use their parent header catalog; archived\n * sessions follow the archived filter, while their accounting slots remain\n * either way so unarchiving restores position.\n */\nfunction sessionVisible(\n session: SessionSummary,\n current: SessionId | undefined,\n archived: ReadonlySet<SessionId>,\n archivedFilter: ArchivedFilter,\n): boolean {\n if (session.origin === 'subagent') return false\n if (session.blank && session.id !== current) return false\n switch (archivedFilter) {\n case 'default':\n return !archived.has(session.id)\n case 'show':\n return true\n case 'only':\n return archived.has(session.id)\n /* v8 ignore next 2 -- closed-union backstop; only reached if the filter is forged */\n default:\n return assertNever(archivedFilter)\n }\n}\n\n/** Registry-global row state consumed by every tree derivation. */\nexport interface SessionRowState {\n /** Registry-global pin ids; pinned rows lead their section in the local order. */\n pinnedSessionIds: readonly SessionId[]\n /** Archive set; members keep their slots and show grayed while visible. */\n archivedSessionIds: readonly SessionId[]\n /** Archived-row visibility choice applied to lists and search alike. */\n archivedFilter: ArchivedFilter\n}\n\n/**\n * Keep the visible New Session placeholder first, then partition pinned and\n * ordinary rows without changing either partition's caller order.\n */\nfunction sectionMembers(\n members: readonly SessionSummary[],\n pinned: ReadonlySet<SessionId>,\n archived: ReadonlySet<SessionId>,\n): SessionSummary[] {\n const placeholders: SessionSummary[] = []\n const leading: SessionSummary[] = []\n const rest: SessionSummary[] = []\n for (const member of members) {\n if (member.blank) placeholders.push(member)\n else if (!archived.has(member.id) && pinned.has(member.id)) leading.push(member)\n else rest.push(member)\n }\n return [...placeholders, ...leading, ...rest]\n}\n\n/**\n * A blank session is the selected Workspace's provisional New Session row;\n * its canonical title never enters search (blank rows are query-excluded)\n * and the renderer localizes its display label. Unnamed history also yields an\n * empty title for localization and does not match a directory-name title search.\n */\nfunction sessionTitle(session: SessionSummary): string {\n return session.blank ? '' : (session.title?.trim() ?? '')\n}\n\n/** Build one group without projecting session lineage into presentation. */\nfunction buildGroup(\n key: string,\n workspaceId: WorkspaceId | undefined,\n cwd: string | undefined,\n createdAt: number | undefined,\n label: string,\n members: readonly SessionSummary[],\n): Group {\n return { key, workspaceId, cwd, createdAt, label, sessions: [...members] }\n}\n\n/** Apply a stored Ungrouped order and append newly loose Sessions by recency. */\nfunction orderedUngrouped(\n members: readonly SessionSummary[],\n stored: readonly string[] | undefined,\n summaries: SessionListState['byId'],\n): SessionSummary[] {\n const byId = new Map(members.map(session => [session.id as string, session]))\n const ids = stored === undefined\n ? orderByRecency(members.map(session => session.id), summaries)\n : reconcileManualOrder(members.map(session => session.id), stored, summaries)\n return ids.flatMap((id) => {\n const session = byId.get(id)\n /* v8 ignore next -- ids are projected exclusively from the members used to build byId. */\n return session === undefined ? [] : [session]\n })\n}\n\n/**\n * Group Sessions by Workspace: one group per caller-ordered entity, with\n * members resolved from caller-ordered sessionIds. Sessions outside every\n * Workspace trail in the browser-local Ungrouped order, which falls back to\n * recency before that order is initialized.\n */\nfunction groupByWorkspace(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archived: ReadonlySet<SessionId>,\n archivedFilter: ArchivedFilter,\n ungroupedOrder: readonly string[] | undefined,\n): Group[] {\n const current = mainSessionId(list)\n const groups: Group[] = []\n const accounted = new Set<SessionId>()\n for (const workspace of workspaces) {\n const members: SessionSummary[] = []\n for (const id of workspace.sessionIds) {\n const summary = list.byId[id]\n if (summary === undefined) continue // account may lead the list pull; the row appears when the summary lands\n accounted.add(id)\n if (!sessionVisible(summary, current, archived, archivedFilter)) continue\n members.push(summary)\n }\n // The archived-only view lists archives, not the Workspace inventory, so\n // a Workspace without archived Sessions contributes no group.\n if (archivedFilter === 'only' && members.length === 0) continue\n groups.push(buildGroup(\n workspace.workspaceId, workspace.workspaceId, workspace.path,\n Date.parse(workspace.createdAt), workspace.title, members,\n ))\n }\n const stray = list.ids\n .map(id => list.byId[id])\n .filter((s): s is SessionSummary =>\n s !== undefined && !accounted.has(s.id) && sessionVisible(s, current, archived, archivedFilter))\n if (stray.length > 0) {\n groups.push(buildGroup(\n UNGROUPED_KEY,\n undefined,\n undefined,\n undefined,\n '',\n orderedUngrouped(stray, ungroupedOrder, list.byId),\n ))\n }\n return groups\n}\n\n/** Keep navigation presentation independent from domain-owned interaction objects. */\nfunction visiblePendingKind(kind: string | undefined): SessionPendingInteractionStatus | undefined {\n switch (kind) {\n case 'approval':\n case 'plan-review':\n case 'question':\n return kind\n default:\n return undefined\n }\n}\n\nfunction runningChildCount(list: SessionListState, parentId: SessionId, statuses: SessionStatuses): number {\n return list.projectionsBySession[parentId]?.values.subagentCatalog?.reduce(\n (count, child) => count + ((statuses.get(child.id)?.running ?? list.byId[child.id]?.running) === true ? 1 : 0),\n 0,\n ) ?? 0\n}\n\nfunction sessionNode(\n s: SessionSummary,\n list: SessionListState,\n statuses: SessionStatuses,\n pinned: ReadonlySet<SessionId>,\n archived: ReadonlySet<SessionId>,\n): SessionNode {\n const status = statuses.get(s.id)\n const pendingInteraction = visiblePendingKind(status?.pendingInteraction?.kind)\n return {\n id: s.id,\n title: sessionTitle(s),\n blank: s.blank,\n running: status?.running ?? s.running,\n runningSubagentCount: runningChildCount(list, s.id, statuses),\n completed: status?.completionUnread === true,\n pinned: !archived.has(s.id) && pinned.has(s.id),\n archived: archived.has(s.id),\n updatedAt: s.updatedAt,\n ...(pendingInteraction === undefined ? {} : { pendingInteraction }),\n }\n}\n\n/**\n * Derive the workspace browser groups with every session as a top-level row.\n *\n * Every group shows, except that the archived-only filter drops groups\n * without visible members; sessions populate under expanded groups with\n * pinned rows leading in the selected local order. Blank sessions are\n * excluded except for the selected provisional New Session row; archived\n * sessions keep their slots and appear per the archived filter. Content\n * search lives outside this derivation (see {@link deriveSearchResults}).\n * @param list - sessions list snapshot (`mainView` retention feeds containsCurrent).\n * @param workspaces - real Workspaces in Host group order with caller-projected Session order.\n * @param rowState - registry-global pin and archive sets plus the archived filter.\n * @param statuses - unified UI status by Session.\n * @param view - local expansion arrays.\n * @param waitingReviewSummary - dsh-gitea-dispatch waiting map (session id → waiting entry).\n * @param scheduleSummary - dsh-later schedule map (session id → schedule entry).\n * @returns group sections in render order.\n */\nexport function deriveGroups(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n rowState: SessionRowState,\n statuses: SessionStatuses,\n view: TreeView,\n waitingReviewSummary?: WaitingReviewSummaryMap,\n scheduleSummary?: ScheduleSummaryMap,\n): GroupNode[] {\n const archived = new Set(rowState.archivedSessionIds)\n const pinned = new Set(rowState.pinnedSessionIds)\n const expandedGroups = new Set(view.expandedGroups)\n const current = mainSessionId(list)\n const currentGroup = current === undefined\n ? undefined\n : owningGroupKey(workspaces, current)\n const groups: GroupNode[] = []\n for (const g of groupByWorkspace(list, workspaces, archived, rowState.archivedFilter, view.ungroupedOrder)) {\n const expanded = expandedGroups.has(g.key)\n const members = sectionMembers(g.sessions, pinned, archived)\n .map(session => sessionNode(session, list, statuses, pinned, archived))\n const memberIds = members.map(m => m.id)\n groups.push({\n key: g.key,\n workspaceId: g.workspaceId,\n cwd: g.cwd,\n createdAt: g.createdAt,\n label: g.label,\n sessionCount: g.sessions.length,\n expanded,\n containsCurrent: g.key === currentGroup,\n // P0-1 优化:展开时徽标不显示,跳过全量聚合(折叠时再算)。\n // 折叠动作本身触发 re-render,届时 expanded=false 会重新走 summarizeGroupStatus。\n liveStatus: expanded\n ? EMPTY_LIVE_STATUS\n : summarizeGroupStatus(members, memberIds, waitingReviewSummary, scheduleSummary),\n sessions: expanded ? members : [],\n })\n }\n return groups\n}\n\n/**\n * Select complete flat-list membership, independently of archive visibility.\n * @param list - sessions list snapshot.\n * @returns known ordinary Session ids, including archives and only the current blank.\n */\nexport function sessionMemberIds(list: SessionListState): SessionId[] {\n return visibleSessionIds(list, [], 'show')\n}\n\n/**\n * Select visible flat-list members without deriving row presentation or ordering.\n * @param list - sessions list snapshot.\n * @param archivedSessionIds - registry-global archive set.\n * @param archivedFilter - archived-row visibility choice.\n * @returns known visible Session ids in list order, including ordinary forks and only the current blank.\n */\nexport function visibleSessionIds(\n list: SessionListState,\n archivedSessionIds: readonly SessionId[],\n archivedFilter: ArchivedFilter,\n): SessionId[] {\n const archived = new Set(archivedSessionIds)\n const current = mainSessionId(list)\n return list.ids.filter((id) => {\n const s = list.byId[id]\n return s !== undefined && sessionVisible(s, current, archived, archivedFilter)\n })\n}\n\n/**\n * Derive flat rows from the browser's complete ordered Session ids, with\n * pinned rows fronted ahead of the supplied order.\n * @param list - sessions list snapshot used to select the ids.\n * @param sessionIds - complete account members in the selected order, including hidden archives.\n * @param rowState - registry-global pin and archive sets plus the archived filter.\n * @param statuses - unified UI status by Session.\n * @returns flat rows in sectioned order with current status indicators.\n */\nexport function deriveFlat(\n list: SessionListState,\n sessionIds: readonly SessionId[],\n rowState: SessionRowState,\n statuses: SessionStatuses,\n): SessionNode[] {\n const archived = new Set(rowState.archivedSessionIds)\n const pinned = new Set(rowState.pinnedSessionIds)\n const current = mainSessionId(list)\n const members = sessionIds.flatMap((id) => {\n const session = list.byId[id]\n return session !== undefined && sessionVisible(session, current, archived, rowState.archivedFilter)\n ? [session]\n : []\n })\n return sectionMembers(members, pinned, archived)\n .map(session => sessionNode(session, list, statuses, pinned, archived))\n}\n\n/**\n * Merge immediate title/Workspace substring matches with ranked Host content\n * matches. Local rows lead newest-first, content-only rows retain backend\n * order, and duplicate sessions receive the backend snippet in place.\n * @param list - session metadata authority.\n * @param workspaces - Workspace membership and display labels.\n * @param query - caller text; surrounding whitespace is ignored.\n * @param archivedSessionIds - registry-global archive set (members match per the archived filter).\n * @param archivedFilter - archived-row visibility choice; search follows it.\n * @param statuses - unified UI status by Session.\n * @param content - ranked Host content-search page.\n * @param limit - protocol-owned maximum merged row count.\n * @returns bounded deduplicated flat rows and a refine-query hint bit.\n */\nexport function deriveSearchResults(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n query: string,\n archivedSessionIds: readonly SessionId[],\n archivedFilter: ArchivedFilter,\n statuses: SessionStatuses,\n content: { items: readonly SessionSearchResultItem[]; hasMore: boolean },\n limit: number,\n): SearchResultSet {\n const q = query.trim().toLowerCase()\n if (q === '') return { items: [], hasMore: false }\n const archived = new Set(archivedSessionIds)\n const current = mainSessionId(list)\n\n const workspaceBySession = new Map<SessionId, string>()\n for (const workspace of workspaces) {\n for (const sessionId of workspace.sessionIds) {\n if (!workspaceBySession.has(sessionId)) workspaceBySession.set(sessionId, workspace.title)\n }\n }\n const labelOf = (summary: SessionSummary): string =>\n workspaceBySession.get(summary.id) ?? workspaceLabel(summary.cwd)\n const contentBySession = new Map<SessionId, SessionSearchResultItem>()\n for (const item of content.items) {\n if (!contentBySession.has(item.sessionId)) contentBySession.set(item.sessionId, item)\n }\n\n const local: SessionSummary[] = []\n for (const id of list.ids) {\n const summary = list.byId[id]\n // Blank placeholders never match a query (their canonical title displays\n // localized, so matching it would tie search to one language).\n if (summary === undefined || summary.blank || !sessionVisible(summary, current, archived, archivedFilter)) continue\n if (\n sessionTitle(summary).toLowerCase().includes(q)\n || labelOf(summary).toLowerCase().includes(q)\n ) {\n local.push(summary)\n }\n }\n const localById = new Map(local.map(summary => [summary.id, summary]))\n const orderedLocal = orderByRecency(local.map(summary => summary.id), list.byId)\n .map(id => localById.get(id) as SessionSummary)\n\n const ordered: SessionSummary[] = []\n const included = new Set<SessionId>()\n const include = (summary: SessionSummary): void => {\n if (included.has(summary.id)) return\n included.add(summary.id)\n ordered.push(summary)\n }\n for (const summary of orderedLocal) include(summary)\n for (const item of content.items) {\n const summary = list.byId[item.sessionId]\n if (summary !== undefined && !summary.blank && sessionVisible(summary, current, archived, archivedFilter)) include(summary)\n }\n\n return {\n items: ordered.slice(0, limit).map((summary) => {\n const match = contentBySession.get(summary.id)\n const status = statuses.get(summary.id)\n const pendingInteraction = visiblePendingKind(status?.pendingInteraction?.kind)\n return {\n id: summary.id,\n title: sessionTitle(summary),\n workspace: labelOf(summary),\n running: status?.running ?? summary.running,\n runningSubagentCount: runningChildCount(list, summary.id, statuses),\n ...(pendingInteraction === undefined\n ? {}\n : { pendingInteraction }),\n completed: status?.completionUnread === true,\n archived: archived.has(summary.id),\n ...match === undefined ? {} : { snippet: match.snippet },\n }\n }),\n hasMore: content.hasMore || ordered.length > limit,\n }\n}\n\n/** Normalize separators for comparison without interpreting POSIX backslashes as separators. */\nfunction folderPath(path: string): string {\n const windows = /^[A-Za-z]:[/\\\\]/.test(path) || path.startsWith('\\\\\\\\')\n return (windows ? path.replaceAll('\\\\', '/') : path).replace(/\\/+$/, '')\n}\n\n/**\n * Find the nearest registered ancestor, excluding the Workspace directory itself.\n * Paths use Host spelling; matching is case-sensitive, like Workspace identity.\n * @param path - Workspace directory.\n * @param parents - registered Workspace directory paths.\n * @returns the owning parent path, or undefined when no parent contains the Workspace.\n */\nexport function owningParentFolder(path: string, parents: readonly string[]): string | undefined {\n const child = folderPath(path)\n let owner: string | undefined\n let length = -1\n for (const parent of parents) {\n const root = folderPath(parent)\n if (root.length > length && child !== root && child.startsWith(`${root}/`)) {\n owner = parent\n length = root.length\n }\n }\n return owner\n}\n","/**\n * The workspace browser's viewing store: the session-list grouping mode,\n * persisted across reloads. Module level exports the factory only (a\n * module-level handle would pin the store identity across plugin reloads);\n * register() receives the factory and the browser derives its PropsStore\n * share from the return type.\n */\nimport { defineStore, type EngineStoreHandle } from '@deepseek-ai/dsh-client-store'\nimport type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { reconcileManualOrder, type ArchivedFilter, type SessionRowState } from './tree.ts'\n\n/** Browser-local order account for the hierarchy-free flat Session list. */\nexport const FLAT_SESSION_ORDER_KEY = '__flat_session_order__'\n\n/** Session-list grouping mode: sibling Workspace sections, a Workspace tree, or one flat list. */\nexport type SessionGroupBy = 'workspace' | 'workspace-tree' | 'flat'\n/** Session order: saved manual positions or current recency. */\nexport type SessionOrderBy = 'manual' | 'updated'\n\n/** Workspace browser viewing state persisted across surface remounts and reloads. */\ntype WorkspaceViewState = {\n groupBy: SessionGroupBy\n orderBy: SessionOrderBy\n /** Explicit group expansion keyed by Workspace identity, including descendants in tree mode. */\n groupExpansion: Record<string, boolean>\n /** Saved manual order per Workspace group plus the browser-local flat-list account. */\n sessionOrderByAccount: Record<string, string[]>\n /** Archived-row visibility; omitted in pre-filter v5 snapshots and read as 'default'. */\n archivedFilter?: ArchivedFilter\n}\n\ntype SessionOrderSource = {\n members: Readonly<Record<string, readonly SessionId[]>>\n summaries: SessionListState['byId']\n rowState: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>\n}\n\n/**\n * Annotation twin of the actions literal below (the export needs a declared\n * return type); drift fails assignability at the defineStore call.\n */\ntype WorkspaceViewActions = {\n setGroupBy: (draft: WorkspaceViewState, mode: SessionGroupBy) => void\n setOrderBy: (\n draft: WorkspaceViewState,\n mode: SessionOrderBy,\n initialOrders: Readonly<Record<string, readonly string[]>>,\n ) => void\n setGroupExpanded: (draft: WorkspaceViewState, key: string, expanded: boolean) => void\n retainAccountKeys: (draft: WorkspaceViewState, workspaceKeys: readonly string[]) => void\n syncSessionOrders: (\n draft: WorkspaceViewState,\n orders: Readonly<Record<string, readonly string[]>>,\n ) => void\n setSessionOrder: (\n draft: WorkspaceViewState,\n accountKey: string,\n order: readonly string[],\n initialOrders: Readonly<Record<string, readonly string[]>>,\n ) => void\n pinSessionOrder: (\n draft: WorkspaceViewState,\n sessionId: string,\n accountKeys: readonly string[],\n source: SessionOrderSource,\n ) => void\n setArchivedFilter: (draft: WorkspaceViewState, filter: ArchivedFilter) => void\n}\n\n/** Copy read-only projections into the persisted mutable store representation. */\nfunction copySessionOrders(\n orders: Readonly<Record<string, readonly string[]>>,\n): Record<string, string[]> {\n return Object.fromEntries(Object.entries(orders).map(([key, order]) => [key, [...order]]))\n}\n\n/**\n * Create the workspace browser viewing store handle.\n * @returns the store handle (spec + type + identity + factory in one).\n */\nexport function createWorkspaceViewStore(): EngineStoreHandle<WorkspaceViewState, WorkspaceViewActions> {\n return defineStore({\n init: (): WorkspaceViewState => ({\n groupBy: 'workspace',\n orderBy: 'updated',\n groupExpansion: {},\n sessionOrderByAccount: {},\n archivedFilter: 'default',\n }),\n persist: 'dsh.workspace.view.v5',\n actions: {\n setGroupBy: (d, mode: SessionGroupBy) => { d.groupBy = mode },\n setOrderBy: (d, mode: SessionOrderBy, initialOrders) => {\n if (mode === d.orderBy) return\n d.sessionOrderByAccount = mode === 'manual' ? copySessionOrders(initialOrders) : {}\n d.orderBy = mode\n },\n setGroupExpanded: (d, key: string, expanded: boolean) => { d.groupExpansion[key] = expanded },\n retainAccountKeys: (d, workspaceKeys: readonly string[]) => {\n const retained = new Set(workspaceKeys)\n d.groupExpansion = Object.fromEntries(\n Object.entries(d.groupExpansion).filter(([key]) => retained.has(key)),\n )\n d.sessionOrderByAccount = Object.fromEntries(\n Object.entries(d.sessionOrderByAccount).filter(([key]) => retained.has(key)),\n )\n delete (d as WorkspaceViewState & { sessionUpdatedAtByAccount?: unknown }).sessionUpdatedAtByAccount\n },\n syncSessionOrders: (d, orders) => {\n if (d.orderBy !== 'manual') return\n Object.assign(d.sessionOrderByAccount, copySessionOrders(orders))\n },\n setSessionOrder: (d, accountKey, order, initialOrders) => {\n if (d.orderBy === 'updated') d.sessionOrderByAccount = copySessionOrders(initialOrders)\n else Object.assign(d.sessionOrderByAccount, copySessionOrders(initialOrders))\n d.orderBy = 'manual'\n d.sessionOrderByAccount[accountKey] = [...order]\n },\n pinSessionOrder: (d, sessionId, accountKeys, source) => {\n const selected = new Set(accountKeys)\n d.sessionOrderByAccount = Object.fromEntries(Object.entries(source.members).map(([key, members]) => {\n const order = reconcileManualOrder(members, d.sessionOrderByAccount[key], source.summaries, source.rowState)\n return [key, selected.has(key) ? [sessionId, ...order.filter(id => id !== sessionId)] : order]\n }))\n },\n setArchivedFilter: (d, filter: ArchivedFilter) => { d.archivedFilter = filter },\n },\n })\n}\n\n/** The bound write set of one viewing-store instance (what the UiWorkspace service drives). */\nexport type WorkspaceViewStoreActions = ReturnType<ReturnType<typeof createWorkspaceViewStore>['create']>['actions']\n","/**\n * The complete account memberships a Pin order write reconciles against,\n * derived from the same Host snapshots the browser orders by, so the\n * UiWorkspace service can complete the write without the browser in the loop.\n */\nimport type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { FLAT_SESSION_ORDER_KEY } from './stores.ts'\nimport { owningGroupKey, sessionMemberIds, type SessionRowState, UNGROUPED_KEY } from './tree.ts'\n\n/** What `pinSessionOrder` reconciles a pinned Session's accounts against. */\nexport interface PinOrderSource {\n members: Readonly<Record<string, readonly SessionId[]>>\n summaries: SessionListState['byId']\n rowState: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>\n}\n\n/**\n * Every account's complete membership: each Workspace, Ungrouped, and the flat list.\n * @param workspaces - current Host Workspaces.\n * @param list - current Session list snapshot.\n * @param rowState - registry-global pin and archive sets.\n * @returns the order source for one pin write.\n */\nexport function pinOrderSource(\n workspaces: readonly WorkspaceView[],\n list: SessionListState,\n rowState: PinOrderSource['rowState'],\n): PinOrderSource {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return {\n members: Object.fromEntries([\n ...workspaces.map(workspace => [workspace.workspaceId, workspace.sessionIds] as const),\n [UNGROUPED_KEY, list.ids.filter(id => list.byId[id] !== undefined && !accounted.has(id))],\n [FLAT_SESSION_ORDER_KEY, sessionMemberIds(list)],\n ]),\n summaries: list.byId,\n rowState,\n }\n}\n\n/**\n * The accounts a pinned Session leads: its group (or Ungrouped) and the flat list.\n * @param workspaces - current Host Workspaces.\n * @param sessionId - the Session being pinned.\n * @returns the account keys `pinSessionOrder` fronts.\n */\nexport function pinOrderAccounts(workspaces: readonly WorkspaceView[], sessionId: SessionId): readonly string[] {\n return [owningGroupKey(workspaces, sessionId), FLAT_SESSION_ORDER_KEY]\n}\n","/** Workspace archive and directory UI capability. */\n\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport type { ClientRemote, DirectoryListing, RemoteFailure } from '@deepseek-ai/dsh-api-remotes/client'\nimport type {\n ISessions,\n SessionCreateError,\n SessionReference,\n SessionTarget,\n SessionListState,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client'\nimport type {\n IWorkspaces, WorkspaceId, WorkspaceSnapshot, WorkspaceView,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type { RowToast } from './contract/slots.ts'\nimport { pinOrderAccounts, pinOrderSource } from './pin-order.ts'\nimport type { WorkspaceViewStoreActions } from './stores.ts'\n\ninterface MainSelection {\n readonly sessionId?: SessionId\n readonly subagentAddress?: SubagentAddress\n}\n\n/** Workspace archive and directory operations consumed by Client UI domains. */\nexport interface UiWorkspace {\n /**\n * Select a Session and show its Conversation as one UI navigation action.\n * @param target - known Session identity or durable direct-parent subagent address to display.\n */\n openSession(target: SessionTarget): void\n /**\n * Connect a Workspace and open its Session unless a later navigation supersedes it.\n * @param workspaceId - target Workspace.\n * @param beforeOpen - optional synchronous preparation for the selected Session,\n * skipped after supersession; a throw aborts the open and releases the retained reference.\n * @returns completion; a superseded request may create a Session but does not open it.\n * @throws on failure; a refused creation is also shown through the Workspace\n * notice unless a later navigation or disposal superseded the request.\n */\n openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void>\n /**\n * Fork a Session without changing the current selection.\n * @param sessionId - source Session.\n * @param onCreated - observer before the optional child-title update.\n * @returns the child SessionId after creation and inherited-title increment.\n */\n forkSession(sessionId: SessionId, onCreated?: (childId: SessionId) => void): Promise<SessionId>\n /**\n * Resolve the reusable or newly created blank Session for a Workspace.\n * @param workspaceId - target Workspace.\n * @returns a Session already addressable through the Session Controller.\n */\n connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>\n /**\n * Start a New Session flow and navigate to its Session; a creation the Host\n * refuses is shown through the Workspace notice and leaves the selection as it was.\n * @param workspaceId - explicit target; absent inherits the current or most recent Workspace.\n */\n startSession(workspaceId?: WorkspaceId): void\n /**\n * Archive a Session and clear it when it is the current selection.\n * @param sessionId - Session to archive.\n * @param options - `stopActivity` asks the Host to stop the Session's running work instead of refusing.\n */\n archiveSession(sessionId: SessionId, options?: { readonly stopActivity?: boolean }): Promise<void>\n /**\n * Unarchive a Session, restoring it to its recorded Workspace position.\n * @param sessionId - Session to unarchive.\n */\n unarchiveSession(sessionId: SessionId): Promise<void>\n /**\n * Pin a Session on the Host, then lead it in its accounts' saved orders\n * (its Workspace group or Ungrouped, and the flat list). The order write\n * reads the memberships current at completion, so reorders that landed\n * while the Host call was pending keep their positions.\n * @param sessionId - Session to pin.\n */\n pinSession(sessionId: SessionId): Promise<void>\n /**\n * Unpin a Session on the Host; saved positions stay as they are.\n * @param sessionId - Session to unpin.\n */\n unpinSession(sessionId: SessionId): Promise<void>\n /**\n * Open the Host-native directory picker.\n * @returns the selected directory, or null when cancelled.\n */\n pickDirectory(): Promise<string | null>\n /**\n * List one Host directory level.\n * @param path - directory path; absent selects the Host home.\n * @param signal - cancellation for a superseded scan.\n * @returns directory entries and breadcrumb ancestry.\n */\n listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing>\n /**\n * Create a child directory.\n * @param path - existing parent directory.\n * @param name - child directory name.\n * @returns created absolute path.\n */\n createDirectory(path: string, name: string): Promise<string>\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n /** Cross-Controller Workspace navigation and directory UI capability. */\n uiWorkspace: UiWorkspace\n }\n}\n\n/** Structured directory failure exposed to directory UI consumers. */\nexport class DirectoryBrowseError extends Error {\n override readonly name = 'DirectoryBrowseError'\n\n /** @param rpcError - Host directory business failure. */\n constructor(readonly rpcError: RemoteFailure) {\n super(`directory browse failed: ${rpcError.code}: ${rpcError.message}`)\n }\n}\n\n/** Implements Workspace archive and directory UI operations. */\nclass UiWorkspaceService extends Service implements UiWorkspace {\n private readonly connecting = new Map<WorkspaceId, Promise<SessionId>>()\n private readonly lifetime = new AbortController()\n private readonly selection = createSnapshotStore<MainSelection>(\n {}, { persist: { name: 'dsh.sessions.current' } },\n )\n private mainReference: SessionReference | undefined\n\n /**\n * @param ctx - Client root Context.\n * @param directoryPicker - the directory-picking Remote namespace.\n * @param workspaces - pure Workspace Controller.\n * @param sessions - pure Session Controller.\n * @param view - the browser's viewing-store write set (one instance shared with its registration).\n * @param notify - show one notice through the Workspace notice channel.\n */\n constructor(\n ctx: Context,\n private readonly directoryPicker: ClientRemote['directoryPicker'],\n private readonly workspaces: IWorkspaces,\n private readonly sessions: ISessions,\n private readonly view: Pick<WorkspaceViewStoreActions, 'pinSessionOrder'>,\n private readonly notify: (toast: RowToast) => void,\n ) {\n super(ctx, 'uiWorkspace')\n ctx.effect(() => {\n const stop = this.watchNavigation()\n return () => {\n stop()\n this.lifetime.abort()\n const reference = this.mainReference\n this.mainReference = undefined\n reference?.release()\n }\n }, 'ui-workspace: Workspace navigation policy')\n }\n\n async connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId> {\n const workspace = this.workspaces.list.getSnapshot().items\n .find(item => item.workspaceId === workspaceId)\n if (workspace === undefined) {\n throw new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`)\n }\n const inflight = this.connecting.get(workspaceId)\n if (inflight !== undefined) return inflight\n\n const attempt = this.reuseOrCreateBlank(workspace)\n .finally(() => { this.connecting.delete(workspaceId) })\n this.connecting.set(workspaceId, attempt)\n return attempt\n }\n\n private reuseOrCreateBlank(workspace: WorkspaceView): Promise<SessionId> {\n const archived = this.workspaces.list.getSnapshot().archivedSessionIds\n const sessions = this.sessions.list.getSnapshot()\n for (const id of sessions.ids) {\n const summary = sessions.byId[id]\n if (summary === undefined || !summary.blank || summary.cwd !== workspace.path\n || !workspace.sessionIds.includes(id) || archived.includes(id)) continue\n return this.reuseBlank(workspace.workspaceId, id)\n }\n return this.sessions.create({ workspaceId: workspace.workspaceId })\n }\n\n private async reuseBlank(workspaceId: WorkspaceId, sessionId: SessionId): Promise<SessionId> {\n try {\n return await this.sessions.create({ workspaceId, sessionId })\n } catch (error: unknown) {\n if (sessionCreateErrorOf(error)?.rpcError.code !== 'session/writer-held') throw error\n return this.sessions.create({ workspaceId })\n }\n }\n\n openSession(target: SessionTarget): void {\n this.replaceMain(target, this.lifetime.signal, 'reveal')\n }\n\n async openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void> {\n const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])\n let sessionId: SessionId\n try {\n sessionId = await this.connectWorkspace(workspaceId)\n } catch (error: unknown) {\n // Reported here, not in connectWorkspace: startup restoration calls that\n // directly and stays console-only.\n if (!navigation.aborted) this.notify({ kind: 'createFailed', message: creationFailureMessage(error) })\n throw error\n }\n if (navigation.aborted) return\n this.replaceMain(sessionId, navigation, 'reveal', beforeOpen)\n }\n\n async forkSession(sessionId: SessionId, onCreated?: (childId: SessionId) => void): Promise<SessionId> {\n return this.sessions.fork({ sessionId, increaseTitle: true, ...onCreated === undefined ? {} : { onCreated } })\n }\n\n startSession(workspaceId?: WorkspaceId): void {\n const workspace = this.workspaces.list.getSnapshot()\n const sessions = this.sessions.list.getSnapshot()\n const current = this.mainReference?.sessionId\n const currentWorkspaceId = current === undefined\n ? undefined\n : workspace.items.find(item => item.sessionIds.includes(current))?.workspaceId\n const recent = workspace.phase === 'ready' && sessions.phase === 'ready'\n ? recentWorkspace(workspace.items, sessions.byId)\n : undefined\n const target = workspaceId ?? currentWorkspaceId ?? recent\n if (target === undefined) {\n this.clearMain()\n return\n }\n void this.openWorkspace(target).catch(\n (reason: unknown) => { console.warn('new session failed:', reason) },\n )\n }\n\n async archiveSession(sessionId: SessionId, options: { readonly stopActivity?: boolean } = {}): Promise<void> {\n await this.workspaces.archiveSession(sessionId, options)\n if (this.mainReference?.sessionId === sessionId) this.clearMain()\n }\n\n async unarchiveSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.unarchiveSession(sessionId)\n }\n\n async pinSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.pinSession(sessionId)\n const { items, pinnedSessionIds, archivedSessionIds } = this.workspaces.list.getSnapshot()\n this.view.pinSessionOrder(\n sessionId,\n pinOrderAccounts(items, sessionId),\n pinOrderSource(items, this.sessions.list.getSnapshot(), { pinnedSessionIds, archivedSessionIds }),\n )\n }\n\n async unpinSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.unpinSession(sessionId)\n }\n\n async pickDirectory(): Promise<string | null> {\n const result = await this.directoryPicker.pick()\n if (!result.ok) throw new Error(`directory picker failed: ${result.error.message}`)\n return result.value\n }\n\n async listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing> {\n const result = await this.directoryPicker.list(path, signal)\n if (!result.ok) throw new DirectoryBrowseError(result.error)\n return result.value\n }\n\n async createDirectory(path: string, name: string): Promise<string> {\n const result = await this.directoryPicker.createDirectory(path, name)\n if (!result.ok) throw new DirectoryBrowseError(result.error)\n return result.value\n }\n\n private watchNavigation(): () => void {\n let initial: 'waiting' | 'connecting' | 'done' = 'waiting'\n const reconcile = (): void => {\n if (this.lifetime.signal.aborted) return\n if (this.clearArchivedCurrent()) return\n if (initial !== 'waiting') return\n const workspace = this.workspaces.list.getSnapshot()\n const sessions = this.sessions.list.getSnapshot()\n if (workspace.phase !== 'ready' || sessions.phase !== 'ready') return\n if (this.mainReference !== undefined) {\n initial = 'done'\n return\n }\n initial = 'connecting'\n void this.restoreSelection(workspace, sessions).then(\n () => { initial = 'done' },\n (reason: unknown) => {\n if (this.lifetime.signal.aborted) return\n initial = 'waiting'\n console.warn('initial Session restoration failed:', reason)\n },\n )\n }\n\n const disposeWorkspaces = this.workspaces.list.subscribe(reconcile)\n const disposeSessions = this.sessions.list.subscribe(reconcile)\n reconcile()\n return () => {\n this.lifetime.abort()\n disposeSessions()\n disposeWorkspaces()\n }\n }\n\n private async restoreSelection(workspaces: WorkspaceSnapshot, sessions: SessionListState): Promise<void> {\n const saved = this.selection.getSnapshot()\n if (saved.subagentAddress !== undefined) {\n this.replaceMain(saved.subagentAddress, this.lifetime.signal, 'preserve')\n return\n }\n const summary = saved.sessionId === undefined ? undefined : sessions.byId[saved.sessionId]\n const workspace = summary === undefined ? undefined\n : workspaces.items.find(item => item.sessionIds.includes(summary.id))\n if (summary !== undefined && (!summary.blank || workspace === undefined)) {\n this.replaceMain(summary.id, this.lifetime.signal, 'preserve')\n return\n }\n const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])\n let sessionId: SessionId | undefined\n if (summary !== undefined && workspace !== undefined && summary.cwd === workspace.path\n && !workspaces.archivedSessionIds.includes(summary.id)) {\n sessionId = await this.reuseBlank(workspace.workspaceId, summary.id)\n }\n let target = workspace?.workspaceId ?? recentWorkspace(workspaces.items, sessions.byId)\n if (target === undefined && workspaces.items.length === 0 && sessions.ids.length === 0) {\n const prepared = await this.initializeDefaultWorkspace(navigation)\n if (navigation.aborted) return\n target = prepared?.workspaceId\n }\n if (sessionId === undefined && target !== undefined) sessionId = await this.connectWorkspace(target)\n if (sessionId !== undefined && !navigation.aborted) {\n this.replaceMain(sessionId, navigation, 'preserve')\n }\n }\n\n private async initializeDefaultWorkspace(signal: AbortSignal): Promise<WorkspaceView | undefined> {\n try {\n return await this.workspaces.initializeDefault(signal)\n } catch (_error: unknown) {\n if (!signal.aborted) this.notify({ kind: 'defaultWorkspaceFailed' })\n return undefined\n }\n }\n\n /** @returns true when an archived current selection was cleared. */\n private clearArchivedCurrent(): boolean {\n const current = this.mainReference?.sessionId\n if (current === undefined\n || !this.workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false\n this.clearMain()\n return true\n }\n\n private clearMain(): void {\n const previous = this.mainReference\n this.mainReference = undefined\n this.selection.set({})\n previous?.release()\n this.ctx.layout.selectPanel(null)\n }\n\n private replaceMain(\n target: SessionTarget,\n signal: AbortSignal,\n panel: 'reveal' | 'preserve',\n beforeOpen?: (sessionId: SessionId) => void,\n ): void {\n signal.throwIfAborted()\n const reference = this.sessions.retain(target, { source: 'mainView' })\n try {\n signal.throwIfAborted()\n beforeOpen?.(reference.sessionId)\n if (signal.aborted) {\n reference.release()\n return\n }\n const subagentAddress = typeof target === 'string'\n ? this.sessions.subagentAddress(reference.sessionId)\n : target\n this.selection.set({\n sessionId: reference.sessionId,\n ...(subagentAddress === undefined ? {} : { subagentAddress }),\n })\n } catch (error: unknown) {\n reference.release()\n throw error\n }\n const previous = this.mainReference\n this.mainReference = reference\n previous?.release()\n if (panel === 'reveal') this.ctx.layout.selectPanel(null)\n }\n\n}\n\n/**\n * `error` as the Session Controller's creation failure, or undefined when it\n * is not one. Client plugin bundles do not share error-class identity, so the\n * name decides.\n */\nfunction sessionCreateErrorOf(error: unknown): SessionCreateError | undefined {\n return error instanceof Error && error.name === 'SessionCreateError' ? error as SessionCreateError : undefined\n}\n\n/**\n * The words a failed Session creation is reported in: a Host refusal keeps its\n * stable code and message; any other failure keeps its own message.\n */\nfunction creationFailureMessage(error: unknown): string {\n const refused = sessionCreateErrorOf(error)\n if (refused !== undefined) return `${refused.rpcError.code}: ${refused.rpcError.message}`\n return error instanceof Error ? error.message : String(error)\n}\n\n/** Stable tie-breaking follows Host Workspace order. */\nfunction recentWorkspace(\n workspaces: readonly WorkspaceView[],\n sessions: SessionListState['byId'],\n): WorkspaceId | undefined {\n let selected: WorkspaceId | undefined\n let selectedTime = Number.NEGATIVE_INFINITY\n for (const workspace of workspaces) {\n let latest = Number.NEGATIVE_INFINITY\n for (const sessionId of workspace.sessionIds) {\n const session = sessions[sessionId]\n if (session !== undefined) latest = Math.max(latest, session.updatedAt)\n }\n if (latest === Number.NEGATIVE_INFINITY) latest = Date.parse(workspace.createdAt)\n if (selected === undefined || latest > selectedTime) {\n selected = workspace.workspaceId\n selectedTime = latest\n }\n }\n return selected\n}\n\nexport { UiWorkspaceService }\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","/**\n * Fixed first-use Workspace naming, shared by the Host that creates the\n * directory and by browser consumers that label the resulting row. A pure fold\n * with no imports, so client bundles inline it instead of requesting a\n * module-table row this package does not publish.\n * @module @deepseek-ai/dsh-api-workspace-controller/default-workspace\n */\n/**\n * Leaf directory name of the first-use Workspace under\n * `<Documents>/deepseek-harness`. Language-neutral, so one installation keeps\n * one on-disk path across language switches. The registry derives the initial\n * title from this same segment, which is the title\n * {@link workspaceDisplayTitle} recognizes as automatic.\n */\nexport const DEFAULT_WORKSPACE_DIRECTORY = 'default-workspace';\n/**\n * The text one Workspace is labeled with. A Workspace still carrying the\n * automatic first-use title reads as the caller's localized default name; every\n * other title reads verbatim in every language. A title the user typed as\n * exactly {@link DEFAULT_WORKSPACE_DIRECTORY} is labeled as the default too;\n * nothing else depends on the distinction.\n * @param title - stored Workspace title.\n * @param localizedDefault - the default Workspace name in the active language.\n * @returns the title to display.\n */\nexport function workspaceDisplayTitle(title, localizedDefault) {\n return title === DEFAULT_WORKSPACE_DIRECTORY ? localizedDefault : title;\n}\n//# sourceMappingURL=default-workspace.js.map","/**\n * Fork-owned: aggregated status badge for collapsed workspace groups.\n *\n * Extracted from `Rows.tsx` so the upstream diff surface is minimal — the\n * vendored file only needs one import and one `<GroupBadge />` call to wire\n * the badge in. Everything fork-specific lives here.\n *\n * @module\n */\nimport type { ReactNode } from 'react'\nimport {\n IconClockOutlineRegular, IconListPenOutlineRegular, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { GroupLiveStatus, GroupNode } from '../tree.ts'\nimport css from './Rows.module.css'\n\n/** The standard locale seat, prop-passed from the browser root. */\ntype RowTranslate = WorkspaceBrowserProps['t']\n\n// ── Accessible label ──\n\n/**\n * Accessible label for a folded group's aggregated status, reusing the\n * session-row locale keys so both surfaces read identically.\n */\nexport function groupLiveLabel(s: GroupLiveStatus, t: RowTranslate): string {\n const parts: string[] = []\n if (s.approval > 0) parts.push(`${s.approval} ${t('status.waitingApproval')}`)\n if (s.planReview > 0) parts.push(`${s.planReview} ${t('status.planReview')}`)\n if (s.question > 0) parts.push(`${s.question} ${t('status.waitingAnswer')}`)\n if (s.running > 0) parts.push(`${s.running} ${t('status.running')}`)\n if (s.subagents > 0) {\n parts.push(t(s.subagents === 1 ? 'status.subagentsRunning.one' : 'status.subagentsRunning.other', { n: s.subagents }))\n }\n if (s.waitingReviewCount > 0) parts.push(`${s.waitingReviewCount} ${t('status.waitingReview')}`)\n if (s.scheduledSessions > 0) parts.push(`${s.scheduledSessions} ${t('status.scheduled')}`)\n if (s.done > 0) parts.push(`${s.done} ${t('status.completed')}`)\n return parts.join(' · ')\n}\n\n// ── Badge ──\n\n/**\n * Aggregated live-status badge for a folded folder row. Dots reuse StateDot so\n * colors match session rows (warning = pending, ongoing = running, done = completed).\n * Renders nothing while expanded or when nothing is pending/active/completed/scheduled/waiting.\n *\n * Count matches the dots: pending + active + completed + waiting-review + scheduled sessions.\n *\n * `showCompleted` (设置项 `showCompletedInBadge`) 关闭时,`done` 完全退出这个聚合\n * 提示——不画绿点、不计入数字、不参与「是否显示徽标」的判断,等价于旧行为。会话行\n * 自身的绿点不受影响:那是行级状态,不是分组提示。\n */\nexport function groupLiveBadge(group: GroupNode, t: RowTranslate, showCompleted: boolean): ReactNode {\n const s = group.liveStatus\n if (group.expanded || s === undefined) return null\n const pending = s.approval + s.planReview + s.question\n const active = s.running + s.subagents\n const scheduled = s.scheduledSessions\n const hasWaitingReview = s.waitingReviewCount > 0\n const completed = showCompleted ? s.done : 0\n // 只在有 pending / active / 已完成 / 定时任务 / 等待评审时显示徽标\n if (pending === 0 && active === 0 && completed === 0 && scheduled === 0 && !hasWaitingReview) return null\n const label = groupLiveLabel(s, t)\n const dots: ReactNode[] = []\n if (pending > 0) dots.push(<StateDot key=\"warn\" state=\"warning\" />)\n if (active > 0) dots.push(<StateDot key=\"run\" state=\"ongoing\" />)\n if (completed > 0) dots.push(<StateDot key=\"done\" state=\"done\" />)\n // 定时任务图标(紫色 #8b5cf6 与 dsh-later 定时徽标同源,浅深底对比均 >=3:1;\n // urgent 橙 / overdue 红走宿主 warn/error 语义令牌)。与等待评审**用不同图标**——\n // 两者同属\"在等\"的语义,只靠颜色区分对色盲用户不可用。\n if (scheduled > 0) {\n const stateColor = s.scheduleState === 'overdue' ? 'var(--dsw-alias-state-error-primary)' : s.scheduleState === 'urgent' ? 'var(--dsw-alias-state-warn-secondary)' : '#8b5cf6'\n dots.push(\n <span key=\"schedule\" style={{ color: stateColor, display: 'inline-flex', alignItems: 'center' }}>\n <IconClockOutlineRegular size={14} />\n </span>\n )\n }\n // 等待评审图标(琥珀色;超时转红)。数据来自 dsh-gitea-dispatch 的\n // useWaitingSummary()——本插件不自己轮询该端点(其 store 是唯一轮询方)。\n if (hasWaitingReview) {\n const stateColor = s.waitingReviewState === 'overdue' ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-state-warn-secondary)'\n dots.push(\n <span key=\"waiting-review\" style={{ color: stateColor, display: 'inline-flex', alignItems: 'center' }}>\n <IconListPenOutlineRegular size={14} />\n </span>\n )\n }\n // 数字统计 pending + active + 已完成 + 定时任务会话 + 等待评审会话(与 dot 一致)\n // P2-3: 数字上限 99+,避免大项目组徽标过宽。\n // P3-3: count = 1 时省略数字(点已表达\"有东西\",\"1\"无额外信息)。\n const count = pending + active + completed + scheduled + s.waitingReviewCount\n const countLabel = count > 99 ? '99+' : count > 1 ? String(count) : ''\n // P2-2: 紧急状态(overdue/urgent)时添加脉冲动画类。\n const isUrgent = s.scheduleState === 'overdue' || s.scheduleState === 'urgent'\n || s.waitingReviewState === 'overdue'\n const badgeClass = isUrgent ? `${css.groupBadge} ${css.groupBadgeUrgent}` : css.groupBadge\n return (\n <span className={badgeClass} role=\"img\" aria-label={label} title={label}>\n {dots}\n {countLabel && <span className={css.groupBadgeCount}>{countLabel}</span>}\n </span>\n )\n}\n\n// ── Hover-card status lines ──\n\n/**\n * Build the status detail lines for the workspace hover card.\n *\n * Extracted so `WorkspaceHoverContent` in `Rows.tsx` only needs to map the\n * returned array — the fork-specific status→line logic lives here.\n */\nexport function hoverStatusLines(\n status: GroupLiveStatus | undefined,\n t: RowTranslate,\n): { state: 'warning' | 'ongoing' | 'done'; text: string }[] {\n const lines: { state: 'warning' | 'ongoing' | 'done'; text: string }[] = []\n if (status === undefined) return lines\n if (status.approval > 0) lines.push({ state: 'warning', text: `${status.approval} ${t('status.waitingApproval')}` })\n if (status.planReview > 0) lines.push({ state: 'warning', text: `${status.planReview} ${t('status.planReview')}` })\n if (status.question > 0) lines.push({ state: 'warning', text: `${status.question} ${t('status.waitingAnswer')}` })\n if (status.running > 0) lines.push({ state: 'ongoing', text: `${status.running} ${t('status.running')}` })\n if (status.subagents > 0) {\n lines.push({\n state: 'ongoing',\n text: t(status.subagents === 1 ? 'status.subagentsRunning.one' : 'status.subagentsRunning.other', { n: status.subagents }),\n })\n }\n if (status.waitingReviewCount > 0) {\n lines.push({ state: 'warning', text: `${status.waitingReviewCount} ${t('status.waitingReview')}` })\n }\n if (status.scheduledSessions > 0) {\n lines.push({ state: 'warning', text: `${status.scheduledSessions} ${t('status.scheduled')}` })\n }\n if (status.done > 0) lines.push({ state: 'done', text: `${status.done} ${t('status.completed')}` })\n return lines\n}\n","/**\n * Workspace browser tree row components (figma Cell set 14:3080): pure presentational —\n * all data and callbacks arrive via props. Hover swaps (folder->chevron,\n * time->ellipsis, action buttons) are CSS-only, and a session row's clipped\n * title marquees programmatically while the row is hovered. Workspace row\n * menus are visual-only except Rename/Delete. A Session row's \"...\" menu and\n * its hover buttons are the `sidebar.workspaces.session.menu.item` and\n * `sidebar.workspaces.session.row.action` lists, rendered through the\n * browser's `renderSlot` with the menu's open state as the occurrence's hook\n * context; this package's own actions are entries like any plugin's. The\n * session and workspace hover cards are suppressed while a menu is open.\n */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { RefObject } from 'react'\nimport clsx from 'clsx'\nimport type { PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots'\nimport {\n HoverCard, IconArchiveOutlineRegular, IconEditOutlineRegular,\n IconEllipsisOutlineRegular, IconFolderCloseRegular, IconFolderOpenRegular,\n IconNewChatOutlineRegular, IconPinFillRegular, IconTrashOutlineRegular,\n IconTriangleRightFillRegular, IconUnarchiveOutlineRegular, Menu, relativeTime, StateDot, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ShortcutCatalogEntry } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { StateDotState } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { abbreviateHomePath } from '@deepseek-ai/dsh-util-workspace-path'\nimport type { MenuOpenState, WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { GroupLiveStatus, GroupNode, SearchResultNode, SessionNode } from '../tree.ts'\nimport { groupLiveBadge, hoverStatusLines } from './GroupBadge.tsx'\nimport css from './Rows.module.css'\n\n/** The standard locale seat, prop-passed from the browser root. */\ntype RowTranslate = WorkspaceBrowserProps['t']\n\n/**\n * Child-seat renderer threaded from the browser root: the row's action lists,\n * its leading decoration, and its hover-card section. The leading seat is\n * rendered only while the row's primary state is idle, so a status dot and a\n * leading occupant never share the row; the hover seat only while the row's\n * card is open.\n */\ntype RowRenderSlots = PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n>['renderSlot']\n\n/** Row display title: blank rows show the localized New Session label. */\nfunction displayTitle(node: SessionNode, t: RowTranslate): string {\n return node.blank ? t('session.new') : (node.title || t('session.untitled'))\n}\n\n/* Overflow this small hides no meaningful tail; scrolling for it reads as an\n accidental jitter, so the title stays put. */\nconst MIN_TITLE_REVEAL_PX = 8\n\n/* Marquee travel speed: slow enough to read the text as it passes. */\nconst TITLE_MARQUEE_PX_PER_MS = 0.03\n\n/**\n * Place the title's scroll position and publish the stylesheet's fade-mask\n * hooks: `data-scrolled` while the title has left its start (left fade) and\n * `data-clipped` while text remains beyond the right edge (right fade).\n * @param title - the row's clipping title element.\n * @param left - scroll offset in CSS pixels.\n * @param range - the title's maximum scroll offset in CSS pixels.\n */\nfunction placeTitle(title: HTMLSpanElement, left: number, range: number): void {\n // jsdom implements no scrollTo; the lane's direct assignment is instant there\n // anyway, so both paths land on the same position.\n if (typeof title.scrollTo === 'function') title.scrollTo({ left, behavior: 'instant' })\n else title.scrollLeft = left\n if (left > 0) title.dataset.scrolled = ''\n else delete title.dataset.scrolled\n if (left < range) title.dataset.clipped = ''\n else delete title.dataset.clipped\n}\n\n/**\n * Return the title to its resting state: scrolled to the start with both fade\n * masks off, so the resting ellipsis renders at full strength.\n * @param title - the row's clipping title element.\n */\nfunction restTitle(title: HTMLSpanElement): void {\n if (typeof title.scrollTo === 'function') title.scrollTo({ left: 0, behavior: 'instant' })\n else title.scrollLeft = 0\n delete title.dataset.scrolled\n delete title.dataset.clipped\n}\n\n/**\n * Marquee a title wider than its one-line cell while its row is hovered: the\n * title clips its own text, so entering crawls it at a constant speed until the\n * far edge (a fork's incremented title, for example) is in view, then rests\n * there under the pointer. Overflow of at most {@link MIN_TITLE_REVEAL_PX}\n * stays put — a barely-clipped title moving a few pixels reads as jitter, not a\n * reveal. Leaving returns the title to the start in one step, because the\n * resting ellipsis and the narrowed cell would otherwise meet the text while it\n * travelled back. Reduced motion jumps to the far edge instead of crawling.\n * @param title - ref to the row's clipping title element.\n * @returns stable pointer enter/leave handlers for the row.\n */\nfunction useTitleMarquee(title: RefObject<HTMLSpanElement | null>): { enter: () => void; leave: () => void } {\n const frame = useRef(0)\n useEffect(() => () => { cancelAnimationFrame(frame.current) }, [])\n return useMemo(() => ({\n enter: (): void => {\n /* v8 ignore next -- defensive: the title span renders unconditionally. */\n if (title.current === null) return\n const element = title.current\n const range = element.scrollWidth - element.clientWidth\n if (range <= MIN_TITLE_REVEAL_PX) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n placeTitle(element, range, range)\n return\n }\n cancelAnimationFrame(frame.current)\n let previous: number | undefined\n let position = 0\n const step = (now: DOMHighResTimeStamp): void => {\n position += previous === undefined ? 0 : (now - previous) * TITLE_MARQUEE_PX_PER_MS\n previous = now\n placeTitle(element, Math.min(position, range), range)\n if (position < range) frame.current = requestAnimationFrame(step)\n }\n frame.current = requestAnimationFrame(step)\n },\n leave: (): void => {\n cancelAnimationFrame(frame.current)\n /* v8 ignore next -- defensive: the title span renders unconditionally. */\n if (title.current === null) return\n restTitle(title.current)\n },\n }), [title])\n}\n\n/** Localized compact relative time (\"刚刚\"/\"5分钟\" in zh, \"now\"/\"5min\" in en). */\nfunction timeLabel(updatedAt: number, now: number, t: RowTranslate): string {\n const { unit, n } = relativeTime(updatedAt, now)\n return unit === 'now' ? t('time.now') : t(`time.${unit}`, { n })\n}\n\n/** Hover-card variant: distances wrap in the ago template; the now bucket stays bare (no \"now ago\"). */\nfunction hoverTimeLabel(updatedAt: number, now: number, t: RowTranslate): string {\n const { unit, n } = relativeTime(updatedAt, now)\n return unit === 'now' ? t('time.now') : t('time.ago', { t: t(`time.${unit}`, { n }) })\n}\n\n/**\n * Absolute creation time through the dictionary's date template (the message\n * clock pattern): `toLocaleString` would follow the browser language, not the\n * app locale, and produce mixed-language text after a switch.\n */\nfunction createdLabel(createdAt: number, t: RowTranslate): string {\n const d = new Date(createdAt)\n const pad2 = (v: number): string => String(v).padStart(2, '0')\n const date = t('date.ymd', { y: d.getFullYear(), m: d.getMonth() + 1, d: d.getDate() })\n return t('hover.created', { time: `${date} ${pad2(d.getHours())}:${pad2(d.getMinutes())}` })\n}\n\n// groupLiveBadge and groupLiveLabel are fork-owned — imported from ./GroupBadge.tsx.\n\n/** Hover-card body: workspace title, display directory path, absolute creation time. */\nfunction WorkspaceHoverContent({ label, cwd, createdAt, status, t }: {\n label: string\n cwd: string | undefined\n createdAt: number\n /** Aggregated member status, supplied only while the group is folded. */\n status: GroupLiveStatus | undefined\n t: RowTranslate\n}) {\n // Fork-owned: status detail lines computed by GroupBadge.tsx.\n const lines = hoverStatusLines(status, t)\n return (\n <div className={css.hoverContent}>\n <div className={css.hoverTitle}>{label}</div>\n <div className={css.hoverPath}>{cwd}</div>\n <div className={css.hoverTime}>{createdLabel(createdAt, t)}</div>\n {lines.map(line => (\n <div className={css.hoverStatus} key={line.text}>\n <StateDot state={line.state} />\n <span>{line.text}</span>\n </div>\n ))}\n </div>\n )\n}\n\n/**\n * Row drag wiring supplied by the tree owner. `drop` reports the half of the\n * row where the pointer released so the owner can resolve an insert anchor.\n */\nexport interface RowDragProps {\n /** Start dragging this row. */\n start: () => void\n /** A compatible row drag is in flight. */\n active: boolean\n /** Current marker on this row: insert line above, below, or none. */\n marker: 'before' | 'after' | null\n /** Report the hovered half while a compatible drag passes over this row. */\n hover: (half: 'before' | 'after') => void\n drop: (half: 'before' | 'after') => void\n end: () => void\n}\n\n/** Drag lifecycle owned by a workspace row; its enclosing group owns hit testing. */\ninterface WorkspaceRowDragProps {\n start: () => void\n end: () => void\n}\n\n/** Pointer-position half of a row (insert line above or below). */\nfunction rowHalf(e: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = e.currentTarget.getBoundingClientRect()\n return e.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\n/**\n * Project (workspace) header row: folder + title;\n * hover reveals the chevron and create button, and dwelling on a real\n * Workspace shows its hover card (the ungrouped bucket has none).\n * `containsCurrent` arrives on the node (derivation fact, no renderer scan).\n * @param props.group - derived group node.\n * @param props.containsCurrentDescendant - highlight an ancestor even when its subtree is collapsed.\n * @param props.onToggle - expand/collapse the group.\n * @param props.onCreate - start a frontend Session inside this Workspace.\n * @param props.drag - optional workspace-row drag wiring.\n * @param props.home - host account home for POSIX hover-path abbreviation.\n * @param props.t - the browser root's locale seat.\n * @returns the row element.\n */\nexport function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, newShortcut, showCompleted = true, t }: {\n group: GroupNode\n newShortcut?: ShortcutCatalogEntry | undefined\n containsCurrentDescendant?: boolean\n onToggle: () => void\n onCreate: () => void\n /** Real-Workspace actions; absent for the ungrouped bucket (no menu shown). */\n actions?: { rename: () => void; delete: () => void } | undefined\n /** Present only for real Workspace rows in the grouped view. */\n drag?: WorkspaceRowDragProps | undefined\n /** Host account home; POSIX home-rooted hover paths display as `~`. */\n home?: string | undefined\n /** 设置项 `showCompletedInBadge`:折叠徽标是否显示「已完成」绿点。 */\n showCompleted?: boolean | undefined\n t: RowTranslate\n}) {\n const row = group\n // The ungrouped bucket has no workspace title: its label is dictionary copy.\n const label = row.workspaceId === undefined ? t('group.ungrouped') : row.label\n const active = containsCurrentDescendant || (group.expanded && group.containsCurrent)\n const [menuOpen, setMenuOpen] = useState(false)\n const workspaceMenuItems = [\n { id: 'rename', label: t('rename'), icon: <IconEditOutlineRegular /> },\n { id: 'delete', label: t('delete.workspace'), icon: <IconTrashOutlineRegular />, danger: true },\n ]\n const ownRow = (\n <div\n className={clsx(css.projectRow, menuOpen && css.menuOpen)}\n data-row-key={`workspace:${group.key}`}\n role=\"treeitem\"\n aria-expanded={row.expanded}\n onClick={onToggle}\n draggable={drag !== undefined}\n onDragStart={drag === undefined\n ? undefined\n : (e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', row.key)\n drag.start()\n }}\n onDragEnd={drag?.end}\n >\n <span className={clsx(css.slot, css.folder, active && css.folderActive)}>\n {row.expanded ? <IconFolderOpenRegular /> : <IconFolderCloseRegular />}\n </span>\n <span className={clsx(css.slot, css.chevron)}>\n <IconTriangleRightFillRegular className={clsx(css.arrow, row.expanded && css.arrowOpen)} />\n </span>\n <span className={css.projectText}>\n <span className={css.title}>{label}</span>\n </span>\n {groupLiveBadge(row, t, showCompleted)}\n <span className={css.rowActions}>\n {actions !== undefined && (\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={workspaceMenuItems}\n onSelect={(id) => {\n setMenuOpen(false)\n // Unknown ids leave before the dispatch: a future menu row must\n // not inherit the destructive branch as an else fallback.\n /* v8 ignore next -- Menu can emit only the rename and delete rows supplied above. */\n if (id !== 'rename' && id !== 'delete') return\n if (id === 'rename') actions.rename()\n else actions.delete()\n }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('actions.workspace.aria', { name: label })}\n onClick={(e) => { e.stopPropagation(); setMenuOpen(v => !v) }}\n >\n <IconEllipsisOutlineRegular />\n </button>\n )}\n />\n )}\n <Tooltip label={t('actions.newSession')} shortcutKeys={newShortcut?.keys} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-keyshortcuts={newShortcut?.aria}\n aria-label={t('actions.newSession.aria', { name: label })}\n onClick={(e) => { e.stopPropagation(); onCreate() }}\n >\n <IconNewChatOutlineRegular />\n </button>\n </Tooltip>\n </span>\n </div>\n )\n // The ungrouped bucket has no backing Workspace: no card to show.\n if (row.createdAt === undefined) return ownRow\n return (\n <HoverCard\n anchor={ownRow}\n content={<WorkspaceHoverContent\n label={row.label}\n cwd={row.cwd === undefined ? undefined : abbreviateHomePath(row.cwd, home)}\n createdAt={row.createdAt}\n status={row.expanded ? undefined : row.liveStatus}\n t={t}\n />}\n openDelayMs={800}\n disabled={menuOpen}\n copyText={row.cwd}\n copyLabel={t('copy')}\n copiedLabel={t('hover.copied')}\n />\n )\n}\n\n/* v8 ignore next 3 -- closed-union backstop; only reached if the status is forged */\nfunction assertNever(value: never): never {\n throw new Error(`unknown pending interaction: ${String(value)}`)\n}\n\ninterface SessionStatus {\n state: StateDotState\n label: string\n /** Compact text that replaces the Session row's update time. */\n trailingLabel?: string\n}\n\n/**\n * Session status presentation; pending interaction is primary and live activity\n * outranks completion reminders.\n */\nfunction sessionStatuses(\n node: Pick<SessionNode, 'pendingInteraction' | 'running' | 'runningSubagentCount' | 'completed'>,\n t: RowTranslate,\n): readonly [SessionStatus, ...SessionStatus[]] {\n const subagents: SessionStatus | undefined = node.runningSubagentCount === 0\n ? undefined\n : {\n state: 'ongoing',\n label: t(\n node.runningSubagentCount === 1\n ? 'status.subagentsRunning.one'\n : 'status.subagentsRunning.other',\n { n: node.runningSubagentCount },\n ),\n }\n let pending: SessionStatus | undefined\n switch (node.pendingInteraction) {\n case 'approval':\n pending = {\n state: 'warning',\n label: t('status.waitingApproval'),\n trailingLabel: t('status.compact.approval'),\n }\n break\n case 'plan-review':\n pending = {\n state: 'warning',\n label: t('status.planReview'),\n trailingLabel: t('status.compact.planReview'),\n }\n break\n case 'question':\n pending = {\n state: 'warning',\n label: t('status.waitingAnswer'),\n trailingLabel: t('status.compact.answer'),\n }\n break\n case undefined: break\n /* v8 ignore next -- closed PendingInteractionStatus union */\n default: return assertNever(node.pendingInteraction)\n }\n if (pending !== undefined) return subagents === undefined ? [pending] : [pending, subagents]\n if (node.running) {\n const primary: SessionStatus = { state: 'ongoing', label: t('status.running') }\n return subagents === undefined ? [primary] : [primary, subagents]\n }\n if (subagents !== undefined) return [subagents]\n if (node.completed) return [{ state: 'done', label: t('status.completed') }]\n return [{ state: 'idle', label: t('status.idle') }]\n}\n\n/** Primary status dot plus every status's screen-reader label, shared by the search and session rows. */\nfunction SessionStatusDots({ statuses }: { statuses: readonly [SessionStatus, ...SessionStatus[]] }) {\n return (\n <>\n <StateDot state={statuses[0].state} />\n {statuses.map(status => (\n <span className={css.visuallyHidden} key={status.label}>{status.label}</span>\n ))}\n </>\n )\n}\n\n/** Non-interactive pinned-row marker; the enclosing row remains the only action. */\nfunction PinnedIndicator({ t }: { t: RowTranslate }) {\n const label = t('row.pinned')\n return (\n <span className={css.pinIndicator} role=\"img\" aria-label={label} title={label}>\n <IconPinFillRegular size={14} />\n </span>\n )\n}\n\n/**\n * Hover-card body: full title, relative time, the Session's own scheduled-task\n * section, and every relevant live status. The task section sits above the\n * status lines so they stay the card's trailing status line.\n */\nfunction SessionHoverContent({ node, now, renderSlot, t }: {\n node: SessionNode\n now: number\n renderSlot: RowRenderSlots\n t: RowTranslate\n}) {\n // On archived rows the archived line already says the session is inactive,\n // so resting statuses (idle/completed) drop; live activity still shows.\n const statuses = sessionStatuses(node, t)\n .filter(status => !(node.archived && (status.state === 'done' || status.state === 'idle')))\n return (\n <div className={css.hoverContent}>\n <div className={css.hoverTitle}>{displayTitle(node, t)}</div>\n {/* Same placeholder rule as the row's trailing cell: no timestamp\n before the first prompt. */}\n {!node.blank && <div className={css.hoverTime}>{hoverTimeLabel(node.updatedAt, now, t)}</div>}\n {renderSlot('sidebar.session.row.hover', { sessionId: node.id })}\n {statuses.map(status => (\n <div className={css.hoverStatus} key={status.label}>\n <StateDot state={status.state} />\n <span>{status.label}</span>\n </div>\n ))}\n {node.archived && (\n <div className={clsx(css.hoverStatus, css.hoverArchived)}>\n <IconArchiveOutlineRegular size={14} />\n <span>{t('row.archived')}</span>\n </div>\n )}\n </div>\n )\n}\n\n/**\n * One flat search result: title, Workspace context, and optional content\n * excerpt. Search navigation opens the session only; it does not address an\n * event inside the conversation. Archived rows carry a hover unarchive\n * button, because search is where the filter surfaces them for recovery.\n * @param props.result - merged local/content search row.\n * @param props.currentId - selected session id.\n * @param props.onOpen - open the selected session.\n * @param props.onUnarchive - unarchive an archived result row.\n * @param props.t - Workspace-browser translation seat.\n * @returns the result row.\n */\nexport function SearchResultItem({ result, currentId, onOpen, onUnarchive, t }: {\n result: SearchResultNode\n currentId: string | undefined\n onOpen: (id: SearchResultNode['id']) => void\n onUnarchive: (id: SearchResultNode['id']) => void\n t: RowTranslate\n}) {\n const selected = result.id === currentId\n const statuses = sessionStatuses(result, t)\n const primaryStatus = statuses[0]\n return (\n <div\n className={clsx(css.searchResultRow, selected && css.selected, result.archived && css.archived)}\n role=\"treeitem\"\n aria-selected={selected}\n aria-description={result.archived ? t('toast.archivedNotOpenable') : undefined}\n onClick={() => { onOpen(result.id) }}\n >\n <span className={css.searchResultHeading}>\n {/* Like session rows, the leading slot owns every row marker; on\n archived rows it stays blank — the grayed row carries the\n archived look. */}\n <span className={css.slot}>\n {!result.archived && primaryStatus.state !== 'idle' && (\n <SessionStatusDots statuses={statuses} />\n )}\n </span>\n <span className={css.searchResultTitle}>{result.title || t('session.untitled')}</span>\n {result.archived && (\n <span className={css.rowActions}>\n <Tooltip label={t('actions.unarchive')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('menu.unarchiveSession')}\n onClick={(e) => { e.stopPropagation(); onUnarchive(result.id) }}\n >\n <IconUnarchiveOutlineRegular size={14} />\n </button>\n </Tooltip>\n </span>\n )}\n </span>\n <span className={css.searchResultMeta}>\n <span className={css.searchResultWorkspace}>{result.workspace || t('group.ungrouped')}</span>\n {result.snippet !== undefined && (\n <span className={css.searchResultSnippet}>{result.snippet}</span>\n )}\n </span>\n </div>\n )\n}\n\n/**\n * One top-level 32px session row: leading 16px cell (status dot, or the\n * leading seat while the row's primary state is idle), title, relative time or\n * compact pending label, and the row actions menu. A row that owns a state dot\n * keeps that cell and renders no seat, so an ambient automation mark never\n * appears beside the row's own state dot. An archived row keeps the cell blank:\n * neither marker renders there, and its live status stays on the hover card.\n * @param props.node - derived session node.\n * @param props.currentId - selected session id (row highlight).\n * @param props.now - epoch ms for relative-time formatting.\n * @param props.onOpen - open a session by id.\n * @param props.onRenameRequest - open the rename dialog from a title double-click (id + current title).\n * @param props.renderSlot - child-seat renderer for the row's action lists\n * (`sidebar.workspaces.session.menu.item` / `sidebar.workspaces.session.row.action`),\n * its leading decoration, and its hover-card section.\n * @param props.onReveal - scroll this row into view after search navigation, then acknowledge it.\n * @param props.drag - optional row-drag target wiring; blank rows cannot start a drag.\n * @param props.t - the browser root's locale seat.\n * @returns the session row.\n */\nexport function SessionNodeItem({\n node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag, t,\n}: {\n node: SessionNode\n currentId: string | undefined\n now: number\n onOpen: (id: SessionNode['id']) => void\n /** Open the rename dialog from a title double-click (id + current title). */\n onRenameRequest: (id: SessionNode['id'], currentTitle: string) => void\n /** Scroll this row into view after search navigation, then acknowledge it. */\n onReveal?: (() => void) | undefined\n /** Present on reorderable-list rows so every row can remain a drop target. */\n drag?: RowDragProps | undefined\n t: RowTranslate\n} & PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n>) {\n const row = node\n const title = displayTitle(node, t)\n const selected = node.id === currentId\n const statuses = sessionStatuses(node, t)\n const primaryStatus = statuses[0]\n const showStatus = primaryStatus.state !== 'idle'\n // Archived rows hold their in-place grayed slot, so manual reorder cannot\n // move them. Pinned rows drag within the pinned block: the browser gates\n // their drop targets to fellow pinned rows.\n const draggable = drag !== undefined && !row.blank && !row.archived\n const [menuOpen, setMenuOpen] = useState(false)\n // The menu's open state, bound into the row entries' `useMenuOpenState` hook.\n const menuOpenState = useMemo((): MenuOpenState => [menuOpen, setMenuOpen], [menuOpen])\n const rowRef = useRef<HTMLDivElement>(null)\n const titleRef = useRef<HTMLSpanElement>(null)\n const marquee = useTitleMarquee(titleRef)\n useEffect(() => {\n if (onReveal === undefined) return\n rowRef.current?.scrollIntoView({ block: 'nearest' })\n onReveal()\n }, [onReveal])\n // Figma session cell: pad 8, status slot 16, then a 4px title gap.\n const ownRow = (\n <div\n ref={rowRef}\n data-row-key={`session:${node.id}`}\n className={clsx(\n css.sessionRow, selected && css.selected, menuOpen && css.menuOpen,\n row.archived && css.archived,\n drag?.marker === 'before' && css.dropBefore, drag?.marker === 'after' && css.dropAfter,\n )}\n role=\"treeitem\"\n aria-selected={selected}\n aria-description={row.archived ? t('toast.archivedNotOpenable') : undefined}\n onClick={() => { onOpen(node.id) }}\n onPointerEnter={marquee.enter}\n onPointerLeave={marquee.leave}\n draggable={draggable}\n onDragStart={!draggable\n ? undefined\n : (e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', node.id)\n drag.start()\n }}\n onDragEnd={!draggable ? undefined : drag.end}\n onDragOver={drag === undefined\n ? undefined\n : (e) => {\n if (!drag.active) return\n e.preventDefault()\n e.dataTransfer.dropEffect = 'move'\n drag.hover(rowHalf(e))\n }}\n onDrop={drag === undefined\n ? undefined\n : (e) => {\n if (!drag.active) return\n e.preventDefault()\n drag.drop(rowHalf(e))\n }}\n >\n {/* Pending interaction and own or descendant activity outrank the\n finished-but-unviewed reminder, which returns after activity stops\n and is cleared by opening the session. Archived rows keep the slot\n blank — the grayed row carries the archived look — and their live\n status stays on the hover card only. */}\n <span className={css.slot}>\n {!row.archived && !row.blank && (showStatus\n ? <SessionStatusDots statuses={statuses} />\n : renderSlot('sidebar.session.row.leading', { sessionId: node.id }))}\n </span>\n <span\n ref={titleRef}\n className={css.title}\n onDoubleClick={row.blank\n ? undefined\n : (e) => { e.stopPropagation(); onRenameRequest(node.id, row.title) }}\n >\n {title}\n </span>\n {/* A blank New Session row is a provisional placeholder: nothing has\n happened in it yet, so a \"now\" timestamp and the row verbs\n (rename/fork/archive) would all act on content that does not\n exist — both trailing cells stay off until the first prompt. */}\n {!row.blank && (\n <span\n className={css.time}\n aria-hidden={primaryStatus.trailingLabel === undefined ? undefined : true}\n >\n {primaryStatus.trailingLabel ?? timeLabel(row.updatedAt, now, t)}\n </span>\n )}\n {/* Trails the time so the marker occupies the same right-edge cell as\n the hover pin button that replaces it. */}\n {row.pinned && !row.archived && <PinnedIndicator t={t} />}\n {/* The strip's clicks stay in the strip: the trigger and every\n row.action entry act without also opening the row, so an entry's\n button needs no propagation handling of its own. */}\n {!row.blank && (\n <span className={css.rowActions} onClick={(e) => { e.stopPropagation() }}>\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('actions.session.aria', { name: title })}\n onClick={() => { setMenuOpen(v => !v) }}\n >\n <IconEllipsisOutlineRegular />\n </button>\n )}\n >\n {renderSlot(\n 'sidebar.workspaces.session.menu.item',\n { sessionId: node.id, displayTitle: row.title },\n { hookContext: menuOpenState },\n )}\n </Menu>\n {renderSlot('sidebar.workspaces.session.row.action', { sessionId: node.id, displayTitle: row.title })}\n </span>\n )}\n </div>\n )\n return (\n <HoverCard\n anchor={ownRow}\n content={<SessionHoverContent node={node} now={now} renderSlot={renderSlot} t={t} />}\n openDelayMs={800}\n disabled={menuOpen || drag?.active === true}\n copyText={row.blank || row.title === '' ? undefined : row.title}\n copyLabel={t('copy')}\n copiedLabel={t('hover.copied')}\n />\n )\n}\n","/** React-commit-driven movement and entry/exit fades for the sidebar's keyed rows. */\nimport { Component, createRef, type ReactNode } from 'react'\nimport css from './AnimatedRows.module.css'\n\nconst ROW_FADE_MS = 100\nconst ROW_GLIDE_MS = 200\n\ninterface AnimatedRowsProps {\n children: ReactNode\n className: string\n label: string\n /** Unique DOM-order keys matching the rendered data-row-key attributes. */\n rowKeys: readonly string[]\n ready: boolean\n /** Changes that replace the view or reveal hidden rows settle immediately. */\n resetKey: string\n}\n\ninterface RowPosition {\n element: HTMLElement\n rect: DOMRect\n opacity: number\n}\n\ninterface RowSnapshot {\n positions: Map<string, RowPosition>\n removed: Map<string, RowPosition>\n}\n\nfunction sameRows(previous: AnimatedRowsProps, next: AnimatedRowsProps): boolean {\n return previous.rowKeys.length === next.rowKeys.length\n && previous.rowKeys.every((key, index) => key === next.rowKeys[index])\n}\n\nfunction intersects(row: DOMRect, viewport: DOMRect): boolean {\n return row.bottom > viewport.top && row.top < viewport.bottom\n && row.right > viewport.left && row.left < viewport.right\n}\n\n/**\n * Animates keyed sidebar rows only when their rendered membership or order changes.\n * Motion starts after the first pointer or keyboard input inside the mounted list.\n * The parent supplies a positioned container for the inert exit overlay.\n */\nexport class AnimatedRows extends Component<AnimatedRowsProps> {\n private armed = false\n private readonly list = createRef<HTMLDivElement>()\n private readonly overlay = createRef<HTMLDivElement>()\n private readonly movements = new Map<HTMLElement, Animation>()\n private readonly exits = new Map<string, { element: HTMLElement; animation: Animation }>()\n\n override getSnapshotBeforeUpdate(previous: AnimatedRowsProps): RowSnapshot | null {\n const list = this.list.current\n if (!this.armed || sameRows(previous, this.props) || previous.resetKey !== this.props.resetKey\n || !previous.ready || !this.props.ready || list === null\n || typeof list.animate !== 'function'\n || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return null\n\n const viewport = list.getBoundingClientRect()\n const positions = this.readPositions()\n const nextKeys = new Set(this.props.rowKeys)\n const removed = new Map<string, RowPosition>()\n for (const [key, row] of positions) {\n if (nextKeys.has(key) || !intersects(row.rect, viewport)) continue\n const clone = row.element.cloneNode(true) as HTMLElement\n clone.removeAttribute('data-row-key')\n clone.inert = true\n clone.style.setProperty(\n '--dsh-workspace-indent', getComputedStyle(row.element).getPropertyValue('--dsh-workspace-indent'),\n )\n removed.set(key, { ...row, element: clone })\n }\n return { positions, removed }\n }\n\n override componentDidUpdate(previous: AnimatedRowsProps, _state: unknown, snapshot: RowSnapshot | null): void {\n if (snapshot === null) {\n if (!sameRows(previous, this.props) || previous.resetKey !== this.props.resetKey\n || previous.ready !== this.props.ready) this.clear()\n return\n }\n\n this.cancelMovements()\n const list = this.list.current as HTMLDivElement\n const overlay = this.overlay.current as HTMLDivElement\n const viewport = list.getBoundingClientRect()\n const origin = overlay.getBoundingClientRect()\n const positions = this.readPositions()\n\n for (const [key, row] of positions) {\n this.removeExit(key)\n const previousRow = snapshot.positions.get(key)\n if (!intersects(row.rect, viewport)\n && (previousRow === undefined || !intersects(previousRow.rect, viewport))) continue\n if (previousRow === undefined) {\n this.move(row.element, [{ opacity: 0 }, { opacity: 1 }], ROW_FADE_MS)\n continue\n }\n const dx = previousRow.rect.left - row.rect.left\n const dy = previousRow.rect.top - row.rect.top\n if (dx === 0 && dy === 0 && previousRow.opacity === 1) continue\n this.move(row.element, [\n { transform: `translate(${String(dx)}px, ${String(dy)}px)`, opacity: previousRow.opacity },\n { transform: 'translate(0, 0)', opacity: 1 },\n ], ROW_GLIDE_MS)\n }\n\n for (const [key, row] of snapshot.removed) {\n const { element } = row\n this.removeExit(key)\n Object.assign(element.style, {\n position: 'absolute', margin: '0', transform: 'none', boxSizing: 'border-box',\n left: `${String(row.rect.left - origin.left)}px`,\n top: `${String(row.rect.top - origin.top)}px`,\n width: `${String(row.rect.width)}px`, height: `${String(row.rect.height)}px`,\n })\n overlay.append(element)\n const animation = element.animate([{ opacity: row.opacity }, { opacity: 0 }], {\n duration: ROW_FADE_MS, easing: 'ease-out', fill: 'forwards',\n })\n this.exits.set(key, { element, animation })\n animation.onfinish = () => { this.removeExit(key) }\n }\n }\n\n override componentWillUnmount(): void {\n this.clear()\n }\n\n private readPositions(): Map<string, RowPosition> {\n const list = this.list.current as HTMLDivElement\n const rows = list.querySelectorAll<HTMLElement>('[data-row-key]')\n return new Map(Array.from(rows, element => [element.dataset.rowKey as string, {\n element,\n rect: element.getBoundingClientRect(),\n opacity: this.movements.has(element) ? Number(getComputedStyle(element).opacity) : 1,\n }]))\n }\n\n private move(element: HTMLElement, keyframes: Keyframe[], duration: number): void {\n const animation = element.animate(keyframes, { duration, easing: 'ease-out' })\n this.movements.set(element, animation)\n animation.onfinish = () => { this.movements.delete(element); animation.cancel() }\n }\n\n private cancelMovements(): void {\n for (const animation of this.movements.values()) {\n animation.onfinish = null\n animation.cancel()\n }\n this.movements.clear()\n }\n\n private removeExit(key: string): void {\n const exit = this.exits.get(key)\n if (exit === undefined) return\n exit.animation.onfinish = null\n exit.animation.cancel()\n exit.element.remove()\n this.exits.delete(key)\n }\n\n private clear(): void {\n this.cancelMovements()\n for (const key of this.exits.keys()) this.removeExit(key)\n }\n\n override render(): ReactNode {\n return <>\n <div\n ref={this.list}\n className={this.props.className}\n role=\"tree\"\n aria-label={this.props.label}\n onPointerDownCapture={() => { this.armed = true }}\n onKeyDownCapture={() => { this.armed = true }}\n >\n {this.props.children}\n </div>\n <div ref={this.overlay} className={css.exits} aria-hidden=\"true\" />\n </>\n }\n}\n","/**\n * Workspace pick/add flow. WorkspacePickFlow is the reusable core (menu +\n * path error dialog) consumed directly by WorkspaceBrowser (same package) and\n * wrapped by WorkspacePicker for the conversation empty-state slot\n * registration. Directory picking itself lives in the composed flow package's\n * slot occupant (see the contract module doc): this core only opens the flow,\n * adopts the picked path, and owns the error surface. Adding a workspace has\n * exactly one route — pick a host directory, new or existing — because the\n * occupant's own create-folder affordance already covers creating one.\n */\nimport type { ReactNode, RefObject } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport {\n Button, IconFolderCloseRegular, IconPlusOutlineRegular, Menu, Modal, type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n WorkspaceId, WorkspaceSnapshot, WorkspaceView,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { workspaceDisplayTitle } from '@deepseek-ai/dsh-api-workspace-controller/default-workspace'\nimport type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { DirectoryFlowOwnerProps, WorkspacePickerProps } from './contract/slots.ts'\nimport css from './WorkspacePicker.module.css'\n\nconst ADD_WORKSPACE = '::add-workspace'\n\n/** Core flow props: the owner supplies popover control and pick semantics. */\nexport interface WorkspacePickFlowProps {\n /** The standard locale seat, forwarded by whichever slot entry hosts the flow. */\n t: WorkspacePickerProps['t']\n /** Popover visibility (anchor button toggle state, owner-local). */\n open: boolean\n /** The anchor button element — the popover's placement anchor. */\n anchorRef?: RefObject<HTMLElement | null> | undefined\n /** Selector hook over the workspace list (framework standard hook). */\n useWorkspaces: <S>(selector: (state: WorkspaceSnapshot) => S) => S\n /** Adopt a picked host directory as a real Workspace. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n /** Bound occupancy selector hook for this surface's directory-flow hole (empty leaves the surface with no add action). */\n useDirectoryFlow: SnapshotSelectorHook<boolean>\n /** Render this surface's directory-flow hole with the owner conversation (the entry's narrowed renderSlot). */\n renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode\n /** A real Workspace was picked or created. */\n onPick: (workspaceId: WorkspaceId) => void\n /** Close the popover (outside click / Escape / post-pick). */\n onClose: () => void\n /** Report the picking interaction and adoption occupancy. */\n onBusyChange?: (busy: boolean) => void\n /** Only offer the add action, hide existing workspaces. */\n addOnly?: boolean\n /** Menu opening direction relative to the anchor. */\n side?: 'bottom' | 'top' | 'right'\n /** Currently active workspace (trailing check in the picker list). */\n selectedId?: WorkspaceId | undefined\n}\n\n/**\n * Render the pick menu plus the adoption error dialog.\n * @param props - owner-controlled flow props.\n * @returns menu + dialog elements.\n */\nexport function WorkspacePickFlow({\n t,\n open,\n anchorRef,\n useWorkspaces,\n createWorkspace,\n useDirectoryFlow,\n renderDirectoryFlow,\n onPick,\n onClose,\n addOnly = false,\n onBusyChange,\n side = 'bottom',\n selectedId,\n}: WorkspacePickFlowProps) {\n const workspaceSnapshot = useWorkspaces(state => state)\n const workspaces = workspaceSnapshot.items\n const getAnchorRect = useCallback(\n () => anchorRef?.current?.getBoundingClientRect() ?? null,\n [anchorRef],\n )\n const [errorOpen, setErrorOpen] = useState(false)\n const [modalError, setModalError] = useState<string | null>(null)\n const [flowOpen, setFlowOpen] = useState(false)\n const [pickingFolder, setPickingFolder] = useState(false)\n // One picking interaction at a time: while the flow is open (native chooser\n // pending, browse dialog up) or its pick is being adopted, every other\n // menu action stays disabled — a late outcome must not race a concurrent\n // selection or adoption.\n const flowBusy = flowOpen || pickingFolder\n useEffect(() => { onBusyChange?.(flowBusy) }, [flowBusy, onBusyChange])\n\n // The occupied hole gates the picking affordance: with no composed flow the\n // entry simply is not there (the seam's documented no-flow default). The\n // framework-bound hook keeps occupancy live: flow plugins activate (and\n // HMR-reload) independently of this menu's renders.\n const flowAvailable = useDirectoryFlow(occupied => occupied)\n // An occupant that unloads mid-interaction leaves nobody to cancel: an\n // open flow over an empty hole withdraws so the menu actions come back.\n // flowOpen is a dependency because the flow can also OPEN over an already\n // empty hole (Choose again after the occupant unloaded with the error\n // dialog up) — that transition must snap back too, not just occupancy loss.\n useEffect(() => {\n if (flowOpen && !flowAvailable) setFlowOpen(false)\n }, [flowOpen, flowAvailable])\n const addEntries: MenuEntry[] = flowAvailable\n ? [{ id: ADD_WORKSPACE, label: t('menu.addWorkspace'), icon: <IconPlusOutlineRegular size={16} />, disabled: flowBusy }]\n : []\n // With workspaces listed, the add action pins below the scroll region\n // (divider + always visible); otherwise it IS the menu.\n const pinAdd = !addOnly && workspaces.length > 0\n const items: MenuEntry[] = pinAdd\n ? workspaces.map(workspace => ({\n id: workspace.workspaceId,\n label: workspaceDisplayTitle(workspace.title, t('workspace.defaultName')),\n icon: <IconFolderCloseRegular size={16} />,\n disabled: flowBusy,\n }))\n : addEntries\n // Nothing listed and nothing to add with (a composition that mounts this\n // package without any directory-picker): an empty popover would claim a\n // choice that does not exist, so the anchor gesture shows nothing at all.\n const menuIsEmpty = items.length === 0\n\n const closeModal = (): void => {\n setErrorOpen(false)\n setModalError(null)\n }\n\n /** Adopt a picked directory; failures land in the folder-error dialog (Choose again reopens the flow). */\n const adoptDirectory = (path: string): Promise<void> =>\n createWorkspace({ path }).then((workspace) => {\n setFlowOpen(false)\n onPick(workspace.workspaceId)\n }).catch((reason: unknown) => {\n setModalError(reason instanceof Error ? reason.message : String(reason))\n setFlowOpen(false)\n setErrorOpen(true)\n })\n\n const openDirectoryFlow = useCallback((): void => {\n onClose()\n setErrorOpen(false)\n setModalError(null)\n setFlowOpen(true)\n }, [onClose])\n\n // A menu exists to disambiguate between targets. With no workspaces listed\n // and the add action the only entry left, the anchor gesture IS that action:\n // a one-row popover would cost a click and offer nothing to choose between.\n // The owner's open request is consumed the same way selecting the entry\n // would consume it (close the popover, raise the flow). An empty list is\n // only final once the baseline lands — until then the menu stays up with its\n // loading status instead of jumping into a flow the arriving list would have\n // made unnecessary; the add-only surface lists nothing and never waits.\n const listSettled = addOnly || workspaceSnapshot.phase === 'ready'\n const addIsTheOnlyEntry = !pinAdd && listSettled && addEntries.length === 1\n // `flowBusy` gates this exactly as it disables the equivalent menu entry: a\n // pick still being adopted owns the surface until it settles.\n useEffect(() => {\n if (open && addIsTheOnlyEntry && !flowBusy) openDirectoryFlow()\n }, [open, addIsTheOnlyEntry, flowBusy, openDirectoryFlow])\n\n /** Owner side of the flow conversation: adopt keeps the flow open (busy) until the Host answers. */\n const flowOwner: DirectoryFlowOwnerProps = {\n open: flowOpen,\n busy: pickingFolder,\n onPicked: (path) => {\n setPickingFolder(true)\n void adoptDirectory(path).finally(() => { setPickingFolder(false) })\n },\n onCancel: () => { setFlowOpen(false) },\n onError: (message) => {\n setFlowOpen(false)\n setModalError(message)\n setErrorOpen(true)\n },\n }\n\n const handleSelect = (id: string): void => {\n if (id === ADD_WORKSPACE) {\n openDirectoryFlow()\n return\n }\n onPick(id as WorkspaceId)\n }\n\n return (\n <>\n <Menu\n open={open && !addIsTheOnlyEntry && !menuIsEmpty}\n anchor={null}\n items={items}\n {...pinAdd ? { footer: addEntries } : {}}\n selectedId={selectedId}\n onSelect={handleSelect}\n onClose={onClose}\n side={side}\n portal\n getAnchorRect={getAnchorRect}\n />\n {open && !addIsTheOnlyEntry && !menuIsEmpty && workspaceSnapshot.phase === 'pending' && <div className={css.menuStatus} role=\"status\">{t('picker.loading')}</div>}\n {renderDirectoryFlow(flowOwner)}\n <Modal\n open={errorOpen}\n onClose={closeModal}\n closeLabel={t('close')}\n title={t('folderError.title')}\n footer={(\n <>\n <Button variant=\"outline\" className={css.modalAction} onClick={closeModal}>{t('cancel')}</Button>\n {/* Retrying needs an occupant to serve the flow; without one the\n * button would open a flow nobody can answer or cancel. */}\n <Button variant=\"primary\" className={css.modalAction} disabled={!flowAvailable} onClick={openDirectoryFlow}>{t('folderError.retry')}</Button>\n </>\n )}\n >\n <div className={css.modalError} role=\"alert\">{modalError}</div>\n </Modal>\n </>\n )\n}\n\n/**\n * The conversation empty-state registration: adapts the owner share to the\n * core flow (all state and semantics live in the flow / the owner).\n * @param props - empty-state slot props (owner share + injected creation callback).\n * @returns the flow element.\n */\nexport function WorkspacePicker({\n open,\n anchorRef,\n useWorkspaces,\n selectedId,\n onPick,\n onClose,\n createWorkspace,\n useDirectoryFlow,\n renderSlot,\n t,\n}: WorkspacePickerProps) {\n return (\n <WorkspacePickFlow\n t={t}\n open={open}\n anchorRef={anchorRef}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('conversation.hero.workspace.directoryFlow', owner)}\n selectedId={selectedId}\n onPick={onPick}\n onClose={onClose}\n />\n )\n}\n","/**\n * The workspace/session browsing region filling the sidebar shell's\n * `sidebar.workspaces` hole: section header (title + view options + add\n * workspace), search, the grouped tree or flat list, and the workspace\n * dialogs. Wide state renders the full browser; rail state renders the two\n * region icons (search / add workspace) as 36px controls on the shell's shared\n * rail entry path, each requesting expansion through the owner share. Adding\n * is the header button's one action, so it raises the directory flow with no\n * menu in between; the flow and its error dialog live in WorkspacePicker\n * (same package — direct composition, no slot between them). A Session row's\n * \"...\" menu and hover buttons are the `sidebar.workspaces.session.menu.item`\n * and `sidebar.workspaces.session.row.action` lists rendered through this\n * entry's `renderSlot`; the actions in them, this package's own included,\n * are slot entries with their own behavior, so this component threads no\n * action callbacks and hosts no action surface.\n */\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport clsx from 'clsx'\nimport {\n Button, IconArchiveCheckOutlineRegular, IconArchiveOffOutlineRegular, IconArchiveOutlineRegular,\n IconChevronsUpDownOutlineRegular, IconClockOutlineRegular, IconCloseFillRegular,\n IconFlatListOutlineRegular, IconFolderCloseRegular, IconProjectAddOutlineRegular,\n IconQueueOutlineRegular, IconSearchOutlineRegular, IconSlidersTwoOutlineRegular,\n IconWorkspaceTreeOutlineRegular, Menu, Modal, Toast, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n SessionListState, SessionSearchResultItem,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { workspaceDisplayTitle } from '@deepseek-ai/dsh-api-workspace-controller/default-workspace'\n\n// Cross-plugin hooks: each sibling plugin is optional and degrades to \"absent\".\n//\n// The lookup uses this bundle's **injected** `require` — the CJS factory parameter\n// `window.__ModuleLoader__.load({ factory: (require) => … })` supplies, which resolves\n// the module-table rows declared in package.json `dsh.client.external`.\n//\n// It must NOT be `globalThis.require`: the host defines no global require (verified in\n// the live page: `typeof globalThis.require === 'undefined'`), so a global lookup\n// silently disables every cross-plugin integration while still building and booting\n// cleanly. The bundle preset externalizes exactly these specifiers (deps.neverBundle\n// matches dsh.client.external), keeping them runtime requires instead of inlining.\ndeclare const require: (id: string) => unknown\n\n// dsh-later schedule summary API (optional — gracefully degrades when absent)\ntype ScheduleSummaryMap = ReadonlyMap<string, { count: number; pausedCount: number; nextAt?: number; state: 'scheduled' | 'urgent' | 'overdue' }>\nlet useScheduleSummaryHook: (() => ScheduleSummaryMap | undefined) | undefined\ntry {\n const dshLater = require('dsh-later/client') as { useScheduleSummary?: () => ScheduleSummaryMap } | undefined\n useScheduleSummaryHook = dshLater?.useScheduleSummary\n} catch {\n // dsh-later not installed — schedule summary will be undefined\n}\n\n// dsh-gitea-dispatch waiting-review API (dsh-gitea-dispatch#16, same optional rule).\n// Its store owns the only poll of /api/gitea-dispatch/waiting, so this plugin never\n// issues that request itself: the badge costs no extra traffic.\ntype WaitingReviewSummaryMap = ReadonlyMap<string, { prNumber: number; state: 'waiting' | 'overdue' }>\nlet useWaitingSummaryHook: (() => WaitingReviewSummaryMap | undefined) | undefined\ntry {\n const giteaDispatch = require('dsh-gitea-dispatch/client') as { useWaitingSummary?: () => WaitingReviewSummaryMap } | undefined\n useWaitingSummaryHook = giteaDispatch?.useWaitingSummary\n} catch {\n // dsh-gitea-dispatch not installed — waiting review count stays 0\n}\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { ArchivedFilter, GroupNode, SessionNode, SessionOrderBy, SessionRowState } from '../tree.ts'\nimport {\n deriveFlat, deriveGroups, deriveSearchResults, orderByRecency, owningGroupKey, owningParentFolder,\n pinCurrentBlank, reconcileManualOrder, sessionMemberIds, UNGROUPED_KEY,\n} from '../tree.ts'\nimport { ProjectRowItem, SearchResultItem, SessionNodeItem } from './Rows.tsx'\nimport { AnimatedRows } from './AnimatedRows.tsx'\nimport { FLAT_SESSION_ORDER_KEY, type SessionGroupBy } from '../stores.ts'\nimport { WorkspacePickFlow } from '../WorkspacePicker.tsx'\nimport css from './WorkspaceBrowser.module.css'\n\n/**\n * Column slide length (--ds-transition-duration-slow): rail-search focus waits it out —\n * focus() forces a synchronous layout and would jank the slide.\n */\nconst EXPAND_SLIDE_MS = 300\n/** Pause between the latest keystroke and a Host content-search request. */\nconst SEARCH_DEBOUNCE_MS = 250\n/** `session.search` wire bound, measured in JavaScript UTF-16 code units. */\nconst SEARCH_QUERY_MAX_CODE_UNITS = 500\n/** Idle Session rows visible per Workspace before the local overflow control. */\nconst COLLAPSED_SESSION_LIMIT = 5\n\n/** Keep provisional and running rows outside the idle-session quota, including parents with running children. */\nfunction collapsedSessionRows(sessions: readonly SessionNode[], limit = COLLAPSED_SESSION_LIMIT): {\n rows: readonly SessionNode[]\n hiddenCount: number\n} {\n let idleCount = 0\n const rows = sessions.filter((session) => {\n if (session.blank || session.running || session.runningSubagentCount > 0) return true\n if (idleCount >= limit) return false\n idleCount += 1\n return true\n })\n return { rows, hiddenCount: sessions.length - rows.length }\n}\n\n/** Keep controlled input and RPC payload inside the session.search wire contract. */\nfunction sanitizeSearchQuery(value: string): string {\n const withoutNul = value.replaceAll('\\0', '')\n if (withoutNul.length <= SEARCH_QUERY_MAX_CODE_UNITS) return withoutNul\n let end = SEARCH_QUERY_MAX_CODE_UNITS\n const last = withoutNul.charCodeAt(end - 1)\n const next = withoutNul.charCodeAt(end)\n if (last >= 0xD800 && last <= 0xDBFF && next >= 0xDC00 && next <= 0xDFFF) end--\n return withoutNul.slice(0, end)\n}\n\n/**\n * Accept the native drag at document level while a row drag is active: row\n * hover still owns the insertion marker, and releasing outside the list must\n * not be rendered as a rejected drop before dragend commits that last marker.\n */\nfunction useNativeDragAcceptance(active: boolean): void {\n useEffect(() => {\n if (!active) return\n const acceptDrag = (event: DragEvent): void => {\n event.preventDefault()\n if (event.dataTransfer !== null) event.dataTransfer.dropEffect = 'move'\n }\n const acceptDrop = (event: DragEvent): void => { event.preventDefault() }\n document.addEventListener('dragover', acceptDrag)\n document.addEventListener('drop', acceptDrop)\n return () => {\n document.removeEventListener('dragover', acceptDrag)\n document.removeEventListener('drop', acceptDrop)\n }\n }, [active])\n}\n\n/** Grouping, ordering, and archived-filter menu; own open state so it resets with the wide chrome. */\nfunction ViewOptionsMenu({ groupBy, orderBy, archivedFilter, onGroupPick, onOrderPick, onArchivedFilterPick, t }: {\n groupBy: SessionGroupBy\n orderBy: SessionOrderBy\n archivedFilter: ArchivedFilter\n onGroupPick: (mode: SessionGroupBy) => void\n onOrderPick: (mode: SessionOrderBy) => void\n onArchivedFilterPick: (filter: ArchivedFilter) => void\n t: WorkspaceBrowserProps['t']\n}) {\n const [open, setOpen] = useState(false)\n return (\n <Menu\n open={open}\n onClose={() => { setOpen(false) }}\n items={[\n { type: 'label' as const, id: 'group-by', text: t('groupBy.label') },\n { id: 'workspace', label: t('groupBy.workspace'), icon: <IconFolderCloseRegular /> },\n { id: 'workspace-tree', label: t('groupBy.workspaceTree'), icon: <IconWorkspaceTreeOutlineRegular /> },\n { id: 'flat', label: t('groupBy.flat'), icon: <IconFlatListOutlineRegular /> },\n { type: 'separator' as const, id: 'order-by-separator' },\n { type: 'label' as const, id: 'order-by', text: t('orderBy.label') },\n { id: 'manual', label: t('orderBy.manual'), icon: <IconChevronsUpDownOutlineRegular /> },\n { id: 'updated', label: t('orderBy.updated'), icon: <IconClockOutlineRegular /> },\n { type: 'separator' as const, id: 'archived-filter-separator' },\n { type: 'label' as const, id: 'filter-by', text: t('filterBy.label') },\n { id: 'hide-archived', label: t('viewOptions.hideArchived'), icon: <IconArchiveOffOutlineRegular /> },\n { id: 'show-archived', label: t('viewOptions.showArchived'), icon: <IconQueueOutlineRegular /> },\n { id: 'only-archived', label: t('viewOptions.onlyArchived'), icon: <IconArchiveCheckOutlineRegular /> },\n ]}\n selectedIds={[\n groupBy,\n orderBy,\n { default: 'hide-archived', show: 'show-archived', only: 'only-archived' }[archivedFilter],\n ]}\n onSelect={(id) => {\n if (id === 'workspace' || id === 'workspace-tree' || id === 'flat') onGroupPick(id)\n else if (id === 'manual' || id === 'updated') onOrderPick(id)\n else if (id === 'hide-archived') onArchivedFilterPick('default')\n else if (id === 'show-archived') onArchivedFilterPick('show')\n else if (id === 'only-archived') onArchivedFilterPick('only')\n setOpen(false)\n }}\n align=\"end\"\n dense\n listClassName={css.viewOptionsMenu}\n // Portal: the section header clips overflow, so an in-place list would\n // be cut off at the header's bounds.\n portal\n anchor={(\n <Tooltip label={t('viewOptions.label')} side=\"bottom\" delayMs={500}>\n <button\n type=\"button\"\n className={clsx(css.iconButton, css.wide)}\n aria-label={t('viewOptions.label')}\n onClick={() => { setOpen(v => !v) }}\n >\n <IconSlidersTwoOutlineRegular />\n </button>\n </Tooltip>\n )}\n />\n )\n}\n\n/** In-flight root-row drag: source identity plus the current insert marker. */\ninterface DragState {\n /** Workspace id, or {@link UNGROUPED_KEY} for the browser-local loose-session account. */\n accountKey: string\n sessionId: SessionNode['id']\n /** Source row was pinned at drag start; drop targets share the pinned block. */\n pinned: boolean\n /** Row the marker sits on and which half (insert above/below it). */\n over: { id: SessionNode['id']; half: 'before' | 'after' } | null\n}\n\n/** Apply a visible drop to the complete account without removing hidden members. */\nfunction sessionDragOrder(\n order: readonly SessionId[],\n rows: readonly SessionNode[],\n drag: DragState,\n over: NonNullable<DragState['over']>,\n): SessionId[] | undefined {\n const source = rows.find(row => row.id === drag.sessionId)\n const target = rows.find(row => row.id === over.id)\n if (source === undefined || target === undefined || source.blank\n || source.pinned !== drag.pinned || target.pinned !== drag.pinned\n || source.id === target.id || !order.includes(source.id)) return\n const section = rows.filter(row => row.pinned === drag.pinned)\n const sourceIndex = section.findIndex(row => row.id === source.id)\n const withoutSource = section.filter(row => row.id !== source.id)\n const insertAt = withoutSource.findIndex(row => row.id === target.id) + (over.half === 'after' ? 1 : 0)\n if (insertAt === sourceIndex) return\n const next = order.filter(id => id !== source.id)\n const targetIndex = next.indexOf(target.id)\n if (targetIndex === -1) return\n next.splice(targetIndex + (over.half === 'after' ? 1 : 0), 0, source.id)\n return pinCurrentBlank(next, rows.find(row => row.blank)?.id)\n}\n\n/** In-flight Workspace-row drag: source identity plus the current marker. */\ninterface WorkspaceDragState {\n workspaceId: WorkspaceId\n over: { id: WorkspaceId; half: 'before' | 'after' } | null\n}\n\n/** Resolve an insertion side across the Workspace header, descendants, and Sessions. */\nfunction workspaceGroupHalf(e: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = e.currentTarget.getBoundingClientRect()\n return e.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\ntype SessionTreeProps = Pick<\n WorkspaceBrowserProps,\n 'useSessionStatus' | 'startSession' | 'open'\n | 'insertWorkspaceBefore' | 't' | 'usePanelInfo' | 'useBadgeSettings'\n> & PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n> & {\n shortcuts: readonly import('@deepseek-ai/dsh-client-shortcuts/client').ShortcutCatalogEntry[]\n /** Always-mounted Session list snapshot. */\n list: SessionListState\n /** Host account home for POSIX hover-path abbreviation. */\n home?: string | undefined\n /** Workspaces in Host group order with browser-projected Session order. */\n workspaces: readonly WorkspaceView[]\n /** Browser-projected order for Sessions outside every Workspace. */\n ungroupedSessionIds: readonly SessionId[]\n /** Whether the current Workspace stream has a complete Host baseline. */\n workspaceReady: boolean\n /** Grouping, ordering, and filter changes replace the view without row motion. */\n animationResetKey: string\n /** Nest Workspaces under their nearest registered ancestors. */\n nestWorkspaces: boolean\n /** Explicit persisted group expansion, including descendants in tree mode. */\n groupExpansion: Readonly<Record<string, boolean>>\n /** Persist one Workspace group's expansion. */\n setGroupExpanded: (key: string, expanded: boolean) => void\n /** Save a drag order and select Manual. */\n setSessionOrder: (accountKey: string, order: readonly string[]) => void\n /** Registry-global pin and archive sets plus the archived-visibility choice. */\n rowState: SessionRowState\n /** Switch the archived filter back to the default hide-archived view. */\n onLeaveArchivedOnly: () => void\n /** Open the browser-owned rename dialog for a real Workspace group. */\n onRenameRequest: (workspaceId: WorkspaceId, currentTitle: string) => void\n /** Open the browser-owned delete-confirmation dialog for a real Workspace group. */\n onDeleteRequest: (workspaceId: WorkspaceId, currentTitle: string) => void\n /** Open the rename dialog from a row title double-click. */\n onSessionRenameRequest: (sessionId: SessionNode['id'], currentTitle: string) => void\n /** One Session chosen from search that must be exposed and scrolled into view. */\n revealSessionId?: SessionId | undefined\n /** Acknowledge that the chosen Session row has been revealed. */\n onSessionRevealed: (sessionId: SessionId) => void\n}\n\n/** The list-empty placeholder — a glyph over the text; the archived-only view names its filter and offers the way back. */\nfunction EmptySessions({ rowState, onLeaveArchivedOnly, t }: Pick<SessionTreeProps, 'rowState' | 'onLeaveArchivedOnly' | 't'>) {\n const archivedOnly = rowState.archivedFilter === 'only'\n return (\n <div className={css.emptyState} data-row-key=\"empty\">\n {archivedOnly ? <IconArchiveOutlineRegular size={24} /> : <IconQueueOutlineRegular size={24} />}\n <div>{archivedOnly ? t('empty.noneArchived') : t('empty.none')}</div>\n {archivedOnly && (\n <button type=\"button\" className={css.emptyAction} onClick={onLeaveArchivedOnly}>\n {t('empty.viewOthers')}\n </button>\n )}\n </div>\n )\n}\n\n/** The scrolling session tree; unmounting drops the sessions subscription and local row limits. */\nfunction SessionTree({\n list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds,\n rowState, onLeaveArchivedOnly,\n workspaceReady, animationResetKey, usePanelInfo,\n onRenameRequest, onDeleteRequest, onSessionRenameRequest,\n renderSlot,\n insertWorkspaceBefore,\n nestWorkspaces, groupExpansion, setGroupExpanded,\n setSessionOrder, home, t,\n revealSessionId, onSessionRevealed, shortcuts, useBadgeSettings,\n}: SessionTreeProps) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n // 设置项 `showCompletedInBadge`:折叠徽标是否显示「已完成」绿点(默认显示)。\n const showCompleted = useBadgeSettings(settings => settings.showCompletedInBadge)\n const statuses = useSessionStatus(s => s)\n const scheduleSummary = useScheduleSummaryHook?.()\n const waitingReviewSummary = useWaitingSummaryHook?.()\n const current = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const revealGroup = revealSessionId === undefined || !workspaceReady\n ? undefined\n : owningGroupKey(workspaces, revealSessionId)\n const [sessionLimits, setSessionLimits] = useState<Readonly<Record<string, number>>>({})\n // Transient drag marker state; the selected mode owns the resulting order.\n const [drag, setDrag] = useState<DragState | null>(null)\n const sessionDropCommitted = useRef(false)\n const [workspaceDrag, setWorkspaceDrag] = useState<WorkspaceDragState | null>(null)\n const workspaceDropCommitted = useRef(false)\n const nativeDragActive = drag !== null || workspaceDrag !== null\n useNativeDragAcceptance(nativeDragActive)\n const currentGroup = current === undefined || !workspaceReady\n ? undefined\n : owningGroupKey(workspaces, current)\n useEffect(() => {\n if (current === undefined || currentGroup === undefined || Object.hasOwn(groupExpansion, currentGroup)) return\n setGroupExpanded(currentGroup, true)\n }, [current, currentGroup, setGroupExpanded, groupExpansion])\n const parents = useMemo(() => {\n if (!nestWorkspaces) return new Map<string, WorkspaceId | undefined>()\n const keysByPath = new Map(workspaces.map(workspace => [workspace.path, workspace.workspaceId]))\n const paths = [...keysByPath.keys()]\n return new Map<string, WorkspaceId | undefined>(workspaces.map((workspace) => {\n const path = owningParentFolder(workspace.path, paths)\n return [workspace.workspaceId, path === undefined ? undefined : keysByPath.get(path)]\n }))\n }, [nestWorkspaces, workspaces])\n const currentAncestors = useMemo(() => {\n const keys = new Set<string>()\n for (let key = currentGroup === undefined ? undefined : parents.get(currentGroup); key !== undefined; key = parents.get(key)) {\n keys.add(key)\n }\n return keys\n }, [currentGroup, parents])\n const expandedGroups = useMemo(() => {\n const ancestorKeys = new Set<string | undefined>(parents.values())\n return [...workspaces.map(workspace => workspace.workspaceId), UNGROUPED_KEY]\n .filter(key => groupExpansion[key] ?? ancestorKeys.has(key))\n }, [groupExpansion, parents, workspaces])\n // P0-2 优化:全部分组都展开时,跨插件摘要不会被消费(P0-1 已跳过聚合),\n // 显式传 undefined 避免 deriveGroups 内无意义的 Map 查找循环。\n const allGroupsExpanded = expandedGroups.length >= workspaces.length + 1\n && workspaces.every(w => expandedGroups.includes(w.workspaceId))\n && expandedGroups.includes(UNGROUPED_KEY)\n const groups = useMemo(\n () => deriveGroups(list, workspaces, rowState, statuses, {\n expandedGroups,\n ungroupedOrder: ungroupedSessionIds,\n }, allGroupsExpanded ? undefined : waitingReviewSummary, allGroupsExpanded ? undefined : scheduleSummary),\n [list, workspaces, rowState, statuses, expandedGroups, ungroupedSessionIds, scheduleSummary, waitingReviewSummary, allGroupsExpanded],\n )\n useEffect(() => {\n for (let key = revealGroup; key !== undefined; key = parents.get(key)) {\n if (groupExpansion[key] === false || (key === revealGroup && groupExpansion[key] !== true)) {\n setGroupExpanded(key, true)\n }\n }\n }, [groupExpansion, parents, revealGroup, setGroupExpanded])\n useEffect(() => {\n if (revealSessionId === undefined || revealGroup === undefined) return\n const group = groups.find(candidate => candidate.key === revealGroup)\n if (group === undefined || !group.expanded || !group.sessions.some(row => row.id === revealSessionId)) return\n if (collapsedSessionRows(group.sessions).rows.some(row => row.id === revealSessionId)) return\n setSessionLimits(limits => limits[revealGroup] === Infinity ? limits : { ...limits, [revealGroup]: Infinity })\n }, [groups, revealGroup, revealSessionId])\n const now = Date.now()\n const commitSessionDrag = (activeDrag: DragState, over: NonNullable<DragState['over']>): void => {\n if (sessionDropCommitted.current) return\n sessionDropCommitted.current = true\n setDrag(null)\n const group = groups.find(candidate => candidate.key === activeDrag.accountKey)\n if (group === undefined) return\n if (over.id === activeDrag.sessionId) return\n const accountSessionIds = activeDrag.accountKey === UNGROUPED_KEY\n ? ungroupedSessionIds\n : workspaces.find(workspace => workspace.workspaceId === activeDrag.accountKey)?.sessionIds\n if (accountSessionIds === undefined) return\n const renderedSessions = collapsedSessionRows(group.sessions, sessionLimits[group.key]).rows\n const nextOrder = sessionDragOrder(accountSessionIds, renderedSessions, activeDrag, over)\n if (nextOrder !== undefined) setSessionOrder(activeDrag.accountKey, nextOrder)\n }\n const commitWorkspaceDrag = (\n activeDrag: WorkspaceDragState,\n over: NonNullable<WorkspaceDragState['over']>,\n ): void => {\n if (workspaceDropCommitted.current) return\n workspaceDropCommitted.current = true\n setWorkspaceDrag(null)\n const owner = parents.get(activeDrag.workspaceId)\n const siblings = workspaces.filter(workspace => parents.get(workspace.workspaceId) === owner)\n const rowIndex = siblings.findIndex(workspace => workspace.workspaceId === over.id)\n if (rowIndex === -1) return\n const anchor = over.half === 'before' ? over.id : siblings[rowIndex + 1]?.workspaceId\n if (anchor === activeDrag.workspaceId) return\n const sourceIndex = siblings.findIndex(workspace => workspace.workspaceId === activeDrag.workspaceId)\n const anchorIndex = anchor === undefined\n ? siblings.length\n : siblings.findIndex(workspace => workspace.workspaceId === anchor)\n if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return\n insertWorkspaceBefore(activeDrag.workspaceId, anchor).catch((reason: unknown) => {\n console.warn('workspace reorder rejected:', reason)\n })\n }\n const childrenByParent = useMemo(() => {\n const rendered = new Set(groups.map(group => group.key))\n const children = new Map<string | undefined, GroupNode[]>()\n for (const group of groups) {\n // The archived-only view drops empty groups, so an ancestor may be\n // absent; nest under the nearest rendered one.\n let parent = parents.get(group.key)\n while (parent !== undefined && !rendered.has(parent)) parent = parents.get(parent)\n const siblings = children.get(parent)\n if (siblings === undefined) children.set(parent, [group])\n else siblings.push(group)\n }\n return children\n }, [groups, parents])\n const rootGroups = childrenByParent.get(undefined) ?? []\n const workspaceDropAtListStart = rootGroups[0]?.workspaceId !== undefined\n && workspaceDrag?.over?.id === rootGroups[0].workspaceId\n && workspaceDrag.over.half === 'before'\n\n const rowKeys: string[] = groups.length === 0 ? ['empty'] : []\n const renderGroup = (group: GroupNode, depth: number): ReactNode => {\n const workspaceId = group.workspaceId\n const children = childrenByParent.get(group.key) ?? []\n const compatibleDrag = workspaceDrag !== null && parents.get(workspaceDrag.workspaceId) === parents.get(group.key)\n const collapsed = collapsedSessionRows(group.sessions)\n const visible = collapsedSessionRows(group.sessions, sessionLimits[group.key])\n const sessionsExpanded = visible.hiddenCount === 0\n rowKeys.push(`workspace:${group.key}`)\n const childRows = group.expanded ? children.map(child => renderGroup(child, depth + 1)) : []\n const sessions = visible.rows\n for (const node of sessions) rowKeys.push(`session:${node.id}`)\n if (collapsed.hiddenCount > 0) rowKeys.push(`overflow:${group.key}`)\n const workspaceMarker = workspaceId !== undefined && workspaceDrag?.over?.id === workspaceId\n ? workspaceDrag.over.half\n : null\n const workspaceDragProps = workspaceId === undefined ? undefined : {\n start: () => {\n workspaceDropCommitted.current = false\n setWorkspaceDrag({ workspaceId, over: null })\n },\n end: () => {\n if (workspaceDrag?.over !== null && workspaceDrag?.over !== undefined) {\n commitWorkspaceDrag(workspaceDrag, workspaceDrag.over)\n } else {\n setWorkspaceDrag(null)\n }\n workspaceDropCommitted.current = false\n },\n }\n const hoverWorkspace = workspaceId === undefined || !compatibleDrag\n ? undefined\n : (half: 'before' | 'after') => {\n setWorkspaceDrag(active => active === null\n ? active\n : { ...active, over: { id: workspaceId, half } })\n }\n const dropWorkspace = workspaceId === undefined || !compatibleDrag\n ? undefined\n : (half: 'before' | 'after') => {\n commitWorkspaceDrag(workspaceDrag, { id: workspaceId, half })\n }\n return (\n // Group section: header, descendant Workspaces, and own Session rows. The\n // inter-group breathing room is the section's own margin\n // (WorkspaceBrowser.module.css).\n <div\n key={group.key}\n style={{ '--dsh-workspace-indent': `${depth * 12}px` } as CSSProperties}\n className={clsx(\n css.groupSection,\n workspaceMarker === 'before' && css.workspaceDropBefore,\n workspaceMarker === 'after' && css.workspaceDropAfter,\n )}\n onDragOver={workspaceDrag === null\n ? undefined\n : (e) => {\n e.preventDefault()\n if (hoverWorkspace === undefined && parents.get(group.key) !== undefined) return\n e.stopPropagation()\n if (hoverWorkspace === undefined) {\n e.dataTransfer.dropEffect = 'none'\n if (workspaceDrag.over !== null) setWorkspaceDrag({ ...workspaceDrag, over: null })\n } else {\n e.dataTransfer.dropEffect = 'move'\n hoverWorkspace(workspaceGroupHalf(e))\n }\n }}\n onDrop={workspaceDrag === null\n ? undefined\n : (e) => {\n e.preventDefault()\n if (dropWorkspace === undefined && parents.get(group.key) !== undefined) return\n e.stopPropagation()\n if (dropWorkspace === undefined) {\n workspaceDropCommitted.current = true\n setWorkspaceDrag(null)\n } else {\n dropWorkspace(workspaceGroupHalf(e))\n }\n }}\n >\n <ProjectRowItem\n newShortcut={shortcuts.find(row => row.id === 'session.new')}\n group={group}\n containsCurrentDescendant={currentAncestors.has(group.key)}\n home={home}\n showCompleted={showCompleted}\n t={t}\n onToggle={() => {\n if (group.expanded) {\n setSessionLimits(limits => ({ ...limits, [group.key]: COLLAPSED_SESSION_LIMIT }))\n }\n setGroupExpanded(group.key, !group.expanded)\n }}\n onCreate={() => {\n if (group.workspaceId !== undefined) {\n setGroupExpanded(group.key, true)\n startSession(group.workspaceId)\n }\n }}\n drag={workspaceDragProps}\n actions={group.workspaceId === undefined\n ? undefined\n : {\n rename: () => {\n /* v8 ignore next -- narrowing guard: the actions object exists only for real-workspace groups. */\n if (group.workspaceId !== undefined) onRenameRequest(group.workspaceId, group.label)\n },\n delete: () => {\n /* v8 ignore next -- narrowing guard: the actions object exists only for real-workspace groups. */\n if (group.workspaceId !== undefined) onDeleteRequest(group.workspaceId, group.label)\n },\n }}\n />\n {childRows.length > 0 && (\n <div role=\"group\">\n {childRows}\n </div>\n )}\n {sessions.map((node) => {\n // Session drag never leaves its browser-local account, and pinned\n // rows reorder only within their leading pinned block.\n const sameGroupDrag = drag !== null && drag.accountKey === group.key\n const compatibleTarget = sameGroupDrag && drag.pinned === node.pinned\n const normalizeHalf = (half: 'before' | 'after'): 'before' | 'after' =>\n node.blank ? 'after' : half\n const dragProps = {\n start: () => {\n sessionDropCommitted.current = false\n setDrag({ accountKey: group.key, sessionId: node.id, pinned: node.pinned, over: null })\n },\n active: compatibleTarget,\n marker: sameGroupDrag && drag.over?.id === node.id ? drag.over.half : null,\n hover: (half: 'before' | 'after') => {\n /* v8 ignore next -- narrowing guard: Rows gates hover on `active`, which is false while the drag state is null. */\n setDrag(d => (d === null ? d : {\n ...d, over: { id: node.id, half: normalizeHalf(half) },\n }))\n },\n drop: (half: 'before' | 'after') => {\n /* v8 ignore next -- narrowing guard: Rows gates drop on `active`, which is false while the drag state is null. */\n if (drag === null) return\n commitSessionDrag(drag, { id: node.id, half: normalizeHalf(half) })\n },\n end: () => {\n if (drag?.over !== null && drag?.over !== undefined) commitSessionDrag(drag, drag.over)\n else setDrag(null)\n sessionDropCommitted.current = false\n },\n }\n return (\n <SessionNodeItem\n key={node.id}\n node={node}\n currentId={current}\n now={now}\n onOpen={open}\n onRenameRequest={onSessionRenameRequest}\n renderSlot={renderSlot}\n onReveal={node.id === revealSessionId && group.key === revealGroup\n ? () => { onSessionRevealed(node.id) }\n : undefined}\n drag={dragProps}\n t={t}\n />\n )\n })}\n {collapsed.hiddenCount > 0 && (\n <button\n type=\"button\"\n className={css.sessionOverflowButton}\n data-row-key={`overflow:${group.key}`}\n aria-expanded={sessionsExpanded}\n onClick={() => {\n setSessionLimits(limits => ({\n ...limits,\n [group.key]: sessionsExpanded\n ? COLLAPSED_SESSION_LIMIT\n : visible.hiddenCount <= COLLAPSED_SESSION_LIMIT\n ? Infinity\n : (limits[group.key] ?? COLLAPSED_SESSION_LIMIT) + COLLAPSED_SESSION_LIMIT,\n }))\n }}\n >\n {sessionsExpanded\n ? t('sessions.collapse')\n : t('sessions.expand', { n: visible.hiddenCount })}\n </button>\n )}\n </div>\n )\n }\n\n const groupRows = rootGroups.map(group => renderGroup(group, 0))\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n {workspaceDropAtListStart && <span className={css.listTopDropIndicator} aria-hidden=\"true\" />}\n <AnimatedRows\n className={clsx(css.list, workspaceDropAtListStart && css.listTopDropActive)}\n label={t('section.sessions')}\n rowKeys={rowKeys}\n ready={list.phase === 'ready' && workspaceReady && !nativeDragActive}\n resetKey={JSON.stringify([animationResetKey, sessionLimits])}\n >\n {groups.length === 0 && (\n <EmptySessions rowState={rowState} onLeaveArchivedOnly={onLeaveArchivedOnly} t={t} />\n )}\n {groupRows}\n </AnimatedRows>\n <span className={css.fade} />\n </div>\n )\n}\n\n/** The flat \"In one list\" body: every session is one draggable top-level row. */\nfunction FlatList({\n list, sessionIds, rowState, onLeaveArchivedOnly, useSessionStatus, open, onSessionRenameRequest,\n usePanelInfo, setSessionOrder, workspaceReady, animationResetKey,\n revealSessionId, onSessionRevealed, renderSlot, t,\n}: Pick<\n SessionTreeProps,\n | 'useSessionStatus'\n | 'open'\n | 'onSessionRenameRequest'\n | 'renderSlot'\n | 'usePanelInfo'\n | 'setSessionOrder'\n | 'workspaceReady'\n | 'animationResetKey'\n | 'revealSessionId'\n | 'onSessionRevealed'\n | 'rowState'\n | 'onLeaveArchivedOnly'\n | 't'\n> & {\n list: SessionListState\n sessionIds: readonly SessionId[]\n}) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n const statuses = useSessionStatus(s => s)\n const rows = useMemo(\n () => deriveFlat(list, sessionIds, rowState, statuses),\n [list, sessionIds, rowState, statuses],\n )\n const [drag, setDrag] = useState<DragState | null>(null)\n const dropCommitted = useRef(false)\n useNativeDragAcceptance(drag !== null)\n const currentId = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const commitDrag = (activeDrag: DragState, over: NonNullable<DragState['over']>): void => {\n if (dropCommitted.current) return\n dropCommitted.current = true\n setDrag(null)\n const nextOrder = sessionDragOrder(sessionIds, rows, activeDrag, over)\n if (nextOrder !== undefined) setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder)\n }\n const now = Date.now()\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n <AnimatedRows\n className={clsx(css.list, css.flatList)}\n label={t('section.sessions')}\n rowKeys={rows.length === 0 ? ['empty'] : rows.map(row => `session:${row.id}`)}\n ready={list.phase === 'ready' && workspaceReady && drag === null}\n resetKey={animationResetKey}\n >\n {rows.length === 0 && (\n <EmptySessions rowState={rowState} onLeaveArchivedOnly={onLeaveArchivedOnly} t={t} />\n )}\n {rows.map((node) => {\n const active = drag !== null && drag.pinned === node.pinned\n const normalizeHalf = (half: 'before' | 'after'): 'before' | 'after' =>\n node.blank ? 'after' : half\n return (\n <SessionNodeItem\n key={node.id}\n node={node}\n currentId={currentId}\n now={now}\n onOpen={open}\n onRenameRequest={onSessionRenameRequest}\n renderSlot={renderSlot}\n onReveal={node.id === revealSessionId\n ? () => { onSessionRevealed(node.id) }\n : undefined}\n drag={{\n start: () => {\n dropCommitted.current = false\n setDrag({ accountKey: FLAT_SESSION_ORDER_KEY, sessionId: node.id, pinned: node.pinned, over: null })\n },\n active,\n marker: active && drag.over?.id === node.id ? drag.over.half : null,\n hover: (half) => {\n setDrag(current => current === null ? current : {\n ...current, over: { id: node.id, half: normalizeHalf(half) },\n })\n },\n drop: (half) => {\n if (drag !== null) commitDrag(drag, { id: node.id, half: normalizeHalf(half) })\n },\n end: () => {\n if (drag?.over !== null && drag?.over !== undefined) commitDrag(drag, drag.over)\n else setDrag(null)\n dropCommitted.current = false\n },\n }}\n t={t}\n />\n )\n })}\n </AnimatedRows>\n <span className={css.fade} />\n </div>\n )\n}\n\ninterface RemoteSearchState {\n query: string\n status: 'idle' | 'loading' | 'ready' | 'error'\n items: readonly SessionSearchResultItem[]\n hasMore: boolean\n}\n\n/** Flat search body: local metadata matches plus the current Host result page. */\nfunction SearchResults({\n useSessions,\n useSessionStatus,\n open,\n onUnarchive,\n workspaces,\n archivedSessionIds,\n archivedFilter,\n query,\n remote,\n resultLimit,\n usePanelInfo,\n t,\n}: Pick<WorkspaceBrowserProps, 'useSessions' | 'useSessionStatus' | 'open' | 't' | 'usePanelInfo'> & {\n workspaces: readonly WorkspaceView[]\n archivedSessionIds: readonly SessionNode['id'][]\n /** Search matches follow the archived filter selected for the list. */\n archivedFilter: ArchivedFilter\n /** Unarchive an archived result row in place. */\n onUnarchive: (id: SessionNode['id']) => void\n query: string\n remote: RemoteSearchState\n resultLimit: number\n}) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n const list = useSessions(s => s)\n const statuses = useSessionStatus(s => s)\n const currentRemote = remote.query === query\n ? remote\n : { query, status: 'loading' as const, items: [], hasMore: false }\n const results = useMemo(\n () => deriveSearchResults(\n list,\n workspaces,\n query,\n archivedSessionIds,\n archivedFilter,\n statuses,\n currentRemote,\n resultLimit,\n ),\n [list, workspaces, query, archivedSessionIds, archivedFilter, statuses, currentRemote, resultLimit],\n )\n const pending = currentRemote.status === 'loading'\n const currentId = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n <div className={css.list}>\n <div className={css.searchTree} role=\"tree\" aria-label={t('search.results.aria')}>\n {results.items.map(result => (\n <SearchResultItem\n key={result.id}\n result={result}\n currentId={currentId}\n onOpen={open}\n onUnarchive={onUnarchive}\n t={t}\n />\n ))}\n </div>\n {pending && (\n /* Two skeleton rows on an empty list, one when local matches already\n show and only the content hits are outstanding. */\n <div role=\"status\" aria-label={t('search.pending')}>\n {(results.items.length === 0 ? [0, 1] : [0]).map(i => (\n <div key={i} className={css.skeletonRow} aria-hidden=\"true\">\n <span className={css.skeletonDot} />\n <span className={css.skeletonBars}>\n <span className={css.skeletonBar} />\n <span className={clsx(css.skeletonBar, css.skeletonBarWide)} />\n </span>\n </div>\n ))}\n </div>\n )}\n {!pending && results.items.length === 0 && (\n <div className={css.empty}>{t('search.noMatches')}</div>\n )}\n {results.hasMore && (\n <div className={css.searchStatus}>\n {t('search.hasMore', { n: resultLimit })}\n </div>\n )}\n </div>\n <span className={css.fade} />\n </div>\n )\n}\n\n/**\n * Render the browsing region.\n * @param props - composed slot props (shell owner share + store + injected actions).\n * @returns the region element tree.\n */\nexport function WorkspaceBrowser({\n wide,\n usePanelInfo,\n expandSidebar,\n useSessions,\n useSessionStatus,\n useWorkspaces,\n useStore,\n actions,\n startSession,\n open,\n requestSessionRename,\n notifyArchivedNotOpenable,\n renameWorkspace,\n deleteWorkspace,\n insertWorkspaceBefore,\n unarchiveSession,\n createWorkspace,\n searchSessions,\n searchResultLimit,\n useDirectoryFlow,\n useHostInfo,\n useShortcuts,\n useWorkspaceShortcuts,\n useBadgeSettings,\n requestSearch,\n requestAddWorkspace,\n closeAddWorkspace,\n setDirectoryBusy,\n dismissForkError,\n renderSlot,\n t,\n}: WorkspaceBrowserProps) {\n const home = useHostInfo(info => info.home)\n const shortcuts = useShortcuts(rows => rows)\n const searchShortcut = shortcuts.find(row => row.id === 'session.search')\n const addShortcut = shortcuts.find(row => row.id === 'workspace.add')\n const shortcutState = useWorkspaceShortcuts(state => state)\n // Ordering remains live while the rail or search replaces the list body.\n const list = useSessions(state => state)\n const storedWorkspaces = useWorkspaces(state => state.items)\n // The resolved name, not `t`, is the memo dependency: the bound seat keeps\n // its identity across a language switch.\n const defaultWorkspaceName = t('workspace.defaultName')\n const workspaces = useMemo(\n () => storedWorkspaces.map(workspace => ({\n ...workspace,\n title: workspaceDisplayTitle(workspace.title, defaultWorkspaceName),\n })),\n [storedWorkspaces, defaultWorkspaceName],\n )\n const workspacePhase = useWorkspaces(state => state.phase)\n const workspaceStreamState = useWorkspaces(state => state.state)\n const archivedSessionIds = useWorkspaces(state => state.archivedSessionIds)\n const pinnedSessionIds = useWorkspaces(state => state.pinnedSessionIds)\n // Live occupancy of this surface's directory-flow hole (the same source the\n // flow reads): a composition without a picking affordance can add nothing.\n const directoryFlowAvailable = useDirectoryFlow(occupied => occupied)\n const groupBy = useStore(s => s.groupBy)\n const orderBy = useStore(s => s.orderBy)\n // Persisted view blobs written before the archived filter existed rehydrate\n // without the field; they read as the default hide-archived view.\n const archivedFilter = useStore(s => s.archivedFilter ?? 'default')\n const groupExpansion = useStore(s => s.groupExpansion)\n const sessionOrderByAccount = useStore(s => s.sessionOrderByAccount)\n // Archived sessions are not openable: the row stays visible under the\n // filter but a click explains instead of navigating.\n const guardedOpen = (sessionId: SessionId): void => {\n if (archivedSessionIds.includes(sessionId)) {\n notifyArchivedNotOpenable()\n return\n }\n open(sessionId)\n }\n const leaveArchivedOnly = (): void => { actions.setArchivedFilter('default') }\n const workspaceReady = workspacePhase === 'ready' && workspaceStreamState !== 'loading'\n const mainSessionId = Object.values(list.byId)\n .find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const currentBlank = mainSessionId !== undefined && list.byId[mainSessionId]?.blank === true\n ? mainSessionId\n : undefined\n const ungroupedMemberIds = useMemo(() => {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return list.ids.filter(id => list.byId[id] !== undefined && !accounted.has(id))\n }, [list, workspaces])\n const orderState = useMemo(\n () => ({ pinnedSessionIds, archivedSessionIds }),\n [archivedSessionIds, pinnedSessionIds],\n )\n const rowState = useMemo<SessionRowState>(\n () => ({ ...orderState, archivedFilter }),\n [orderState, archivedFilter],\n )\n const flatMemberIds = useMemo(() => sessionMemberIds(list), [list])\n const orderedWorkspaces = useMemo(() => workspaces.map((workspace) => {\n const memberIds = workspace.sessionIds\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(memberIds, list.byId)\n : reconcileManualOrder(memberIds, sessionOrderByAccount[workspace.workspaceId], list.byId, orderState)\n return {\n ...workspace,\n sessionIds: pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && memberIds.includes(currentBlank) ? currentBlank : undefined,\n ),\n }\n }), [currentBlank, list.byId, orderBy, orderState, sessionOrderByAccount, workspaces])\n const orderedUngroupedSessionIds = useMemo(() => {\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(ungroupedMemberIds, list.byId)\n : reconcileManualOrder(ungroupedMemberIds, sessionOrderByAccount[UNGROUPED_KEY], list.byId, orderState)\n return pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && ungroupedMemberIds.includes(currentBlank) ? currentBlank : undefined,\n )\n }, [currentBlank, list.byId, orderBy, orderState, sessionOrderByAccount, ungroupedMemberIds])\n const orderedFlatSessionIds = useMemo(() => {\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(flatMemberIds, list.byId)\n : reconcileManualOrder(flatMemberIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY], list.byId, orderState)\n return pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && flatMemberIds.includes(currentBlank) ? currentBlank : undefined,\n )\n }, [currentBlank, flatMemberIds, list.byId, orderBy, orderState, sessionOrderByAccount])\n const activeSessionOrders = useMemo<Readonly<Record<string, readonly SessionId[]>>>(() => Object.fromEntries([\n ...orderedWorkspaces.map(workspace => [workspace.workspaceId, workspace.sessionIds] as const),\n [UNGROUPED_KEY, orderedUngroupedSessionIds] as const,\n [FLAT_SESSION_ORDER_KEY, orderedFlatSessionIds] as const,\n ]), [orderedFlatSessionIds, orderedUngroupedSessionIds, orderedWorkspaces])\n useEffect(() => {\n if (workspacePhase !== 'ready') return\n actions.retainAccountKeys([\n UNGROUPED_KEY,\n FLAT_SESSION_ORDER_KEY,\n ...workspaces.map(workspace => workspace.workspaceId),\n ])\n }, [actions.retainAccountKeys, workspacePhase, workspaces])\n useEffect(() => {\n if (list.phase !== 'ready' || workspaceReady || orderBy !== 'manual' || currentBlank === undefined) return\n // A first prompt can end blank pinning before the Workspace baseline arrives.\n // Preserve saved members until that baseline can establish departures.\n const changed: Record<string, readonly string[]> = {}\n for (const [key, ids] of Object.entries(activeSessionOrders)) {\n if (key !== FLAT_SESSION_ORDER_KEY && workspacePhase !== 'ready') continue\n const saved = sessionOrderByAccount[key] ?? []\n if (ids[0] !== currentBlank || saved[0] === currentBlank) continue\n changed[key] = [currentBlank, ...saved.filter(id => id !== currentBlank)]\n }\n if (Object.keys(changed).length > 0) actions.syncSessionOrders(changed)\n }, [\n actions.syncSessionOrders,\n activeSessionOrders,\n currentBlank,\n list.phase,\n orderBy,\n sessionOrderByAccount,\n workspacePhase,\n workspaceReady,\n ])\n useEffect(() => {\n if (list.phase !== 'ready' || !workspaceReady || orderBy !== 'manual' || currentBlank === undefined) return\n const moved = Object.entries(activeSessionOrders).some(([key, ids]) =>\n ids[0] === currentBlank && sessionOrderByAccount[key]?.[0] !== currentBlank)\n if (moved) actions.syncSessionOrders(activeSessionOrders)\n }, [\n actions.syncSessionOrders,\n activeSessionOrders,\n currentBlank,\n list.phase,\n orderBy,\n sessionOrderByAccount,\n workspaceReady,\n ])\n const saveSessionOrder = (accountKey: string, order: readonly string[]): void => {\n actions.setSessionOrder(accountKey, order, activeSessionOrders)\n }\n // The query outlives the tree and the input (both wide-only) so collapsing\n // does not silently drop an in-progress filter.\n const [query, setQuery] = useState('')\n const [searchExpanded, setSearchExpanded] = useState(false)\n const [revealSessionId, setRevealSessionId] = useState<SessionId | undefined>(undefined)\n const normalizedQuery = sanitizeSearchQuery(query).trim()\n const [remoteSearch, setRemoteSearch] = useState<RemoteSearchState>({\n query: '',\n status: 'idle',\n items: [],\n hasMore: false,\n })\n const searchRoot = useRef<HTMLDivElement | null>(null)\n const searchInput = useRef<HTMLInputElement | null>(null)\n // Section-header + opens the picker menu (same popover in wide and rail\n // states; the menu anchors on this button).\n const wsPickerOpen = shortcutState.addRequested\n const wsPlusRef = useRef<HTMLButtonElement>(null)\n const composingRef = useRef(false)\n\n const openSearchResult = (sessionId: SessionId): void => {\n if (archivedSessionIds.includes(sessionId)) {\n notifyArchivedNotOpenable()\n return\n }\n setRevealSessionId(sessionId)\n setQuery('')\n setSearchExpanded(false)\n open(sessionId)\n }\n const acknowledgeSessionReveal = (sessionId: SessionId): void => {\n setRevealSessionId(current => current === sessionId ? undefined : current)\n }\n useEffect(() => {\n if (normalizedQuery !== '') setRevealSessionId(undefined)\n }, [normalizedQuery])\n\n // Rail search = expand + land in the search box: the flag arms before the\n // expand request; once the shell flips wide the input mounts and takes focus.\n const [searchOnExpand, setSearchOnExpand] = useState(false)\n useEffect(() => {\n if (wide && searchOnExpand) {\n const timer = window.setTimeout(() => {\n searchInput.current?.focus({ preventScroll: true })\n setSearchOnExpand(false)\n }, EXPAND_SLIDE_MS)\n return () => { window.clearTimeout(timer) }\n }\n }, [wide, searchOnExpand])\n useEffect(() => {\n if (shortcutState.searchRequest === 0) return\n closeAddWorkspace()\n setSearchExpanded(true)\n if (!wide) {\n setSearchOnExpand(true)\n expandSidebar()\n } else searchInput.current?.focus({ preventScroll: true })\n }, [shortcutState.searchRequest])\n\n useEffect(() => {\n if (!wide || !searchExpanded || searchOnExpand) return\n searchInput.current?.focus({ preventScroll: true })\n }, [wide, searchExpanded, searchOnExpand])\n\n // Outside-click dismissal stays off while the rail gesture is in flight\n // (searchOnExpand): the rail click flips the shell wide and mounts this\n // listener during its own dispatch, then keeps bubbling to document with\n // the now-unmounted rail button as its target — outside searchRoot, so the\n // listener would dismiss the search that click just opened.\n useEffect(() => {\n if (!wide || !searchExpanded || searchOnExpand) return\n const onClick = (event: MouseEvent): void => {\n if (!(event.target instanceof Node) || searchRoot.current?.contains(event.target) === true) return\n searchInput.current?.blur()\n if (normalizedQuery !== '') return\n setSearchExpanded(false)\n }\n document.addEventListener('click', onClick)\n return () => { document.removeEventListener('click', onClick) }\n }, [normalizedQuery, wide, searchExpanded, searchOnExpand])\n\n useEffect(() => {\n if (normalizedQuery === '') {\n setRemoteSearch({ query: '', status: 'idle', items: [], hasMore: false })\n return\n }\n const controller = new AbortController()\n setRemoteSearch({\n query: normalizedQuery,\n status: 'loading',\n items: [],\n hasMore: false,\n })\n const timer = window.setTimeout(() => {\n searchSessions(normalizedQuery, controller.signal).then((result) => {\n if (controller.signal.aborted) return\n setRemoteSearch({\n query: normalizedQuery,\n status: 'ready',\n items: result.items,\n hasMore: result.hasMore,\n })\n }).catch(() => {\n if (controller.signal.aborted) return\n setRemoteSearch({\n query: normalizedQuery,\n status: 'error',\n items: [],\n hasMore: false,\n })\n })\n }, SEARCH_DEBOUNCE_MS)\n return () => {\n window.clearTimeout(timer)\n controller.abort()\n }\n }, [normalizedQuery, searchSessions])\n\n // Rename dialog (browser-owned so it outlives row unmounts during collapse).\n // The stored title decides whether confirming is a real rename; the draft is\n // seeded with the label on screen. They differ for a Workspace still\n // carrying its automatic title, so confirming the prefill pins that name.\n const [renameTarget, setRenameTarget] = useState<{ workspaceId: WorkspaceId; storedTitle: string } | null>(null)\n const [renameDraft, setRenameDraft] = useState('')\n const [renaming, setRenaming] = useState(false)\n const [renameError, setRenameError] = useState<string | null>(null)\n const renameTrimmed = renameDraft.trim()\n // Self is excluded by identity, not by title: the draft is seeded with the\n // localized label, which for an automatically titled Workspace equals its\n // own displayed title without being a conflict with itself.\n const renameDuplicate = renameTarget !== null && renameTrimmed !== ''\n && workspaces.some(w => w.workspaceId !== renameTarget.workspaceId && w.title === renameTrimmed)\n const renameBlocked = renaming || renameTrimmed === ''\n || renameTarget === null || renameTrimmed === renameTarget.storedTitle || renameDuplicate\n const closeRename = () => {\n if (renaming) return\n setRenameTarget(null)\n setRenameError(null)\n }\n const confirmRename = () => {\n if (renameBlocked) return\n setRenaming(true)\n setRenameError(null)\n renameWorkspace(renameTarget.workspaceId, renameTrimmed).then(() => {\n setRenaming(false)\n setRenameTarget(null)\n }).catch((reason: unknown) => {\n setRenaming(false)\n setRenameError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n\n // The search results' restore button; the row actions own the rest of the\n // Session verbs as slot entries.\n const onSessionUnarchive = (sessionId: SessionNode['id']) => {\n unarchiveSession(sessionId).catch((reason: unknown) => {\n console.warn('session unarchive rejected:', reason)\n })\n }\n\n // Delete dialog is separate from the row so a successful removal can\n // unmount that row without tearing down the in-flight confirmation state.\n const [deleteTarget, setDeleteTarget] = useState<{ workspaceId: WorkspaceId; title: string } | null>(null)\n const [deleting, setDeleting] = useState(false)\n const [deleteCommittedId, setDeleteCommittedId] = useState<WorkspaceId | null>(null)\n const [deleteError, setDeleteError] = useState<string | null>(null)\n useEffect(() => {\n if (deleteCommittedId === null\n || workspaces.some(workspace => workspace.workspaceId === deleteCommittedId)) return\n setDeleting(false)\n setDeleteCommittedId(null)\n setDeleteTarget(null)\n }, [deleteCommittedId, workspaces])\n const closeDelete = () => {\n if (deleting) return\n setDeleteTarget(null)\n setDeleteError(null)\n }\n const confirmDelete = () => {\n /* v8 ignore next -- the Modal is absent without a target and its button is disabled while deleting. */\n if (deleting || deleteTarget === null) return\n setDeleting(true)\n setDeleteCommittedId(null)\n setDeleteError(null)\n deleteWorkspace(deleteTarget.workspaceId).then(() => {\n // Keep the confirmation pending until this component has rendered the\n // committed list projection without the deleted id. Closing earlier\n // exposes one stale React frame to the next Create Workspace gesture.\n setDeleteCommittedId(deleteTarget.workspaceId)\n }).catch((reason: unknown) => {\n setDeleting(false)\n setDeleteError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n\n return (\n <div className={clsx(css.root, !wide && css.rail)}>\n <div className={css.sectionHeader}>\n {wide && (\n <span className={clsx(css.sectionLabel, css.wide, searchExpanded && css.sectionLabelHidden)}>\n {groupBy === 'flat' ? t('section.sessions') : t('section.workspaces')}\n </span>\n )}\n {wide && (\n <div className={clsx(css.searchSlot, searchExpanded && css.searchSlotExpanded)}>\n <div\n ref={searchRoot}\n className={clsx(css.search, searchExpanded && css.searchExpanded)}\n onClick={() => {\n closeAddWorkspace()\n setSearchExpanded(true)\n searchInput.current?.focus()\n }}\n >\n <Tooltip label={t('search')} shortcutKeys={searchShortcut?.keys} side=\"bottom\" delayMs={500} disabled={searchExpanded}>\n <button\n type=\"button\"\n className={css.searchButton}\n aria-label={t('search.sessions.aria')}\n aria-keyshortcuts={searchShortcut?.aria}\n aria-expanded={searchExpanded}\n onClick={() => {\n requestSearch()\n }}\n >\n <IconSearchOutlineRegular size={searchExpanded ? 11 : 14} />\n </button>\n </Tooltip>\n <input\n ref={searchInput}\n className={css.searchInput}\n type=\"text\"\n placeholder={t('search.placeholder')}\n maxLength={SEARCH_QUERY_MAX_CODE_UNITS}\n value={query}\n tabIndex={searchExpanded ? 0 : -1}\n onChange={(e) => { setQuery(sanitizeSearchQuery(e.target.value)) }}\n onKeyDown={(e) => {\n if (e.key !== 'Escape') return\n setQuery('')\n setSearchExpanded(false)\n }}\n />\n {searchExpanded && (\n <button\n type=\"button\"\n className={css.clearButton}\n aria-label={t('search.clear')}\n onClick={(e) => {\n e.stopPropagation()\n setQuery('')\n setSearchExpanded(false)\n }}\n >\n <IconCloseFillRegular />\n </button>\n )}\n </div>\n </div>\n )}\n <div className={clsx(css.headerActions, wide && searchExpanded && css.headerActionsHidden)}>\n {wide && (\n <ViewOptionsMenu\n groupBy={groupBy}\n orderBy={orderBy}\n archivedFilter={archivedFilter}\n onGroupPick={actions.setGroupBy}\n onOrderPick={(mode) => { actions.setOrderBy(mode, activeSessionOrders) }}\n onArchivedFilterPick={actions.setArchivedFilter}\n t={t}\n />\n )}\n {/* Adding is the button's one action, so a composition with no\n picking affordance has nothing to offer here: the region hides the\n button rather than leaving a dead one in the header. */}\n {directoryFlowAvailable && (\n <Tooltip label={t('workspace.add')} shortcutKeys={addShortcut?.keys} side=\"bottom\" delayMs={500}>\n <button\n ref={wsPlusRef}\n type=\"button\"\n className={css.iconButton}\n aria-label={t('workspace.add')}\n aria-keyshortcuts={addShortcut?.aria}\n onClick={() => {\n requestAddWorkspace()\n }}\n >\n <IconProjectAddOutlineRegular size={wide ? 16 : 18} />\n </button>\n </Tooltip>\n )}\n </div>\n {/* Add flow + its error dialog (same package — direct composition). */}\n <WorkspacePickFlow\n t={t}\n open={wsPickerOpen}\n anchorRef={wsPlusRef}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('sidebar.workspaces.directoryFlow', owner)}\n addOnly\n onBusyChange={setDirectoryBusy}\n side=\"right\"\n onPick={(workspaceId) => {\n closeAddWorkspace()\n startSession(workspaceId)\n }}\n onClose={() => { closeAddWorkspace() }}\n />\n </div>\n\n {/* The collapsed rail keeps search as its own 36px control. */}\n {!wide && <div className={css.search}>\n <Tooltip label={t('search')} shortcutKeys={searchShortcut?.keys}>\n <button\n type=\"button\"\n className={css.searchButton}\n aria-label={t('search.sessions.aria')}\n aria-keyshortcuts={searchShortcut?.aria}\n onClick={() => {\n requestSearch()\n }}\n >\n <IconSearchOutlineRegular size={18} />\n </button>\n </Tooltip>\n </div>}\n\n {/* Always-mounted seat keeps the region's flex slot while the list\n itself is wide-only. */}\n <div className={css.listArea}>\n {wide && (normalizedQuery !== ''\n ? (\n <SearchResults\n usePanelInfo={usePanelInfo}\n useSessions={useSessions}\n useSessionStatus={useSessionStatus}\n open={openSearchResult}\n onUnarchive={onSessionUnarchive}\n workspaces={workspaces}\n archivedSessionIds={archivedSessionIds}\n archivedFilter={archivedFilter}\n query={normalizedQuery}\n remote={remoteSearch}\n resultLimit={searchResultLimit}\n t={t}\n />\n )\n : groupBy === 'flat'\n ? (\n <FlatList\n usePanelInfo={usePanelInfo}\n list={list}\n sessionIds={orderedFlatSessionIds}\n rowState={rowState}\n onLeaveArchivedOnly={leaveArchivedOnly}\n workspaceReady={workspaceReady}\n animationResetKey={`${groupBy}/${orderBy}/${archivedFilter}`}\n useSessionStatus={useSessionStatus}\n open={guardedOpen}\n onSessionRenameRequest={requestSessionRename}\n renderSlot={renderSlot}\n setSessionOrder={saveSessionOrder}\n revealSessionId={revealSessionId}\n onSessionRevealed={acknowledgeSessionReveal}\n t={t}\n />\n )\n : (\n <SessionTree\n usePanelInfo={usePanelInfo}\n useBadgeSettings={useBadgeSettings}\n list={list}\n shortcuts={shortcuts}\n useSessionStatus={useSessionStatus}\n onSessionRenameRequest={requestSessionRename}\n renderSlot={renderSlot}\n workspaces={orderedWorkspaces}\n ungroupedSessionIds={orderedUngroupedSessionIds}\n workspaceReady={workspaceReady}\n nestWorkspaces={groupBy === 'workspace-tree'}\n animationResetKey={`${groupBy}/${orderBy}/${archivedFilter}`}\n groupExpansion={groupExpansion}\n setGroupExpanded={actions.setGroupExpanded}\n setSessionOrder={saveSessionOrder}\n rowState={rowState}\n onLeaveArchivedOnly={leaveArchivedOnly}\n startSession={startSession}\n open={guardedOpen}\n insertWorkspaceBefore={insertWorkspaceBefore}\n revealSessionId={revealSessionId}\n onSessionRevealed={acknowledgeSessionReveal}\n home={home}\n t={t}\n onRenameRequest={(workspaceId, displayTitle) => {\n setRenameTarget({\n workspaceId,\n storedTitle: storedWorkspaces.find(w => w.workspaceId === workspaceId)?.title ?? displayTitle,\n })\n setRenameDraft(displayTitle)\n setRenameError(null)\n }}\n onDeleteRequest={(workspaceId, title) => {\n setDeleteTarget({ workspaceId, title })\n setDeleteError(null)\n }}\n />\n ))}\n </div>\n\n <Modal\n open={renameTarget !== null}\n onClose={closeRename}\n closeLabel={t('close')}\n title={t('rename.workspace.title')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={renaming} onClick={closeRename}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={renameBlocked} onClick={confirmRename}>{t('rename')}</Button>\n </>\n )}\n >\n <input\n className={css.renameInput}\n value={renameDraft}\n aria-label={t('field.workspaceName')}\n data-modal-autofocus\n disabled={renaming}\n onFocus={(e) => { e.target.select() }}\n onChange={(e) => { setRenameDraft(e.target.value); setRenameError(null) }}\n onCompositionStart={() => { composingRef.current = true }}\n onCompositionEnd={() => { composingRef.current = false }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !composingRef.current) {\n e.preventDefault()\n confirmRename()\n }\n }}\n />\n {renameDuplicate && (\n <div className={css.renameError} role=\"alert\">{t('conflict.named', { name: renameTrimmed })}</div>\n )}\n {renameError !== null && <div className={css.renameError} role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={deleteTarget !== null}\n onClose={closeDelete}\n closeLabel={t('close')}\n title={t('delete.workspace')}\n {...deleteTarget === null\n ? {}\n : { description: t('delete.desc', { name: deleteTarget.title }) }}\n footer={(\n <>\n <Button variant=\"outline\" disabled={deleting} onClick={closeDelete}>{t('cancel')}</Button>\n <Button\n variant=\"outline\"\n className={css.deleteAction}\n disabled={deleting}\n onClick={confirmDelete}\n >\n {t('delete.workspace')}\n </Button>\n </>\n )}\n >\n {deleting && <div className={css.deleteStatus} role=\"status\">{t('delete.pending')}</div>}\n {deleteError !== null && <div className={css.renameError} role=\"alert\">{deleteError}</div>}\n </Modal>\n {shortcutState.forkError !== null && <Toast key={shortcutState.forkError.seq}\n text={t(shortcutState.forkError.reason === 'unavailable' ? 'shortcut.noCompletedTurn' : 'shortcut.forkFailed')}\n onDone={dismissForkError} />}\n </div>\n )\n}\n","/**\n * The archive action: a `sidebar.workspaces.session.menu.item` row and a\n * `sidebar.workspaces.session.row.action` button over one injected behavior,\n * plus the `shell.overlay` dialog that confirms stopping a Session's running\n * work before archiving it. The same entries restore an archived row; the\n * notice a successful archive raises and the diagnostics for Host rejections\n * live in the injected callbacks, not here.\n */\nimport { useState } from 'react'\nimport type { SessionActivity } from '@deepseek-ai/dsh-api-workspace-controller/client'\n// Type-only: the family keys each provider merges; a key this program did not compile takes the generic line.\nimport type {} from '@deepseek-ai/dsh-agent/types'\nimport type {} from '@deepseek-ai/dsh-jobs/view'\nimport type {} from '@deepseek-ai/dsh-schedule/client'\nimport type {} from '@deepseek-ai/dsh-subagent/client'\nimport {\n Button, IconArchiveOutlineRegular, IconUnarchiveOutlineRegular, MenuItemButton, Modal, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n ArchiveSessionInjected, SessionArchiveConfirmInjected, SessionArchiveConfirmProps, SessionArchiveConfirmRequest,\n SessionMenuItemProps, SessionRowActionProps,\n} from '../contract/slots.ts'\nimport css from '../rows/Rows.module.css'\nimport browserCss from '../rows/WorkspaceBrowser.module.css'\n\n/**\n * Menu row (order 400): archive, or restore an archived row.\n * @param props - owner share, the archive share, and the menu open state.\n * @returns the row.\n */\nexport function ArchiveSessionMenuItem({\n sessionId, useArchived, useMenuOpenState, useShortcuts, archiveSession, unarchiveSession, t,\n}: SessionMenuItemProps<ArchiveSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.archive'))\n const archived = useArchived(set => set.has(sessionId))\n return (\n <MenuItemButton\n shortcut={archived ? undefined : shortcut}\n icon={archived ? <IconUnarchiveOutlineRegular size={14} /> : <IconArchiveOutlineRegular size={14} />}\n onSelect={() => {\n setMenuOpen(false)\n ;(archived ? unarchiveSession : archiveSession)(sessionId)\n }}\n >\n {t(archived ? 'menu.unarchiveSession' : 'menu.archiveSession')}\n </MenuItemButton>\n )\n}\n\n/**\n * Hover button (order 100): archive, or restore an archived row.\n * @param props - owner share and the archive share.\n * @returns the button.\n */\nexport function ArchiveSessionRowButton({\n sessionId, useArchived, archiveSession, unarchiveSession, t,\n}: SessionRowActionProps<ArchiveSessionInjected>) {\n const archived = useArchived(set => set.has(sessionId))\n return (\n <Tooltip label={t(archived ? 'actions.unarchive' : 'actions.archive')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t(archived ? 'menu.unarchiveSession' : 'menu.archiveSession')}\n onClick={() => { (archived ? unarchiveSession : archiveSession)(sessionId) }}\n >\n {archived ? <IconUnarchiveOutlineRegular size={14} /> : <IconArchiveOutlineRegular size={14} />}\n </button>\n </Tooltip>\n )\n}\n\n/**\n * The `shell.overlay` entry: nothing while no confirmation is pending,\n * otherwise one dialog per request (keyed by the Session). Confirming asks\n * the Host to stop the listed work and archive; cancelling leaves the\n * Session running and visible.\n * @param props - the request hook, its settlement, the stop-and-archive hop, and the locale seat.\n * @returns the open dialog, or null.\n */\nexport function SessionArchiveConfirmDialog({\n useArchiveRequest, settleSessionArchive, stopAndArchiveSession, t,\n}: SessionArchiveConfirmProps) {\n const request = useArchiveRequest(pending => pending)\n if (request === null) return null\n return (\n <ArchiveConfirmForm\n key={request.sessionId}\n request={request}\n stopAndArchiveSession={stopAndArchiveSession}\n onSettle={settleSessionArchive}\n t={t}\n />\n )\n}\n\n/** One request's dialog: in-flight and error state die with it. */\nfunction ArchiveConfirmForm({ request, stopAndArchiveSession, onSettle, t }: {\n request: SessionArchiveConfirmRequest\n stopAndArchiveSession: SessionArchiveConfirmInjected['stopAndArchiveSession']\n onSettle: () => void\n t: SessionArchiveConfirmProps['t']\n}) {\n const [archiving, setArchiving] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const close = () => {\n if (archiving) return\n onSettle()\n }\n const confirm = () => {\n setArchiving(true)\n setError(null)\n stopAndArchiveSession(request.sessionId).then(() => {\n setArchiving(false)\n onSettle()\n }).catch((reason: unknown) => {\n setArchiving(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n return (\n <Modal\n open\n onClose={close}\n closeLabel={t('close')}\n title={t('archive.confirm.title')}\n description={t('archive.confirm.desc', { title: request.displayTitle })}\n footer={(\n <>\n <Button variant=\"outline\" disabled={archiving} onClick={close}>{t('cancel')}</Button>\n <Button\n variant=\"outline\"\n className={browserCss.deleteAction}\n disabled={archiving}\n onClick={confirm}\n >\n {t('archive.confirm.action')}\n </Button>\n </>\n )}\n >\n <ul className={browserCss.archiveActivity} aria-label={t('archive.confirm.activity')}>\n {request.activity.map((entry, index) => (\n <li key={`${entry.kind}-${String(index)}`}>{activityLine(entry, t)}</li>\n ))}\n </ul>\n {archiving && <div className={browserCss.deleteStatus} role=\"status\">{t('archive.confirm.pending')}</div>}\n {error !== null && <div className={browserCss.renameError} role=\"alert\">{error}</div>}\n </Modal>\n )\n}\n\n/**\n * One family's line: its count and the items' labels (ids when a family\n * carries no label). A family this dictionary does not know — a provider\n * merged into the kind map — falls through to the generic line.\n */\nfunction activityLine(entry: SessionActivity, t: SessionArchiveConfirmProps['t']): string {\n const items = entry.items ?? []\n const n = items.length\n const names = items.map(item => item.label ?? item.id).join(t('archive.confirm.listSeparator'))\n const plural = n === 1 ? 'one' : 'other'\n switch (entry.kind) {\n case 'turn': return t('archive.confirm.turn')\n case 'subagent': return t(`archive.confirm.subagents.${plural}`, { n, names })\n case 'job': return t(`archive.confirm.jobs.${plural}`, { n, names })\n case 'schedule': return t(`archive.confirm.schedules.${plural}`, { n, names })\n default: return t(`archive.confirm.other.${plural}`, { kind: entry.kind, n })\n }\n}\n","/** Derived observable sources for the row actions' injected hooks. */\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\n\n/**\n * Project one observable into another, recomputing only when the source\n * snapshot changes identity, so consumers that select from the projection\n * (a Set lookup per row) never rebuild it per read.\n * @param source - the observable to project.\n * @param project - pure projection of one source snapshot.\n * @returns the projected observable, subscribing through the source.\n */\nexport function derive<S, T>(source: HostObservable<S>, project: (snapshot: S) => T): HostObservable<T> {\n let seen: S | undefined\n let value: T | undefined\n return {\n getSnapshot: () => {\n const snapshot = source.getSnapshot()\n if (value === undefined || snapshot !== seen) {\n seen = snapshot\n value = project(snapshot)\n }\n return value\n },\n subscribe: listener => source.subscribe(listener),\n }\n}\n","/** The fork action: one `sidebar.workspaces.session.menu.item` row. */\nimport { IconBranchOutlineRegular, MenuItemButton } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ForkSessionInjected, SessionMenuItemProps } from '../contract/slots.ts'\n\n/**\n * Menu row (order 300): fork at the Session's last completed turn; the child\n * arrives through the Host list beside its source.\n * @param props - owner share, menu open state, and the fork share.\n * @returns the row.\n */\nexport function ForkSessionMenuItem({\n sessionId, useMenuOpenState, useShortcuts, forkSession, t,\n}: SessionMenuItemProps<ForkSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.fork'))\n return (\n <MenuItemButton\n shortcut={shortcut}\n icon={<IconBranchOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n forkSession(sessionId)\n }}\n >\n {t('menu.fork')}\n </MenuItemButton>\n )\n}\n","/**\n * The pin action: a `sidebar.workspaces.session.menu.item` row and a\n * `sidebar.workspaces.session.row.action` button over one injected behavior.\n * Pin and archive are mutually exclusive on the Host, so the action reads both\n * sets and does not offer itself on an archived row; what a pin does beyond\n * the Host call (fronting the Session in its saved orders, the failure\n * notice) lives in the injected callbacks, not here.\n */\nimport {\n IconPinFillRegular, IconPinOutlineRegular, MenuItemButton, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PinSessionInjected, SessionMenuItemProps, SessionRowActionProps } from '../contract/slots.ts'\nimport css from '../rows/Rows.module.css'\n\ntype PinState = Pick<SessionMenuItemProps<PinSessionInjected>, 'sessionId' | 'usePinned' | 'useArchived'>\n\n/** The row's pin and archive membership, one Set lookup each. */\nfunction usePinState({ sessionId, usePinned, useArchived }: PinState) {\n return {\n pinned: usePinned(pinned => pinned.has(sessionId)),\n archived: useArchived(archived => archived.has(sessionId)),\n }\n}\n\n/**\n * Menu row (order 100): pin or unpin by the row's current state; absent on archived rows.\n * @param props - owner share, the pin share, and the menu open state.\n * @returns the row, or null for an archived Session.\n */\nexport function PinSessionMenuItem(props: SessionMenuItemProps<PinSessionInjected>) {\n const { sessionId, useMenuOpenState, pinSession, unpinSession, t } = props\n const [, setMenuOpen] = useMenuOpenState()\n const { pinned, archived } = usePinState(props)\n if (archived) return null\n return (\n <MenuItemButton\n icon={pinned ? <IconPinFillRegular /> : <IconPinOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n ;(pinned ? unpinSession : pinSession)(sessionId)\n }}\n >\n {t(pinned ? 'menu.unpinSession' : 'menu.pinSession')}\n </MenuItemButton>\n )\n}\n\n/**\n * Hover button (order 200, rightmost: it lands where the rest-state pin marker sits); absent on archived rows.\n * @param props - owner share and the pin share.\n * @returns the button, or null for an archived Session.\n */\nexport function PinSessionRowButton(props: SessionRowActionProps<PinSessionInjected>) {\n const { sessionId, pinSession, unpinSession, t } = props\n const { pinned, archived } = usePinState(props)\n if (archived) return null\n return (\n <Tooltip label={t(pinned ? 'actions.unpin' : 'actions.pin')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t(pinned ? 'menu.unpinSession' : 'menu.pinSession')}\n onClick={() => { (pinned ? unpinSession : pinSession)(sessionId) }}\n >\n {pinned ? <IconPinFillRegular size={14} /> : <IconPinOutlineRegular size={14} />}\n </button>\n </Tooltip>\n )\n}\n","/**\n * The rename action: a `sidebar.workspaces.session.menu.item` row that raises\n * the rename request, and the `shell.overlay` dialog entry that answers it.\n * The dialog lives outside the row menu because the row unmounts with the\n * menu; the browser raises the same request from a title double-click.\n */\nimport { useRef, useState } from 'react'\nimport { Button, IconEditOutlineRegular, MenuItemButton, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n RenameSessionInjected, SessionMenuItemProps, SessionRenameDialogInjected, SessionRenameDialogProps, SessionRenameTarget,\n} from '../contract/slots.ts'\nimport css from '../rows/WorkspaceBrowser.module.css'\n\n/**\n * Menu row (order 200): ask for the rename dialog, seeded with the row's current title.\n * @param props - owner share, menu open state, and the rename share.\n * @returns the row.\n */\nexport function RenameSessionMenuItem({\n sessionId, displayTitle, useMenuOpenState, useShortcuts, requestSessionRename, t,\n}: SessionMenuItemProps<RenameSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.rename'))\n return (\n <MenuItemButton\n shortcut={shortcut}\n icon={<IconEditOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n requestSessionRename(sessionId, displayTitle)\n }}\n >\n {t('rename')}\n </MenuItemButton>\n )\n}\n\n/**\n * The `shell.overlay` entry: nothing while no rename is requested, otherwise\n * one dialog per request (keyed by the Session, so a new request starts a\n * fresh draft). Sessions have no client-side name-conflict rule (the host\n * normalizes), and unlike Workspace rename an unchanged title is NOT\n * blocked. An unnamed Session starts with an empty draft and requires a name.\n * @param props - the request hook, its settlement, the rename hop, and the locale seat.\n * @returns the open dialog, or null.\n */\nexport function SessionRenameDialog({ useRenameRequest, settleSessionRename, renameSession, t }: SessionRenameDialogProps) {\n const request = useRenameRequest(pending => pending)\n if (request === null) return null\n return (\n <RenameForm\n key={request.sessionId}\n request={request}\n renameSession={renameSession}\n onSettle={settleSessionRename}\n t={t}\n />\n )\n}\n\n/** One request's dialog: the draft seeds from the request on mount; in-flight and error state die with it. */\nfunction RenameForm({ request, renameSession, onSettle, t }: {\n request: SessionRenameTarget\n renameSession: SessionRenameDialogInjected['renameSession']\n onSettle: () => void\n t: SessionRenameDialogProps['t']\n}) {\n const [draft, setDraft] = useState(request.currentTitle)\n const [renaming, setRenaming] = useState(false)\n const [error, setError] = useState<string | null>(null)\n // IME composition: Enter that commits a composition must not submit.\n const composingRef = useRef(false)\n const trimmed = draft.trim()\n const blocked = renaming || trimmed === ''\n const close = () => {\n if (renaming) return\n onSettle()\n }\n const confirm = () => {\n if (blocked) return\n setRenaming(true)\n setError(null)\n renameSession(request.sessionId, trimmed).then(() => {\n setRenaming(false)\n onSettle()\n }).catch((reason: unknown) => {\n setRenaming(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n return (\n <Modal\n open\n onClose={close}\n closeLabel={t('close')}\n title={t('rename.session.title')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={renaming} onClick={close}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={blocked} onClick={confirm}>{t('rename')}</Button>\n </>\n )}\n >\n <input\n className={css.renameInput}\n value={draft}\n aria-label={t('field.sessionName')}\n data-modal-autofocus\n disabled={renaming}\n onFocus={(e) => { e.target.select() }}\n onChange={(e) => { setDraft(e.target.value); setError(null) }}\n onCompositionStart={() => { composingRef.current = true }}\n onCompositionEnd={() => { composingRef.current = false }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !composingRef.current) {\n e.preventDefault()\n confirm()\n }\n }}\n />\n {error !== null && <div className={css.renameError} role=\"alert\">{error}</div>}\n </Modal>\n )\n}\n","/**\n * The `shell.overlay` entry for Workspace and Session notices.\n * One notice is visible at a time; a parent rerender does not extend its hold.\n */\nimport { IconWarningOutlineRegular, Toast } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { assertNever } from '@deepseek-ai/dsh-util-values'\nimport type { RowToastProps, RowToastState } from '../contract/slots.ts'\n\n/**\n * Hold for the notices that take longer to read than a one-line warning: the\n * actionable archived notice (two buttons to react to) and a refused Session\n * creation, which quotes the Host's reason.\n */\nconst LONG_TOAST_HOLD_MS = 6000\n\n/**\n * Render the current notice: the archived and stopped-and-archived notices\n * with their undo action — plus the show-archived action while archived rows\n * are hidden — on a 6 s hold, a refused Session creation with the Host's\n * reason on the same hold, or a plain warning for a failed pin, an archived\n * row that was clicked, or default Workspace creation.\n * @param props - the notice hook, the shared viewing store, the notice dismissal, the two archived-notice actions, and the locale seat.\n * @returns the notice on display, or null.\n */\nexport function RowActionToast({ useToast, useStore, dismissToast, undoArchive, showArchived, t }: RowToastProps) {\n const toast = useToast(current => current)\n const archivedRowsVisible = useStore(state => (state.archivedFilter ?? 'default') !== 'default')\n if (toast === null) return null\n if (toast.kind === 'archived' || toast.kind === 'stoppedAndArchived') {\n const { sessionId } = toast\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={t(toast.kind === 'archived' ? 'toast.archived' : 'toast.stoppedAndArchived')}\n tone=\"success\"\n holdMs={LONG_TOAST_HOLD_MS}\n actions={[\n { label: t('toast.archivedUndo'), onClick: () => { dismissToast(); undoArchive(sessionId) } },\n ...archivedRowsVisible ? [] : [\n { prefix: t('toast.archivedOr'), label: t('toast.archivedFilter'), onClick: () => { dismissToast(); showArchived() } },\n ],\n ]}\n onDone={dismissToast}\n />\n )\n }\n if (toast.kind === 'createFailed') {\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={t('toast.createFailed', { message: toast.message })}\n icon={<IconWarningOutlineRegular />}\n holdMs={LONG_TOAST_HOLD_MS}\n onDone={dismissToast}\n />\n )\n }\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={plainNoticeText(toast, t)}\n icon={<IconWarningOutlineRegular />}\n onDone={dismissToast}\n />\n )\n}\n\n/** The copy of one plain warning, keyed by the notice kind the union closes over. */\nfunction plainNoticeText(\n toast: Exclude<RowToastState, { kind: 'archived' | 'stoppedAndArchived' | 'createFailed' }>,\n t: RowToastProps['t'],\n): string {\n switch (toast.kind) {\n case 'pinFailed': return t('toast.pinFailed')\n case 'unpinFailed': return t('toast.unpinFailed')\n case 'defaultWorkspaceFailed': return t('defaultWorkspace.failed')\n case 'archivedNotOpenable': return t('toast.archivedNotOpenable')\n /* v8 ignore next 2 -- closed-union backstop; only reached if a notice kind is forged */\n default:\n return assertNever(toast)\n }\n}\n","/**\n * `workspace` namespace dictionaries: the browsing region (section header,\n * search, tree rows, dialogs) and the pick/add flow. Runtime failure\n * messages (wire error strings) pass through untranslated by policy.\n */\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'defaultWorkspace.failed': '无法创建默认工作区,请通过“选择工作区”选择文件夹',\n 'group.ungrouped': '未分组',\n 'session.new': '新会话',\n 'session.untitled': '未命名',\n 'shortcut.noSession': '请先选择一个会话',\n 'shortcut.noPicker': '目录选择器不可用',\n 'shortcut.directoryBusy': '正在选择或添加工作区',\n 'shortcut.noCompletedTurn': '当前会话没有已结束的轮次',\n 'shortcut.forkFailed': '无法分叉会话,请重试',\n 'section.workspaces': '工作区',\n 'section.sessions': '会话',\n 'viewOptions.label': '视图选项',\n 'groupBy.label': '分组方式',\n 'groupBy.workspace': '按工作区',\n 'groupBy.workspaceTree': '按工作区树',\n 'groupBy.flat': '单列表',\n 'orderBy.label': '排序方式',\n 'orderBy.manual': '手动排序',\n 'orderBy.updated': '最近更新',\n 'filterBy.label': '筛选会话',\n 'viewOptions.hideArchived': '隐藏已归档',\n 'viewOptions.showArchived': '全部对话(显示已归档)',\n 'viewOptions.onlyArchived': '仅显示已归档',\n 'sessions.expand': '展开其余 {n} 个会话',\n 'sessions.collapse': '收起',\n 'empty.none': '暂无会话',\n 'empty.noneArchived': '暂无已归档会话',\n 'empty.viewOthers': '查看其他会话',\n 'empty.noMatches': '无匹配结果',\n 'workspace.add': '添加工作区',\n 'search.sessions.aria': '搜索会话',\n 'search.placeholder': '搜索会话名称',\n 'search.clear': '清除搜索',\n 'search.results.aria': '搜索结果',\n 'search.pending': '正在搜索会话历史…',\n 'search.noMatches': '无匹配会话',\n 'search.hasMore': '仅显示前 {n} 条结果,请缩小搜索范围。',\n 'menu.addWorkspace': '添加工作区…',\n 'picker.loading': '正在加载工作区…',\n 'conflict.named': '已存在名为“{name}”的工作区。',\n 'folderError.title': '无法打开文件夹',\n 'folderError.retry': '重新选择',\n 'rename': '重命名',\n 'rename.workspace.title': '重命名工作区',\n 'rename.session.title': '重命名会话',\n 'field.workspaceName': '工作区名称',\n 'field.sessionName': '会话名称',\n 'delete.workspace': '删除工作区',\n 'delete.desc': '将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。',\n 'delete.pending': '正在删除工作区…',\n 'menu.fork': '分叉会话',\n 'menu.archiveSession': '归档会话',\n 'menu.unarchiveSession': '取消归档',\n 'menu.pinSession': '置顶会话',\n 'menu.unpinSession': '取消置顶',\n 'row.archived': '已归档',\n 'row.pinned': '已置顶',\n 'toast.archivedNotOpenable': '已归档对话暂时无法查看,请取消归档后查看',\n 'toast.archived': '会话已归档,可',\n 'toast.stoppedAndArchived': '已停止并归档,可',\n 'archive.confirm.title': '停止并归档此会话?',\n 'archive.confirm.desc': '“{title}”仍有正在进行的工作。归档会先停止这些工作;之后可在侧栏筛选“全部对话(显示已归档)”中恢复会话,被停止的工作不会自动继续。',\n 'archive.confirm.activity': '将被停止的工作',\n 'archive.confirm.turn': '进行中的回合',\n 'archive.confirm.subagents.one': '{n} 个运行中的子智能体:{names}',\n 'archive.confirm.subagents.other': '{n} 个运行中的子智能体:{names}',\n 'archive.confirm.jobs.one': '{n} 个后台任务:{names}',\n 'archive.confirm.jobs.other': '{n} 个后台任务:{names}',\n 'archive.confirm.schedules.one': '{n} 条定时提醒:{names}',\n 'archive.confirm.schedules.other': '{n} 条定时提醒:{names}',\n 'archive.confirm.other.one': '{n} 项其他工作({kind})',\n 'archive.confirm.other.other': '{n} 项其他工作({kind})',\n 'archive.confirm.listSeparator': '、',\n 'archive.confirm.action': '停止并归档',\n 'archive.confirm.pending': '正在停止并归档…',\n 'toast.archivedUndo': '撤销',\n 'toast.archivedOr': '或',\n 'toast.archivedFilter': '筛选已归档会话',\n 'toast.pinFailed': '置顶失败,请稍后重试',\n 'toast.unpinFailed': '取消置顶失败,请稍后重试',\n 'toast.createFailed': '新建会话失败:{message}',\n 'sessions.count.one': '{n} 个会话',\n 'sessions.count.other': '{n} 个会话',\n 'actions.workspace.aria': '工作区“{name}”的操作',\n 'actions.session.aria': '会话“{name}”的操作',\n 'actions.archive': '归档会话',\n 'actions.unarchive': '取消归档',\n 'actions.pin': '置顶会话',\n 'actions.unpin': '取消置顶',\n 'actions.newSession': '新会话',\n 'actions.newSession.aria': '在“{name}”中新建会话',\n 'status.running': '进行中',\n 'status.subagentsRunning.one': '{n} 个子智能体运行中',\n 'status.subagentsRunning.other': '{n} 个子智能体运行中',\n 'status.idle': '空闲',\n 'status.waitingApproval': '等待审批',\n 'status.planReview': '计划待审',\n 'status.waitingAnswer': '等待回答',\n 'status.compact.approval': '待审批',\n 'status.compact.planReview': '计划待审',\n 'status.compact.answer': '待回答',\n 'status.waitingReview': '等待评审',\n 'status.scheduled': '定时任务',\n 'status.completed': '已完成',\n 'hover.created': '创建于 {time}',\n 'hover.copied': '已复制',\n 'date.ymd': '{y}年{m}月{d}日',\n 'time.now': '刚刚',\n 'time.minutes': '{n}分钟',\n 'time.hours': '{n}小时',\n 'time.days': '{n}天',\n 'time.months': '{n}个月',\n 'time.years': '{n}年',\n 'time.ago': '{t}前',\n} satisfies Record<string, string>\n\n/** The workspace namespace key union. */\nexport type WorkspaceKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'defaultWorkspace.failed': 'Unable to create default workspace. Use Choose workspace to select a folder.',\n 'group.ungrouped': 'Ungrouped',\n 'session.new': 'New Session',\n 'session.untitled': 'Untitled',\n 'shortcut.noSession': 'Select a session first',\n 'shortcut.noPicker': 'Directory picker unavailable',\n 'shortcut.directoryBusy': 'Selecting or adding a workspace',\n 'shortcut.noCompletedTurn': 'This session has no completed turn',\n 'shortcut.forkFailed': 'Could not fork the session. Try again.',\n 'section.workspaces': 'Workspaces',\n 'section.sessions': 'Sessions',\n 'viewOptions.label': 'View options',\n 'groupBy.label': 'Group by',\n 'groupBy.workspace': 'WorkSpace',\n 'groupBy.workspaceTree': 'Workspace Tree',\n 'groupBy.flat': 'In one list',\n 'orderBy.label': 'Order by',\n 'orderBy.manual': 'Manual',\n 'orderBy.updated': 'Last updated',\n 'filterBy.label': 'Filter sessions',\n 'viewOptions.hideArchived': 'Hide archived',\n 'viewOptions.showArchived': 'All conversations (show archived)',\n 'viewOptions.onlyArchived': 'Archived only',\n 'sessions.expand': 'Show {n} more sessions',\n 'sessions.collapse': 'Show less',\n 'empty.none': 'No sessions yet',\n 'empty.noneArchived': 'No archived sessions yet',\n 'empty.viewOthers': 'View other sessions',\n 'empty.noMatches': 'No matches',\n 'workspace.add': 'Add workspace',\n 'search.sessions.aria': 'Search sessions',\n 'search.placeholder': 'Search session names',\n 'search.clear': 'Clear search',\n 'search.results.aria': 'Search results',\n 'search.pending': 'Searching session history…',\n 'search.noMatches': 'No matching sessions',\n 'search.hasMore': 'Showing the first {n} results. Narrow your search.',\n 'menu.addWorkspace': 'Add workspace…',\n 'picker.loading': 'Loading workspaces…',\n 'conflict.named': 'A workspace named “{name}” already exists.',\n 'folderError.title': 'Couldn’t open folder',\n 'folderError.retry': 'Choose again',\n 'rename': 'Rename',\n 'rename.workspace.title': 'Rename workspace',\n 'rename.session.title': 'Rename session',\n 'field.workspaceName': 'Workspace name',\n 'field.sessionName': 'Session name',\n 'delete.workspace': 'Delete workspace',\n 'delete.desc': 'This removes “{name}” from the workspace list. The folder and session logs will be kept. Its sessions will appear under Ungrouped.',\n 'delete.pending': 'Deleting workspace…',\n 'menu.fork': 'Fork session',\n 'menu.archiveSession': 'Archive session',\n 'menu.unarchiveSession': 'Unarchive session',\n 'menu.pinSession': 'Pin session',\n 'menu.unpinSession': 'Unpin session',\n 'row.archived': 'Archived',\n 'row.pinned': 'Pinned',\n 'toast.archivedNotOpenable': 'Archived sessions cannot be opened. Unarchive it to view.',\n 'toast.archived': 'Session archived. You can ',\n 'toast.stoppedAndArchived': 'Session stopped and archived. You can ',\n 'archive.confirm.title': 'Stop and archive this session?',\n 'archive.confirm.desc': '“{title}” still has work in progress. Archiving stops it first; you can restore the session later from the “All conversations (show archived)” filter in the sidebar, and the stopped work will not resume on its own.',\n 'archive.confirm.activity': 'Work that will be stopped',\n 'archive.confirm.turn': 'The turn in progress',\n 'archive.confirm.subagents.one': '{n} running subagent: {names}',\n 'archive.confirm.subagents.other': '{n} running subagents: {names}',\n 'archive.confirm.jobs.one': '{n} background job: {names}',\n 'archive.confirm.jobs.other': '{n} background jobs: {names}',\n 'archive.confirm.schedules.one': '{n} scheduled reminder: {names}',\n 'archive.confirm.schedules.other': '{n} scheduled reminders: {names}',\n 'archive.confirm.other.one': '{n} other item of work ({kind})',\n 'archive.confirm.other.other': '{n} other items of work ({kind})',\n 'archive.confirm.listSeparator': ', ',\n 'archive.confirm.action': 'Stop and archive',\n 'archive.confirm.pending': 'Stopping and archiving…',\n 'toast.archivedUndo': 'undo',\n 'toast.archivedOr': ' or ',\n 'toast.archivedFilter': 'filter archived sessions',\n 'toast.pinFailed': 'Pin failed. Try again later.',\n 'toast.unpinFailed': 'Unpin failed. Try again later.',\n 'toast.createFailed': 'New session failed: {message}',\n 'sessions.count.one': '{n} session',\n 'sessions.count.other': '{n} sessions',\n 'actions.workspace.aria': 'Workspace actions for {name}',\n 'actions.session.aria': 'Session actions for {name}',\n 'actions.archive': 'Archive',\n 'actions.unarchive': 'Unarchive',\n 'actions.pin': 'Pin',\n 'actions.unpin': 'Unpin',\n 'actions.newSession': 'New session',\n 'actions.newSession.aria': 'New session in {name}',\n 'status.running': 'Running',\n 'status.subagentsRunning.one': '{n} subagent running',\n 'status.subagentsRunning.other': '{n} subagents running',\n 'status.idle': 'Idle',\n 'status.waitingApproval': 'Waiting for approval',\n 'status.planReview': 'Plan awaiting review',\n 'status.waitingAnswer': 'Waiting for answer',\n 'status.compact.approval': 'Approval',\n 'status.compact.planReview': 'Plan review',\n 'status.compact.answer': 'Answer',\n 'status.waitingReview': 'Waiting for review',\n 'status.scheduled': 'Scheduled',\n 'status.completed': 'Completed',\n 'hover.created': 'Created {time}',\n 'hover.copied': 'Copied',\n 'date.ymd': '{y}-{m}-{d}',\n 'time.now': 'now',\n 'time.minutes': '{n}min',\n 'time.hours': '{n}h',\n 'time.days': '{n}d',\n 'time.months': '{n}mo',\n 'time.years': '{n}y',\n 'time.ago': '{t} ago',\n} satisfies Record<WorkspaceKey, string>\n","/**\n * Workspace plugin, browser half. Two registrations: WorkspaceBrowser fills\n * the sidebar shell's `sidebar.workspaces` hole (the whole browsing region),\n * and WorkspacePicker fills the conversation hero's picker hole\n * (`conversation.hero.workspace` — both hero forms). Both read real Host\n * Workspaces through the global useWorkspaces hook, and each declares its\n * own `single` directory-flow child hole for the composed picker package's\n * client half. WorkspaceBrowser additionally declares the two Session row\n * action lists, and this apply registers the shipped actions — pin, rename,\n * fork, archive — into them the way any client plugin would, each with its\n * own behavior, plus the rename dialog and the row-action notice into\n * `shell.overlay` (see the contract module doc). It also declares two\n * Session-row seats: the leading decoration a row renders only while its own\n * primary state is idle, and the section the row's hover card renders between\n * its relative time and its trailing status line. Export discipline:\n * packages/client/AGENTS.md.\n */\nimport type {} from '@deepseek-ai/dsh-client-product-analytics/client'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client'\nimport type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {\n IWorkspaces, SessionActivity, WorkspaceArchiveError, WorkspaceSnapshot,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { HostObservable, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\n// Type-only: pulls the Controller service merges.\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-api-workspace-controller/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the SlotRegistry service merge (ctx.slots).\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\n// Type-only: pulls the Session root standard-hook merge.\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport {\n type ArchiveSessionInjected, type ForkSessionInjected, menuOpenStateFactory, type PinSessionInjected,\n type SessionArchiveConfirmInjected, type SessionArchiveConfirmRequest,\n type RenameSessionInjected, type RowToast, type RowToastInjected, type RowToastState, type SessionRenameDialogInjected,\n type WorkspaceBrowserInjected, type WorkspacePickerInjected,\n} from './contract/slots.ts'\nimport { createWorkspaceShortcutControls, installWorkspaceShortcuts } from './shortcuts.ts'\nimport { createBadgeSettingsSource, ENTRY_ID, type ResolvedBadgeSettings, type SettingsScopeLike } from './badge-settings.ts'\nimport { UiWorkspaceService } from './navigation.ts'\nimport { createWorkspaceViewStore } from './stores.ts'\nimport { WorkspaceBrowser } from './rows/WorkspaceBrowser.tsx'\nimport { ArchiveSessionMenuItem, ArchiveSessionRowButton, SessionArchiveConfirmDialog } from './session-actions/ArchiveSession.tsx'\nimport { derive } from './session-actions/derived.ts'\nimport { ForkSessionMenuItem } from './session-actions/ForkSession.tsx'\nimport { PinSessionMenuItem, PinSessionRowButton } from './session-actions/PinSession.tsx'\nimport { RenameSessionMenuItem, SessionRenameDialog } from './session-actions/RenameSession.tsx'\nimport { RowActionToast } from './session-actions/RowActionToast.tsx'\nimport { WorkspacePicker } from './WorkspacePicker.tsx'\nimport { en, zh, type WorkspaceKey } from './locales.ts'\n\nexport type { UiWorkspace } from './navigation.ts'\nexport type {\n DirectoryFlowOwnerProps, DirectoryFlowSlotName, DirectoryPickingHooks, DirectoryPickingInjected,\n MenuOpenState, RowToast, SessionRenameTarget, SessionRowOwnerProps, UseMenuOpenState, WorkspaceBrowserInjected,\n SessionRowScheduleOwnerProps,\n WorkspaceBrowserProps,\n WorkspacePickerInjected, WorkspacePickerProps,\n} from './contract/slots.ts'\nexport type { WorkspaceKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface GlobalStandardProps {\n /** Selector hook over the pure Workspace Controller snapshot. */\n useWorkspaces: SnapshotSelectorHook<WorkspaceSnapshot>\n /** Selector hook over this plugin's own settings face (badge preferences). */\n useBadgeSettings: SnapshotSelectorHook<ResolvedBadgeSettings>\n }\n\n interface LocaleNamespaceMap {\n /** The workspace browsing region and pick/create flow copy. */\n workspace: WorkspaceKey\n }\n}\n\ndeclare module '@deepseek-ai/dsh-api-session-controller/client' {\n interface SessionReferenceSourceMap {\n workspaceOperation: unknown\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nconst NS = 'workspace'\n\n/**\n * `configForms` 服务的最小结构面(宿主 `@deepseek-ai/dsh-client-ui-settings` 的\n * 一部分)。此处按结构声明而非导入该包:本插件不需要设置页的其余能力,窄化的\n * 形状让服务缺席时降级为一个 `undefined` 检查而非编译期依赖。\n */\ninterface ConfigFormsLike {\n get(entryId: string): SettingsScopeLike\n}\n\n/**\n * Required services (cordis fiber inject). The target slots are declared by\n * the ui-sidebar / ui-conversation applies, whose activation order relative\n * to this one is NOT constrained: dsh.client.inject edges are informational\n * (loading/prefetch metadata, never apply sequencing) and neither owner\n * provides a waitable service. apply therefore depends on each slot\n * declaration through `slots.inject()` instead of assuming order.\n */\nexport const inject = [\n 'slots', 'sessions', 'workspaces', 'locale', 'remote', 'remote.directoryPicker', 'layout', 'shortcuts',\n]\n\n/**\n * Register the browser and picker once their slot declarations are on the\n * ledger. Inject factories return plain callbacks; data reads use the\n * framework's global hooks.\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n const sessions = ctx.get('sessions') as ISessions\n const workspaces = ctx.get('workspaces') as IWorkspaces\n // One viewing-store instance, created here as ui-layout does for its layout\n // store: the browser declares the handle, and the UiWorkspace service writes\n // view order through the same instance the renderer hands the browser.\n const viewHandle = createWorkspaceViewStore()\n const viewInstance = viewHandle.create()\n const viewStore: typeof viewHandle = { ...viewHandle, create: () => viewInstance }\n const rowToast = createSnapshotStore<RowToastState | null>(null)\n let toastSeq = 0\n const notify = (toast: RowToast): void => { rowToast.set({ ...toast, seq: ++toastSeq }) }\n const uiWorkspace = new UiWorkspaceService(\n ctx, ctx.remote.directoryPicker, workspaces, sessions, viewInstance.actions, notify,\n )\n ctx.slots.provideRoot({ hooks: { workspaces: workspaces.list } })\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-workspace: dictionaries')\n const shortcutControls = createWorkspaceShortcutControls()\n\n // 折叠徽标的显示偏好(`showCompletedInBadge`)。\n //\n // 源先挂上(**恒在**,值先是默认):标准 props 的 hook 调用顺序必须稳定,晚挂或\n // 摘掉 `useBadgeSettings` 都会改变顺序而崩渲染。设置面随后经 `ctx.inject` 接入,\n // 只改源的值,不改源的存亡。\n const badgeSettings = createBadgeSettingsSource()\n ctx.slots.provideRoot({ hooks: { badgeSettings } })\n\n // 等宿主设置服务就绪——**非阻塞**:`ctx.inject` 是嵌套插件,服务永不到达也只是设置\n // 读不到(回落默认),本插件其余功能不受影响。这里不直接用 `ctx.get` 读:服务可能在\n // 本插件之后才注册,那时读到的 undefined 会永久生效(设置被静默忽略直到刷新)。\n //\n // 寻址键是**条目 id**(`cordis.patch.yml` 的 `id: dsh-group-status`),不是 settings\n // namespace——宿主 `describe()` 的 `ns` 即条目 id。\n ctx.inject(['configForms'], (configCtx) => {\n const forms = configCtx.get('configForms') as ConfigFormsLike | undefined\n const scope: SettingsScopeLike | undefined =\n forms !== undefined && typeof forms.get === 'function' ? forms.get(ENTRY_ID) : undefined\n if (scope === undefined) return\n badgeSettings.publish(scope.getSnapshot())\n configCtx.effect(\n () => scope.subscribe(() => { badgeSettings.publish(scope.getSnapshot()) }),\n 'dsh-group-status: badge settings',\n )\n })\n\n const searchSessions: WorkspaceBrowserInjected['searchSessions'] = async (query, signal) => {\n const result = await sessions.search(query, signal)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n }\n\n // Stable per-surface occupancy sources (the renderer's hook cache keys by\n // source identity): true while the surface's directory-flow hole is filled.\n const flowSource = (hole: 'sidebar.workspaces.directoryFlow' | 'conversation.hero.workspace.directoryFlow'): HostObservable<boolean> => ({\n getSnapshot: () => ctx.slots.entries(hole).length > 0,\n subscribe: listener => ctx.slots.subscribe(hole, listener),\n })\n const browserFlowSource = flowSource('sidebar.workspaces.directoryFlow')\n const hostInfo: HostObservable<RemoteHostFacts> = {\n getSnapshot: () => ctx.remote.$host,\n subscribe: listener => ctx.on('connection/reset', listener),\n }\n const pickerFlowSource = flowSource('conversation.hero.workspace.directoryFlow')\n const openSession: WorkspaceBrowserInjected['open'] = (sessionId) => {\n uiWorkspace.openSession(sessionId)\n }\n // Registry-global sets as Sets, rebuilt only when the Workspace snapshot changes.\n const pinnedSet = derive(workspaces.list, snapshot => new Set<SessionId>(snapshot.pinnedSessionIds))\n const archivedSet = derive(workspaces.list, snapshot => new Set<SessionId>(snapshot.archivedSessionIds))\n // Plugin-private facts the row actions and their overlay surfaces share:\n // the pending rename request and the notice on display. Each business\n // writes through its own injected callback and the surface reads through\n // its bound hook.\n const renameRequest = derive(shortcutControls.state, state => state.renameTarget)\n const archiveRequest = createSnapshotStore<SessionArchiveConfirmRequest | null>(null)\n const requestSessionRename = shortcutControls.rename\n const unarchiveSession = (sessionId: SessionId): void => {\n uiWorkspace.unarchiveSession(sessionId).catch((reason: unknown) => {\n console.warn('session unarchive rejected:', reason)\n })\n }\n const renameSession: SessionRenameDialogInjected['renameSession'] = async (sessionId, title) => {\n const result = await sessions.using(\n sessionId,\n { source: 'workspaceOperation' },\n reference => reference.binding.session.rename(title),\n )\n if (!result.ok) throw new Error(result.error.message)\n }\n const pinInjected = (): PinSessionInjected => ({\n hooks: { pinned: pinnedSet, archived: archivedSet },\n // Pin failures surface as a notice: nothing else on the surface moves, so\n // a silent failure would read as a dead action.\n pinSession: (sessionId) => {\n uiWorkspace.pinSession(sessionId).catch(() => { notify({ kind: 'pinFailed' }) })\n },\n unpinSession: (sessionId) => {\n uiWorkspace.unpinSession(sessionId).catch(() => { notify({ kind: 'unpinFailed' }) })\n },\n })\n const archiveInjected = (): ArchiveSessionInjected => ({\n hooks: { archived: archivedSet },\n // Archive preserves the log and the account position, so a quiet Session\n // needs no confirmation; the notice offers undo and the archived filter.\n // The Host's refusal for running work is the one case that asks first:\n // the confirmation names that work and offers to stop it.\n archiveSession: (sessionId) => {\n uiWorkspace.archiveSession(sessionId).then(() => {\n notify({ kind: 'archived', sessionId })\n }).catch((reason: unknown) => {\n const activity = activeSessionRefusal(reason)\n if (activity === undefined) {\n console.warn('session archive rejected:', reason)\n return\n }\n const displayTitle = sessions.list.getSnapshot().byId[sessionId]?.displayTitle ?? sessionId\n archiveRequest.set({ sessionId, displayTitle, activity })\n })\n },\n unarchiveSession,\n })\n installWorkspaceShortcuts(ctx, uiWorkspace, shortcutControls, archiveInjected().archiveSession)\n const archiveConfirmInjected = (): SessionArchiveConfirmInjected => ({\n hooks: { archiveRequest },\n settleSessionArchive: () => { archiveRequest.set(null) },\n stopAndArchiveSession: async (sessionId) => {\n await uiWorkspace.archiveSession(sessionId, { stopActivity: true })\n notify({ kind: 'stoppedAndArchived', sessionId })\n },\n })\n const forkInjected = (): ForkSessionInjected => ({\n forkSession: (sessionId) => {\n uiWorkspace.forkSession(sessionId, (childId) => {\n ctx.get('productAnalytics')?.track('branch_session_click', { session_id: childId, parent_session_id: sessionId, click_position: 'sidebar' })\n }).catch(() => {\n // Fork or child-title failure leaves the list as it was.\n })\n },\n })\n const renameInjected = (): RenameSessionInjected => ({ requestSessionRename })\n const renameDialogInjected = (): SessionRenameDialogInjected => ({\n hooks: { renameRequest },\n settleSessionRename: shortcutControls.closeRename,\n renameSession,\n })\n const rowToastInjected = (): RowToastInjected => ({\n hooks: { toast: rowToast },\n dismissToast: () => { rowToast.set(null) },\n undoArchive: unarchiveSession,\n showArchived: () => { viewInstance.actions.setArchivedFilter('show') },\n })\n const browserInjected = (): WorkspaceBrowserInjected => ({\n // Explicit group actions keep their target; unscoped New Session inherits\n // the current Session Workspace before the recent-Workspace fallback.\n startSession: (workspaceId) => { uiWorkspace.startSession(workspaceId) },\n open: openSession,\n searchSessions,\n searchResultLimit: sessions.searchResultLimit,\n requestSessionRename,\n notifyArchivedNotOpenable: () => { notify({ kind: 'archivedNotOpenable' }) },\n renameWorkspace: async (workspaceId, title) => { await workspaces.rename(workspaceId, title) },\n deleteWorkspace: async (workspaceId) => { await workspaces.delete(workspaceId) },\n insertWorkspaceBefore: async (workspaceId, beforeWorkspaceId) => {\n await workspaces.insertBefore(workspaceId, beforeWorkspaceId)\n },\n unarchiveSession: async (sessionId) => { await uiWorkspace.unarchiveSession(sessionId) },\n createWorkspace: input => workspaces.create(input),\n requestSearch: shortcutControls.search,\n requestAddWorkspace: shortcutControls.add,\n closeAddWorkspace: shortcutControls.closeAdd,\n setDirectoryBusy: shortcutControls.directoryBusy,\n dismissForkError: shortcutControls.dismissForkError,\n hooks: { directoryFlow: browserFlowSource, hostInfo, workspaceShortcuts: shortcutControls.state, shortcuts: ctx.shortcuts.catalog },\n })\n const pickerInjected = (): WorkspacePickerInjected => ({\n createWorkspace: input => workspaces.create(input),\n hooks: { directoryFlow: pickerFlowSource },\n })\n // Each registration declares its owned children in the same call; slot\n // injection follows both the owner and declaration HMR lifetimes.\n ctx.slots.inject('sidebar.workspaces', () => ctx.slots.register(\n {\n name: 'sidebar.workspaces',\n children: {\n 'sidebar.workspaces.directoryFlow': { kind: 'single', scope: 'root' },\n // Every row entry reads the menu's open state through a hook bound\n // from the row's render occurrence (the owner passes the state pair\n // as hookContext).\n 'sidebar.workspaces.session.menu.item': {\n kind: 'list', scope: 'root', inject: { hooks: { menuOpenState: menuOpenStateFactory, shortcuts: ctx.shortcuts.catalog } },\n },\n 'sidebar.workspaces.session.row.action': { kind: 'list', scope: 'root' },\n 'sidebar.session.row.leading': { kind: 'list', scope: 'root' },\n 'sidebar.session.row.hover': { kind: 'list', scope: 'root' },\n },\n store: viewStore,\n inject: browserInjected,\n locale: NS,\n },\n WorkspaceBrowser,\n ))\n // The shipped row actions take the same route as a plugin's: `slots.inject`\n // waits for the browser registration above to declare each list, and the\n // entries leave with it. Orders step by 100 so a plugin entry can land\n // between them.\n ctx.slots.inject('sidebar.workspaces.session.menu.item', function* () {\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'pin', order: 100, locale: NS, inject: pinInjected }, PinSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'rename', order: 200, locale: NS, inject: renameInjected }, RenameSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'fork', order: 300, locale: NS, inject: forkInjected }, ForkSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'archive', order: 400, locale: NS, inject: archiveInjected }, ArchiveSessionMenuItem)\n })\n ctx.slots.inject('sidebar.workspaces.session.row.action', function* () {\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.row.action', id: 'archive', order: 100, locale: NS, inject: archiveInjected }, ArchiveSessionRowButton)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.row.action', id: 'pin', order: 200, locale: NS, inject: pinInjected }, PinSessionRowButton)\n })\n // The surfaces the actions raise live in the frame-wide layer: they must\n // outlive the row menu the action sat in.\n ctx.slots.inject('shell.overlay', function* () {\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.session-rename', locale: NS, inject: renameDialogInjected,\n }, SessionRenameDialog)\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.session-archive', locale: NS, inject: archiveConfirmInjected,\n }, SessionArchiveConfirmDialog)\n // The toast shares the browser's viewing store: it reads the archived\n // filter to drop the archived notice's filter action once rows are visible.\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.row-toast', locale: NS, store: viewStore, inject: rowToastInjected,\n }, RowActionToast)\n })\n ctx.slots.inject('conversation.hero.workspace', () => ctx.slots.register(\n {\n name: 'conversation.hero.workspace',\n children: { 'conversation.hero.workspace.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: pickerInjected,\n locale: NS,\n },\n WorkspacePicker,\n ))\n}\n\n/**\n * The activity a Host `workspace/session-active` refusal reported, or nothing\n * for any other failure. The class identity check goes by name: client plugin\n * bundles do not share error-class identity.\n */\nfunction activeSessionRefusal(reason: unknown): readonly SessionActivity[] | undefined {\n if (!(reason instanceof Error) || reason.name !== 'WorkspaceArchiveError') return undefined\n const { rpcError } = reason as WorkspaceArchiveError\n return rpcError.code === 'workspace/session-active' ? rpcError.details.activity : undefined\n}\n"],"ignoreList":[3,4,10,11],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["createSnapshotStore","useMemo","SettingsFormModel","useSyncExternalStore","useId","SettingsForm","css","Switch","assertNever","assertNever","defineStore","Service","createSnapshotStore","StateDot","IconClockOutlineRegular","IconListPenOutlineRegular","css","useRef","useMemo","relativeTime","css","StateDot","useState","IconEditOutlineRegular","IconTrashOutlineRegular","IconFolderOpenRegular","IconFolderCloseRegular","IconTriangleRightFillRegular","Menu","IconEllipsisOutlineRegular","Tooltip","IconNewChatOutlineRegular","HoverCard","IconPinFillRegular","IconArchiveOutlineRegular","IconUnarchiveOutlineRegular","Component","createRef","css","useCallback","useState","IconPlusOutlineRegular","IconFolderCloseRegular","Menu","css","Modal","Button","useState","Menu","IconFolderCloseRegular","IconWorkspaceTreeOutlineRegular","IconFlatListOutlineRegular","IconChevronsUpDownOutlineRegular","IconClockOutlineRegular","IconArchiveOffOutlineRegular","IconQueueOutlineRegular","IconArchiveCheckOutlineRegular","css","Tooltip","IconSlidersTwoOutlineRegular","IconArchiveOutlineRegular","useRef","useMemo","IconSearchOutlineRegular","IconCloseFillRegular","IconProjectAddOutlineRegular","Modal","Button","Toast","MenuItemButton","IconUnarchiveOutlineRegular","IconArchiveOutlineRegular","Tooltip","css","useState","Modal","Button","browserCss","MenuItemButton","IconBranchOutlineRegular","MenuItemButton","IconPinFillRegular","IconPinOutlineRegular","Tooltip","css","MenuItemButton","IconEditOutlineRegular","useState","useRef","Modal","Button","css","Toast","IconWarningOutlineRegular","assertNever","createSnapshotStore"],"sources":["../src/client/contract/slots.ts","../src/client/shortcuts.ts","../src/client/badge-settings.ts","../src/client/badge-field.ts","../src/client/BadgeSettingsCard.tsx","../node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.2.0-rc.2_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-values/lib/index.js","../node_modules/.pnpm/@deepseek-ai+dsh-util-workspace-path@0.2.0-rc.2_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-workspace-path/lib/index.js","../src/client/tree.ts","../src/client/stores.ts","../src/client/pin-order.ts","../src/client/navigation.ts","../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs","../node_modules/.pnpm/@deepseek-ai+dsh-api-workspace-controller@0.2.0-rc.2_7b1cc3b3e03980f49f8901a2ede23841/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/default-workspace.js","../src/client/group-status.ts","../src/client/rows/GroupBadge.tsx","../src/client/rows/Rows.tsx","../src/client/rows/AnimatedRows.tsx","../src/client/WorkspacePicker.tsx","../src/client/rows/WorkspaceBrowser.tsx","../src/client/session-actions/ArchiveSession.tsx","../src/client/session-actions/derived.ts","../src/client/session-actions/ForkSession.tsx","../src/client/session-actions/PinSession.tsx","../src/client/session-actions/RenameSession.tsx","../src/client/session-actions/RowActionToast.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * ui-workspace contracts. Two registrations share this package:\n *\n * - WorkspaceBrowser fills the sidebar shell's `sidebar.workspaces` hole —\n * the whole browsing region (section header, search, grouped/flat session\n * list, workspace dialogs). It registers this package's viewing store and\n * consumes the shell's two-fact owner share (wide / expandSidebar).\n * - WorkspacePicker fills the conversation empty-state hole (menu + error\n * dialog shared with the browser).\n *\n * Both registrations declare a **directory-flow hole** (`single` kind): the\n * slot a composed picker package's client half fills with its\n * picking interaction — a renderless native-chooser driver or an in-app\n * browsing dialog. ui-workspace owns the trigger (the \"Add workspace…\"\n * entry, present only while the hole is occupied) and the adoption\n * semantics (`createWorkspace({ path })`, the retryable error dialog,\n * Choose again); the occupant owns everything between `open` and the picked path,\n * including creating a new directory to hand back. That occupant-owned\n * creation is why adding a workspace has a single route: an unoccupied hole\n * leaves the surface with no add affordance at all.\n * Two holes exist because the two menu surfaces are independent slot entries\n * and a hole has exactly one declaring entry — they carry the same owner\n * contract and the same occupant.\n *\n * WorkspaceBrowser also declares the two **Session row action lists**: every\n * row of a Session's \"...\" menu is an entry of\n * `sidebar.workspaces.session.menu.item`, and every hover button at the row's\n * end is an entry of `sidebar.workspaces.session.row.action`. The shipped\n * actions — pin, rename, fork, archive — are ordinary entries this package\n * registers from `apply`, each carrying its own behavior in its own inject\n * face and reading its own Host state through hooks that face injects, so a\n * client plugin's action lands beside them by `order` and needs nothing from\n * the browser beyond the row identity.\n *\n * The browser entry additionally declares two `list` seats per Session row\n * (`sidebar.session.row.leading` / `sidebar.session.row.hover`) for ambient\n * row decorations. Both take the row's Session identity and nothing else: a\n * session-scoped seat would force a Session binding, which would activate and\n * retain every listed Session.\n */\nimport type {\n HostObservable, InjectFace, PropsHooks, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore, SlotHookFactory,\n} from '@deepseek-ai/dsh-client-ui-slots'\n// Type-only: pull the owner SlotMap merges into programs that resolve the\n// runtime shares below.\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type { SessionSearchResultItem } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client'\nimport type { SessionActivity, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { ShortcutCatalogEntry } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { WorkspaceShortcutState } from '../shortcuts.ts'\nimport type { createWorkspaceViewStore } from '../stores.ts'\n\n/**\n * Owner share of the directory-flow holes: the complete conversation between\n * the trigger surface and the picking interaction. The occupant reads `open`\n * to run/render its interaction and reports exactly one outcome per open.\n */\nexport interface DirectoryFlowOwnerProps {\n /** True while a picking interaction is requested; flipping back to false withdraws the request. */\n open: boolean\n /** True while the owner adopts a picked path (`createWorkspace` in flight); occupants disable their commit affordances. */\n busy: boolean\n /** The operator picked a directory (absolute host path); the owner adopts it. */\n onPicked: (path: string) => void\n /** The operator dismissed the interaction; the owner just closes the flow. */\n onCancel: () => void\n /** The interaction itself failed (chooser missing, listing denied); the owner shows its error surface. */\n onError: (message: string) => void\n}\n\n/** Owner share of one Session row action occurrence: the row the action belongs to. */\nexport interface SessionRowOwnerProps {\n /** Session the row shows. */\n sessionId: SessionId\n /** Row display title: persisted title, or empty when the Session has none. */\n displayTitle: string\n}\n\n/** The row menu's open state as its owner holds it: the `useState` pair. */\nexport type MenuOpenState = readonly [open: boolean, setOpen: (open: boolean) => void]\n\n/**\n * Hook every row-menu entry receives. Rows only render while the menu is\n * open, so an entry reads it for the setter: `setOpen(false)` dismisses the\n * menu the entry sits in — the same state the owner's `onClose` sets.\n */\nexport type UseMenuOpenState = () => MenuOpenState\n\n/**\n * Bind the row's render occurrence into the entries' `useMenuOpenState` hook:\n * the owner supplies its open-state pair as the occurrence's `hookContext`,\n * and the hook hands that pair back.\n * @param _standard - framework standard props (unused).\n * @param state - the menu's open-state pair from the render occurrence.\n * @returns the hook the entry calls.\n */\nexport const menuOpenStateFactory: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState> =\n (_standard, state) => () => state\n\n/**\n * Owner share of the two Session-row schedule seats. Both receive only the\n * row's Session identity: the occupant reads that Session's own scheduled\n * tasks, and reading them activates nothing.\n */\nexport interface SessionRowScheduleOwnerProps {\n /** Session this row shows; the occupant addresses its own data by this id. */\n readonly sessionId: SessionId\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** Directory-flow hole under the conversation empty-state picker (declared by the WorkspacePicker entry). */\n 'conversation.hero.workspace.directoryFlow': { kind: 'single'; scope: 'root'; owner: DirectoryFlowOwnerProps }\n /** Directory-flow hole under the sidebar browsing region (declared by the WorkspaceBrowser entry). */\n 'sidebar.workspaces.directoryFlow': { kind: 'single'; scope: 'root'; owner: DirectoryFlowOwnerProps }\n /**\n * Leading decoration of one Session row, in the 16px cell before the title\n * that the row's own state dot otherwise occupies. A higher-priority state\n * (a pending interaction, a new message, live activity) replaces the seat\n * with that dot for the same row, so an occupant here never renders beside\n * a status dot and is mounted only by a row whose primary state is idle.\n * An archived row keeps that cell blank — neither its status dot nor this\n * seat renders there, and its live status appears on the hover card only.\n */\n 'sidebar.session.row.leading': { kind: 'list'; scope: 'root'; owner: SessionRowScheduleOwnerProps }\n /**\n * Section of the Session row's hover card between its relative time and\n * its trailing status line. Mounted only while that card is open.\n */\n 'sidebar.session.row.hover': { kind: 'list'; scope: 'root'; owner: SessionRowScheduleOwnerProps }\n /**\n * The rows of one Session's \"...\" menu, in ascending `order`. ui-workspace\n * registers the shipped rows here — `pin` (100), `rename` (200), `fork`\n * (300), `archive` (400) — so a plugin row is placed by its own `order`\n * among them. Use a package-namespaced `id`; reusing a shipped id at\n * another `priority` shadows that row. Each entry renders one\n * `role=\"menuitem\"` `<button>` (the shipped rows use ui-primitives'\n * `MenuItemButton`, which adds the host styling and `separatorBefore`),\n * decides its own visibility from its own state, and dismisses the menu\n * through the injected `useMenuOpenState` hook after acting; the list's\n * keyboard walk and focus return read the DOM, so any such button joins\n * them. Labels come from the contributing package's locale namespace.\n * @example\n * return {\n * inject: ['slots'],\n * apply(ctx) {\n * const copyLabel = 'Copy Session ID' // Localize in the contributing package.\n * ctx.slots.inject('sidebar.workspaces.session.menu.item', () => ctx.slots.register(\n * { name: 'sidebar.workspaces.session.menu.item', id: 'copy-session-id', order: 500 },\n * ({ sessionId, useMenuOpenState }) => {\n * const [, setMenuOpen] = useMenuOpenState()\n * return React.createElement(\n * 'button',\n * { type: 'button', role: 'menuitem', onClick: () => { setMenuOpen(false); void navigator.clipboard.writeText(sessionId) } },\n * copyLabel,\n * )\n * },\n * ))\n * },\n * }\n */\n 'sidebar.workspaces.session.menu.item': {\n kind: 'list'\n scope: 'root'\n owner: SessionRowOwnerProps\n hookContext: MenuOpenState\n inject: { hooks: {\n menuOpenState: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState>\n shortcuts: HostObservable<readonly ShortcutCatalogEntry[]>\n } }\n }\n /**\n * The hover buttons at the end of one Session row, in ascending `order`,\n * after the \"...\" menu trigger. ui-workspace registers `archive` (100) and\n * `pin` (200) here. An entry renders one icon button (or nothing, when its\n * action does not apply to the row) and owns the action it performs. Clicks\n * inside the strip stay in the strip, so the button needs no propagation\n * handling to keep the row from opening.\n */\n 'sidebar.workspaces.session.row.action': { kind: 'list'; scope: 'root'; owner: SessionRowOwnerProps }\n }\n}\n\n/** The two directory-flow holes; a flow package's client half registers its one component into both. */\nexport type DirectoryFlowSlotName =\n | 'conversation.hero.workspace.directoryFlow'\n | 'sidebar.workspaces.directoryFlow'\n\n/**\n * Directory-picking share both trigger surfaces consume. Occupancy rides the\n * inject face's reserved `hooks` compartment: the renderer binds the source\n * into the `useDirectoryFlow` selector hook, so an empty hole hides the\n * \"Add workspace…\" entry reactively and the surface withdraws an open\n * flow whose occupant unloaded mid-interaction (nobody is left to cancel).\n */\nexport type DirectoryPickingInjected = {\n hooks: {\n /** True while this surface's directory-flow hole is occupied. */\n directoryFlow: HostObservable<boolean>\n }\n}\n\n/** Component-side view of the picking share: the bound occupancy selector hook. */\nexport type DirectoryPickingHooks = PropsHooks<DirectoryPickingInjected['hooks']>\n\n/**\n * Browser-private injected share (arrives via the register inject factory).\n * Data reads use the global framework hooks; these are the Host actions the\n * browsing region drives.\n */\nexport type WorkspaceBrowserInjected = {\n hooks: DirectoryPickingInjected['hooks'] & {\n /**\n * Fixed Host facts, reached through a hook rather than injected as values:\n * the renderer memoizes an entry's inject result for the registration's\n * lifetime, so facts read there would freeze at whatever the first render\n * saw. Select the field the surface needs (`info => info.home`).\n */\n hostInfo: HostObservable<RemoteHostFacts>\n workspaceShortcuts: HostObservable<WorkspaceShortcutState>\n shortcuts: HostObservable<readonly ShortcutCatalogEntry[]>\n }\n /** Open the browser search and focus its input. */\n requestSearch: () => void\n /** Request the existing directory picker. */\n requestAddWorkspace: () => void\n /** Consume the directory-picker opening request. */\n closeAddWorkspace: () => void\n /** Publish directory interaction occupancy for command availability. */\n setDirectoryBusy: (busy: boolean) => void\n /** Dismiss the shortcut's fork-failure notification. */\n dismissForkError: () => void\n /**\n * Start a New Session in a Workspace: reuse-or-create its blank session and\n * open it; without an explicit workspace, inherit the current Session\n * Workspace, then the recent Workspace, or clear into the New Session view.\n */\n startSession: (workspaceId?: WorkspaceId) => void\n /** Open a real Session. */\n open: (sessionId: SessionId) => void\n /**\n * Search current visible conversation messages. The Host fixes the result\n * bound; `hasMore` means the query needs narrowing.\n */\n searchSessions: (\n query: string,\n signal: AbortSignal,\n ) => Promise<{ items: readonly SessionSearchResultItem[]; hasMore: boolean }>\n /** Maximum number of merged rows rendered for one search. */\n searchResultLimit: number\n /** Open the Session rename dialog (a row title double-click); the rename action entry raises the same request. */\n requestSessionRename: (sessionId: SessionId, currentTitle: string) => void\n /** Tell the user an archived row cannot be opened (a click on it). */\n notifyArchivedNotOpenable: () => void\n /** Rename a Host Workspace (rejects on name conflict; resolves on durability). */\n renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>\n /** Delete only a Host Workspace registration; directory and Session logs remain. */\n deleteWorkspace: (workspaceId: WorkspaceId) => Promise<void>\n /**\n * Reorder a Workspace in the durable registry display order.\n * Omitted anchor appends to the end.\n */\n insertWorkspaceBefore: (workspaceId: WorkspaceId, beforeWorkspaceId?: WorkspaceId) => Promise<void>\n /** Remove a Session from the registry-global archived set (the search results' restore button). */\n unarchiveSession: (sessionId: SessionId) => Promise<void>\n /** Adopt a picked host directory as a real Workspace before targeting a Session. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n}\n\n/** The browser's declared viewing store handle, shared with the row actions that write view state. */\nexport type WorkspaceViewStoreHandle = ReturnType<typeof createWorkspaceViewStore>\n\n/** Props of one shipped row-menu entry: owner share + locale seat + the entry's own injected share. */\nexport type SessionMenuItemProps<Injected extends object = object> =\n PropsRuntime<'sidebar.workspaces.session.menu.item'>\n & PropsLocale<'workspace'>\n & InjectFace<Injected>\n\n/** Props of one shipped row hover button: owner share + locale seat + the entry's own injected share. */\nexport type SessionRowActionProps<Injected extends object = object> =\n PropsRuntime<'sidebar.workspaces.session.row.action'>\n & PropsLocale<'workspace'>\n & InjectFace<Injected>\n\n/** One transient Workspace notice rendered by the overlay toast entry. */\nexport type RowToast =\n | { kind: 'archived'; sessionId: SessionId }\n | { kind: 'stoppedAndArchived'; sessionId: SessionId }\n | { kind: 'pinFailed' }\n | { kind: 'unpinFailed' }\n | { kind: 'archivedNotOpenable' }\n | { kind: 'defaultWorkspaceFailed' }\n /**\n * An explicit New Session request that failed. `message` is untranslated:\n * a Host refusal as `code: message` — the stable code stays in the copy so\n * a report can be searched by it — and any other failure's own message.\n */\n | { kind: 'createFailed'; message: string }\n\n/** The notice on display; `seq` keys remounts so a repeated notice restarts its hold. */\nexport type RowToastState = RowToast & { seq: number }\n\n/**\n * Pin action share (menu row and hover button). The callbacks carry the whole\n * behavior: the Host call, fronting the Session in its saved orders after a\n * pin, and the failure notice. The hooks are the registry-global sets as\n * Sets, so a row reads its own membership with one lookup.\n */\nexport interface PinSessionInjected {\n hooks: {\n /** Pinned Session ids. */\n pinned: HostObservable<ReadonlySet<SessionId>>\n /** Archived Session ids (pin does not apply to an archived row). */\n archived: HostObservable<ReadonlySet<SessionId>>\n }\n /** Pin a Session; on success it leads its accounts' saved orders, on failure the notice says so. */\n pinSession: (sessionId: SessionId) => void\n /** Unpin a Session; saved positions stay as they are. */\n unpinSession: (sessionId: SessionId) => void\n}\n\n/**\n * Archive action share (menu row and hover button). The callbacks carry the\n * whole behavior: the Host call, the notice a success raises, the\n * stop-and-archive confirmation a Host refusal for running work raises, and\n * the diagnostics for any other rejection.\n */\nexport interface ArchiveSessionInjected {\n hooks: {\n /** Archived Session ids. */\n archived: HostObservable<ReadonlySet<SessionId>>\n }\n /**\n * Archive a Session into the registry-global set: the row keeps its\n * account position and shows per the archived filter; archiving the\n * current session clears the selection into the New Session view state.\n * A Session with running work is not archived by this call: the Host's\n * refusal opens the stop-and-archive confirmation instead.\n */\n archiveSession: (sessionId: SessionId) => void\n /** Remove a Session from the registry-global archived set. */\n unarchiveSession: (sessionId: SessionId) => void\n}\n\n/**\n * A stop-and-archive confirmation the archive action asked for: the Host\n * refused the plain archive because this work still runs.\n */\nexport interface SessionArchiveConfirmRequest {\n /** Session to stop and archive. */\n sessionId: SessionId\n /** The row's display title, named in the dialog. */\n displayTitle: string\n /** What the Host reported running, in family order. */\n activity: readonly SessionActivity[]\n}\n\n/**\n * Stop-and-archive dialog share: the pending confirmation, its settlement,\n * and the archive hop that asks the Host to stop the work first.\n */\nexport interface SessionArchiveConfirmInjected {\n hooks: {\n /** The confirmation asked for, until the dialog consumes or cancels it. */\n archiveRequest: HostObservable<SessionArchiveConfirmRequest | null>\n }\n /** Consume or cancel the pending confirmation. */\n settleSessionArchive: () => void\n /**\n * Archive a Session after the Host stops its running work; resolves once\n * the archive set is durable (the stops settle in the background) and\n * raises the stopped-and-archived notice.\n */\n stopAndArchiveSession: (sessionId: SessionId) => Promise<void>\n}\n\n/** Fork action share. */\nexport interface ForkSessionInjected {\n /** Fork a Session at its last completed turn; the child arrives through the Host list. */\n forkSession: (sessionId: SessionId) => void\n}\n\n/** Rename action share: the row only raises the request; the dialog entry answers it. */\nexport interface RenameSessionInjected {\n /** Ask for the rename dialog, seeded with the row's current title. */\n requestSessionRename: (sessionId: SessionId, currentTitle: string) => void\n}\n\n/** A Session rename the rename action asked for; the dialog entry opens on it. */\nexport interface SessionRenameTarget {\n /** Session to rename. */\n sessionId: SessionId\n /** Title the dialog seeds its draft from. */\n currentTitle: string\n}\n\n/** Rename dialog share: the pending request, its settlement, and the rename hop the dialog confirms with. */\nexport interface SessionRenameDialogInjected {\n hooks: {\n /** The rename asked for, until the dialog consumes or cancels it. */\n renameRequest: HostObservable<SessionRenameTarget | null>\n }\n /** Consume or cancel the pending request. */\n settleSessionRename: () => void\n /** Rename a Session (explicit user title; resolves on host acceptance). */\n renameSession: (sessionId: SessionId, title: string) => Promise<void>\n}\n\n/** Row toast share: the notice on display, its dismissal, and the two actions the archived notice offers. */\nexport interface RowToastInjected {\n hooks: {\n /** The notice on display, or none. */\n toast: HostObservable<RowToastState | null>\n }\n /** Take the notice down. */\n dismissToast: () => void\n /** Undo an archive from its notice. */\n undoArchive: (sessionId: SessionId) => void\n /** Switch the archived filter to \"show\" so the archived row is back in view. */\n showArchived: () => void\n}\n\n/** Props of the rename dialog entry in `shell.overlay`. */\nexport type SessionRenameDialogProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & Omit<SessionRenameDialogInjected, 'hooks'>\n & PropsHooks<SessionRenameDialogInjected['hooks']>\n\n/** Props of the stop-and-archive dialog entry in `shell.overlay`. */\nexport type SessionArchiveConfirmProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & Omit<SessionArchiveConfirmInjected, 'hooks'>\n & PropsHooks<SessionArchiveConfirmInjected['hooks']>\n\n/**\n * Props of the row toast entry in `shell.overlay`. The declared viewing store\n * carries the archived filter; the archived notice omits its filter action\n * when archived rows are already visible.\n */\nexport type RowToastProps =\n PropsRuntime<'shell.overlay'>\n & PropsLocale<'workspace'>\n & PropsStore<WorkspaceViewStoreHandle>\n & Omit<RowToastInjected, 'hooks'>\n & PropsHooks<RowToastInjected['hooks']>\n\n/** Full browser props: shell owner share + viewing store + injected actions + the locale seat. */\nexport type WorkspaceBrowserProps =\n PropsRuntime<'sidebar.workspaces'>\n & PropsRenderSlots<\n | 'sidebar.workspaces.directoryFlow'\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n >\n & PropsStore<WorkspaceViewStoreHandle>\n & Omit<WorkspaceBrowserInjected, 'hooks'>\n & PropsHooks<WorkspaceBrowserInjected['hooks']>\n & PropsLocale<'workspace'>\n\n/**\n * Picker-private injected share. Pick semantics remain in the owner's onPick\n * callback; this callback creates only the real Host Workspace. A type alias\n * supplies the implicit index signature required by the registry.\n */\nexport type WorkspacePickerInjected = DirectoryPickingInjected & {\n /** Adopt a picked host directory as a real Workspace before targeting a Session. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n}\n\n/**\n * Full picker props: the owner share plus the creation callback and the\n * locale seat. The two picker holes (blank-session hero / New-Session view)\n * share one owner currency, so one composed type serves both registrations.\n */\nexport type WorkspacePickerProps =\n PropsRuntime<'conversation.hero.workspace'>\n & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'>\n & Omit<WorkspacePickerInjected, 'hooks'>\n & PropsHooks<WorkspacePickerInjected['hooks']>\n & PropsLocale<'workspace'>\n","/** Workspace command registration and browser-owned opening requests. */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { SessionForkError } from '@deepseek-ai/dsh-api-session-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { ShortcutCommand, ShortcutCommandId } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { UiWorkspace } from './navigation.ts'\n\n/** Transient requests consumed by the existing workspace browser. */\nexport interface WorkspaceShortcutState {\n readonly searchRequest: number\n readonly addRequested: boolean\n readonly directoryBusy: boolean\n readonly renameTarget: { readonly sessionId: SessionId; readonly currentTitle: string } | null\n readonly forkError: { readonly reason: 'unavailable' | 'failed'; readonly seq: number } | null\n}\n\ninterface WorkspaceShortcutControls {\n state: SnapshotStore<WorkspaceShortcutState>\n search: () => void\n add: () => void\n closeAdd: () => void\n directoryBusy: (busy: boolean) => void\n rename: (sessionId: SessionId, currentTitle: string) => void\n closeRename: () => void\n forkFailed: (reason: 'unavailable' | 'failed') => void\n dismissForkError: () => void\n}\n\n/**\n * Create the private browser request source shared by commands and controls.\n * @returns observable state and its complete mutation callbacks.\n */\nexport function createWorkspaceShortcutControls(): WorkspaceShortcutControls {\n const state = createSnapshotStore<WorkspaceShortcutState>({\n searchRequest: 0, addRequested: false, directoryBusy: false, renameTarget: null, forkError: null,\n })\n let forkErrorSeq = 0\n return {\n state,\n search: () => { state.set({ ...state.getSnapshot(), searchRequest: state.getSnapshot().searchRequest + 1 }) },\n add: () => { state.set(state.getSnapshot().directoryBusy ? state.getSnapshot() : { ...state.getSnapshot(), addRequested: true }) },\n closeAdd: () => { state.set({ ...state.getSnapshot(), addRequested: false }) },\n directoryBusy: (busy: boolean) => { state.set({ ...state.getSnapshot(), directoryBusy: busy }) },\n rename: (sessionId: SessionId, currentTitle: string) => {\n state.set({ ...state.getSnapshot(), renameTarget: { sessionId, currentTitle } })\n },\n closeRename: () => { state.set({ ...state.getSnapshot(), renameTarget: null }) },\n forkFailed: (reason) => {\n forkErrorSeq += 1\n state.set({ ...state.getSnapshot(), forkError: { reason, seq: forkErrorSeq } })\n },\n dismissForkError: () => { state.set({ ...state.getSnapshot(), forkError: null }) },\n }\n}\n\n/**\n * Register navigation commands against the existing workspace owner.\n * Rename requires a nonblank main Conversation with no modal obscuring it.\n * @param ctx - plugin context with the shortcut, locale, and model services.\n * @param navigation - session creation and forking from the pointer controls' navigation service.\n * @param controls - browser-owned opening requests.\n * @param archiveSession - shared archive action, including running-work confirmation and notices.\n */\nexport function installWorkspaceShortcuts(\n ctx: Context,\n navigation: Pick<UiWorkspace, 'startSession' | 'forkSession'>,\n controls: ReturnType<typeof createWorkspaceShortcutControls>,\n archiveSession: (sessionId: SessionId) => void,\n): void {\n const t = ctx.locale.bind('workspace')\n const current = () => Object.values(ctx.sessions.list.getSnapshot().byId)\n .find(row => (row.retainedBy.mainView ?? 0) > 0)\n const addReason = () => ctx.slots.entries('sidebar.workspaces.directoryFlow').length === 0\n ? t('shortcut.noPicker')\n : controls.state.getSnapshot().directoryBusy ? t('shortcut.directoryBusy') : null\n const register = (id: string, label: () => string, aliases: string[], code: string,\n modifiers: ('primary' | 'alt' | 'shift')[], webModifiers: ('primary' | 'alt' | 'shift')[], resolve: ShortcutCommand['resolve']): void => {\n ctx.effect(() => ctx.shortcuts.register({\n id: id as ShortcutCommandId, label, aliases, defaults: {\n 'desktop:macos': { code, modifiers }, 'desktop:windows': { code, modifiers }, 'desktop:linux': { code, modifiers },\n 'web:macos': { code, modifiers: webModifiers }, 'web:windows': { code, modifiers: webModifiers },\n },\n regions: ['page', 'editable'], modals: [], resolve,\n }), `ui-workspace: ${id}`)\n }\n register('session.new', () => t('session.new'), ['new session', 'new chat'], 'KeyN', ['primary'], ['primary', 'alt'],\n () => ({ status: 'handled', run: () => { navigation.startSession() } }))\n register('session.search', () => t('search.sessions.aria'), ['search sessions'], 'KeyK', ['primary'], ['primary', 'alt'],\n () => ({ status: 'handled', run: controls.search }))\n register('workspace.add', () => t('workspace.add'), ['add workspace', 'open folder'], 'KeyO', ['primary'], ['primary', 'alt'],\n () => {\n const reason = addReason()\n return reason === null ? { status: 'handled', run: controls.add } : { status: 'blocked', reason }\n })\n register('session.rename', () => t('rename.session.title'), ['rename session'], 'KeyG', ['primary', 'alt'], ['primary', 'alt'], (context) => {\n const target = current()\n return target === undefined || target.blank || context.modal !== null || ctx.layout.panelInfo.getSnapshot().activePanelId !== null\n ? { status: 'blocked', reason: t('shortcut.noSession') }\n : { status: 'handled', run: () => { controls.rename(target.id, target.title?.trim() ?? '') } }\n })\n register('session.fork', () => t('menu.fork'), ['fork session'], 'KeyF', ['primary', 'alt'], ['primary', 'shift'], () => {\n const target = current()\n if (target === undefined) return { status: 'blocked', reason: t('shortcut.noSession') }\n if (target.blank) return { status: 'blocked', reason: t('shortcut.noCompletedTurn') }\n return { status: 'handled', run: () => {\n void navigation.forkSession(target.id).catch((error: unknown) => {\n // Client plugin bundles do not share error-class identity.\n const unavailable = error instanceof Error && error.name === 'SessionForkError'\n && (error as SessionForkError).rpcError.code === 'session/fork-unavailable'\n controls.forkFailed(unavailable ? 'unavailable' : 'failed')\n if (!unavailable) console.warn('session fork rejected:', error)\n })\n } }\n })\n register('session.archive', () => t('menu.archiveSession'), ['archive session'], 'KeyA', ['primary', 'shift'], ['primary', 'alt'], () => {\n const target = current()\n return target === undefined ? { status: 'blocked', reason: t('shortcut.noSession') }\n : { status: 'handled', run: () => {\n archiveSession(target.id)\n } }\n })\n}\n","/**\n * 插件设置读取(折叠徽标显示偏好)。\n *\n * 数据流:apply 时先建一个**稳定**的标准 props 源并经 `provideRoot` 挂上(此时还不知道\n * 设置面在不在),再用 `ctx.inject(['configForms'], …)` 等宿主设置服务就绪——就绪后\n * 订阅本条目设置面,把快照推给源。设置页保存 → 宿主替换快照 → 源通知 → 徽标即时重渲染。\n *\n * 为什么不在 apply 里直接 `ctx.get('configForms')`:服务可能在**本插件之后**才注册,\n * 那时读到的 undefined 会永久生效(设置被静默忽略,直到刷新)。`ctx.inject` 是非阻塞的\n * 嵌套插件,服务永不到达也不会影响本插件其余功能。\n *\n * 为什么源必须一开始就存在:标准 props 的 hook 调用顺序必须稳定——挂上/摘掉\n * `useBadgeSettings` 会改变调用顺序而崩渲染。故源恒在,只有它的**值**随设置变化。\n *\n * 稳定性约定(React 外部存储,见 dsh-later 的同名 hook):`getSnapshot` 必须返回稳定\n * 引用——每次都构造新对象会让选择器的 `Object.is` 比较永不成立,触发\n * 「Maximum update depth exceeded」死循环(React #185),折叠行徽标会整块崩掉。\n *\n * 设置面缺席或未就绪时,回落到**默认全部显示**,与 `Config` 各字段的 schema 默认值同源:\n * 读不到配置不是「关掉」。\n */\n\n/** Loader 条目 id —— 设置页的寻址键,也是宿主 `describe()` 的 ns。 */\nexport const ENTRY_ID = 'dsh-group-status'\n\n/** 设置面快照的最小结构面(与宿主 `ConfigFormSnapshot` 兼容)。 */\nexport interface SettingsSnapshotLike {\n readonly status: string\n readonly value?: unknown\n}\n\n/** 设置面的最小结构面(与宿主 `ConfigForm` 兼容)。 */\nexport interface SettingsScopeLike {\n getSnapshot(): SettingsSnapshotLike\n subscribe(listener: () => void): () => void\n}\n\n/** 本插件在浏览器半关心的设置项。 */\nexport interface ResolvedBadgeSettings {\n /** 折叠徽标是否显示「已完成」绿点;缺失/非法一律回落 true。 */\n showCompletedInBadge: boolean\n /** 折叠徽标是否显示「进行中」转圈(含子智能体);缺失/非法一律回落 true。 */\n showRunningInBadge: boolean\n /** 折叠徽标是否显示「待审批」黄点(approval / plan-review / question);缺失/非法一律回落 true。 */\n showPendingInBadge: boolean\n /** 折叠徽标是否显示「定时任务」时钟图标(数据来自 dsh-later);缺失/非法一律回落 true。 */\n showScheduledInBadge: boolean\n /** 折叠徽标是否显示「等待评审」列表笔图标(数据来自 dsh-gitea-dispatch);缺失/非法一律回落 true。 */\n showWaitingReviewInBadge: boolean\n /** 悬停卡里是否显示聚合明细行;缺失/非法一律回落 true。 */\n showHoverDetails: boolean\n /** 徽标数字显示阈值:数量 >= 此值时才显示数字;缺失/非法一律回落 2(默认 count=1 时省略)。 */\n countThreshold: number\n}\n\n/** 标准 props 源的结构面(与 `HostObservable<ResolvedBadgeSettings>` 兼容)。 */\nexport interface BadgeSettingsSource {\n getSnapshot(): ResolvedBadgeSettings\n subscribe(listener: () => void): () => void\n}\n\n/** 始终存在的源:由 {@link createBadgeSettingsSource} 创建。 */\nexport interface MutableBadgeSettingsSource extends BadgeSettingsSource {\n /**\n * 采纳一条新快照(设置面就绪或宿主变更时推入)。\n *\n * 引用或取值都没变则**不通知**:宿主会为无关变更替换快照,无谓通知会让折叠行整列\n * 重渲染。\n * @param snapshot - 设置面快照;undefined 表示设置面缺失/收回。\n */\n publish(snapshot: SettingsSnapshotLike | undefined): void\n}\n\n/** 默认值:与 `Config` 各字段的 schema 默认同源(全部显示,数字阈值 2 即 count=1 时省略)。 */\nexport const DEFAULT_BADGE_SETTINGS: ResolvedBadgeSettings = Object.freeze({\n showCompletedInBadge: true,\n showRunningInBadge: true,\n showPendingInBadge: true,\n showScheduledInBadge: true,\n showWaitingReviewInBadge: true,\n showHoverDetails: true,\n countThreshold: 2,\n})\n\n/** 两个设置对象是否逐字段相等(用于发布前比较,避免无谓通知)。 */\nfunction settingsEqual(a: ResolvedBadgeSettings, b: ResolvedBadgeSettings): boolean {\n return (\n a.showCompletedInBadge === b.showCompletedInBadge &&\n a.showRunningInBadge === b.showRunningInBadge &&\n a.showPendingInBadge === b.showPendingInBadge &&\n a.showScheduledInBadge === b.showScheduledInBadge &&\n a.showWaitingReviewInBadge === b.showWaitingReviewInBadge &&\n a.showHoverDetails === b.showHoverDetails &&\n a.countThreshold === b.countThreshold\n )\n}\n\n/** 从原始快照派生:只有**显式 false** 才隐藏,缺失/非法一律显示(countThreshold 默认 2)。 */\nfunction resolveFromSnapshot(snap: SettingsSnapshotLike | undefined): ResolvedBadgeSettings {\n if (snap === undefined || snap.status !== 'ready') return DEFAULT_BADGE_SETTINGS\n const value = snap.value as Record<string, unknown> | undefined\n if (value === undefined || value === null || typeof value !== 'object') return DEFAULT_BADGE_SETTINGS\n const getBool = (field: string, def: boolean): boolean => {\n const v = value[field]\n return typeof v === 'boolean' ? v : def\n }\n const getNumber = (field: string, def: number): number => {\n const v = value[field]\n return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? Math.floor(v) : def\n }\n return {\n showCompletedInBadge: getBool('showCompletedInBadge', true),\n showRunningInBadge: getBool('showRunningInBadge', true),\n showPendingInBadge: getBool('showPendingInBadge', true),\n showScheduledInBadge: getBool('showScheduledInBadge', true),\n showWaitingReviewInBadge: getBool('showWaitingReviewInBadge', true),\n showHoverDetails: getBool('showHoverDetails', true),\n countThreshold: getNumber('countThreshold', 2),\n }\n}\n\n/**\n * 建一个恒在、取值稳定的徽标设置源。\n *\n * `getSnapshot` 是**纯读**(无副作用、无订阅),因此可以安全地在渲染期间被反复调用,\n * 也满足外部存储的引用稳定要求;订阅只由 {@link MutableBadgeSettingsSource.publish}\n * 在取值真正变化时触发。\n * @returns 源;调用方持有它并在设置面就绪后 `publish`。\n */\nexport function createBadgeSettingsSource(): MutableBadgeSettingsSource {\n const listeners = new Set<() => void>()\n let resolved: ResolvedBadgeSettings = DEFAULT_BADGE_SETTINGS\n let seen: SettingsSnapshotLike | undefined\n let seenSet = false\n return {\n getSnapshot: () => resolved,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n },\n publish: (snapshot) => {\n // 同一快照引用重复推入(含 undefined ↔ undefined)直接丢弃。\n if (seenSet && snapshot === seen) return\n seen = snapshot\n seenSet = true\n const next = resolveFromSnapshot(snapshot)\n // 取值没变就不替换引用、不通知:宿主为无关字段替换快照时不该惊动折叠行。\n if (settingsEqual(next, resolved)) return\n resolved = next\n for (const listener of [...listeners]) listener()\n },\n }\n}\n\n/** 旧口径的纯解析函数,保留给测试与 `publish` 复用。 */\nexport function resolveBadgeSettings(snapshot: SettingsSnapshotLike | undefined): ResolvedBadgeSettings {\n return resolveFromSnapshot(snapshot)\n}","/**\n * 折叠徽标设置项的字段定义(纯逻辑,不碰 React / 宿主组件)。\n *\n * 官方设置卡片的模型(`SettingsFormModel`)把每个字段都当**草稿文本**处理:控件读\n * `format(存储值)` 得到文本,用户编辑后 `parse(文本)` 决定这次保存写什么。布尔字段\n * 没有现成的官方 spec(官方只提供 `settingsTextField` / `settingsNumberField`),所以\n * 这里按同一契约写一份:文本就是 schema 的布尔字面量。\n *\n * 单独成文件是为了可测:`parse` 必须对非法草稿返回 `undefined`(模型据此把该字段标为\n * invalid 并挡住保存,而不是把畸形值写下去),`format` 必须把缺失值读成默认 `true`\n * ——与 `Config` 各字段的 schema 默认、`badge-settings.ts` 的解析同源。\n *\n * 类型从 primitives **type-only** 引入:编译期接住官方契约,运行时不留依赖,\n * 测试里也就不必把那个包(及其整棵依赖闭包)拉进来。\n */\nimport type { SettingsFieldSpec } from '@deepseek-ai/dsh-client-ui-primitives'\n\n/** 卡片字段名(与 `src/index.ts` 的 `Config` 同名同义)。 */\nexport const BADGE_FIELDS = {\n showCompletedInBadge: 'showCompletedInBadge',\n showRunningInBadge: 'showRunningInBadge',\n showPendingInBadge: 'showPendingInBadge',\n showScheduledInBadge: 'showScheduledInBadge',\n showWaitingReviewInBadge: 'showWaitingReviewInBadge',\n showHoverDetails: 'showHoverDetails',\n countThreshold: 'countThreshold',\n} as const\n\n/** 存储值解析成开关状态:只有显式 false 才是「关闭」。 */\nexport function isFieldEnabled(value: unknown): boolean {\n return value !== false\n}\n\n/**\n * 草稿文本解析成开关状态:与 {@link isFieldEnabled} 不同,这里比较的是模型给的\n * **文本**,别把字符串喂给上面那个函数(`'false' !== false` 恒真)。\n */\nexport function isDraftEnabled(text: string): boolean {\n return text !== 'false'\n}\n\n/**\n * 构造一个布尔字段的字段转换规格。\n *\n * `parse` 只接受 `'true'` / `'false'`:空串、任意其它文本都返回 `undefined`,\n * 让模型把字段判为 invalid 并拒绝保存(官方模型的既定行为)。\n *\n * @param field - 字段名(与 Config 同名)。\n * @param defaultValue - 缺失值时的默认(true = 默认显示,false = 默认隐藏)。\n */\nfunction makeBooleanField(field: string, defaultValue: boolean): SettingsFieldSpec {\n return {\n field,\n format: value => {\n const enabled = value === undefined || value === null || typeof value !== 'boolean'\n ? defaultValue\n : value\n return enabled ? 'true' : 'false'\n },\n parse: text =>\n text === 'true' ? { kind: 'set', value: true }\n : text === 'false' ? { kind: 'set', value: false }\n : undefined,\n }\n}\n\n/** 各字段的字段转换规格。 */\nexport const showCompletedField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showCompletedInBadge, true)\nexport const showRunningField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showRunningInBadge, true)\nexport const showPendingField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showPendingInBadge, true)\nexport const showScheduledField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showScheduledInBadge, true)\nexport const showWaitingReviewField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showWaitingReviewInBadge, true)\nexport const showHoverDetailsField: SettingsFieldSpec = makeBooleanField(BADGE_FIELDS.showHoverDetails, true)\nexport const countThresholdField: SettingsFieldSpec = {\n field: BADGE_FIELDS.countThreshold,\n format: value => {\n const n = value === undefined || value === null || typeof value !== 'number' || !Number.isFinite(value)\n ? 2\n : Math.floor(value)\n return String(n < 0 ? 0 : n)\n },\n parse: text => {\n const n = Number(text)\n if (!Number.isFinite(n) || n < 0 || n !== Math.floor(n)) return undefined\n return { kind: 'set', value: n }\n },\n}\n\n/** 所有字段规格(按卡片渲染顺序)。 */\nexport const ALL_BADGE_FIELDS: SettingsFieldSpec[] = [\n showCompletedField,\n showRunningField,\n showPendingField,\n showScheduledField,\n showWaitingReviewField,\n showHoverDetailsField,\n countThresholdField,\n]\n","/**\n * 折叠徽标的设置卡片:插件 → dsh-group-status(bundle 详情页的配置表单)。\n *\n * 为什么需要这张卡片:0.2.0 起宿主把插件 `Config`(`src/index.ts`,根节点\n * `.volatile()`)投影到客户端 `configForms` 服务上,但**不会**自动把表单画进\n * 「插件」页——插件页只在客户端往 `plugins.bundle.config` 注册了卡片时才渲染\n * (见 dsh-later / dsh-gitea-dispatch 的同款做法)。没有它,README「设置项」一节\n * 描述的配置表单在 GUI 里根本不存在。\n *\n * 视觉与交互**不自造**,全部交给官方组件(`@deepseek-ai/dsh-client-ui-primitives`):\n * - `SettingsForm`:表单框架——只读提示、不可用提示、保存按钮、失败行、间距;\n * - `SettingsFormModel`:分步草稿与保存(revision 围栏、宿主拒绝时不丢草稿);\n * - `Switch`:开关本体。\n * 官方设置页(设置 → 内置插件 → 子智能体 / 网页搜索)用的就是这三件,本卡片的\n * 类名与取值也逐条对齐它们的 CSS(见 `BadgeSettingsCard.module.css` 头部)。\n *\n * 字段定义在 `badge-field.ts`(纯逻辑,可单测);这里只管把它们接到模型与槽位上。\n */\nimport { useEffect, useId, useMemo, useSyncExternalStore } from 'react'\nimport type { JSX } from 'react'\nimport {\n SettingsForm,\n SettingsFormModel,\n Switch,\n type SettingsFormLabels,\n type SettingsFormScope,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { ALL_BADGE_FIELDS, BADGE_FIELDS, isDraftEnabled } from './badge-field.ts'\nimport type { WorkspaceKey } from './locales.ts'\nimport css from './BadgeSettingsCard.module.css'\n\n/**\n * 卡片 props:宿主设置表单 + 本命名空间文案取值器。\n *\n * `scope` 直接用官方 `SettingsFormScope`(= `configForms.get(条目 id)` 的运行时形状:\n * `getSnapshot` / `subscribe` / `mutate`),因此不需要本地复刻契约,也就不会与宿主漂移。\n * `locale: NS` 由框架按声明注入 `t`。\n */\nexport interface BadgeSettingsCardProps {\n readonly scope: SettingsFormScope<Record<string, unknown>>\n readonly t: (key: WorkspaceKey) => string\n}\n\n/**\n * 渲染折叠徽标的设置表单。\n *\n * 模型与投影都按 `scope` 记忆:宿主换一份表单(条目重新服务)时整体重建,旧模型\n * 在 effect 清理里 `dispose()`,不会留下悬挂订阅。\n * @param props - 宿主设置表单与文案取值器。\n * @returns 官方表单框架包着本插件的开关字段。\n */\nexport function BadgeSettingsCard({ scope, t }: BadgeSettingsCardProps): JSX.Element {\n const model = useMemo(\n () => new SettingsFormModel<Record<string, unknown>>(scope, ALL_BADGE_FIELDS),\n [scope],\n )\n useEffect(() => () => { model.dispose() }, [model])\n // 投影:框架状态 + 所有字段的草稿。模型的 publish 会在宿主折叠或草稿变化时重算。\n const store = useMemo(\n () => model.bind(() => ({\n ...model.shell(),\n fields: ALL_BADGE_FIELDS.map(spec => ({ field: spec.field, text: model.field(spec.field).text })),\n })),\n [model],\n )\n const state = useSyncExternalStore(store.subscribe, store.getSnapshot)\n const actions = useMemo(() => model.actions(), [model])\n const badgeSectionId = useId()\n const hoverSectionId = useId()\n const countSectionId = useId()\n\n const labels: SettingsFormLabels = {\n unavailable: t('settings.unavailable'),\n readOnly: t('settings.readOnly'),\n saveFailed: t('settings.saveFailed'),\n save: t('settings.save'),\n saving: t('settings.saving'),\n }\n\n // 按字段名查草稿文本。\n const fieldText = (field: string): string => {\n const found = state.fields.find(f => f.field === field)\n return found?.text ?? 'true'\n }\n\n return (\n <SettingsForm\n labels={labels}\n state={state}\n onSave={() => { actions.save() }}\n onDiscard={() => { actions.discard() }}\n >\n <section className={css.section} aria-labelledby={badgeSectionId}>\n <h3 className={css.heading} id={badgeSectionId}>{t('settings.badge.section')}</h3>\n <ToggleRow field={BADGE_FIELDS.showRunningInBadge} text={fieldText(BADGE_FIELDS.showRunningInBadge)} label={t('settings.badge.showRunning')} hint={t('settings.badge.showRunningHint')} state={state} actions={actions} />\n <ToggleRow field={BADGE_FIELDS.showPendingInBadge} text={fieldText(BADGE_FIELDS.showPendingInBadge)} label={t('settings.badge.showPending')} hint={t('settings.badge.showPendingHint')} state={state} actions={actions} />\n <ToggleRow field={BADGE_FIELDS.showCompletedInBadge} text={fieldText(BADGE_FIELDS.showCompletedInBadge)} label={t('settings.badge.showCompleted')} hint={t('settings.badge.showCompletedHint')} state={state} actions={actions} />\n <ToggleRow field={BADGE_FIELDS.showScheduledInBadge} text={fieldText(BADGE_FIELDS.showScheduledInBadge)} label={t('settings.badge.showScheduled')} hint={t('settings.badge.showScheduledHint')} state={state} actions={actions} />\n <ToggleRow field={BADGE_FIELDS.showWaitingReviewInBadge} text={fieldText(BADGE_FIELDS.showWaitingReviewInBadge)} label={t('settings.badge.showWaitingReview')} hint={t('settings.badge.showWaitingReviewHint')} state={state} actions={actions} />\n </section>\n <section className={css.section} aria-labelledby={hoverSectionId}>\n <h3 className={css.heading} id={hoverSectionId}>{t('settings.hover.section')}</h3>\n <ToggleRow field={BADGE_FIELDS.showHoverDetails} text={fieldText(BADGE_FIELDS.showHoverDetails)} label={t('settings.hover.showDetails')} hint={t('settings.hover.showDetailsHint')} state={state} actions={actions} />\n </section>\n <section className={css.section} aria-labelledby={countSectionId}>\n <h3 className={css.heading} id={countSectionId}>{t('settings.count.section')}</h3>\n <NumberRow field={BADGE_FIELDS.countThreshold} text={fieldText(BADGE_FIELDS.countThreshold)} label={t('settings.count.threshold')} hint={t('settings.count.thresholdHint')} state={state} actions={actions} />\n </section>\n </SettingsForm>\n )\n}\n\n/** 单行开关:label + Switch + hint。 */\nfunction ToggleRow({ field, text, label, hint, state, actions }: {\n field: string\n text: string\n label: string\n hint: string\n state: { writable: boolean; saving: boolean }\n actions: { edit: (field: string, value: string) => void }\n}): JSX.Element {\n return (\n <div className={css.badgeField}>\n <div className={css.badgeToggleRow}>\n <span className={css.badgeToggleLabel}>{label}</span>\n <Switch\n checked={isDraftEnabled(text)}\n label={label}\n disabled={!state.writable || state.saving}\n onChange={next => { actions.edit(field, next ? 'true' : 'false') }}\n />\n </div>\n <p className={css.hint}>{hint}</p>\n </div>\n )\n}\n\n/** 单行数字输入:label + 带加减按钮的数字输入 + hint。 */\nfunction NumberRow({ field, text, label, hint, state, actions }: {\n field: string\n text: string\n label: string\n hint: string\n state: { writable: boolean; saving: boolean }\n actions: { edit: (field: string, value: string) => void }\n}): JSX.Element {\n const disabled = !state.writable || state.saving\n const currentValue = Number(text) || 0\n const decrement = () => { if (!disabled && currentValue > 0) actions.edit(field, String(currentValue - 1)) }\n const increment = () => { if (!disabled) actions.edit(field, String(currentValue + 1)) }\n return (\n <div className={css.badgeField}>\n <div className={css.badgeToggleRow}>\n <span className={css.badgeToggleLabel}>{label}</span>\n <div className={css.badgeNumberControl}>\n <button\n type=\"button\"\n className={css.badgeNumberButton}\n disabled={disabled || currentValue <= 0}\n onClick={decrement}\n aria-label=\"减少\"\n >\n −\n </button>\n <span className={css.badgeNumberValue}>{text}</span>\n <button\n type=\"button\"\n className={css.badgeNumberButton}\n disabled={disabled}\n onClick={increment}\n aria-label=\"增加\"\n >\n +\n </button>\n </div>\n </div>\n <p className={css.hint}>{hint}</p>\n </div>\n )\n}\n","//#region lib/types/index.js\n/** Duplicate-install-safe JSON and immutable-value helpers. @module @deepseek-ai/dsh-util-values */\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n\tconst rendered = JSON.stringify(value) ?? String(value);\n\tthrow new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype has a native constructor matching this engine's representation. */\nfunction hasIntrinsicConstructor(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name === \"Array\" ? Array : Object);\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n\tconst keys = Reflect.ownKeys(value);\n\tif (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n\treturn keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n\tconst ancestors = /* @__PURE__ */ new Set();\n\tlet root;\n\tconst assign = (destination, item) => {\n\t\tif (destination === void 0) return;\n\t\tif (destination.kind === \"root\") root = item;\n\t\telse if (destination.kind === \"array\") destination.target[destination.index] = item;\n\t\telse Object.defineProperty(destination.target, destination.key, {\n\t\t\tvalue: item,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t\twritable: true\n\t\t});\n\t};\n\tconst tasks = [{\n\t\tkind: \"visit\",\n\t\tvalue,\n\t\t...detach ? { destination: { kind: \"root\" } } : {}\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tancestors.delete(task.source);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"array-item\") {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.index],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"array\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tindex: task.index\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-property\") {\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.key],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"object\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tkey: task.key\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst current = task.value;\n\t\tif (current === null) {\n\t\t\tassign(task.destination, null);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"boolean\" || typeof current === \"string\") {\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"number\") {\n\t\t\tif (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current !== \"object\") return void 0;\n\t\tif (ancestors.has(current)) return void 0;\n\t\tif (Array.isArray(current)) {\n\t\t\tif (!hasPlainArrayPrototype(current)) return void 0;\n\t\t\tconst length = current.length;\n\t\t\tif (Reflect.ownKeys(current).length !== length + 1) return void 0;\n\t\t\tconst target = detach ? [] : void 0;\n\t\t\tif (target !== void 0) assign(task.destination, target);\n\t\t\tancestors.add(current);\n\t\t\ttasks.push({\n\t\t\t\tkind: \"leave\",\n\t\t\t\tsource: current\n\t\t\t});\n\t\t\tfor (let index = length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"array-item\",\n\t\t\t\tsource: current,\n\t\t\t\tindex,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasPlainObjectPrototype(current)) return void 0;\n\t\tconst keys = enumerableStringKeys(current);\n\t\tif (keys === void 0) return void 0;\n\t\tconst target = detach ? {} : void 0;\n\t\tif (target !== void 0) assign(task.destination, target);\n\t\tancestors.add(current);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tsource: current\n\t\t});\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"object-property\",\n\t\t\t\tsource: current,\n\t\t\t\tkey,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t}\n\t}\n\treturn detach ? root : true;\n}\n/**\n* Validate and detach lossless JSON in one read per property.\n* @param value - candidate value to validate and detach.\n* @returns the detached snapshot, or `undefined` when the value is not losslessly JSON-serializable.\n*/\nfunction snapshotJsonValue(value) {\n\treturn walkJsonValue(value, true);\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n\treturn walkJsonValue(value, false) === true;\n}\n/**\n* Compare JSON-compatible values structurally.\n* @param a - one JSON-compatible value.\n* @param b - the other JSON-compatible value.\n* @returns whether both values contain the same JSON data.\n*/\nfunction deepEqualJson(a, b) {\n\tif (a === b) return true;\n\tif (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false;\n\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\tif (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n\t\treturn a.every((entry, index) => deepEqualJson(entry, b[index]));\n\t}\n\tconst left = a;\n\tconst right = b;\n\tconst keys = Object.keys(left);\n\tif (keys.length !== Object.keys(right).length) return false;\n\treturn keys.every((key) => key in right && deepEqualJson(left[key], right[key]));\n}\n/**\n* Deep-freeze an object graph in place while leaving live AbortSignal objects mutable.\n* @param value - value to freeze.\n* @returns the same value after every reachable enumerable child is frozen.\n*/\nfunction deepFreeze(value) {\n\tconst seen = /* @__PURE__ */ new WeakSet();\n\tconst pending = [{\n\t\tkind: \"visit\",\n\t\tnode: value\n\t}];\n\twhile (pending.length > 0) {\n\t\tconst task = pending.pop();\n\t\t/* v8 ignore next -- the loop condition guarantees one pending task. */\n\t\tif (task === void 0) continue;\n\t\tif (task.kind === \"property\") {\n\t\t\tpending.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tnode: task.source[task.key]\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst node = task.node;\n\t\tif (node === null || typeof node !== \"object\") continue;\n\t\tif (node instanceof AbortSignal) continue;\n\t\tif (seen.has(node)) continue;\n\t\tseen.add(node);\n\t\tObject.freeze(node);\n\t\tconst keys = Object.keys(node);\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) continue;\n\t\t\tpending.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tsource: node,\n\t\t\t\tkey\n\t\t\t});\n\t\t}\n\t}\n\treturn value;\n}\n/**\n* Weak-key lookup with a strongly retained iterable set of associated values.\n*\n* Each value must belong to only one key. The container performs no automatic\n* cleanup; owners delete associations or clear the container at lifecycle end.\n*/\nvar WeakMapWithValues = class {\n\tkeys = /* @__PURE__ */ new WeakMap();\n\tvalueSet = /* @__PURE__ */ new Set();\n\t/** Live strongly retained values in insertion order. */\n\tvalues = this.valueSet;\n\t/**\n\t* Read the value associated with a key.\n\t* @param key - weakly held lookup key.\n\t* @returns the associated value, or absence.\n\t*/\n\tget(key) {\n\t\treturn this.keys.get(key);\n\t}\n\t/**\n\t* Test whether a key has an association.\n\t* @param key - weakly held lookup key.\n\t* @returns whether the key is present.\n\t*/\n\thas(key) {\n\t\treturn this.keys.has(key);\n\t}\n\t/**\n\t* Associate one key with one caller-unique value.\n\t* @param key - weakly held lookup key.\n\t* @param value - strongly retained value that belongs to no other key.\n\t* @returns this container.\n\t*/\n\tset(key, value) {\n\t\tif (this.keys.has(key)) {\n\t\t\tconst previous = this.keys.get(key);\n\t\t\tif (previous === value) return this;\n\t\t\tthis.valueSet.delete(previous);\n\t\t}\n\t\tthis.keys.set(key, value);\n\t\tthis.valueSet.add(value);\n\t\treturn this;\n\t}\n\t/**\n\t* Remove one association and its strongly retained value.\n\t* @param key - weakly held lookup key.\n\t* @returns whether an association was removed.\n\t*/\n\tdelete(key) {\n\t\tif (!this.keys.has(key)) return false;\n\t\tconst value = this.keys.get(key);\n\t\tconst deleted = this.keys.delete(key);\n\t\tthis.valueSet.delete(value);\n\t\treturn deleted;\n\t}\n\t/** Remove every association and strongly retained value. */\n\tclear() {\n\t\tthis.keys = /* @__PURE__ */ new WeakMap();\n\t\tthis.valueSet.clear();\n\t}\n};\n//#endregion\nexport { WeakMapWithValues, assertNever, deepEqualJson, deepFreeze, isJsonValue, snapshotJsonValue };\n","//#region lib/types/file-address.js\n/**\n* The `dsh-resource://file/…` address grammar: how a file is named across the\n* Sidebar and the resource model, built and parsed without touching a\n* filesystem.\n* @module\n*/\n/** The scheme and type every file address opens with. */\nconst FILE_ADDRESS_PREFIX = \"dsh-resource://file/\";\n/** Component-encode one id or path segment, keeping `:` literal for drive letters. */\nfunction encodeSegment(segment) {\n\treturn encodeURIComponent(segment).replace(/%3A/gi, \":\");\n}\n/** Encode a `/`-separated path segment by segment. */\nfunction encodePath(path) {\n\treturn path.split(\"/\").map(encodeSegment).join(\"/\");\n}\n/** Whether a decoded first path segment is a Windows drive (`C:`). */\nfunction isDriveSegment(segment) {\n\treturn segment !== void 0 && /^[A-Za-z]:$/.test(segment);\n}\n/**\n* Build the address of a file read through one Session.\n* @param sessionId - the Session whose Host workspace resolves the path.\n* @param path - absolute or workspace-relative path; backslashes are normalized to `/`, and leading `./` prefixes are dropped.\n* @returns the `dsh-resource://file/session/<sessionId>/<path>` address.\n*/\nfunction sessionFileAddress(sessionId, path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\").replace(/^(?:\\.\\/)+/, \"\");\n\treturn `${FILE_ADDRESS_PREFIX}session/${encodeSegment(sessionId)}/${encodePath(normalized)}`;\n}\n/**\n* Build the address of a file by its absolute path.\n* @param path - absolute path; backslashes are normalized to `/` and the leading `/` is dropped,\n* except that a UNC path (`\\\\server\\share`) keeps one empty first segment.\n* @returns the `dsh-resource://file/absolute/<path>` address.\n*/\nfunction absoluteFileAddress(path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\");\n\tconst unc = normalized.startsWith(\"//\");\n\tconst absolute = normalized.replace(/^\\/+/, \"\");\n\treturn `${FILE_ADDRESS_PREFIX}absolute/${unc ? \"/\" : \"\"}${encodePath(absolute)}`;\n}\n/**\n* Read a file address back into its parts without resolving `.` or `..`.\n* Query and fragment suffixes are ignored; encoded path segments are decoded.\n* @param address - a candidate address.\n* @returns the parts, or `undefined` when the string is not a `dsh-resource://file/` URI in a known scope with a path, or a segment is not validly encoded.\n*/\nfunction parseFileAddress(address) {\n\ttry {\n\t\tif (!address.startsWith(FILE_ADDRESS_PREFIX)) return void 0;\n\t\tconst end = address.search(/[?#]/);\n\t\tconst [scope, ...rest] = address.slice(20, end === -1 ? void 0 : end).split(\"/\");\n\t\tif (scope === \"session\") {\n\t\t\tconst [id, ...segments] = rest;\n\t\t\tif (id === void 0 || id === \"\" || segments.length === 0) return void 0;\n\t\t\treturn {\n\t\t\t\tscope,\n\t\t\t\tsessionId: decodeURIComponent(id),\n\t\t\t\tpath: segments.map(decodeURIComponent).join(\"/\")\n\t\t\t};\n\t\t}\n\t\tif (scope === \"absolute\") {\n\t\t\tconst unc = rest[0] === \"\" && rest.length > 1;\n\t\t\tconst segments = (unc ? rest.slice(1) : rest).map(decodeURIComponent);\n\t\t\tif (segments.length === 0 || segments[0] === \"\") return void 0;\n\t\t\tif (unc) return {\n\t\t\t\tscope,\n\t\t\t\tpath: `//${segments.join(\"/\")}`\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tscope,\n\t\t\t\tpath: isDriveSegment(segments[0]) ? segments.join(\"/\") : `/${segments.join(\"/\")}`\n\t\t\t};\n\t\t}\n\t\treturn;\n\t} catch {\n\t\treturn;\n\t}\n}\n//#endregion\n//#region lib/types/index.js\n/**\n* Browser-safe Workspace path and display helpers.\n* @module @deepseek-ai/dsh-util-workspace-path\n*/\n/** Whether a path uses a Windows drive or UNC prefix. */\nfunction isWindowsStylePath(value) {\n\treturn /^[A-Za-z]:[/\\\\]/.test(value) || value.startsWith(\"\\\\\\\\\");\n}\n/**\n* Whether a path is absolute in either spelling the Host accepts: POSIX (`/a/b`) or Windows drive or UNC.\n* @param path - the path to classify.\n* @returns `true` for an absolute path; `false` for a Workspace-relative one.\n*/\nfunction isAbsoluteWorkspacePath(path) {\n\treturn path.startsWith(\"/\") || isWindowsStylePath(path);\n}\n/**\n* Resolve a Workspace-relative path into the Host-facing spelling used by path operations.\n* @param cwd - Session Workspace root, when known.\n* @param path - Absolute or Workspace-relative path.\n* @returns an absolute path when a Workspace root is available, otherwise the original path.\n*/\nfunction resolveWorkspacePath(cwd, path) {\n\tif (isAbsoluteWorkspacePath(path)) return path;\n\tif (cwd === void 0 || cwd === \"\") return path;\n\tconst separator = isWindowsStylePath(cwd) && cwd.includes(\"\\\\\") ? \"\\\\\" : \"/\";\n\treturn `${cwd.replace(/[/\\\\]+$/, \"\")}${separator}${path.replace(/^[/\\\\]+/, \"\")}`;\n}\n/**\n* Abbreviate a POSIX home directory for display.\n* @param path - Absolute or already-short display path.\n* @param home - Host account home; absent skips abbreviation.\n* @returns `~` or `~/…` for the POSIX home and its descendants, otherwise `path`.\n*/\nfunction abbreviateHomePath(path, home) {\n\tif (home === void 0 || home === \"\") return path;\n\tif (isWindowsStylePath(path) || isWindowsStylePath(home)) return path;\n\tconst root = home.replace(/\\/+$/, \"\");\n\tif (root === \"\" || root === \"/\") return path;\n\tif (path.replace(/\\/+$/, \"\") === root) return \"~\";\n\tif (path.startsWith(`${root}/`)) return `~${path.slice(root.length)}`;\n\treturn path;\n}\n/**\n* Read the final non-empty segment of a Workspace path for display.\n* Workspace-label surfaces use this helper instead of deriving another basename.\n* @param path - Workspace directory path using POSIX or Windows separators.\n* @returns the final segment, or an empty string for a separator-only path.\n*/\nfunction workspaceTitleOf(path) {\n\tconst trimmed = path.replace(/[/\\\\]+$/, \"\");\n\tconst separator = Math.max(trimmed.lastIndexOf(\"/\"), trimmed.lastIndexOf(\"\\\\\"));\n\treturn trimmed.slice(separator + 1);\n}\n/**\n* Split a path for display: the directories through their last separator, and\n* the final segment after it. Both `/` and `\\` separate, so a Windows path\n* splits where its own segments end; trailing separators are dropped first, so\n* a directory path names its own last segment. A path with no separator, or a\n* separator-only path, is all name.\n* @param path - file or directory path using POSIX or Windows separators.\n* @returns the directory prefix (possibly empty) and the final segment.\n*/\nfunction pathPartsOf(path) {\n\tconst trimmed = path.replace(/[/\\\\]+$/, \"\");\n\tif (trimmed === \"\") return {\n\t\tdirectory: \"\",\n\t\tname: path\n\t};\n\tconst cut = Math.max(trimmed.lastIndexOf(\"/\"), trimmed.lastIndexOf(\"\\\\\")) + 1;\n\treturn {\n\t\tdirectory: trimmed.slice(0, cut),\n\t\tname: trimmed.slice(cut)\n\t};\n}\n/**\n* The address for a path as a caller holds it: a relative path, or an absolute\n* path inside the Session's workspace, becomes a `session`-scoped address; an\n* absolute path outside it, or one whose workspace root is unknown, keeps its\n* absolute path in that Session's address.\n* @param sessionId - the Session the path is read in.\n* @param cwd - that Session's workspace root, when known.\n* @param path - absolute or workspace-relative path, in either separator spelling.\n* @returns the `dsh-resource://file/…` address.\n*/\nfunction fileAddressFor(sessionId, cwd, path) {\n\tconst normalized = path.replace(/\\\\/g, \"/\");\n\tif (!isAbsoluteWorkspacePath(normalized)) return sessionFileAddress(sessionId, normalized);\n\tconst root = cwd === void 0 ? \"\" : cwd.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n\tif (root !== \"\" && normalized === root) return sessionFileAddress(sessionId, \"\");\n\tif (root !== \"\" && normalized.startsWith(`${root}/`)) return sessionFileAddress(sessionId, normalized.slice(root.length + 1));\n\treturn sessionFileAddress(sessionId, normalized);\n}\n/**\n* Strip the workspace root from a workspace-rooted absolute path (display only).\n* @param text - the path to shorten.\n* @param cwd - session workspace root; absent or empty leaves the path unchanged.\n* @returns the path relative to the workspace root, or unchanged when it is not rooted there.\n*/\nfunction relativizeToCwd(text, cwd) {\n\tif (cwd === void 0 || cwd === \"\") return text;\n\tconst root = cwd.replace(/[/\\\\]+$/, \"\");\n\tif (text.startsWith(`${root}/`) || text.startsWith(`${root}\\\\`)) return text.slice(root.length + 1);\n\treturn text;\n}\n/**\n* Address a decoded absolute file path through the authenticated file route.\n* @param base - HTTP(S) application base, including its deployment prefix, or `dsh-app://app/`.\n* @param path - Native file path; URL escapes in authored Markdown must already be decoded.\n* @returns File URL, or undefined for unsupported transports and non-absolute paths.\n*/\nfunction fileMediaUrl(base, path) {\n\tif (!/^https?:/u.test(base) && !base.startsWith(\"dsh-app://app/\") || !isAbsoluteWorkspacePath(path) || /^[/\\\\]{2}/u.test(path) || /[\\u0000-\\u001f\\u007f]/u.test(path)) return void 0;\n\treturn new URL(`api/file?path=${encodeURIComponent(path)}`, base).href;\n}\n//#endregion\nexport { abbreviateHomePath, absoluteFileAddress, fileAddressFor, fileMediaUrl, isAbsoluteWorkspacePath, parseFileAddress, pathPartsOf, relativizeToCwd, resolveWorkspacePath, sessionFileAddress, workspaceTitleOf };\n","/**\n * Derives the workspace browser tree from caller-projected Workspace and\n * Session order. Unassigned Sessions trail under Ungrouped; only the selected\n * blank Session remains visible.\n */\nimport {\n type SessionListState, type SessionSearchResultItem, type SessionSummary,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {\n SessionStatusSnapshot,\n} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { assertNever } from '@deepseek-ai/dsh-util-values'\nimport { workspaceTitleOf } from '@deepseek-ai/dsh-util-workspace-path'\n// Fork-owned: `GroupLiveStatus` lives in ./group-status.ts and is re-exported here so\n// the vendored row components can keep importing every group type from one module.\n// Nothing else is re-exported: the status computation has no reason to pass through\n// this file, and the cross-plugin summary types had no consumers at all.\nimport type { GroupLiveStatus } from './group-status.ts'\n\nexport type { GroupLiveStatus }\n\n/** Group key for Sessions outside every Workspace. */\nexport const UNGROUPED_KEY = ''\n\n/**\n * Resolve the Workspace browser group that owns one Session.\n * @param workspaces - authoritative Workspace membership.\n * @param sessionId - Session whose browser group is required.\n * @returns owning Workspace id, or {@link UNGROUPED_KEY} when no Workspace accounts for it.\n */\nexport function owningGroupKey(\n workspaces: readonly WorkspaceView[],\n sessionId: SessionId,\n): string {\n return (workspaces.find(workspace => workspace.sessionIds.includes(sessionId))\n ?.workspaceId as string | undefined) ?? UNGROUPED_KEY\n}\n\n/** Pending interaction kinds with dedicated Workspace-row presentation. */\nexport type SessionPendingInteractionStatus = 'approval' | 'plan-review' | 'question'\ntype SessionStatuses = SessionStatusSnapshot\n\nfunction mainSessionId(list: SessionListState): SessionId | undefined {\n return Object.values(list.byId)\n .find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n}\n\n/** One top-level session row in a group or the flat list. */\nexport interface SessionNode {\n id: SessionId\n /** Stored title, or empty; the renderer localizes blank and unnamed row labels. */\n title: string\n /** The provisional blank session (renderer shows the localized New Session title). */\n blank: boolean\n /** A Session-scoped UI consumer is awaiting this user. */\n pendingInteraction?: SessionPendingInteractionStatus\n running: boolean\n /** Running direct children in the loaded subagent catalog. */\n runningSubagentCount: number\n /** Finished running while not selected and not yet opened (the green \"done\" reminder dot). */\n completed: boolean\n /** In the registry-global pin set: leads its section, reorderable only among pinned rows. */\n pinned: boolean\n /** In the registry-global archive set: shown grayed in place and not openable. */\n archived: boolean\n updatedAt: number\n}\n\n/** Session order selected by the Workspace browser. */\nexport type SessionOrderBy = 'manual' | 'updated'\n\n// ── Group node shapes ──\n// The live-status computation this fork adds lives entirely in ./group-status.ts;\n// only its `GroupLiveStatus` type is re-exported above. Keeping it in a separate\n// file minimises the upstream diff surface.\n\n/** One workspace group section: header row facts + visible top-level session rows. */\nexport interface GroupNode {\n /** Group key: the workspace id or {@link UNGROUPED_KEY}. */\n key: string\n /** Backing Workspace id; absent only for the ungrouped bucket. */\n workspaceId: WorkspaceId | undefined\n cwd: string | undefined\n /** Workspace creation time (epoch ms); absent only for the ungrouped bucket. */\n createdAt: number | undefined\n label: string\n /** Total visible sessions in the group. */\n sessionCount: number\n expanded: boolean\n /** The group contains the selected session (active folder tint; supplied here so the renderer never scans). */\n containsCurrent: boolean\n /** Aggregated member status; computed externally by HOC in WorkspaceBrowser.tsx. */\n liveStatus?: GroupLiveStatus\n /** Visible session rows (empty while the group is folded). */\n sessions: readonly SessionNode[]\n}\n\n/** One flat search row combining list metadata with an optional content match. */\nexport interface SearchResultNode {\n id: SessionId\n title: string\n workspace: string\n /** A Session-scoped UI consumer is awaiting this user. */\n pendingInteraction?: SessionPendingInteractionStatus\n running: boolean\n /** Running direct children in the loaded subagent catalog. */\n runningSubagentCount: number\n /** Finished running while not selected and not yet opened (the green \"done\" reminder dot). */\n completed: boolean\n /** In the registry-global archive set: shown grayed and not openable. */\n archived: boolean\n snippet?: string\n}\n\n/** Bounded merged search projection plus the refine-query hint bit. */\nexport interface SearchResultSet {\n items: readonly SearchResultNode[]\n hasMore: boolean\n}\n\n/** Viewing state consumed by the derivation. */\nexport interface TreeView {\n expandedGroups: readonly string[]\n /** Browser-local order for Sessions without a backing Workspace account. */\n ungroupedOrder?: readonly string[]\n}\n\ninterface Group {\n key: string\n workspaceId: WorkspaceId | undefined\n cwd: string | undefined\n createdAt: number | undefined\n label: string\n sessions: SessionSummary[]\n}\n\n/**\n * Directory display label: basename of the path (both separators accepted).\n * Ungrouped-bucket fallback for surfaces without a workspace title.\n * @param cwd - directory path, or undefined for the ungrouped bucket.\n * @returns basename, the raw cwd when it has no basename, or an empty ungrouped marker.\n */\nexport function workspaceLabel(cwd: string | undefined): string {\n if (cwd === undefined || cwd === '') return ''\n const base = workspaceTitleOf(cwd)\n return base !== '' ? base : cwd\n}\n\n/**\n * Project known account members by current Session recency.\n * @param sessionIds - authoritative account membership.\n * @param summaries - current Session summaries; members without a summary are omitted until it arrives.\n * @returns known members newest first, with Session identity as the deterministic tie-break.\n */\nexport function orderByRecency(\n sessionIds: readonly SessionId[],\n summaries: SessionListState['byId'],\n): SessionId[] {\n return sessionIds.flatMap((id) => {\n const summary = summaries[id]\n if (summary === undefined) return []\n return [{ id, rank: summary.updatedAt }]\n })\n .sort((a, b) => {\n if (a.rank !== b.rank) return b.rank - a.rank\n return a.id < b.id ? -1 : 1\n })\n .map(member => member.id)\n}\n\n/**\n * Reconcile a browser-local manual order with current account membership.\n * New ordinary forks precede their sources without changing saved entries' relative order.\n * @param memberIds - authoritative account membership.\n * @param savedOrder - previously saved browser-local order.\n * @param summaries - current Session metadata; unknown new members wait for their summaries.\n * @param rowState - global pin and archive membership; only account members can supplement the order.\n * @returns saved relative positions plus missing members ordered by pin, fork source, recency, and archive status.\n */\nexport function reconcileManualOrder(\n memberIds: readonly SessionId[],\n savedOrder: readonly string[] | undefined,\n summaries: SessionListState['byId'],\n rowState?: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>,\n): SessionId[] {\n const members = new Map(memberIds.map(id => [id as string, id]))\n const included = new Set<string>()\n const ordered: SessionId[] = []\n for (const key of savedOrder ?? []) {\n const id = members.get(key)\n if (id === undefined || included.has(key)) continue\n ordered.push(id)\n included.add(key)\n }\n const archived = new Set(rowState?.archivedSessionIds)\n const pins: SessionId[] = []\n for (const sessionId of rowState?.pinnedSessionIds ?? []) {\n const id = members.get(sessionId)\n if (id === undefined || included.has(id) || archived.has(id) || summaries[id] === undefined) continue\n pins.push(id)\n included.add(id)\n }\n const ordinary: SessionId[] = []\n const archives: SessionId[] = []\n for (const id of orderByRecency([...members.values()].filter(id => !included.has(id)), summaries)) {\n if (archived.has(id)) archives.push(id)\n else ordinary.push(id)\n }\n const result = [...pins, ...ordered, ...ordinary, ...archives]\n const pending = new Set(ordinary)\n const placeFork = (id: SessionId): void => {\n if (!pending.delete(id)) return\n const parentId = summaries[id]?.parentId\n if (parentId === undefined || parentId === id || !result.includes(parentId)) return\n placeFork(parentId)\n result.splice(result.indexOf(id), 1)\n result.splice(result.indexOf(parentId), 0, id)\n }\n for (const id of [...ordinary].reverse()) placeFork(id)\n return result\n}\n\n/**\n * Keep the selected provisional New Session ahead of either base order.\n * @param order - recency or reconciled manual order.\n * @param currentBlank - selected blank Session in this account, when present.\n * @returns a copy with the selected blank first and no duplicate slot.\n */\nexport function pinCurrentBlank(\n order: readonly SessionId[],\n currentBlank: SessionId | undefined,\n): SessionId[] {\n if (currentBlank === undefined) return [...order]\n return [currentBlank, ...order.filter(id => id !== currentBlank)]\n}\n\n/**\n * Archived-row visibility choice: the default hides archived rows, `show`\n * mixes them into their kept slots, and `only` restricts the view (and\n * search) to archived rows.\n */\nexport type ArchivedFilter = 'default' | 'show' | 'only'\n\n/**\n * Ordinary sessions are visible; among blank sessions, only the current one\n * is visible. Subagent children use their parent header catalog; archived\n * sessions follow the archived filter, while their accounting slots remain\n * either way so unarchiving restores position.\n */\nfunction sessionVisible(\n session: SessionSummary,\n current: SessionId | undefined,\n archived: ReadonlySet<SessionId>,\n archivedFilter: ArchivedFilter,\n): boolean {\n if (session.origin === 'subagent') return false\n if (session.blank && session.id !== current) return false\n switch (archivedFilter) {\n case 'default':\n return !archived.has(session.id)\n case 'show':\n return true\n case 'only':\n return archived.has(session.id)\n /* v8 ignore next 2 -- closed-union backstop; only reached if the filter is forged */\n default:\n return assertNever(archivedFilter)\n }\n}\n\n/** Registry-global row state consumed by every tree derivation. */\nexport interface SessionRowState {\n /** Registry-global pin ids; pinned rows lead their section in the local order. */\n pinnedSessionIds: readonly SessionId[]\n /** Archive set; members keep their slots and show grayed while visible. */\n archivedSessionIds: readonly SessionId[]\n /** Archived-row visibility choice applied to lists and search alike. */\n archivedFilter: ArchivedFilter\n}\n\n/**\n * Keep the visible New Session placeholder first, then partition pinned and\n * ordinary rows without changing either partition's caller order.\n */\nfunction sectionMembers(\n members: readonly SessionSummary[],\n pinned: ReadonlySet<SessionId>,\n archived: ReadonlySet<SessionId>,\n): SessionSummary[] {\n const placeholders: SessionSummary[] = []\n const leading: SessionSummary[] = []\n const rest: SessionSummary[] = []\n for (const member of members) {\n if (member.blank) placeholders.push(member)\n else if (!archived.has(member.id) && pinned.has(member.id)) leading.push(member)\n else rest.push(member)\n }\n return [...placeholders, ...leading, ...rest]\n}\n\n/**\n * A blank session is the selected Workspace's provisional New Session row;\n * its canonical title never enters search (blank rows are query-excluded)\n * and the renderer localizes its display label. Unnamed history also yields an\n * empty title for localization and does not match a directory-name title search.\n */\nfunction sessionTitle(session: SessionSummary): string {\n return session.blank ? '' : (session.title?.trim() ?? '')\n}\n\n/** Build one group without projecting session lineage into presentation. */\nfunction buildGroup(\n key: string,\n workspaceId: WorkspaceId | undefined,\n cwd: string | undefined,\n createdAt: number | undefined,\n label: string,\n members: readonly SessionSummary[],\n): Group {\n return { key, workspaceId, cwd, createdAt, label, sessions: [...members] }\n}\n\n/** Apply a stored Ungrouped order and append newly loose Sessions by recency. */\nfunction orderedUngrouped(\n members: readonly SessionSummary[],\n stored: readonly string[] | undefined,\n summaries: SessionListState['byId'],\n): SessionSummary[] {\n const byId = new Map(members.map(session => [session.id as string, session]))\n const ids = stored === undefined\n ? orderByRecency(members.map(session => session.id), summaries)\n : reconcileManualOrder(members.map(session => session.id), stored, summaries)\n return ids.flatMap((id) => {\n const session = byId.get(id)\n /* v8 ignore next -- ids are projected exclusively from the members used to build byId. */\n return session === undefined ? [] : [session]\n })\n}\n\n/**\n * Group Sessions by Workspace: one group per caller-ordered entity, with\n * members resolved from caller-ordered sessionIds. Sessions outside every\n * Workspace trail in the browser-local Ungrouped order, which falls back to\n * recency before that order is initialized.\n */\nfunction groupByWorkspace(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archived: ReadonlySet<SessionId>,\n archivedFilter: ArchivedFilter,\n ungroupedOrder: readonly string[] | undefined,\n): Group[] {\n const current = mainSessionId(list)\n const groups: Group[] = []\n const accounted = new Set<SessionId>()\n for (const workspace of workspaces) {\n const members: SessionSummary[] = []\n for (const id of workspace.sessionIds) {\n const summary = list.byId[id]\n if (summary === undefined) continue // account may lead the list pull; the row appears when the summary lands\n accounted.add(id)\n if (!sessionVisible(summary, current, archived, archivedFilter)) continue\n members.push(summary)\n }\n // The archived-only view lists archives, not the Workspace inventory, so\n // a Workspace without archived Sessions contributes no group.\n if (archivedFilter === 'only' && members.length === 0) continue\n groups.push(buildGroup(\n workspace.workspaceId, workspace.workspaceId, workspace.path,\n Date.parse(workspace.createdAt), workspace.title, members,\n ))\n }\n const stray = list.ids\n .map(id => list.byId[id])\n .filter((s): s is SessionSummary =>\n s !== undefined && !accounted.has(s.id) && sessionVisible(s, current, archived, archivedFilter))\n if (stray.length > 0) {\n groups.push(buildGroup(\n UNGROUPED_KEY,\n undefined,\n undefined,\n undefined,\n '',\n orderedUngrouped(stray, ungroupedOrder, list.byId),\n ))\n }\n return groups\n}\n\n/** Keep navigation presentation independent from domain-owned interaction objects. */\nfunction visiblePendingKind(kind: string | undefined): SessionPendingInteractionStatus | undefined {\n switch (kind) {\n case 'approval':\n case 'plan-review':\n case 'question':\n return kind\n default:\n return undefined\n }\n}\n\nfunction runningChildCount(list: SessionListState, parentId: SessionId, statuses: SessionStatuses): number {\n return list.projectionsBySession[parentId]?.values.subagentCatalog?.reduce(\n (count, child) => count + ((statuses.get(child.id)?.running ?? list.byId[child.id]?.running) === true ? 1 : 0),\n 0,\n ) ?? 0\n}\n\nfunction sessionNode(\n s: SessionSummary,\n list: SessionListState,\n statuses: SessionStatuses,\n pinned: ReadonlySet<SessionId>,\n archived: ReadonlySet<SessionId>,\n): SessionNode {\n const status = statuses.get(s.id)\n const pendingInteraction = visiblePendingKind(status?.pendingInteraction?.kind)\n return {\n id: s.id,\n title: sessionTitle(s),\n blank: s.blank,\n running: status?.running ?? s.running,\n runningSubagentCount: runningChildCount(list, s.id, statuses),\n completed: status?.completionUnread === true,\n pinned: !archived.has(s.id) && pinned.has(s.id),\n archived: archived.has(s.id),\n updatedAt: s.updatedAt,\n ...(pendingInteraction === undefined ? {} : { pendingInteraction }),\n }\n}\n\n/**\n * Derive the workspace browser groups with every session as a top-level row.\n *\n * Every group shows, except that the archived-only filter drops groups\n * without visible members; sessions populate under expanded groups with\n * pinned rows leading in the selected local order. Blank sessions are\n * excluded except for the selected provisional New Session row; archived\n * sessions keep their slots and appear per the archived filter. Content\n * search lives outside this derivation (see {@link deriveSearchResults}).\n * @param list - sessions list snapshot (`mainView` retention feeds containsCurrent).\n * @param workspaces - real Workspaces in Host group order with caller-projected Session order.\n * @param rowState - registry-global pin and archive sets plus the archived filter.\n * @param statuses - unified UI status by Session.\n * @param view - local expansion arrays.\n * @param waitingReviewSummary - dsh-gitea-dispatch waiting map (session id → waiting entry).\n * @param scheduleSummary - dsh-later schedule map (session id → schedule entry).\n * @returns group sections in render order.\n */\nexport function deriveGroups(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n rowState: SessionRowState,\n statuses: SessionStatuses,\n view: TreeView,\n): GroupNode[] {\n const archived = new Set(rowState.archivedSessionIds)\n const pinned = new Set(rowState.pinnedSessionIds)\n const expandedGroups = new Set(view.expandedGroups)\n const current = mainSessionId(list)\n const currentGroup = current === undefined\n ? undefined\n : owningGroupKey(workspaces, current)\n const groups: GroupNode[] = []\n for (const g of groupByWorkspace(list, workspaces, archived, rowState.archivedFilter, view.ungroupedOrder)) {\n const expanded = expandedGroups.has(g.key)\n const members = sectionMembers(g.sessions, pinned, archived)\n .map(session => sessionNode(session, list, statuses, pinned, archived))\n groups.push({\n key: g.key,\n workspaceId: g.workspaceId,\n cwd: g.cwd,\n createdAt: g.createdAt,\n label: g.label,\n sessionCount: g.sessions.length,\n expanded,\n containsCurrent: g.key === currentGroup,\n // Sessions always included so HOC in WorkspaceBrowser.tsx can compute badge.\n // Rendering logic in WorkspaceBrowser.tsx still checks `expanded` before rendering rows.\n sessions: members,\n })\n }\n return groups\n}\n\n/**\n * Select complete flat-list membership, independently of archive visibility.\n * @param list - sessions list snapshot.\n * @returns known ordinary Session ids, including archives and only the current blank.\n */\nexport function sessionMemberIds(list: SessionListState): SessionId[] {\n return visibleSessionIds(list, [], 'show')\n}\n\n/**\n * Select visible flat-list members without deriving row presentation or ordering.\n * @param list - sessions list snapshot.\n * @param archivedSessionIds - registry-global archive set.\n * @param archivedFilter - archived-row visibility choice.\n * @returns known visible Session ids in list order, including ordinary forks and only the current blank.\n */\nexport function visibleSessionIds(\n list: SessionListState,\n archivedSessionIds: readonly SessionId[],\n archivedFilter: ArchivedFilter,\n): SessionId[] {\n const archived = new Set(archivedSessionIds)\n const current = mainSessionId(list)\n return list.ids.filter((id) => {\n const s = list.byId[id]\n return s !== undefined && sessionVisible(s, current, archived, archivedFilter)\n })\n}\n\n/**\n * Derive flat rows from the browser's complete ordered Session ids, with\n * pinned rows fronted ahead of the supplied order.\n * @param list - sessions list snapshot used to select the ids.\n * @param sessionIds - complete account members in the selected order, including hidden archives.\n * @param rowState - registry-global pin and archive sets plus the archived filter.\n * @param statuses - unified UI status by Session.\n * @returns flat rows in sectioned order with current status indicators.\n */\nexport function deriveFlat(\n list: SessionListState,\n sessionIds: readonly SessionId[],\n rowState: SessionRowState,\n statuses: SessionStatuses,\n): SessionNode[] {\n const archived = new Set(rowState.archivedSessionIds)\n const pinned = new Set(rowState.pinnedSessionIds)\n const current = mainSessionId(list)\n const members = sessionIds.flatMap((id) => {\n const session = list.byId[id]\n return session !== undefined && sessionVisible(session, current, archived, rowState.archivedFilter)\n ? [session]\n : []\n })\n return sectionMembers(members, pinned, archived)\n .map(session => sessionNode(session, list, statuses, pinned, archived))\n}\n\n/**\n * Merge immediate title/Workspace substring matches with ranked Host content\n * matches. Local rows lead newest-first, content-only rows retain backend\n * order, and duplicate sessions receive the backend snippet in place.\n * @param list - session metadata authority.\n * @param workspaces - Workspace membership and display labels.\n * @param query - caller text; surrounding whitespace is ignored.\n * @param archivedSessionIds - registry-global archive set (members match per the archived filter).\n * @param archivedFilter - archived-row visibility choice; search follows it.\n * @param statuses - unified UI status by Session.\n * @param content - ranked Host content-search page.\n * @param limit - protocol-owned maximum merged row count.\n * @returns bounded deduplicated flat rows and a refine-query hint bit.\n */\nexport function deriveSearchResults(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n query: string,\n archivedSessionIds: readonly SessionId[],\n archivedFilter: ArchivedFilter,\n statuses: SessionStatuses,\n content: { items: readonly SessionSearchResultItem[]; hasMore: boolean },\n limit: number,\n): SearchResultSet {\n const q = query.trim().toLowerCase()\n if (q === '') return { items: [], hasMore: false }\n const archived = new Set(archivedSessionIds)\n const current = mainSessionId(list)\n\n const workspaceBySession = new Map<SessionId, string>()\n for (const workspace of workspaces) {\n for (const sessionId of workspace.sessionIds) {\n if (!workspaceBySession.has(sessionId)) workspaceBySession.set(sessionId, workspace.title)\n }\n }\n const labelOf = (summary: SessionSummary): string =>\n workspaceBySession.get(summary.id) ?? workspaceLabel(summary.cwd)\n const contentBySession = new Map<SessionId, SessionSearchResultItem>()\n for (const item of content.items) {\n if (!contentBySession.has(item.sessionId)) contentBySession.set(item.sessionId, item)\n }\n\n const local: SessionSummary[] = []\n for (const id of list.ids) {\n const summary = list.byId[id]\n // Blank placeholders never match a query (their canonical title displays\n // localized, so matching it would tie search to one language).\n if (summary === undefined || summary.blank || !sessionVisible(summary, current, archived, archivedFilter)) continue\n if (\n sessionTitle(summary).toLowerCase().includes(q)\n || labelOf(summary).toLowerCase().includes(q)\n ) {\n local.push(summary)\n }\n }\n const localById = new Map(local.map(summary => [summary.id, summary]))\n const orderedLocal = orderByRecency(local.map(summary => summary.id), list.byId)\n .map(id => localById.get(id) as SessionSummary)\n\n const ordered: SessionSummary[] = []\n const included = new Set<SessionId>()\n const include = (summary: SessionSummary): void => {\n if (included.has(summary.id)) return\n included.add(summary.id)\n ordered.push(summary)\n }\n for (const summary of orderedLocal) include(summary)\n for (const item of content.items) {\n const summary = list.byId[item.sessionId]\n if (summary !== undefined && !summary.blank && sessionVisible(summary, current, archived, archivedFilter)) include(summary)\n }\n\n return {\n items: ordered.slice(0, limit).map((summary) => {\n const match = contentBySession.get(summary.id)\n const status = statuses.get(summary.id)\n const pendingInteraction = visiblePendingKind(status?.pendingInteraction?.kind)\n return {\n id: summary.id,\n title: sessionTitle(summary),\n workspace: labelOf(summary),\n running: status?.running ?? summary.running,\n runningSubagentCount: runningChildCount(list, summary.id, statuses),\n ...(pendingInteraction === undefined\n ? {}\n : { pendingInteraction }),\n completed: status?.completionUnread === true,\n archived: archived.has(summary.id),\n ...match === undefined ? {} : { snippet: match.snippet },\n }\n }),\n hasMore: content.hasMore || ordered.length > limit,\n }\n}\n\n/** Normalize separators for comparison without interpreting POSIX backslashes as separators. */\nfunction folderPath(path: string): string {\n const windows = /^[A-Za-z]:[/\\\\]/.test(path) || path.startsWith('\\\\\\\\')\n return (windows ? path.replaceAll('\\\\', '/') : path).replace(/\\/+$/, '')\n}\n\n/**\n * Find the nearest registered ancestor, excluding the Workspace directory itself.\n * Paths use Host spelling; matching is case-sensitive, like Workspace identity.\n * @param path - Workspace directory.\n * @param parents - registered Workspace directory paths.\n * @returns the owning parent path, or undefined when no parent contains the Workspace.\n */\nexport function owningParentFolder(path: string, parents: readonly string[]): string | undefined {\n const child = folderPath(path)\n let owner: string | undefined\n let length = -1\n for (const parent of parents) {\n const root = folderPath(parent)\n if (root.length > length && child !== root && child.startsWith(`${root}/`)) {\n owner = parent\n length = root.length\n }\n }\n return owner\n}\n","/**\n * The workspace browser's viewing store: the session-list grouping mode,\n * persisted across reloads. Module level exports the factory only (a\n * module-level handle would pin the store identity across plugin reloads);\n * register() receives the factory and the browser derives its PropsStore\n * share from the return type.\n */\nimport { defineStore, type EngineStoreHandle } from '@deepseek-ai/dsh-client-store'\nimport type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { reconcileManualOrder, type ArchivedFilter, type SessionRowState } from './tree.ts'\n\n/** Browser-local order account for the hierarchy-free flat Session list. */\nexport const FLAT_SESSION_ORDER_KEY = '__flat_session_order__'\n\n/** Session-list grouping mode: sibling Workspace sections, a Workspace tree, or one flat list. */\nexport type SessionGroupBy = 'workspace' | 'workspace-tree' | 'flat'\n/** Session order: saved manual positions or current recency. */\nexport type SessionOrderBy = 'manual' | 'updated'\n\n/** Workspace browser viewing state persisted across surface remounts and reloads. */\ntype WorkspaceViewState = {\n groupBy: SessionGroupBy\n orderBy: SessionOrderBy\n /** Explicit group expansion keyed by Workspace identity, including descendants in tree mode. */\n groupExpansion: Record<string, boolean>\n /** Saved manual order per Workspace group plus the browser-local flat-list account. */\n sessionOrderByAccount: Record<string, string[]>\n /** Archived-row visibility; omitted in pre-filter v5 snapshots and read as 'default'. */\n archivedFilter?: ArchivedFilter\n}\n\ntype SessionOrderSource = {\n members: Readonly<Record<string, readonly SessionId[]>>\n summaries: SessionListState['byId']\n rowState: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>\n}\n\n/**\n * Annotation twin of the actions literal below (the export needs a declared\n * return type); drift fails assignability at the defineStore call.\n */\ntype WorkspaceViewActions = {\n setGroupBy: (draft: WorkspaceViewState, mode: SessionGroupBy) => void\n setOrderBy: (\n draft: WorkspaceViewState,\n mode: SessionOrderBy,\n initialOrders: Readonly<Record<string, readonly string[]>>,\n ) => void\n setGroupExpanded: (draft: WorkspaceViewState, key: string, expanded: boolean) => void\n retainAccountKeys: (draft: WorkspaceViewState, workspaceKeys: readonly string[]) => void\n syncSessionOrders: (\n draft: WorkspaceViewState,\n orders: Readonly<Record<string, readonly string[]>>,\n ) => void\n setSessionOrder: (\n draft: WorkspaceViewState,\n accountKey: string,\n order: readonly string[],\n initialOrders: Readonly<Record<string, readonly string[]>>,\n ) => void\n pinSessionOrder: (\n draft: WorkspaceViewState,\n sessionId: string,\n accountKeys: readonly string[],\n source: SessionOrderSource,\n ) => void\n setArchivedFilter: (draft: WorkspaceViewState, filter: ArchivedFilter) => void\n}\n\n/** Copy read-only projections into the persisted mutable store representation. */\nfunction copySessionOrders(\n orders: Readonly<Record<string, readonly string[]>>,\n): Record<string, string[]> {\n return Object.fromEntries(Object.entries(orders).map(([key, order]) => [key, [...order]]))\n}\n\n/**\n * Create the workspace browser viewing store handle.\n * @returns the store handle (spec + type + identity + factory in one).\n */\nexport function createWorkspaceViewStore(): EngineStoreHandle<WorkspaceViewState, WorkspaceViewActions> {\n return defineStore({\n init: (): WorkspaceViewState => ({\n groupBy: 'workspace',\n orderBy: 'updated',\n groupExpansion: {},\n sessionOrderByAccount: {},\n archivedFilter: 'default',\n }),\n persist: 'dsh.workspace.view.v5',\n actions: {\n setGroupBy: (d, mode: SessionGroupBy) => { d.groupBy = mode },\n setOrderBy: (d, mode: SessionOrderBy, initialOrders) => {\n if (mode === d.orderBy) return\n d.sessionOrderByAccount = mode === 'manual' ? copySessionOrders(initialOrders) : {}\n d.orderBy = mode\n },\n setGroupExpanded: (d, key: string, expanded: boolean) => { d.groupExpansion[key] = expanded },\n retainAccountKeys: (d, workspaceKeys: readonly string[]) => {\n const retained = new Set(workspaceKeys)\n d.groupExpansion = Object.fromEntries(\n Object.entries(d.groupExpansion).filter(([key]) => retained.has(key)),\n )\n d.sessionOrderByAccount = Object.fromEntries(\n Object.entries(d.sessionOrderByAccount).filter(([key]) => retained.has(key)),\n )\n delete (d as WorkspaceViewState & { sessionUpdatedAtByAccount?: unknown }).sessionUpdatedAtByAccount\n },\n syncSessionOrders: (d, orders) => {\n if (d.orderBy !== 'manual') return\n Object.assign(d.sessionOrderByAccount, copySessionOrders(orders))\n },\n setSessionOrder: (d, accountKey, order, initialOrders) => {\n if (d.orderBy === 'updated') d.sessionOrderByAccount = copySessionOrders(initialOrders)\n else Object.assign(d.sessionOrderByAccount, copySessionOrders(initialOrders))\n d.orderBy = 'manual'\n d.sessionOrderByAccount[accountKey] = [...order]\n },\n pinSessionOrder: (d, sessionId, accountKeys, source) => {\n const selected = new Set(accountKeys)\n d.sessionOrderByAccount = Object.fromEntries(Object.entries(source.members).map(([key, members]) => {\n const order = reconcileManualOrder(members, d.sessionOrderByAccount[key], source.summaries, source.rowState)\n return [key, selected.has(key) ? [sessionId, ...order.filter(id => id !== sessionId)] : order]\n }))\n },\n setArchivedFilter: (d, filter: ArchivedFilter) => { d.archivedFilter = filter },\n },\n })\n}\n\n/** The bound write set of one viewing-store instance (what the UiWorkspace service drives). */\nexport type WorkspaceViewStoreActions = ReturnType<ReturnType<typeof createWorkspaceViewStore>['create']>['actions']\n","/**\n * The complete account memberships a Pin order write reconciles against,\n * derived from the same Host snapshots the browser orders by, so the\n * UiWorkspace service can complete the write without the browser in the loop.\n */\nimport type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { FLAT_SESSION_ORDER_KEY } from './stores.ts'\nimport { owningGroupKey, sessionMemberIds, type SessionRowState, UNGROUPED_KEY } from './tree.ts'\n\n/** What `pinSessionOrder` reconciles a pinned Session's accounts against. */\nexport interface PinOrderSource {\n members: Readonly<Record<string, readonly SessionId[]>>\n summaries: SessionListState['byId']\n rowState: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>\n}\n\n/**\n * Every account's complete membership: each Workspace, Ungrouped, and the flat list.\n * @param workspaces - current Host Workspaces.\n * @param list - current Session list snapshot.\n * @param rowState - registry-global pin and archive sets.\n * @returns the order source for one pin write.\n */\nexport function pinOrderSource(\n workspaces: readonly WorkspaceView[],\n list: SessionListState,\n rowState: PinOrderSource['rowState'],\n): PinOrderSource {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return {\n members: Object.fromEntries([\n ...workspaces.map(workspace => [workspace.workspaceId, workspace.sessionIds] as const),\n [UNGROUPED_KEY, list.ids.filter(id => list.byId[id] !== undefined && !accounted.has(id))],\n [FLAT_SESSION_ORDER_KEY, sessionMemberIds(list)],\n ]),\n summaries: list.byId,\n rowState,\n }\n}\n\n/**\n * The accounts a pinned Session leads: its group (or Ungrouped) and the flat list.\n * @param workspaces - current Host Workspaces.\n * @param sessionId - the Session being pinned.\n * @returns the account keys `pinSessionOrder` fronts.\n */\nexport function pinOrderAccounts(workspaces: readonly WorkspaceView[], sessionId: SessionId): readonly string[] {\n return [owningGroupKey(workspaces, sessionId), FLAT_SESSION_ORDER_KEY]\n}\n","/** Workspace archive and directory UI capability. */\n\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport type { ClientRemote, DirectoryListing, RemoteFailure } from '@deepseek-ai/dsh-api-remotes/client'\nimport type {\n ISessions,\n SessionCreateError,\n SessionReference,\n SessionTarget,\n SessionListState,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client'\nimport type {\n IWorkspaces, WorkspaceId, WorkspaceSnapshot, WorkspaceView,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type { RowToast } from './contract/slots.ts'\nimport { pinOrderAccounts, pinOrderSource } from './pin-order.ts'\nimport type { WorkspaceViewStoreActions } from './stores.ts'\n\ninterface MainSelection {\n readonly sessionId?: SessionId\n readonly subagentAddress?: SubagentAddress\n}\n\n/** Workspace archive and directory operations consumed by Client UI domains. */\nexport interface UiWorkspace {\n /**\n * Select a Session and show its Conversation as one UI navigation action.\n * @param target - known Session identity or durable direct-parent subagent address to display.\n */\n openSession(target: SessionTarget): void\n /**\n * Connect a Workspace and open its Session unless a later navigation supersedes it.\n * @param workspaceId - target Workspace.\n * @param beforeOpen - optional synchronous preparation for the selected Session,\n * skipped after supersession; a throw aborts the open and releases the retained reference.\n * @returns completion; a superseded request may create a Session but does not open it.\n * @throws on failure; a refused creation is also shown through the Workspace\n * notice unless a later navigation or disposal superseded the request.\n */\n openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void>\n /**\n * Fork a Session without changing the current selection.\n * @param sessionId - source Session.\n * @param onCreated - observer before the optional child-title update.\n * @returns the child SessionId after creation and inherited-title increment.\n */\n forkSession(sessionId: SessionId, onCreated?: (childId: SessionId) => void): Promise<SessionId>\n /**\n * Resolve the reusable or newly created blank Session for a Workspace.\n * @param workspaceId - target Workspace.\n * @returns a Session already addressable through the Session Controller.\n */\n connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>\n /**\n * Start a New Session flow and navigate to its Session; a creation the Host\n * refuses is shown through the Workspace notice and leaves the selection as it was.\n * @param workspaceId - explicit target; absent inherits the current or most recent Workspace.\n */\n startSession(workspaceId?: WorkspaceId): void\n /**\n * Archive a Session and clear it when it is the current selection.\n * @param sessionId - Session to archive.\n * @param options - `stopActivity` asks the Host to stop the Session's running work instead of refusing.\n */\n archiveSession(sessionId: SessionId, options?: { readonly stopActivity?: boolean }): Promise<void>\n /**\n * Unarchive a Session, restoring it to its recorded Workspace position.\n * @param sessionId - Session to unarchive.\n */\n unarchiveSession(sessionId: SessionId): Promise<void>\n /**\n * Pin a Session on the Host, then lead it in its accounts' saved orders\n * (its Workspace group or Ungrouped, and the flat list). The order write\n * reads the memberships current at completion, so reorders that landed\n * while the Host call was pending keep their positions.\n * @param sessionId - Session to pin.\n */\n pinSession(sessionId: SessionId): Promise<void>\n /**\n * Unpin a Session on the Host; saved positions stay as they are.\n * @param sessionId - Session to unpin.\n */\n unpinSession(sessionId: SessionId): Promise<void>\n /**\n * Open the Host-native directory picker.\n * @returns the selected directory, or null when cancelled.\n */\n pickDirectory(): Promise<string | null>\n /**\n * List one Host directory level.\n * @param path - directory path; absent selects the Host home.\n * @param signal - cancellation for a superseded scan.\n * @returns directory entries and breadcrumb ancestry.\n */\n listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing>\n /**\n * Create a child directory.\n * @param path - existing parent directory.\n * @param name - child directory name.\n * @returns created absolute path.\n */\n createDirectory(path: string, name: string): Promise<string>\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n /** Cross-Controller Workspace navigation and directory UI capability. */\n uiWorkspace: UiWorkspace\n }\n}\n\n/** Structured directory failure exposed to directory UI consumers. */\nexport class DirectoryBrowseError extends Error {\n override readonly name = 'DirectoryBrowseError'\n\n /** @param rpcError - Host directory business failure. */\n constructor(readonly rpcError: RemoteFailure) {\n super(`directory browse failed: ${rpcError.code}: ${rpcError.message}`)\n }\n}\n\n/** Implements Workspace archive and directory UI operations. */\nclass UiWorkspaceService extends Service implements UiWorkspace {\n private readonly connecting = new Map<WorkspaceId, Promise<SessionId>>()\n private readonly lifetime = new AbortController()\n private readonly selection = createSnapshotStore<MainSelection>(\n {}, { persist: { name: 'dsh.sessions.current' } },\n )\n private mainReference: SessionReference | undefined\n\n /**\n * @param ctx - Client root Context.\n * @param directoryPicker - the directory-picking Remote namespace.\n * @param workspaces - pure Workspace Controller.\n * @param sessions - pure Session Controller.\n * @param view - the browser's viewing-store write set (one instance shared with its registration).\n * @param notify - show one notice through the Workspace notice channel.\n */\n constructor(\n ctx: Context,\n private readonly directoryPicker: ClientRemote['directoryPicker'],\n private readonly workspaces: IWorkspaces,\n private readonly sessions: ISessions,\n private readonly view: Pick<WorkspaceViewStoreActions, 'pinSessionOrder'>,\n private readonly notify: (toast: RowToast) => void,\n ) {\n super(ctx, 'uiWorkspace')\n ctx.effect(() => {\n const stop = this.watchNavigation()\n return () => {\n stop()\n this.lifetime.abort()\n const reference = this.mainReference\n this.mainReference = undefined\n reference?.release()\n }\n }, 'ui-workspace: Workspace navigation policy')\n }\n\n async connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId> {\n const workspace = this.workspaces.list.getSnapshot().items\n .find(item => item.workspaceId === workspaceId)\n if (workspace === undefined) {\n throw new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`)\n }\n const inflight = this.connecting.get(workspaceId)\n if (inflight !== undefined) return inflight\n\n const attempt = this.reuseOrCreateBlank(workspace)\n .finally(() => { this.connecting.delete(workspaceId) })\n this.connecting.set(workspaceId, attempt)\n return attempt\n }\n\n private reuseOrCreateBlank(workspace: WorkspaceView): Promise<SessionId> {\n const archived = this.workspaces.list.getSnapshot().archivedSessionIds\n const sessions = this.sessions.list.getSnapshot()\n for (const id of sessions.ids) {\n const summary = sessions.byId[id]\n if (summary === undefined || !summary.blank || summary.cwd !== workspace.path\n || !workspace.sessionIds.includes(id) || archived.includes(id)) continue\n return this.reuseBlank(workspace.workspaceId, id)\n }\n return this.sessions.create({ workspaceId: workspace.workspaceId })\n }\n\n private async reuseBlank(workspaceId: WorkspaceId, sessionId: SessionId): Promise<SessionId> {\n try {\n return await this.sessions.create({ workspaceId, sessionId })\n } catch (error: unknown) {\n if (sessionCreateErrorOf(error)?.rpcError.code !== 'session/writer-held') throw error\n return this.sessions.create({ workspaceId })\n }\n }\n\n openSession(target: SessionTarget): void {\n this.replaceMain(target, this.lifetime.signal, 'reveal')\n }\n\n async openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void> {\n const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])\n let sessionId: SessionId\n try {\n sessionId = await this.connectWorkspace(workspaceId)\n } catch (error: unknown) {\n // Reported here, not in connectWorkspace: startup restoration calls that\n // directly and stays console-only.\n if (!navigation.aborted) this.notify({ kind: 'createFailed', message: creationFailureMessage(error) })\n throw error\n }\n if (navigation.aborted) return\n this.replaceMain(sessionId, navigation, 'reveal', beforeOpen)\n }\n\n async forkSession(sessionId: SessionId, onCreated?: (childId: SessionId) => void): Promise<SessionId> {\n return this.sessions.fork({ sessionId, increaseTitle: true, ...onCreated === undefined ? {} : { onCreated } })\n }\n\n startSession(workspaceId?: WorkspaceId): void {\n const workspace = this.workspaces.list.getSnapshot()\n const sessions = this.sessions.list.getSnapshot()\n const current = this.mainReference?.sessionId\n const currentWorkspaceId = current === undefined\n ? undefined\n : workspace.items.find(item => item.sessionIds.includes(current))?.workspaceId\n const recent = workspace.phase === 'ready' && sessions.phase === 'ready'\n ? recentWorkspace(workspace.items, sessions.byId)\n : undefined\n const target = workspaceId ?? currentWorkspaceId ?? recent\n if (target === undefined) {\n this.clearMain()\n return\n }\n void this.openWorkspace(target).catch(\n (reason: unknown) => { console.warn('new session failed:', reason) },\n )\n }\n\n async archiveSession(sessionId: SessionId, options: { readonly stopActivity?: boolean } = {}): Promise<void> {\n await this.workspaces.archiveSession(sessionId, options)\n if (this.mainReference?.sessionId === sessionId) this.clearMain()\n }\n\n async unarchiveSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.unarchiveSession(sessionId)\n }\n\n async pinSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.pinSession(sessionId)\n const { items, pinnedSessionIds, archivedSessionIds } = this.workspaces.list.getSnapshot()\n this.view.pinSessionOrder(\n sessionId,\n pinOrderAccounts(items, sessionId),\n pinOrderSource(items, this.sessions.list.getSnapshot(), { pinnedSessionIds, archivedSessionIds }),\n )\n }\n\n async unpinSession(sessionId: SessionId): Promise<void> {\n await this.workspaces.unpinSession(sessionId)\n }\n\n async pickDirectory(): Promise<string | null> {\n const result = await this.directoryPicker.pick()\n if (!result.ok) throw new Error(`directory picker failed: ${result.error.message}`)\n return result.value\n }\n\n async listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing> {\n const result = await this.directoryPicker.list(path, signal)\n if (!result.ok) throw new DirectoryBrowseError(result.error)\n return result.value\n }\n\n async createDirectory(path: string, name: string): Promise<string> {\n const result = await this.directoryPicker.createDirectory(path, name)\n if (!result.ok) throw new DirectoryBrowseError(result.error)\n return result.value\n }\n\n private watchNavigation(): () => void {\n let initial: 'waiting' | 'connecting' | 'done' = 'waiting'\n const reconcile = (): void => {\n if (this.lifetime.signal.aborted) return\n if (this.clearArchivedCurrent()) return\n if (initial !== 'waiting') return\n const workspace = this.workspaces.list.getSnapshot()\n const sessions = this.sessions.list.getSnapshot()\n if (workspace.phase !== 'ready' || sessions.phase !== 'ready') return\n if (this.mainReference !== undefined) {\n initial = 'done'\n return\n }\n initial = 'connecting'\n void this.restoreSelection(workspace, sessions).then(\n () => { initial = 'done' },\n (reason: unknown) => {\n if (this.lifetime.signal.aborted) return\n initial = 'waiting'\n console.warn('initial Session restoration failed:', reason)\n },\n )\n }\n\n const disposeWorkspaces = this.workspaces.list.subscribe(reconcile)\n const disposeSessions = this.sessions.list.subscribe(reconcile)\n reconcile()\n return () => {\n this.lifetime.abort()\n disposeSessions()\n disposeWorkspaces()\n }\n }\n\n private async restoreSelection(workspaces: WorkspaceSnapshot, sessions: SessionListState): Promise<void> {\n const saved = this.selection.getSnapshot()\n if (saved.subagentAddress !== undefined) {\n this.replaceMain(saved.subagentAddress, this.lifetime.signal, 'preserve')\n return\n }\n const summary = saved.sessionId === undefined ? undefined : sessions.byId[saved.sessionId]\n const workspace = summary === undefined ? undefined\n : workspaces.items.find(item => item.sessionIds.includes(summary.id))\n if (summary !== undefined && (!summary.blank || workspace === undefined)) {\n this.replaceMain(summary.id, this.lifetime.signal, 'preserve')\n return\n }\n const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal])\n let sessionId: SessionId | undefined\n if (summary !== undefined && workspace !== undefined && summary.cwd === workspace.path\n && !workspaces.archivedSessionIds.includes(summary.id)) {\n sessionId = await this.reuseBlank(workspace.workspaceId, summary.id)\n }\n let target = workspace?.workspaceId ?? recentWorkspace(workspaces.items, sessions.byId)\n if (target === undefined && workspaces.items.length === 0 && sessions.ids.length === 0) {\n const prepared = await this.initializeDefaultWorkspace(navigation)\n if (navigation.aborted) return\n target = prepared?.workspaceId\n }\n if (sessionId === undefined && target !== undefined) sessionId = await this.connectWorkspace(target)\n if (sessionId !== undefined && !navigation.aborted) {\n this.replaceMain(sessionId, navigation, 'preserve')\n }\n }\n\n private async initializeDefaultWorkspace(signal: AbortSignal): Promise<WorkspaceView | undefined> {\n try {\n return await this.workspaces.initializeDefault(signal)\n } catch (_error: unknown) {\n if (!signal.aborted) this.notify({ kind: 'defaultWorkspaceFailed' })\n return undefined\n }\n }\n\n /** @returns true when an archived current selection was cleared. */\n private clearArchivedCurrent(): boolean {\n const current = this.mainReference?.sessionId\n if (current === undefined\n || !this.workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false\n this.clearMain()\n return true\n }\n\n private clearMain(): void {\n const previous = this.mainReference\n this.mainReference = undefined\n this.selection.set({})\n previous?.release()\n this.ctx.layout.selectPanel(null)\n }\n\n private replaceMain(\n target: SessionTarget,\n signal: AbortSignal,\n panel: 'reveal' | 'preserve',\n beforeOpen?: (sessionId: SessionId) => void,\n ): void {\n signal.throwIfAborted()\n const reference = this.sessions.retain(target, { source: 'mainView' })\n try {\n signal.throwIfAborted()\n beforeOpen?.(reference.sessionId)\n if (signal.aborted) {\n reference.release()\n return\n }\n const subagentAddress = typeof target === 'string'\n ? this.sessions.subagentAddress(reference.sessionId)\n : target\n this.selection.set({\n sessionId: reference.sessionId,\n ...(subagentAddress === undefined ? {} : { subagentAddress }),\n })\n } catch (error: unknown) {\n reference.release()\n throw error\n }\n const previous = this.mainReference\n this.mainReference = reference\n previous?.release()\n if (panel === 'reveal') this.ctx.layout.selectPanel(null)\n }\n\n}\n\n/**\n * `error` as the Session Controller's creation failure, or undefined when it\n * is not one. Client plugin bundles do not share error-class identity, so the\n * name decides.\n */\nfunction sessionCreateErrorOf(error: unknown): SessionCreateError | undefined {\n return error instanceof Error && error.name === 'SessionCreateError' ? error as SessionCreateError : undefined\n}\n\n/**\n * The words a failed Session creation is reported in: a Host refusal keeps its\n * stable code and message; any other failure keeps its own message.\n */\nfunction creationFailureMessage(error: unknown): string {\n const refused = sessionCreateErrorOf(error)\n if (refused !== undefined) return `${refused.rpcError.code}: ${refused.rpcError.message}`\n return error instanceof Error ? error.message : String(error)\n}\n\n/** Stable tie-breaking follows Host Workspace order. */\nfunction recentWorkspace(\n workspaces: readonly WorkspaceView[],\n sessions: SessionListState['byId'],\n): WorkspaceId | undefined {\n let selected: WorkspaceId | undefined\n let selectedTime = Number.NEGATIVE_INFINITY\n for (const workspace of workspaces) {\n let latest = Number.NEGATIVE_INFINITY\n for (const sessionId of workspace.sessionIds) {\n const session = sessions[sessionId]\n if (session !== undefined) latest = Math.max(latest, session.updatedAt)\n }\n if (latest === Number.NEGATIVE_INFINITY) latest = Date.parse(workspace.createdAt)\n if (selected === undefined || latest > selectedTime) {\n selected = workspace.workspaceId\n selectedTime = latest\n }\n }\n return selected\n}\n\nexport { UiWorkspaceService }\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","/**\n * Fixed first-use Workspace naming, shared by the Host that creates the\n * directory and by browser consumers that label the resulting row. A pure fold\n * with no imports, so client bundles inline it instead of requesting a\n * module-table row this package does not publish.\n * @module @deepseek-ai/dsh-api-workspace-controller/default-workspace\n */\n/**\n * Leaf directory name of the first-use Workspace under\n * `<Documents>/deepseek-harness`. Language-neutral, so one installation keeps\n * one on-disk path across language switches. The registry derives the initial\n * title from this same segment, which is the title\n * {@link workspaceDisplayTitle} recognizes as automatic.\n */\nexport const DEFAULT_WORKSPACE_DIRECTORY = 'default-workspace';\n/**\n * The text one Workspace is labeled with. A Workspace still carrying the\n * automatic first-use title reads as the caller's localized default name; every\n * other title reads verbatim in every language. A title the user typed as\n * exactly {@link DEFAULT_WORKSPACE_DIRECTORY} is labeled as the default too;\n * nothing else depends on the distinction.\n * @param title - stored Workspace title.\n * @param localizedDefault - the default Workspace name in the active language.\n * @returns the title to display.\n */\nexport function workspaceDisplayTitle(title, localizedDefault) {\n return title === DEFAULT_WORKSPACE_DIRECTORY ? localizedDefault : title;\n}\n//# sourceMappingURL=default-workspace.js.map","/**\n * Fork-owned: aggregated live-status computation for collapsed workspace groups.\n *\n * Extracted from `tree.ts` so the upstream diff surface is minimal — the\n * vendored file only needs one import line and one field assignment to wire\n * the badge aggregation in. Everything fork-specific lives here.\n *\n * @module\n */\nimport type { GroupNode, SessionNode } from './tree.ts'\n\n// ── Types (structurally typed to avoid compile-time dependency on cross-plugin packages) ──\n\n/**\n * One session's waiting-review fact, as published by dsh-gitea-dispatch's\n * `useWaitingSummary()` (issue: dsh-gitea-dispatch#16).\n */\nexport interface WaitingReviewSummaryEntry {\n readonly prNumber: number\n readonly state: 'waiting' | 'overdue'\n}\n\n/** Session id → that session's waiting-review fact (no entry = not waiting). */\nexport type WaitingReviewSummaryMap = ReadonlyMap<string, WaitingReviewSummaryEntry>\n\n/**\n * One session's schedule fact, as published by dsh-later's `useScheduleSummary()`.\n */\nexport interface ScheduleSummaryEntry {\n readonly count: number\n readonly pausedCount: number\n readonly nextAt?: number\n readonly state: 'scheduled' | 'urgent' | 'overdue'\n}\n\n/** Session id → that session's schedule fact (no entry = no scheduled tasks). */\nexport type ScheduleSummaryMap = ReadonlyMap<string, ScheduleSummaryEntry>\n\n// ── Aggregated status ──\n\n/**\n * Aggregated live-session counts for one group, computed over all members so a\n * folded folder row can hint at hidden activity.\n */\nexport interface GroupLiveStatus {\n /** Members currently running. */\n running: number\n /** Members awaiting tool approval. */\n approval: number\n /** Members awaiting plan review. */\n planReview: number\n /** Members awaiting a question answer. */\n question: number\n /** Members finished and not yet opened (the green \"done\" reminder). */\n done: number\n /** Running direct children across members. */\n subagents: number\n /** Members with scheduled tasks (from dsh-later). */\n scheduledSessions: number\n /** Total scheduled tasks across members (including paused). */\n scheduledCount: number\n /** Highest-priority schedule state: overdue > urgent > scheduled. */\n scheduleState: 'scheduled' | 'urgent' | 'overdue' | undefined\n /** Members waiting for CI review of their PR (from dsh-gitea-dispatch). */\n waitingReviewCount: number\n /** Highest-priority waiting state across members: overdue > waiting. */\n waitingReviewState: 'waiting' | 'overdue' | undefined\n}\n\n/**\n * Zero-valued sentinel for {@link GroupLiveStatus}.\n *\n * Used when a group is expanded (badge is hidden, so aggregation is wasted\n * work) or when no cross-plugin data is available. Kept as a frozen constant\n * so the reference is stable across renders — `Object.is` comparisons in\n * React selectors never trigger spurious re-renders on it.\n */\nexport const EMPTY_LIVE_STATUS: GroupLiveStatus = Object.freeze({\n running: 0, approval: 0, planReview: 0, question: 0, done: 0, subagents: 0,\n scheduledSessions: 0, scheduledCount: 0, scheduleState: undefined,\n waitingReviewCount: 0, waitingReviewState: undefined,\n}) as GroupLiveStatus\n\n/**\n * Merge two {@link GroupLiveStatus} objects by summing counters and taking the\n * highest-priority state (overdue > urgent > scheduled for schedule; overdue > waiting\n * for waiting-review).\n *\n * Used for multi-level aggregation: when a parent group is collapsed, its badge\n * must reflect all descendant sessions, not just direct members.\n */\nexport function mergeLiveStatus(a: GroupLiveStatus, b: GroupLiveStatus): GroupLiveStatus {\n // Schedule state: overdue (3) > urgent (2) > scheduled (1) > undefined (0)\n const priorityOf = (s: 'scheduled' | 'urgent' | 'overdue' | undefined): number =>\n s === 'overdue' ? 3 : s === 'urgent' ? 2 : s === 'scheduled' ? 1 : 0\n const schedulePriorityA = priorityOf(a.scheduleState)\n const schedulePriorityB = priorityOf(b.scheduleState)\n const scheduleState = schedulePriorityA >= schedulePriorityB ? a.scheduleState : b.scheduleState\n\n // Waiting-review state: overdue > waiting > undefined\n const waitingPriorityA = a.waitingReviewState === 'overdue' ? 2 : a.waitingReviewState === 'waiting' ? 1 : 0\n const waitingPriorityB = b.waitingReviewState === 'overdue' ? 2 : b.waitingReviewState === 'waiting' ? 1 : 0\n const waitingReviewState = waitingPriorityA >= waitingPriorityB ? a.waitingReviewState : b.waitingReviewState\n\n return {\n running: a.running + b.running,\n approval: a.approval + b.approval,\n planReview: a.planReview + b.planReview,\n question: a.question + b.question,\n done: a.done + b.done,\n subagents: a.subagents + b.subagents,\n scheduledSessions: a.scheduledSessions + b.scheduledSessions,\n scheduledCount: a.scheduledCount + b.scheduledCount,\n scheduleState,\n waitingReviewCount: a.waitingReviewCount + b.waitingReviewCount,\n waitingReviewState,\n }\n}\n\n// ── Helpers ──\n\n/**\n * Strip the `session-` / `webhook-` prefix from a Session id.\n *\n * dsh-gitea-dispatch publishes its waiting map keyed by the host SessionId, but\n * its HTTP endpoints key by this normalized form. Accepting both here keeps the\n * badge working across that publisher's conventions without knowing which is in\n * play.\n */\nfunction stripSessionPrefix(id: string): string {\n return id.replace(/^(?:session|webhook)-/, '')\n}\n\n// ── Main computation ──\n\n/**\n * Fold every member row of a group into counts so a collapsed folder can hint at\n * hidden live sessions. Mirrors the session-row status priority (pending\n * outranks running outranks completed) at the counting level; labels resolve with\n * locale at render time.\n * @param nodes - member rows of the group.\n * @param sessionIds - the same members' Session ids (schedule and waiting facts are keyed by id).\n * @param waitingReviewSummary - dsh-gitea-dispatch waiting map, when that plugin is loaded.\n * @param scheduleSummary - dsh-later schedule map, when that plugin is loaded.\n */\nexport function summarizeGroupStatus(\n nodes: readonly SessionNode[],\n sessionIds: readonly string[],\n waitingReviewSummary?: WaitingReviewSummaryMap,\n scheduleSummary?: ScheduleSummaryMap,\n): GroupLiveStatus {\n let running = 0\n let approval = 0\n let planReview = 0\n let question = 0\n let done = 0\n let subagents = 0\n for (const n of nodes) {\n if (n.blank || n.archived) continue\n if (n.pendingInteraction === 'approval') { approval += 1; continue }\n if (n.pendingInteraction === 'plan-review') { planReview += 1; continue }\n if (n.pendingInteraction === 'question') { question += 1; continue }\n if (n.running) running += 1\n else if (n.completed) done += 1\n subagents += n.runningSubagentCount\n }\n\n // Aggregate schedule summary from dsh-later\n let scheduledSessions = 0\n let scheduledCount = 0\n let scheduleState: 'scheduled' | 'urgent' | 'overdue' | undefined = undefined\n\n if (scheduleSummary && sessionIds.length > 0) {\n let totalSessions = 0\n let totalCount = 0\n let highestPriority = 0 // 0=none, 1=scheduled, 2=urgent, 3=overdue\n\n for (const id of sessionIds) {\n const entry = scheduleSummary.get(id)\n if (entry) {\n totalSessions += 1\n totalCount += entry.count\n const priority = entry.state === 'overdue' ? 3 : entry.state === 'urgent' ? 2 : 1\n if (priority > highestPriority) highestPriority = priority\n }\n }\n\n scheduledSessions = totalSessions\n scheduledCount = totalCount\n scheduleState = highestPriority === 3 ? 'overdue' : highestPriority === 2 ? 'urgent' : highestPriority === 1 ? 'scheduled' : undefined\n }\n\n // Aggregate waiting-review summary from dsh-gitea-dispatch (its #16).\n //\n // Counts **members**, not PRs: one session waits on exactly one PR, and the\n // badge's number must mean \"how many sessions in this folder need attention\".\n // `overdue` outranks `waiting` for the dot color, mirroring the schedule rule.\n let waitingReviewCount = 0\n let waitingReviewState: 'waiting' | 'overdue' | undefined = undefined\n if (waitingReviewSummary && sessionIds.length > 0) {\n for (const id of sessionIds) {\n const entry = waitingReviewSummary.get(id) ?? waitingReviewSummary.get(stripSessionPrefix(id))\n if (entry === undefined) continue\n waitingReviewCount += 1\n if (entry.state === 'overdue') waitingReviewState = 'overdue'\n else if (waitingReviewState === undefined) waitingReviewState = 'waiting'\n }\n }\n\n return {\n running, approval, planReview, question, done, subagents,\n scheduledSessions, scheduledCount, scheduleState,\n waitingReviewCount, waitingReviewState,\n }\n}\n\n/**\n * Measure each group's own members, as the input to {@link aggregateGroupStatuses}.\n *\n * Every group is measured, expanded ones included. A folder row shows no badge while\n * it is expanded, but its sessions still need attention and a collapsed ancestor must\n * keep counting them — so expansion is a rendering fact, never an input to the\n * aggregation. Short-circuiting expanded groups to `EMPTY_LIVE_STATUS` (the shape this\n * had before the tree-wide aggregator existed, harmless while nothing aggregated) makes\n * every collapsed parent undercount by the size of its expanded descendants.\n *\n * @param groups - derived groups, each with its member rows already populated.\n * @param waitingReviewSummary - dsh-gitea-dispatch waiting map, when that plugin is loaded.\n * @param scheduleSummary - dsh-later schedule map, when that plugin is loaded.\n */\nexport function directStatusesForGroups(\n groups: readonly { key: string; sessions: readonly SessionNode[] }[],\n waitingReviewSummary?: WaitingReviewSummaryMap,\n scheduleSummary?: ScheduleSummaryMap,\n): Map<string, GroupLiveStatus> {\n const map = new Map<string, GroupLiveStatus>()\n for (const group of groups) {\n map.set(group.key, summarizeGroupStatus(\n group.sessions, group.sessions.map(s => s.id), waitingReviewSummary, scheduleSummary,\n ))\n }\n return map\n}\n\n/**\n * Fold every group's DIRECT status up the workspace tree, so a collapsed folder\n * counts every descendant session. A group's own row shows no badge while it is\n * expanded, but its sessions still need attention and its collapsed ancestor must\n * keep counting them — so the walk never depends on a group's expanded state.\n *\n * @param direct - each group's own-member status, keyed by group key.\n * @param childrenByParent - the rendered tree: parent key (`undefined` = roots) → children.\n * @returns aggregated status per group key: own members plus the whole subtree.\n */\nexport function aggregateGroupStatuses(\n direct: ReadonlyMap<string, GroupLiveStatus>,\n childrenByParent: ReadonlyMap<string | undefined, readonly { key: string }[]>,\n): Map<string, GroupLiveStatus> {\n const aggregated = new Map<string, GroupLiveStatus>()\n // Parentage comes from path-prefix matching, so a self- or mutual-parent edge is\n // representable; without this guard the fold would recurse forever and hang the sidebar.\n const visiting = new Set<string>()\n const fold = (key: string): GroupLiveStatus => {\n const cached = aggregated.get(key)\n if (cached !== undefined) return cached\n if (visiting.has(key)) return direct.get(key) ?? EMPTY_LIVE_STATUS\n visiting.add(key)\n let total = direct.get(key) ?? EMPTY_LIVE_STATUS\n for (const child of childrenByParent.get(key) ?? []) {\n total = mergeLiveStatus(total, fold(child.key))\n }\n visiting.delete(key)\n aggregated.set(key, total)\n return total\n }\n // Every listed child is folded, not just the roots: an unreachable group would\n // otherwise be missing from the map and lose its badge.\n for (const children of childrenByParent.values()) {\n for (const child of children) fold(child.key)\n }\n return aggregated\n}\n\n/**\n * A group row whose badge input is resolved: its own members plus its whole subtree.\n *\n * `GroupNode.liveStatus` is optional only because upstream never fills it — this\n * package's aggregator is the sole producer. Typing a rendered row as\n * `StatusedGroupNode` is what turns \"a row that skipped the aggregator\" into a compile\n * error instead of a folder that silently lost its badge, which is how the PR #10\n * regression reached main.\n */\nexport interface StatusedGroupNode extends GroupNode {\n liveStatus: GroupLiveStatus\n}\n\n/**\n * Attach each group's subtree-wide status, in derivation order. This is the producer\n * the sidebar renders from.\n *\n * Expanded groups carry their status too: their own row draws no badge (a decision\n * inside `groupLiveBadge`), but a collapsed ancestor still has to count them, so\n * expansion never suppresses the measurement.\n *\n * @param groups - derived rows, in the order they render.\n * @param direct - each group's own-member status, from {@link directStatusesForGroups}.\n * @param childrenByParent - the rendered tree: parent key (`undefined` = roots) → children.\n */\nexport function withAggregatedStatus(\n groups: readonly GroupNode[],\n direct: ReadonlyMap<string, GroupLiveStatus>,\n childrenByParent: ReadonlyMap<string | undefined, readonly GroupNode[]>,\n): StatusedGroupNode[] {\n const aggregated = aggregateGroupStatuses(direct, childrenByParent)\n // A group missing from the fold has neither measured members nor listed children,\n // so it is idle rather than unknown.\n return groups.map(group => ({ ...group, liveStatus: aggregated.get(group.key) ?? EMPTY_LIVE_STATUS }))\n}\n","/**\n * Fork-owned: aggregated status badge for collapsed workspace groups.\n *\n * Extracted from `Rows.tsx` so the upstream diff surface is minimal — the\n * vendored file only needs one import and one `<GroupBadge />` call to wire\n * the badge in. Everything fork-specific lives here.\n *\n * @module\n */\nimport type { ReactNode } from 'react'\nimport {\n IconClockOutlineRegular, IconListPenOutlineRegular, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { GroupNode } from '../tree.ts'\nimport type { GroupLiveStatus } from '../group-status.ts'\nimport type { ResolvedBadgeSettings } from '../badge-settings.ts'\nimport css from './Rows.module.css'\n\n/** The standard locale seat, prop-passed from the browser root. */\ntype RowTranslate = WorkspaceBrowserProps['t']\n\n// ── Accessible label ──\n\n/**\n * Accessible label for a folded group's aggregated status, reusing the\n * session-row locale keys so both surfaces read identically.\n *\n * 按设置过滤:关掉的来源不出现在标签里(aria-label 与徽标视觉一致)。\n */\nexport function groupLiveLabel(s: GroupLiveStatus, t: RowTranslate, settings: ResolvedBadgeSettings): string {\n const parts: string[] = []\n if (settings.showPendingInBadge) {\n if (s.approval > 0) parts.push(`${s.approval} ${t('status.waitingApproval')}`)\n if (s.planReview > 0) parts.push(`${s.planReview} ${t('status.planReview')}`)\n if (s.question > 0) parts.push(`${s.question} ${t('status.waitingAnswer')}`)\n }\n if (settings.showRunningInBadge) {\n if (s.running > 0) parts.push(`${s.running} ${t('status.running')}`)\n if (s.subagents > 0) {\n parts.push(t(s.subagents === 1 ? 'status.subagentsRunning.one' : 'status.subagentsRunning.other', { n: s.subagents }))\n }\n }\n if (settings.showWaitingReviewInBadge && s.waitingReviewCount > 0) parts.push(`${s.waitingReviewCount} ${t('status.waitingReview')}`)\n if (settings.showScheduledInBadge && s.scheduledSessions > 0) parts.push(`${s.scheduledSessions} ${t('status.scheduled')}`)\n if (settings.showCompletedInBadge && s.done > 0) parts.push(`${s.done} ${t('status.completed')}`)\n return parts.join(' · ')\n}\n\n// ── Badge ──\n\n/**\n * Aggregated live-status badge for a folded folder row. Dots reuse StateDot so\n * colors match session rows (warning = pending, ongoing = running, done = completed).\n * Renders nothing while expanded or when nothing is pending/active/completed/scheduled/waiting.\n *\n * Count matches the dots: pending + active + completed + waiting-review + scheduled sessions.\n *\n * `settings` 按来源过滤:关掉的来源不画点、不计数、不进 aria-label、不参与「是否显示徽标」\n * 的判断。会话行自身的状态不受影响:那是行级状态,不是分组提示。\n */\nexport function groupLiveBadge(group: GroupNode, t: RowTranslate, settings: ResolvedBadgeSettings): ReactNode {\n const s = group.liveStatus\n if (group.expanded || s === undefined) return null\n const pending = settings.showPendingInBadge ? s.approval + s.planReview + s.question : 0\n const active = settings.showRunningInBadge ? s.running + s.subagents : 0\n const scheduled = settings.showScheduledInBadge ? s.scheduledSessions : 0\n const hasWaitingReview = settings.showWaitingReviewInBadge && s.waitingReviewCount > 0\n const completed = settings.showCompletedInBadge ? s.done : 0\n // 只在有 pending / active / 已完成 / 定时任务 / 等待评审时显示徽标\n if (pending === 0 && active === 0 && completed === 0 && scheduled === 0 && !hasWaitingReview) return null\n const label = groupLiveLabel(s, t, settings)\n const dots: ReactNode[] = []\n if (pending > 0) dots.push(<StateDot key=\"warn\" state=\"warning\" />)\n if (active > 0) dots.push(<StateDot key=\"run\" state=\"ongoing\" />)\n if (completed > 0) dots.push(<StateDot key=\"done\" state=\"done\" />)\n // 定时任务图标(紫色 #8b5cf6 与 dsh-later 定时徽标同源,浅深底对比均 >=3:1;\n // urgent 橙 / overdue 红走宿主 warn/error 语义令牌)。与等待评审**用不同图标**——\n // 两者同属\"在等\"的语义,只靠颜色区分对色盲用户不可用。\n if (scheduled > 0) {\n const stateColor = s.scheduleState === 'overdue' ? 'var(--dsw-alias-state-error-primary)' : s.scheduleState === 'urgent' ? 'var(--dsw-alias-state-warn-secondary)' : '#8b5cf6'\n dots.push(\n <span key=\"schedule\" style={{ color: stateColor, display: 'inline-flex', alignItems: 'center' }}>\n <IconClockOutlineRegular size={14} />\n </span>\n )\n }\n // 等待评审图标(琥珀色;超时转红)。数据来自 dsh-gitea-dispatch 的\n // useWaitingSummary()——本插件不自己轮询该端点(其 store 是唯一轮询方)。\n if (hasWaitingReview) {\n const stateColor = s.waitingReviewState === 'overdue' ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-state-warn-secondary)'\n dots.push(\n <span key=\"waiting-review\" style={{ color: stateColor, display: 'inline-flex', alignItems: 'center' }}>\n <IconListPenOutlineRegular size={14} />\n </span>\n )\n }\n // 数字统计 pending + active + 已完成 + 定时任务会话 + 等待评审会话(与 dot 一致)\n // P2-3: 数字上限 99+,避免大项目组徽标过宽。\n // P3-3: count < countThreshold 时省略数字(点已表达\"有东西\");设置项 countThreshold 可调。\n const count = pending + active + completed + scheduled + (hasWaitingReview ? s.waitingReviewCount : 0)\n const countLabel = count > 99 ? '99+' : count >= settings.countThreshold ? String(count) : ''\n // P2-2: 紧急状态(overdue/urgent)时添加脉冲动画类。\n const isUrgent = s.scheduleState === 'overdue' || s.scheduleState === 'urgent'\n || s.waitingReviewState === 'overdue'\n const badgeClass = isUrgent ? `${css.groupBadge} ${css.groupBadgeUrgent}` : css.groupBadge\n return (\n <span className={badgeClass} role=\"img\" aria-label={label} title={label}>\n {dots}\n {countLabel && <span className={css.groupBadgeCount}>{countLabel}</span>}\n </span>\n )\n}\n\n// ── Hover-card status lines ──\n\n/**\n * Build the status detail lines for the workspace hover card.\n *\n * Extracted so `WorkspaceHoverContent` in `Rows.tsx` only needs to map the\n * returned array — the fork-specific status→line logic lives here.\n *\n * 按设置过滤:关掉的来源不出现在明细行里;`showHoverDetails=false` 时整段返回空。\n */\nexport function hoverStatusLines(\n status: GroupLiveStatus | undefined,\n t: RowTranslate,\n settings: ResolvedBadgeSettings,\n): { state: 'warning' | 'ongoing' | 'done'; text: string }[] {\n const lines: { state: 'warning' | 'ongoing' | 'done'; text: string }[] = []\n if (status === undefined || !settings.showHoverDetails) return lines\n if (settings.showPendingInBadge) {\n if (status.approval > 0) lines.push({ state: 'warning', text: `${status.approval} ${t('status.waitingApproval')}` })\n if (status.planReview > 0) lines.push({ state: 'warning', text: `${status.planReview} ${t('status.planReview')}` })\n if (status.question > 0) lines.push({ state: 'warning', text: `${status.question} ${t('status.waitingAnswer')}` })\n }\n if (settings.showRunningInBadge) {\n if (status.running > 0) lines.push({ state: 'ongoing', text: `${status.running} ${t('status.running')}` })\n if (status.subagents > 0) {\n lines.push({\n state: 'ongoing',\n text: t(status.subagents === 1 ? 'status.subagentsRunning.one' : 'status.subagentsRunning.other', { n: status.subagents }),\n })\n }\n }\n if (settings.showWaitingReviewInBadge && status.waitingReviewCount > 0) {\n lines.push({ state: 'warning', text: `${status.waitingReviewCount} ${t('status.waitingReview')}` })\n }\n if (settings.showScheduledInBadge && status.scheduledSessions > 0) {\n lines.push({ state: 'warning', text: `${status.scheduledSessions} ${t('status.scheduled')}` })\n }\n if (settings.showCompletedInBadge && status.done > 0) lines.push({ state: 'done', text: `${status.done} ${t('status.completed')}` })\n return lines\n}\n","/**\n * Workspace browser tree row components (figma Cell set 14:3080): pure presentational —\n * all data and callbacks arrive via props. Hover swaps (folder->chevron,\n * time->ellipsis, action buttons) are CSS-only, and a session row's clipped\n * title marquees programmatically while the row is hovered. Workspace row\n * menus are visual-only except Rename/Delete. A Session row's \"...\" menu and\n * its hover buttons are the `sidebar.workspaces.session.menu.item` and\n * `sidebar.workspaces.session.row.action` lists, rendered through the\n * browser's `renderSlot` with the menu's open state as the occurrence's hook\n * context; this package's own actions are entries like any plugin's. The\n * session and workspace hover cards are suppressed while a menu is open.\n */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { RefObject } from 'react'\nimport clsx from 'clsx'\nimport type { PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots'\nimport {\n HoverCard, IconArchiveOutlineRegular, IconEditOutlineRegular,\n IconEllipsisOutlineRegular, IconFolderCloseRegular, IconFolderOpenRegular,\n IconNewChatOutlineRegular, IconPinFillRegular, IconTrashOutlineRegular,\n IconTriangleRightFillRegular, IconUnarchiveOutlineRegular, Menu, relativeTime, StateDot, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ShortcutCatalogEntry } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport type { StateDotState } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { abbreviateHomePath } from '@deepseek-ai/dsh-util-workspace-path'\nimport type { MenuOpenState, WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { GroupLiveStatus, GroupNode, SearchResultNode, SessionNode } from '../tree.ts'\nimport { groupLiveBadge, hoverStatusLines } from './GroupBadge.tsx'\nimport css from './Rows.module.css'\n\n/** The standard locale seat, prop-passed from the browser root. */\ntype RowTranslate = WorkspaceBrowserProps['t']\n\n/**\n * Child-seat renderer threaded from the browser root: the row's action lists,\n * its leading decoration, and its hover-card section. The leading seat is\n * rendered only while the row's primary state is idle, so a status dot and a\n * leading occupant never share the row; the hover seat only while the row's\n * card is open.\n */\ntype RowRenderSlots = PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n>['renderSlot']\n\n/** Row display title: blank rows show the localized New Session label. */\nfunction displayTitle(node: SessionNode, t: RowTranslate): string {\n return node.blank ? t('session.new') : (node.title || t('session.untitled'))\n}\n\n/* Overflow this small hides no meaningful tail; scrolling for it reads as an\n accidental jitter, so the title stays put. */\nconst MIN_TITLE_REVEAL_PX = 8\n\n/* Marquee travel speed: slow enough to read the text as it passes. */\nconst TITLE_MARQUEE_PX_PER_MS = 0.03\n\n/**\n * Place the title's scroll position and publish the stylesheet's fade-mask\n * hooks: `data-scrolled` while the title has left its start (left fade) and\n * `data-clipped` while text remains beyond the right edge (right fade).\n * @param title - the row's clipping title element.\n * @param left - scroll offset in CSS pixels.\n * @param range - the title's maximum scroll offset in CSS pixels.\n */\nfunction placeTitle(title: HTMLSpanElement, left: number, range: number): void {\n // jsdom implements no scrollTo; the lane's direct assignment is instant there\n // anyway, so both paths land on the same position.\n if (typeof title.scrollTo === 'function') title.scrollTo({ left, behavior: 'instant' })\n else title.scrollLeft = left\n if (left > 0) title.dataset.scrolled = ''\n else delete title.dataset.scrolled\n if (left < range) title.dataset.clipped = ''\n else delete title.dataset.clipped\n}\n\n/**\n * Return the title to its resting state: scrolled to the start with both fade\n * masks off, so the resting ellipsis renders at full strength.\n * @param title - the row's clipping title element.\n */\nfunction restTitle(title: HTMLSpanElement): void {\n if (typeof title.scrollTo === 'function') title.scrollTo({ left: 0, behavior: 'instant' })\n else title.scrollLeft = 0\n delete title.dataset.scrolled\n delete title.dataset.clipped\n}\n\n/**\n * Marquee a title wider than its one-line cell while its row is hovered: the\n * title clips its own text, so entering crawls it at a constant speed until the\n * far edge (a fork's incremented title, for example) is in view, then rests\n * there under the pointer. Overflow of at most {@link MIN_TITLE_REVEAL_PX}\n * stays put — a barely-clipped title moving a few pixels reads as jitter, not a\n * reveal. Leaving returns the title to the start in one step, because the\n * resting ellipsis and the narrowed cell would otherwise meet the text while it\n * travelled back. Reduced motion jumps to the far edge instead of crawling.\n * @param title - ref to the row's clipping title element.\n * @returns stable pointer enter/leave handlers for the row.\n */\nfunction useTitleMarquee(title: RefObject<HTMLSpanElement | null>): { enter: () => void; leave: () => void } {\n const frame = useRef(0)\n useEffect(() => () => { cancelAnimationFrame(frame.current) }, [])\n return useMemo(() => ({\n enter: (): void => {\n /* v8 ignore next -- defensive: the title span renders unconditionally. */\n if (title.current === null) return\n const element = title.current\n const range = element.scrollWidth - element.clientWidth\n if (range <= MIN_TITLE_REVEAL_PX) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n placeTitle(element, range, range)\n return\n }\n cancelAnimationFrame(frame.current)\n let previous: number | undefined\n let position = 0\n const step = (now: DOMHighResTimeStamp): void => {\n position += previous === undefined ? 0 : (now - previous) * TITLE_MARQUEE_PX_PER_MS\n previous = now\n placeTitle(element, Math.min(position, range), range)\n if (position < range) frame.current = requestAnimationFrame(step)\n }\n frame.current = requestAnimationFrame(step)\n },\n leave: (): void => {\n cancelAnimationFrame(frame.current)\n /* v8 ignore next -- defensive: the title span renders unconditionally. */\n if (title.current === null) return\n restTitle(title.current)\n },\n }), [title])\n}\n\n/** Localized compact relative time (\"刚刚\"/\"5分钟\" in zh, \"now\"/\"5min\" in en). */\nfunction timeLabel(updatedAt: number, now: number, t: RowTranslate): string {\n const { unit, n } = relativeTime(updatedAt, now)\n return unit === 'now' ? t('time.now') : t(`time.${unit}`, { n })\n}\n\n/** Hover-card variant: distances wrap in the ago template; the now bucket stays bare (no \"now ago\"). */\nfunction hoverTimeLabel(updatedAt: number, now: number, t: RowTranslate): string {\n const { unit, n } = relativeTime(updatedAt, now)\n return unit === 'now' ? t('time.now') : t('time.ago', { t: t(`time.${unit}`, { n }) })\n}\n\n/**\n * Absolute creation time through the dictionary's date template (the message\n * clock pattern): `toLocaleString` would follow the browser language, not the\n * app locale, and produce mixed-language text after a switch.\n */\nfunction createdLabel(createdAt: number, t: RowTranslate): string {\n const d = new Date(createdAt)\n const pad2 = (v: number): string => String(v).padStart(2, '0')\n const date = t('date.ymd', { y: d.getFullYear(), m: d.getMonth() + 1, d: d.getDate() })\n return t('hover.created', { time: `${date} ${pad2(d.getHours())}:${pad2(d.getMinutes())}` })\n}\n\n// groupLiveBadge and groupLiveLabel are fork-owned — imported from ./GroupBadge.tsx.\n\n/** Hover-card body: workspace title, display directory path, absolute creation time. */\nfunction WorkspaceHoverContent({ label, cwd, createdAt, status, settings, t }: {\n label: string\n cwd: string | undefined\n createdAt: number\n /** Aggregated member status, supplied only while the group is folded. */\n status: GroupLiveStatus | undefined\n /** 徽标设置:悬停明细按来源过滤;`showHoverDetails=false` 时整段为空。 */\n settings: import('../badge-settings.ts').ResolvedBadgeSettings\n t: RowTranslate\n}) {\n // Fork-owned: status detail lines computed by GroupBadge.tsx.\n const lines = hoverStatusLines(status, t, settings)\n return (\n <div className={css.hoverContent}>\n <div className={css.hoverTitle}>{label}</div>\n <div className={css.hoverPath}>{cwd}</div>\n <div className={css.hoverTime}>{createdLabel(createdAt, t)}</div>\n {lines.map(line => (\n <div className={css.hoverStatus} key={line.text}>\n <StateDot state={line.state} />\n <span>{line.text}</span>\n </div>\n ))}\n </div>\n )\n}\n\n/**\n * Row drag wiring supplied by the tree owner. `drop` reports the half of the\n * row where the pointer released so the owner can resolve an insert anchor.\n */\nexport interface RowDragProps {\n /** Start dragging this row. */\n start: () => void\n /** A compatible row drag is in flight. */\n active: boolean\n /** Current marker on this row: insert line above, below, or none. */\n marker: 'before' | 'after' | null\n /** Report the hovered half while a compatible drag passes over this row. */\n hover: (half: 'before' | 'after') => void\n drop: (half: 'before' | 'after') => void\n end: () => void\n}\n\n/** Drag lifecycle owned by a workspace row; its enclosing group owns hit testing. */\ninterface WorkspaceRowDragProps {\n start: () => void\n end: () => void\n}\n\n/** Pointer-position half of a row (insert line above or below). */\nfunction rowHalf(e: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = e.currentTarget.getBoundingClientRect()\n return e.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\n/**\n * Project (workspace) header row: folder + title;\n * hover reveals the chevron and create button, and dwelling on a real\n * Workspace shows its hover card (the ungrouped bucket has none).\n * `containsCurrent` arrives on the node (derivation fact, no renderer scan).\n * @param props.group - derived group node.\n * @param props.containsCurrentDescendant - highlight an ancestor even when its subtree is collapsed.\n * @param props.onToggle - expand/collapse the group.\n * @param props.onCreate - start a frontend Session inside this Workspace.\n * @param props.drag - optional workspace-row drag wiring.\n * @param props.home - host account home for POSIX hover-path abbreviation.\n * @param props.t - the browser root's locale seat.\n * @returns the row element.\n */\nexport function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, newShortcut, settings, t }: {\n group: GroupNode\n newShortcut?: ShortcutCatalogEntry | undefined\n containsCurrentDescendant?: boolean\n onToggle: () => void\n onCreate: () => void\n /** Real-Workspace actions; absent for the ungrouped bucket (no menu shown). */\n actions?: { rename: () => void; delete: () => void } | undefined\n /** Present only for real Workspace rows in the grouped view. */\n drag?: WorkspaceRowDragProps | undefined\n /** Host account home; POSIX home-rooted hover paths display as `~`. */\n home?: string | undefined\n /** 徽标设置:各来源显隐、悬停明细、数字样式。 */\n settings: import('../badge-settings.ts').ResolvedBadgeSettings\n t: RowTranslate\n}) {\n const row = group\n // The ungrouped bucket has no workspace title: its label is dictionary copy.\n const label = row.workspaceId === undefined ? t('group.ungrouped') : row.label\n const active = containsCurrentDescendant || (group.expanded && group.containsCurrent)\n const [menuOpen, setMenuOpen] = useState(false)\n const workspaceMenuItems = [\n { id: 'rename', label: t('rename'), icon: <IconEditOutlineRegular /> },\n { id: 'delete', label: t('delete.workspace'), icon: <IconTrashOutlineRegular />, danger: true },\n ]\n const ownRow = (\n <div\n className={clsx(css.projectRow, menuOpen && css.menuOpen)}\n data-row-key={`workspace:${group.key}`}\n role=\"treeitem\"\n aria-expanded={row.expanded}\n onClick={onToggle}\n draggable={drag !== undefined}\n onDragStart={drag === undefined\n ? undefined\n : (e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', row.key)\n drag.start()\n }}\n onDragEnd={drag?.end}\n >\n <span className={clsx(css.slot, css.folder, active && css.folderActive)}>\n {row.expanded ? <IconFolderOpenRegular /> : <IconFolderCloseRegular />}\n </span>\n <span className={clsx(css.slot, css.chevron)}>\n <IconTriangleRightFillRegular className={clsx(css.arrow, row.expanded && css.arrowOpen)} />\n </span>\n <span className={css.projectText}>\n <span className={css.title}>{label}</span>\n </span>\n {groupLiveBadge(group, t, settings)}\n <span className={css.rowActions}>\n {actions !== undefined && (\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={workspaceMenuItems}\n onSelect={(id) => {\n setMenuOpen(false)\n // Unknown ids leave before the dispatch: a future menu row must\n // not inherit the destructive branch as an else fallback.\n /* v8 ignore next -- Menu can emit only the rename and delete rows supplied above. */\n if (id !== 'rename' && id !== 'delete') return\n if (id === 'rename') actions.rename()\n else actions.delete()\n }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('actions.workspace.aria', { name: label })}\n onClick={(e) => { e.stopPropagation(); setMenuOpen(v => !v) }}\n >\n <IconEllipsisOutlineRegular />\n </button>\n )}\n />\n )}\n <Tooltip label={t('actions.newSession')} shortcutKeys={newShortcut?.keys} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-keyshortcuts={newShortcut?.aria}\n aria-label={t('actions.newSession.aria', { name: label })}\n onClick={(e) => { e.stopPropagation(); onCreate() }}\n >\n <IconNewChatOutlineRegular />\n </button>\n </Tooltip>\n </span>\n </div>\n )\n // The ungrouped bucket has no backing Workspace: no card to show.\n if (row.createdAt === undefined) return ownRow\n return (\n <HoverCard\n anchor={ownRow}\n content={<WorkspaceHoverContent\n label={row.label}\n cwd={row.cwd === undefined ? undefined : abbreviateHomePath(row.cwd, home)}\n createdAt={row.createdAt}\n status={row.expanded ? undefined : row.liveStatus}\n settings={settings}\n t={t}\n />}\n openDelayMs={800}\n disabled={menuOpen}\n copyText={row.cwd}\n copyLabel={t('copy')}\n copiedLabel={t('hover.copied')}\n />\n )\n}\n\n/* v8 ignore next 3 -- closed-union backstop; only reached if the status is forged */\nfunction assertNever(value: never): never {\n throw new Error(`unknown pending interaction: ${String(value)}`)\n}\n\ninterface SessionStatus {\n state: StateDotState\n label: string\n /** Compact text that replaces the Session row's update time. */\n trailingLabel?: string\n}\n\n/**\n * Session status presentation; pending interaction is primary and live activity\n * outranks completion reminders.\n */\nfunction sessionStatuses(\n node: Pick<SessionNode, 'pendingInteraction' | 'running' | 'runningSubagentCount' | 'completed'>,\n t: RowTranslate,\n): readonly [SessionStatus, ...SessionStatus[]] {\n const subagents: SessionStatus | undefined = node.runningSubagentCount === 0\n ? undefined\n : {\n state: 'ongoing',\n label: t(\n node.runningSubagentCount === 1\n ? 'status.subagentsRunning.one'\n : 'status.subagentsRunning.other',\n { n: node.runningSubagentCount },\n ),\n }\n let pending: SessionStatus | undefined\n switch (node.pendingInteraction) {\n case 'approval':\n pending = {\n state: 'warning',\n label: t('status.waitingApproval'),\n trailingLabel: t('status.compact.approval'),\n }\n break\n case 'plan-review':\n pending = {\n state: 'warning',\n label: t('status.planReview'),\n trailingLabel: t('status.compact.planReview'),\n }\n break\n case 'question':\n pending = {\n state: 'warning',\n label: t('status.waitingAnswer'),\n trailingLabel: t('status.compact.answer'),\n }\n break\n case undefined: break\n /* v8 ignore next -- closed PendingInteractionStatus union */\n default: return assertNever(node.pendingInteraction)\n }\n if (pending !== undefined) return subagents === undefined ? [pending] : [pending, subagents]\n if (node.running) {\n const primary: SessionStatus = { state: 'ongoing', label: t('status.running') }\n return subagents === undefined ? [primary] : [primary, subagents]\n }\n if (subagents !== undefined) return [subagents]\n if (node.completed) return [{ state: 'done', label: t('status.completed') }]\n return [{ state: 'idle', label: t('status.idle') }]\n}\n\n/** Primary status dot plus every status's screen-reader label, shared by the search and session rows. */\nfunction SessionStatusDots({ statuses }: { statuses: readonly [SessionStatus, ...SessionStatus[]] }) {\n return (\n <>\n <StateDot state={statuses[0].state} />\n {statuses.map(status => (\n <span className={css.visuallyHidden} key={status.label}>{status.label}</span>\n ))}\n </>\n )\n}\n\n/** Non-interactive pinned-row marker; the enclosing row remains the only action. */\nfunction PinnedIndicator({ t }: { t: RowTranslate }) {\n const label = t('row.pinned')\n return (\n <span className={css.pinIndicator} role=\"img\" aria-label={label} title={label}>\n <IconPinFillRegular size={14} />\n </span>\n )\n}\n\n/**\n * Hover-card body: full title, relative time, the Session's own scheduled-task\n * section, and every relevant live status. The task section sits above the\n * status lines so they stay the card's trailing status line.\n */\nfunction SessionHoverContent({ node, now, renderSlot, t }: {\n node: SessionNode\n now: number\n renderSlot: RowRenderSlots\n t: RowTranslate\n}) {\n // On archived rows the archived line already says the session is inactive,\n // so resting statuses (idle/completed) drop; live activity still shows.\n const statuses = sessionStatuses(node, t)\n .filter(status => !(node.archived && (status.state === 'done' || status.state === 'idle')))\n return (\n <div className={css.hoverContent}>\n <div className={css.hoverTitle}>{displayTitle(node, t)}</div>\n {/* Same placeholder rule as the row's trailing cell: no timestamp\n before the first prompt. */}\n {!node.blank && <div className={css.hoverTime}>{hoverTimeLabel(node.updatedAt, now, t)}</div>}\n {renderSlot('sidebar.session.row.hover', { sessionId: node.id })}\n {statuses.map(status => (\n <div className={css.hoverStatus} key={status.label}>\n <StateDot state={status.state} />\n <span>{status.label}</span>\n </div>\n ))}\n {node.archived && (\n <div className={clsx(css.hoverStatus, css.hoverArchived)}>\n <IconArchiveOutlineRegular size={14} />\n <span>{t('row.archived')}</span>\n </div>\n )}\n </div>\n )\n}\n\n/**\n * One flat search result: title, Workspace context, and optional content\n * excerpt. Search navigation opens the session only; it does not address an\n * event inside the conversation. Archived rows carry a hover unarchive\n * button, because search is where the filter surfaces them for recovery.\n * @param props.result - merged local/content search row.\n * @param props.currentId - selected session id.\n * @param props.onOpen - open the selected session.\n * @param props.onUnarchive - unarchive an archived result row.\n * @param props.t - Workspace-browser translation seat.\n * @returns the result row.\n */\nexport function SearchResultItem({ result, currentId, onOpen, onUnarchive, t }: {\n result: SearchResultNode\n currentId: string | undefined\n onOpen: (id: SearchResultNode['id']) => void\n onUnarchive: (id: SearchResultNode['id']) => void\n t: RowTranslate\n}) {\n const selected = result.id === currentId\n const statuses = sessionStatuses(result, t)\n const primaryStatus = statuses[0]\n return (\n <div\n className={clsx(css.searchResultRow, selected && css.selected, result.archived && css.archived)}\n role=\"treeitem\"\n aria-selected={selected}\n aria-description={result.archived ? t('toast.archivedNotOpenable') : undefined}\n onClick={() => { onOpen(result.id) }}\n >\n <span className={css.searchResultHeading}>\n {/* Like session rows, the leading slot owns every row marker; on\n archived rows it stays blank — the grayed row carries the\n archived look. */}\n <span className={css.slot}>\n {!result.archived && primaryStatus.state !== 'idle' && (\n <SessionStatusDots statuses={statuses} />\n )}\n </span>\n <span className={css.searchResultTitle}>{result.title || t('session.untitled')}</span>\n {result.archived && (\n <span className={css.rowActions}>\n <Tooltip label={t('actions.unarchive')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('menu.unarchiveSession')}\n onClick={(e) => { e.stopPropagation(); onUnarchive(result.id) }}\n >\n <IconUnarchiveOutlineRegular size={14} />\n </button>\n </Tooltip>\n </span>\n )}\n </span>\n <span className={css.searchResultMeta}>\n <span className={css.searchResultWorkspace}>{result.workspace || t('group.ungrouped')}</span>\n {result.snippet !== undefined && (\n <span className={css.searchResultSnippet}>{result.snippet}</span>\n )}\n </span>\n </div>\n )\n}\n\n/**\n * One top-level 32px session row: leading 16px cell (status dot, or the\n * leading seat while the row's primary state is idle), title, relative time or\n * compact pending label, and the row actions menu. A row that owns a state dot\n * keeps that cell and renders no seat, so an ambient automation mark never\n * appears beside the row's own state dot. An archived row keeps the cell blank:\n * neither marker renders there, and its live status stays on the hover card.\n * @param props.node - derived session node.\n * @param props.currentId - selected session id (row highlight).\n * @param props.now - epoch ms for relative-time formatting.\n * @param props.onOpen - open a session by id.\n * @param props.onRenameRequest - open the rename dialog from a title double-click (id + current title).\n * @param props.renderSlot - child-seat renderer for the row's action lists\n * (`sidebar.workspaces.session.menu.item` / `sidebar.workspaces.session.row.action`),\n * its leading decoration, and its hover-card section.\n * @param props.onReveal - scroll this row into view after search navigation, then acknowledge it.\n * @param props.drag - optional row-drag target wiring; blank rows cannot start a drag.\n * @param props.t - the browser root's locale seat.\n * @returns the session row.\n */\nexport function SessionNodeItem({\n node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag, t,\n}: {\n node: SessionNode\n currentId: string | undefined\n now: number\n onOpen: (id: SessionNode['id']) => void\n /** Open the rename dialog from a title double-click (id + current title). */\n onRenameRequest: (id: SessionNode['id'], currentTitle: string) => void\n /** Scroll this row into view after search navigation, then acknowledge it. */\n onReveal?: (() => void) | undefined\n /** Present on reorderable-list rows so every row can remain a drop target. */\n drag?: RowDragProps | undefined\n t: RowTranslate\n} & PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n>) {\n const row = node\n const title = displayTitle(node, t)\n const selected = node.id === currentId\n const statuses = sessionStatuses(node, t)\n const primaryStatus = statuses[0]\n const showStatus = primaryStatus.state !== 'idle'\n // Archived rows hold their in-place grayed slot, so manual reorder cannot\n // move them. Pinned rows drag within the pinned block: the browser gates\n // their drop targets to fellow pinned rows.\n const draggable = drag !== undefined && !row.blank && !row.archived\n const [menuOpen, setMenuOpen] = useState(false)\n // The menu's open state, bound into the row entries' `useMenuOpenState` hook.\n const menuOpenState = useMemo((): MenuOpenState => [menuOpen, setMenuOpen], [menuOpen])\n const rowRef = useRef<HTMLDivElement>(null)\n const titleRef = useRef<HTMLSpanElement>(null)\n const marquee = useTitleMarquee(titleRef)\n useEffect(() => {\n if (onReveal === undefined) return\n rowRef.current?.scrollIntoView({ block: 'nearest' })\n onReveal()\n }, [onReveal])\n // Figma session cell: pad 8, status slot 16, then a 4px title gap.\n const ownRow = (\n <div\n ref={rowRef}\n data-row-key={`session:${node.id}`}\n className={clsx(\n css.sessionRow, selected && css.selected, menuOpen && css.menuOpen,\n row.archived && css.archived,\n drag?.marker === 'before' && css.dropBefore, drag?.marker === 'after' && css.dropAfter,\n )}\n role=\"treeitem\"\n aria-selected={selected}\n aria-description={row.archived ? t('toast.archivedNotOpenable') : undefined}\n onClick={() => { onOpen(node.id) }}\n onPointerEnter={marquee.enter}\n onPointerLeave={marquee.leave}\n draggable={draggable}\n onDragStart={!draggable\n ? undefined\n : (e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', node.id)\n drag.start()\n }}\n onDragEnd={!draggable ? undefined : drag.end}\n onDragOver={drag === undefined\n ? undefined\n : (e) => {\n if (!drag.active) return\n e.preventDefault()\n e.dataTransfer.dropEffect = 'move'\n drag.hover(rowHalf(e))\n }}\n onDrop={drag === undefined\n ? undefined\n : (e) => {\n if (!drag.active) return\n e.preventDefault()\n drag.drop(rowHalf(e))\n }}\n >\n {/* Pending interaction and own or descendant activity outrank the\n finished-but-unviewed reminder, which returns after activity stops\n and is cleared by opening the session. Archived rows keep the slot\n blank — the grayed row carries the archived look — and their live\n status stays on the hover card only. */}\n <span className={css.slot}>\n {!row.archived && !row.blank && (showStatus\n ? <SessionStatusDots statuses={statuses} />\n : renderSlot('sidebar.session.row.leading', { sessionId: node.id }))}\n </span>\n <span\n ref={titleRef}\n className={css.title}\n onDoubleClick={row.blank\n ? undefined\n : (e) => { e.stopPropagation(); onRenameRequest(node.id, row.title) }}\n >\n {title}\n </span>\n {/* A blank New Session row is a provisional placeholder: nothing has\n happened in it yet, so a \"now\" timestamp and the row verbs\n (rename/fork/archive) would all act on content that does not\n exist — both trailing cells stay off until the first prompt. */}\n {!row.blank && (\n <span\n className={css.time}\n aria-hidden={primaryStatus.trailingLabel === undefined ? undefined : true}\n >\n {primaryStatus.trailingLabel ?? timeLabel(row.updatedAt, now, t)}\n </span>\n )}\n {/* Trails the time so the marker occupies the same right-edge cell as\n the hover pin button that replaces it. */}\n {row.pinned && !row.archived && <PinnedIndicator t={t} />}\n {/* The strip's clicks stay in the strip: the trigger and every\n row.action entry act without also opening the row, so an entry's\n button needs no propagation handling of its own. */}\n {!row.blank && (\n <span className={css.rowActions} onClick={(e) => { e.stopPropagation() }}>\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t('actions.session.aria', { name: title })}\n onClick={() => { setMenuOpen(v => !v) }}\n >\n <IconEllipsisOutlineRegular />\n </button>\n )}\n >\n {renderSlot(\n 'sidebar.workspaces.session.menu.item',\n { sessionId: node.id, displayTitle: row.title },\n { hookContext: menuOpenState },\n )}\n </Menu>\n {renderSlot('sidebar.workspaces.session.row.action', { sessionId: node.id, displayTitle: row.title })}\n </span>\n )}\n </div>\n )\n return (\n <HoverCard\n anchor={ownRow}\n content={<SessionHoverContent node={node} now={now} renderSlot={renderSlot} t={t} />}\n openDelayMs={800}\n disabled={menuOpen || drag?.active === true}\n copyText={row.blank || row.title === '' ? undefined : row.title}\n copyLabel={t('copy')}\n copiedLabel={t('hover.copied')}\n />\n )\n}\n","/** React-commit-driven movement and entry/exit fades for the sidebar's keyed rows. */\nimport { Component, createRef, type ReactNode } from 'react'\nimport css from './AnimatedRows.module.css'\n\nconst ROW_FADE_MS = 100\nconst ROW_GLIDE_MS = 200\n\ninterface AnimatedRowsProps {\n children: ReactNode\n className: string\n label: string\n /** Unique DOM-order keys matching the rendered data-row-key attributes. */\n rowKeys: readonly string[]\n ready: boolean\n /** Changes that replace the view or reveal hidden rows settle immediately. */\n resetKey: string\n}\n\ninterface RowPosition {\n element: HTMLElement\n rect: DOMRect\n opacity: number\n}\n\ninterface RowSnapshot {\n positions: Map<string, RowPosition>\n removed: Map<string, RowPosition>\n}\n\nfunction sameRows(previous: AnimatedRowsProps, next: AnimatedRowsProps): boolean {\n return previous.rowKeys.length === next.rowKeys.length\n && previous.rowKeys.every((key, index) => key === next.rowKeys[index])\n}\n\nfunction intersects(row: DOMRect, viewport: DOMRect): boolean {\n return row.bottom > viewport.top && row.top < viewport.bottom\n && row.right > viewport.left && row.left < viewport.right\n}\n\n/**\n * Animates keyed sidebar rows only when their rendered membership or order changes.\n * Motion starts after the first pointer or keyboard input inside the mounted list.\n * The parent supplies a positioned container for the inert exit overlay.\n */\nexport class AnimatedRows extends Component<AnimatedRowsProps> {\n private armed = false\n private readonly list = createRef<HTMLDivElement>()\n private readonly overlay = createRef<HTMLDivElement>()\n private readonly movements = new Map<HTMLElement, Animation>()\n private readonly exits = new Map<string, { element: HTMLElement; animation: Animation }>()\n\n override getSnapshotBeforeUpdate(previous: AnimatedRowsProps): RowSnapshot | null {\n const list = this.list.current\n if (!this.armed || sameRows(previous, this.props) || previous.resetKey !== this.props.resetKey\n || !previous.ready || !this.props.ready || list === null\n || typeof list.animate !== 'function'\n || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return null\n\n const viewport = list.getBoundingClientRect()\n const positions = this.readPositions()\n const nextKeys = new Set(this.props.rowKeys)\n const removed = new Map<string, RowPosition>()\n for (const [key, row] of positions) {\n if (nextKeys.has(key) || !intersects(row.rect, viewport)) continue\n const clone = row.element.cloneNode(true) as HTMLElement\n clone.removeAttribute('data-row-key')\n clone.inert = true\n clone.style.setProperty(\n '--dsh-workspace-indent', getComputedStyle(row.element).getPropertyValue('--dsh-workspace-indent'),\n )\n removed.set(key, { ...row, element: clone })\n }\n return { positions, removed }\n }\n\n override componentDidUpdate(previous: AnimatedRowsProps, _state: unknown, snapshot: RowSnapshot | null): void {\n if (snapshot === null) {\n if (!sameRows(previous, this.props) || previous.resetKey !== this.props.resetKey\n || previous.ready !== this.props.ready) this.clear()\n return\n }\n\n this.cancelMovements()\n const list = this.list.current as HTMLDivElement\n const overlay = this.overlay.current as HTMLDivElement\n const viewport = list.getBoundingClientRect()\n const origin = overlay.getBoundingClientRect()\n const positions = this.readPositions()\n\n for (const [key, row] of positions) {\n this.removeExit(key)\n const previousRow = snapshot.positions.get(key)\n if (!intersects(row.rect, viewport)\n && (previousRow === undefined || !intersects(previousRow.rect, viewport))) continue\n if (previousRow === undefined) {\n this.move(row.element, [{ opacity: 0 }, { opacity: 1 }], ROW_FADE_MS)\n continue\n }\n const dx = previousRow.rect.left - row.rect.left\n const dy = previousRow.rect.top - row.rect.top\n if (dx === 0 && dy === 0 && previousRow.opacity === 1) continue\n this.move(row.element, [\n { transform: `translate(${String(dx)}px, ${String(dy)}px)`, opacity: previousRow.opacity },\n { transform: 'translate(0, 0)', opacity: 1 },\n ], ROW_GLIDE_MS)\n }\n\n for (const [key, row] of snapshot.removed) {\n const { element } = row\n this.removeExit(key)\n Object.assign(element.style, {\n position: 'absolute', margin: '0', transform: 'none', boxSizing: 'border-box',\n left: `${String(row.rect.left - origin.left)}px`,\n top: `${String(row.rect.top - origin.top)}px`,\n width: `${String(row.rect.width)}px`, height: `${String(row.rect.height)}px`,\n })\n overlay.append(element)\n const animation = element.animate([{ opacity: row.opacity }, { opacity: 0 }], {\n duration: ROW_FADE_MS, easing: 'ease-out', fill: 'forwards',\n })\n this.exits.set(key, { element, animation })\n animation.onfinish = () => { this.removeExit(key) }\n }\n }\n\n override componentWillUnmount(): void {\n this.clear()\n }\n\n private readPositions(): Map<string, RowPosition> {\n const list = this.list.current as HTMLDivElement\n const rows = list.querySelectorAll<HTMLElement>('[data-row-key]')\n return new Map(Array.from(rows, element => [element.dataset.rowKey as string, {\n element,\n rect: element.getBoundingClientRect(),\n opacity: this.movements.has(element) ? Number(getComputedStyle(element).opacity) : 1,\n }]))\n }\n\n private move(element: HTMLElement, keyframes: Keyframe[], duration: number): void {\n const animation = element.animate(keyframes, { duration, easing: 'ease-out' })\n this.movements.set(element, animation)\n animation.onfinish = () => { this.movements.delete(element); animation.cancel() }\n }\n\n private cancelMovements(): void {\n for (const animation of this.movements.values()) {\n animation.onfinish = null\n animation.cancel()\n }\n this.movements.clear()\n }\n\n private removeExit(key: string): void {\n const exit = this.exits.get(key)\n if (exit === undefined) return\n exit.animation.onfinish = null\n exit.animation.cancel()\n exit.element.remove()\n this.exits.delete(key)\n }\n\n private clear(): void {\n this.cancelMovements()\n for (const key of this.exits.keys()) this.removeExit(key)\n }\n\n override render(): ReactNode {\n return <>\n <div\n ref={this.list}\n className={this.props.className}\n role=\"tree\"\n aria-label={this.props.label}\n onPointerDownCapture={() => { this.armed = true }}\n onKeyDownCapture={() => { this.armed = true }}\n >\n {this.props.children}\n </div>\n <div ref={this.overlay} className={css.exits} aria-hidden=\"true\" />\n </>\n }\n}\n","/**\n * Workspace pick/add flow. WorkspacePickFlow is the reusable core (menu +\n * path error dialog) consumed directly by WorkspaceBrowser (same package) and\n * wrapped by WorkspacePicker for the conversation empty-state slot\n * registration. Directory picking itself lives in the composed flow package's\n * slot occupant (see the contract module doc): this core only opens the flow,\n * adopts the picked path, and owns the error surface. Adding a workspace has\n * exactly one route — pick a host directory, new or existing — because the\n * occupant's own create-folder affordance already covers creating one.\n */\nimport type { ReactNode, RefObject } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport {\n Button, IconFolderCloseRegular, IconPlusOutlineRegular, Menu, Modal, type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n WorkspaceId, WorkspaceSnapshot, WorkspaceView,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { workspaceDisplayTitle } from '@deepseek-ai/dsh-api-workspace-controller/default-workspace'\nimport type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { DirectoryFlowOwnerProps, WorkspacePickerProps } from './contract/slots.ts'\nimport css from './WorkspacePicker.module.css'\n\nconst ADD_WORKSPACE = '::add-workspace'\n\n/** Core flow props: the owner supplies popover control and pick semantics. */\nexport interface WorkspacePickFlowProps {\n /** The standard locale seat, forwarded by whichever slot entry hosts the flow. */\n t: WorkspacePickerProps['t']\n /** Popover visibility (anchor button toggle state, owner-local). */\n open: boolean\n /** The anchor button element — the popover's placement anchor. */\n anchorRef?: RefObject<HTMLElement | null> | undefined\n /** Selector hook over the workspace list (framework standard hook). */\n useWorkspaces: <S>(selector: (state: WorkspaceSnapshot) => S) => S\n /** Adopt a picked host directory as a real Workspace. */\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n /** Bound occupancy selector hook for this surface's directory-flow hole (empty leaves the surface with no add action). */\n useDirectoryFlow: SnapshotSelectorHook<boolean>\n /** Render this surface's directory-flow hole with the owner conversation (the entry's narrowed renderSlot). */\n renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode\n /** A real Workspace was picked or created. */\n onPick: (workspaceId: WorkspaceId) => void\n /** Close the popover (outside click / Escape / post-pick). */\n onClose: () => void\n /** Report the picking interaction and adoption occupancy. */\n onBusyChange?: (busy: boolean) => void\n /** Only offer the add action, hide existing workspaces. */\n addOnly?: boolean\n /** Menu opening direction relative to the anchor. */\n side?: 'bottom' | 'top' | 'right'\n /** Currently active workspace (trailing check in the picker list). */\n selectedId?: WorkspaceId | undefined\n}\n\n/**\n * Render the pick menu plus the adoption error dialog.\n * @param props - owner-controlled flow props.\n * @returns menu + dialog elements.\n */\nexport function WorkspacePickFlow({\n t,\n open,\n anchorRef,\n useWorkspaces,\n createWorkspace,\n useDirectoryFlow,\n renderDirectoryFlow,\n onPick,\n onClose,\n addOnly = false,\n onBusyChange,\n side = 'bottom',\n selectedId,\n}: WorkspacePickFlowProps) {\n const workspaceSnapshot = useWorkspaces(state => state)\n const workspaces = workspaceSnapshot.items\n const getAnchorRect = useCallback(\n () => anchorRef?.current?.getBoundingClientRect() ?? null,\n [anchorRef],\n )\n const [errorOpen, setErrorOpen] = useState(false)\n const [modalError, setModalError] = useState<string | null>(null)\n const [flowOpen, setFlowOpen] = useState(false)\n const [pickingFolder, setPickingFolder] = useState(false)\n // One picking interaction at a time: while the flow is open (native chooser\n // pending, browse dialog up) or its pick is being adopted, every other\n // menu action stays disabled — a late outcome must not race a concurrent\n // selection or adoption.\n const flowBusy = flowOpen || pickingFolder\n useEffect(() => { onBusyChange?.(flowBusy) }, [flowBusy, onBusyChange])\n\n // The occupied hole gates the picking affordance: with no composed flow the\n // entry simply is not there (the seam's documented no-flow default). The\n // framework-bound hook keeps occupancy live: flow plugins activate (and\n // HMR-reload) independently of this menu's renders.\n const flowAvailable = useDirectoryFlow(occupied => occupied)\n // An occupant that unloads mid-interaction leaves nobody to cancel: an\n // open flow over an empty hole withdraws so the menu actions come back.\n // flowOpen is a dependency because the flow can also OPEN over an already\n // empty hole (Choose again after the occupant unloaded with the error\n // dialog up) — that transition must snap back too, not just occupancy loss.\n useEffect(() => {\n if (flowOpen && !flowAvailable) setFlowOpen(false)\n }, [flowOpen, flowAvailable])\n const addEntries: MenuEntry[] = flowAvailable\n ? [{ id: ADD_WORKSPACE, label: t('menu.addWorkspace'), icon: <IconPlusOutlineRegular size={16} />, disabled: flowBusy }]\n : []\n // With workspaces listed, the add action pins below the scroll region\n // (divider + always visible); otherwise it IS the menu.\n const pinAdd = !addOnly && workspaces.length > 0\n const items: MenuEntry[] = pinAdd\n ? workspaces.map(workspace => ({\n id: workspace.workspaceId,\n label: workspaceDisplayTitle(workspace.title, t('workspace.defaultName')),\n icon: <IconFolderCloseRegular size={16} />,\n disabled: flowBusy,\n }))\n : addEntries\n // Nothing listed and nothing to add with (a composition that mounts this\n // package without any directory-picker): an empty popover would claim a\n // choice that does not exist, so the anchor gesture shows nothing at all.\n const menuIsEmpty = items.length === 0\n\n const closeModal = (): void => {\n setErrorOpen(false)\n setModalError(null)\n }\n\n /** Adopt a picked directory; failures land in the folder-error dialog (Choose again reopens the flow). */\n const adoptDirectory = (path: string): Promise<void> =>\n createWorkspace({ path }).then((workspace) => {\n setFlowOpen(false)\n onPick(workspace.workspaceId)\n }).catch((reason: unknown) => {\n setModalError(reason instanceof Error ? reason.message : String(reason))\n setFlowOpen(false)\n setErrorOpen(true)\n })\n\n const openDirectoryFlow = useCallback((): void => {\n onClose()\n setErrorOpen(false)\n setModalError(null)\n setFlowOpen(true)\n }, [onClose])\n\n // A menu exists to disambiguate between targets. With no workspaces listed\n // and the add action the only entry left, the anchor gesture IS that action:\n // a one-row popover would cost a click and offer nothing to choose between.\n // The owner's open request is consumed the same way selecting the entry\n // would consume it (close the popover, raise the flow). An empty list is\n // only final once the baseline lands — until then the menu stays up with its\n // loading status instead of jumping into a flow the arriving list would have\n // made unnecessary; the add-only surface lists nothing and never waits.\n const listSettled = addOnly || workspaceSnapshot.phase === 'ready'\n const addIsTheOnlyEntry = !pinAdd && listSettled && addEntries.length === 1\n // `flowBusy` gates this exactly as it disables the equivalent menu entry: a\n // pick still being adopted owns the surface until it settles.\n useEffect(() => {\n if (open && addIsTheOnlyEntry && !flowBusy) openDirectoryFlow()\n }, [open, addIsTheOnlyEntry, flowBusy, openDirectoryFlow])\n\n /** Owner side of the flow conversation: adopt keeps the flow open (busy) until the Host answers. */\n const flowOwner: DirectoryFlowOwnerProps = {\n open: flowOpen,\n busy: pickingFolder,\n onPicked: (path) => {\n setPickingFolder(true)\n void adoptDirectory(path).finally(() => { setPickingFolder(false) })\n },\n onCancel: () => { setFlowOpen(false) },\n onError: (message) => {\n setFlowOpen(false)\n setModalError(message)\n setErrorOpen(true)\n },\n }\n\n const handleSelect = (id: string): void => {\n if (id === ADD_WORKSPACE) {\n openDirectoryFlow()\n return\n }\n onPick(id as WorkspaceId)\n }\n\n return (\n <>\n <Menu\n open={open && !addIsTheOnlyEntry && !menuIsEmpty}\n anchor={null}\n items={items}\n {...pinAdd ? { footer: addEntries } : {}}\n selectedId={selectedId}\n onSelect={handleSelect}\n onClose={onClose}\n side={side}\n portal\n getAnchorRect={getAnchorRect}\n />\n {open && !addIsTheOnlyEntry && !menuIsEmpty && workspaceSnapshot.phase === 'pending' && <div className={css.menuStatus} role=\"status\">{t('picker.loading')}</div>}\n {renderDirectoryFlow(flowOwner)}\n <Modal\n open={errorOpen}\n onClose={closeModal}\n closeLabel={t('close')}\n title={t('folderError.title')}\n footer={(\n <>\n <Button variant=\"outline\" className={css.modalAction} onClick={closeModal}>{t('cancel')}</Button>\n {/* Retrying needs an occupant to serve the flow; without one the\n * button would open a flow nobody can answer or cancel. */}\n <Button variant=\"primary\" className={css.modalAction} disabled={!flowAvailable} onClick={openDirectoryFlow}>{t('folderError.retry')}</Button>\n </>\n )}\n >\n <div className={css.modalError} role=\"alert\">{modalError}</div>\n </Modal>\n </>\n )\n}\n\n/**\n * The conversation empty-state registration: adapts the owner share to the\n * core flow (all state and semantics live in the flow / the owner).\n * @param props - empty-state slot props (owner share + injected creation callback).\n * @returns the flow element.\n */\nexport function WorkspacePicker({\n open,\n anchorRef,\n useWorkspaces,\n selectedId,\n onPick,\n onClose,\n createWorkspace,\n useDirectoryFlow,\n renderSlot,\n t,\n}: WorkspacePickerProps) {\n return (\n <WorkspacePickFlow\n t={t}\n open={open}\n anchorRef={anchorRef}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('conversation.hero.workspace.directoryFlow', owner)}\n selectedId={selectedId}\n onPick={onPick}\n onClose={onClose}\n />\n )\n}\n","/**\n * The workspace/session browsing region filling the sidebar shell's\n * `sidebar.workspaces` hole: section header (title + view options + add\n * workspace), search, the grouped tree or flat list, and the workspace\n * dialogs. Wide state renders the full browser; rail state renders the two\n * region icons (search / add workspace) as 36px controls on the shell's shared\n * rail entry path, each requesting expansion through the owner share. Adding\n * is the header button's one action, so it raises the directory flow with no\n * menu in between; the flow and its error dialog live in WorkspacePicker\n * (same package — direct composition, no slot between them). A Session row's\n * \"...\" menu and hover buttons are the `sidebar.workspaces.session.menu.item`\n * and `sidebar.workspaces.session.row.action` lists rendered through this\n * entry's `renderSlot`; the actions in them, this package's own included,\n * are slot entries with their own behavior, so this component threads no\n * action callbacks and hosts no action surface.\n */\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport clsx from 'clsx'\nimport {\n Button, IconArchiveCheckOutlineRegular, IconArchiveOffOutlineRegular, IconArchiveOutlineRegular,\n IconChevronsUpDownOutlineRegular, IconClockOutlineRegular, IconCloseFillRegular,\n IconFlatListOutlineRegular, IconFolderCloseRegular, IconProjectAddOutlineRegular,\n IconQueueOutlineRegular, IconSearchOutlineRegular, IconSlidersTwoOutlineRegular,\n IconWorkspaceTreeOutlineRegular, Menu, Modal, Toast, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n SessionListState, SessionSearchResultItem,\n} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { workspaceDisplayTitle } from '@deepseek-ai/dsh-api-workspace-controller/default-workspace'\n\n// Cross-plugin hooks: each sibling plugin is optional and degrades to \"absent\".\n//\n// The lookup uses this bundle's **injected** `require` — the CJS factory parameter\n// `window.__ModuleLoader__.load({ factory: (require) => … })` supplies, which resolves\n// the module-table rows declared in package.json `dsh.client.external`.\n//\n// It must NOT be `globalThis.require`: the host defines no global require (verified in\n// the live page: `typeof globalThis.require === 'undefined'`), so a global lookup\n// silently disables every cross-plugin integration while still building and booting\n// cleanly. The bundle preset externalizes exactly these specifiers (deps.neverBundle\n// matches dsh.client.external), keeping them runtime requires instead of inlining.\ndeclare const require: (id: string) => unknown\n\n// dsh-later schedule summary API (optional — gracefully degrades when absent)\ntype ScheduleSummaryMap = ReadonlyMap<string, { count: number; pausedCount: number; nextAt?: number; state: 'scheduled' | 'urgent' | 'overdue' }>\nlet useScheduleSummaryHook: (() => ScheduleSummaryMap | undefined) | undefined\ntry {\n const dshLater = require('dsh-later/client') as { useScheduleSummary?: () => ScheduleSummaryMap } | undefined\n useScheduleSummaryHook = dshLater?.useScheduleSummary\n} catch {\n // dsh-later not installed — schedule summary will be undefined\n}\n\n// dsh-gitea-dispatch waiting-review API (dsh-gitea-dispatch#16, same optional rule).\n// Its store owns the only poll of /api/gitea-dispatch/waiting, so this plugin never\n// issues that request itself: the badge costs no extra traffic.\ntype WaitingReviewSummaryMap = ReadonlyMap<string, { prNumber: number; state: 'waiting' | 'overdue' }>\nlet useWaitingSummaryHook: (() => WaitingReviewSummaryMap | undefined) | undefined\ntry {\n const giteaDispatch = require('dsh-gitea-dispatch/client') as { useWaitingSummary?: () => WaitingReviewSummaryMap } | undefined\n useWaitingSummaryHook = giteaDispatch?.useWaitingSummary\n} catch {\n // dsh-gitea-dispatch not installed — waiting review count stays 0\n}\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { WorkspaceBrowserProps } from '../contract/slots.ts'\nimport type { ArchivedFilter, GroupNode, SessionNode, SessionOrderBy, SessionRowState } from '../tree.ts'\nimport {\n deriveFlat, deriveGroups, deriveSearchResults, orderByRecency, owningGroupKey, owningParentFolder,\n pinCurrentBlank, reconcileManualOrder, sessionMemberIds, UNGROUPED_KEY,\n} from '../tree.ts'\nimport { directStatusesForGroups, withAggregatedStatus, type StatusedGroupNode } from '../group-status.ts'\nimport { ProjectRowItem, SearchResultItem, SessionNodeItem } from './Rows.tsx'\nimport { AnimatedRows } from './AnimatedRows.tsx'\nimport { FLAT_SESSION_ORDER_KEY, type SessionGroupBy } from '../stores.ts'\nimport { WorkspacePickFlow } from '../WorkspacePicker.tsx'\nimport css from './WorkspaceBrowser.module.css'\n\n/**\n * Column slide length (--ds-transition-duration-slow): rail-search focus waits it out —\n * focus() forces a synchronous layout and would jank the slide.\n */\nconst EXPAND_SLIDE_MS = 300\n/** Pause between the latest keystroke and a Host content-search request. */\nconst SEARCH_DEBOUNCE_MS = 250\n/** `session.search` wire bound, measured in JavaScript UTF-16 code units. */\nconst SEARCH_QUERY_MAX_CODE_UNITS = 500\n/** Idle Session rows visible per Workspace before the local overflow control. */\nconst COLLAPSED_SESSION_LIMIT = 5\n\n/** Keep provisional and running rows outside the idle-session quota, including parents with running children. */\nfunction collapsedSessionRows(sessions: readonly SessionNode[], limit = COLLAPSED_SESSION_LIMIT): {\n rows: readonly SessionNode[]\n hiddenCount: number\n} {\n let idleCount = 0\n const rows = sessions.filter((session) => {\n if (session.blank || session.running || session.runningSubagentCount > 0) return true\n if (idleCount >= limit) return false\n idleCount += 1\n return true\n })\n return { rows, hiddenCount: sessions.length - rows.length }\n}\n\n/** Keep controlled input and RPC payload inside the session.search wire contract. */\nfunction sanitizeSearchQuery(value: string): string {\n const withoutNul = value.replaceAll('\\0', '')\n if (withoutNul.length <= SEARCH_QUERY_MAX_CODE_UNITS) return withoutNul\n let end = SEARCH_QUERY_MAX_CODE_UNITS\n const last = withoutNul.charCodeAt(end - 1)\n const next = withoutNul.charCodeAt(end)\n if (last >= 0xD800 && last <= 0xDBFF && next >= 0xDC00 && next <= 0xDFFF) end--\n return withoutNul.slice(0, end)\n}\n\n/**\n * Accept the native drag at document level while a row drag is active: row\n * hover still owns the insertion marker, and releasing outside the list must\n * not be rendered as a rejected drop before dragend commits that last marker.\n */\nfunction useNativeDragAcceptance(active: boolean): void {\n useEffect(() => {\n if (!active) return\n const acceptDrag = (event: DragEvent): void => {\n event.preventDefault()\n if (event.dataTransfer !== null) event.dataTransfer.dropEffect = 'move'\n }\n const acceptDrop = (event: DragEvent): void => { event.preventDefault() }\n document.addEventListener('dragover', acceptDrag)\n document.addEventListener('drop', acceptDrop)\n return () => {\n document.removeEventListener('dragover', acceptDrag)\n document.removeEventListener('drop', acceptDrop)\n }\n }, [active])\n}\n\n/** Grouping, ordering, and archived-filter menu; own open state so it resets with the wide chrome. */\nfunction ViewOptionsMenu({ groupBy, orderBy, archivedFilter, onGroupPick, onOrderPick, onArchivedFilterPick, t }: {\n groupBy: SessionGroupBy\n orderBy: SessionOrderBy\n archivedFilter: ArchivedFilter\n onGroupPick: (mode: SessionGroupBy) => void\n onOrderPick: (mode: SessionOrderBy) => void\n onArchivedFilterPick: (filter: ArchivedFilter) => void\n t: WorkspaceBrowserProps['t']\n}) {\n const [open, setOpen] = useState(false)\n return (\n <Menu\n open={open}\n onClose={() => { setOpen(false) }}\n items={[\n { type: 'label' as const, id: 'group-by', text: t('groupBy.label') },\n { id: 'workspace', label: t('groupBy.workspace'), icon: <IconFolderCloseRegular /> },\n { id: 'workspace-tree', label: t('groupBy.workspaceTree'), icon: <IconWorkspaceTreeOutlineRegular /> },\n { id: 'flat', label: t('groupBy.flat'), icon: <IconFlatListOutlineRegular /> },\n { type: 'separator' as const, id: 'order-by-separator' },\n { type: 'label' as const, id: 'order-by', text: t('orderBy.label') },\n { id: 'manual', label: t('orderBy.manual'), icon: <IconChevronsUpDownOutlineRegular /> },\n { id: 'updated', label: t('orderBy.updated'), icon: <IconClockOutlineRegular /> },\n { type: 'separator' as const, id: 'archived-filter-separator' },\n { type: 'label' as const, id: 'filter-by', text: t('filterBy.label') },\n { id: 'hide-archived', label: t('viewOptions.hideArchived'), icon: <IconArchiveOffOutlineRegular /> },\n { id: 'show-archived', label: t('viewOptions.showArchived'), icon: <IconQueueOutlineRegular /> },\n { id: 'only-archived', label: t('viewOptions.onlyArchived'), icon: <IconArchiveCheckOutlineRegular /> },\n ]}\n selectedIds={[\n groupBy,\n orderBy,\n { default: 'hide-archived', show: 'show-archived', only: 'only-archived' }[archivedFilter],\n ]}\n onSelect={(id) => {\n if (id === 'workspace' || id === 'workspace-tree' || id === 'flat') onGroupPick(id)\n else if (id === 'manual' || id === 'updated') onOrderPick(id)\n else if (id === 'hide-archived') onArchivedFilterPick('default')\n else if (id === 'show-archived') onArchivedFilterPick('show')\n else if (id === 'only-archived') onArchivedFilterPick('only')\n setOpen(false)\n }}\n align=\"end\"\n dense\n listClassName={css.viewOptionsMenu}\n // Portal: the section header clips overflow, so an in-place list would\n // be cut off at the header's bounds.\n portal\n anchor={(\n <Tooltip label={t('viewOptions.label')} side=\"bottom\" delayMs={500}>\n <button\n type=\"button\"\n className={clsx(css.iconButton, css.wide)}\n aria-label={t('viewOptions.label')}\n onClick={() => { setOpen(v => !v) }}\n >\n <IconSlidersTwoOutlineRegular />\n </button>\n </Tooltip>\n )}\n />\n )\n}\n\n/** In-flight root-row drag: source identity plus the current insert marker. */\ninterface DragState {\n /** Workspace id, or {@link UNGROUPED_KEY} for the browser-local loose-session account. */\n accountKey: string\n sessionId: SessionNode['id']\n /** Source row was pinned at drag start; drop targets share the pinned block. */\n pinned: boolean\n /** Row the marker sits on and which half (insert above/below it). */\n over: { id: SessionNode['id']; half: 'before' | 'after' } | null\n}\n\n/** Apply a visible drop to the complete account without removing hidden members. */\nfunction sessionDragOrder(\n order: readonly SessionId[],\n rows: readonly SessionNode[],\n drag: DragState,\n over: NonNullable<DragState['over']>,\n): SessionId[] | undefined {\n const source = rows.find(row => row.id === drag.sessionId)\n const target = rows.find(row => row.id === over.id)\n if (source === undefined || target === undefined || source.blank\n || source.pinned !== drag.pinned || target.pinned !== drag.pinned\n || source.id === target.id || !order.includes(source.id)) return\n const section = rows.filter(row => row.pinned === drag.pinned)\n const sourceIndex = section.findIndex(row => row.id === source.id)\n const withoutSource = section.filter(row => row.id !== source.id)\n const insertAt = withoutSource.findIndex(row => row.id === target.id) + (over.half === 'after' ? 1 : 0)\n if (insertAt === sourceIndex) return\n const next = order.filter(id => id !== source.id)\n const targetIndex = next.indexOf(target.id)\n if (targetIndex === -1) return\n next.splice(targetIndex + (over.half === 'after' ? 1 : 0), 0, source.id)\n return pinCurrentBlank(next, rows.find(row => row.blank)?.id)\n}\n\n/** In-flight Workspace-row drag: source identity plus the current marker. */\ninterface WorkspaceDragState {\n workspaceId: WorkspaceId\n over: { id: WorkspaceId; half: 'before' | 'after' } | null\n}\n\n/** Resolve an insertion side across the Workspace header, descendants, and Sessions. */\nfunction workspaceGroupHalf(e: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = e.currentTarget.getBoundingClientRect()\n return e.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\ntype SessionTreeProps = Pick<\n WorkspaceBrowserProps,\n 'useSessionStatus' | 'startSession' | 'open'\n | 'insertWorkspaceBefore' | 't' | 'usePanelInfo' | 'useBadgeSettings'\n> & PropsRenderSlots<\n | 'sidebar.workspaces.session.menu.item'\n | 'sidebar.workspaces.session.row.action'\n | 'sidebar.session.row.leading'\n | 'sidebar.session.row.hover'\n> & {\n shortcuts: readonly import('@deepseek-ai/dsh-client-shortcuts/client').ShortcutCatalogEntry[]\n /** Always-mounted Session list snapshot. */\n list: SessionListState\n /** Host account home for POSIX hover-path abbreviation. */\n home?: string | undefined\n /** Workspaces in Host group order with browser-projected Session order. */\n workspaces: readonly WorkspaceView[]\n /** Browser-projected order for Sessions outside every Workspace. */\n ungroupedSessionIds: readonly SessionId[]\n /** Whether the current Workspace stream has a complete Host baseline. */\n workspaceReady: boolean\n /** Grouping, ordering, and filter changes replace the view without row motion. */\n animationResetKey: string\n /** Nest Workspaces under their nearest registered ancestors. */\n nestWorkspaces: boolean\n /** Explicit persisted group expansion, including descendants in tree mode. */\n groupExpansion: Readonly<Record<string, boolean>>\n /** Persist one Workspace group's expansion. */\n setGroupExpanded: (key: string, expanded: boolean) => void\n /** Save a drag order and select Manual. */\n setSessionOrder: (accountKey: string, order: readonly string[]) => void\n /** Registry-global pin and archive sets plus the archived-visibility choice. */\n rowState: SessionRowState\n /** Switch the archived filter back to the default hide-archived view. */\n onLeaveArchivedOnly: () => void\n /** Open the browser-owned rename dialog for a real Workspace group. */\n onRenameRequest: (workspaceId: WorkspaceId, currentTitle: string) => void\n /** Open the browser-owned delete-confirmation dialog for a real Workspace group. */\n onDeleteRequest: (workspaceId: WorkspaceId, currentTitle: string) => void\n /** Open the rename dialog from a row title double-click. */\n onSessionRenameRequest: (sessionId: SessionNode['id'], currentTitle: string) => void\n /** One Session chosen from search that must be exposed and scrolled into view. */\n revealSessionId?: SessionId | undefined\n /** Acknowledge that the chosen Session row has been revealed. */\n onSessionRevealed: (sessionId: SessionId) => void\n}\n\n/** The list-empty placeholder — a glyph over the text; the archived-only view names its filter and offers the way back. */\nfunction EmptySessions({ rowState, onLeaveArchivedOnly, t }: Pick<SessionTreeProps, 'rowState' | 'onLeaveArchivedOnly' | 't'>) {\n const archivedOnly = rowState.archivedFilter === 'only'\n return (\n <div className={css.emptyState} data-row-key=\"empty\">\n {archivedOnly ? <IconArchiveOutlineRegular size={24} /> : <IconQueueOutlineRegular size={24} />}\n <div>{archivedOnly ? t('empty.noneArchived') : t('empty.none')}</div>\n {archivedOnly && (\n <button type=\"button\" className={css.emptyAction} onClick={onLeaveArchivedOnly}>\n {t('empty.viewOthers')}\n </button>\n )}\n </div>\n )\n}\n\n/** The scrolling session tree; unmounting drops the sessions subscription and local row limits. */\nfunction SessionTree({\n list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds,\n rowState, onLeaveArchivedOnly,\n workspaceReady, animationResetKey, usePanelInfo,\n onRenameRequest, onDeleteRequest, onSessionRenameRequest,\n renderSlot,\n insertWorkspaceBefore,\n nestWorkspaces, groupExpansion, setGroupExpanded,\n setSessionOrder, home, t,\n revealSessionId, onSessionRevealed, shortcuts, useBadgeSettings,\n}: SessionTreeProps) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n // 徽标设置:各来源显隐、悬停明细、数字样式。\n const badgeSettings = useBadgeSettings(settings => settings)\n const statuses = useSessionStatus(s => s)\n const scheduleSummary = useScheduleSummaryHook?.()\n const waitingReviewSummary = useWaitingSummaryHook?.()\n const current = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const revealGroup = revealSessionId === undefined || !workspaceReady\n ? undefined\n : owningGroupKey(workspaces, revealSessionId)\n const [sessionLimits, setSessionLimits] = useState<Readonly<Record<string, number>>>({})\n // Transient drag marker state; the selected mode owns the resulting order.\n const [drag, setDrag] = useState<DragState | null>(null)\n const sessionDropCommitted = useRef(false)\n const [workspaceDrag, setWorkspaceDrag] = useState<WorkspaceDragState | null>(null)\n const workspaceDropCommitted = useRef(false)\n const nativeDragActive = drag !== null || workspaceDrag !== null\n useNativeDragAcceptance(nativeDragActive)\n const currentGroup = current === undefined || !workspaceReady\n ? undefined\n : owningGroupKey(workspaces, current)\n useEffect(() => {\n if (current === undefined || currentGroup === undefined || Object.hasOwn(groupExpansion, currentGroup)) return\n setGroupExpanded(currentGroup, true)\n }, [current, currentGroup, setGroupExpanded, groupExpansion])\n const parents = useMemo(() => {\n if (!nestWorkspaces) return new Map<string, WorkspaceId | undefined>()\n const keysByPath = new Map(workspaces.map(workspace => [workspace.path, workspace.workspaceId]))\n const paths = [...keysByPath.keys()]\n return new Map<string, WorkspaceId | undefined>(workspaces.map((workspace) => {\n const path = owningParentFolder(workspace.path, paths)\n return [workspace.workspaceId, path === undefined ? undefined : keysByPath.get(path)]\n }))\n }, [nestWorkspaces, workspaces])\n const currentAncestors = useMemo(() => {\n const keys = new Set<string>()\n for (let key = currentGroup === undefined ? undefined : parents.get(currentGroup); key !== undefined; key = parents.get(key)) {\n keys.add(key)\n }\n return keys\n }, [currentGroup, parents])\n const expandedGroups = useMemo(() => {\n const ancestorKeys = new Set<string | undefined>(parents.values())\n return [...workspaces.map(workspace => workspace.workspaceId), UNGROUPED_KEY]\n .filter(key => groupExpansion[key] ?? ancestorKeys.has(key))\n }, [groupExpansion, parents, workspaces])\n const groups = useMemo(\n () => deriveGroups(list, workspaces, rowState, statuses, {\n expandedGroups,\n ungroupedOrder: ungroupedSessionIds,\n }),\n [list, workspaces, rowState, statuses, expandedGroups, ungroupedSessionIds],\n )\n useEffect(() => {\n for (let key = revealGroup; key !== undefined; key = parents.get(key)) {\n if (groupExpansion[key] === false || (key === revealGroup && groupExpansion[key] !== true)) {\n setGroupExpanded(key, true)\n }\n }\n }, [groupExpansion, parents, revealGroup, setGroupExpanded])\n useEffect(() => {\n if (revealSessionId === undefined || revealGroup === undefined) return\n const group = groups.find(candidate => candidate.key === revealGroup)\n if (group === undefined || !group.expanded || !group.sessions.some(row => row.id === revealSessionId)) return\n if (collapsedSessionRows(group.sessions).rows.some(row => row.id === revealSessionId)) return\n setSessionLimits(limits => limits[revealGroup] === Infinity ? limits : { ...limits, [revealGroup]: Infinity })\n }, [groups, revealGroup, revealSessionId])\n const now = Date.now()\n const commitSessionDrag = (activeDrag: DragState, over: NonNullable<DragState['over']>): void => {\n if (sessionDropCommitted.current) return\n sessionDropCommitted.current = true\n setDrag(null)\n const group = groups.find(candidate => candidate.key === activeDrag.accountKey)\n if (group === undefined) return\n if (over.id === activeDrag.sessionId) return\n const accountSessionIds = activeDrag.accountKey === UNGROUPED_KEY\n ? ungroupedSessionIds\n : workspaces.find(workspace => workspace.workspaceId === activeDrag.accountKey)?.sessionIds\n if (accountSessionIds === undefined) return\n const renderedSessions = collapsedSessionRows(group.sessions, sessionLimits[group.key]).rows\n const nextOrder = sessionDragOrder(accountSessionIds, renderedSessions, activeDrag, over)\n if (nextOrder !== undefined) setSessionOrder(activeDrag.accountKey, nextOrder)\n }\n const commitWorkspaceDrag = (\n activeDrag: WorkspaceDragState,\n over: NonNullable<WorkspaceDragState['over']>,\n ): void => {\n if (workspaceDropCommitted.current) return\n workspaceDropCommitted.current = true\n setWorkspaceDrag(null)\n const owner = parents.get(activeDrag.workspaceId)\n const siblings = workspaces.filter(workspace => parents.get(workspace.workspaceId) === owner)\n const rowIndex = siblings.findIndex(workspace => workspace.workspaceId === over.id)\n if (rowIndex === -1) return\n const anchor = over.half === 'before' ? over.id : siblings[rowIndex + 1]?.workspaceId\n if (anchor === activeDrag.workspaceId) return\n const sourceIndex = siblings.findIndex(workspace => workspace.workspaceId === activeDrag.workspaceId)\n const anchorIndex = anchor === undefined\n ? siblings.length\n : siblings.findIndex(workspace => workspace.workspaceId === anchor)\n if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return\n insertWorkspaceBefore(activeDrag.workspaceId, anchor).catch((reason: unknown) => {\n console.warn('workspace reorder rejected:', reason)\n })\n }\n // Build tree structure from original groups (for aggregation traversal)\n const childrenByParentForAggregation = useMemo(() => {\n const rendered = new Set(groups.map(group => group.key))\n const children = new Map<string | undefined, GroupNode[]>()\n for (const group of groups) {\n let parent = parents.get(group.key)\n while (parent !== undefined && !rendered.has(parent)) parent = parents.get(parent)\n const siblings = children.get(parent)\n if (siblings === undefined) children.set(parent, [group])\n else siblings.push(group)\n }\n return children\n }, [groups, parents])\n\n // Fork-owned: each group's DIRECT member status — the input to the tree-wide\n // aggregation below. deriveGroups stopped computing liveStatus (PR #10 moved it\n // out), so this map is the aggregator's only data source. Expanded groups are\n // measured too; see directStatusesForGroups.\n const directStatusByGroup = useMemo(\n () => directStatusesForGroups(groups, waitingReviewSummary, scheduleSummary),\n [groups, waitingReviewSummary, scheduleSummary],\n )\n\n // Multi-level aggregation: a collapsed folder's badge covers its own members plus\n // every descendant group's, at any depth. Every row comes back measured, so the\n // render path can never see an unresolved liveStatus.\n const groupsWithAggregatedStatus = useMemo(\n () => withAggregatedStatus(groups, directStatusByGroup, childrenByParentForAggregation),\n [groups, directStatusByGroup, childrenByParentForAggregation],\n )\n\n // Rebuild tree structure with aggregated groups (for rendering)\n const childrenByParent = useMemo(() => {\n const rendered = new Set(groupsWithAggregatedStatus.map(group => group.key))\n const children = new Map<string | undefined, StatusedGroupNode[]>()\n for (const group of groupsWithAggregatedStatus) {\n // The archived-only view drops empty groups, so an ancestor may be\n // absent; nest under the nearest rendered one.\n let parent = parents.get(group.key)\n while (parent !== undefined && !rendered.has(parent)) parent = parents.get(parent)\n const siblings = children.get(parent)\n if (siblings === undefined) children.set(parent, [group])\n else siblings.push(group)\n }\n return children\n }, [groupsWithAggregatedStatus, parents])\n\n const rootGroups = childrenByParent.get(undefined) ?? []\n const workspaceDropAtListStart = rootGroups[0]?.workspaceId !== undefined\n && workspaceDrag?.over?.id === rootGroups[0].workspaceId\n && workspaceDrag.over.half === 'before'\n\n const rowKeys: string[] = groupsWithAggregatedStatus.length === 0 ? ['empty'] : []\n const renderGroup = (group: StatusedGroupNode, depth: number): ReactNode => {\n const workspaceId = group.workspaceId\n const children = childrenByParent.get(group.key) ?? []\n const compatibleDrag = workspaceDrag !== null && parents.get(workspaceDrag.workspaceId) === parents.get(group.key)\n const collapsed = collapsedSessionRows(group.sessions)\n const visible = collapsedSessionRows(group.sessions, sessionLimits[group.key])\n const sessionsExpanded = visible.hiddenCount === 0\n rowKeys.push(`workspace:${group.key}`)\n const childRows = group.expanded ? children.map(child => renderGroup(child, depth + 1)) : []\n const sessions = visible.rows\n for (const node of sessions) rowKeys.push(`session:${node.id}`)\n if (collapsed.hiddenCount > 0) rowKeys.push(`overflow:${group.key}`)\n const workspaceMarker = workspaceId !== undefined && workspaceDrag?.over?.id === workspaceId\n ? workspaceDrag.over.half\n : null\n const workspaceDragProps = workspaceId === undefined ? undefined : {\n start: () => {\n workspaceDropCommitted.current = false\n setWorkspaceDrag({ workspaceId, over: null })\n },\n end: () => {\n if (workspaceDrag?.over !== null && workspaceDrag?.over !== undefined) {\n commitWorkspaceDrag(workspaceDrag, workspaceDrag.over)\n } else {\n setWorkspaceDrag(null)\n }\n workspaceDropCommitted.current = false\n },\n }\n const hoverWorkspace = workspaceId === undefined || !compatibleDrag\n ? undefined\n : (half: 'before' | 'after') => {\n setWorkspaceDrag(active => active === null\n ? active\n : { ...active, over: { id: workspaceId, half } })\n }\n const dropWorkspace = workspaceId === undefined || !compatibleDrag\n ? undefined\n : (half: 'before' | 'after') => {\n commitWorkspaceDrag(workspaceDrag, { id: workspaceId, half })\n }\n // group arrives from groupsWithAggregatedStatus: collapsed groups already\n // carry the bottom-up aggregated liveStatus (direct + all descendants).\n return (\n // Group section: header, descendant Workspaces, and own Session rows. The\n // inter-group breathing room is the section's own margin\n // (WorkspaceBrowser.module.css).\n <div\n key={group.key}\n style={{ '--dsh-workspace-indent': `${depth * 12}px` } as CSSProperties}\n className={clsx(\n css.groupSection,\n workspaceMarker === 'before' && css.workspaceDropBefore,\n workspaceMarker === 'after' && css.workspaceDropAfter,\n )}\n onDragOver={workspaceDrag === null\n ? undefined\n : (e) => {\n e.preventDefault()\n if (hoverWorkspace === undefined && parents.get(group.key) !== undefined) return\n e.stopPropagation()\n if (hoverWorkspace === undefined) {\n e.dataTransfer.dropEffect = 'none'\n if (workspaceDrag.over !== null) setWorkspaceDrag({ ...workspaceDrag, over: null })\n } else {\n e.dataTransfer.dropEffect = 'move'\n hoverWorkspace(workspaceGroupHalf(e))\n }\n }}\n onDrop={workspaceDrag === null\n ? undefined\n : (e) => {\n e.preventDefault()\n if (dropWorkspace === undefined && parents.get(group.key) !== undefined) return\n e.stopPropagation()\n if (dropWorkspace === undefined) {\n workspaceDropCommitted.current = true\n setWorkspaceDrag(null)\n } else {\n dropWorkspace(workspaceGroupHalf(e))\n }\n }}\n >\n <ProjectRowItem\n newShortcut={shortcuts.find(row => row.id === 'session.new')}\n group={group}\n containsCurrentDescendant={currentAncestors.has(group.key)}\n home={home}\n settings={badgeSettings}\n t={t}\n onToggle={() => {\n if (group.expanded) {\n setSessionLimits(limits => ({ ...limits, [group.key]: COLLAPSED_SESSION_LIMIT }))\n }\n setGroupExpanded(group.key, !group.expanded)\n }}\n onCreate={() => {\n if (group.workspaceId !== undefined) {\n setGroupExpanded(group.key, true)\n startSession(group.workspaceId)\n }\n }}\n drag={workspaceDragProps}\n actions={group.workspaceId === undefined\n ? undefined\n : {\n rename: () => {\n /* v8 ignore next -- narrowing guard: the actions object exists only for real-workspace groups. */\n if (group.workspaceId !== undefined) onRenameRequest(group.workspaceId, group.label)\n },\n delete: () => {\n /* v8 ignore next -- narrowing guard: the actions object exists only for real-workspace groups. */\n if (group.workspaceId !== undefined) onDeleteRequest(group.workspaceId, group.label)\n },\n }}\n />\n {childRows.length > 0 && (\n <div role=\"group\">\n {childRows}\n </div>\n )}\n {group.expanded && sessions.map((node) => {\n // Session drag never leaves its browser-local account, and pinned\n // rows reorder only within their leading pinned block.\n const sameGroupDrag = drag !== null && drag.accountKey === group.key\n const compatibleTarget = sameGroupDrag && drag.pinned === node.pinned\n const normalizeHalf = (half: 'before' | 'after'): 'before' | 'after' =>\n node.blank ? 'after' : half\n const dragProps = {\n start: () => {\n sessionDropCommitted.current = false\n setDrag({ accountKey: group.key, sessionId: node.id, pinned: node.pinned, over: null })\n },\n active: compatibleTarget,\n marker: sameGroupDrag && drag.over?.id === node.id ? drag.over.half : null,\n hover: (half: 'before' | 'after') => {\n /* v8 ignore next -- narrowing guard: Rows gates hover on `active`, which is false while the drag state is null. */\n setDrag(d => (d === null ? d : {\n ...d, over: { id: node.id, half: normalizeHalf(half) },\n }))\n },\n drop: (half: 'before' | 'after') => {\n /* v8 ignore next -- narrowing guard: Rows gates drop on `active`, which is false while the drag state is null. */\n if (drag === null) return\n commitSessionDrag(drag, { id: node.id, half: normalizeHalf(half) })\n },\n end: () => {\n if (drag?.over !== null && drag?.over !== undefined) commitSessionDrag(drag, drag.over)\n else setDrag(null)\n sessionDropCommitted.current = false\n },\n }\n return (\n <SessionNodeItem\n key={node.id}\n node={node}\n currentId={current}\n now={now}\n onOpen={open}\n onRenameRequest={onSessionRenameRequest}\n renderSlot={renderSlot}\n onReveal={node.id === revealSessionId && group.key === revealGroup\n ? () => { onSessionRevealed(node.id) }\n : undefined}\n drag={dragProps}\n t={t}\n />\n )\n })}\n {group.expanded && collapsed.hiddenCount > 0 && (\n <button\n type=\"button\"\n className={css.sessionOverflowButton}\n data-row-key={`overflow:${group.key}`}\n aria-expanded={sessionsExpanded}\n onClick={() => {\n setSessionLimits(limits => ({\n ...limits,\n [group.key]: sessionsExpanded\n ? COLLAPSED_SESSION_LIMIT\n : visible.hiddenCount <= COLLAPSED_SESSION_LIMIT\n ? Infinity\n : (limits[group.key] ?? COLLAPSED_SESSION_LIMIT) + COLLAPSED_SESSION_LIMIT,\n }))\n }}\n >\n {sessionsExpanded\n ? t('sessions.collapse')\n : t('sessions.expand', { n: visible.hiddenCount })}\n </button>\n )}\n </div>\n )\n }\n\n const groupRows = rootGroups.map(group => renderGroup(group, 0))\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n {workspaceDropAtListStart && <span className={css.listTopDropIndicator} aria-hidden=\"true\" />}\n <AnimatedRows\n className={clsx(css.list, workspaceDropAtListStart && css.listTopDropActive)}\n label={t('section.sessions')}\n rowKeys={rowKeys}\n ready={list.phase === 'ready' && workspaceReady && !nativeDragActive}\n // Fork-owned: upstream also mixes `sessionLimits` into this key so that\n // revealing hidden rows settles instantly. But folding a group writes\n // sessionLimits too (reset to COLLAPSED_SESSION_LIMIT), which silently\n // suppressed the row fade-out on every collapse. Keep only the\n // view-replacement key so collapse/expand still animates.\n resetKey={animationResetKey}\n >\n {groupsWithAggregatedStatus.length === 0 && (\n <EmptySessions rowState={rowState} onLeaveArchivedOnly={onLeaveArchivedOnly} t={t} />\n )}\n {groupRows}\n </AnimatedRows>\n <span className={css.fade} />\n </div>\n )\n}\n\n/** The flat \"In one list\" body: every session is one draggable top-level row. */\nfunction FlatList({\n list, sessionIds, rowState, onLeaveArchivedOnly, useSessionStatus, open, onSessionRenameRequest,\n usePanelInfo, setSessionOrder, workspaceReady, animationResetKey,\n revealSessionId, onSessionRevealed, renderSlot, t,\n}: Pick<\n SessionTreeProps,\n | 'useSessionStatus'\n | 'open'\n | 'onSessionRenameRequest'\n | 'renderSlot'\n | 'usePanelInfo'\n | 'setSessionOrder'\n | 'workspaceReady'\n | 'animationResetKey'\n | 'revealSessionId'\n | 'onSessionRevealed'\n | 'rowState'\n | 'onLeaveArchivedOnly'\n | 't'\n> & {\n list: SessionListState\n sessionIds: readonly SessionId[]\n}) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n const statuses = useSessionStatus(s => s)\n const rows = useMemo(\n () => deriveFlat(list, sessionIds, rowState, statuses),\n [list, sessionIds, rowState, statuses],\n )\n const [drag, setDrag] = useState<DragState | null>(null)\n const dropCommitted = useRef(false)\n useNativeDragAcceptance(drag !== null)\n const currentId = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const commitDrag = (activeDrag: DragState, over: NonNullable<DragState['over']>): void => {\n if (dropCommitted.current) return\n dropCommitted.current = true\n setDrag(null)\n const nextOrder = sessionDragOrder(sessionIds, rows, activeDrag, over)\n if (nextOrder !== undefined) setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder)\n }\n const now = Date.now()\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n <AnimatedRows\n className={clsx(css.list, css.flatList)}\n label={t('section.sessions')}\n rowKeys={rows.length === 0 ? ['empty'] : rows.map(row => `session:${row.id}`)}\n ready={list.phase === 'ready' && workspaceReady && drag === null}\n resetKey={animationResetKey}\n >\n {rows.length === 0 && (\n <EmptySessions rowState={rowState} onLeaveArchivedOnly={onLeaveArchivedOnly} t={t} />\n )}\n {rows.map((node) => {\n const active = drag !== null && drag.pinned === node.pinned\n const normalizeHalf = (half: 'before' | 'after'): 'before' | 'after' =>\n node.blank ? 'after' : half\n return (\n <SessionNodeItem\n key={node.id}\n node={node}\n currentId={currentId}\n now={now}\n onOpen={open}\n onRenameRequest={onSessionRenameRequest}\n renderSlot={renderSlot}\n onReveal={node.id === revealSessionId\n ? () => { onSessionRevealed(node.id) }\n : undefined}\n drag={{\n start: () => {\n dropCommitted.current = false\n setDrag({ accountKey: FLAT_SESSION_ORDER_KEY, sessionId: node.id, pinned: node.pinned, over: null })\n },\n active,\n marker: active && drag.over?.id === node.id ? drag.over.half : null,\n hover: (half) => {\n setDrag(current => current === null ? current : {\n ...current, over: { id: node.id, half: normalizeHalf(half) },\n })\n },\n drop: (half) => {\n if (drag !== null) commitDrag(drag, { id: node.id, half: normalizeHalf(half) })\n },\n end: () => {\n if (drag?.over !== null && drag?.over !== undefined) commitDrag(drag, drag.over)\n else setDrag(null)\n dropCommitted.current = false\n },\n }}\n t={t}\n />\n )\n })}\n </AnimatedRows>\n <span className={css.fade} />\n </div>\n )\n}\n\ninterface RemoteSearchState {\n query: string\n status: 'idle' | 'loading' | 'ready' | 'error'\n items: readonly SessionSearchResultItem[]\n hasMore: boolean\n}\n\n/** Flat search body: local metadata matches plus the current Host result page. */\nfunction SearchResults({\n useSessions,\n useSessionStatus,\n open,\n onUnarchive,\n workspaces,\n archivedSessionIds,\n archivedFilter,\n query,\n remote,\n resultLimit,\n usePanelInfo,\n t,\n}: Pick<WorkspaceBrowserProps, 'useSessions' | 'useSessionStatus' | 'open' | 't' | 'usePanelInfo'> & {\n workspaces: readonly WorkspaceView[]\n archivedSessionIds: readonly SessionNode['id'][]\n /** Search matches follow the archived filter selected for the list. */\n archivedFilter: ArchivedFilter\n /** Unarchive an archived result row in place. */\n onUnarchive: (id: SessionNode['id']) => void\n query: string\n remote: RemoteSearchState\n resultLimit: number\n}) {\n const panelActive = usePanelInfo(info => info.activePanelId !== null)\n const list = useSessions(s => s)\n const statuses = useSessionStatus(s => s)\n const currentRemote = remote.query === query\n ? remote\n : { query, status: 'loading' as const, items: [], hasMore: false }\n const results = useMemo(\n () => deriveSearchResults(\n list,\n workspaces,\n query,\n archivedSessionIds,\n archivedFilter,\n statuses,\n currentRemote,\n resultLimit,\n ),\n [list, workspaces, query, archivedSessionIds, archivedFilter, statuses, currentRemote, resultLimit],\n )\n const pending = currentRemote.status === 'loading'\n const currentId = panelActive\n ? undefined\n : Object.values(list.byId).find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n\n return (\n <div className={clsx(css.treeBody, css.wide)}>\n <div className={css.list}>\n <div className={css.searchTree} role=\"tree\" aria-label={t('search.results.aria')}>\n {results.items.map(result => (\n <SearchResultItem\n key={result.id}\n result={result}\n currentId={currentId}\n onOpen={open}\n onUnarchive={onUnarchive}\n t={t}\n />\n ))}\n </div>\n {pending && (\n /* Two skeleton rows on an empty list, one when local matches already\n show and only the content hits are outstanding. */\n <div role=\"status\" aria-label={t('search.pending')}>\n {(results.items.length === 0 ? [0, 1] : [0]).map(i => (\n <div key={i} className={css.skeletonRow} aria-hidden=\"true\">\n <span className={css.skeletonDot} />\n <span className={css.skeletonBars}>\n <span className={css.skeletonBar} />\n <span className={clsx(css.skeletonBar, css.skeletonBarWide)} />\n </span>\n </div>\n ))}\n </div>\n )}\n {!pending && results.items.length === 0 && (\n <div className={css.empty}>{t('search.noMatches')}</div>\n )}\n {results.hasMore && (\n <div className={css.searchStatus}>\n {t('search.hasMore', { n: resultLimit })}\n </div>\n )}\n </div>\n <span className={css.fade} />\n </div>\n )\n}\n\n/**\n * Render the browsing region.\n * @param props - composed slot props (shell owner share + store + injected actions).\n * @returns the region element tree.\n */\nexport function WorkspaceBrowser({\n wide,\n usePanelInfo,\n expandSidebar,\n useSessions,\n useSessionStatus,\n useWorkspaces,\n useStore,\n actions,\n startSession,\n open,\n requestSessionRename,\n notifyArchivedNotOpenable,\n renameWorkspace,\n deleteWorkspace,\n insertWorkspaceBefore,\n unarchiveSession,\n createWorkspace,\n searchSessions,\n searchResultLimit,\n useDirectoryFlow,\n useHostInfo,\n useShortcuts,\n useWorkspaceShortcuts,\n useBadgeSettings,\n requestSearch,\n requestAddWorkspace,\n closeAddWorkspace,\n setDirectoryBusy,\n dismissForkError,\n renderSlot,\n t,\n}: WorkspaceBrowserProps) {\n const home = useHostInfo(info => info.home)\n const shortcuts = useShortcuts(rows => rows)\n const searchShortcut = shortcuts.find(row => row.id === 'session.search')\n const addShortcut = shortcuts.find(row => row.id === 'workspace.add')\n const shortcutState = useWorkspaceShortcuts(state => state)\n // Ordering remains live while the rail or search replaces the list body.\n const list = useSessions(state => state)\n const storedWorkspaces = useWorkspaces(state => state.items)\n // The resolved name, not `t`, is the memo dependency: the bound seat keeps\n // its identity across a language switch.\n const defaultWorkspaceName = t('workspace.defaultName')\n const workspaces = useMemo(\n () => storedWorkspaces.map(workspace => ({\n ...workspace,\n title: workspaceDisplayTitle(workspace.title, defaultWorkspaceName),\n })),\n [storedWorkspaces, defaultWorkspaceName],\n )\n const workspacePhase = useWorkspaces(state => state.phase)\n const workspaceStreamState = useWorkspaces(state => state.state)\n const archivedSessionIds = useWorkspaces(state => state.archivedSessionIds)\n const pinnedSessionIds = useWorkspaces(state => state.pinnedSessionIds)\n // Live occupancy of this surface's directory-flow hole (the same source the\n // flow reads): a composition without a picking affordance can add nothing.\n const directoryFlowAvailable = useDirectoryFlow(occupied => occupied)\n const groupBy = useStore(s => s.groupBy)\n const orderBy = useStore(s => s.orderBy)\n // Persisted view blobs written before the archived filter existed rehydrate\n // without the field; they read as the default hide-archived view.\n const archivedFilter = useStore(s => s.archivedFilter ?? 'default')\n const groupExpansion = useStore(s => s.groupExpansion)\n const sessionOrderByAccount = useStore(s => s.sessionOrderByAccount)\n // Archived sessions are not openable: the row stays visible under the\n // filter but a click explains instead of navigating.\n const guardedOpen = (sessionId: SessionId): void => {\n if (archivedSessionIds.includes(sessionId)) {\n notifyArchivedNotOpenable()\n return\n }\n open(sessionId)\n }\n const leaveArchivedOnly = (): void => { actions.setArchivedFilter('default') }\n const workspaceReady = workspacePhase === 'ready' && workspaceStreamState !== 'loading'\n const mainSessionId = Object.values(list.byId)\n .find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n const currentBlank = mainSessionId !== undefined && list.byId[mainSessionId]?.blank === true\n ? mainSessionId\n : undefined\n const ungroupedMemberIds = useMemo(() => {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return list.ids.filter(id => list.byId[id] !== undefined && !accounted.has(id))\n }, [list, workspaces])\n const orderState = useMemo(\n () => ({ pinnedSessionIds, archivedSessionIds }),\n [archivedSessionIds, pinnedSessionIds],\n )\n const rowState = useMemo<SessionRowState>(\n () => ({ ...orderState, archivedFilter }),\n [orderState, archivedFilter],\n )\n const flatMemberIds = useMemo(() => sessionMemberIds(list), [list])\n const orderedWorkspaces = useMemo(() => workspaces.map((workspace) => {\n const memberIds = workspace.sessionIds\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(memberIds, list.byId)\n : reconcileManualOrder(memberIds, sessionOrderByAccount[workspace.workspaceId], list.byId, orderState)\n return {\n ...workspace,\n sessionIds: pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && memberIds.includes(currentBlank) ? currentBlank : undefined,\n ),\n }\n }), [currentBlank, list.byId, orderBy, orderState, sessionOrderByAccount, workspaces])\n const orderedUngroupedSessionIds = useMemo(() => {\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(ungroupedMemberIds, list.byId)\n : reconcileManualOrder(ungroupedMemberIds, sessionOrderByAccount[UNGROUPED_KEY], list.byId, orderState)\n return pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && ungroupedMemberIds.includes(currentBlank) ? currentBlank : undefined,\n )\n }, [currentBlank, list.byId, orderBy, orderState, sessionOrderByAccount, ungroupedMemberIds])\n const orderedFlatSessionIds = useMemo(() => {\n const baseOrder = orderBy === 'updated'\n ? orderByRecency(flatMemberIds, list.byId)\n : reconcileManualOrder(flatMemberIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY], list.byId, orderState)\n return pinCurrentBlank(\n baseOrder,\n currentBlank !== undefined && flatMemberIds.includes(currentBlank) ? currentBlank : undefined,\n )\n }, [currentBlank, flatMemberIds, list.byId, orderBy, orderState, sessionOrderByAccount])\n const activeSessionOrders = useMemo<Readonly<Record<string, readonly SessionId[]>>>(() => Object.fromEntries([\n ...orderedWorkspaces.map(workspace => [workspace.workspaceId, workspace.sessionIds] as const),\n [UNGROUPED_KEY, orderedUngroupedSessionIds] as const,\n [FLAT_SESSION_ORDER_KEY, orderedFlatSessionIds] as const,\n ]), [orderedFlatSessionIds, orderedUngroupedSessionIds, orderedWorkspaces])\n useEffect(() => {\n if (workspacePhase !== 'ready') return\n actions.retainAccountKeys([\n UNGROUPED_KEY,\n FLAT_SESSION_ORDER_KEY,\n ...workspaces.map(workspace => workspace.workspaceId),\n ])\n }, [actions.retainAccountKeys, workspacePhase, workspaces])\n useEffect(() => {\n if (list.phase !== 'ready' || workspaceReady || orderBy !== 'manual' || currentBlank === undefined) return\n // A first prompt can end blank pinning before the Workspace baseline arrives.\n // Preserve saved members until that baseline can establish departures.\n const changed: Record<string, readonly string[]> = {}\n for (const [key, ids] of Object.entries(activeSessionOrders)) {\n if (key !== FLAT_SESSION_ORDER_KEY && workspacePhase !== 'ready') continue\n const saved = sessionOrderByAccount[key] ?? []\n if (ids[0] !== currentBlank || saved[0] === currentBlank) continue\n changed[key] = [currentBlank, ...saved.filter(id => id !== currentBlank)]\n }\n if (Object.keys(changed).length > 0) actions.syncSessionOrders(changed)\n }, [\n actions.syncSessionOrders,\n activeSessionOrders,\n currentBlank,\n list.phase,\n orderBy,\n sessionOrderByAccount,\n workspacePhase,\n workspaceReady,\n ])\n useEffect(() => {\n if (list.phase !== 'ready' || !workspaceReady || orderBy !== 'manual' || currentBlank === undefined) return\n const moved = Object.entries(activeSessionOrders).some(([key, ids]) =>\n ids[0] === currentBlank && sessionOrderByAccount[key]?.[0] !== currentBlank)\n if (moved) actions.syncSessionOrders(activeSessionOrders)\n }, [\n actions.syncSessionOrders,\n activeSessionOrders,\n currentBlank,\n list.phase,\n orderBy,\n sessionOrderByAccount,\n workspaceReady,\n ])\n const saveSessionOrder = (accountKey: string, order: readonly string[]): void => {\n actions.setSessionOrder(accountKey, order, activeSessionOrders)\n }\n // The query outlives the tree and the input (both wide-only) so collapsing\n // does not silently drop an in-progress filter.\n const [query, setQuery] = useState('')\n const [searchExpanded, setSearchExpanded] = useState(false)\n const [revealSessionId, setRevealSessionId] = useState<SessionId | undefined>(undefined)\n const normalizedQuery = sanitizeSearchQuery(query).trim()\n const [remoteSearch, setRemoteSearch] = useState<RemoteSearchState>({\n query: '',\n status: 'idle',\n items: [],\n hasMore: false,\n })\n const searchRoot = useRef<HTMLDivElement | null>(null)\n const searchInput = useRef<HTMLInputElement | null>(null)\n // Section-header + opens the picker menu (same popover in wide and rail\n // states; the menu anchors on this button).\n const wsPickerOpen = shortcutState.addRequested\n const wsPlusRef = useRef<HTMLButtonElement>(null)\n const composingRef = useRef(false)\n\n const openSearchResult = (sessionId: SessionId): void => {\n if (archivedSessionIds.includes(sessionId)) {\n notifyArchivedNotOpenable()\n return\n }\n setRevealSessionId(sessionId)\n setQuery('')\n setSearchExpanded(false)\n open(sessionId)\n }\n const acknowledgeSessionReveal = (sessionId: SessionId): void => {\n setRevealSessionId(current => current === sessionId ? undefined : current)\n }\n useEffect(() => {\n if (normalizedQuery !== '') setRevealSessionId(undefined)\n }, [normalizedQuery])\n\n // Rail search = expand + land in the search box: the flag arms before the\n // expand request; once the shell flips wide the input mounts and takes focus.\n const [searchOnExpand, setSearchOnExpand] = useState(false)\n useEffect(() => {\n if (wide && searchOnExpand) {\n const timer = window.setTimeout(() => {\n searchInput.current?.focus({ preventScroll: true })\n setSearchOnExpand(false)\n }, EXPAND_SLIDE_MS)\n return () => { window.clearTimeout(timer) }\n }\n }, [wide, searchOnExpand])\n useEffect(() => {\n if (shortcutState.searchRequest === 0) return\n closeAddWorkspace()\n setSearchExpanded(true)\n if (!wide) {\n setSearchOnExpand(true)\n expandSidebar()\n } else searchInput.current?.focus({ preventScroll: true })\n }, [shortcutState.searchRequest])\n\n useEffect(() => {\n if (!wide || !searchExpanded || searchOnExpand) return\n searchInput.current?.focus({ preventScroll: true })\n }, [wide, searchExpanded, searchOnExpand])\n\n // Outside-click dismissal stays off while the rail gesture is in flight\n // (searchOnExpand): the rail click flips the shell wide and mounts this\n // listener during its own dispatch, then keeps bubbling to document with\n // the now-unmounted rail button as its target — outside searchRoot, so the\n // listener would dismiss the search that click just opened.\n useEffect(() => {\n if (!wide || !searchExpanded || searchOnExpand) return\n const onClick = (event: MouseEvent): void => {\n if (!(event.target instanceof Node) || searchRoot.current?.contains(event.target) === true) return\n searchInput.current?.blur()\n if (normalizedQuery !== '') return\n setSearchExpanded(false)\n }\n document.addEventListener('click', onClick)\n return () => { document.removeEventListener('click', onClick) }\n }, [normalizedQuery, wide, searchExpanded, searchOnExpand])\n\n useEffect(() => {\n if (normalizedQuery === '') {\n setRemoteSearch({ query: '', status: 'idle', items: [], hasMore: false })\n return\n }\n const controller = new AbortController()\n setRemoteSearch({\n query: normalizedQuery,\n status: 'loading',\n items: [],\n hasMore: false,\n })\n const timer = window.setTimeout(() => {\n searchSessions(normalizedQuery, controller.signal).then((result) => {\n if (controller.signal.aborted) return\n setRemoteSearch({\n query: normalizedQuery,\n status: 'ready',\n items: result.items,\n hasMore: result.hasMore,\n })\n }).catch(() => {\n if (controller.signal.aborted) return\n setRemoteSearch({\n query: normalizedQuery,\n status: 'error',\n items: [],\n hasMore: false,\n })\n })\n }, SEARCH_DEBOUNCE_MS)\n return () => {\n window.clearTimeout(timer)\n controller.abort()\n }\n }, [normalizedQuery, searchSessions])\n\n // Rename dialog (browser-owned so it outlives row unmounts during collapse).\n // The stored title decides whether confirming is a real rename; the draft is\n // seeded with the label on screen. They differ for a Workspace still\n // carrying its automatic title, so confirming the prefill pins that name.\n const [renameTarget, setRenameTarget] = useState<{ workspaceId: WorkspaceId; storedTitle: string } | null>(null)\n const [renameDraft, setRenameDraft] = useState('')\n const [renaming, setRenaming] = useState(false)\n const [renameError, setRenameError] = useState<string | null>(null)\n const renameTrimmed = renameDraft.trim()\n // Self is excluded by identity, not by title: the draft is seeded with the\n // localized label, which for an automatically titled Workspace equals its\n // own displayed title without being a conflict with itself.\n const renameDuplicate = renameTarget !== null && renameTrimmed !== ''\n && workspaces.some(w => w.workspaceId !== renameTarget.workspaceId && w.title === renameTrimmed)\n const renameBlocked = renaming || renameTrimmed === ''\n || renameTarget === null || renameTrimmed === renameTarget.storedTitle || renameDuplicate\n const closeRename = () => {\n if (renaming) return\n setRenameTarget(null)\n setRenameError(null)\n }\n const confirmRename = () => {\n if (renameBlocked) return\n setRenaming(true)\n setRenameError(null)\n renameWorkspace(renameTarget.workspaceId, renameTrimmed).then(() => {\n setRenaming(false)\n setRenameTarget(null)\n }).catch((reason: unknown) => {\n setRenaming(false)\n setRenameError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n\n // The search results' restore button; the row actions own the rest of the\n // Session verbs as slot entries.\n const onSessionUnarchive = (sessionId: SessionNode['id']) => {\n unarchiveSession(sessionId).catch((reason: unknown) => {\n console.warn('session unarchive rejected:', reason)\n })\n }\n\n // Delete dialog is separate from the row so a successful removal can\n // unmount that row without tearing down the in-flight confirmation state.\n const [deleteTarget, setDeleteTarget] = useState<{ workspaceId: WorkspaceId; title: string } | null>(null)\n const [deleting, setDeleting] = useState(false)\n const [deleteCommittedId, setDeleteCommittedId] = useState<WorkspaceId | null>(null)\n const [deleteError, setDeleteError] = useState<string | null>(null)\n useEffect(() => {\n if (deleteCommittedId === null\n || workspaces.some(workspace => workspace.workspaceId === deleteCommittedId)) return\n setDeleting(false)\n setDeleteCommittedId(null)\n setDeleteTarget(null)\n }, [deleteCommittedId, workspaces])\n const closeDelete = () => {\n if (deleting) return\n setDeleteTarget(null)\n setDeleteError(null)\n }\n const confirmDelete = () => {\n /* v8 ignore next -- the Modal is absent without a target and its button is disabled while deleting. */\n if (deleting || deleteTarget === null) return\n setDeleting(true)\n setDeleteCommittedId(null)\n setDeleteError(null)\n deleteWorkspace(deleteTarget.workspaceId).then(() => {\n // Keep the confirmation pending until this component has rendered the\n // committed list projection without the deleted id. Closing earlier\n // exposes one stale React frame to the next Create Workspace gesture.\n setDeleteCommittedId(deleteTarget.workspaceId)\n }).catch((reason: unknown) => {\n setDeleting(false)\n setDeleteError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n\n return (\n <div className={clsx(css.root, !wide && css.rail)}>\n <div className={css.sectionHeader}>\n {wide && (\n <span className={clsx(css.sectionLabel, css.wide, searchExpanded && css.sectionLabelHidden)}>\n {groupBy === 'flat' ? t('section.sessions') : t('section.workspaces')}\n </span>\n )}\n {wide && (\n <div className={clsx(css.searchSlot, searchExpanded && css.searchSlotExpanded)}>\n <div\n ref={searchRoot}\n className={clsx(css.search, searchExpanded && css.searchExpanded)}\n onClick={() => {\n closeAddWorkspace()\n setSearchExpanded(true)\n searchInput.current?.focus()\n }}\n >\n <Tooltip label={t('search')} shortcutKeys={searchShortcut?.keys} side=\"bottom\" delayMs={500} disabled={searchExpanded}>\n <button\n type=\"button\"\n className={css.searchButton}\n aria-label={t('search.sessions.aria')}\n aria-keyshortcuts={searchShortcut?.aria}\n aria-expanded={searchExpanded}\n onClick={() => {\n requestSearch()\n }}\n >\n <IconSearchOutlineRegular size={searchExpanded ? 11 : 14} />\n </button>\n </Tooltip>\n <input\n ref={searchInput}\n className={css.searchInput}\n type=\"text\"\n placeholder={t('search.placeholder')}\n maxLength={SEARCH_QUERY_MAX_CODE_UNITS}\n value={query}\n tabIndex={searchExpanded ? 0 : -1}\n onChange={(e) => { setQuery(sanitizeSearchQuery(e.target.value)) }}\n onKeyDown={(e) => {\n if (e.key !== 'Escape') return\n setQuery('')\n setSearchExpanded(false)\n }}\n />\n {searchExpanded && (\n <button\n type=\"button\"\n className={css.clearButton}\n aria-label={t('search.clear')}\n onClick={(e) => {\n e.stopPropagation()\n setQuery('')\n setSearchExpanded(false)\n }}\n >\n <IconCloseFillRegular />\n </button>\n )}\n </div>\n </div>\n )}\n <div className={clsx(css.headerActions, wide && searchExpanded && css.headerActionsHidden)}>\n {wide && (\n <ViewOptionsMenu\n groupBy={groupBy}\n orderBy={orderBy}\n archivedFilter={archivedFilter}\n onGroupPick={actions.setGroupBy}\n onOrderPick={(mode) => { actions.setOrderBy(mode, activeSessionOrders) }}\n onArchivedFilterPick={actions.setArchivedFilter}\n t={t}\n />\n )}\n {/* Adding is the button's one action, so a composition with no\n picking affordance has nothing to offer here: the region hides the\n button rather than leaving a dead one in the header. */}\n {directoryFlowAvailable && (\n <Tooltip label={t('workspace.add')} shortcutKeys={addShortcut?.keys} side=\"bottom\" delayMs={500}>\n <button\n ref={wsPlusRef}\n type=\"button\"\n className={css.iconButton}\n aria-label={t('workspace.add')}\n aria-keyshortcuts={addShortcut?.aria}\n onClick={() => {\n requestAddWorkspace()\n }}\n >\n <IconProjectAddOutlineRegular size={wide ? 16 : 18} />\n </button>\n </Tooltip>\n )}\n </div>\n {/* Add flow + its error dialog (same package — direct composition). */}\n <WorkspacePickFlow\n t={t}\n open={wsPickerOpen}\n anchorRef={wsPlusRef}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('sidebar.workspaces.directoryFlow', owner)}\n addOnly\n onBusyChange={setDirectoryBusy}\n side=\"right\"\n onPick={(workspaceId) => {\n closeAddWorkspace()\n startSession(workspaceId)\n }}\n onClose={() => { closeAddWorkspace() }}\n />\n </div>\n\n {/* The collapsed rail keeps search as its own 36px control. */}\n {!wide && <div className={css.search}>\n <Tooltip label={t('search')} shortcutKeys={searchShortcut?.keys}>\n <button\n type=\"button\"\n className={css.searchButton}\n aria-label={t('search.sessions.aria')}\n aria-keyshortcuts={searchShortcut?.aria}\n onClick={() => {\n requestSearch()\n }}\n >\n <IconSearchOutlineRegular size={18} />\n </button>\n </Tooltip>\n </div>}\n\n {/* Always-mounted seat keeps the region's flex slot while the list\n itself is wide-only. */}\n <div className={css.listArea}>\n {wide && (normalizedQuery !== ''\n ? (\n <SearchResults\n usePanelInfo={usePanelInfo}\n useSessions={useSessions}\n useSessionStatus={useSessionStatus}\n open={openSearchResult}\n onUnarchive={onSessionUnarchive}\n workspaces={workspaces}\n archivedSessionIds={archivedSessionIds}\n archivedFilter={archivedFilter}\n query={normalizedQuery}\n remote={remoteSearch}\n resultLimit={searchResultLimit}\n t={t}\n />\n )\n : groupBy === 'flat'\n ? (\n <FlatList\n usePanelInfo={usePanelInfo}\n list={list}\n sessionIds={orderedFlatSessionIds}\n rowState={rowState}\n onLeaveArchivedOnly={leaveArchivedOnly}\n workspaceReady={workspaceReady}\n animationResetKey={`${groupBy}/${orderBy}/${archivedFilter}`}\n useSessionStatus={useSessionStatus}\n open={guardedOpen}\n onSessionRenameRequest={requestSessionRename}\n renderSlot={renderSlot}\n setSessionOrder={saveSessionOrder}\n revealSessionId={revealSessionId}\n onSessionRevealed={acknowledgeSessionReveal}\n t={t}\n />\n )\n : (\n <SessionTree\n usePanelInfo={usePanelInfo}\n useBadgeSettings={useBadgeSettings}\n list={list}\n shortcuts={shortcuts}\n useSessionStatus={useSessionStatus}\n onSessionRenameRequest={requestSessionRename}\n renderSlot={renderSlot}\n workspaces={orderedWorkspaces}\n ungroupedSessionIds={orderedUngroupedSessionIds}\n workspaceReady={workspaceReady}\n nestWorkspaces={groupBy === 'workspace-tree'}\n animationResetKey={`${groupBy}/${orderBy}/${archivedFilter}`}\n groupExpansion={groupExpansion}\n setGroupExpanded={actions.setGroupExpanded}\n setSessionOrder={saveSessionOrder}\n rowState={rowState}\n onLeaveArchivedOnly={leaveArchivedOnly}\n startSession={startSession}\n open={guardedOpen}\n insertWorkspaceBefore={insertWorkspaceBefore}\n revealSessionId={revealSessionId}\n onSessionRevealed={acknowledgeSessionReveal}\n home={home}\n t={t}\n onRenameRequest={(workspaceId, displayTitle) => {\n setRenameTarget({\n workspaceId,\n storedTitle: storedWorkspaces.find(w => w.workspaceId === workspaceId)?.title ?? displayTitle,\n })\n setRenameDraft(displayTitle)\n setRenameError(null)\n }}\n onDeleteRequest={(workspaceId, title) => {\n setDeleteTarget({ workspaceId, title })\n setDeleteError(null)\n }}\n />\n ))}\n </div>\n\n <Modal\n open={renameTarget !== null}\n onClose={closeRename}\n closeLabel={t('close')}\n title={t('rename.workspace.title')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={renaming} onClick={closeRename}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={renameBlocked} onClick={confirmRename}>{t('rename')}</Button>\n </>\n )}\n >\n <input\n className={css.renameInput}\n value={renameDraft}\n aria-label={t('field.workspaceName')}\n data-modal-autofocus\n disabled={renaming}\n onFocus={(e) => { e.target.select() }}\n onChange={(e) => { setRenameDraft(e.target.value); setRenameError(null) }}\n onCompositionStart={() => { composingRef.current = true }}\n onCompositionEnd={() => { composingRef.current = false }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !composingRef.current) {\n e.preventDefault()\n confirmRename()\n }\n }}\n />\n {renameDuplicate && (\n <div className={css.renameError} role=\"alert\">{t('conflict.named', { name: renameTrimmed })}</div>\n )}\n {renameError !== null && <div className={css.renameError} role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={deleteTarget !== null}\n onClose={closeDelete}\n closeLabel={t('close')}\n title={t('delete.workspace')}\n {...deleteTarget === null\n ? {}\n : { description: t('delete.desc', { name: deleteTarget.title }) }}\n footer={(\n <>\n <Button variant=\"outline\" disabled={deleting} onClick={closeDelete}>{t('cancel')}</Button>\n <Button\n variant=\"outline\"\n className={css.deleteAction}\n disabled={deleting}\n onClick={confirmDelete}\n >\n {t('delete.workspace')}\n </Button>\n </>\n )}\n >\n {deleting && <div className={css.deleteStatus} role=\"status\">{t('delete.pending')}</div>}\n {deleteError !== null && <div className={css.renameError} role=\"alert\">{deleteError}</div>}\n </Modal>\n {shortcutState.forkError !== null && <Toast key={shortcutState.forkError.seq}\n text={t(shortcutState.forkError.reason === 'unavailable' ? 'shortcut.noCompletedTurn' : 'shortcut.forkFailed')}\n onDone={dismissForkError} />}\n </div>\n )\n}\n","/**\n * The archive action: a `sidebar.workspaces.session.menu.item` row and a\n * `sidebar.workspaces.session.row.action` button over one injected behavior,\n * plus the `shell.overlay` dialog that confirms stopping a Session's running\n * work before archiving it. The same entries restore an archived row; the\n * notice a successful archive raises and the diagnostics for Host rejections\n * live in the injected callbacks, not here.\n */\nimport { useState } from 'react'\nimport type { SessionActivity } from '@deepseek-ai/dsh-api-workspace-controller/client'\n// Type-only: the family keys each provider merges; a key this program did not compile takes the generic line.\nimport type {} from '@deepseek-ai/dsh-agent/types'\nimport type {} from '@deepseek-ai/dsh-jobs/view'\nimport type {} from '@deepseek-ai/dsh-schedule/client'\nimport type {} from '@deepseek-ai/dsh-subagent/client'\nimport {\n Button, IconArchiveOutlineRegular, IconUnarchiveOutlineRegular, MenuItemButton, Modal, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n ArchiveSessionInjected, SessionArchiveConfirmInjected, SessionArchiveConfirmProps, SessionArchiveConfirmRequest,\n SessionMenuItemProps, SessionRowActionProps,\n} from '../contract/slots.ts'\nimport css from '../rows/Rows.module.css'\nimport browserCss from '../rows/WorkspaceBrowser.module.css'\n\n/**\n * Menu row (order 400): archive, or restore an archived row.\n * @param props - owner share, the archive share, and the menu open state.\n * @returns the row.\n */\nexport function ArchiveSessionMenuItem({\n sessionId, useArchived, useMenuOpenState, useShortcuts, archiveSession, unarchiveSession, t,\n}: SessionMenuItemProps<ArchiveSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.archive'))\n const archived = useArchived(set => set.has(sessionId))\n return (\n <MenuItemButton\n shortcut={archived ? undefined : shortcut}\n icon={archived ? <IconUnarchiveOutlineRegular size={14} /> : <IconArchiveOutlineRegular size={14} />}\n onSelect={() => {\n setMenuOpen(false)\n ;(archived ? unarchiveSession : archiveSession)(sessionId)\n }}\n >\n {t(archived ? 'menu.unarchiveSession' : 'menu.archiveSession')}\n </MenuItemButton>\n )\n}\n\n/**\n * Hover button (order 100): archive, or restore an archived row.\n * @param props - owner share and the archive share.\n * @returns the button.\n */\nexport function ArchiveSessionRowButton({\n sessionId, useArchived, archiveSession, unarchiveSession, t,\n}: SessionRowActionProps<ArchiveSessionInjected>) {\n const archived = useArchived(set => set.has(sessionId))\n return (\n <Tooltip label={t(archived ? 'actions.unarchive' : 'actions.archive')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t(archived ? 'menu.unarchiveSession' : 'menu.archiveSession')}\n onClick={() => { (archived ? unarchiveSession : archiveSession)(sessionId) }}\n >\n {archived ? <IconUnarchiveOutlineRegular size={14} /> : <IconArchiveOutlineRegular size={14} />}\n </button>\n </Tooltip>\n )\n}\n\n/**\n * The `shell.overlay` entry: nothing while no confirmation is pending,\n * otherwise one dialog per request (keyed by the Session). Confirming asks\n * the Host to stop the listed work and archive; cancelling leaves the\n * Session running and visible.\n * @param props - the request hook, its settlement, the stop-and-archive hop, and the locale seat.\n * @returns the open dialog, or null.\n */\nexport function SessionArchiveConfirmDialog({\n useArchiveRequest, settleSessionArchive, stopAndArchiveSession, t,\n}: SessionArchiveConfirmProps) {\n const request = useArchiveRequest(pending => pending)\n if (request === null) return null\n return (\n <ArchiveConfirmForm\n key={request.sessionId}\n request={request}\n stopAndArchiveSession={stopAndArchiveSession}\n onSettle={settleSessionArchive}\n t={t}\n />\n )\n}\n\n/** One request's dialog: in-flight and error state die with it. */\nfunction ArchiveConfirmForm({ request, stopAndArchiveSession, onSettle, t }: {\n request: SessionArchiveConfirmRequest\n stopAndArchiveSession: SessionArchiveConfirmInjected['stopAndArchiveSession']\n onSettle: () => void\n t: SessionArchiveConfirmProps['t']\n}) {\n const [archiving, setArchiving] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const close = () => {\n if (archiving) return\n onSettle()\n }\n const confirm = () => {\n setArchiving(true)\n setError(null)\n stopAndArchiveSession(request.sessionId).then(() => {\n setArchiving(false)\n onSettle()\n }).catch((reason: unknown) => {\n setArchiving(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n return (\n <Modal\n open\n onClose={close}\n closeLabel={t('close')}\n title={t('archive.confirm.title')}\n description={t('archive.confirm.desc', { title: request.displayTitle })}\n footer={(\n <>\n <Button variant=\"outline\" disabled={archiving} onClick={close}>{t('cancel')}</Button>\n <Button\n variant=\"outline\"\n className={browserCss.deleteAction}\n disabled={archiving}\n onClick={confirm}\n >\n {t('archive.confirm.action')}\n </Button>\n </>\n )}\n >\n <ul className={browserCss.archiveActivity} aria-label={t('archive.confirm.activity')}>\n {request.activity.map((entry, index) => (\n <li key={`${entry.kind}-${String(index)}`}>{activityLine(entry, t)}</li>\n ))}\n </ul>\n {archiving && <div className={browserCss.deleteStatus} role=\"status\">{t('archive.confirm.pending')}</div>}\n {error !== null && <div className={browserCss.renameError} role=\"alert\">{error}</div>}\n </Modal>\n )\n}\n\n/**\n * One family's line: its count and the items' labels (ids when a family\n * carries no label). A family this dictionary does not know — a provider\n * merged into the kind map — falls through to the generic line.\n */\nfunction activityLine(entry: SessionActivity, t: SessionArchiveConfirmProps['t']): string {\n const items = entry.items ?? []\n const n = items.length\n const names = items.map(item => item.label ?? item.id).join(t('archive.confirm.listSeparator'))\n const plural = n === 1 ? 'one' : 'other'\n switch (entry.kind) {\n case 'turn': return t('archive.confirm.turn')\n case 'subagent': return t(`archive.confirm.subagents.${plural}`, { n, names })\n case 'job': return t(`archive.confirm.jobs.${plural}`, { n, names })\n case 'schedule': return t(`archive.confirm.schedules.${plural}`, { n, names })\n default: return t(`archive.confirm.other.${plural}`, { kind: entry.kind, n })\n }\n}\n","/** Derived observable sources for the row actions' injected hooks. */\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\n\n/**\n * Project one observable into another, recomputing only when the source\n * snapshot changes identity, so consumers that select from the projection\n * (a Set lookup per row) never rebuild it per read.\n * @param source - the observable to project.\n * @param project - pure projection of one source snapshot.\n * @returns the projected observable, subscribing through the source.\n */\nexport function derive<S, T>(source: HostObservable<S>, project: (snapshot: S) => T): HostObservable<T> {\n let seen: S | undefined\n let value: T | undefined\n return {\n getSnapshot: () => {\n const snapshot = source.getSnapshot()\n if (value === undefined || snapshot !== seen) {\n seen = snapshot\n value = project(snapshot)\n }\n return value\n },\n subscribe: listener => source.subscribe(listener),\n }\n}\n","/** The fork action: one `sidebar.workspaces.session.menu.item` row. */\nimport { IconBranchOutlineRegular, MenuItemButton } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ForkSessionInjected, SessionMenuItemProps } from '../contract/slots.ts'\n\n/**\n * Menu row (order 300): fork at the Session's last completed turn; the child\n * arrives through the Host list beside its source.\n * @param props - owner share, menu open state, and the fork share.\n * @returns the row.\n */\nexport function ForkSessionMenuItem({\n sessionId, useMenuOpenState, useShortcuts, forkSession, t,\n}: SessionMenuItemProps<ForkSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.fork'))\n return (\n <MenuItemButton\n shortcut={shortcut}\n icon={<IconBranchOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n forkSession(sessionId)\n }}\n >\n {t('menu.fork')}\n </MenuItemButton>\n )\n}\n","/**\n * The pin action: a `sidebar.workspaces.session.menu.item` row and a\n * `sidebar.workspaces.session.row.action` button over one injected behavior.\n * Pin and archive are mutually exclusive on the Host, so the action reads both\n * sets and does not offer itself on an archived row; what a pin does beyond\n * the Host call (fronting the Session in its saved orders, the failure\n * notice) lives in the injected callbacks, not here.\n */\nimport {\n IconPinFillRegular, IconPinOutlineRegular, MenuItemButton, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PinSessionInjected, SessionMenuItemProps, SessionRowActionProps } from '../contract/slots.ts'\nimport css from '../rows/Rows.module.css'\n\ntype PinState = Pick<SessionMenuItemProps<PinSessionInjected>, 'sessionId' | 'usePinned' | 'useArchived'>\n\n/** The row's pin and archive membership, one Set lookup each. */\nfunction usePinState({ sessionId, usePinned, useArchived }: PinState) {\n return {\n pinned: usePinned(pinned => pinned.has(sessionId)),\n archived: useArchived(archived => archived.has(sessionId)),\n }\n}\n\n/**\n * Menu row (order 100): pin or unpin by the row's current state; absent on archived rows.\n * @param props - owner share, the pin share, and the menu open state.\n * @returns the row, or null for an archived Session.\n */\nexport function PinSessionMenuItem(props: SessionMenuItemProps<PinSessionInjected>) {\n const { sessionId, useMenuOpenState, pinSession, unpinSession, t } = props\n const [, setMenuOpen] = useMenuOpenState()\n const { pinned, archived } = usePinState(props)\n if (archived) return null\n return (\n <MenuItemButton\n icon={pinned ? <IconPinFillRegular /> : <IconPinOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n ;(pinned ? unpinSession : pinSession)(sessionId)\n }}\n >\n {t(pinned ? 'menu.unpinSession' : 'menu.pinSession')}\n </MenuItemButton>\n )\n}\n\n/**\n * Hover button (order 200, rightmost: it lands where the rest-state pin marker sits); absent on archived rows.\n * @param props - owner share and the pin share.\n * @returns the button, or null for an archived Session.\n */\nexport function PinSessionRowButton(props: SessionRowActionProps<PinSessionInjected>) {\n const { sessionId, pinSession, unpinSession, t } = props\n const { pinned, archived } = usePinState(props)\n if (archived) return null\n return (\n <Tooltip label={t(pinned ? 'actions.unpin' : 'actions.pin')} side=\"bottom\" align=\"end\" delayMs={500}>\n <button\n type=\"button\"\n className={css.iconButton}\n aria-label={t(pinned ? 'menu.unpinSession' : 'menu.pinSession')}\n onClick={() => { (pinned ? unpinSession : pinSession)(sessionId) }}\n >\n {pinned ? <IconPinFillRegular size={14} /> : <IconPinOutlineRegular size={14} />}\n </button>\n </Tooltip>\n )\n}\n","/**\n * The rename action: a `sidebar.workspaces.session.menu.item` row that raises\n * the rename request, and the `shell.overlay` dialog entry that answers it.\n * The dialog lives outside the row menu because the row unmounts with the\n * menu; the browser raises the same request from a title double-click.\n */\nimport { useRef, useState } from 'react'\nimport { Button, IconEditOutlineRegular, MenuItemButton, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n RenameSessionInjected, SessionMenuItemProps, SessionRenameDialogInjected, SessionRenameDialogProps, SessionRenameTarget,\n} from '../contract/slots.ts'\nimport css from '../rows/WorkspaceBrowser.module.css'\n\n/**\n * Menu row (order 200): ask for the rename dialog, seeded with the row's current title.\n * @param props - owner share, menu open state, and the rename share.\n * @returns the row.\n */\nexport function RenameSessionMenuItem({\n sessionId, displayTitle, useMenuOpenState, useShortcuts, requestSessionRename, t,\n}: SessionMenuItemProps<RenameSessionInjected>) {\n const [, setMenuOpen] = useMenuOpenState()\n const shortcut = useShortcuts(rows => rows.find(row => row.id === 'session.rename'))\n return (\n <MenuItemButton\n shortcut={shortcut}\n icon={<IconEditOutlineRegular />}\n onSelect={() => {\n setMenuOpen(false)\n requestSessionRename(sessionId, displayTitle)\n }}\n >\n {t('rename')}\n </MenuItemButton>\n )\n}\n\n/**\n * The `shell.overlay` entry: nothing while no rename is requested, otherwise\n * one dialog per request (keyed by the Session, so a new request starts a\n * fresh draft). Sessions have no client-side name-conflict rule (the host\n * normalizes), and unlike Workspace rename an unchanged title is NOT\n * blocked. An unnamed Session starts with an empty draft and requires a name.\n * @param props - the request hook, its settlement, the rename hop, and the locale seat.\n * @returns the open dialog, or null.\n */\nexport function SessionRenameDialog({ useRenameRequest, settleSessionRename, renameSession, t }: SessionRenameDialogProps) {\n const request = useRenameRequest(pending => pending)\n if (request === null) return null\n return (\n <RenameForm\n key={request.sessionId}\n request={request}\n renameSession={renameSession}\n onSettle={settleSessionRename}\n t={t}\n />\n )\n}\n\n/** One request's dialog: the draft seeds from the request on mount; in-flight and error state die with it. */\nfunction RenameForm({ request, renameSession, onSettle, t }: {\n request: SessionRenameTarget\n renameSession: SessionRenameDialogInjected['renameSession']\n onSettle: () => void\n t: SessionRenameDialogProps['t']\n}) {\n const [draft, setDraft] = useState(request.currentTitle)\n const [renaming, setRenaming] = useState(false)\n const [error, setError] = useState<string | null>(null)\n // IME composition: Enter that commits a composition must not submit.\n const composingRef = useRef(false)\n const trimmed = draft.trim()\n const blocked = renaming || trimmed === ''\n const close = () => {\n if (renaming) return\n onSettle()\n }\n const confirm = () => {\n if (blocked) return\n setRenaming(true)\n setError(null)\n renameSession(request.sessionId, trimmed).then(() => {\n setRenaming(false)\n onSettle()\n }).catch((reason: unknown) => {\n setRenaming(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n return (\n <Modal\n open\n onClose={close}\n closeLabel={t('close')}\n title={t('rename.session.title')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={renaming} onClick={close}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={blocked} onClick={confirm}>{t('rename')}</Button>\n </>\n )}\n >\n <input\n className={css.renameInput}\n value={draft}\n aria-label={t('field.sessionName')}\n data-modal-autofocus\n disabled={renaming}\n onFocus={(e) => { e.target.select() }}\n onChange={(e) => { setDraft(e.target.value); setError(null) }}\n onCompositionStart={() => { composingRef.current = true }}\n onCompositionEnd={() => { composingRef.current = false }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !composingRef.current) {\n e.preventDefault()\n confirm()\n }\n }}\n />\n {error !== null && <div className={css.renameError} role=\"alert\">{error}</div>}\n </Modal>\n )\n}\n","/**\n * The `shell.overlay` entry for Workspace and Session notices.\n * One notice is visible at a time; a parent rerender does not extend its hold.\n */\nimport { IconWarningOutlineRegular, Toast } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { assertNever } from '@deepseek-ai/dsh-util-values'\nimport type { RowToastProps, RowToastState } from '../contract/slots.ts'\n\n/**\n * Hold for the notices that take longer to read than a one-line warning: the\n * actionable archived notice (two buttons to react to) and a refused Session\n * creation, which quotes the Host's reason.\n */\nconst LONG_TOAST_HOLD_MS = 6000\n\n/**\n * Render the current notice: the archived and stopped-and-archived notices\n * with their undo action — plus the show-archived action while archived rows\n * are hidden — on a 6 s hold, a refused Session creation with the Host's\n * reason on the same hold, or a plain warning for a failed pin, an archived\n * row that was clicked, or default Workspace creation.\n * @param props - the notice hook, the shared viewing store, the notice dismissal, the two archived-notice actions, and the locale seat.\n * @returns the notice on display, or null.\n */\nexport function RowActionToast({ useToast, useStore, dismissToast, undoArchive, showArchived, t }: RowToastProps) {\n const toast = useToast(current => current)\n const archivedRowsVisible = useStore(state => (state.archivedFilter ?? 'default') !== 'default')\n if (toast === null) return null\n if (toast.kind === 'archived' || toast.kind === 'stoppedAndArchived') {\n const { sessionId } = toast\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={t(toast.kind === 'archived' ? 'toast.archived' : 'toast.stoppedAndArchived')}\n tone=\"success\"\n holdMs={LONG_TOAST_HOLD_MS}\n actions={[\n { label: t('toast.archivedUndo'), onClick: () => { dismissToast(); undoArchive(sessionId) } },\n ...archivedRowsVisible ? [] : [\n { prefix: t('toast.archivedOr'), label: t('toast.archivedFilter'), onClick: () => { dismissToast(); showArchived() } },\n ],\n ]}\n onDone={dismissToast}\n />\n )\n }\n if (toast.kind === 'createFailed') {\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={t('toast.createFailed', { message: toast.message })}\n icon={<IconWarningOutlineRegular />}\n holdMs={LONG_TOAST_HOLD_MS}\n onDone={dismissToast}\n />\n )\n }\n return (\n <Toast\n key={`toast-${String(toast.seq)}`}\n text={plainNoticeText(toast, t)}\n icon={<IconWarningOutlineRegular />}\n onDone={dismissToast}\n />\n )\n}\n\n/** The copy of one plain warning, keyed by the notice kind the union closes over. */\nfunction plainNoticeText(\n toast: Exclude<RowToastState, { kind: 'archived' | 'stoppedAndArchived' | 'createFailed' }>,\n t: RowToastProps['t'],\n): string {\n switch (toast.kind) {\n case 'pinFailed': return t('toast.pinFailed')\n case 'unpinFailed': return t('toast.unpinFailed')\n case 'defaultWorkspaceFailed': return t('defaultWorkspace.failed')\n case 'archivedNotOpenable': return t('toast.archivedNotOpenable')\n /* v8 ignore next 2 -- closed-union backstop; only reached if a notice kind is forged */\n default:\n return assertNever(toast)\n }\n}\n","/**\n * `workspace` namespace dictionaries: the browsing region (section header,\n * search, tree rows, dialogs) and the pick/add flow. Runtime failure\n * messages (wire error strings) pass through untranslated by policy.\n */\n\n/** Simplified Chinese dictionary (the key-set source of truth). */\nexport const zh = {\n 'defaultWorkspace.failed': '无法创建默认工作区,请通过“选择工作区”选择文件夹',\n 'group.ungrouped': '未分组',\n 'session.new': '新会话',\n 'session.untitled': '未命名',\n 'shortcut.noSession': '请先选择一个会话',\n 'shortcut.noPicker': '目录选择器不可用',\n 'shortcut.directoryBusy': '正在选择或添加工作区',\n 'shortcut.noCompletedTurn': '当前会话没有已结束的轮次',\n 'shortcut.forkFailed': '无法分叉会话,请重试',\n 'section.workspaces': '工作区',\n 'section.sessions': '会话',\n 'viewOptions.label': '视图选项',\n 'groupBy.label': '分组方式',\n 'groupBy.workspace': '按工作区',\n 'groupBy.workspaceTree': '按工作区树',\n 'groupBy.flat': '单列表',\n 'orderBy.label': '排序方式',\n 'orderBy.manual': '手动排序',\n 'orderBy.updated': '最近更新',\n 'filterBy.label': '筛选会话',\n 'viewOptions.hideArchived': '隐藏已归档',\n 'viewOptions.showArchived': '全部对话(显示已归档)',\n 'viewOptions.onlyArchived': '仅显示已归档',\n 'sessions.expand': '展开其余 {n} 个会话',\n 'sessions.collapse': '收起',\n 'empty.none': '暂无会话',\n 'empty.noneArchived': '暂无已归档会话',\n 'empty.viewOthers': '查看其他会话',\n 'empty.noMatches': '无匹配结果',\n 'workspace.add': '添加工作区',\n 'search.sessions.aria': '搜索会话',\n 'search.placeholder': '搜索会话名称',\n 'search.clear': '清除搜索',\n 'search.results.aria': '搜索结果',\n 'search.pending': '正在搜索会话历史…',\n 'search.noMatches': '无匹配会话',\n 'search.hasMore': '仅显示前 {n} 条结果,请缩小搜索范围。',\n 'menu.addWorkspace': '添加工作区…',\n 'picker.loading': '正在加载工作区…',\n 'conflict.named': '已存在名为“{name}”的工作区。',\n 'folderError.title': '无法打开文件夹',\n 'folderError.retry': '重新选择',\n 'rename': '重命名',\n 'rename.workspace.title': '重命名工作区',\n 'rename.session.title': '重命名会话',\n 'field.workspaceName': '工作区名称',\n 'field.sessionName': '会话名称',\n 'delete.workspace': '删除工作区',\n 'delete.desc': '将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。',\n 'delete.pending': '正在删除工作区…',\n 'menu.fork': '分叉会话',\n 'menu.archiveSession': '归档会话',\n 'menu.unarchiveSession': '取消归档',\n 'menu.pinSession': '置顶会话',\n 'menu.unpinSession': '取消置顶',\n 'row.archived': '已归档',\n 'row.pinned': '已置顶',\n 'toast.archivedNotOpenable': '已归档对话暂时无法查看,请取消归档后查看',\n 'toast.archived': '会话已归档,可',\n 'toast.stoppedAndArchived': '已停止并归档,可',\n 'archive.confirm.title': '停止并归档此会话?',\n 'archive.confirm.desc': '“{title}”仍有正在进行的工作。归档会先停止这些工作;之后可在侧栏筛选“全部对话(显示已归档)”中恢复会话,被停止的工作不会自动继续。',\n 'archive.confirm.activity': '将被停止的工作',\n 'archive.confirm.turn': '进行中的回合',\n 'archive.confirm.subagents.one': '{n} 个运行中的子智能体:{names}',\n 'archive.confirm.subagents.other': '{n} 个运行中的子智能体:{names}',\n 'archive.confirm.jobs.one': '{n} 个后台任务:{names}',\n 'archive.confirm.jobs.other': '{n} 个后台任务:{names}',\n 'archive.confirm.schedules.one': '{n} 条定时提醒:{names}',\n 'archive.confirm.schedules.other': '{n} 条定时提醒:{names}',\n 'archive.confirm.other.one': '{n} 项其他工作({kind})',\n 'archive.confirm.other.other': '{n} 项其他工作({kind})',\n 'archive.confirm.listSeparator': '、',\n 'archive.confirm.action': '停止并归档',\n 'archive.confirm.pending': '正在停止并归档…',\n 'toast.archivedUndo': '撤销',\n 'toast.archivedOr': '或',\n 'toast.archivedFilter': '筛选已归档会话',\n 'toast.pinFailed': '置顶失败,请稍后重试',\n 'toast.unpinFailed': '取消置顶失败,请稍后重试',\n 'toast.createFailed': '新建会话失败:{message}',\n 'sessions.count.one': '{n} 个会话',\n 'sessions.count.other': '{n} 个会话',\n 'actions.workspace.aria': '工作区“{name}”的操作',\n 'actions.session.aria': '会话“{name}”的操作',\n 'actions.archive': '归档会话',\n 'actions.unarchive': '取消归档',\n 'actions.pin': '置顶会话',\n 'actions.unpin': '取消置顶',\n 'actions.newSession': '新会话',\n 'actions.newSession.aria': '在“{name}”中新建会话',\n 'status.running': '进行中',\n 'status.subagentsRunning.one': '{n} 个子智能体运行中',\n 'status.subagentsRunning.other': '{n} 个子智能体运行中',\n 'status.idle': '空闲',\n 'status.waitingApproval': '等待审批',\n 'status.planReview': '计划待审',\n 'status.waitingAnswer': '等待回答',\n 'status.compact.approval': '待审批',\n 'status.compact.planReview': '计划待审',\n 'status.compact.answer': '待回答',\n 'status.waitingReview': '等待评审',\n 'status.scheduled': '定时任务',\n 'status.completed': '已完成',\n 'hover.created': '创建于 {time}',\n 'hover.copied': '已复制',\n 'date.ymd': '{y}年{m}月{d}日',\n 'time.now': '刚刚',\n 'time.minutes': '{n}分钟',\n 'time.hours': '{n}小时',\n 'time.days': '{n}天',\n 'time.months': '{n}个月',\n 'time.years': '{n}年',\n 'time.ago': '{t}前',\n 'settings.badge.section': '折叠徽标',\n 'settings.badge.showRunning': '显示「进行中」转圈',\n 'settings.badge.showRunningHint': '关闭后,进行中的会话(含子智能体)不再画转圈,也不再计入折叠徽标的数字与悬停明细。',\n 'settings.badge.showPending': '显示「待审批」黄点',\n 'settings.badge.showPendingHint': '关闭后,等待审批 / 计划评审 / 等待回答的会话不再画黄点,也不再计入折叠徽标的数字与悬停明细。',\n 'settings.badge.showCompleted': '显示「已完成」绿点',\n 'settings.badge.showCompletedHint': '关闭后,「已完成」的会话不再画绿点,也不再计入折叠徽标的数字与悬停明细。会话行自身的绿点不受影响。',\n 'settings.badge.showScheduled': '显示「定时任务」时钟',\n 'settings.badge.showScheduledHint': '关闭后,带定时提醒的会话(来自 dsh-later)不再画时钟图标,也不再计入折叠徽标的数字与悬停明细。',\n 'settings.badge.showWaitingReview': '显示「等待评审」列表笔',\n 'settings.badge.showWaitingReviewHint': '关闭后,等待代码评审的会话(来自 dsh-gitea-dispatch)不再画列表笔图标,也不再计入折叠徽标的数字与悬停明细。',\n 'settings.hover.section': '悬停明细',\n 'settings.hover.showDetails': '显示状态明细行',\n 'settings.hover.showDetailsHint': '关闭后,悬停卡只显示工作区标题、路径和创建时间——不再显示聚合状态明细行。',\n 'settings.count.section': '数字显示',\n 'settings.count.threshold': '数字显示阈值',\n 'settings.count.thresholdHint': '数量 >= 此值时才在徽标上显示数字。默认 2(即 count=1 时省略,因为状态点已表达\"有东西\")。设为 1 则始终显示。',\n 'settings.save': '保存',\n 'settings.saving': '保存中…',\n 'settings.saveFailed': '本部署没有接受这些值,已保留供你修改。',\n 'settings.readOnly': '本部署的设置为只读。',\n 'settings.unavailable': '该插件当前未加载,暂时无法配置。',\n} satisfies Record<string, string>\n\n/** The workspace namespace key union. */\nexport type WorkspaceKey = keyof typeof zh\n\n/** English dictionary, checked complete against the zh key set. */\nexport const en = {\n 'defaultWorkspace.failed': 'Unable to create default workspace. Use Choose workspace to select a folder.',\n 'group.ungrouped': 'Ungrouped',\n 'session.new': 'New Session',\n 'session.untitled': 'Untitled',\n 'shortcut.noSession': 'Select a session first',\n 'shortcut.noPicker': 'Directory picker unavailable',\n 'shortcut.directoryBusy': 'Selecting or adding a workspace',\n 'shortcut.noCompletedTurn': 'This session has no completed turn',\n 'shortcut.forkFailed': 'Could not fork the session. Try again.',\n 'section.workspaces': 'Workspaces',\n 'section.sessions': 'Sessions',\n 'viewOptions.label': 'View options',\n 'groupBy.label': 'Group by',\n 'groupBy.workspace': 'WorkSpace',\n 'groupBy.workspaceTree': 'Workspace Tree',\n 'groupBy.flat': 'In one list',\n 'orderBy.label': 'Order by',\n 'orderBy.manual': 'Manual',\n 'orderBy.updated': 'Last updated',\n 'filterBy.label': 'Filter sessions',\n 'viewOptions.hideArchived': 'Hide archived',\n 'viewOptions.showArchived': 'All conversations (show archived)',\n 'viewOptions.onlyArchived': 'Archived only',\n 'sessions.expand': 'Show {n} more sessions',\n 'sessions.collapse': 'Show less',\n 'empty.none': 'No sessions yet',\n 'empty.noneArchived': 'No archived sessions yet',\n 'empty.viewOthers': 'View other sessions',\n 'empty.noMatches': 'No matches',\n 'workspace.add': 'Add workspace',\n 'search.sessions.aria': 'Search sessions',\n 'search.placeholder': 'Search session names',\n 'search.clear': 'Clear search',\n 'search.results.aria': 'Search results',\n 'search.pending': 'Searching session history…',\n 'search.noMatches': 'No matching sessions',\n 'search.hasMore': 'Showing the first {n} results. Narrow your search.',\n 'menu.addWorkspace': 'Add workspace…',\n 'picker.loading': 'Loading workspaces…',\n 'conflict.named': 'A workspace named “{name}” already exists.',\n 'folderError.title': 'Couldn’t open folder',\n 'folderError.retry': 'Choose again',\n 'rename': 'Rename',\n 'rename.workspace.title': 'Rename workspace',\n 'rename.session.title': 'Rename session',\n 'field.workspaceName': 'Workspace name',\n 'field.sessionName': 'Session name',\n 'delete.workspace': 'Delete workspace',\n 'delete.desc': 'This removes “{name}” from the workspace list. The folder and session logs will be kept. Its sessions will appear under Ungrouped.',\n 'delete.pending': 'Deleting workspace…',\n 'menu.fork': 'Fork session',\n 'menu.archiveSession': 'Archive session',\n 'menu.unarchiveSession': 'Unarchive session',\n 'menu.pinSession': 'Pin session',\n 'menu.unpinSession': 'Unpin session',\n 'row.archived': 'Archived',\n 'row.pinned': 'Pinned',\n 'toast.archivedNotOpenable': 'Archived sessions cannot be opened. Unarchive it to view.',\n 'toast.archived': 'Session archived. You can ',\n 'toast.stoppedAndArchived': 'Session stopped and archived. You can ',\n 'archive.confirm.title': 'Stop and archive this session?',\n 'archive.confirm.desc': '“{title}” still has work in progress. Archiving stops it first; you can restore the session later from the “All conversations (show archived)” filter in the sidebar, and the stopped work will not resume on its own.',\n 'archive.confirm.activity': 'Work that will be stopped',\n 'archive.confirm.turn': 'The turn in progress',\n 'archive.confirm.subagents.one': '{n} running subagent: {names}',\n 'archive.confirm.subagents.other': '{n} running subagents: {names}',\n 'archive.confirm.jobs.one': '{n} background job: {names}',\n 'archive.confirm.jobs.other': '{n} background jobs: {names}',\n 'archive.confirm.schedules.one': '{n} scheduled reminder: {names}',\n 'archive.confirm.schedules.other': '{n} scheduled reminders: {names}',\n 'archive.confirm.other.one': '{n} other item of work ({kind})',\n 'archive.confirm.other.other': '{n} other items of work ({kind})',\n 'archive.confirm.listSeparator': ', ',\n 'archive.confirm.action': 'Stop and archive',\n 'archive.confirm.pending': 'Stopping and archiving…',\n 'toast.archivedUndo': 'undo',\n 'toast.archivedOr': ' or ',\n 'toast.archivedFilter': 'filter archived sessions',\n 'toast.pinFailed': 'Pin failed. Try again later.',\n 'toast.unpinFailed': 'Unpin failed. Try again later.',\n 'toast.createFailed': 'New session failed: {message}',\n 'sessions.count.one': '{n} session',\n 'sessions.count.other': '{n} sessions',\n 'actions.workspace.aria': 'Workspace actions for {name}',\n 'actions.session.aria': 'Session actions for {name}',\n 'actions.archive': 'Archive',\n 'actions.unarchive': 'Unarchive',\n 'actions.pin': 'Pin',\n 'actions.unpin': 'Unpin',\n 'actions.newSession': 'New session',\n 'actions.newSession.aria': 'New session in {name}',\n 'status.running': 'Running',\n 'status.subagentsRunning.one': '{n} subagent running',\n 'status.subagentsRunning.other': '{n} subagents running',\n 'status.idle': 'Idle',\n 'status.waitingApproval': 'Waiting for approval',\n 'status.planReview': 'Plan awaiting review',\n 'status.waitingAnswer': 'Waiting for answer',\n 'status.compact.approval': 'Approval',\n 'status.compact.planReview': 'Plan review',\n 'status.compact.answer': 'Answer',\n 'status.waitingReview': 'Waiting for review',\n 'status.scheduled': 'Scheduled',\n 'status.completed': 'Completed',\n 'hover.created': 'Created {time}',\n 'hover.copied': 'Copied',\n 'date.ymd': '{y}-{m}-{d}',\n 'time.now': 'now',\n 'time.minutes': '{n}min',\n 'time.hours': '{n}h',\n 'time.days': '{n}d',\n 'time.months': '{n}mo',\n 'time.years': '{n}y',\n 'time.ago': '{t} ago',\n 'settings.badge.section': 'Collapsed badge',\n 'settings.badge.showRunning': 'Show the running dot',\n 'settings.badge.showRunningHint': 'When off, running Sessions (and subagents) stop drawing the spinning dot and drop out of the collapsed badge count and its hover details.',\n 'settings.badge.showPending': 'Show the pending dot',\n 'settings.badge.showPendingHint': 'When off, Sessions waiting for approval / plan review / answer stop drawing the yellow dot and drop out of the collapsed badge count and its hover details.',\n 'settings.badge.showCompleted': 'Show the completed dot',\n 'settings.badge.showCompletedHint': 'When off, completed Sessions stop drawing the dot and drop out of the collapsed badge count and its hover details. The Session row\\'s own dot is unaffected.',\n 'settings.badge.showScheduled': 'Show the scheduled icon',\n 'settings.badge.showScheduledHint': 'When off, Sessions with scheduled reminders (from dsh-later) stop drawing the clock icon and drop out of the collapsed badge count and its hover details.',\n 'settings.badge.showWaitingReview': 'Show the waiting-for-review icon',\n 'settings.badge.showWaitingReviewHint': 'When off, Sessions waiting for code review (from dsh-gitea-dispatch) stop drawing the list-pen icon and drop out of the collapsed badge count and its hover details.',\n 'settings.hover.section': 'Hover details',\n 'settings.hover.showDetails': 'Show status detail lines',\n 'settings.hover.showDetailsHint': 'When off, the hover card shows only the workspace title, path, and creation time — no aggregated status lines.',\n 'settings.count.section': 'Count display',\n 'settings.count.threshold': 'Count display threshold',\n 'settings.count.thresholdHint': 'The count is shown on the badge only when the total is >= this value. Default 2 (omits the count when it equals 1 — the dots already convey \"something is happening\"). Set to 1 to always show.',\n 'settings.save': 'Save',\n 'settings.saving': 'Saving…',\n 'settings.saveFailed': 'The deployment did not accept these values; they were left for you to correct.',\n 'settings.readOnly': 'This deployment stores settings read-only.',\n 'settings.unavailable': 'This plugin is not loaded, so it cannot be configured right now.',\n} satisfies Record<WorkspaceKey, string>\n","/**\n * Workspace plugin, browser half. Two registrations: WorkspaceBrowser fills\n * the sidebar shell's `sidebar.workspaces` hole (the whole browsing region),\n * and WorkspacePicker fills the conversation hero's picker hole\n * (`conversation.hero.workspace` — both hero forms). Both read real Host\n * Workspaces through the global useWorkspaces hook, and each declares its\n * own `single` directory-flow child hole for the composed picker package's\n * client half. WorkspaceBrowser additionally declares the two Session row\n * action lists, and this apply registers the shipped actions — pin, rename,\n * fork, archive — into them the way any client plugin would, each with its\n * own behavior, plus the rename dialog and the row-action notice into\n * `shell.overlay` (see the contract module doc). It also declares two\n * Session-row seats: the leading decoration a row renders only while its own\n * primary state is idle, and the section the row's hover card renders between\n * its relative time and its trailing status line. Export discipline:\n * packages/client/AGENTS.md.\n */\nimport type {} from '@deepseek-ai/dsh-client-product-analytics/client'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client'\nimport type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {\n IWorkspaces, SessionActivity, WorkspaceArchiveError, WorkspaceSnapshot,\n} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { HostObservable, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\n// Type-only: pulls the Controller service merges.\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-api-workspace-controller/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the SlotRegistry service merge (ctx.slots).\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\n// Type-only: pulls the Session root standard-hook merge.\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\n// Type-only:插件页卡片的官方设置表单契约(运行时由 `configForms` 服务提供)。\nimport type { SettingsFormScope } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n type ArchiveSessionInjected, type ForkSessionInjected, menuOpenStateFactory, type PinSessionInjected,\n type SessionArchiveConfirmInjected, type SessionArchiveConfirmRequest,\n type RenameSessionInjected, type RowToast, type RowToastInjected, type RowToastState, type SessionRenameDialogInjected,\n type WorkspaceBrowserInjected, type WorkspacePickerInjected,\n} from './contract/slots.ts'\nimport { createWorkspaceShortcutControls, installWorkspaceShortcuts } from './shortcuts.ts'\nimport { createBadgeSettingsSource, ENTRY_ID, type ResolvedBadgeSettings } from './badge-settings.ts'\nimport { BadgeSettingsCard } from './BadgeSettingsCard.tsx'\nimport { UiWorkspaceService } from './navigation.ts'\nimport { createWorkspaceViewStore } from './stores.ts'\nimport { WorkspaceBrowser } from './rows/WorkspaceBrowser.tsx'\nimport { ArchiveSessionMenuItem, ArchiveSessionRowButton, SessionArchiveConfirmDialog } from './session-actions/ArchiveSession.tsx'\nimport { derive } from './session-actions/derived.ts'\nimport { ForkSessionMenuItem } from './session-actions/ForkSession.tsx'\nimport { PinSessionMenuItem, PinSessionRowButton } from './session-actions/PinSession.tsx'\nimport { RenameSessionMenuItem, SessionRenameDialog } from './session-actions/RenameSession.tsx'\nimport { RowActionToast } from './session-actions/RowActionToast.tsx'\nimport { WorkspacePicker } from './WorkspacePicker.tsx'\nimport { en, zh, type WorkspaceKey } from './locales.ts'\n\nexport type { UiWorkspace } from './navigation.ts'\nexport type {\n DirectoryFlowOwnerProps, DirectoryFlowSlotName, DirectoryPickingHooks, DirectoryPickingInjected,\n MenuOpenState, RowToast, SessionRenameTarget, SessionRowOwnerProps, UseMenuOpenState, WorkspaceBrowserInjected,\n SessionRowScheduleOwnerProps,\n WorkspaceBrowserProps,\n WorkspacePickerInjected, WorkspacePickerProps,\n} from './contract/slots.ts'\nexport type { WorkspaceKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface GlobalStandardProps {\n /** Selector hook over the pure Workspace Controller snapshot. */\n useWorkspaces: SnapshotSelectorHook<WorkspaceSnapshot>\n /** Selector hook over this plugin's own settings face (badge preferences). */\n useBadgeSettings: SnapshotSelectorHook<ResolvedBadgeSettings>\n }\n\n interface LocaleNamespaceMap {\n /** The workspace browsing region and pick/create flow copy. */\n workspace: WorkspaceKey\n }\n}\n\ndeclare module '@deepseek-ai/dsh-api-session-controller/client' {\n interface SessionReferenceSourceMap {\n workspaceOperation: unknown\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nconst NS = 'workspace'\n\n/**\n * `configForms` 服务的最小结构面(宿主 `@deepseek-ai/dsh-client-ui-settings` 的\n * 一部分)。此处按结构声明而非导入该包:本插件不需要设置页的其余能力,窄化的\n * 形状让服务缺席时降级为一个 `undefined` 检查而非编译期依赖。\n *\n * `get` 的返回类型直接用官方 `SettingsFormScope`:那就是 `configForms.get(条目 id)`\n * 的运行时形状(`getSnapshot` / `subscribe` / `mutate`),设置卡片(官方\n * `SettingsFormModel`)要的也正是它,因此不需要本地复刻一份契约。\n *\n * `whileServed` 可选:它在 0.1.7 settings rewrite 一代才有,用于「宿主仍在服务该\n * 条目命名空间时」维持一段注册。缺席时只跳过插件页卡片,折叠徽标的读通道照常。\n */\ninterface ConfigFormsLike {\n get(entryId: string): SettingsFormScope<Record<string, unknown>>\n whileServed?(\n entryIds: readonly string[],\n register: (served: ReadonlySet<string>) => () => void,\n ): () => void\n}\n\n/** 插件详情页配置表单的槽位名(按包名寻址;契约见 `plugin-manager-slot.d.ts`)。 */\nconst CONFIG_CARD_SLOT = 'plugins.bundle.config'\n\n/**\n * 插件管理器分发 `plugins.bundle.config` 用的键 = **包名**(不是条目 id)。\n * 本包的补丁把行 id 也写成同名,但两者是不同概念,别改成 ENTRY_ID 的引用。\n */\nconst CONFIG_CARD_KEY = 'dsh-group-status'\n\n/**\n * Required services (cordis fiber inject). The target slots are declared by\n * the ui-sidebar / ui-conversation applies, whose activation order relative\n * to this one is NOT constrained: dsh.client.inject edges are informational\n * (loading/prefetch metadata, never apply sequencing) and neither owner\n * provides a waitable service. apply therefore depends on each slot\n * declaration through `slots.inject()` instead of assuming order.\n */\nexport const inject = [\n 'slots', 'sessions', 'workspaces', 'locale', 'remote', 'remote.directoryPicker', 'layout', 'shortcuts',\n]\n\n/**\n * Register the browser and picker once their slot declarations are on the\n * ledger. Inject factories return plain callbacks; data reads use the\n * framework's global hooks.\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n const sessions = ctx.get('sessions') as ISessions\n const workspaces = ctx.get('workspaces') as IWorkspaces\n // One viewing-store instance, created here as ui-layout does for its layout\n // store: the browser declares the handle, and the UiWorkspace service writes\n // view order through the same instance the renderer hands the browser.\n const viewHandle = createWorkspaceViewStore()\n const viewInstance = viewHandle.create()\n const viewStore: typeof viewHandle = { ...viewHandle, create: () => viewInstance }\n const rowToast = createSnapshotStore<RowToastState | null>(null)\n let toastSeq = 0\n const notify = (toast: RowToast): void => { rowToast.set({ ...toast, seq: ++toastSeq }) }\n const uiWorkspace = new UiWorkspaceService(\n ctx, ctx.remote.directoryPicker, workspaces, sessions, viewInstance.actions, notify,\n )\n ctx.slots.provideRoot({ hooks: { workspaces: workspaces.list } })\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-workspace: dictionaries')\n const shortcutControls = createWorkspaceShortcutControls()\n\n // 折叠徽标的显示偏好(`showCompletedInBadge`)。\n //\n // 源先挂上(**恒在**,值先是默认):标准 props 的 hook 调用顺序必须稳定,晚挂或\n // 摘掉 `useBadgeSettings` 都会改变顺序而崩渲染。设置面随后经 `ctx.inject` 接入,\n // 只改源的值,不改源的存亡。\n const badgeSettings = createBadgeSettingsSource()\n ctx.slots.provideRoot({ hooks: { badgeSettings } })\n\n // 等宿主设置服务就绪——**非阻塞**:`ctx.inject` 是嵌套插件,服务永不到达也只是设置\n // 读不到(回落默认),本插件其余功能不受影响。这里不直接用 `ctx.get` 读:服务可能在\n // 本插件之后才注册,那时读到的 undefined 会永久生效(设置被静默忽略直到刷新)。\n //\n // 寻址键是**条目 id**(`cordis.patch.yml` 的 `id: dsh-group-status`),不是 settings\n // namespace——宿主 `describe()` 的 `ns` 即条目 id。\n ctx.inject(['configForms'], (configCtx) => {\n const forms = configCtx.get('configForms') as ConfigFormsLike | undefined\n if (forms === undefined || typeof forms.get !== 'function') return\n // 同一份官方设置表单既喂折叠徽标(只读快照),也喂插件页卡片(读写)。\n const scope = forms.get(ENTRY_ID)\n if (scope === undefined) return\n badgeSettings.publish(scope.getSnapshot())\n configCtx.effect(\n () => scope.subscribe(() => { badgeSettings.publish(scope.getSnapshot()) }),\n 'dsh-group-status: badge settings',\n )\n\n // 插件详情页(插件 → dsh-group-status)的配置表单。宿主把 `Config` 投影成\n // 上面这份表单,但页面要插件自己注册卡片才画得出来——没有这段,设置项在\n // GUI 里不存在(README 的「设置项」一节描述的就是这张卡片)。\n //\n // 键取**包名**(插件管理器按包名分发该槽位),寻址的表单仍是上面同一份 scope,\n // 于是卡片与折叠徽标永远读同一个值。\n //\n // `whileServed` 盯住条目命名空间:宿主不再服务该条目时连卡片一起注销,避免\n // 留下一张点开即空的表单。`bind` 是必需的:它是类原型方法,内部读写\n // `this.mirror`,取下来裸调用会丢接收者。\n const whileServed = forms.whileServed?.bind(forms)\n if (whileServed === undefined) return\n configCtx.effect(\n () => whileServed([ENTRY_ID], () => ctx.slots.inject(CONFIG_CARD_SLOT, () =>\n ctx.slots.register(\n {\n name: CONFIG_CARD_SLOT,\n key: CONFIG_CARD_KEY,\n locale: NS,\n inject: () => ({ scope }),\n },\n BadgeSettingsCard,\n ))),\n 'dsh-group-status: plugins-page card',\n )\n })\n\n const searchSessions: WorkspaceBrowserInjected['searchSessions'] = async (query, signal) => {\n const result = await sessions.search(query, signal)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n }\n\n // Stable per-surface occupancy sources (the renderer's hook cache keys by\n // source identity): true while the surface's directory-flow hole is filled.\n const flowSource = (hole: 'sidebar.workspaces.directoryFlow' | 'conversation.hero.workspace.directoryFlow'): HostObservable<boolean> => ({\n getSnapshot: () => ctx.slots.entries(hole).length > 0,\n subscribe: listener => ctx.slots.subscribe(hole, listener),\n })\n const browserFlowSource = flowSource('sidebar.workspaces.directoryFlow')\n const hostInfo: HostObservable<RemoteHostFacts> = {\n getSnapshot: () => ctx.remote.$host,\n subscribe: listener => ctx.on('connection/reset', listener),\n }\n const pickerFlowSource = flowSource('conversation.hero.workspace.directoryFlow')\n const openSession: WorkspaceBrowserInjected['open'] = (sessionId) => {\n uiWorkspace.openSession(sessionId)\n }\n // Registry-global sets as Sets, rebuilt only when the Workspace snapshot changes.\n const pinnedSet = derive(workspaces.list, snapshot => new Set<SessionId>(snapshot.pinnedSessionIds))\n const archivedSet = derive(workspaces.list, snapshot => new Set<SessionId>(snapshot.archivedSessionIds))\n // Plugin-private facts the row actions and their overlay surfaces share:\n // the pending rename request and the notice on display. Each business\n // writes through its own injected callback and the surface reads through\n // its bound hook.\n const renameRequest = derive(shortcutControls.state, state => state.renameTarget)\n const archiveRequest = createSnapshotStore<SessionArchiveConfirmRequest | null>(null)\n const requestSessionRename = shortcutControls.rename\n const unarchiveSession = (sessionId: SessionId): void => {\n uiWorkspace.unarchiveSession(sessionId).catch((reason: unknown) => {\n console.warn('session unarchive rejected:', reason)\n })\n }\n const renameSession: SessionRenameDialogInjected['renameSession'] = async (sessionId, title) => {\n const result = await sessions.using(\n sessionId,\n { source: 'workspaceOperation' },\n reference => reference.binding.session.rename(title),\n )\n if (!result.ok) throw new Error(result.error.message)\n }\n const pinInjected = (): PinSessionInjected => ({\n hooks: { pinned: pinnedSet, archived: archivedSet },\n // Pin failures surface as a notice: nothing else on the surface moves, so\n // a silent failure would read as a dead action.\n pinSession: (sessionId) => {\n uiWorkspace.pinSession(sessionId).catch(() => { notify({ kind: 'pinFailed' }) })\n },\n unpinSession: (sessionId) => {\n uiWorkspace.unpinSession(sessionId).catch(() => { notify({ kind: 'unpinFailed' }) })\n },\n })\n const archiveInjected = (): ArchiveSessionInjected => ({\n hooks: { archived: archivedSet },\n // Archive preserves the log and the account position, so a quiet Session\n // needs no confirmation; the notice offers undo and the archived filter.\n // The Host's refusal for running work is the one case that asks first:\n // the confirmation names that work and offers to stop it.\n archiveSession: (sessionId) => {\n uiWorkspace.archiveSession(sessionId).then(() => {\n notify({ kind: 'archived', sessionId })\n }).catch((reason: unknown) => {\n const activity = activeSessionRefusal(reason)\n if (activity === undefined) {\n console.warn('session archive rejected:', reason)\n return\n }\n const displayTitle = sessions.list.getSnapshot().byId[sessionId]?.displayTitle ?? sessionId\n archiveRequest.set({ sessionId, displayTitle, activity })\n })\n },\n unarchiveSession,\n })\n installWorkspaceShortcuts(ctx, uiWorkspace, shortcutControls, archiveInjected().archiveSession)\n const archiveConfirmInjected = (): SessionArchiveConfirmInjected => ({\n hooks: { archiveRequest },\n settleSessionArchive: () => { archiveRequest.set(null) },\n stopAndArchiveSession: async (sessionId) => {\n await uiWorkspace.archiveSession(sessionId, { stopActivity: true })\n notify({ kind: 'stoppedAndArchived', sessionId })\n },\n })\n const forkInjected = (): ForkSessionInjected => ({\n forkSession: (sessionId) => {\n uiWorkspace.forkSession(sessionId, (childId) => {\n ctx.get('productAnalytics')?.track('branch_session_click', { session_id: childId, parent_session_id: sessionId, click_position: 'sidebar' })\n }).catch(() => {\n // Fork or child-title failure leaves the list as it was.\n })\n },\n })\n const renameInjected = (): RenameSessionInjected => ({ requestSessionRename })\n const renameDialogInjected = (): SessionRenameDialogInjected => ({\n hooks: { renameRequest },\n settleSessionRename: shortcutControls.closeRename,\n renameSession,\n })\n const rowToastInjected = (): RowToastInjected => ({\n hooks: { toast: rowToast },\n dismissToast: () => { rowToast.set(null) },\n undoArchive: unarchiveSession,\n showArchived: () => { viewInstance.actions.setArchivedFilter('show') },\n })\n const browserInjected = (): WorkspaceBrowserInjected => ({\n // Explicit group actions keep their target; unscoped New Session inherits\n // the current Session Workspace before the recent-Workspace fallback.\n startSession: (workspaceId) => { uiWorkspace.startSession(workspaceId) },\n open: openSession,\n searchSessions,\n searchResultLimit: sessions.searchResultLimit,\n requestSessionRename,\n notifyArchivedNotOpenable: () => { notify({ kind: 'archivedNotOpenable' }) },\n renameWorkspace: async (workspaceId, title) => { await workspaces.rename(workspaceId, title) },\n deleteWorkspace: async (workspaceId) => { await workspaces.delete(workspaceId) },\n insertWorkspaceBefore: async (workspaceId, beforeWorkspaceId) => {\n await workspaces.insertBefore(workspaceId, beforeWorkspaceId)\n },\n unarchiveSession: async (sessionId) => { await uiWorkspace.unarchiveSession(sessionId) },\n createWorkspace: input => workspaces.create(input),\n requestSearch: shortcutControls.search,\n requestAddWorkspace: shortcutControls.add,\n closeAddWorkspace: shortcutControls.closeAdd,\n setDirectoryBusy: shortcutControls.directoryBusy,\n dismissForkError: shortcutControls.dismissForkError,\n hooks: { directoryFlow: browserFlowSource, hostInfo, workspaceShortcuts: shortcutControls.state, shortcuts: ctx.shortcuts.catalog },\n })\n const pickerInjected = (): WorkspacePickerInjected => ({\n createWorkspace: input => workspaces.create(input),\n hooks: { directoryFlow: pickerFlowSource },\n })\n // Each registration declares its owned children in the same call; slot\n // injection follows both the owner and declaration HMR lifetimes.\n ctx.slots.inject('sidebar.workspaces', () => ctx.slots.register(\n {\n name: 'sidebar.workspaces',\n children: {\n 'sidebar.workspaces.directoryFlow': { kind: 'single', scope: 'root' },\n // Every row entry reads the menu's open state through a hook bound\n // from the row's render occurrence (the owner passes the state pair\n // as hookContext).\n 'sidebar.workspaces.session.menu.item': {\n kind: 'list', scope: 'root', inject: { hooks: { menuOpenState: menuOpenStateFactory, shortcuts: ctx.shortcuts.catalog } },\n },\n 'sidebar.workspaces.session.row.action': { kind: 'list', scope: 'root' },\n 'sidebar.session.row.leading': { kind: 'list', scope: 'root' },\n 'sidebar.session.row.hover': { kind: 'list', scope: 'root' },\n },\n store: viewStore,\n inject: browserInjected,\n locale: NS,\n },\n WorkspaceBrowser,\n ))\n // The shipped row actions take the same route as a plugin's: `slots.inject`\n // waits for the browser registration above to declare each list, and the\n // entries leave with it. Orders step by 100 so a plugin entry can land\n // between them.\n ctx.slots.inject('sidebar.workspaces.session.menu.item', function* () {\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'pin', order: 100, locale: NS, inject: pinInjected }, PinSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'rename', order: 200, locale: NS, inject: renameInjected }, RenameSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'fork', order: 300, locale: NS, inject: forkInjected }, ForkSessionMenuItem)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.menu.item', id: 'archive', order: 400, locale: NS, inject: archiveInjected }, ArchiveSessionMenuItem)\n })\n ctx.slots.inject('sidebar.workspaces.session.row.action', function* () {\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.row.action', id: 'archive', order: 100, locale: NS, inject: archiveInjected }, ArchiveSessionRowButton)\n yield ctx.slots.register({ name: 'sidebar.workspaces.session.row.action', id: 'pin', order: 200, locale: NS, inject: pinInjected }, PinSessionRowButton)\n })\n // The surfaces the actions raise live in the frame-wide layer: they must\n // outlive the row menu the action sat in.\n ctx.slots.inject('shell.overlay', function* () {\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.session-rename', locale: NS, inject: renameDialogInjected,\n }, SessionRenameDialog)\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.session-archive', locale: NS, inject: archiveConfirmInjected,\n }, SessionArchiveConfirmDialog)\n // The toast shares the browser's viewing store: it reads the archived\n // filter to drop the archived notice's filter action once rows are visible.\n yield ctx.slots.register({\n name: 'shell.overlay', id: 'workspace.row-toast', locale: NS, store: viewStore, inject: rowToastInjected,\n }, RowActionToast)\n })\n ctx.slots.inject('conversation.hero.workspace', () => ctx.slots.register(\n {\n name: 'conversation.hero.workspace',\n children: { 'conversation.hero.workspace.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: pickerInjected,\n locale: NS,\n },\n WorkspacePicker,\n ))\n}\n\n/**\n * The activity a Host `workspace/session-active` refusal reported, or nothing\n * for any other failure. The class identity check goes by name: client plugin\n * bundles do not share error-class identity.\n */\nfunction activeSessionRefusal(reason: unknown): readonly SessionActivity[] | undefined {\n if (!(reason instanceof Error) || reason.name !== 'WorkspaceArchiveError') return undefined\n const { rpcError } = reason as WorkspaceArchiveError\n return rpcError.code === 'workspace/session-active' ? rpcError.details.activity : undefined\n}\n"],"ignoreList":[5,6,11,12],"mappings":"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"}