@huanlin/dsh-plugin-ya-workspace-sidebar 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -1203,7 +1203,45 @@ window.__ModuleLoader__.load({
1203
1203
  * pre-split client runtime: reuse-or-create Workspace connection, the
1204
1204
  * explicit/current/recent New Session fallback, archived-current clearing,
1205
1205
  * boot auto-selection, and the directory-picking wire calls.
1206
+ *
1207
+ * dsh 0.1.7-rc.1 moved the Session selection out of the Session Controller
1208
+ * (`SessionListState.current` / `ISessions.open` / `ISessions.clear` are gone)
1209
+ * into this service: a retained `mainReference` plus a persisted selection
1210
+ * store (`dsh.sessions.current`). This port mirrors the shipped
1211
+ * `UiWorkspaceService` selection mechanics.
1206
1212
  */
1213
+ /** Persisted selection store (the official `dsh.sessions.current` key). */
1214
+ var SelectionStore = class {
1215
+ key;
1216
+ listeners = /* @__PURE__ */ new Set();
1217
+ value;
1218
+ constructor(key = "dsh.sessions.current") {
1219
+ this.key = key;
1220
+ this.value = this.read();
1221
+ }
1222
+ getSnapshot = () => this.value;
1223
+ subscribe = (listener) => {
1224
+ this.listeners.add(listener);
1225
+ return () => {
1226
+ this.listeners.delete(listener);
1227
+ };
1228
+ };
1229
+ set = (value) => {
1230
+ this.value = value;
1231
+ try {
1232
+ globalThis.localStorage?.setItem(this.key, JSON.stringify(value));
1233
+ } catch {}
1234
+ for (const listener of [...this.listeners]) listener();
1235
+ };
1236
+ read() {
1237
+ try {
1238
+ const raw = globalThis.localStorage?.getItem(this.key);
1239
+ return raw === null || raw === void 0 ? {} : JSON.parse(raw);
1240
+ } catch {
1241
+ return {};
1242
+ }
1243
+ }
1244
+ };
1207
1245
  /** Implements Workspace navigation and directory UI operations. */
1208
1246
  var YaWorkspaceNavigation = class extends _deepseek_ai_cordis.Service {
1209
1247
  directoryPicker;
@@ -1211,6 +1249,8 @@ window.__ModuleLoader__.load({
1211
1249
  sessions;
1212
1250
  connecting = /* @__PURE__ */ new Map();
1213
1251
  lifetime = new AbortController();
1252
+ selection = new SelectionStore();
1253
+ mainReference;
1214
1254
  /**
1215
1255
  * @param ctx - Client root Context.
1216
1256
  * @param directoryPicker - the directory-picking Remote namespace.
@@ -1224,61 +1264,95 @@ window.__ModuleLoader__.load({
1224
1264
  this.sessions = sessions;
1225
1265
  ctx.effect(() => this.watchNavigation(), "ya-workspace-sidebar: Workspace navigation policy");
1226
1266
  }
1267
+ /** The Session currently shown in the main view, or undefined. */
1268
+ get currentSessionId() {
1269
+ return this.mainReference?.sessionId;
1270
+ }
1271
+ /** Observe the current selection (the sidebar's blank-row filter and highlight). */
1272
+ subscribeSelection(listener) {
1273
+ return this.selection.subscribe(listener);
1274
+ }
1227
1275
  async connectWorkspace(workspaceId) {
1228
1276
  const workspace = this.workspaces.list.getSnapshot().items.find((item) => item.workspaceId === workspaceId);
1229
1277
  if (workspace === void 0) throw new Error(`ya-workspace-sidebar: unknown workspace "${workspaceId}"`);
1230
1278
  const inflight = this.connecting.get(workspaceId);
1231
1279
  if (inflight !== void 0) return inflight;
1280
+ const attempt = this.reuseOrCreateBlank(workspace).finally(() => {
1281
+ this.connecting.delete(workspaceId);
1282
+ });
1283
+ this.connecting.set(workspaceId, attempt);
1284
+ return attempt;
1285
+ }
1286
+ reuseOrCreateBlank(workspace) {
1232
1287
  const archived = this.workspaces.list.getSnapshot().archivedSessionIds;
1233
1288
  const sessions = this.sessions.list.getSnapshot();
1234
1289
  for (const id of sessions.ids) {
1235
1290
  const summary = sessions.byId[id];
1236
- if (summary !== void 0 && summary.blank && summary.cwd === workspace.path && workspace.sessionIds.includes(summary.id) && !archived.includes(summary.id)) return summary.id;
1291
+ if (summary === void 0 || !summary.blank || summary.cwd !== workspace.path || !workspace.sessionIds.includes(id) || archived.includes(id)) continue;
1292
+ return this.reuseBlank(workspace.workspaceId, id);
1237
1293
  }
1238
- const attempt = this.sessions.create({ workspaceId }).finally(() => {
1239
- this.connecting.delete(workspaceId);
1240
- });
1241
- this.connecting.set(workspaceId, attempt);
1242
- return attempt;
1294
+ return this.sessions.create({ workspaceId: workspace.workspaceId });
1243
1295
  }
1244
- openSession(sessionId) {
1245
- this.sessions.open(sessionId);
1246
- this.ctx.layout.selectPanel(null);
1296
+ async reuseBlank(workspaceId, sessionId) {
1297
+ try {
1298
+ return await this.sessions.create({
1299
+ workspaceId,
1300
+ sessionId
1301
+ });
1302
+ } catch (error) {
1303
+ if (!(error instanceof Error) || error.name !== "SessionCreateError") throw error;
1304
+ if (error.rpcError?.code !== "session/writer-held") throw error;
1305
+ return this.sessions.create({ workspaceId });
1306
+ }
1307
+ }
1308
+ openSession(target) {
1309
+ this.replaceMain(target, this.lifetime.signal, "reveal");
1247
1310
  }
1248
1311
  async openWorkspace(workspaceId, beforeOpen) {
1249
1312
  const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);
1250
- const isCurrent = () => !navigation.aborted;
1251
- const sessionId = await this.connectWorkspace(workspaceId);
1252
- if (!isCurrent()) return;
1253
- beforeOpen?.(sessionId);
1254
- if (isCurrent()) this.openSession(sessionId);
1313
+ let sessionId;
1314
+ try {
1315
+ sessionId = await this.connectWorkspace(workspaceId);
1316
+ } catch (error) {
1317
+ if (!navigation.aborted) console.warn("ya-workspace-sidebar: workspace open failed:", error);
1318
+ throw error;
1319
+ }
1320
+ if (navigation.aborted) return;
1321
+ this.replaceMain(sessionId, navigation, "reveal", beforeOpen);
1255
1322
  }
1256
1323
  async forkSession(sessionId) {
1257
- const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);
1258
- const childId = await this.sessions.fork({
1324
+ await this.sessions.fork({
1259
1325
  sessionId,
1260
1326
  increaseTitle: true
1261
1327
  });
1262
- if (!navigation.aborted) this.openSession(childId);
1263
1328
  }
1264
1329
  startSession(workspaceId) {
1265
1330
  const workspaces = this.workspaces.list.getSnapshot();
1266
1331
  const sessions = this.sessions.list.getSnapshot();
1267
- const current = sessions.current;
1332
+ const current = this.mainReference?.sessionId;
1268
1333
  const currentWorkspaceId = current === void 0 ? void 0 : workspaces.items.find((item) => item.sessionIds.includes(current))?.workspaceId;
1269
1334
  const recent = workspaces.phase === "ready" && sessions.phase === "ready" ? recentWorkspace(workspaces.items, sessions.byId) : void 0;
1270
1335
  const target = workspaceId ?? currentWorkspaceId ?? recent;
1271
1336
  if (target === void 0) {
1272
- this.sessions.clear();
1273
- this.ctx.layout.selectPanel(null);
1337
+ this.clearMain();
1274
1338
  return;
1275
1339
  }
1276
1340
  this.openWorkspace(target).then(() => {}, (reason) => {
1277
1341
  console.warn("ya-workspace-sidebar: new session failed:", reason);
1278
1342
  });
1279
1343
  }
1280
- async archiveSession(sessionId) {
1281
- await this.workspaces.archiveSession(sessionId);
1344
+ async archiveSession(sessionId, options = {}) {
1345
+ await this.workspaces.archiveSession(sessionId, options);
1346
+ if (this.mainReference?.sessionId === sessionId) this.clearMain();
1347
+ }
1348
+ async unarchiveSession(sessionId) {
1349
+ await this.workspaces.unarchiveSession(sessionId);
1350
+ }
1351
+ async pinSession(sessionId) {
1352
+ await this.workspaces.pinSession(sessionId);
1353
+ }
1354
+ async unpinSession(sessionId) {
1355
+ await this.workspaces.unpinSession(sessionId);
1282
1356
  }
1283
1357
  async pickDirectory() {
1284
1358
  const result = await this.directoryPicker.pick();
@@ -1304,24 +1378,17 @@ window.__ModuleLoader__.load({
1304
1378
  const workspaces = this.workspaces.list.getSnapshot();
1305
1379
  const sessions = this.sessions.list.getSnapshot();
1306
1380
  if (workspaces.phase !== "ready" || sessions.phase !== "ready") return;
1307
- if (sessions.current !== void 0) {
1308
- initial = "done";
1309
- return;
1310
- }
1311
- const target = recentWorkspace(workspaces.items, sessions.byId);
1312
- if (target === void 0) {
1381
+ if (this.mainReference !== void 0) {
1313
1382
  initial = "done";
1314
1383
  return;
1315
1384
  }
1316
1385
  initial = "connecting";
1317
- this.connectWorkspace(target).then((sessionId) => {
1318
- if (this.lifetime.signal.aborted) return;
1319
- if (this.sessions.list.getSnapshot().current === void 0) this.sessions.open(sessionId);
1386
+ this.restoreSelection(workspaces, sessions).then(() => {
1320
1387
  initial = "done";
1321
1388
  }, (reason) => {
1322
1389
  if (this.lifetime.signal.aborted) return;
1323
1390
  initial = "waiting";
1324
- console.warn("ya-workspace-sidebar: initial workspace selection failed:", reason);
1391
+ console.warn("ya-workspace-sidebar: initial Session restoration failed:", reason);
1325
1392
  });
1326
1393
  };
1327
1394
  const disposeWorkspaces = this.workspaces.list.subscribe(reconcile);
@@ -1333,13 +1400,63 @@ window.__ModuleLoader__.load({
1333
1400
  disposeWorkspaces();
1334
1401
  };
1335
1402
  }
1403
+ async restoreSelection(workspaces, sessions) {
1404
+ const saved = this.selection.getSnapshot();
1405
+ if (saved.subagentAddress !== void 0) {
1406
+ this.replaceMain(saved.subagentAddress, this.lifetime.signal, "preserve");
1407
+ return;
1408
+ }
1409
+ const summary = saved.sessionId === void 0 ? void 0 : sessions.byId[saved.sessionId];
1410
+ const workspace = summary === void 0 ? void 0 : workspaces.items.find((item) => item.sessionIds.includes(summary.id));
1411
+ if (summary !== void 0 && (!summary.blank || workspace === void 0)) {
1412
+ this.replaceMain(summary.id, this.lifetime.signal, "preserve");
1413
+ return;
1414
+ }
1415
+ const navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);
1416
+ let sessionId;
1417
+ if (summary !== void 0 && workspace !== void 0 && summary.cwd === workspace.path && !workspaces.archivedSessionIds.includes(summary.id)) sessionId = await this.reuseBlank(workspace.workspaceId, summary.id);
1418
+ const target = workspace?.workspaceId ?? recentWorkspace(workspaces.items, sessions.byId);
1419
+ if (sessionId === void 0 && target !== void 0) sessionId = await this.connectWorkspace(target);
1420
+ if (sessionId !== void 0 && !navigation.aborted) this.replaceMain(sessionId, navigation, "preserve");
1421
+ }
1336
1422
  /** @returns true when an archived current selection was cleared. */
1337
1423
  clearArchivedCurrent() {
1338
- const current = this.sessions.list.getSnapshot().current;
1424
+ const current = this.mainReference?.sessionId;
1339
1425
  if (current === void 0 || !this.workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false;
1340
- this.sessions.clear();
1426
+ this.clearMain();
1341
1427
  return true;
1342
1428
  }
1429
+ clearMain() {
1430
+ const previous = this.mainReference;
1431
+ this.mainReference = void 0;
1432
+ this.selection.set({});
1433
+ previous?.release();
1434
+ this.ctx.layout.selectPanel(null);
1435
+ }
1436
+ replaceMain(target, signal, panel, beforeOpen) {
1437
+ signal.throwIfAborted();
1438
+ const reference = this.sessions.retain(target, { source: "mainView" });
1439
+ try {
1440
+ signal.throwIfAborted();
1441
+ beforeOpen?.(reference.sessionId);
1442
+ if (signal.aborted) {
1443
+ reference.release();
1444
+ return;
1445
+ }
1446
+ const subagentAddress = typeof target === "string" ? this.sessions.subagentAddress(reference.sessionId) : target;
1447
+ this.selection.set({
1448
+ sessionId: reference.sessionId,
1449
+ ...subagentAddress === void 0 ? {} : { subagentAddress }
1450
+ });
1451
+ } catch (error) {
1452
+ reference.release();
1453
+ throw error;
1454
+ }
1455
+ const previous = this.mainReference;
1456
+ this.mainReference = reference;
1457
+ previous?.release();
1458
+ if (panel === "reveal") this.ctx.layout.selectPanel(null);
1459
+ }
1343
1460
  };
1344
1461
  /** Stable tie-breaking follows Host Workspace order. */
1345
1462
  function recentWorkspace(workspaces, sessions) {
@@ -1464,14 +1581,14 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
1464
1581
  const addEntries = flowAvailable ? [{
1465
1582
  id: ADD,
1466
1583
  label: t("addWorkspaceMenu"),
1467
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 }),
1584
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 16 }),
1468
1585
  disabled: flowOpen || busy
1469
1586
  }] : [];
1470
1587
  const pinnedAdd = !addOnly && snapshot.items.length > 0;
1471
1588
  const items = pinnedAdd ? snapshot.items.map((workspace) => ({
1472
1589
  id: workspace.workspaceId,
1473
1590
  label: workspace.title,
1474
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 }),
1591
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }),
1475
1592
  disabled: flowOpen || busy
1476
1593
  })) : addEntries;
1477
1594
  const settled = addOnly || snapshot.phase === "ready";
@@ -1575,7 +1692,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
1575
1692
  //#region src/client/model.ts
1576
1693
  /** Resolve the visible status-dot kind for one session, if any. */
1577
1694
  function pendingKindOf(pending, id) {
1578
- const kind = pending.get(id)?.kind;
1695
+ const kind = pending.get(id)?.pendingInteraction?.kind;
1579
1696
  return kind === "approval" || kind === "plan-review" || kind === "question" ? kind : void 0;
1580
1697
  }
1581
1698
  /** Navigation key for sessions not accounted to a real workspace. */
@@ -1591,7 +1708,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
1591
1708
  blank: summary.blank,
1592
1709
  running: summary.running,
1593
1710
  ...pendingInteraction === void 0 ? {} : { pendingInteraction },
1594
- completed: summary.completed === true,
1711
+ completed: pending.get(summary.id)?.completionUnread === true,
1595
1712
  updatedAt: summary.updatedAt,
1596
1713
  workspaceKey,
1597
1714
  workspaceTitle,
@@ -2122,7 +2239,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2122
2239
  const title = row.blank ? t("newSession") : row.title;
2123
2240
  const isDelete = actionMode === "delete";
2124
2241
  const actionLabel = isDelete ? t("deleteSession") : t("archive");
2125
- const actionIcon = isDelete ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 });
2242
+ const actionIcon = isDelete ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: 16 });
2126
2243
  const hasCwd = row.cwd !== void 0;
2127
2244
  const pathsKnown = paths !== void 0;
2128
2245
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -2183,17 +2300,17 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2183
2300
  {
2184
2301
  id: "rename",
2185
2302
  label: t("rename"),
2186
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {})
2303
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, {})
2187
2304
  },
2188
2305
  {
2189
2306
  id: "fork",
2190
2307
  label: t("fork"),
2191
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, {})
2308
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, {})
2192
2309
  },
2193
2310
  {
2194
2311
  id: "unread",
2195
2312
  label: unread ? t("markRead") : t("markUnread"),
2196
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconClockOutline16, {})
2313
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconClockOutlineRegular, {})
2197
2314
  },
2198
2315
  {
2199
2316
  type: "separator",
@@ -2202,31 +2319,31 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2202
2319
  {
2203
2320
  id: "reveal",
2204
2321
  label: t("revealInExplorer"),
2205
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}),
2322
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutlineRegular, {}),
2206
2323
  disabled: !hasCwd
2207
2324
  },
2208
2325
  {
2209
2326
  id: "copy-path",
2210
2327
  label: t("copyPath"),
2211
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}),
2328
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular, {}),
2212
2329
  disabled: !hasCwd
2213
2330
  },
2214
2331
  {
2215
2332
  id: "copy-dir",
2216
2333
  label: t("copySessionDir"),
2217
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}),
2334
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular, {}),
2218
2335
  disabled: !pathsKnown || paths?.dir == null
2219
2336
  },
2220
2337
  {
2221
2338
  id: "copy-log",
2222
2339
  label: t("copyLogPath"),
2223
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}),
2340
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular, {}),
2224
2341
  disabled: !pathsKnown || paths?.log == null
2225
2342
  },
2226
2343
  {
2227
2344
  id: "copy-id",
2228
2345
  label: t("copySessionId"),
2229
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, {})
2346
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutlineRegular, {})
2230
2347
  },
2231
2348
  {
2232
2349
  type: "separator",
@@ -2292,7 +2409,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2292
2409
  onOpenMenu(row);
2293
2410
  setMenuOpenButton((value) => !value);
2294
2411
  },
2295
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, {})
2412
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutlineRegular, {})
2296
2413
  })
2297
2414
  })
2298
2415
  })
@@ -2318,7 +2435,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2318
2435
  children: [
2319
2436
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2320
2437
  className: "ya-status-slot",
2321
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, {})
2438
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, {})
2322
2439
  }),
2323
2440
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2324
2441
  className: "ya-row-main",
@@ -2336,7 +2453,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2336
2453
  children: row.path
2337
2454
  })]
2338
2455
  }),
2339
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {}),
2456
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineMedium, {}),
2340
2457
  row.real && menuAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
2341
2458
  open: true,
2342
2459
  onClose: () => {
@@ -2346,7 +2463,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2346
2463
  {
2347
2464
  id: "create",
2348
2465
  label: t("newSession"),
2349
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, {})
2466
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, {})
2350
2467
  },
2351
2468
  {
2352
2469
  type: "separator",
@@ -2355,13 +2472,13 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2355
2472
  {
2356
2473
  id: "reveal",
2357
2474
  label: t("revealInExplorer"),
2358
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}),
2475
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutlineRegular, {}),
2359
2476
  disabled: !hasPath
2360
2477
  },
2361
2478
  {
2362
2479
  id: "copy-path",
2363
2480
  label: t("copyPath"),
2364
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}),
2481
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular, {}),
2365
2482
  disabled: !hasPath
2366
2483
  },
2367
2484
  {
@@ -2371,12 +2488,12 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2371
2488
  {
2372
2489
  id: "rename",
2373
2490
  label: t("rename"),
2374
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, {})
2491
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, {})
2375
2492
  },
2376
2493
  {
2377
2494
  id: "delete",
2378
2495
  label: t("deleteWorkspace"),
2379
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}),
2496
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, {}),
2380
2497
  danger: true
2381
2498
  }
2382
2499
  ],
@@ -2403,12 +2520,17 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2403
2520
  }
2404
2521
  /** Fill `sidebar.workspaces` with the replacement browser. */
2405
2522
  function WorkspaceSidebar(props) {
2406
- const { wide, expandSidebar, useSessions, useSessionPendingInteraction, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t, resolveSessionPaths, revealInExplorer } = props;
2523
+ const { wide, expandSidebar, useSessions, useSessionStatus, useCurrentSession, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t, resolveSessionPaths, revealInExplorer } = props;
2407
2524
  const sessions = useSessions((state) => state);
2525
+ const current = useCurrentSession((value) => value);
2526
+ const sessionsView = (0, react.useMemo)(() => ({
2527
+ ...sessions,
2528
+ current
2529
+ }), [sessions, current]);
2408
2530
  const workspaceState = useWorkspaces((state) => state);
2409
2531
  const workspaces = workspaceState.items;
2410
2532
  const archived = workspaceState.archivedSessionIds;
2411
- const pendingInteractions = useSessionPendingInteraction((state) => state);
2533
+ const pendingInteractions = useSessionStatus((state) => state);
2412
2534
  const directoryFlowAvailable = useDirectoryFlow((value) => value);
2413
2535
  const [pinnedOrder, setPinnedOrder] = (0, react.useState)(() => getPinnedOrder());
2414
2536
  const [unreadSet, setUnreadSet] = (0, react.useState)(() => getUnread());
@@ -2434,16 +2556,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2434
2556
  setPathsTick((tick) => tick + 1);
2435
2557
  }).catch(() => {});
2436
2558
  };
2437
- const allRows = (0, react.useMemo)(() => deriveRecent(sessions, workspaces, archived, pendingInteractions, Number.MAX_SAFE_INTEGER), [
2559
+ const allRows = (0, react.useMemo)(() => deriveRecent(sessionsView, workspaces, archived, pendingInteractions, Number.MAX_SAFE_INTEGER), [
2438
2560
  archived,
2439
2561
  pendingInteractions,
2440
- sessions,
2562
+ sessionsView,
2441
2563
  workspaces
2442
2564
  ]);
2443
2565
  const recent = (0, react.useMemo)(() => applyPinned(allRows, pinnedOrder), [allRows, pinnedOrder]);
2444
- const workspaceRows = (0, react.useMemo)(() => deriveWorkspaces(sessions, workspaces, archived), [
2566
+ const workspaceRows = (0, react.useMemo)(() => deriveWorkspaces(sessionsView, workspaces, archived), [
2445
2567
  archived,
2446
- sessions,
2568
+ sessionsView,
2447
2569
  workspaces
2448
2570
  ]);
2449
2571
  const now = Date.now();
@@ -2457,31 +2579,31 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2457
2579
  const observedCurrent = (0, react.useRef)(void 0);
2458
2580
  const initialized = (0, react.useRef)(false);
2459
2581
  (0, react.useEffect)(() => {
2460
- if (initialized.current && observedCurrent.current === sessions.current) return;
2582
+ if (initialized.current && observedCurrent.current === current) return;
2461
2583
  initialized.current = true;
2462
- observedCurrent.current = sessions.current;
2463
- if (sessions.current !== void 0) {
2584
+ observedCurrent.current = current;
2585
+ if (current !== void 0) {
2464
2586
  setDirection("forward");
2465
- setSelectedKey(workspaceKeyForSession(sessions.current, workspaces));
2587
+ setSelectedKey(workspaceKeyForSession(current, workspaces));
2466
2588
  }
2467
- }, [sessions.current, workspaces]);
2589
+ }, [current, workspaces]);
2468
2590
  (0, react.useEffect)(() => {
2469
2591
  if (selectedKey !== null && selectedKey !== "__ya_ungrouped__" && !workspaces.some((workspace) => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED);
2470
2592
  }, [selectedKey, workspaces]);
2471
2593
  const selectedWorkspace = selectedKey === null || selectedKey === "__ya_ungrouped__" ? void 0 : workspaces.find((workspace) => workspace.workspaceId === selectedKey);
2472
- const levelGroups = (0, react.useMemo)(() => selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? deriveWorkspaceSessionGroups(selectedKey, sessions, workspaces, archived, pendingInteractions, now) : [], [
2594
+ const levelGroups = (0, react.useMemo)(() => selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? deriveWorkspaceSessionGroups(selectedKey, sessionsView, workspaces, archived, pendingInteractions, now) : [], [
2473
2595
  archived,
2474
2596
  pendingInteractions,
2475
- sessions,
2597
+ sessionsView,
2476
2598
  workspaces,
2477
2599
  selectedKey,
2478
2600
  now
2479
2601
  ]);
2480
2602
  const levelPinned = (0, react.useMemo)(() => extractPinnedGroups(levelGroups, pinnedOrder), [levelGroups, pinnedOrder]);
2481
- const levelRows = (0, react.useMemo)(() => applyPinned(selectedKey === "__ya_ungrouped__" ? deriveWorkspaceSessions(UNGROUPED, sessions, workspaces, archived, pendingInteractions) : [], pinnedOrder), [
2603
+ const levelRows = (0, react.useMemo)(() => applyPinned(selectedKey === "__ya_ungrouped__" ? deriveWorkspaceSessions(UNGROUPED, sessionsView, workspaces, archived, pendingInteractions) : [], pinnedOrder), [
2482
2604
  archived,
2483
2605
  pendingInteractions,
2484
- sessions,
2606
+ sessionsView,
2485
2607
  workspaces,
2486
2608
  selectedKey,
2487
2609
  pinnedOrder
@@ -2736,7 +2858,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2736
2858
  };
2737
2859
  const sessionItem = (row, context = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionItem, {
2738
2860
  row,
2739
- current: sessions.current,
2861
+ current,
2740
2862
  now,
2741
2863
  open: openRow,
2742
2864
  rename: beginSessionRename,
@@ -2773,7 +2895,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2773
2895
  event.stopPropagation();
2774
2896
  toggleActionMode();
2775
2897
  },
2776
- children: actionMode === "delete" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: wide ? 16 : 18 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: wide ? 16 : 18 })
2898
+ children: actionMode === "delete" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: wide ? 16 : 18 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: wide ? 16 : 18 })
2777
2899
  }),
2778
2900
  directoryFlowAvailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2779
2901
  ref: pickerAnchor,
@@ -2783,7 +2905,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2783
2905
  onClick: () => {
2784
2906
  setPickerOpen((value) => !value);
2785
2907
  },
2786
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconProjectAddOutline16, { size: wide ? 16 : 18 })
2908
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconProjectAddOutlineRegular, { size: wide ? 16 : 18 })
2787
2909
  }),
2788
2910
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkspacePickFlow, {
2789
2911
  t,
@@ -2815,7 +2937,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2815
2937
  type: "button",
2816
2938
  className: "ya-search-icon",
2817
2939
  "aria-label": t("search"),
2818
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: wide ? 14 : 18 })
2940
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: wide ? 14 : 18 })
2819
2941
  }),
2820
2942
  wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2821
2943
  className: "ya-search-input",
@@ -2833,7 +2955,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2833
2955
  onClick: () => {
2834
2956
  setQuery("");
2835
2957
  },
2836
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseFill14, {})
2958
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseFillMedium, {})
2837
2959
  })
2838
2960
  ]
2839
2961
  }),
@@ -2874,7 +2996,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2874
2996
  event.stopPropagation();
2875
2997
  setRecentCollapsed((value) => !value);
2876
2998
  },
2877
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
2999
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineMedium, {})
2878
3000
  })]
2879
3001
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2880
3002
  className: "ya-recent-list-wrap",
@@ -2923,7 +3045,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2923
3045
  },
2924
3046
  children: t("workspaces")
2925
3047
  }),
2926
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {}),
3048
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineMedium, {}),
2927
3049
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2928
3050
  className: "ya-crumb",
2929
3051
  children: selectedKey === "__ya_ungrouped__" ? t("ungrouped") : selectedWorkspace?.title
@@ -2935,7 +3057,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
2935
3057
  onClick: () => {
2936
3058
  startSession(selectedKey);
2937
3059
  },
2938
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, {})
3060
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, {})
2939
3061
  })
2940
3062
  ] })
2941
3063
  }),
@@ -3131,6 +3253,10 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
3131
3253
  const createWorkspace = (input) => ctx.workspaces.create(input);
3132
3254
  const navigation = new YaWorkspaceNavigation(ctx, ctx.remote.directoryPicker, ctx.workspaces, ctx.sessions);
3133
3255
  ctx.slots.provideRoot({ hooks: { workspaces: ctx.workspaces.list } });
3256
+ const currentSession = {
3257
+ getSnapshot: () => navigation.currentSessionId,
3258
+ subscribe: (listener) => navigation.subscribeSelection(listener)
3259
+ };
3134
3260
  const searchSessions = async (query, signal) => {
3135
3261
  const result = await ctx.sessions.search(query, signal);
3136
3262
  if (!result.ok) throw new Error(result.error.message);
@@ -3197,7 +3323,10 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
3197
3323
  console.warn("reveal request rejected:", reason);
3198
3324
  }
3199
3325
  },
3200
- hooks: { directoryFlow: sidebarFlow }
3326
+ hooks: {
3327
+ directoryFlow: sidebarFlow,
3328
+ currentSession
3329
+ }
3201
3330
  });
3202
3331
  const pickerInjected = () => ({
3203
3332
  createWorkspace,