@huanlin/dsh-plugin-ya-workspace-sidebar 0.3.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ /** Fixed-stride virtual scroller for the global recent-sessions block. */
2
+ import { type ReactNode } from 'react';
3
+ import { type SessionRow } from './model.ts';
4
+ interface VirtualRecentListProps {
5
+ rows: readonly SessionRow[];
6
+ renderItem: (row: SessionRow) => ReactNode;
7
+ ariaLabel: string;
8
+ /** Receives the viewport element for external geometry (the drag resizer). */
9
+ viewportRef?: (node: HTMLDivElement | null) => void;
10
+ /** Overrides the stylesheet's default viewport cap, in px. */
11
+ maxHeight?: number;
12
+ }
13
+ /**
14
+ * Renders `rows` inside a bounded, scrollable viewport while mounting only
15
+ * the visible slice (plus overscan). The row stride is fixed
16
+ * ({@link RECENT_ROW_STRIDE}), so windowing is pure arithmetic — no per-row
17
+ * measurement — and the scroll position survives session-list updates.
18
+ */
19
+ export declare function VirtualRecentList({ rows, renderItem, ariaLabel, viewportRef, maxHeight }: VirtualRecentListProps): import("react").JSX.Element;
20
+ export {};
@@ -1,26 +1,26 @@
1
- /** Existing-workspace menu plus composed directory-adoption flow. */
2
- import type { ReactNode, RefObject } from 'react';
3
- import type { WorkspaceId, WorkspaceListState, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
4
- import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
5
- import type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts';
6
- interface FlowProps {
7
- t: PickerProps['t'];
8
- open: boolean;
9
- anchorRef?: RefObject<HTMLElement | null>;
10
- useWorkspaces: <S>(selector: (state: WorkspaceListState) => S) => S;
11
- createWorkspace: (input: {
12
- path: string;
13
- }) => Promise<WorkspaceView>;
14
- useDirectoryFlow: SnapshotSelectorHook<boolean>;
15
- renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode;
16
- onPick: (workspaceId: WorkspaceId) => void;
17
- onClose: () => void;
18
- addOnly?: boolean;
19
- side?: 'bottom' | 'top' | 'right';
20
- selectedId?: WorkspaceId;
21
- }
22
- /** Render the workspace target menu and directory picking conversation. */
23
- export declare function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly, side, selectedId, }: FlowProps): import("react").JSX.Element;
24
- /** Fill the conversation hero's workspace picker seat. */
25
- export declare function WorkspacePicker({ open, anchorRef, useWorkspaces, selectedId, onPick, onClose, createWorkspace, useDirectoryFlow, renderSlot, t, }: PickerProps): import("react").JSX.Element;
26
- export {};
1
+ /** Existing-workspace menu plus composed directory-adoption flow. */
2
+ import type { ReactNode, RefObject } from 'react';
3
+ import type { WorkspaceId, WorkspaceSnapshot, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
4
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
5
+ import type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts';
6
+ interface FlowProps {
7
+ t: PickerProps['t'];
8
+ open: boolean;
9
+ anchorRef?: RefObject<HTMLElement | null>;
10
+ useWorkspaces: SnapshotSelectorHook<WorkspaceSnapshot>;
11
+ createWorkspace: (input: {
12
+ path: string;
13
+ }) => Promise<WorkspaceView>;
14
+ useDirectoryFlow: SnapshotSelectorHook<boolean>;
15
+ renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode;
16
+ onPick: (workspaceId: WorkspaceId) => void;
17
+ onClose: () => void;
18
+ addOnly?: boolean;
19
+ side?: 'bottom' | 'top' | 'right';
20
+ selectedId?: WorkspaceId;
21
+ }
22
+ /** Render the workspace target menu and directory picking conversation. */
23
+ export declare function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly, side, selectedId, }: FlowProps): import("react").JSX.Element;
24
+ /** Fill the conversation hero's workspace picker seat. */
25
+ export declare function WorkspacePicker({ open, anchorRef, useWorkspaces, selectedId, onPick, onClose, createWorkspace, useDirectoryFlow, renderSlot, t, }: PickerProps): import("react").JSX.Element;
26
+ export {};
@@ -1,68 +1,76 @@
1
- /** Slot contracts and injected Host actions for ya-workspace-sidebar. */
2
- import type { HostObservable, PropsLocale, PropsRenderSlots, PropsRuntime, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
3
- import type { SessionId, SessionSearchResultItem, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
4
- import type { YaWorkspaceKey } from './locales.ts';
5
- /** Directory-picker conversation owned by each trigger surface. */
6
- export interface DirectoryFlowOwnerProps {
7
- open: boolean;
8
- busy: boolean;
9
- onPicked: (path: string) => void;
10
- onCancel: () => void;
11
- onError: (message: string) => void;
12
- }
13
- declare module '@deepseek-ai/dsh-client-ui-slots' {
14
- interface SlotMap {
15
- 'sidebar.workspaces.directoryFlow': {
16
- kind: 'single';
17
- scope: 'root';
18
- owner: DirectoryFlowOwnerProps;
19
- };
20
- 'conversation.hero.workspace.directoryFlow': {
21
- kind: 'single';
22
- scope: 'root';
23
- owner: DirectoryFlowOwnerProps;
24
- };
25
- }
26
- interface LocaleNamespaceMap {
27
- 'ya-workspace-sidebar': YaWorkspaceKey;
28
- }
29
- }
30
- /** Shared directory-flow occupancy source. */
31
- export interface DirectoryInjected {
32
- hooks: {
33
- directoryFlow: HostObservable<boolean>;
34
- };
35
- }
36
- /** Browser-private Host operations. */
37
- export type SidebarInjected = DirectoryInjected & {
38
- startSession: (workspaceId?: WorkspaceId) => void;
39
- open: (sessionId: SessionId) => void;
40
- searchSessions: (query: string, signal: AbortSignal) => Promise<{
41
- items: readonly SessionSearchResultItem[];
42
- hasMore: boolean;
43
- }>;
44
- searchResultLimit: number;
45
- renameSession: (sessionId: SessionId, title: string) => Promise<void>;
46
- forkSession: (sessionId: SessionId) => void;
47
- renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>;
48
- deleteWorkspace: (workspaceId: WorkspaceId) => Promise<void>;
49
- archiveSession: (sessionId: SessionId) => Promise<void>;
50
- insertSessionBefore: (workspaceId: WorkspaceId, sessionId: SessionId, beforeSessionId?: SessionId) => Promise<void>;
51
- createWorkspace: (input: {
52
- path: string;
53
- }) => Promise<WorkspaceView>;
54
- };
55
- /** Full sidebar component props. */
56
- export type SidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsRenderSlots<'sidebar.workspaces.directoryFlow'> & Omit<SidebarInjected, 'hooks'> & {
57
- useDirectoryFlow: SnapshotSelectorHook<boolean>;
58
- } & PropsLocale<'ya-workspace-sidebar'>;
59
- /** Conversation hero picker operations. */
60
- export type PickerInjected = DirectoryInjected & {
61
- createWorkspace: (input: {
62
- path: string;
63
- }) => Promise<WorkspaceView>;
64
- };
65
- /** Full conversation hero picker props. */
66
- export type PickerProps = PropsRuntime<'conversation.hero.workspace'> & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'> & Omit<PickerInjected, 'hooks'> & {
67
- useDirectoryFlow: SnapshotSelectorHook<boolean>;
68
- } & PropsLocale<'ya-workspace-sidebar'>;
1
+ /** Slot contracts and injected Host actions for ya-workspace-sidebar. */
2
+ import type { HostObservable, PropsLocale, PropsRenderSlots, PropsRuntime, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
3
+ import type { SessionSearchResultItem } from '@deepseek-ai/dsh-api-session-controller/client';
4
+ import type { WorkspaceId, WorkspaceSnapshot, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
5
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
6
+ import type { YaWorkspaceKey } from './locales.ts';
7
+ /** Directory-picker conversation owned by each trigger surface. */
8
+ export interface DirectoryFlowOwnerProps {
9
+ open: boolean;
10
+ busy: boolean;
11
+ onPicked: (path: string) => void;
12
+ onCancel: () => void;
13
+ onError: (message: string) => void;
14
+ }
15
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
16
+ /** The official ui-workspace provider is disabled by this bundle's patch,
17
+ * so this plugin owns the global workspaces selector hook (bound from the
18
+ * Workspace Controller snapshot this apply installs via slots.provideRoot). */
19
+ interface GlobalStandardProps {
20
+ useWorkspaces: SnapshotSelectorHook<WorkspaceSnapshot>;
21
+ }
22
+ interface SlotMap {
23
+ 'sidebar.workspaces.directoryFlow': {
24
+ kind: 'single';
25
+ scope: 'root';
26
+ owner: DirectoryFlowOwnerProps;
27
+ };
28
+ 'conversation.hero.workspace.directoryFlow': {
29
+ kind: 'single';
30
+ scope: 'root';
31
+ owner: DirectoryFlowOwnerProps;
32
+ };
33
+ }
34
+ interface LocaleNamespaceMap {
35
+ 'ya-workspace-sidebar': YaWorkspaceKey;
36
+ }
37
+ }
38
+ /** Shared directory-flow occupancy source. */
39
+ export interface DirectoryInjected {
40
+ hooks: {
41
+ directoryFlow: HostObservable<boolean>;
42
+ };
43
+ }
44
+ /** Browser-private Host operations. */
45
+ export type SidebarInjected = DirectoryInjected & {
46
+ startSession: (workspaceId?: WorkspaceId) => void;
47
+ open: (sessionId: SessionId) => void;
48
+ searchSessions: (query: string, signal: AbortSignal) => Promise<{
49
+ items: readonly SessionSearchResultItem[];
50
+ hasMore: boolean;
51
+ }>;
52
+ searchResultLimit: number;
53
+ renameSession: (sessionId: SessionId, title: string) => Promise<void>;
54
+ forkSession: (sessionId: SessionId) => void;
55
+ renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>;
56
+ deleteWorkspace: (workspaceId: WorkspaceId) => Promise<void>;
57
+ archiveSession: (sessionId: SessionId) => Promise<void>;
58
+ insertSessionBefore: (workspaceId: WorkspaceId, sessionId: SessionId, beforeSessionId?: SessionId) => Promise<void>;
59
+ createWorkspace: (input: {
60
+ path: string;
61
+ }) => Promise<WorkspaceView>;
62
+ };
63
+ /** Full sidebar component props. */
64
+ export type SidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsRenderSlots<'sidebar.workspaces.directoryFlow'> & Omit<SidebarInjected, 'hooks'> & {
65
+ useDirectoryFlow: SnapshotSelectorHook<boolean>;
66
+ } & PropsLocale<'ya-workspace-sidebar'>;
67
+ /** Conversation hero picker operations. */
68
+ export type PickerInjected = DirectoryInjected & {
69
+ createWorkspace: (input: {
70
+ path: string;
71
+ }) => Promise<WorkspaceView>;
72
+ };
73
+ /** Full conversation hero picker props. */
74
+ export type PickerProps = PropsRuntime<'conversation.hero.workspace'> & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'> & Omit<PickerInjected, 'hooks'> & {
75
+ useDirectoryFlow: SnapshotSelectorHook<boolean>;
76
+ } & PropsLocale<'ya-workspace-sidebar'>;
@@ -1,5 +1,9 @@
1
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
2
- /** Services required by both replacement client entries. */
3
- export declare const inject: string[];
4
- /** Register the sidebar browser and conversation hero picker. */
5
- export declare function apply(ctx: ClientContext): void;
1
+ /** Client assembly for the replacement workspace sidebar and hero picker. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /**
4
+ * Services required by the replacement client entries. `remote` and
5
+ * `remote.directoryPicker` feed the uiWorkspace stand-in's directory picking.
6
+ */
7
+ export declare const inject: string[];
8
+ /** Register the sidebar browser and conversation hero picker. */
9
+ export declare function apply(ctx: Context): void;
@@ -1,111 +1,113 @@
1
- /** Product copy for the replacement workspace browser. */
2
- export declare const zh: {
3
- workspaces: string;
4
- sessions: string;
5
- recent: string;
6
- ungrouped: string;
7
- newSession: string;
8
- addWorkspace: string;
9
- addWorkspaceMenu: string;
10
- search: string;
11
- searchPlaceholder: string;
12
- clearSearch: string;
13
- searching: string;
14
- searchUnavailable: string;
15
- noMatches: string;
16
- noSessions: string;
17
- noWorkspaces: string;
18
- loading: string;
19
- rename: string;
20
- renameWorkspace: string;
21
- renameSession: string;
22
- deleteWorkspace: string;
23
- deleteDescription: string;
24
- fork: string;
25
- archive: string;
26
- archiveMode: string;
27
- deleteMode: string;
28
- deleteSession: string;
29
- deleteSessionTitle: string;
30
- deleteSessionConfirm: string;
31
- toggleActionMode: string;
32
- actionModeLabel: string;
33
- cancel: string;
34
- confirm: string;
35
- retry: string;
36
- folderError: string;
37
- workspaceName: string;
38
- sessionName: string;
39
- count: string;
40
- now: string;
41
- minutes: string;
42
- hours: string;
43
- days: string;
44
- months: string;
45
- years: string;
46
- running: string;
47
- waiting: string;
48
- completed: string;
49
- collapse: string;
50
- expand: string;
51
- today: string;
52
- yesterday: string;
53
- date: string;
54
- dateYear: string;
55
- };
56
- export type YaWorkspaceKey = keyof typeof zh;
57
- export declare const en: {
58
- workspaces: string;
59
- sessions: string;
60
- recent: string;
61
- ungrouped: string;
62
- newSession: string;
63
- addWorkspace: string;
64
- addWorkspaceMenu: string;
65
- search: string;
66
- searchPlaceholder: string;
67
- clearSearch: string;
68
- searching: string;
69
- searchUnavailable: string;
70
- noMatches: string;
71
- noSessions: string;
72
- noWorkspaces: string;
73
- loading: string;
74
- rename: string;
75
- renameWorkspace: string;
76
- renameSession: string;
77
- deleteWorkspace: string;
78
- deleteDescription: string;
79
- fork: string;
80
- archive: string;
81
- archiveMode: string;
82
- deleteMode: string;
83
- deleteSession: string;
84
- deleteSessionTitle: string;
85
- deleteSessionConfirm: string;
86
- toggleActionMode: string;
87
- actionModeLabel: string;
88
- cancel: string;
89
- confirm: string;
90
- retry: string;
91
- folderError: string;
92
- workspaceName: string;
93
- sessionName: string;
94
- count: string;
95
- now: string;
96
- minutes: string;
97
- hours: string;
98
- days: string;
99
- months: string;
100
- years: string;
101
- running: string;
102
- waiting: string;
103
- completed: string;
104
- collapse: string;
105
- expand: string;
106
- today: string;
107
- yesterday: string;
108
- date: string;
109
- dateYear: string;
110
- };
111
- export declare const NS = "ya-workspace-sidebar";
1
+ /** Product copy for the replacement workspace browser. */
2
+ export declare const zh: {
3
+ workspaces: string;
4
+ sessions: string;
5
+ recent: string;
6
+ ungrouped: string;
7
+ newSession: string;
8
+ addWorkspace: string;
9
+ addWorkspaceMenu: string;
10
+ search: string;
11
+ searchPlaceholder: string;
12
+ clearSearch: string;
13
+ searching: string;
14
+ searchUnavailable: string;
15
+ noMatches: string;
16
+ noSessions: string;
17
+ noWorkspaces: string;
18
+ loading: string;
19
+ rename: string;
20
+ renameWorkspace: string;
21
+ renameSession: string;
22
+ deleteWorkspace: string;
23
+ deleteDescription: string;
24
+ fork: string;
25
+ archive: string;
26
+ archiveMode: string;
27
+ deleteMode: string;
28
+ deleteSession: string;
29
+ deleteSessionTitle: string;
30
+ deleteSessionConfirm: string;
31
+ toggleActionMode: string;
32
+ actionModeLabel: string;
33
+ cancel: string;
34
+ confirm: string;
35
+ retry: string;
36
+ folderError: string;
37
+ workspaceName: string;
38
+ sessionName: string;
39
+ count: string;
40
+ now: string;
41
+ minutes: string;
42
+ hours: string;
43
+ days: string;
44
+ months: string;
45
+ years: string;
46
+ running: string;
47
+ waiting: string;
48
+ completed: string;
49
+ collapse: string;
50
+ expand: string;
51
+ resizeRecent: string;
52
+ today: string;
53
+ yesterday: string;
54
+ date: string;
55
+ dateYear: string;
56
+ };
57
+ export type YaWorkspaceKey = keyof typeof zh;
58
+ export declare const en: {
59
+ workspaces: string;
60
+ sessions: string;
61
+ recent: string;
62
+ ungrouped: string;
63
+ newSession: string;
64
+ addWorkspace: string;
65
+ addWorkspaceMenu: string;
66
+ search: string;
67
+ searchPlaceholder: string;
68
+ clearSearch: string;
69
+ searching: string;
70
+ searchUnavailable: string;
71
+ noMatches: string;
72
+ noSessions: string;
73
+ noWorkspaces: string;
74
+ loading: string;
75
+ rename: string;
76
+ renameWorkspace: string;
77
+ renameSession: string;
78
+ deleteWorkspace: string;
79
+ deleteDescription: string;
80
+ fork: string;
81
+ archive: string;
82
+ archiveMode: string;
83
+ deleteMode: string;
84
+ deleteSession: string;
85
+ deleteSessionTitle: string;
86
+ deleteSessionConfirm: string;
87
+ toggleActionMode: string;
88
+ actionModeLabel: string;
89
+ cancel: string;
90
+ confirm: string;
91
+ retry: string;
92
+ folderError: string;
93
+ workspaceName: string;
94
+ sessionName: string;
95
+ count: string;
96
+ now: string;
97
+ minutes: string;
98
+ hours: string;
99
+ days: string;
100
+ months: string;
101
+ years: string;
102
+ running: string;
103
+ waiting: string;
104
+ completed: string;
105
+ collapse: string;
106
+ expand: string;
107
+ resizeRecent: string;
108
+ today: string;
109
+ yesterday: string;
110
+ date: string;
111
+ dateYear: string;
112
+ };
113
+ export declare const NS = "ya-workspace-sidebar";
@@ -1,53 +1,87 @@
1
- /** Pure sidebar projections shared by the browser and unit tests. */
2
- import type { SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
3
- /** Navigation key for sessions not accounted to a real workspace. */
4
- export declare const UNGROUPED: "__ya_ungrouped__";
5
- /** One sidebar session row. */
6
- export interface SessionRow {
7
- id: SessionId;
8
- title: string;
9
- blank: boolean;
10
- running: boolean;
11
- pendingInteraction?: SessionSummary['pendingInteraction'];
12
- completed: boolean;
13
- updatedAt: number;
14
- workspaceKey: WorkspaceId | typeof UNGROUPED;
15
- workspaceTitle: string;
16
- }
17
- /** One date-bucketed group of session rows for the real-workspace level. */
18
- export interface SessionDateGroup {
19
- /** Local calendar date `YYYY-MM-DD`, stable key. */
20
- dateKey: string;
21
- /** Days between today's local date and this group's local date (0=today, 1=yesterday, …). */
22
- dayOffset: number;
23
- rows: SessionRow[];
24
- }
25
- /** One first-level workspace row. */
26
- export interface WorkspaceRow {
27
- key: WorkspaceId | typeof UNGROUPED;
28
- title: string;
29
- path?: string;
30
- createdAt?: string;
31
- count: number;
32
- real: boolean;
33
- }
34
- /** Resolve the first/second-level destination for one session. */
35
- export declare function workspaceKeyForSession(sessionId: SessionId | undefined, workspaces: readonly WorkspaceView[]): WorkspaceId | typeof UNGROUPED | null;
36
- /** Derive global recent sessions, newest first. */
37
- export declare function deriveRecent(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], limit?: number): SessionRow[];
38
- /** Derive first-level real workspaces plus the virtual Ungrouped row. */
39
- export declare function deriveWorkspaces(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): WorkspaceRow[];
40
- /** Derive the selected workspace's sessions in its canonical order. */
41
- export declare function deriveWorkspaceSessions(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): SessionRow[];
42
- /**
43
- * Derive the selected real workspace's sessions grouped by local calendar date.
44
- *
45
- * - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
46
- * - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
47
- * - {@link visible} filter is reused (archived / subagent / blank visibility).
48
- * - Future timestamps clamp to today's bucket (`dayOffset` 0).
49
- * - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
50
- */
51
- export declare function deriveWorkspaceSessionGroups(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], now: number): SessionDateGroup[];
52
- /** Case-insensitive local title/workspace matching used beside Host content search. */
53
- export declare function localMatches(rows: readonly SessionRow[], query: string): SessionRow[];
1
+ /** Pure sidebar projections shared by the browser and unit tests. */
2
+ import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
3
+ import type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
4
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
5
+ /** Pending-interaction kinds surfaced as a row status dot. */
6
+ export type PendingInteractionKind = 'approval' | 'plan-review' | 'question';
7
+ /** Renderer-visible view of ui-session's pending-interaction snapshot entries. */
8
+ export type PendingInteractionEntry = {
9
+ readonly kind: string;
10
+ };
11
+ /** Pending-interaction snapshot consumed by the derive functions. */
12
+ export type PendingInteractionMap = ReadonlyMap<SessionId, PendingInteractionEntry>;
13
+ /** Navigation key for sessions not accounted to a real workspace. */
14
+ export declare const UNGROUPED: "__ya_ungrouped__";
15
+ /** One sidebar session row. */
16
+ export interface SessionRow {
17
+ id: SessionId;
18
+ title: string;
19
+ blank: boolean;
20
+ running: boolean;
21
+ pendingInteraction?: PendingInteractionKind;
22
+ completed: boolean;
23
+ updatedAt: number;
24
+ workspaceKey: WorkspaceId | typeof UNGROUPED;
25
+ workspaceTitle: string;
26
+ }
27
+ /** One date-bucketed group. Empty `dateKey` is the undated trailing bucket. */
28
+ export interface DateGroup<T> {
29
+ /** Local calendar date `YYYY-MM-DD`, or `''` for rows with no timestamp. */
30
+ dateKey: string;
31
+ /** Days between today's local date and this group's local date (0=today, 1=yesterday, …). */
32
+ dayOffset: number;
33
+ rows: T[];
34
+ }
35
+ /** One date-bucketed group of session rows for the real-workspace level. */
36
+ export type SessionDateGroup = DateGroup<SessionRow>;
37
+ /** One date-bucketed group of first-level workspace rows. */
38
+ export type WorkspaceDateGroup = DateGroup<WorkspaceRow>;
39
+ /** One first-level workspace row. */
40
+ export interface WorkspaceRow {
41
+ key: WorkspaceId | typeof UNGROUPED;
42
+ title: string;
43
+ path?: string;
44
+ createdAt?: string;
45
+ /** Newest visible session `updatedAt`; empty real workspaces fall back to `createdAt`. */
46
+ lastUsedAt?: number;
47
+ count: number;
48
+ real: boolean;
49
+ }
50
+ /** Resolve the first/second-level destination for one session. */
51
+ export declare function workspaceKeyForSession(sessionId: SessionId | undefined, workspaces: readonly WorkspaceView[]): WorkspaceId | typeof UNGROUPED | null;
52
+ /** Derive global recent sessions, newest first. */
53
+ export declare function deriveRecent(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], pending: PendingInteractionMap, limit?: number): SessionRow[];
54
+ /** Fixed occupied height of one recent-sessions row: 33px two-line row + 2px vertical margins. */
55
+ export declare const RECENT_ROW_STRIDE = 35;
56
+ /** Half-open render window `[start, end)` of a fixed-stride virtual list. */
57
+ export interface VirtualWindow {
58
+ start: number;
59
+ end: number;
60
+ }
61
+ /**
62
+ * Windowing math for the recent-sessions virtual list (fixed row stride).
63
+ *
64
+ * Clamps `scrollTop` into the valid range, then pads the visible row range
65
+ * with `overscan` rows on both edges. Before the viewport has been measured
66
+ * (`viewportHeight <= 0`) it still returns a small head window so the first
67
+ * paint is never blank.
68
+ */
69
+ export declare function virtualWindow(scrollTop: number, viewportHeight: number, count: number, stride?: number, overscan?: number): VirtualWindow;
70
+ /** Derive first-level workspaces plus Ungrouped, newest session activity first. */
71
+ export declare function deriveWorkspaces(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): WorkspaceRow[];
72
+ /** Derive the selected workspace's sessions in its canonical order. */
73
+ export declare function deriveWorkspaceSessions(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], pending: PendingInteractionMap): SessionRow[];
74
+ /**
75
+ * Derive the selected real workspace's sessions grouped by local calendar date.
76
+ *
77
+ * - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
78
+ * - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
79
+ * - {@link visible} filter is reused (archived / subagent / blank visibility).
80
+ * - Future timestamps clamp to today's bucket (`dayOffset` 0).
81
+ * - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
82
+ */
83
+ export declare function deriveWorkspaceSessionGroups(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], pending: PendingInteractionMap, now: number): SessionDateGroup[];
84
+ /** Group root workspace rows by local calendar date of `lastUsedAt`; undated rows trail with empty `dateKey`. */
85
+ export declare function deriveWorkspaceGroups(rows: readonly WorkspaceRow[], now: number): WorkspaceDateGroup[];
86
+ /** Case-insensitive local title/workspace matching used beside Host content search. */
87
+ export declare function localMatches(rows: readonly SessionRow[], query: string): SessionRow[];