@deepseek-ai/dsh-client-ui-workspace 0.1.7-alpha.2 → 0.1.7-rc.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 +72 -5
- package/README.md +12 -10
- package/README.zh.md +12 -10
- package/lib/client.js +608 -329
- package/lib/types/client/WorkspacePicker.d.ts +3 -1
- package/lib/types/client/contract/slots.d.ts +60 -3
- package/lib/types/client/index.d.ts +5 -2
- package/lib/types/client/locales.d.ts +16 -4
- package/lib/types/client/navigation.d.ts +2 -1
- package/lib/types/client/rows/Rows.d.ts +14 -10
- package/lib/types/client/rows/WorkspaceBrowser.d.ts +1 -1
- package/lib/types/client/session-actions/ArchiveSession.d.ts +1 -1
- package/lib/types/client/session-actions/ForkSession.d.ts +1 -1
- package/lib/types/client/session-actions/RenameSession.d.ts +1 -1
- package/lib/types/client/session-actions/RowActionToast.d.ts +6 -5
- package/lib/types/client/shortcuts.d.ts +45 -0
- package/lib/types/client/tree.d.ts +3 -6
- package/package.json +25 -23
package/lib/client.js
CHANGED
|
@@ -20,228 +20,188 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
*/
|
|
21
21
|
const menuOpenStateFactory = (_standard, state) => () => state;
|
|
22
22
|
//#endregion
|
|
23
|
-
//#region lib/types/client/
|
|
23
|
+
//#region lib/types/client/shortcuts.js
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* messages (wire error strings) pass through untranslated by policy.
|
|
25
|
+
* Create the private browser request source shared by commands and controls.
|
|
26
|
+
* @returns observable state and its complete mutation callbacks.
|
|
28
27
|
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
"
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
"archive.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
"toast.archivedUndo": "undo",
|
|
207
|
-
"toast.archivedOr": " or ",
|
|
208
|
-
"toast.archivedFilter": "filter archived sessions",
|
|
209
|
-
"toast.pinFailed": "Pin failed. Try again later.",
|
|
210
|
-
"toast.unpinFailed": "Unpin failed. Try again later.",
|
|
211
|
-
"toast.createFailed": "New session failed: {message}",
|
|
212
|
-
"sessions.count.one": "{n} session",
|
|
213
|
-
"sessions.count.other": "{n} sessions",
|
|
214
|
-
"actions.workspace.aria": "Workspace actions for {name}",
|
|
215
|
-
"actions.session.aria": "Session actions for {name}",
|
|
216
|
-
"actions.archive": "Archive",
|
|
217
|
-
"actions.unarchive": "Unarchive",
|
|
218
|
-
"actions.pin": "Pin",
|
|
219
|
-
"actions.unpin": "Unpin",
|
|
220
|
-
"actions.newSession": "New session",
|
|
221
|
-
"actions.newSession.aria": "New session in {name}",
|
|
222
|
-
"status.running": "Running",
|
|
223
|
-
"status.subagentsRunning.one": "{n} subagent running",
|
|
224
|
-
"status.subagentsRunning.other": "{n} subagents running",
|
|
225
|
-
"status.idle": "Idle",
|
|
226
|
-
"status.waitingApproval": "Waiting for approval",
|
|
227
|
-
"status.planReview": "Plan awaiting review",
|
|
228
|
-
"status.waitingAnswer": "Waiting for answer",
|
|
229
|
-
"status.compact.approval": "Approval",
|
|
230
|
-
"status.compact.planReview": "Plan review",
|
|
231
|
-
"status.compact.answer": "Answer",
|
|
232
|
-
"status.completed": "Completed",
|
|
233
|
-
"schedule.active": "Has active scheduled task",
|
|
234
|
-
"hover.created": "Created {time}",
|
|
235
|
-
"hover.copied": "Copied",
|
|
236
|
-
"date.ymd": "{y}-{m}-{d}",
|
|
237
|
-
"time.now": "now",
|
|
238
|
-
"time.minutes": "{n}min",
|
|
239
|
-
"time.hours": "{n}h",
|
|
240
|
-
"time.days": "{n}d",
|
|
241
|
-
"time.months": "{n}mo",
|
|
242
|
-
"time.years": "{n}y",
|
|
243
|
-
"time.ago": "{t} ago"
|
|
244
|
-
};
|
|
28
|
+
function createWorkspaceShortcutControls() {
|
|
29
|
+
const state = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
30
|
+
searchRequest: 0,
|
|
31
|
+
addRequested: false,
|
|
32
|
+
directoryBusy: false,
|
|
33
|
+
renameTarget: null,
|
|
34
|
+
forkError: null
|
|
35
|
+
});
|
|
36
|
+
let forkErrorSeq = 0;
|
|
37
|
+
return {
|
|
38
|
+
state,
|
|
39
|
+
search: () => {
|
|
40
|
+
state.set({
|
|
41
|
+
...state.getSnapshot(),
|
|
42
|
+
searchRequest: state.getSnapshot().searchRequest + 1
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
add: () => {
|
|
46
|
+
state.set(state.getSnapshot().directoryBusy ? state.getSnapshot() : {
|
|
47
|
+
...state.getSnapshot(),
|
|
48
|
+
addRequested: true
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
closeAdd: () => {
|
|
52
|
+
state.set({
|
|
53
|
+
...state.getSnapshot(),
|
|
54
|
+
addRequested: false
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
directoryBusy: (busy) => {
|
|
58
|
+
state.set({
|
|
59
|
+
...state.getSnapshot(),
|
|
60
|
+
directoryBusy: busy
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
rename: (sessionId, currentTitle) => {
|
|
64
|
+
state.set({
|
|
65
|
+
...state.getSnapshot(),
|
|
66
|
+
renameTarget: {
|
|
67
|
+
sessionId,
|
|
68
|
+
currentTitle
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
closeRename: () => {
|
|
73
|
+
state.set({
|
|
74
|
+
...state.getSnapshot(),
|
|
75
|
+
renameTarget: null
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
forkFailed: (reason) => {
|
|
79
|
+
forkErrorSeq += 1;
|
|
80
|
+
state.set({
|
|
81
|
+
...state.getSnapshot(),
|
|
82
|
+
forkError: {
|
|
83
|
+
reason,
|
|
84
|
+
seq: forkErrorSeq
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
dismissForkError: () => {
|
|
89
|
+
state.set({
|
|
90
|
+
...state.getSnapshot(),
|
|
91
|
+
forkError: null
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Register navigation commands against the existing workspace owner.
|
|
98
|
+
* @param ctx - plugin context with the shortcut, locale, and model services.
|
|
99
|
+
* @param navigation - session creation and forking from the pointer controls' navigation service.
|
|
100
|
+
* @param controls - browser-owned opening requests.
|
|
101
|
+
* @param archiveSession - shared archive action, including running-work confirmation and notices.
|
|
102
|
+
*/
|
|
103
|
+
function installWorkspaceShortcuts(ctx, navigation, controls, archiveSession) {
|
|
104
|
+
const t = ctx.locale.bind("workspace");
|
|
105
|
+
const current = () => Object.values(ctx.sessions.list.getSnapshot().byId).find((row) => (row.retainedBy.mainView ?? 0) > 0);
|
|
106
|
+
const addReason = () => ctx.slots.entries("sidebar.workspaces.directoryFlow").length === 0 ? t("shortcut.noPicker") : controls.state.getSnapshot().directoryBusy ? t("shortcut.directoryBusy") : null;
|
|
107
|
+
const register = (id, label, aliases, code, modifiers, webModifiers, resolve) => {
|
|
108
|
+
ctx.effect(() => ctx.shortcuts.register({
|
|
109
|
+
id,
|
|
110
|
+
label,
|
|
111
|
+
aliases,
|
|
112
|
+
defaults: {
|
|
113
|
+
"desktop:macos": {
|
|
114
|
+
code,
|
|
115
|
+
modifiers
|
|
116
|
+
},
|
|
117
|
+
"desktop:windows": {
|
|
118
|
+
code,
|
|
119
|
+
modifiers
|
|
120
|
+
},
|
|
121
|
+
"desktop:linux": {
|
|
122
|
+
code,
|
|
123
|
+
modifiers
|
|
124
|
+
},
|
|
125
|
+
"web:macos": {
|
|
126
|
+
code,
|
|
127
|
+
modifiers: webModifiers
|
|
128
|
+
},
|
|
129
|
+
"web:windows": {
|
|
130
|
+
code,
|
|
131
|
+
modifiers: webModifiers
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
regions: ["page", "editable"],
|
|
135
|
+
modals: [],
|
|
136
|
+
resolve
|
|
137
|
+
}), `ui-workspace: ${id}`);
|
|
138
|
+
};
|
|
139
|
+
register("session.new", () => t("session.new"), ["new session", "new chat"], "KeyN", ["primary"], ["primary", "alt"], () => ({
|
|
140
|
+
status: "handled",
|
|
141
|
+
run: () => {
|
|
142
|
+
navigation.startSession();
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
register("session.search", () => t("search.sessions.aria"), ["search sessions"], "KeyK", ["primary"], ["primary", "alt"], () => ({
|
|
146
|
+
status: "handled",
|
|
147
|
+
run: controls.search
|
|
148
|
+
}));
|
|
149
|
+
register("workspace.add", () => t("workspace.add"), ["add workspace", "open folder"], "KeyO", ["primary"], ["primary", "alt"], () => {
|
|
150
|
+
const reason = addReason();
|
|
151
|
+
return reason === null ? {
|
|
152
|
+
status: "handled",
|
|
153
|
+
run: controls.add
|
|
154
|
+
} : {
|
|
155
|
+
status: "blocked",
|
|
156
|
+
reason
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
register("session.rename", () => t("rename.session.title"), ["rename session"], "KeyR", ["primary", "alt"], ["primary", "shift"], () => {
|
|
160
|
+
const target = current();
|
|
161
|
+
return target === void 0 ? {
|
|
162
|
+
status: "blocked",
|
|
163
|
+
reason: t("shortcut.noSession")
|
|
164
|
+
} : {
|
|
165
|
+
status: "handled",
|
|
166
|
+
run: () => {
|
|
167
|
+
controls.rename(target.id, target.displayTitle);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
register("session.fork", () => t("menu.fork"), ["fork session"], "KeyF", ["primary", "alt"], ["primary", "shift"], () => {
|
|
172
|
+
const target = current();
|
|
173
|
+
if (target === void 0) return {
|
|
174
|
+
status: "blocked",
|
|
175
|
+
reason: t("shortcut.noSession")
|
|
176
|
+
};
|
|
177
|
+
if (target.blank) return {
|
|
178
|
+
status: "blocked",
|
|
179
|
+
reason: t("shortcut.noCompletedTurn")
|
|
180
|
+
};
|
|
181
|
+
return {
|
|
182
|
+
status: "handled",
|
|
183
|
+
run: () => {
|
|
184
|
+
navigation.forkSession(target.id).catch((error) => {
|
|
185
|
+
const unavailable = error instanceof Error && error.name === "SessionForkError" && error.rpcError.code === "session/fork-unavailable";
|
|
186
|
+
controls.forkFailed(unavailable ? "unavailable" : "failed");
|
|
187
|
+
if (!unavailable) console.warn("session fork rejected:", error);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
register("session.archive", () => t("menu.archiveSession"), ["archive session"], "KeyA", ["primary", "shift"], ["primary", "alt"], () => {
|
|
193
|
+
const target = current();
|
|
194
|
+
return target === void 0 ? {
|
|
195
|
+
status: "blocked",
|
|
196
|
+
reason: t("shortcut.noSession")
|
|
197
|
+
} : {
|
|
198
|
+
status: "handled",
|
|
199
|
+
run: () => {
|
|
200
|
+
archiveSession(target.id);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
}
|
|
245
205
|
//#endregion
|
|
246
206
|
//#region ../../util/values/src/index.ts
|
|
247
207
|
/**
|
|
@@ -429,10 +389,6 @@ window.__ModuleLoader__.load({
|
|
|
429
389
|
function sessionTitle(session) {
|
|
430
390
|
return session.blank ? "" : session.displayTitle;
|
|
431
391
|
}
|
|
432
|
-
/** The list projection alone owns the best-effort active-Schedule indicator. */
|
|
433
|
-
function hasActiveSchedule(session) {
|
|
434
|
-
return (session.projectionValues?.schedule?.length ?? 0) > 0;
|
|
435
|
-
}
|
|
436
392
|
/** Build one group without projecting session lineage into presentation. */
|
|
437
393
|
function buildGroup(key, workspaceId, cwd, createdAt, label, members) {
|
|
438
394
|
return {
|
|
@@ -472,6 +428,7 @@ window.__ModuleLoader__.load({
|
|
|
472
428
|
if (!sessionVisible(summary, current, archived, archivedFilter)) continue;
|
|
473
429
|
members.push(summary);
|
|
474
430
|
}
|
|
431
|
+
if (archivedFilter === "only" && members.length === 0) continue;
|
|
475
432
|
groups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members));
|
|
476
433
|
}
|
|
477
434
|
const stray = list.ids.map((id) => list.byId[id]).filter((s) => s !== void 0 && !accounted.has(s.id) && sessionVisible(s, current, archived, archivedFilter));
|
|
@@ -500,7 +457,6 @@ window.__ModuleLoader__.load({
|
|
|
500
457
|
running: status?.running ?? s.running,
|
|
501
458
|
runningSubagentCount: runningChildCount(list, s.id, statuses),
|
|
502
459
|
completed: status?.completionUnread === true,
|
|
503
|
-
hasActiveSchedule: hasActiveSchedule(s),
|
|
504
460
|
pinned: !archived.has(s.id) && pinned.has(s.id),
|
|
505
461
|
archived: archived.has(s.id),
|
|
506
462
|
updatedAt: s.updatedAt,
|
|
@@ -510,8 +466,9 @@ window.__ModuleLoader__.load({
|
|
|
510
466
|
/**
|
|
511
467
|
* Derive the workspace browser groups with every session as a top-level row.
|
|
512
468
|
*
|
|
513
|
-
* Every group shows
|
|
514
|
-
*
|
|
469
|
+
* Every group shows, except that the archived-only filter drops groups
|
|
470
|
+
* without visible members; sessions populate under expanded groups with
|
|
471
|
+
* pinned rows leading in the selected local order. Blank sessions are
|
|
515
472
|
* excluded except for the selected provisional New Session row; archived
|
|
516
473
|
* sessions keep their slots and appear per the archived filter. Content
|
|
517
474
|
* search lives outside this derivation (see {@link deriveSearchResults}).
|
|
@@ -646,7 +603,6 @@ window.__ModuleLoader__.load({
|
|
|
646
603
|
runningSubagentCount: runningChildCount(list, summary.id, statuses),
|
|
647
604
|
...pendingInteraction === void 0 ? {} : { pendingInteraction },
|
|
648
605
|
completed: status?.completionUnread === true,
|
|
649
|
-
hasActiveSchedule: hasActiveSchedule(summary),
|
|
650
606
|
archived: archived.has(summary.id),
|
|
651
607
|
...match === void 0 ? {} : { snippet: match.snippet }
|
|
652
608
|
};
|
|
@@ -988,13 +944,8 @@ window.__ModuleLoader__.load({
|
|
|
988
944
|
if (sessionId !== void 0 && !navigation.aborted) this.replaceMain(sessionId, navigation, "preserve");
|
|
989
945
|
}
|
|
990
946
|
async initializeDefaultWorkspace(signal) {
|
|
991
|
-
const language = this.ctx.locale.getSnapshot().active.toLowerCase().split("-")[0];
|
|
992
|
-
const title = (language === "zh" ? zh : en)["defaultWorkspace.title"];
|
|
993
947
|
try {
|
|
994
|
-
return await this.workspaces.initializeDefault(
|
|
995
|
-
directoryName: language === "zh" || language === "en" ? title : "default-workspace",
|
|
996
|
-
title
|
|
997
|
-
}, signal);
|
|
948
|
+
return await this.workspaces.initializeDefault(signal);
|
|
998
949
|
} catch (_error) {
|
|
999
950
|
if (!signal.aborted) this.notify({ kind: "defaultWorkspaceFailed" });
|
|
1000
951
|
return;
|
|
@@ -1089,9 +1040,22 @@ window.__ModuleLoader__.load({
|
|
|
1089
1040
|
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
1090
1041
|
return n;
|
|
1091
1042
|
}
|
|
1043
|
+
/**
|
|
1044
|
+
* The text one Workspace is labeled with. A Workspace still carrying the
|
|
1045
|
+
* automatic first-use title reads as the caller's localized default name; every
|
|
1046
|
+
* other title reads verbatim in every language. A title the user typed as
|
|
1047
|
+
* exactly {@link DEFAULT_WORKSPACE_DIRECTORY} is labeled as the default too;
|
|
1048
|
+
* nothing else depends on the distinction.
|
|
1049
|
+
* @param title - stored Workspace title.
|
|
1050
|
+
* @param localizedDefault - the default Workspace name in the active language.
|
|
1051
|
+
* @returns the title to display.
|
|
1052
|
+
*/
|
|
1053
|
+
function workspaceDisplayTitle(title, localizedDefault) {
|
|
1054
|
+
return title === "default-workspace" ? localizedDefault : title;
|
|
1055
|
+
}
|
|
1092
1056
|
//#endregion
|
|
1093
1057
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-workspace/src/client/rows/Rows.module.css.mjs
|
|
1094
|
-
const css$3 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{padding:0 8px;cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);
|
|
1058
|
+
const css$3 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{border-radius:var(--dsw-radius-md);padding:0 8px;cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);align-items:center;gap:6px;padding-inline-start:calc(8px + var(--dsh-workspace-indent,0px));display:flex}.YDXeBa_projectRow:hover,.YDXeBa_sessionRow:hover,.YDXeBa_sessionRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultRow{box-sizing:border-box;border-radius:var(--dsw-radius-lg);cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;flex-direction:column;align-items:stretch;padding:4px 8px;display:flex}.YDXeBa_searchResultRow:hover,.YDXeBa_searchResultRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultHeading{align-items:center;min-width:0;display:flex}.YDXeBa_searchResultTitle{text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:0;margin-left:4px;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_searchResultMeta{align-items:center;gap:6px;min-width:0;margin-left:20px;display:flex}.YDXeBa_searchResultWorkspace,.YDXeBa_searchResultSnippet{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.YDXeBa_searchResultWorkspace{max-width:40%;color:var(--dsw-alias-label-tertiary);flex:none}.YDXeBa_searchResultWorkspace:only-child{max-width:100%}.YDXeBa_searchResultSnippet{min-width:0;color:var(--dsw-alias-label-secondary);flex:1}.YDXeBa_projectRow{box-sizing:border-box;align-items:center;height:34px}.YDXeBa_projectRow .YDXeBa_rowActions{height:20px}.YDXeBa_sessionRow{gap:0;height:32px}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_slot{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.YDXeBa_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.YDXeBa_folderActive{color:var(--dsw-alias-state-business-primary)}.YDXeBa_projectRow .YDXeBa_chevron{display:none}.YDXeBa_projectRow:hover .YDXeBa_chevron{display:inline-flex}.YDXeBa_projectRow:hover .YDXeBa_folder{display:none}.YDXeBa_arrow{transition:transform .15s var(--ds-ease-in-out)}.YDXeBa_arrowOpen{transform:rotate(90deg)}.YDXeBa_projectText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.YDXeBa_title{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_renameInput{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled]{mask-image:linear-gradient(90deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-clipped]{mask-image:linear-gradient(270deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled][data-clipped]{mask-image:linear-gradient(90deg,#0000,#000 12px calc(100% - 12px),#0000)}.YDXeBa_meta{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow:hidden}.YDXeBa_time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:16px}.YDXeBa_pinIndicator{width:16px;height:20px;color:var(--dsw-alias-label-caption);flex:none;justify-content:center;align-items:center;margin-left:6px;display:inline-flex}.YDXeBa_sessionRow.YDXeBa_archived .YDXeBa_title,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultTitle,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultWorkspace,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultSnippet{color:var(--dsw-alias-label-caption)}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:10px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_searchResultRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_searchResultHeading .YDXeBa_rowActions{margin-left:auto}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time,.YDXeBa_sessionRow:hover .YDXeBa_pinIndicator,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_pinIndicator{display:none}@media (hover:hover){.YDXeBa_sessionRow:hover .YDXeBa_title,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_title{text-overflow:clip}}.YDXeBa_projectRow.YDXeBa_menuOpen,.YDXeBa_sessionRow.YDXeBa_menuOpen{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_sessionRow.YDXeBa_dropBefore,.YDXeBa_sessionRow.YDXeBa_dropAfter{position:relative}.YDXeBa_sessionRow.YDXeBa_dropBefore:before,.YDXeBa_sessionRow.YDXeBa_dropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.YDXeBa_sessionRow.YDXeBa_dropBefore:before{top:-7px}.YDXeBa_sessionRow.YDXeBa_dropAfter:after{bottom:-7px}.YDXeBa_hoverContent{flex-direction:column;gap:8px;display:flex}.YDXeBa_hoverTitle{color:#fff;overflow-wrap:break-word;font-size:14px;line-height:20px}.YDXeBa_hoverPath{color:#cfd3d6;word-break:break-all;font-size:12px;line-height:16px}.YDXeBa_hoverTime{color:#cfd3d6;font-size:12px;line-height:16px}.YDXeBa_hoverStatus{color:#adb2b8;align-items:center;gap:8px;font-size:12px;line-height:20px;display:flex}.YDXeBa_hoverArchived svg{flex-shrink:0;margin:0 -4px}.YDXeBa_iconButton{border-radius:var(--dsw-radius-xs);cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.YDXeBa_iconButton:hover{color:var(--dsw-alias-label-primary)}.YDXeBa_chevron{color:var(--dsw-alias-label-caption)}@media (prefers-reduced-motion:reduce){.YDXeBa_arrow{transition:none;animation:none}}";
|
|
1095
1059
|
const tagId$3 = "@deepseek-ai/dsh-client-ui-workspace/Rows.module.css";
|
|
1096
1060
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
1097
1061
|
const tag = document.createElement("style");
|
|
@@ -1108,7 +1072,6 @@ window.__ModuleLoader__.load({
|
|
|
1108
1072
|
"dot": "YDXeBa_dot",
|
|
1109
1073
|
"dropAfter": "YDXeBa_dropAfter",
|
|
1110
1074
|
"dropBefore": "YDXeBa_dropBefore",
|
|
1111
|
-
"flatSessionRowWithoutStatus": "YDXeBa_flatSessionRowWithoutStatus",
|
|
1112
1075
|
"folder": "YDXeBa_folder",
|
|
1113
1076
|
"folderActive": "YDXeBa_folderActive",
|
|
1114
1077
|
"hoverArchived": "YDXeBa_hoverArchived",
|
|
@@ -1125,14 +1088,12 @@ window.__ModuleLoader__.load({
|
|
|
1125
1088
|
"projectText": "YDXeBa_projectText",
|
|
1126
1089
|
"renameInput": "YDXeBa_renameInput",
|
|
1127
1090
|
"rowActions": "YDXeBa_rowActions",
|
|
1128
|
-
"scheduleIndicator": "YDXeBa_scheduleIndicator",
|
|
1129
1091
|
"searchResultHeading": "YDXeBa_searchResultHeading",
|
|
1130
1092
|
"searchResultMeta": "YDXeBa_searchResultMeta",
|
|
1131
1093
|
"searchResultRow": "YDXeBa_searchResultRow",
|
|
1132
1094
|
"searchResultSnippet": "YDXeBa_searchResultSnippet",
|
|
1133
1095
|
"searchResultTitle": "YDXeBa_searchResultTitle",
|
|
1134
1096
|
"searchResultWorkspace": "YDXeBa_searchResultWorkspace",
|
|
1135
|
-
"searchScheduleIndicator": "YDXeBa_searchScheduleIndicator",
|
|
1136
1097
|
"selected": "YDXeBa_selected",
|
|
1137
1098
|
"sessionRow": "YDXeBa_sessionRow",
|
|
1138
1099
|
"slot": "YDXeBa_slot",
|
|
@@ -1303,7 +1264,7 @@ window.__ModuleLoader__.load({
|
|
|
1303
1264
|
* @param props.t - the browser root's locale seat.
|
|
1304
1265
|
* @returns the row element.
|
|
1305
1266
|
*/
|
|
1306
|
-
function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, t }) {
|
|
1267
|
+
function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, newShortcut, t }) {
|
|
1307
1268
|
const row = group;
|
|
1308
1269
|
const label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;
|
|
1309
1270
|
const active = containsCurrentDescendant || group.expanded && group.containsCurrent;
|
|
@@ -1376,12 +1337,14 @@ window.__ModuleLoader__.load({
|
|
|
1376
1337
|
})
|
|
1377
1338
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1378
1339
|
label: t("actions.newSession"),
|
|
1340
|
+
shortcutKeys: newShortcut?.keys,
|
|
1379
1341
|
side: "bottom",
|
|
1380
1342
|
align: "end",
|
|
1381
1343
|
delayMs: 500,
|
|
1382
1344
|
children: (0, react_jsx_runtime.jsx)("button", {
|
|
1383
1345
|
type: "button",
|
|
1384
1346
|
className: Rows_module_css_default.iconButton,
|
|
1347
|
+
"aria-keyshortcuts": newShortcut?.aria,
|
|
1385
1348
|
"aria-label": t("actions.newSession.aria", { name: label }),
|
|
1386
1349
|
onClick: (e) => {
|
|
1387
1350
|
e.stopPropagation();
|
|
@@ -1474,17 +1437,6 @@ window.__ModuleLoader__.load({
|
|
|
1474
1437
|
children: status.label
|
|
1475
1438
|
}, status.label))] });
|
|
1476
1439
|
}
|
|
1477
|
-
/** Non-interactive active-Schedule marker; the enclosing row remains the only action. */
|
|
1478
|
-
function ActiveScheduleIndicator({ t, search = false }) {
|
|
1479
|
-
const label = t("schedule.active");
|
|
1480
|
-
return (0, react_jsx_runtime.jsx)("span", {
|
|
1481
|
-
className: clsx(Rows_module_css_default.scheduleIndicator, search && Rows_module_css_default.searchScheduleIndicator),
|
|
1482
|
-
role: "img",
|
|
1483
|
-
"aria-label": label,
|
|
1484
|
-
title: label,
|
|
1485
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconAlarmClockOutlineRegular, {})
|
|
1486
|
-
});
|
|
1487
|
-
}
|
|
1488
1440
|
/** Non-interactive pinned-row marker; the enclosing row remains the only action. */
|
|
1489
1441
|
function PinnedIndicator({ t }) {
|
|
1490
1442
|
const label = t("row.pinned");
|
|
@@ -1496,8 +1448,12 @@ window.__ModuleLoader__.load({
|
|
|
1496
1448
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPinFillRegular, { size: 14 })
|
|
1497
1449
|
});
|
|
1498
1450
|
}
|
|
1499
|
-
/**
|
|
1500
|
-
|
|
1451
|
+
/**
|
|
1452
|
+
* Hover-card body: full title, relative time, the Session's own scheduled-task
|
|
1453
|
+
* section, and every relevant live status. The task section sits above the
|
|
1454
|
+
* status lines so they stay the card's trailing status line.
|
|
1455
|
+
*/
|
|
1456
|
+
function SessionHoverContent({ node, now, renderSlot, t }) {
|
|
1501
1457
|
const statuses = sessionStatuses(node, t).filter((status) => !(node.archived && (status.state === "done" || status.state === "idle")));
|
|
1502
1458
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1503
1459
|
className: Rows_module_css_default.hoverContent,
|
|
@@ -1510,6 +1466,7 @@ window.__ModuleLoader__.load({
|
|
|
1510
1466
|
className: Rows_module_css_default.hoverTime,
|
|
1511
1467
|
children: hoverTimeLabel(node.updatedAt, now, t)
|
|
1512
1468
|
}),
|
|
1469
|
+
renderSlot("sidebar.session.row.hover", { sessionId: node.id }),
|
|
1513
1470
|
statuses.map((status) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1514
1471
|
className: Rows_module_css_default.hoverStatus,
|
|
1515
1472
|
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: status.state }), (0, react_jsx_runtime.jsx)("span", { children: status.label })]
|
|
@@ -1556,10 +1513,6 @@ window.__ModuleLoader__.load({
|
|
|
1556
1513
|
className: Rows_module_css_default.searchResultTitle,
|
|
1557
1514
|
children: result.title
|
|
1558
1515
|
}),
|
|
1559
|
-
result.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, {
|
|
1560
|
-
t,
|
|
1561
|
-
search: true
|
|
1562
|
-
}),
|
|
1563
1516
|
result.archived && (0, react_jsx_runtime.jsx)("span", {
|
|
1564
1517
|
className: Rows_module_css_default.rowActions,
|
|
1565
1518
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
@@ -1593,22 +1546,26 @@ window.__ModuleLoader__.load({
|
|
|
1593
1546
|
});
|
|
1594
1547
|
}
|
|
1595
1548
|
/**
|
|
1596
|
-
* One top-level
|
|
1597
|
-
*
|
|
1598
|
-
* and the row actions menu.
|
|
1549
|
+
* One top-level 32px session row: leading 16px cell (status dot, or the
|
|
1550
|
+
* leading seat while the row's primary state is idle), title, relative time or
|
|
1551
|
+
* compact pending label, and the row actions menu. A row that owns a state dot
|
|
1552
|
+
* keeps that cell and renders no seat, so an ambient automation mark never
|
|
1553
|
+
* appears beside the row's own state dot. An archived row keeps the cell blank:
|
|
1554
|
+
* neither marker renders there, and its live status stays on the hover card.
|
|
1599
1555
|
* @param props.node - derived session node.
|
|
1600
1556
|
* @param props.currentId - selected session id (row highlight).
|
|
1601
1557
|
* @param props.now - epoch ms for relative-time formatting.
|
|
1602
1558
|
* @param props.onOpen - open a session by id.
|
|
1603
1559
|
* @param props.onRenameRequest - open the rename dialog from a title double-click (id + current title).
|
|
1604
|
-
* @param props.renderSlot -
|
|
1560
|
+
* @param props.renderSlot - child-seat renderer for the row's action lists
|
|
1561
|
+
* (`sidebar.workspaces.session.menu.item` / `sidebar.workspaces.session.row.action`),
|
|
1562
|
+
* its leading decoration, and its hover-card section.
|
|
1605
1563
|
* @param props.onReveal - scroll this row into view after search navigation, then acknowledge it.
|
|
1606
1564
|
* @param props.drag - optional row-drag target wiring; blank rows cannot start a drag.
|
|
1607
|
-
* @param props.flat - omit the empty status slot in the hierarchy-free flat list.
|
|
1608
1565
|
* @param props.t - the browser root's locale seat.
|
|
1609
1566
|
* @returns the session row.
|
|
1610
1567
|
*/
|
|
1611
|
-
function SessionNodeItem({ node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag,
|
|
1568
|
+
function SessionNodeItem({ node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag, t }) {
|
|
1612
1569
|
const row = node;
|
|
1613
1570
|
const title = displayTitle(node, t);
|
|
1614
1571
|
const selected = node.id === currentId;
|
|
@@ -1630,7 +1587,7 @@ window.__ModuleLoader__.load({
|
|
|
1630
1587
|
anchor: (0, react_jsx_runtime.jsxs)("div", {
|
|
1631
1588
|
ref: rowRef,
|
|
1632
1589
|
"data-row-key": `session:${node.id}`,
|
|
1633
|
-
className: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived,
|
|
1590
|
+
className: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),
|
|
1634
1591
|
role: "treeitem",
|
|
1635
1592
|
"aria-selected": selected,
|
|
1636
1593
|
"aria-description": row.archived ? t("toast.archivedNotOpenable") : void 0,
|
|
@@ -1658,9 +1615,9 @@ window.__ModuleLoader__.load({
|
|
|
1658
1615
|
drag.drop(rowHalf(e));
|
|
1659
1616
|
},
|
|
1660
1617
|
children: [
|
|
1661
|
-
(
|
|
1618
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1662
1619
|
className: Rows_module_css_default.slot,
|
|
1663
|
-
children: !row.archived &&
|
|
1620
|
+
children: !row.archived && !row.blank && (showStatus ? (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses }) : renderSlot("sidebar.session.row.leading", { sessionId: node.id }))
|
|
1664
1621
|
}),
|
|
1665
1622
|
(0, react_jsx_runtime.jsx)("span", {
|
|
1666
1623
|
ref: titleRef,
|
|
@@ -1671,7 +1628,6 @@ window.__ModuleLoader__.load({
|
|
|
1671
1628
|
},
|
|
1672
1629
|
children: title
|
|
1673
1630
|
}),
|
|
1674
|
-
row.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, { t }),
|
|
1675
1631
|
!row.blank && (0, react_jsx_runtime.jsx)("span", {
|
|
1676
1632
|
className: Rows_module_css_default.time,
|
|
1677
1633
|
"aria-hidden": primaryStatus.trailingLabel === void 0 ? void 0 : true,
|
|
@@ -1713,6 +1669,7 @@ window.__ModuleLoader__.load({
|
|
|
1713
1669
|
content: (0, react_jsx_runtime.jsx)(SessionHoverContent, {
|
|
1714
1670
|
node,
|
|
1715
1671
|
now,
|
|
1672
|
+
renderSlot,
|
|
1716
1673
|
t
|
|
1717
1674
|
}),
|
|
1718
1675
|
openDelayMs: 800,
|
|
@@ -1922,7 +1879,7 @@ window.__ModuleLoader__.load({
|
|
|
1922
1879
|
* @param props - owner-controlled flow props.
|
|
1923
1880
|
* @returns menu + dialog elements.
|
|
1924
1881
|
*/
|
|
1925
|
-
function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly = false, side = "bottom", selectedId }) {
|
|
1882
|
+
function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly = false, onBusyChange, side = "bottom", selectedId }) {
|
|
1926
1883
|
const workspaceSnapshot = useWorkspaces((state) => state);
|
|
1927
1884
|
const workspaces = workspaceSnapshot.items;
|
|
1928
1885
|
const getAnchorRect = (0, react.useCallback)(() => anchorRef?.current?.getBoundingClientRect() ?? null, [anchorRef]);
|
|
@@ -1931,6 +1888,9 @@ window.__ModuleLoader__.load({
|
|
|
1931
1888
|
const [flowOpen, setFlowOpen] = (0, react.useState)(false);
|
|
1932
1889
|
const [pickingFolder, setPickingFolder] = (0, react.useState)(false);
|
|
1933
1890
|
const flowBusy = flowOpen || pickingFolder;
|
|
1891
|
+
(0, react.useEffect)(() => {
|
|
1892
|
+
onBusyChange?.(flowBusy);
|
|
1893
|
+
}, [flowBusy, onBusyChange]);
|
|
1934
1894
|
const flowAvailable = useDirectoryFlow((occupied) => occupied);
|
|
1935
1895
|
(0, react.useEffect)(() => {
|
|
1936
1896
|
if (flowOpen && !flowAvailable) setFlowOpen(false);
|
|
@@ -1944,7 +1904,7 @@ window.__ModuleLoader__.load({
|
|
|
1944
1904
|
const pinAdd = !addOnly && workspaces.length > 0;
|
|
1945
1905
|
const items = pinAdd ? workspaces.map((workspace) => ({
|
|
1946
1906
|
id: workspace.workspaceId,
|
|
1947
|
-
label: workspace.title,
|
|
1907
|
+
label: workspaceDisplayTitle(workspace.title, t("workspace.defaultName")),
|
|
1948
1908
|
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }),
|
|
1949
1909
|
disabled: flowBusy
|
|
1950
1910
|
})) : addEntries;
|
|
@@ -2070,7 +2030,7 @@ window.__ModuleLoader__.load({
|
|
|
2070
2030
|
}
|
|
2071
2031
|
//#endregion
|
|
2072
2032
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-workspace/src/client/rows/WorkspaceBrowser.module.css.mjs
|
|
2073
|
-
const css = ".bhn1Oq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;min-height:0;padding-right:var(--dsh-session-list-edge-inset);flex-direction:column;flex:1;display:flex}.bhn1Oq_root.bhn1Oq_rail{padding-right:0}.bhn1Oq_iconButton{
|
|
2033
|
+
const css = ".bhn1Oq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;min-height:0;padding-right:var(--dsh-session-list-edge-inset);flex-direction:column;flex:1;display:flex}.bhn1Oq_root.bhn1Oq_rail{padding-right:0}.bhn1Oq_iconButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_iconButton:focus-visible,.bhn1Oq_searchButton:focus-visible,.bhn1Oq_clearButton:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.bhn1Oq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_viewOptionsMenu{min-width:200px}.bhn1Oq_sectionHeader{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;display:flex;overflow:hidden}.bhn1Oq_root:not(.bhn1Oq_rail) .bhn1Oq_sectionHeader{margin-top:2px;margin-right:-4px}.bhn1Oq_sectionLabel{white-space:nowrap;opacity:1;visibility:visible;min-width:0;max-width:45%;transition:max-width .18s var(--ds-ease-in-out), margin-right .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;line-height:20px;overflow:hidden}.bhn1Oq_sectionLabelHidden{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transition-delay:0s,0s,0s,0s,.18s;transform:translate(-4px)}.bhn1Oq_searchSlot{box-sizing:border-box;min-width:0;max-width:28px;transition:max-width .18s var(--ds-ease-in-out), padding-left .18s var(--ds-ease-in-out);flex:1;align-items:center;margin-left:auto;padding-left:0;display:flex}.bhn1Oq_searchSlotExpanded{max-width:100%;padding-left:0}.bhn1Oq_headerActions{opacity:1;visibility:visible;max-width:60px;transition:max-width .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;align-items:center;gap:4px;display:flex;overflow:hidden}.bhn1Oq_headerActionsHidden{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transition-delay:0s,0s,0s,.18s;transform:translate(4px)}.bhn1Oq_search{box-sizing:border-box;border-radius:var(--dsw-radius-sm);cursor:text;width:100%;height:28px;color:var(--dsw-alias-label-secondary);transition:width .18s var(--ds-ease-in-out), padding .18s var(--ds-ease-in-out), border-color .18s var(--ds-ease-in-out), background-color .18s var(--ds-ease-in-out);background:0 0;border:none;flex:none;align-items:center;gap:0;margin:0;padding:0;display:flex;overflow:hidden}.bhn1Oq_searchExpanded{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;margin-inline:-2px;padding:0 4px 0 0}.bhn1Oq_searchButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_searchExpanded .bhn1Oq_searchButton{width:28px;height:30px}.bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_searchExpanded .bhn1Oq_searchButton:hover{background:0 0}.bhn1Oq_searchInput{opacity:0;pointer-events:none;width:0;min-width:0;color:var(--dsw-alias-label-primary);transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;font-size:13px;line-height:18px}.bhn1Oq_searchExpanded .bhn1Oq_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.bhn1Oq_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.bhn1Oq_clearButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_rail .bhn1Oq_sectionHeader{justify-content:flex-start;gap:0;margin-bottom:12px;padding-left:0}.bhn1Oq_rail .bhn1Oq_headerActions{max-width:none}.bhn1Oq_rail .bhn1Oq_iconButton{border-radius:var(--dsw-radius-md);width:36px;height:36px;color:var(--dsw-alias-label-primary)}.bhn1Oq_rail .bhn1Oq_search{border-radius:var(--dsw-radius-md);background:0 0;border-color:#0000;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.bhn1Oq_rail .bhn1Oq_searchButton{border-radius:var(--dsw-radius-md);width:36px;height:36px;color:var(--dsw-alias-label-primary)}.bhn1Oq_rail .bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:visible}.bhn1Oq_rail .bhn1Oq_listArea{margin-left:0;margin-right:0;padding-left:0}.bhn1Oq_treeBody{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.bhn1Oq_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}[data-platform=darwin] .bhn1Oq_fade{display:none}.bhn1Oq_wide{animation:bhn1Oq_wide-in .2s var(--ds-ease-in-out)}@keyframes bhn1Oq_wide-in{0%{opacity:0}}.bhn1Oq_list{min-height:0;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;flex:1;padding-bottom:16px;overflow-y:auto}.bhn1Oq_flatList>*+*,.bhn1Oq_searchTree>[role=treeitem]+[role=treeitem],.bhn1Oq_groupSection>*+*{margin-top:2px}.bhn1Oq_searchStatus{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.bhn1Oq_skeletonRow{box-sizing:border-box;align-items:flex-start;gap:8px;min-height:48px;padding:6px 8px 7px;display:flex}.bhn1Oq_skeletonDot{corner-shape:round;border-radius:50%;flex:none;width:16px;height:16px}.bhn1Oq_skeletonBars{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{background:var(--dsw-alias-bg-skeleton);animation:2s cubic-bezier(.36,0,.64,1) infinite bhn1Oq_search-skeleton}.bhn1Oq_skeletonBar{border-radius:var(--dsw-radius-xs);width:65%;height:16px}.bhn1Oq_skeletonBarWide{width:90%;height:13px}@keyframes bhn1Oq_search-skeleton{0%{opacity:1}40%{opacity:.6}80%,to{opacity:1}}.bhn1Oq_groupSection{position:relative}.bhn1Oq_groupSection+.bhn1Oq_groupSection{margin-top:4px}.bhn1Oq_listTopDropIndicator,.bhn1Oq_workspaceDropBefore:before,.bhn1Oq_workspaceDropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:0}.bhn1Oq_listTopDropIndicator{top:-8px;left:0;right:var(--dsh-session-list-edge-inset)}.bhn1Oq_listTopDropActive>.bhn1Oq_workspaceDropBefore:first-child:before{display:none}.bhn1Oq_workspaceDropBefore:before{top:-8px}.bhn1Oq_workspaceDropAfter:after{bottom:-8px}.bhn1Oq_sessionOverflowButton{border-radius:var(--dsw-radius-sm);width:100%;height:28px;padding:0 12px 0 calc(28px + var(--dsh-workspace-indent,0px));cursor:pointer;text-align:left;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;font-size:12px}.bhn1Oq_groupSection>.bhn1Oq_sessionOverflowButton{margin-top:0}.bhn1Oq_sessionOverflowButton:hover{color:var(--dsw-alias-label-secondary);background:0 0}.bhn1Oq_empty{color:var(--dsw-alias-label-tertiary);padding:16px 12px;font-size:13px}.bhn1Oq_emptyState{color:var(--dsw-alias-label-tertiary);flex-direction:column;align-items:center;gap:8px;margin-top:80px;padding:0 12px;font-size:13px;line-height:20px;display:flex}.bhn1Oq_emptyState>svg{color:var(--dsw-alias-label-caption);margin-bottom:4px}.bhn1Oq_emptyAction{cursor:pointer;color:var(--dsw-alias-link);background:0 0;border:none;padding:0;font-size:13px;line-height:20px}.bhn1Oq_renameInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-lg);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.bhn1Oq_renameInput:disabled{color:var(--dsw-alias-label-dimmed)}.bhn1Oq_renameError{color:var(--dsw-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}.bhn1Oq_deleteAction:not(:disabled){color:var(--dsw-alias-state-error-primary)}.bhn1Oq_deleteStatus{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.bhn1Oq_archiveActivity{color:var(--dsw-alias-label-primary);margin:0 0 8px;padding-left:18px;font-size:13px;line-height:20px}.bhn1Oq_archiveActivity li{overflow-wrap:anywhere}@media (prefers-reduced-motion:reduce){.bhn1Oq_wide,.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{animation:none}.bhn1Oq_search,.bhn1Oq_sectionLabel,.bhn1Oq_searchSlot,.bhn1Oq_searchInput,.bhn1Oq_headerActions{transition:none}}";
|
|
2074
2034
|
const tagId = "@deepseek-ai/dsh-client-ui-workspace/WorkspaceBrowser.module.css";
|
|
2075
2035
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2076
2036
|
const tag = document.createElement("style");
|
|
@@ -2085,6 +2045,8 @@ window.__ModuleLoader__.load({
|
|
|
2085
2045
|
"deleteAction": "bhn1Oq_deleteAction",
|
|
2086
2046
|
"deleteStatus": "bhn1Oq_deleteStatus",
|
|
2087
2047
|
"empty": "bhn1Oq_empty",
|
|
2048
|
+
"emptyAction": "bhn1Oq_emptyAction",
|
|
2049
|
+
"emptyState": "bhn1Oq_emptyState",
|
|
2088
2050
|
"fade": "bhn1Oq_fade",
|
|
2089
2051
|
"flatList": "bhn1Oq_flatList",
|
|
2090
2052
|
"groupSection": "bhn1Oq_groupSection",
|
|
@@ -2257,10 +2219,15 @@ window.__ModuleLoader__.load({
|
|
|
2257
2219
|
id: "filter-by",
|
|
2258
2220
|
text: t("filterBy.label")
|
|
2259
2221
|
},
|
|
2222
|
+
{
|
|
2223
|
+
id: "hide-archived",
|
|
2224
|
+
label: t("viewOptions.hideArchived"),
|
|
2225
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOffOutlineRegular, {})
|
|
2226
|
+
},
|
|
2260
2227
|
{
|
|
2261
2228
|
id: "show-archived",
|
|
2262
2229
|
label: t("viewOptions.showArchived"),
|
|
2263
|
-
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2230
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, {})
|
|
2264
2231
|
},
|
|
2265
2232
|
{
|
|
2266
2233
|
id: "only-archived",
|
|
@@ -2271,14 +2238,18 @@ window.__ModuleLoader__.load({
|
|
|
2271
2238
|
selectedIds: [
|
|
2272
2239
|
groupBy,
|
|
2273
2240
|
orderBy,
|
|
2274
|
-
|
|
2275
|
-
|
|
2241
|
+
{
|
|
2242
|
+
default: "hide-archived",
|
|
2243
|
+
show: "show-archived",
|
|
2244
|
+
only: "only-archived"
|
|
2245
|
+
}[archivedFilter]
|
|
2276
2246
|
],
|
|
2277
2247
|
onSelect: (id) => {
|
|
2278
2248
|
if (id === "workspace" || id === "workspace-tree" || id === "flat") onGroupPick(id);
|
|
2279
2249
|
else if (id === "manual" || id === "updated") onOrderPick(id);
|
|
2280
|
-
else if (id === "
|
|
2281
|
-
else if (id === "
|
|
2250
|
+
else if (id === "hide-archived") onArchivedFilterPick("default");
|
|
2251
|
+
else if (id === "show-archived") onArchivedFilterPick("show");
|
|
2252
|
+
else if (id === "only-archived") onArchivedFilterPick("only");
|
|
2282
2253
|
setOpen(false);
|
|
2283
2254
|
},
|
|
2284
2255
|
align: "end",
|
|
@@ -2320,8 +2291,26 @@ window.__ModuleLoader__.load({
|
|
|
2320
2291
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
2321
2292
|
return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
2322
2293
|
}
|
|
2294
|
+
/** The list-empty placeholder — a glyph over the text; the archived-only view names its filter and offers the way back. */
|
|
2295
|
+
function EmptySessions({ rowState, onLeaveArchivedOnly, t }) {
|
|
2296
|
+
const archivedOnly = rowState.archivedFilter === "only";
|
|
2297
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2298
|
+
className: WorkspaceBrowser_module_css_default.emptyState,
|
|
2299
|
+
"data-row-key": "empty",
|
|
2300
|
+
children: [
|
|
2301
|
+
archivedOnly ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: 24 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, { size: 24 }),
|
|
2302
|
+
(0, react_jsx_runtime.jsx)("div", { children: archivedOnly ? t("empty.noneArchived") : t("empty.none") }),
|
|
2303
|
+
archivedOnly && (0, react_jsx_runtime.jsx)("button", {
|
|
2304
|
+
type: "button",
|
|
2305
|
+
className: WorkspaceBrowser_module_css_default.emptyAction,
|
|
2306
|
+
onClick: onLeaveArchivedOnly,
|
|
2307
|
+
children: t("empty.viewOthers")
|
|
2308
|
+
})
|
|
2309
|
+
]
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2323
2312
|
/** The scrolling session tree; unmounting drops the sessions subscription and local row limits. */
|
|
2324
|
-
function SessionTree({ list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds, rowState, workspaceReady, animationResetKey, usePanelInfo, onRenameRequest, onDeleteRequest, onSessionRenameRequest, renderSlot, insertWorkspaceBefore, nestWorkspaces, groupExpansion, setGroupExpanded, setSessionOrder, home, t, revealSessionId, onSessionRevealed }) {
|
|
2313
|
+
function SessionTree({ list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds, rowState, onLeaveArchivedOnly, workspaceReady, animationResetKey, usePanelInfo, onRenameRequest, onDeleteRequest, onSessionRenameRequest, renderSlot, insertWorkspaceBefore, nestWorkspaces, groupExpansion, setGroupExpanded, setSessionOrder, home, t, revealSessionId, onSessionRevealed, shortcuts }) {
|
|
2325
2314
|
const panelActive = usePanelInfo((info) => info.activePanelId !== null);
|
|
2326
2315
|
const statuses = useSessionStatus((s) => s);
|
|
2327
2316
|
const current = panelActive ? void 0 : Object.values(list.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
|
|
@@ -2430,9 +2419,11 @@ window.__ModuleLoader__.load({
|
|
|
2430
2419
|
});
|
|
2431
2420
|
};
|
|
2432
2421
|
const childrenByParent = (0, react.useMemo)(() => {
|
|
2422
|
+
const rendered = new Set(groups.map((group) => group.key));
|
|
2433
2423
|
const children = /* @__PURE__ */ new Map();
|
|
2434
2424
|
for (const group of groups) {
|
|
2435
|
-
|
|
2425
|
+
let parent = parents.get(group.key);
|
|
2426
|
+
while (parent !== void 0 && !rendered.has(parent)) parent = parents.get(parent);
|
|
2436
2427
|
const siblings = children.get(parent);
|
|
2437
2428
|
if (siblings === void 0) children.set(parent, [group]);
|
|
2438
2429
|
else siblings.push(group);
|
|
@@ -2513,6 +2504,7 @@ window.__ModuleLoader__.load({
|
|
|
2513
2504
|
},
|
|
2514
2505
|
children: [
|
|
2515
2506
|
(0, react_jsx_runtime.jsx)(ProjectRowItem, {
|
|
2507
|
+
newShortcut: shortcuts.find((row) => row.id === "session.new"),
|
|
2516
2508
|
group,
|
|
2517
2509
|
containsCurrentDescendant: currentAncestors.has(group.key),
|
|
2518
2510
|
home,
|
|
@@ -2630,10 +2622,10 @@ window.__ModuleLoader__.load({
|
|
|
2630
2622
|
rowKeys,
|
|
2631
2623
|
ready: list.phase === "ready" && workspaceReady && !nativeDragActive,
|
|
2632
2624
|
resetKey: JSON.stringify([animationResetKey, sessionLimits]),
|
|
2633
|
-
children: [groups.length === 0 && (0, react_jsx_runtime.jsx)(
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2625
|
+
children: [groups.length === 0 && (0, react_jsx_runtime.jsx)(EmptySessions, {
|
|
2626
|
+
rowState,
|
|
2627
|
+
onLeaveArchivedOnly,
|
|
2628
|
+
t
|
|
2637
2629
|
}), groupRows]
|
|
2638
2630
|
}),
|
|
2639
2631
|
(0, react_jsx_runtime.jsx)("span", { className: WorkspaceBrowser_module_css_default.fade })
|
|
@@ -2641,7 +2633,7 @@ window.__ModuleLoader__.load({
|
|
|
2641
2633
|
});
|
|
2642
2634
|
}
|
|
2643
2635
|
/** The flat "In one list" body: every session is one draggable top-level row. */
|
|
2644
|
-
function FlatList({ list, sessionIds, rowState, useSessionStatus, open, onSessionRenameRequest,
|
|
2636
|
+
function FlatList({ list, sessionIds, rowState, onLeaveArchivedOnly, useSessionStatus, open, onSessionRenameRequest, usePanelInfo, setSessionOrder, workspaceReady, animationResetKey, revealSessionId, onSessionRevealed, renderSlot, t }) {
|
|
2645
2637
|
const panelActive = usePanelInfo((info) => info.activePanelId !== null);
|
|
2646
2638
|
const statuses = useSessionStatus((s) => s);
|
|
2647
2639
|
const rows = (0, react.useMemo)(() => deriveFlat(list, sessionIds, rowState, statuses), [
|
|
@@ -2670,10 +2662,10 @@ window.__ModuleLoader__.load({
|
|
|
2670
2662
|
rowKeys: rows.length === 0 ? ["empty"] : rows.map((row) => `session:${row.id}`),
|
|
2671
2663
|
ready: list.phase === "ready" && workspaceReady && drag === null,
|
|
2672
2664
|
resetKey: animationResetKey,
|
|
2673
|
-
children: [rows.length === 0 && (0, react_jsx_runtime.jsx)(
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2665
|
+
children: [rows.length === 0 && (0, react_jsx_runtime.jsx)(EmptySessions, {
|
|
2666
|
+
rowState,
|
|
2667
|
+
onLeaveArchivedOnly,
|
|
2668
|
+
t
|
|
2677
2669
|
}), rows.map((node) => {
|
|
2678
2670
|
const active = drag !== null && drag.pinned === node.pinned;
|
|
2679
2671
|
const normalizeHalf = (half) => node.blank ? "after" : half;
|
|
@@ -2687,7 +2679,6 @@ window.__ModuleLoader__.load({
|
|
|
2687
2679
|
onReveal: node.id === revealSessionId ? () => {
|
|
2688
2680
|
onSessionRevealed(node.id);
|
|
2689
2681
|
} : void 0,
|
|
2690
|
-
flat: true,
|
|
2691
2682
|
drag: {
|
|
2692
2683
|
start: () => {
|
|
2693
2684
|
dropCommitted.current = false;
|
|
@@ -2796,10 +2787,19 @@ window.__ModuleLoader__.load({
|
|
|
2796
2787
|
* @param props - composed slot props (shell owner share + store + injected actions).
|
|
2797
2788
|
* @returns the region element tree.
|
|
2798
2789
|
*/
|
|
2799
|
-
function WorkspaceBrowser({ wide, usePanelInfo, expandSidebar, useSessions, useSessionStatus, useWorkspaces, useStore, actions, startSession, open, requestSessionRename, notifyArchivedNotOpenable, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, unarchiveSession, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostInfo, renderSlot, t }) {
|
|
2790
|
+
function WorkspaceBrowser({ wide, usePanelInfo, expandSidebar, useSessions, useSessionStatus, useWorkspaces, useStore, actions, startSession, open, requestSessionRename, notifyArchivedNotOpenable, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, unarchiveSession, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostInfo, useShortcuts, useWorkspaceShortcuts, requestSearch, requestAddWorkspace, closeAddWorkspace, setDirectoryBusy, dismissForkError, renderSlot, t }) {
|
|
2800
2791
|
const home = useHostInfo((info) => info.home);
|
|
2792
|
+
const shortcuts = useShortcuts((rows) => rows);
|
|
2793
|
+
const searchShortcut = shortcuts.find((row) => row.id === "session.search");
|
|
2794
|
+
const addShortcut = shortcuts.find((row) => row.id === "workspace.add");
|
|
2795
|
+
const shortcutState = useWorkspaceShortcuts((state) => state);
|
|
2801
2796
|
const list = useSessions((state) => state);
|
|
2802
|
-
const
|
|
2797
|
+
const storedWorkspaces = useWorkspaces((state) => state.items);
|
|
2798
|
+
const defaultWorkspaceName = t("workspace.defaultName");
|
|
2799
|
+
const workspaces = (0, react.useMemo)(() => storedWorkspaces.map((workspace) => ({
|
|
2800
|
+
...workspace,
|
|
2801
|
+
title: workspaceDisplayTitle(workspace.title, defaultWorkspaceName)
|
|
2802
|
+
})), [storedWorkspaces, defaultWorkspaceName]);
|
|
2803
2803
|
const workspacePhase = useWorkspaces((state) => state.phase);
|
|
2804
2804
|
const workspaceStreamState = useWorkspaces((state) => state.state);
|
|
2805
2805
|
const archivedSessionIds = useWorkspaces((state) => state.archivedSessionIds);
|
|
@@ -2817,6 +2817,9 @@ window.__ModuleLoader__.load({
|
|
|
2817
2817
|
}
|
|
2818
2818
|
open(sessionId);
|
|
2819
2819
|
};
|
|
2820
|
+
const leaveArchivedOnly = () => {
|
|
2821
|
+
actions.setArchivedFilter("default");
|
|
2822
|
+
};
|
|
2820
2823
|
const workspaceReady = workspacePhase === "ready" && workspaceStreamState !== "loading";
|
|
2821
2824
|
const mainSessionId = Object.values(list.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
|
|
2822
2825
|
const currentBlank = mainSessionId !== void 0 && list.byId[mainSessionId]?.blank === true ? mainSessionId : void 0;
|
|
@@ -2936,7 +2939,7 @@ window.__ModuleLoader__.load({
|
|
|
2936
2939
|
});
|
|
2937
2940
|
const searchRoot = (0, react.useRef)(null);
|
|
2938
2941
|
const searchInput = (0, react.useRef)(null);
|
|
2939
|
-
const
|
|
2942
|
+
const wsPickerOpen = shortcutState.addRequested;
|
|
2940
2943
|
const wsPlusRef = (0, react.useRef)(null);
|
|
2941
2944
|
const composingRef = (0, react.useRef)(false);
|
|
2942
2945
|
const openSearchResult = (sessionId) => {
|
|
@@ -2967,6 +2970,15 @@ window.__ModuleLoader__.load({
|
|
|
2967
2970
|
};
|
|
2968
2971
|
}
|
|
2969
2972
|
}, [wide, searchOnExpand]);
|
|
2973
|
+
(0, react.useEffect)(() => {
|
|
2974
|
+
if (shortcutState.searchRequest === 0) return;
|
|
2975
|
+
closeAddWorkspace();
|
|
2976
|
+
setSearchExpanded(true);
|
|
2977
|
+
if (!wide) {
|
|
2978
|
+
setSearchOnExpand(true);
|
|
2979
|
+
expandSidebar();
|
|
2980
|
+
} else searchInput.current?.focus({ preventScroll: true });
|
|
2981
|
+
}, [shortcutState.searchRequest]);
|
|
2970
2982
|
(0, react.useEffect)(() => {
|
|
2971
2983
|
if (!wide || !searchExpanded || searchOnExpand) return;
|
|
2972
2984
|
searchInput.current?.focus({ preventScroll: true });
|
|
@@ -3039,8 +3051,8 @@ window.__ModuleLoader__.load({
|
|
|
3039
3051
|
const [renaming, setRenaming] = (0, react.useState)(false);
|
|
3040
3052
|
const [renameError, setRenameError] = (0, react.useState)(null);
|
|
3041
3053
|
const renameTrimmed = renameDraft.trim();
|
|
3042
|
-
const renameDuplicate = renameTarget !== null && renameTrimmed !== "" &&
|
|
3043
|
-
const renameBlocked = renaming || renameTrimmed === "" || renameTarget === null || renameTrimmed === renameTarget.
|
|
3054
|
+
const renameDuplicate = renameTarget !== null && renameTrimmed !== "" && workspaces.some((w) => w.workspaceId !== renameTarget.workspaceId && w.title === renameTrimmed);
|
|
3055
|
+
const renameBlocked = renaming || renameTrimmed === "" || renameTarget === null || renameTrimmed === renameTarget.storedTitle || renameDuplicate;
|
|
3044
3056
|
const closeRename = () => {
|
|
3045
3057
|
if (renaming) return;
|
|
3046
3058
|
setRenameTarget(null);
|
|
@@ -3107,13 +3119,14 @@ window.__ModuleLoader__.load({
|
|
|
3107
3119
|
ref: searchRoot,
|
|
3108
3120
|
className: clsx(WorkspaceBrowser_module_css_default.search, searchExpanded && WorkspaceBrowser_module_css_default.searchExpanded),
|
|
3109
3121
|
onClick: () => {
|
|
3110
|
-
|
|
3122
|
+
closeAddWorkspace();
|
|
3111
3123
|
setSearchExpanded(true);
|
|
3112
3124
|
searchInput.current?.focus();
|
|
3113
3125
|
},
|
|
3114
3126
|
children: [
|
|
3115
3127
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
3116
3128
|
label: t("search"),
|
|
3129
|
+
shortcutKeys: searchShortcut?.keys,
|
|
3117
3130
|
side: "bottom",
|
|
3118
3131
|
delayMs: 500,
|
|
3119
3132
|
disabled: searchExpanded,
|
|
@@ -3121,10 +3134,10 @@ window.__ModuleLoader__.load({
|
|
|
3121
3134
|
type: "button",
|
|
3122
3135
|
className: WorkspaceBrowser_module_css_default.searchButton,
|
|
3123
3136
|
"aria-label": t("search.sessions.aria"),
|
|
3137
|
+
"aria-keyshortcuts": searchShortcut?.aria,
|
|
3124
3138
|
"aria-expanded": searchExpanded,
|
|
3125
3139
|
onClick: () => {
|
|
3126
|
-
|
|
3127
|
-
setSearchExpanded(true);
|
|
3140
|
+
requestSearch();
|
|
3128
3141
|
},
|
|
3129
3142
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: searchExpanded ? 11 : 14 })
|
|
3130
3143
|
})
|
|
@@ -3174,6 +3187,7 @@ window.__ModuleLoader__.load({
|
|
|
3174
3187
|
t
|
|
3175
3188
|
}), directoryFlowAvailable && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
3176
3189
|
label: t("workspace.add"),
|
|
3190
|
+
shortcutKeys: addShortcut?.keys,
|
|
3177
3191
|
side: "bottom",
|
|
3178
3192
|
delayMs: 500,
|
|
3179
3193
|
children: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -3181,8 +3195,9 @@ window.__ModuleLoader__.load({
|
|
|
3181
3195
|
type: "button",
|
|
3182
3196
|
className: WorkspaceBrowser_module_css_default.iconButton,
|
|
3183
3197
|
"aria-label": t("workspace.add"),
|
|
3198
|
+
"aria-keyshortcuts": addShortcut?.aria,
|
|
3184
3199
|
onClick: () => {
|
|
3185
|
-
|
|
3200
|
+
requestAddWorkspace();
|
|
3186
3201
|
},
|
|
3187
3202
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconProjectAddOutlineRegular, { size: wide ? 16 : 18 })
|
|
3188
3203
|
})
|
|
@@ -3197,13 +3212,14 @@ window.__ModuleLoader__.load({
|
|
|
3197
3212
|
useDirectoryFlow,
|
|
3198
3213
|
renderDirectoryFlow: (owner) => renderSlot("sidebar.workspaces.directoryFlow", owner),
|
|
3199
3214
|
addOnly: true,
|
|
3215
|
+
onBusyChange: setDirectoryBusy,
|
|
3200
3216
|
side: "right",
|
|
3201
3217
|
onPick: (workspaceId) => {
|
|
3202
|
-
|
|
3218
|
+
closeAddWorkspace();
|
|
3203
3219
|
startSession(workspaceId);
|
|
3204
3220
|
},
|
|
3205
3221
|
onClose: () => {
|
|
3206
|
-
|
|
3222
|
+
closeAddWorkspace();
|
|
3207
3223
|
}
|
|
3208
3224
|
})
|
|
3209
3225
|
]
|
|
@@ -3212,14 +3228,14 @@ window.__ModuleLoader__.load({
|
|
|
3212
3228
|
className: WorkspaceBrowser_module_css_default.search,
|
|
3213
3229
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
3214
3230
|
label: t("search"),
|
|
3231
|
+
shortcutKeys: searchShortcut?.keys,
|
|
3215
3232
|
children: (0, react_jsx_runtime.jsx)("button", {
|
|
3216
3233
|
type: "button",
|
|
3217
3234
|
className: WorkspaceBrowser_module_css_default.searchButton,
|
|
3218
3235
|
"aria-label": t("search.sessions.aria"),
|
|
3236
|
+
"aria-keyshortcuts": searchShortcut?.aria,
|
|
3219
3237
|
onClick: () => {
|
|
3220
|
-
|
|
3221
|
-
setSearchOnExpand(true);
|
|
3222
|
-
expandSidebar();
|
|
3238
|
+
requestSearch();
|
|
3223
3239
|
},
|
|
3224
3240
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: 18 })
|
|
3225
3241
|
})
|
|
@@ -3245,6 +3261,7 @@ window.__ModuleLoader__.load({
|
|
|
3245
3261
|
list,
|
|
3246
3262
|
sessionIds: orderedFlatSessionIds,
|
|
3247
3263
|
rowState,
|
|
3264
|
+
onLeaveArchivedOnly: leaveArchivedOnly,
|
|
3248
3265
|
workspaceReady,
|
|
3249
3266
|
animationResetKey: `${groupBy}/${orderBy}/${archivedFilter}`,
|
|
3250
3267
|
useSessionStatus,
|
|
@@ -3258,6 +3275,7 @@ window.__ModuleLoader__.load({
|
|
|
3258
3275
|
}) : (0, react_jsx_runtime.jsx)(SessionTree, {
|
|
3259
3276
|
usePanelInfo,
|
|
3260
3277
|
list,
|
|
3278
|
+
shortcuts,
|
|
3261
3279
|
useSessionStatus,
|
|
3262
3280
|
onSessionRenameRequest: requestSessionRename,
|
|
3263
3281
|
renderSlot,
|
|
@@ -3270,6 +3288,7 @@ window.__ModuleLoader__.load({
|
|
|
3270
3288
|
setGroupExpanded: actions.setGroupExpanded,
|
|
3271
3289
|
setSessionOrder: saveSessionOrder,
|
|
3272
3290
|
rowState,
|
|
3291
|
+
onLeaveArchivedOnly: leaveArchivedOnly,
|
|
3273
3292
|
startSession,
|
|
3274
3293
|
open: guardedOpen,
|
|
3275
3294
|
insertWorkspaceBefore,
|
|
@@ -3277,12 +3296,12 @@ window.__ModuleLoader__.load({
|
|
|
3277
3296
|
onSessionRevealed: acknowledgeSessionReveal,
|
|
3278
3297
|
home,
|
|
3279
3298
|
t,
|
|
3280
|
-
onRenameRequest: (workspaceId,
|
|
3299
|
+
onRenameRequest: (workspaceId, displayTitle) => {
|
|
3281
3300
|
setRenameTarget({
|
|
3282
3301
|
workspaceId,
|
|
3283
|
-
|
|
3302
|
+
storedTitle: storedWorkspaces.find((w) => w.workspaceId === workspaceId)?.title ?? displayTitle
|
|
3284
3303
|
});
|
|
3285
|
-
setRenameDraft(
|
|
3304
|
+
setRenameDraft(displayTitle);
|
|
3286
3305
|
setRenameError(null);
|
|
3287
3306
|
},
|
|
3288
3307
|
onDeleteRequest: (workspaceId, title) => {
|
|
@@ -3315,7 +3334,7 @@ window.__ModuleLoader__.load({
|
|
|
3315
3334
|
className: WorkspaceBrowser_module_css_default.renameInput,
|
|
3316
3335
|
value: renameDraft,
|
|
3317
3336
|
"aria-label": t("field.workspaceName"),
|
|
3318
|
-
|
|
3337
|
+
"data-modal-autofocus": true,
|
|
3319
3338
|
disabled: renaming,
|
|
3320
3339
|
onFocus: (e) => {
|
|
3321
3340
|
e.target.select();
|
|
@@ -3376,7 +3395,11 @@ window.__ModuleLoader__.load({
|
|
|
3376
3395
|
role: "alert",
|
|
3377
3396
|
children: deleteError
|
|
3378
3397
|
})]
|
|
3379
|
-
})
|
|
3398
|
+
}),
|
|
3399
|
+
shortcutState.forkError !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
3400
|
+
text: t(shortcutState.forkError.reason === "unavailable" ? "shortcut.noCompletedTurn" : "shortcut.forkFailed"),
|
|
3401
|
+
onDone: dismissForkError
|
|
3402
|
+
}, shortcutState.forkError.seq)
|
|
3380
3403
|
]
|
|
3381
3404
|
});
|
|
3382
3405
|
}
|
|
@@ -3395,10 +3418,12 @@ window.__ModuleLoader__.load({
|
|
|
3395
3418
|
* @param props - owner share, the archive share, and the menu open state.
|
|
3396
3419
|
* @returns the row.
|
|
3397
3420
|
*/
|
|
3398
|
-
function ArchiveSessionMenuItem({ sessionId, useArchived, useMenuOpenState, archiveSession, unarchiveSession, t }) {
|
|
3421
|
+
function ArchiveSessionMenuItem({ sessionId, useArchived, useMenuOpenState, useShortcuts, archiveSession, unarchiveSession, t }) {
|
|
3399
3422
|
const [, setMenuOpen] = useMenuOpenState();
|
|
3423
|
+
const shortcut = useShortcuts((rows) => rows.find((row) => row.id === "session.archive"));
|
|
3400
3424
|
const archived = useArchived((set) => set.has(sessionId));
|
|
3401
3425
|
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
|
|
3426
|
+
shortcut: archived ? void 0 : shortcut,
|
|
3402
3427
|
icon: archived ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUnarchiveOutlineRegular, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: 14 }),
|
|
3403
3428
|
onSelect: () => {
|
|
3404
3429
|
setMenuOpen(false);
|
|
@@ -3568,9 +3593,10 @@ window.__ModuleLoader__.load({
|
|
|
3568
3593
|
* @param props - owner share, menu open state, and the fork share.
|
|
3569
3594
|
* @returns the row.
|
|
3570
3595
|
*/
|
|
3571
|
-
function ForkSessionMenuItem({ sessionId, useMenuOpenState, forkSession, t }) {
|
|
3596
|
+
function ForkSessionMenuItem({ sessionId, useMenuOpenState, useShortcuts, forkSession, t }) {
|
|
3572
3597
|
const [, setMenuOpen] = useMenuOpenState();
|
|
3573
3598
|
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
|
|
3599
|
+
shortcut: useShortcuts((rows) => rows.find((row) => row.id === "session.fork")),
|
|
3574
3600
|
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, {}),
|
|
3575
3601
|
onSelect: () => {
|
|
3576
3602
|
setMenuOpen(false);
|
|
@@ -3653,9 +3679,10 @@ window.__ModuleLoader__.load({
|
|
|
3653
3679
|
* @param props - owner share, menu open state, and the rename share.
|
|
3654
3680
|
* @returns the row.
|
|
3655
3681
|
*/
|
|
3656
|
-
function RenameSessionMenuItem({ sessionId, displayTitle, useMenuOpenState, requestSessionRename, t }) {
|
|
3682
|
+
function RenameSessionMenuItem({ sessionId, displayTitle, useMenuOpenState, useShortcuts, requestSessionRename, t }) {
|
|
3657
3683
|
const [, setMenuOpen] = useMenuOpenState();
|
|
3658
3684
|
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
|
|
3685
|
+
shortcut: useShortcuts((rows) => rows.find((row) => row.id === "session.rename")),
|
|
3659
3686
|
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, {}),
|
|
3660
3687
|
onSelect: () => {
|
|
3661
3688
|
setMenuOpen(false);
|
|
@@ -3727,7 +3754,7 @@ window.__ModuleLoader__.load({
|
|
|
3727
3754
|
className: WorkspaceBrowser_module_css_default.renameInput,
|
|
3728
3755
|
value: draft,
|
|
3729
3756
|
"aria-label": t("field.sessionName"),
|
|
3730
|
-
|
|
3757
|
+
"data-modal-autofocus": true,
|
|
3731
3758
|
disabled: renaming,
|
|
3732
3759
|
onFocus: (e) => {
|
|
3733
3760
|
e.target.select();
|
|
@@ -3769,14 +3796,16 @@ window.__ModuleLoader__.load({
|
|
|
3769
3796
|
const LONG_TOAST_HOLD_MS = 6e3;
|
|
3770
3797
|
/**
|
|
3771
3798
|
* Render the current notice: the archived and stopped-and-archived notices
|
|
3772
|
-
* with their undo
|
|
3773
|
-
*
|
|
3774
|
-
*
|
|
3775
|
-
*
|
|
3799
|
+
* with their undo action — plus the show-archived action while archived rows
|
|
3800
|
+
* are hidden — on a 6 s hold, a refused Session creation with the Host's
|
|
3801
|
+
* reason on the same hold, or a plain warning for a failed pin, an archived
|
|
3802
|
+
* row that was clicked, or default Workspace creation.
|
|
3803
|
+
* @param props - the notice hook, the shared viewing store, the notice dismissal, the two archived-notice actions, and the locale seat.
|
|
3776
3804
|
* @returns the notice on display, or null.
|
|
3777
3805
|
*/
|
|
3778
|
-
function RowActionToast({ useToast, dismissToast, undoArchive, showArchived, t }) {
|
|
3806
|
+
function RowActionToast({ useToast, useStore, dismissToast, undoArchive, showArchived, t }) {
|
|
3779
3807
|
const toast = useToast((current) => current);
|
|
3808
|
+
const archivedRowsVisible = useStore((state) => (state.archivedFilter ?? "default") !== "default");
|
|
3780
3809
|
if (toast === null) return null;
|
|
3781
3810
|
if (toast.kind === "archived" || toast.kind === "stoppedAndArchived") {
|
|
3782
3811
|
const { sessionId } = toast;
|
|
@@ -3790,14 +3819,14 @@ window.__ModuleLoader__.load({
|
|
|
3790
3819
|
dismissToast();
|
|
3791
3820
|
undoArchive(sessionId);
|
|
3792
3821
|
}
|
|
3793
|
-
}, {
|
|
3822
|
+
}, ...archivedRowsVisible ? [] : [{
|
|
3794
3823
|
prefix: t("toast.archivedOr"),
|
|
3795
3824
|
label: t("toast.archivedFilter"),
|
|
3796
3825
|
onClick: () => {
|
|
3797
3826
|
dismissToast();
|
|
3798
3827
|
showArchived();
|
|
3799
3828
|
}
|
|
3800
|
-
}],
|
|
3829
|
+
}]],
|
|
3801
3830
|
onDone: dismissToast
|
|
3802
3831
|
}, `toast-${String(toast.seq)}`);
|
|
3803
3832
|
}
|
|
@@ -3825,6 +3854,241 @@ window.__ModuleLoader__.load({
|
|
|
3825
3854
|
}
|
|
3826
3855
|
}
|
|
3827
3856
|
//#endregion
|
|
3857
|
+
//#region lib/types/client/locales.js
|
|
3858
|
+
/**
|
|
3859
|
+
* `workspace` namespace dictionaries: the browsing region (section header,
|
|
3860
|
+
* search, tree rows, dialogs) and the pick/add flow. Runtime failure
|
|
3861
|
+
* messages (wire error strings) pass through untranslated by policy.
|
|
3862
|
+
*/
|
|
3863
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
3864
|
+
const zh = {
|
|
3865
|
+
"defaultWorkspace.failed": "无法创建默认工作区,请通过“选择工作区”选择文件夹",
|
|
3866
|
+
"group.ungrouped": "未分组",
|
|
3867
|
+
"session.new": "新会话",
|
|
3868
|
+
"shortcut.noSession": "请先选择一个会话",
|
|
3869
|
+
"shortcut.noPicker": "目录选择器不可用",
|
|
3870
|
+
"shortcut.directoryBusy": "正在选择或添加工作区",
|
|
3871
|
+
"shortcut.noCompletedTurn": "当前会话没有已结束的轮次",
|
|
3872
|
+
"shortcut.forkFailed": "无法分叉会话,请重试",
|
|
3873
|
+
"section.workspaces": "工作区",
|
|
3874
|
+
"section.sessions": "会话",
|
|
3875
|
+
"viewOptions.label": "视图选项",
|
|
3876
|
+
"groupBy.label": "分组方式",
|
|
3877
|
+
"groupBy.workspace": "按工作区",
|
|
3878
|
+
"groupBy.workspaceTree": "按工作区树",
|
|
3879
|
+
"groupBy.flat": "单列表",
|
|
3880
|
+
"orderBy.label": "排序方式",
|
|
3881
|
+
"orderBy.manual": "手动排序",
|
|
3882
|
+
"orderBy.updated": "最近更新",
|
|
3883
|
+
"filterBy.label": "筛选会话",
|
|
3884
|
+
"viewOptions.hideArchived": "隐藏已归档",
|
|
3885
|
+
"viewOptions.showArchived": "全部对话(显示已归档)",
|
|
3886
|
+
"viewOptions.onlyArchived": "仅显示已归档",
|
|
3887
|
+
"sessions.expand": "展开其余 {n} 个会话",
|
|
3888
|
+
"sessions.collapse": "收起",
|
|
3889
|
+
"empty.none": "暂无会话",
|
|
3890
|
+
"empty.noneArchived": "暂无已归档会话",
|
|
3891
|
+
"empty.viewOthers": "查看其他会话",
|
|
3892
|
+
"empty.noMatches": "无匹配结果",
|
|
3893
|
+
"workspace.add": "添加工作区",
|
|
3894
|
+
"search.sessions.aria": "搜索会话",
|
|
3895
|
+
"search.placeholder": "搜索会话名称",
|
|
3896
|
+
"search.clear": "清除搜索",
|
|
3897
|
+
"search.results.aria": "搜索结果",
|
|
3898
|
+
"search.pending": "正在搜索会话历史…",
|
|
3899
|
+
"search.noMatches": "无匹配会话",
|
|
3900
|
+
"search.hasMore": "仅显示前 {n} 条结果,请缩小搜索范围。",
|
|
3901
|
+
"menu.addWorkspace": "添加工作区…",
|
|
3902
|
+
"picker.loading": "正在加载工作区…",
|
|
3903
|
+
"conflict.named": "已存在名为“{name}”的工作区。",
|
|
3904
|
+
"folderError.title": "无法打开文件夹",
|
|
3905
|
+
"folderError.retry": "重新选择",
|
|
3906
|
+
"rename": "重命名",
|
|
3907
|
+
"rename.workspace.title": "重命名工作区",
|
|
3908
|
+
"rename.session.title": "重命名会话",
|
|
3909
|
+
"field.workspaceName": "工作区名称",
|
|
3910
|
+
"field.sessionName": "会话名称",
|
|
3911
|
+
"delete.workspace": "删除工作区",
|
|
3912
|
+
"delete.desc": "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",
|
|
3913
|
+
"delete.pending": "正在删除工作区…",
|
|
3914
|
+
"menu.fork": "分叉会话",
|
|
3915
|
+
"menu.archiveSession": "归档会话",
|
|
3916
|
+
"menu.unarchiveSession": "取消归档",
|
|
3917
|
+
"menu.pinSession": "置顶会话",
|
|
3918
|
+
"menu.unpinSession": "取消置顶",
|
|
3919
|
+
"row.archived": "已归档",
|
|
3920
|
+
"row.pinned": "已置顶",
|
|
3921
|
+
"toast.archivedNotOpenable": "已归档对话暂时无法查看,请取消归档后查看",
|
|
3922
|
+
"toast.archived": "会话已归档,可",
|
|
3923
|
+
"toast.stoppedAndArchived": "已停止并归档,可",
|
|
3924
|
+
"archive.confirm.title": "停止并归档此会话?",
|
|
3925
|
+
"archive.confirm.desc": "“{title}”仍有正在进行的工作。归档会先停止这些工作;之后可在侧栏筛选“全部对话(显示已归档)”中恢复会话,被停止的工作不会自动继续。",
|
|
3926
|
+
"archive.confirm.activity": "将被停止的工作",
|
|
3927
|
+
"archive.confirm.turn": "进行中的回合",
|
|
3928
|
+
"archive.confirm.subagents.one": "{n} 个运行中的子智能体:{names}",
|
|
3929
|
+
"archive.confirm.subagents.other": "{n} 个运行中的子智能体:{names}",
|
|
3930
|
+
"archive.confirm.jobs.one": "{n} 个后台任务:{names}",
|
|
3931
|
+
"archive.confirm.jobs.other": "{n} 个后台任务:{names}",
|
|
3932
|
+
"archive.confirm.schedules.one": "{n} 条定时提醒:{names}",
|
|
3933
|
+
"archive.confirm.schedules.other": "{n} 条定时提醒:{names}",
|
|
3934
|
+
"archive.confirm.other.one": "{n} 项其他工作({kind})",
|
|
3935
|
+
"archive.confirm.other.other": "{n} 项其他工作({kind})",
|
|
3936
|
+
"archive.confirm.listSeparator": "、",
|
|
3937
|
+
"archive.confirm.action": "停止并归档",
|
|
3938
|
+
"archive.confirm.pending": "正在停止并归档…",
|
|
3939
|
+
"toast.archivedUndo": "撤销",
|
|
3940
|
+
"toast.archivedOr": "或",
|
|
3941
|
+
"toast.archivedFilter": "筛选已归档会话",
|
|
3942
|
+
"toast.pinFailed": "置顶失败,请稍后重试",
|
|
3943
|
+
"toast.unpinFailed": "取消置顶失败,请稍后重试",
|
|
3944
|
+
"toast.createFailed": "新建会话失败:{message}",
|
|
3945
|
+
"sessions.count.one": "{n} 个会话",
|
|
3946
|
+
"sessions.count.other": "{n} 个会话",
|
|
3947
|
+
"actions.workspace.aria": "工作区“{name}”的操作",
|
|
3948
|
+
"actions.session.aria": "会话“{name}”的操作",
|
|
3949
|
+
"actions.archive": "归档会话",
|
|
3950
|
+
"actions.unarchive": "取消归档",
|
|
3951
|
+
"actions.pin": "置顶会话",
|
|
3952
|
+
"actions.unpin": "取消置顶",
|
|
3953
|
+
"actions.newSession": "新会话",
|
|
3954
|
+
"actions.newSession.aria": "在“{name}”中新建会话",
|
|
3955
|
+
"status.running": "进行中",
|
|
3956
|
+
"status.subagentsRunning.one": "{n} 个子智能体运行中",
|
|
3957
|
+
"status.subagentsRunning.other": "{n} 个子智能体运行中",
|
|
3958
|
+
"status.idle": "空闲",
|
|
3959
|
+
"status.waitingApproval": "等待审批",
|
|
3960
|
+
"status.planReview": "计划待审",
|
|
3961
|
+
"status.waitingAnswer": "等待回答",
|
|
3962
|
+
"status.compact.approval": "待审批",
|
|
3963
|
+
"status.compact.planReview": "计划待审",
|
|
3964
|
+
"status.compact.answer": "待回答",
|
|
3965
|
+
"status.completed": "已完成",
|
|
3966
|
+
"hover.created": "创建于 {time}",
|
|
3967
|
+
"hover.copied": "已复制",
|
|
3968
|
+
"date.ymd": "{y}年{m}月{d}日",
|
|
3969
|
+
"time.now": "刚刚",
|
|
3970
|
+
"time.minutes": "{n}分钟",
|
|
3971
|
+
"time.hours": "{n}小时",
|
|
3972
|
+
"time.days": "{n}天",
|
|
3973
|
+
"time.months": "{n}个月",
|
|
3974
|
+
"time.years": "{n}年",
|
|
3975
|
+
"time.ago": "{t}前"
|
|
3976
|
+
};
|
|
3977
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
3978
|
+
const en = {
|
|
3979
|
+
"defaultWorkspace.failed": "Unable to create default workspace. Use Choose workspace to select a folder.",
|
|
3980
|
+
"group.ungrouped": "Ungrouped",
|
|
3981
|
+
"session.new": "New Session",
|
|
3982
|
+
"shortcut.noSession": "Select a session first",
|
|
3983
|
+
"shortcut.noPicker": "Directory picker unavailable",
|
|
3984
|
+
"shortcut.directoryBusy": "Selecting or adding a workspace",
|
|
3985
|
+
"shortcut.noCompletedTurn": "This session has no completed turn",
|
|
3986
|
+
"shortcut.forkFailed": "Could not fork the session. Try again.",
|
|
3987
|
+
"section.workspaces": "Workspaces",
|
|
3988
|
+
"section.sessions": "Sessions",
|
|
3989
|
+
"viewOptions.label": "View options",
|
|
3990
|
+
"groupBy.label": "Group by",
|
|
3991
|
+
"groupBy.workspace": "WorkSpace",
|
|
3992
|
+
"groupBy.workspaceTree": "Workspace Tree",
|
|
3993
|
+
"groupBy.flat": "In one list",
|
|
3994
|
+
"orderBy.label": "Order by",
|
|
3995
|
+
"orderBy.manual": "Manual",
|
|
3996
|
+
"orderBy.updated": "Last updated",
|
|
3997
|
+
"filterBy.label": "Filter sessions",
|
|
3998
|
+
"viewOptions.hideArchived": "Hide archived",
|
|
3999
|
+
"viewOptions.showArchived": "All conversations (show archived)",
|
|
4000
|
+
"viewOptions.onlyArchived": "Archived only",
|
|
4001
|
+
"sessions.expand": "Show {n} more sessions",
|
|
4002
|
+
"sessions.collapse": "Show less",
|
|
4003
|
+
"empty.none": "No sessions yet",
|
|
4004
|
+
"empty.noneArchived": "No archived sessions yet",
|
|
4005
|
+
"empty.viewOthers": "View other sessions",
|
|
4006
|
+
"empty.noMatches": "No matches",
|
|
4007
|
+
"workspace.add": "Add workspace",
|
|
4008
|
+
"search.sessions.aria": "Search sessions",
|
|
4009
|
+
"search.placeholder": "Search session names",
|
|
4010
|
+
"search.clear": "Clear search",
|
|
4011
|
+
"search.results.aria": "Search results",
|
|
4012
|
+
"search.pending": "Searching session history…",
|
|
4013
|
+
"search.noMatches": "No matching sessions",
|
|
4014
|
+
"search.hasMore": "Showing the first {n} results. Narrow your search.",
|
|
4015
|
+
"menu.addWorkspace": "Add workspace…",
|
|
4016
|
+
"picker.loading": "Loading workspaces…",
|
|
4017
|
+
"conflict.named": "A workspace named “{name}” already exists.",
|
|
4018
|
+
"folderError.title": "Couldn’t open folder",
|
|
4019
|
+
"folderError.retry": "Choose again",
|
|
4020
|
+
"rename": "Rename",
|
|
4021
|
+
"rename.workspace.title": "Rename workspace",
|
|
4022
|
+
"rename.session.title": "Rename session",
|
|
4023
|
+
"field.workspaceName": "Workspace name",
|
|
4024
|
+
"field.sessionName": "Session name",
|
|
4025
|
+
"delete.workspace": "Delete workspace",
|
|
4026
|
+
"delete.desc": "This removes “{name}” from the workspace list. The folder and session logs will be kept. Its sessions will appear under Ungrouped.",
|
|
4027
|
+
"delete.pending": "Deleting workspace…",
|
|
4028
|
+
"menu.fork": "Fork session",
|
|
4029
|
+
"menu.archiveSession": "Archive session",
|
|
4030
|
+
"menu.unarchiveSession": "Unarchive session",
|
|
4031
|
+
"menu.pinSession": "Pin session",
|
|
4032
|
+
"menu.unpinSession": "Unpin session",
|
|
4033
|
+
"row.archived": "Archived",
|
|
4034
|
+
"row.pinned": "Pinned",
|
|
4035
|
+
"toast.archivedNotOpenable": "Archived sessions cannot be opened. Unarchive it to view.",
|
|
4036
|
+
"toast.archived": "Session archived. You can ",
|
|
4037
|
+
"toast.stoppedAndArchived": "Session stopped and archived. You can ",
|
|
4038
|
+
"archive.confirm.title": "Stop and archive this session?",
|
|
4039
|
+
"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.",
|
|
4040
|
+
"archive.confirm.activity": "Work that will be stopped",
|
|
4041
|
+
"archive.confirm.turn": "The turn in progress",
|
|
4042
|
+
"archive.confirm.subagents.one": "{n} running subagent: {names}",
|
|
4043
|
+
"archive.confirm.subagents.other": "{n} running subagents: {names}",
|
|
4044
|
+
"archive.confirm.jobs.one": "{n} background job: {names}",
|
|
4045
|
+
"archive.confirm.jobs.other": "{n} background jobs: {names}",
|
|
4046
|
+
"archive.confirm.schedules.one": "{n} scheduled reminder: {names}",
|
|
4047
|
+
"archive.confirm.schedules.other": "{n} scheduled reminders: {names}",
|
|
4048
|
+
"archive.confirm.other.one": "{n} other item of work ({kind})",
|
|
4049
|
+
"archive.confirm.other.other": "{n} other items of work ({kind})",
|
|
4050
|
+
"archive.confirm.listSeparator": ", ",
|
|
4051
|
+
"archive.confirm.action": "Stop and archive",
|
|
4052
|
+
"archive.confirm.pending": "Stopping and archiving…",
|
|
4053
|
+
"toast.archivedUndo": "undo",
|
|
4054
|
+
"toast.archivedOr": " or ",
|
|
4055
|
+
"toast.archivedFilter": "filter archived sessions",
|
|
4056
|
+
"toast.pinFailed": "Pin failed. Try again later.",
|
|
4057
|
+
"toast.unpinFailed": "Unpin failed. Try again later.",
|
|
4058
|
+
"toast.createFailed": "New session failed: {message}",
|
|
4059
|
+
"sessions.count.one": "{n} session",
|
|
4060
|
+
"sessions.count.other": "{n} sessions",
|
|
4061
|
+
"actions.workspace.aria": "Workspace actions for {name}",
|
|
4062
|
+
"actions.session.aria": "Session actions for {name}",
|
|
4063
|
+
"actions.archive": "Archive",
|
|
4064
|
+
"actions.unarchive": "Unarchive",
|
|
4065
|
+
"actions.pin": "Pin",
|
|
4066
|
+
"actions.unpin": "Unpin",
|
|
4067
|
+
"actions.newSession": "New session",
|
|
4068
|
+
"actions.newSession.aria": "New session in {name}",
|
|
4069
|
+
"status.running": "Running",
|
|
4070
|
+
"status.subagentsRunning.one": "{n} subagent running",
|
|
4071
|
+
"status.subagentsRunning.other": "{n} subagents running",
|
|
4072
|
+
"status.idle": "Idle",
|
|
4073
|
+
"status.waitingApproval": "Waiting for approval",
|
|
4074
|
+
"status.planReview": "Plan awaiting review",
|
|
4075
|
+
"status.waitingAnswer": "Waiting for answer",
|
|
4076
|
+
"status.compact.approval": "Approval",
|
|
4077
|
+
"status.compact.planReview": "Plan review",
|
|
4078
|
+
"status.compact.answer": "Answer",
|
|
4079
|
+
"status.completed": "Completed",
|
|
4080
|
+
"hover.created": "Created {time}",
|
|
4081
|
+
"hover.copied": "Copied",
|
|
4082
|
+
"date.ymd": "{y}-{m}-{d}",
|
|
4083
|
+
"time.now": "now",
|
|
4084
|
+
"time.minutes": "{n}min",
|
|
4085
|
+
"time.hours": "{n}h",
|
|
4086
|
+
"time.days": "{n}d",
|
|
4087
|
+
"time.months": "{n}mo",
|
|
4088
|
+
"time.years": "{n}y",
|
|
4089
|
+
"time.ago": "{t} ago"
|
|
4090
|
+
};
|
|
4091
|
+
//#endregion
|
|
3828
4092
|
//#region lib/types/client/index.js
|
|
3829
4093
|
/** Dictionary namespace owned by this plugin. */
|
|
3830
4094
|
const NS = "workspace";
|
|
@@ -3843,7 +4107,8 @@ window.__ModuleLoader__.load({
|
|
|
3843
4107
|
"locale",
|
|
3844
4108
|
"remote",
|
|
3845
4109
|
"remote.directoryPicker",
|
|
3846
|
-
"layout"
|
|
4110
|
+
"layout",
|
|
4111
|
+
"shortcuts"
|
|
3847
4112
|
];
|
|
3848
4113
|
/**
|
|
3849
4114
|
* Register the browser and picker once their slot declarations are on the
|
|
@@ -3874,6 +4139,7 @@ window.__ModuleLoader__.load({
|
|
|
3874
4139
|
zh,
|
|
3875
4140
|
en
|
|
3876
4141
|
}), "ui-workspace: dictionaries");
|
|
4142
|
+
const shortcutControls = createWorkspaceShortcutControls();
|
|
3877
4143
|
const searchSessions = async (query, signal) => {
|
|
3878
4144
|
const result = await sessions.search(query, signal);
|
|
3879
4145
|
if (!result.ok) throw new Error(result.error.message);
|
|
@@ -3894,14 +4160,9 @@ window.__ModuleLoader__.load({
|
|
|
3894
4160
|
};
|
|
3895
4161
|
const pinnedSet = derive(workspaces.list, (snapshot) => new Set(snapshot.pinnedSessionIds));
|
|
3896
4162
|
const archivedSet = derive(workspaces.list, (snapshot) => new Set(snapshot.archivedSessionIds));
|
|
3897
|
-
const renameRequest = (
|
|
4163
|
+
const renameRequest = derive(shortcutControls.state, (state) => state.renameTarget);
|
|
3898
4164
|
const archiveRequest = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(null);
|
|
3899
|
-
const requestSessionRename =
|
|
3900
|
-
renameRequest.set({
|
|
3901
|
-
sessionId,
|
|
3902
|
-
currentTitle
|
|
3903
|
-
});
|
|
3904
|
-
};
|
|
4165
|
+
const requestSessionRename = shortcutControls.rename;
|
|
3905
4166
|
const unarchiveSession = (sessionId) => {
|
|
3906
4167
|
uiWorkspace.unarchiveSession(sessionId).catch((reason) => {
|
|
3907
4168
|
console.warn("session unarchive rejected:", reason);
|
|
@@ -3951,6 +4212,7 @@ window.__ModuleLoader__.load({
|
|
|
3951
4212
|
},
|
|
3952
4213
|
unarchiveSession
|
|
3953
4214
|
});
|
|
4215
|
+
installWorkspaceShortcuts(ctx, uiWorkspace, shortcutControls, archiveInjected().archiveSession);
|
|
3954
4216
|
const archiveConfirmInjected = () => ({
|
|
3955
4217
|
hooks: { archiveRequest },
|
|
3956
4218
|
settleSessionArchive: () => {
|
|
@@ -3970,9 +4232,7 @@ window.__ModuleLoader__.load({
|
|
|
3970
4232
|
const renameInjected = () => ({ requestSessionRename });
|
|
3971
4233
|
const renameDialogInjected = () => ({
|
|
3972
4234
|
hooks: { renameRequest },
|
|
3973
|
-
settleSessionRename:
|
|
3974
|
-
renameRequest.set(null);
|
|
3975
|
-
},
|
|
4235
|
+
settleSessionRename: shortcutControls.closeRename,
|
|
3976
4236
|
renameSession
|
|
3977
4237
|
});
|
|
3978
4238
|
const rowToastInjected = () => ({
|
|
@@ -4009,9 +4269,16 @@ window.__ModuleLoader__.load({
|
|
|
4009
4269
|
await uiWorkspace.unarchiveSession(sessionId);
|
|
4010
4270
|
},
|
|
4011
4271
|
createWorkspace: (input) => workspaces.create(input),
|
|
4272
|
+
requestSearch: shortcutControls.search,
|
|
4273
|
+
requestAddWorkspace: shortcutControls.add,
|
|
4274
|
+
closeAddWorkspace: shortcutControls.closeAdd,
|
|
4275
|
+
setDirectoryBusy: shortcutControls.directoryBusy,
|
|
4276
|
+
dismissForkError: shortcutControls.dismissForkError,
|
|
4012
4277
|
hooks: {
|
|
4013
4278
|
directoryFlow: browserFlowSource,
|
|
4014
|
-
hostInfo
|
|
4279
|
+
hostInfo,
|
|
4280
|
+
workspaceShortcuts: shortcutControls.state,
|
|
4281
|
+
shortcuts: ctx.shortcuts.catalog
|
|
4015
4282
|
}
|
|
4016
4283
|
});
|
|
4017
4284
|
const pickerInjected = () => ({
|
|
@@ -4028,11 +4295,22 @@ window.__ModuleLoader__.load({
|
|
|
4028
4295
|
"sidebar.workspaces.session.menu.item": {
|
|
4029
4296
|
kind: "list",
|
|
4030
4297
|
scope: "root",
|
|
4031
|
-
inject: { hooks: {
|
|
4298
|
+
inject: { hooks: {
|
|
4299
|
+
menuOpenState: menuOpenStateFactory,
|
|
4300
|
+
shortcuts: ctx.shortcuts.catalog
|
|
4301
|
+
} }
|
|
4032
4302
|
},
|
|
4033
4303
|
"sidebar.workspaces.session.row.action": {
|
|
4034
4304
|
kind: "list",
|
|
4035
4305
|
scope: "root"
|
|
4306
|
+
},
|
|
4307
|
+
"sidebar.session.row.leading": {
|
|
4308
|
+
kind: "list",
|
|
4309
|
+
scope: "root"
|
|
4310
|
+
},
|
|
4311
|
+
"sidebar.session.row.hover": {
|
|
4312
|
+
kind: "list",
|
|
4313
|
+
scope: "root"
|
|
4036
4314
|
}
|
|
4037
4315
|
},
|
|
4038
4316
|
store: viewStore,
|
|
@@ -4102,6 +4380,7 @@ window.__ModuleLoader__.load({
|
|
|
4102
4380
|
name: "shell.overlay",
|
|
4103
4381
|
id: "workspace.row-toast",
|
|
4104
4382
|
locale: NS,
|
|
4383
|
+
store: viewStore,
|
|
4105
4384
|
inject: rowToastInjected
|
|
4106
4385
|
}, RowActionToast);
|
|
4107
4386
|
});
|