@deepseek-ai/dsh-client-ui-workspace 0.1.6-alpha.2 → 0.1.7-alpha.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/README.i18n.yaml +2 -2
- package/README.md +102 -11
- package/README.zh.md +102 -11
- package/lib/client.js +2182 -1015
- package/lib/types/client/contract/slots.d.ts +253 -16
- package/lib/types/client/index.d.ts +6 -2
- package/lib/types/client/locales.d.ts +84 -2
- package/lib/types/client/navigation.d.ts +39 -6
- package/lib/types/client/pin-order.d.ts +31 -0
- package/lib/types/client/rows/AnimatedRows.d.ts +44 -0
- package/lib/types/client/rows/Rows.d.ts +15 -15
- package/lib/types/client/rows/WorkspaceBrowser.d.ts +1 -1
- package/lib/types/client/session-actions/ArchiveSession.d.ts +23 -0
- package/lib/types/client/session-actions/ForkSession.d.ts +9 -0
- package/lib/types/client/session-actions/PinSession.d.ts +14 -0
- package/lib/types/client/session-actions/RenameSession.d.ts +18 -0
- package/lib/types/client/session-actions/RowActionToast.d.ts +11 -0
- package/lib/types/client/session-actions/derived.d.ts +12 -0
- package/lib/types/client/stores.d.ts +14 -0
- package/lib/types/client/tree.d.ts +53 -20
- package/package.json +26 -23
- package/lib/types/client/subagent-lineage.d.ts +0 -21
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* - WorkspacePicker fills the conversation empty-state hole (menu + error
|
|
9
9
|
* dialog shared with the browser).
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Both registrations declare a **directory-flow hole** (`single` kind): the
|
|
12
|
+
* slot a composed picker package's client half fills with its
|
|
13
13
|
* picking interaction — a renderless native-chooser driver or an in-app
|
|
14
14
|
* browsing dialog. ui-workspace owns the trigger (the "Add workspace…"
|
|
15
15
|
* entry, present only while the hole is occupied) and the adoption
|
|
@@ -21,11 +21,21 @@
|
|
|
21
21
|
* Two holes exist because the two menu surfaces are independent slot entries
|
|
22
22
|
* and a hole has exactly one declaring entry — they carry the same owner
|
|
23
23
|
* contract and the same occupant.
|
|
24
|
+
*
|
|
25
|
+
* WorkspaceBrowser also declares the two **Session row action lists**: every
|
|
26
|
+
* row of a Session's "..." menu is an entry of
|
|
27
|
+
* `sidebar.workspaces.session.menu.item`, and every hover button at the row's
|
|
28
|
+
* end is an entry of `sidebar.workspaces.session.row.action`. The shipped
|
|
29
|
+
* actions — pin, rename, fork, archive — are ordinary entries this package
|
|
30
|
+
* registers from `apply`, each carrying its own behavior in its own inject
|
|
31
|
+
* face and reading its own Host state through hooks that face injects, so a
|
|
32
|
+
* client plugin's action lands beside them by `order` and needs nothing from
|
|
33
|
+
* the browser beyond the row identity.
|
|
24
34
|
*/
|
|
25
|
-
import type { HostObservable, PropsHooks, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
|
|
35
|
+
import type { HostObservable, InjectFace, PropsHooks, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore, SlotHookFactory } from '@deepseek-ai/dsh-client-ui-slots';
|
|
26
36
|
import type { SessionSearchResultItem } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
27
37
|
import type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client';
|
|
28
|
-
import type { WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
38
|
+
import type { SessionActivity, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
29
39
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
30
40
|
import type { createWorkspaceViewStore } from '../stores.ts';
|
|
31
41
|
/**
|
|
@@ -45,6 +55,30 @@ export interface DirectoryFlowOwnerProps {
|
|
|
45
55
|
/** The interaction itself failed (chooser missing, listing denied); the owner shows its error surface. */
|
|
46
56
|
onError: (message: string) => void;
|
|
47
57
|
}
|
|
58
|
+
/** Owner share of one Session row action occurrence: the row the action belongs to. */
|
|
59
|
+
export interface SessionRowOwnerProps {
|
|
60
|
+
/** Session the row shows. */
|
|
61
|
+
sessionId: SessionId;
|
|
62
|
+
/** Row display title: persisted title, project basename, or Session id. */
|
|
63
|
+
displayTitle: string;
|
|
64
|
+
}
|
|
65
|
+
/** The row menu's open state as its owner holds it: the `useState` pair. */
|
|
66
|
+
export type MenuOpenState = readonly [open: boolean, setOpen: (open: boolean) => void];
|
|
67
|
+
/**
|
|
68
|
+
* Hook every row-menu entry receives. Rows only render while the menu is
|
|
69
|
+
* open, so an entry reads it for the setter: `setOpen(false)` dismisses the
|
|
70
|
+
* menu the entry sits in — the same state the owner's `onClose` sets.
|
|
71
|
+
*/
|
|
72
|
+
export type UseMenuOpenState = () => MenuOpenState;
|
|
73
|
+
/**
|
|
74
|
+
* Bind the row's render occurrence into the entries' `useMenuOpenState` hook:
|
|
75
|
+
* the owner supplies its open-state pair as the occurrence's `hookContext`,
|
|
76
|
+
* and the hook hands that pair back.
|
|
77
|
+
* @param _standard - framework standard props (unused).
|
|
78
|
+
* @param state - the menu's open-state pair from the render occurrence.
|
|
79
|
+
* @returns the hook the entry calls.
|
|
80
|
+
*/
|
|
81
|
+
export declare const menuOpenStateFactory: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState>;
|
|
48
82
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
49
83
|
interface SlotMap {
|
|
50
84
|
/** Directory-flow hole under the conversation empty-state picker (declared by the WorkspacePicker entry). */
|
|
@@ -59,6 +93,61 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
59
93
|
scope: 'root';
|
|
60
94
|
owner: DirectoryFlowOwnerProps;
|
|
61
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* The rows of one Session's "..." menu, in ascending `order`. ui-workspace
|
|
98
|
+
* registers the shipped rows here — `pin` (100), `rename` (200), `fork`
|
|
99
|
+
* (300), `archive` (400) — so a plugin row is placed by its own `order`
|
|
100
|
+
* among them. Use a package-namespaced `id`; reusing a shipped id at
|
|
101
|
+
* another `priority` shadows that row. Each entry renders one
|
|
102
|
+
* `role="menuitem"` `<button>` (the shipped rows use ui-primitives'
|
|
103
|
+
* `MenuItemButton`, which adds the host styling and `separatorBefore`),
|
|
104
|
+
* decides its own visibility from its own state, and dismisses the menu
|
|
105
|
+
* through the injected `useMenuOpenState` hook after acting; the list's
|
|
106
|
+
* keyboard walk and focus return read the DOM, so any such button joins
|
|
107
|
+
* them. Labels come from the contributing package's locale namespace.
|
|
108
|
+
* @example
|
|
109
|
+
* return {
|
|
110
|
+
* inject: ['slots'],
|
|
111
|
+
* apply(ctx) {
|
|
112
|
+
* const copyLabel = 'Copy Session ID' // Localize in the contributing package.
|
|
113
|
+
* ctx.slots.inject('sidebar.workspaces.session.menu.item', () => ctx.slots.register(
|
|
114
|
+
* { name: 'sidebar.workspaces.session.menu.item', id: 'copy-session-id', order: 500 },
|
|
115
|
+
* ({ sessionId, useMenuOpenState }) => {
|
|
116
|
+
* const [, setMenuOpen] = useMenuOpenState()
|
|
117
|
+
* return React.createElement(
|
|
118
|
+
* 'button',
|
|
119
|
+
* { type: 'button', role: 'menuitem', onClick: () => { setMenuOpen(false); void navigator.clipboard.writeText(sessionId) } },
|
|
120
|
+
* copyLabel,
|
|
121
|
+
* )
|
|
122
|
+
* },
|
|
123
|
+
* ))
|
|
124
|
+
* },
|
|
125
|
+
* }
|
|
126
|
+
*/
|
|
127
|
+
'sidebar.workspaces.session.menu.item': {
|
|
128
|
+
kind: 'list';
|
|
129
|
+
scope: 'root';
|
|
130
|
+
owner: SessionRowOwnerProps;
|
|
131
|
+
hookContext: MenuOpenState;
|
|
132
|
+
inject: {
|
|
133
|
+
hooks: {
|
|
134
|
+
menuOpenState: SlotHookFactory<'sidebar.workspaces.session.menu.item', UseMenuOpenState>;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* The hover buttons at the end of one Session row, in ascending `order`,
|
|
140
|
+
* after the "..." menu trigger. ui-workspace registers `archive` (100) and
|
|
141
|
+
* `pin` (200) here. An entry renders one icon button (or nothing, when its
|
|
142
|
+
* action does not apply to the row) and owns the action it performs. Clicks
|
|
143
|
+
* inside the strip stay in the strip, so the button needs no propagation
|
|
144
|
+
* handling to keep the row from opening.
|
|
145
|
+
*/
|
|
146
|
+
'sidebar.workspaces.session.row.action': {
|
|
147
|
+
kind: 'list';
|
|
148
|
+
scope: 'root';
|
|
149
|
+
owner: SessionRowOwnerProps;
|
|
150
|
+
};
|
|
62
151
|
}
|
|
63
152
|
}
|
|
64
153
|
/** The two directory-flow holes; a flow package's client half registers its one component into both. */
|
|
@@ -111,10 +200,10 @@ export type WorkspaceBrowserInjected = {
|
|
|
111
200
|
}>;
|
|
112
201
|
/** Maximum number of merged rows rendered for one search. */
|
|
113
202
|
searchResultLimit: number;
|
|
114
|
-
/**
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
|
|
203
|
+
/** Open the Session rename dialog (a row title double-click); the rename action entry raises the same request. */
|
|
204
|
+
requestSessionRename: (sessionId: SessionId, currentTitle: string) => void;
|
|
205
|
+
/** Tell the user an archived row cannot be opened (a click on it). */
|
|
206
|
+
notifyArchivedNotOpenable: () => void;
|
|
118
207
|
/** Rename a Host Workspace (rejects on name conflict; resolves on durability). */
|
|
119
208
|
renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>;
|
|
120
209
|
/** Delete only a Host Workspace registration; directory and Session logs remain. */
|
|
@@ -124,19 +213,167 @@ export type WorkspaceBrowserInjected = {
|
|
|
124
213
|
* Omitted anchor appends to the end.
|
|
125
214
|
*/
|
|
126
215
|
insertWorkspaceBefore: (workspaceId: WorkspaceId, beforeWorkspaceId?: WorkspaceId) => Promise<void>;
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
* surfaces, log and accounting slot retained. Archiving the current
|
|
130
|
-
* session clears the selection into the New Session view state.
|
|
131
|
-
*/
|
|
132
|
-
archiveSession: (sessionId: SessionId) => Promise<void>;
|
|
216
|
+
/** Remove a Session from the registry-global archived set (the search results' restore button). */
|
|
217
|
+
unarchiveSession: (sessionId: SessionId) => Promise<void>;
|
|
133
218
|
/** Adopt a picked host directory as a real Workspace before targeting a Session. */
|
|
134
219
|
createWorkspace: (input: {
|
|
135
220
|
path: string;
|
|
136
221
|
}) => Promise<WorkspaceView>;
|
|
137
222
|
};
|
|
223
|
+
/** The browser's declared viewing store handle, shared with the row actions that write view state. */
|
|
224
|
+
export type WorkspaceViewStoreHandle = ReturnType<typeof createWorkspaceViewStore>;
|
|
225
|
+
/** Props of one shipped row-menu entry: owner share + locale seat + the entry's own injected share. */
|
|
226
|
+
export type SessionMenuItemProps<Injected extends object = object> = PropsRuntime<'sidebar.workspaces.session.menu.item'> & PropsLocale<'workspace'> & InjectFace<Injected>;
|
|
227
|
+
/** Props of one shipped row hover button: owner share + locale seat + the entry's own injected share. */
|
|
228
|
+
export type SessionRowActionProps<Injected extends object = object> = PropsRuntime<'sidebar.workspaces.session.row.action'> & PropsLocale<'workspace'> & InjectFace<Injected>;
|
|
229
|
+
/** One transient Workspace notice rendered by the overlay toast entry. */
|
|
230
|
+
export type RowToast = {
|
|
231
|
+
kind: 'archived';
|
|
232
|
+
sessionId: SessionId;
|
|
233
|
+
} | {
|
|
234
|
+
kind: 'stoppedAndArchived';
|
|
235
|
+
sessionId: SessionId;
|
|
236
|
+
} | {
|
|
237
|
+
kind: 'pinFailed';
|
|
238
|
+
} | {
|
|
239
|
+
kind: 'unpinFailed';
|
|
240
|
+
} | {
|
|
241
|
+
kind: 'archivedNotOpenable';
|
|
242
|
+
} | {
|
|
243
|
+
kind: 'defaultWorkspaceFailed';
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* An explicit New Session request that failed. `message` is untranslated:
|
|
247
|
+
* a Host refusal as `code: message` — the stable code stays in the copy so
|
|
248
|
+
* a report can be searched by it — and any other failure's own message.
|
|
249
|
+
*/
|
|
250
|
+
| {
|
|
251
|
+
kind: 'createFailed';
|
|
252
|
+
message: string;
|
|
253
|
+
};
|
|
254
|
+
/** The notice on display; `seq` keys remounts so a repeated notice restarts its hold. */
|
|
255
|
+
export type RowToastState = RowToast & {
|
|
256
|
+
seq: number;
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Pin action share (menu row and hover button). The callbacks carry the whole
|
|
260
|
+
* behavior: the Host call, fronting the Session in its saved orders after a
|
|
261
|
+
* pin, and the failure notice. The hooks are the registry-global sets as
|
|
262
|
+
* Sets, so a row reads its own membership with one lookup.
|
|
263
|
+
*/
|
|
264
|
+
export interface PinSessionInjected {
|
|
265
|
+
hooks: {
|
|
266
|
+
/** Pinned Session ids. */
|
|
267
|
+
pinned: HostObservable<ReadonlySet<SessionId>>;
|
|
268
|
+
/** Archived Session ids (pin does not apply to an archived row). */
|
|
269
|
+
archived: HostObservable<ReadonlySet<SessionId>>;
|
|
270
|
+
};
|
|
271
|
+
/** Pin a Session; on success it leads its accounts' saved orders, on failure the notice says so. */
|
|
272
|
+
pinSession: (sessionId: SessionId) => void;
|
|
273
|
+
/** Unpin a Session; saved positions stay as they are. */
|
|
274
|
+
unpinSession: (sessionId: SessionId) => void;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Archive action share (menu row and hover button). The callbacks carry the
|
|
278
|
+
* whole behavior: the Host call, the notice a success raises, the
|
|
279
|
+
* stop-and-archive confirmation a Host refusal for running work raises, and
|
|
280
|
+
* the diagnostics for any other rejection.
|
|
281
|
+
*/
|
|
282
|
+
export interface ArchiveSessionInjected {
|
|
283
|
+
hooks: {
|
|
284
|
+
/** Archived Session ids. */
|
|
285
|
+
archived: HostObservable<ReadonlySet<SessionId>>;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Archive a Session into the registry-global set: the row keeps its
|
|
289
|
+
* account position and shows per the archived filter; archiving the
|
|
290
|
+
* current session clears the selection into the New Session view state.
|
|
291
|
+
* A Session with running work is not archived by this call: the Host's
|
|
292
|
+
* refusal opens the stop-and-archive confirmation instead.
|
|
293
|
+
*/
|
|
294
|
+
archiveSession: (sessionId: SessionId) => void;
|
|
295
|
+
/** Remove a Session from the registry-global archived set. */
|
|
296
|
+
unarchiveSession: (sessionId: SessionId) => void;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* A stop-and-archive confirmation the archive action asked for: the Host
|
|
300
|
+
* refused the plain archive because this work still runs.
|
|
301
|
+
*/
|
|
302
|
+
export interface SessionArchiveConfirmRequest {
|
|
303
|
+
/** Session to stop and archive. */
|
|
304
|
+
sessionId: SessionId;
|
|
305
|
+
/** The row's display title, named in the dialog. */
|
|
306
|
+
displayTitle: string;
|
|
307
|
+
/** What the Host reported running, in family order. */
|
|
308
|
+
activity: readonly SessionActivity[];
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Stop-and-archive dialog share: the pending confirmation, its settlement,
|
|
312
|
+
* and the archive hop that asks the Host to stop the work first.
|
|
313
|
+
*/
|
|
314
|
+
export interface SessionArchiveConfirmInjected {
|
|
315
|
+
hooks: {
|
|
316
|
+
/** The confirmation asked for, until the dialog consumes or cancels it. */
|
|
317
|
+
archiveRequest: HostObservable<SessionArchiveConfirmRequest | null>;
|
|
318
|
+
};
|
|
319
|
+
/** Consume or cancel the pending confirmation. */
|
|
320
|
+
settleSessionArchive: () => void;
|
|
321
|
+
/**
|
|
322
|
+
* Archive a Session after the Host stops its running work; resolves once
|
|
323
|
+
* the archive set is durable (the stops settle in the background) and
|
|
324
|
+
* raises the stopped-and-archived notice.
|
|
325
|
+
*/
|
|
326
|
+
stopAndArchiveSession: (sessionId: SessionId) => Promise<void>;
|
|
327
|
+
}
|
|
328
|
+
/** Fork action share. */
|
|
329
|
+
export interface ForkSessionInjected {
|
|
330
|
+
/** Fork a Session at its last completed turn; the child arrives through the Host list. */
|
|
331
|
+
forkSession: (sessionId: SessionId) => void;
|
|
332
|
+
}
|
|
333
|
+
/** Rename action share: the row only raises the request; the dialog entry answers it. */
|
|
334
|
+
export interface RenameSessionInjected {
|
|
335
|
+
/** Ask for the rename dialog, seeded with the row's current title. */
|
|
336
|
+
requestSessionRename: (sessionId: SessionId, currentTitle: string) => void;
|
|
337
|
+
}
|
|
338
|
+
/** A Session rename the rename action asked for; the dialog entry opens on it. */
|
|
339
|
+
export interface SessionRenameTarget {
|
|
340
|
+
/** Session to rename. */
|
|
341
|
+
sessionId: SessionId;
|
|
342
|
+
/** Title the dialog seeds its draft from. */
|
|
343
|
+
currentTitle: string;
|
|
344
|
+
}
|
|
345
|
+
/** Rename dialog share: the pending request, its settlement, and the rename hop the dialog confirms with. */
|
|
346
|
+
export interface SessionRenameDialogInjected {
|
|
347
|
+
hooks: {
|
|
348
|
+
/** The rename asked for, until the dialog consumes or cancels it. */
|
|
349
|
+
renameRequest: HostObservable<SessionRenameTarget | null>;
|
|
350
|
+
};
|
|
351
|
+
/** Consume or cancel the pending request. */
|
|
352
|
+
settleSessionRename: () => void;
|
|
353
|
+
/** Rename a Session (explicit user title; resolves on host acceptance). */
|
|
354
|
+
renameSession: (sessionId: SessionId, title: string) => Promise<void>;
|
|
355
|
+
}
|
|
356
|
+
/** Row toast share: the notice on display, its dismissal, and the two actions the archived notice offers. */
|
|
357
|
+
export interface RowToastInjected {
|
|
358
|
+
hooks: {
|
|
359
|
+
/** The notice on display, or none. */
|
|
360
|
+
toast: HostObservable<RowToastState | null>;
|
|
361
|
+
};
|
|
362
|
+
/** Take the notice down. */
|
|
363
|
+
dismissToast: () => void;
|
|
364
|
+
/** Undo an archive from its notice. */
|
|
365
|
+
undoArchive: (sessionId: SessionId) => void;
|
|
366
|
+
/** Switch the archived filter to "show" so the archived row is back in view. */
|
|
367
|
+
showArchived: () => void;
|
|
368
|
+
}
|
|
369
|
+
/** Props of the rename dialog entry in `shell.overlay`. */
|
|
370
|
+
export type SessionRenameDialogProps = PropsRuntime<'shell.overlay'> & PropsLocale<'workspace'> & Omit<SessionRenameDialogInjected, 'hooks'> & PropsHooks<SessionRenameDialogInjected['hooks']>;
|
|
371
|
+
/** Props of the stop-and-archive dialog entry in `shell.overlay`. */
|
|
372
|
+
export type SessionArchiveConfirmProps = PropsRuntime<'shell.overlay'> & PropsLocale<'workspace'> & Omit<SessionArchiveConfirmInjected, 'hooks'> & PropsHooks<SessionArchiveConfirmInjected['hooks']>;
|
|
373
|
+
/** Props of the row toast entry in `shell.overlay`. */
|
|
374
|
+
export type RowToastProps = PropsRuntime<'shell.overlay'> & PropsLocale<'workspace'> & Omit<RowToastInjected, 'hooks'> & PropsHooks<RowToastInjected['hooks']>;
|
|
138
375
|
/** Full browser props: shell owner share + viewing store + injected actions + the locale seat. */
|
|
139
|
-
export type WorkspaceBrowserProps = PropsRuntime<'sidebar.workspaces'> & PropsRenderSlots<'sidebar.workspaces.directoryFlow'> & PropsStore<
|
|
376
|
+
export type WorkspaceBrowserProps = PropsRuntime<'sidebar.workspaces'> & PropsRenderSlots<'sidebar.workspaces.directoryFlow' | 'sidebar.workspaces.session.menu.item' | 'sidebar.workspaces.session.row.action'> & PropsStore<WorkspaceViewStoreHandle> & Omit<WorkspaceBrowserInjected, 'hooks'> & PropsHooks<WorkspaceBrowserInjected['hooks']> & PropsLocale<'workspace'>;
|
|
140
377
|
/**
|
|
141
378
|
* Picker-private injected share. Pick semantics remain in the owner's onPick
|
|
142
379
|
* callback; this callback creates only the real Host Workspace. A type alias
|
|
@@ -153,5 +390,5 @@ export type WorkspacePickerInjected = DirectoryPickingInjected & {
|
|
|
153
390
|
* locale seat. The two picker holes (blank-session hero / New-Session view)
|
|
154
391
|
* share one owner currency, so one composed type serves both registrations.
|
|
155
392
|
*/
|
|
156
|
-
export type WorkspacePickerProps = PropsRuntime<'conversation.hero.workspace'> & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'> & Omit<WorkspacePickerInjected, 'hooks'> &
|
|
393
|
+
export type WorkspacePickerProps = PropsRuntime<'conversation.hero.workspace'> & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'> & Omit<WorkspacePickerInjected, 'hooks'> & PropsHooks<WorkspacePickerInjected['hooks']> & PropsLocale<'workspace'>;
|
|
157
394
|
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
* (`conversation.hero.workspace` — both hero forms). Both read real Host
|
|
6
6
|
* Workspaces through the global useWorkspaces hook, and each declares its
|
|
7
7
|
* own `single` directory-flow child hole for the composed picker package's
|
|
8
|
-
* client half
|
|
8
|
+
* client half. WorkspaceBrowser additionally declares the two Session row
|
|
9
|
+
* action lists, and this apply registers the shipped actions — pin, rename,
|
|
10
|
+
* fork, archive — into them the way any client plugin would, each with its
|
|
11
|
+
* own behavior, plus the rename dialog and the row-action notice into
|
|
12
|
+
* `shell.overlay` (see the contract module doc). Export discipline:
|
|
9
13
|
* packages/client/AGENTS.md.
|
|
10
14
|
*/
|
|
11
15
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -13,7 +17,7 @@ import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controlle
|
|
|
13
17
|
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
|
|
14
18
|
import { type WorkspaceKey } from './locales.ts';
|
|
15
19
|
export type { UiWorkspace } from './navigation.ts';
|
|
16
|
-
export type { DirectoryFlowOwnerProps, DirectoryFlowSlotName, DirectoryPickingHooks, DirectoryPickingInjected, WorkspaceBrowserInjected, WorkspaceBrowserProps, WorkspacePickerInjected, WorkspacePickerProps, } from './contract/slots.ts';
|
|
20
|
+
export type { DirectoryFlowOwnerProps, DirectoryFlowSlotName, DirectoryPickingHooks, DirectoryPickingInjected, MenuOpenState, RowToast, SessionRenameTarget, SessionRowOwnerProps, UseMenuOpenState, WorkspaceBrowserInjected, WorkspaceBrowserProps, WorkspacePickerInjected, WorkspacePickerProps, } from './contract/slots.ts';
|
|
17
21
|
export type { WorkspaceKey } from './locales.ts';
|
|
18
22
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
19
23
|
interface GlobalStandardProps {
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
7
7
|
export declare const zh: {
|
|
8
|
+
'defaultWorkspace.failed': string;
|
|
9
|
+
'defaultWorkspace.title': string;
|
|
8
10
|
'group.ungrouped': string;
|
|
9
11
|
'session.new': string;
|
|
10
12
|
'section.workspaces': string;
|
|
@@ -17,6 +19,9 @@ export declare const zh: {
|
|
|
17
19
|
'orderBy.label': string;
|
|
18
20
|
'orderBy.manual': string;
|
|
19
21
|
'orderBy.updated': string;
|
|
22
|
+
'filterBy.label': string;
|
|
23
|
+
'viewOptions.showArchived': string;
|
|
24
|
+
'viewOptions.onlyArchived': string;
|
|
20
25
|
'sessions.expand': string;
|
|
21
26
|
'sessions.collapse': string;
|
|
22
27
|
'empty.none': string;
|
|
@@ -27,7 +32,6 @@ export declare const zh: {
|
|
|
27
32
|
'search.clear': string;
|
|
28
33
|
'search.results.aria': string;
|
|
29
34
|
'search.pending': string;
|
|
30
|
-
'search.unavailable': string;
|
|
31
35
|
'search.noMatches': string;
|
|
32
36
|
'search.hasMore': string;
|
|
33
37
|
'menu.addWorkspace': string;
|
|
@@ -45,10 +49,44 @@ export declare const zh: {
|
|
|
45
49
|
'delete.pending': string;
|
|
46
50
|
'menu.fork': string;
|
|
47
51
|
'menu.archiveSession': string;
|
|
52
|
+
'menu.unarchiveSession': string;
|
|
53
|
+
'menu.pinSession': string;
|
|
54
|
+
'menu.unpinSession': string;
|
|
55
|
+
'row.archived': string;
|
|
56
|
+
'row.pinned': string;
|
|
57
|
+
'toast.archivedNotOpenable': string;
|
|
58
|
+
'toast.archived': string;
|
|
59
|
+
'toast.stoppedAndArchived': string;
|
|
60
|
+
'archive.confirm.title': string;
|
|
61
|
+
'archive.confirm.desc': string;
|
|
62
|
+
'archive.confirm.activity': string;
|
|
63
|
+
'archive.confirm.turn': string;
|
|
64
|
+
'archive.confirm.subagents.one': string;
|
|
65
|
+
'archive.confirm.subagents.other': string;
|
|
66
|
+
'archive.confirm.jobs.one': string;
|
|
67
|
+
'archive.confirm.jobs.other': string;
|
|
68
|
+
'archive.confirm.schedules.one': string;
|
|
69
|
+
'archive.confirm.schedules.other': string;
|
|
70
|
+
'archive.confirm.other.one': string;
|
|
71
|
+
'archive.confirm.other.other': string;
|
|
72
|
+
'archive.confirm.listSeparator': string;
|
|
73
|
+
'archive.confirm.action': string;
|
|
74
|
+
'archive.confirm.pending': string;
|
|
75
|
+
'toast.archivedUndo': string;
|
|
76
|
+
'toast.archivedOr': string;
|
|
77
|
+
'toast.archivedFilter': string;
|
|
78
|
+
'toast.pinFailed': string;
|
|
79
|
+
'toast.unpinFailed': string;
|
|
80
|
+
'toast.createFailed': string;
|
|
48
81
|
'sessions.count.one': string;
|
|
49
82
|
'sessions.count.other': string;
|
|
50
83
|
'actions.workspace.aria': string;
|
|
51
84
|
'actions.session.aria': string;
|
|
85
|
+
'actions.archive': string;
|
|
86
|
+
'actions.unarchive': string;
|
|
87
|
+
'actions.pin': string;
|
|
88
|
+
'actions.unpin': string;
|
|
89
|
+
'actions.newSession': string;
|
|
52
90
|
'actions.newSession.aria': string;
|
|
53
91
|
'status.running': string;
|
|
54
92
|
'status.subagentsRunning.one': string;
|
|
@@ -57,6 +95,9 @@ export declare const zh: {
|
|
|
57
95
|
'status.waitingApproval': string;
|
|
58
96
|
'status.planReview': string;
|
|
59
97
|
'status.waitingAnswer': string;
|
|
98
|
+
'status.compact.approval': string;
|
|
99
|
+
'status.compact.planReview': string;
|
|
100
|
+
'status.compact.answer': string;
|
|
60
101
|
'status.completed': string;
|
|
61
102
|
'schedule.active': string;
|
|
62
103
|
'hover.created': string;
|
|
@@ -74,6 +115,8 @@ export declare const zh: {
|
|
|
74
115
|
export type WorkspaceKey = keyof typeof zh;
|
|
75
116
|
/** English dictionary, checked complete against the zh key set. */
|
|
76
117
|
export declare const en: {
|
|
118
|
+
'defaultWorkspace.failed': string;
|
|
119
|
+
'defaultWorkspace.title': string;
|
|
77
120
|
'group.ungrouped': string;
|
|
78
121
|
'session.new': string;
|
|
79
122
|
'section.workspaces': string;
|
|
@@ -86,6 +129,9 @@ export declare const en: {
|
|
|
86
129
|
'orderBy.label': string;
|
|
87
130
|
'orderBy.manual': string;
|
|
88
131
|
'orderBy.updated': string;
|
|
132
|
+
'filterBy.label': string;
|
|
133
|
+
'viewOptions.showArchived': string;
|
|
134
|
+
'viewOptions.onlyArchived': string;
|
|
89
135
|
'sessions.expand': string;
|
|
90
136
|
'sessions.collapse': string;
|
|
91
137
|
'empty.none': string;
|
|
@@ -96,7 +142,6 @@ export declare const en: {
|
|
|
96
142
|
'search.clear': string;
|
|
97
143
|
'search.results.aria': string;
|
|
98
144
|
'search.pending': string;
|
|
99
|
-
'search.unavailable': string;
|
|
100
145
|
'search.noMatches': string;
|
|
101
146
|
'search.hasMore': string;
|
|
102
147
|
'menu.addWorkspace': string;
|
|
@@ -114,10 +159,44 @@ export declare const en: {
|
|
|
114
159
|
'delete.pending': string;
|
|
115
160
|
'menu.fork': string;
|
|
116
161
|
'menu.archiveSession': string;
|
|
162
|
+
'menu.unarchiveSession': string;
|
|
163
|
+
'menu.pinSession': string;
|
|
164
|
+
'menu.unpinSession': string;
|
|
165
|
+
'row.archived': string;
|
|
166
|
+
'row.pinned': string;
|
|
167
|
+
'toast.archivedNotOpenable': string;
|
|
168
|
+
'toast.archived': string;
|
|
169
|
+
'toast.stoppedAndArchived': string;
|
|
170
|
+
'archive.confirm.title': string;
|
|
171
|
+
'archive.confirm.desc': string;
|
|
172
|
+
'archive.confirm.activity': string;
|
|
173
|
+
'archive.confirm.turn': string;
|
|
174
|
+
'archive.confirm.subagents.one': string;
|
|
175
|
+
'archive.confirm.subagents.other': string;
|
|
176
|
+
'archive.confirm.jobs.one': string;
|
|
177
|
+
'archive.confirm.jobs.other': string;
|
|
178
|
+
'archive.confirm.schedules.one': string;
|
|
179
|
+
'archive.confirm.schedules.other': string;
|
|
180
|
+
'archive.confirm.other.one': string;
|
|
181
|
+
'archive.confirm.other.other': string;
|
|
182
|
+
'archive.confirm.listSeparator': string;
|
|
183
|
+
'archive.confirm.action': string;
|
|
184
|
+
'archive.confirm.pending': string;
|
|
185
|
+
'toast.archivedUndo': string;
|
|
186
|
+
'toast.archivedOr': string;
|
|
187
|
+
'toast.archivedFilter': string;
|
|
188
|
+
'toast.pinFailed': string;
|
|
189
|
+
'toast.unpinFailed': string;
|
|
190
|
+
'toast.createFailed': string;
|
|
117
191
|
'sessions.count.one': string;
|
|
118
192
|
'sessions.count.other': string;
|
|
119
193
|
'actions.workspace.aria': string;
|
|
120
194
|
'actions.session.aria': string;
|
|
195
|
+
'actions.archive': string;
|
|
196
|
+
'actions.unarchive': string;
|
|
197
|
+
'actions.pin': string;
|
|
198
|
+
'actions.unpin': string;
|
|
199
|
+
'actions.newSession': string;
|
|
121
200
|
'actions.newSession.aria': string;
|
|
122
201
|
'status.running': string;
|
|
123
202
|
'status.subagentsRunning.one': string;
|
|
@@ -126,6 +205,9 @@ export declare const en: {
|
|
|
126
205
|
'status.waitingApproval': string;
|
|
127
206
|
'status.planReview': string;
|
|
128
207
|
'status.waitingAnswer': string;
|
|
208
|
+
'status.compact.approval': string;
|
|
209
|
+
'status.compact.planReview': string;
|
|
210
|
+
'status.compact.answer': string;
|
|
129
211
|
'status.completed': string;
|
|
130
212
|
'schedule.active': string;
|
|
131
213
|
'hover.created': string;
|
|
@@ -4,6 +4,8 @@ import type { ClientRemote, DirectoryListing, RemoteFailure } from '@deepseek-ai
|
|
|
4
4
|
import type { ISessions, SessionTarget } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
5
5
|
import type { IWorkspaces, WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
6
6
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
7
|
+
import type { RowToast } from './contract/slots.ts';
|
|
8
|
+
import type { WorkspaceViewStoreActions } from './stores.ts';
|
|
7
9
|
/** Workspace archive and directory operations consumed by Client UI domains. */
|
|
8
10
|
export interface UiWorkspace {
|
|
9
11
|
/**
|
|
@@ -16,12 +18,14 @@ export interface UiWorkspace {
|
|
|
16
18
|
* @param workspaceId - target Workspace.
|
|
17
19
|
* @param beforeOpen - optional synchronous preparation for the selected Session, skipped after supersession.
|
|
18
20
|
* @returns completion; a superseded request may create a Session but does not open it.
|
|
21
|
+
* @throws on failure; a refused creation is also shown through the Workspace
|
|
22
|
+
* notice unless a later navigation or disposal superseded the request.
|
|
19
23
|
*/
|
|
20
24
|
openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void>;
|
|
21
25
|
/**
|
|
22
|
-
* Fork a Session
|
|
26
|
+
* Fork a Session without changing the current selection.
|
|
23
27
|
* @param sessionId - source Session.
|
|
24
|
-
* @returns completion
|
|
28
|
+
* @returns completion after child creation and inherited-title increment.
|
|
25
29
|
*/
|
|
26
30
|
forkSession(sessionId: SessionId): Promise<void>;
|
|
27
31
|
/**
|
|
@@ -31,20 +35,37 @@ export interface UiWorkspace {
|
|
|
31
35
|
*/
|
|
32
36
|
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>;
|
|
33
37
|
/**
|
|
34
|
-
* Start a New Session flow and navigate to its Session
|
|
38
|
+
* Start a New Session flow and navigate to its Session; a creation the Host
|
|
39
|
+
* refuses is shown through the Workspace notice and leaves the selection as it was.
|
|
35
40
|
* @param workspaceId - explicit target; absent inherits the current or most recent Workspace.
|
|
36
41
|
*/
|
|
37
42
|
startSession(workspaceId?: WorkspaceId): void;
|
|
38
43
|
/**
|
|
39
44
|
* Archive a Session and clear it when it is the current selection.
|
|
40
45
|
* @param sessionId - Session to archive.
|
|
46
|
+
* @param options - `stopActivity` asks the Host to stop the Session's running work instead of refusing.
|
|
41
47
|
*/
|
|
42
|
-
archiveSession(sessionId: SessionId
|
|
48
|
+
archiveSession(sessionId: SessionId, options?: {
|
|
49
|
+
readonly stopActivity?: boolean;
|
|
50
|
+
}): Promise<void>;
|
|
43
51
|
/**
|
|
44
52
|
* Unarchive a Session, restoring it to its recorded Workspace position.
|
|
45
53
|
* @param sessionId - Session to unarchive.
|
|
46
54
|
*/
|
|
47
55
|
unarchiveSession(sessionId: SessionId): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Pin a Session on the Host, then lead it in its accounts' saved orders
|
|
58
|
+
* (its Workspace group or Ungrouped, and the flat list). The order write
|
|
59
|
+
* reads the memberships current at completion, so reorders that landed
|
|
60
|
+
* while the Host call was pending keep their positions.
|
|
61
|
+
* @param sessionId - Session to pin.
|
|
62
|
+
*/
|
|
63
|
+
pinSession(sessionId: SessionId): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Unpin a Session on the Host; saved positions stay as they are.
|
|
66
|
+
* @param sessionId - Session to unpin.
|
|
67
|
+
*/
|
|
68
|
+
unpinSession(sessionId: SessionId): Promise<void>;
|
|
48
69
|
/**
|
|
49
70
|
* Open the Host-native directory picker.
|
|
50
71
|
* @returns the selected directory, or null when cancelled.
|
|
@@ -83,6 +104,8 @@ declare class UiWorkspaceService extends Service implements UiWorkspace {
|
|
|
83
104
|
private readonly directoryPicker;
|
|
84
105
|
private readonly workspaces;
|
|
85
106
|
private readonly sessions;
|
|
107
|
+
private readonly view;
|
|
108
|
+
private readonly notify;
|
|
86
109
|
private readonly connecting;
|
|
87
110
|
private readonly lifetime;
|
|
88
111
|
private readonly selection;
|
|
@@ -92,19 +115,29 @@ declare class UiWorkspaceService extends Service implements UiWorkspace {
|
|
|
92
115
|
* @param directoryPicker - the directory-picking Remote namespace.
|
|
93
116
|
* @param workspaces - pure Workspace Controller.
|
|
94
117
|
* @param sessions - pure Session Controller.
|
|
118
|
+
* @param view - the browser's viewing-store write set (one instance shared with its registration).
|
|
119
|
+
* @param notify - show one notice through the Workspace notice channel.
|
|
95
120
|
*/
|
|
96
|
-
constructor(ctx: Context, directoryPicker: ClientRemote['directoryPicker'], workspaces: IWorkspaces, sessions: ISessions);
|
|
121
|
+
constructor(ctx: Context, directoryPicker: ClientRemote['directoryPicker'], workspaces: IWorkspaces, sessions: ISessions, view: Pick<WorkspaceViewStoreActions, 'pinSessionOrder'>, notify: (toast: RowToast) => void);
|
|
97
122
|
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>;
|
|
123
|
+
private reuseOrCreateBlank;
|
|
124
|
+
private reuseBlank;
|
|
98
125
|
openSession(target: SessionTarget): void;
|
|
99
126
|
openWorkspace(workspaceId: WorkspaceId, beforeOpen?: (sessionId: SessionId) => void): Promise<void>;
|
|
100
127
|
forkSession(sessionId: SessionId): Promise<void>;
|
|
101
128
|
startSession(workspaceId?: WorkspaceId): void;
|
|
102
|
-
archiveSession(sessionId: SessionId
|
|
129
|
+
archiveSession(sessionId: SessionId, options?: {
|
|
130
|
+
readonly stopActivity?: boolean;
|
|
131
|
+
}): Promise<void>;
|
|
103
132
|
unarchiveSession(sessionId: SessionId): Promise<void>;
|
|
133
|
+
pinSession(sessionId: SessionId): Promise<void>;
|
|
134
|
+
unpinSession(sessionId: SessionId): Promise<void>;
|
|
104
135
|
pickDirectory(): Promise<string | null>;
|
|
105
136
|
listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing>;
|
|
106
137
|
createDirectory(path: string, name: string): Promise<string>;
|
|
107
138
|
private watchNavigation;
|
|
139
|
+
private restoreSelection;
|
|
140
|
+
private initializeDefaultWorkspace;
|
|
108
141
|
/** @returns true when an archived current selection was cleared. */
|
|
109
142
|
private clearArchivedCurrent;
|
|
110
143
|
private clearMain;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The complete account memberships a Pin order write reconciles against,
|
|
3
|
+
* derived from the same Host snapshots the browser orders by, so the
|
|
4
|
+
* UiWorkspace service can complete the write without the browser in the loop.
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
7
|
+
import type { WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
8
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
9
|
+
import { type SessionRowState } from './tree.ts';
|
|
10
|
+
/** What `pinSessionOrder` reconciles a pinned Session's accounts against. */
|
|
11
|
+
export interface PinOrderSource {
|
|
12
|
+
members: Readonly<Record<string, readonly SessionId[]>>;
|
|
13
|
+
summaries: SessionListState['byId'];
|
|
14
|
+
rowState: Pick<SessionRowState, 'pinnedSessionIds' | 'archivedSessionIds'>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Every account's complete membership: each Workspace, Ungrouped, and the flat list.
|
|
18
|
+
* @param workspaces - current Host Workspaces.
|
|
19
|
+
* @param list - current Session list snapshot.
|
|
20
|
+
* @param rowState - registry-global pin and archive sets.
|
|
21
|
+
* @returns the order source for one pin write.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pinOrderSource(workspaces: readonly WorkspaceView[], list: SessionListState, rowState: PinOrderSource['rowState']): PinOrderSource;
|
|
24
|
+
/**
|
|
25
|
+
* The accounts a pinned Session leads: its group (or Ungrouped) and the flat list.
|
|
26
|
+
* @param workspaces - current Host Workspaces.
|
|
27
|
+
* @param sessionId - the Session being pinned.
|
|
28
|
+
* @returns the account keys `pinSessionOrder` fronts.
|
|
29
|
+
*/
|
|
30
|
+
export declare function pinOrderAccounts(workspaces: readonly WorkspaceView[], sessionId: SessionId): readonly string[];
|
|
31
|
+
//# sourceMappingURL=pin-order.d.ts.map
|