dsh-git-worktree 0.7.2 → 0.7.3

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
@@ -33,8 +33,10 @@ let react_jsx_runtime = require("react/jsx-runtime");
33
33
  react_jsx_runtime = __toESM(react_jsx_runtime);
34
34
  let __deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
35
35
  __deepseek_ai_dsh_client_ui_primitives = __toESM(__deepseek_ai_dsh_client_ui_primitives);
36
- let __deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
37
- __deepseek_ai_dsh_client_runtime_client = __toESM(__deepseek_ai_dsh_client_runtime_client);
36
+ let __deepseek_ai_cordis = require("@deepseek-ai/cordis");
37
+ __deepseek_ai_cordis = __toESM(__deepseek_ai_cordis);
38
+ let __deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
39
+ __deepseek_ai_dsh_client_store = __toESM(__deepseek_ai_dsh_client_store);
38
40
 
39
41
  //#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
40
42
  var _a$1;
@@ -9672,7 +9674,8 @@ const TARGET_CONSOLE_STYLES = String.raw`
9672
9674
  //#endregion
9673
9675
  //#region \0virtual:dsh-official-workspace-client
9674
9676
  const modules = {
9675
- "@deepseek-ai/dsh-client-runtime/client": __deepseek_ai_dsh_client_runtime_client,
9677
+ "@deepseek-ai/cordis": __deepseek_ai_cordis,
9678
+ "@deepseek-ai/dsh-client-store": __deepseek_ai_dsh_client_store,
9676
9679
  "react/jsx-runtime": react_jsx_runtime,
9677
9680
  "react": react,
9678
9681
  "@deepseek-ai/dsh-client-ui-primitives": __deepseek_ai_dsh_client_ui_primitives
@@ -9681,10 +9684,158 @@ const official = ((require$1) => {
9681
9684
  var module$1 = { exports: {} };
9682
9685
  var exports$1 = module$1.exports;
9683
9686
  Object.defineProperty(exports$1, Symbol.toStringTag, { value: "Module" });
9684
- let _deepseek_ai_dsh_client_runtime_client = require$1("@deepseek-ai/dsh-client-runtime/client");
9687
+ let _deepseek_ai_cordis = require$1("@deepseek-ai/cordis");
9688
+ let _deepseek_ai_dsh_client_store = require$1("@deepseek-ai/dsh-client-store");
9685
9689
  let react_jsx_runtime$1 = require$1("react/jsx-runtime");
9686
9690
  let react$1 = require$1("react");
9687
9691
  let _deepseek_ai_dsh_client_ui_primitives = require$1("@deepseek-ai/dsh-client-ui-primitives");
9692
+ /** Workspace archive and directory UI capability. */
9693
+ /** Structured directory failure exposed to directory UI consumers. */
9694
+ var DirectoryBrowseError = class extends Error {
9695
+ rpcError;
9696
+ name = "DirectoryBrowseError";
9697
+ /** @param rpcError - Host directory business failure. */
9698
+ constructor(rpcError) {
9699
+ super(`directory browse failed: ${rpcError.code}: ${rpcError.message}`);
9700
+ this.rpcError = rpcError;
9701
+ }
9702
+ };
9703
+ /** Implements Workspace archive and directory UI operations. */
9704
+ var UiWorkspaceService = class extends _deepseek_ai_cordis.Service {
9705
+ directoryPicker;
9706
+ workspaces;
9707
+ sessions;
9708
+ connecting = /* @__PURE__ */ new Map();
9709
+ /**
9710
+ * @param ctx - Client root Context.
9711
+ * @param directoryPicker - the directory-picking Remote namespace.
9712
+ * @param workspaces - pure Workspace Controller.
9713
+ * @param sessions - pure Session Controller.
9714
+ */
9715
+ constructor(ctx, directoryPicker, workspaces, sessions) {
9716
+ super(ctx, "uiWorkspace");
9717
+ this.directoryPicker = directoryPicker;
9718
+ this.workspaces = workspaces;
9719
+ this.sessions = sessions;
9720
+ ctx.effect(() => this.watchNavigation(), "ui-workspace: Workspace navigation policy");
9721
+ }
9722
+ async connectWorkspace(workspaceId) {
9723
+ const workspace = this.workspaces.list.getSnapshot().items.find((item) => item.workspaceId === workspaceId);
9724
+ if (workspace === void 0) throw new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`);
9725
+ const inflight = this.connecting.get(workspaceId);
9726
+ if (inflight !== void 0) return inflight;
9727
+ const archived = this.workspaces.list.getSnapshot().archivedSessionIds;
9728
+ const sessions = this.sessions.list.getSnapshot();
9729
+ for (const id of sessions.ids) {
9730
+ const summary = sessions.byId[id];
9731
+ if (summary !== void 0 && summary.blank && summary.cwd === workspace.path && workspace.sessionIds.includes(summary.id) && !archived.includes(summary.id)) return summary.id;
9732
+ }
9733
+ const attempt$1 = this.sessions.create({ workspaceId }).finally(() => {
9734
+ this.connecting.delete(workspaceId);
9735
+ });
9736
+ this.connecting.set(workspaceId, attempt$1);
9737
+ return attempt$1;
9738
+ }
9739
+ startSession(workspaceId) {
9740
+ const workspace = this.workspaces.list.getSnapshot();
9741
+ const sessions = this.sessions.list.getSnapshot();
9742
+ const current = sessions.current;
9743
+ const currentWorkspaceId = current === void 0 ? void 0 : workspace.items.find((item) => item.sessionIds.includes(current))?.workspaceId;
9744
+ const recent = workspace.phase === "ready" && sessions.phase === "ready" ? recentWorkspace(workspace.items, sessions.byId) : void 0;
9745
+ const target = workspaceId ?? currentWorkspaceId ?? recent;
9746
+ if (target === void 0) {
9747
+ this.sessions.clear();
9748
+ return;
9749
+ }
9750
+ this.connectWorkspace(target).then((sessionId) => {
9751
+ this.sessions.open(sessionId);
9752
+ }, (reason) => {
9753
+ console.warn("new session failed:", reason);
9754
+ });
9755
+ }
9756
+ async archiveSession(sessionId) {
9757
+ await this.workspaces.archiveSession(sessionId);
9758
+ }
9759
+ async pickDirectory() {
9760
+ const result = await this.directoryPicker.pick();
9761
+ if (!result.ok) throw new Error(`directory picker failed: ${result.error.message}`);
9762
+ return result.value;
9763
+ }
9764
+ async listDirectory(path, signal) {
9765
+ const result = await this.directoryPicker.list(path, signal);
9766
+ if (!result.ok) throw new DirectoryBrowseError(result.error);
9767
+ return result.value;
9768
+ }
9769
+ async createDirectory(path, name) {
9770
+ const result = await this.directoryPicker.createDirectory(path, name);
9771
+ if (!result.ok) throw new DirectoryBrowseError(result.error);
9772
+ return result.value;
9773
+ }
9774
+ watchNavigation() {
9775
+ let initial = "waiting";
9776
+ let disposed = false;
9777
+ const reconcile = () => {
9778
+ if (disposed) return;
9779
+ if (this.clearArchivedCurrent()) return;
9780
+ if (initial !== "waiting") return;
9781
+ const workspace = this.workspaces.list.getSnapshot();
9782
+ const sessions = this.sessions.list.getSnapshot();
9783
+ if (workspace.phase !== "ready" || sessions.phase !== "ready") return;
9784
+ if (sessions.current !== void 0) {
9785
+ initial = "done";
9786
+ return;
9787
+ }
9788
+ const target = recentWorkspace(workspace.items, sessions.byId);
9789
+ if (target === void 0) {
9790
+ initial = "done";
9791
+ return;
9792
+ }
9793
+ initial = "connecting";
9794
+ this.connectWorkspace(target).then((sessionId) => {
9795
+ if (disposed) return;
9796
+ if (this.sessions.list.getSnapshot().current === void 0) this.sessions.open(sessionId);
9797
+ initial = "done";
9798
+ }, (reason) => {
9799
+ if (disposed) return;
9800
+ initial = "waiting";
9801
+ console.warn("initial workspace selection failed:", reason);
9802
+ });
9803
+ };
9804
+ const disposeWorkspaces = this.workspaces.list.subscribe(reconcile);
9805
+ const disposeSessions = this.sessions.list.subscribe(reconcile);
9806
+ reconcile();
9807
+ return () => {
9808
+ disposed = true;
9809
+ disposeSessions();
9810
+ disposeWorkspaces();
9811
+ };
9812
+ }
9813
+ /** @returns true when an archived current selection was cleared. */
9814
+ clearArchivedCurrent() {
9815
+ const current = this.sessions.list.getSnapshot().current;
9816
+ if (current === void 0 || !this.workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false;
9817
+ this.sessions.clear();
9818
+ return true;
9819
+ }
9820
+ };
9821
+ /** Stable tie-breaking follows Host Workspace order. */
9822
+ function recentWorkspace(workspaces, sessions) {
9823
+ let selected;
9824
+ let selectedTime = Number.NEGATIVE_INFINITY;
9825
+ for (const workspace of workspaces) {
9826
+ let latest = Number.NEGATIVE_INFINITY;
9827
+ for (const sessionId of workspace.sessionIds) {
9828
+ const session = sessions[sessionId];
9829
+ if (session !== void 0) latest = Math.max(latest, session.updatedAt);
9830
+ }
9831
+ if (latest === Number.NEGATIVE_INFINITY) latest = Date.parse(workspace.createdAt);
9832
+ if (selected === void 0 || latest > selectedTime) {
9833
+ selected = workspace.workspaceId;
9834
+ selectedTime = latest;
9835
+ }
9836
+ }
9837
+ return selected;
9838
+ }
9688
9839
  /**
9689
9840
  * The workspace browser's viewing store: the session-list grouping mode,
9690
9841
  * persisted across reloads. Module level exports the factory only (a
@@ -9699,7 +9850,7 @@ const official = ((require$1) => {
9699
9850
  * @returns the store handle (spec + type + identity + factory in one).
9700
9851
  */
9701
9852
  function createWorkspaceViewStore() {
9702
- return (0, _deepseek_ai_dsh_client_runtime_client.defineStore)({
9853
+ return (0, _deepseek_ai_dsh_client_store.defineStore)({
9703
9854
  init: () => ({
9704
9855
  groupBy: "workspace",
9705
9856
  orderBy: "updated",
@@ -9747,18 +9898,78 @@ const official = ((require$1) => {
9747
9898
  for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
9748
9899
  return n;
9749
9900
  }
9750
- /** Display label for the ungrouped bucket row. */
9751
- const UNGROUPED_LABEL = "Ungrouped";
9901
+ /**
9902
+ * Browser-safe Workspace path and display helpers.
9903
+ * @module @deepseek-ai/dsh-util-workspace-path
9904
+ */
9905
+ /** Whether a path uses a Windows drive or UNC prefix. */
9906
+ function isWindowsStylePath(value) {
9907
+ return /^[A-Za-z]:[/\\]/.test(value) || value.startsWith("\\\\");
9908
+ }
9909
+ /**
9910
+ * Abbreviate a POSIX home directory for display.
9911
+ * @param path - Absolute or already-short display path.
9912
+ * @param home - Host account home; absent skips abbreviation.
9913
+ * @returns `~` or `~/…` for the POSIX home and its descendants, otherwise `path`.
9914
+ */
9915
+ function abbreviateHomePath(path, home) {
9916
+ if (home === void 0 || home === "") return path;
9917
+ if (isWindowsStylePath(path) || isWindowsStylePath(home)) return path;
9918
+ const root = home.replace(/\/+$/, "");
9919
+ if (root === "" || root === "/") return path;
9920
+ if (path.replace(/\/+$/, "") === root) return "~";
9921
+ if (path.startsWith(`${root}/`)) return `~${path.slice(root.length)}`;
9922
+ return path;
9923
+ }
9924
+ /**
9925
+ * Read the final non-empty segment of a Workspace path for display.
9926
+ * Workspace-label surfaces use this helper instead of deriving another basename.
9927
+ * @param path - Workspace directory path using POSIX or Windows separators.
9928
+ * @returns the final segment, or an empty string for a separator-only path.
9929
+ */
9930
+ function workspaceTitleOf(path) {
9931
+ const trimmed = path.replace(/[/\\]+$/, "");
9932
+ const separator = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
9933
+ return trimmed.slice(separator + 1);
9934
+ }
9935
+ /** UI Workspace-owned projection of descendant counts from Session summaries. */
9936
+ /**
9937
+ * Index uninterrupted subagent descendants under each ancestor.
9938
+ * @param summaries - Session summaries keyed by id.
9939
+ * @returns descendant totals keyed by possible parent id.
9940
+ */
9941
+ function indexSubagentDescendants(summaries) {
9942
+ const indexed = /* @__PURE__ */ new Map();
9943
+ for (const descendant of Object.values(summaries)) {
9944
+ if (descendant.origin !== "subagent") continue;
9945
+ const seen = /* @__PURE__ */ new Set();
9946
+ let current = descendant;
9947
+ while (current?.origin === "subagent" && current.parentId !== void 0 && !seen.has(current.id)) {
9948
+ seen.add(current.id);
9949
+ const aggregate = indexed.get(current.parentId);
9950
+ if (aggregate === void 0) indexed.set(current.parentId, {
9951
+ count: 1,
9952
+ runningCount: descendant.running ? 1 : 0
9953
+ });
9954
+ else {
9955
+ aggregate.count += 1;
9956
+ if (descendant.running) aggregate.runningCount += 1;
9957
+ }
9958
+ current = summaries[current.parentId];
9959
+ }
9960
+ }
9961
+ return indexed;
9962
+ }
9752
9963
  /**
9753
9964
  * Directory display label: basename of the path (both separators accepted).
9754
9965
  * Ungrouped-bucket fallback for surfaces without a workspace title.
9755
9966
  * @param cwd - directory path, or undefined for the ungrouped bucket.
9756
- * @returns basename, the raw cwd when it has no basename, or the ungrouped label.
9967
+ * @returns basename, the raw cwd when it has no basename, or an empty ungrouped marker.
9757
9968
  */
9758
9969
  function workspaceLabel(cwd) {
9759
- if (cwd === void 0 || cwd === "") return UNGROUPED_LABEL;
9760
- const base = cwd.replace(/[/\\]+$/, "").split(/[/\\]/).pop();
9761
- return base !== void 0 && base !== "" ? base : cwd;
9970
+ if (cwd === void 0 || cwd === "") return "";
9971
+ const base = workspaceTitleOf(cwd);
9972
+ return base !== "" ? base : cwd;
9762
9973
  }
9763
9974
  /** Recency comparator: newest first, id as the deterministic tiebreak (ids are unique per group). */
9764
9975
  function byRecency(a, b) {
@@ -9780,7 +9991,11 @@ const official = ((require$1) => {
9780
9991
  * and the renderer localizes its display label.
9781
9992
  */
9782
9993
  function sessionTitle(session) {
9783
- return session.blank ? "New Session" : session.displayTitle;
9994
+ return session.blank ? "" : session.displayTitle;
9995
+ }
9996
+ /** The list projection alone owns the best-effort active-Schedule indicator. */
9997
+ function hasActiveSchedule(session) {
9998
+ return (session.projectionValues?.schedule?.length ?? 0) > 0;
9784
9999
  }
9785
10000
  /** Build one group without projecting session lineage into presentation. */
9786
10001
  function buildGroup(key, workspaceId, cwd, createdAt, label, members, order) {
@@ -9835,10 +10050,20 @@ const official = ((require$1) => {
9835
10050
  groups.push(group);
9836
10051
  }
9837
10052
  const stray = list.ids.map((id) => list.byId[id]).filter((s) => s !== void 0 && !accounted.has(s.id) && sessionVisible(s, list.current, archived));
9838
- if (stray.length > 0) groups.push(buildGroup("", void 0, void 0, void 0, UNGROUPED_LABEL, ungroupedOrder === void 0 ? stray : orderedUngrouped(stray, ungroupedOrder), ungroupedOrder === void 0 ? "recency" : "account"));
10053
+ if (stray.length > 0) groups.push(buildGroup("", void 0, void 0, void 0, "", ungroupedOrder === void 0 ? stray : orderedUngrouped(stray, ungroupedOrder), ungroupedOrder === void 0 ? "recency" : "account"));
9839
10054
  return groups;
9840
10055
  }
9841
- function sessionNode(s, descendants) {
10056
+ /** Keep navigation presentation independent from domain-owned interaction objects. */
10057
+ function visiblePendingKind(kind) {
10058
+ switch (kind) {
10059
+ case "approval":
10060
+ case "plan-review":
10061
+ case "question": return kind;
10062
+ default: return;
10063
+ }
10064
+ }
10065
+ function sessionNode(s, descendants, pendingInteractions) {
10066
+ const pendingInteraction = visiblePendingKind(pendingInteractions.get(s.id)?.kind);
9842
10067
  return {
9843
10068
  id: s.id,
9844
10069
  title: sessionTitle(s),
@@ -9846,9 +10071,10 @@ const official = ((require$1) => {
9846
10071
  running: s.running,
9847
10072
  runningSubagentCount: descendants.get(s.id)?.runningCount ?? 0,
9848
10073
  completed: s.completed === true,
10074
+ hasActiveSchedule: hasActiveSchedule(s),
9849
10075
  updatedAt: s.updatedAt,
9850
10076
  ...s.__dshGitWorktree === void 0 ? {} : { __dshGitWorktree: s.__dshGitWorktree },
9851
- ...s.pendingInteraction === void 0 ? {} : { pendingInteraction: s.pendingInteraction }
10077
+ ...pendingInteraction === void 0 ? {} : { pendingInteraction }
9852
10078
  };
9853
10079
  }
9854
10080
  /**
@@ -9862,13 +10088,14 @@ const official = ((require$1) => {
9862
10088
  * @param list - sessions list snapshot (`current` feeds containsCurrent).
9863
10089
  * @param workspaces - real workspaces in stable Host order.
9864
10090
  * @param archivedSessionIds - registry-global archive set.
10091
+ * @param pendingInteractions - pending UI interactions by Session.
9865
10092
  * @param view - local expansion arrays.
9866
10093
  * @returns group sections in render order.
9867
10094
  */
9868
- function deriveGroups(list, workspaces, archivedSessionIds, view) {
10095
+ function deriveGroups(list, workspaces, archivedSessionIds, pendingInteractions, view) {
9869
10096
  const archived = new Set(archivedSessionIds);
9870
10097
  const expandedGroups = new Set(view.expandedGroups);
9871
- const descendants = (0, _deepseek_ai_dsh_client_runtime_client.indexSubagentDescendants)(list.byId);
10098
+ const descendants = indexSubagentDescendants(list.byId);
9872
10099
  const currentGroup = list.current === void 0 ? void 0 : workspaces.find((w) => w.sessionIds.includes(list.current))?.workspaceId ?? "";
9873
10100
  const groups = [];
9874
10101
  for (const g of groupByWorkspace(list, workspaces, archived, view.ungroupedOrder)) {
@@ -9883,7 +10110,7 @@ const official = ((require$1) => {
9883
10110
  sessionCount: g.sessions.length,
9884
10111
  expanded,
9885
10112
  containsCurrent: g.key === currentGroup,
9886
- sessions: expanded ? g.sessions.map((session) => sessionNode(session, descendants)) : []
10113
+ sessions: expanded ? g.sessions.map((session) => sessionNode(session, descendants, pendingInteractions)) : []
9887
10114
  });
9888
10115
  }
9889
10116
  return groups;
@@ -9895,11 +10122,12 @@ const official = ((require$1) => {
9895
10122
  * (see {@link deriveSearchResults}).
9896
10123
  * @param list - sessions list snapshot.
9897
10124
  * @param archivedSessionIds - registry-global archive set.
10125
+ * @param pendingInteractions - pending UI interactions by Session.
9898
10126
  * @returns flat rows in render order.
9899
10127
  */
9900
- function deriveFlat(list, archivedSessionIds) {
10128
+ function deriveFlat(list, archivedSessionIds, pendingInteractions) {
9901
10129
  const archived = new Set(archivedSessionIds);
9902
- const descendants = (0, _deepseek_ai_dsh_client_runtime_client.indexSubagentDescendants)(list.byId);
10130
+ const descendants = indexSubagentDescendants(list.byId);
9903
10131
  const rows = [];
9904
10132
  for (const id of list.ids) {
9905
10133
  const s = list.byId[id];
@@ -9907,7 +10135,7 @@ const official = ((require$1) => {
9907
10135
  rows.push(s);
9908
10136
  }
9909
10137
  rows.sort(byRecency);
9910
- return rows.map((session) => sessionNode(session, descendants));
10138
+ return rows.map((session) => sessionNode(session, descendants, pendingInteractions));
9911
10139
  }
9912
10140
  /**
9913
10141
  * Merge immediate title/Workspace substring matches with ranked Host content
@@ -9917,18 +10145,19 @@ const official = ((require$1) => {
9917
10145
  * @param workspaces - Workspace membership and display labels.
9918
10146
  * @param query - caller text; surrounding whitespace is ignored.
9919
10147
  * @param archivedSessionIds - registry-global archive set (members never match).
10148
+ * @param pendingInteractions - pending UI interactions by Session.
9920
10149
  * @param content - ranked Host content-search page.
9921
10150
  * @param limit - protocol-owned maximum merged row count.
9922
10151
  * @returns bounded deduplicated flat rows and a refine-query hint bit.
9923
10152
  */
9924
- function deriveSearchResults(list, workspaces, query, archivedSessionIds, content, limit) {
10153
+ function deriveSearchResults(list, workspaces, query, archivedSessionIds, pendingInteractions, content, limit) {
9925
10154
  const q = query.trim().toLowerCase();
9926
10155
  if (q === "") return {
9927
10156
  items: [],
9928
10157
  hasMore: false
9929
10158
  };
9930
10159
  const archived = new Set(archivedSessionIds);
9931
- const descendants = (0, _deepseek_ai_dsh_client_runtime_client.indexSubagentDescendants)(list.byId);
10160
+ const descendants = indexSubagentDescendants(list.byId);
9932
10161
  const workspaceBySession = /* @__PURE__ */ new Map();
9933
10162
  for (const workspace of workspaces) for (const sessionId of workspace.sessionIds) if (!workspaceBySession.has(sessionId)) workspaceBySession.set(sessionId, workspace.title);
9934
10163
  const labelOf = (summary) => workspaceBySession.get(summary.id) ?? workspaceLabel(summary.cwd);
@@ -9956,6 +10185,7 @@ const official = ((require$1) => {
9956
10185
  return {
9957
10186
  items: ordered.slice(0, limit).map((summary) => {
9958
10187
  const match = contentBySession.get(summary.id);
10188
+ const pendingInteraction = visiblePendingKind(pendingInteractions.get(summary.id)?.kind);
9959
10189
  return {
9960
10190
  id: summary.id,
9961
10191
  title: sessionTitle(summary),
@@ -9963,52 +10193,16 @@ const official = ((require$1) => {
9963
10193
  running: summary.running,
9964
10194
  runningSubagentCount: descendants.get(summary.id)?.runningCount ?? 0,
9965
10195
  ...summary.__dshGitWorktree === void 0 ? {} : { __dshGitWorktree: summary.__dshGitWorktree },
9966
- ...summary.pendingInteraction === void 0 ? {} : { pendingInteraction: summary.pendingInteraction },
10196
+ ...pendingInteraction === void 0 ? {} : { pendingInteraction },
9967
10197
  completed: summary.completed === true,
10198
+ hasActiveSchedule: hasActiveSchedule(summary),
9968
10199
  ...match === void 0 ? {} : { snippet: match.snippet }
9969
10200
  };
9970
10201
  }),
9971
10202
  hasMore: content.hasMore || ordered.length > limit
9972
10203
  };
9973
10204
  }
9974
- /**
9975
- * Compact relative time for session rows, as a structured bucket the
9976
- * renderer localizes ("now"/"5min"/"3h"/"2d"/"4mo"/"1y" in en).
9977
- * @param updatedAt - epoch ms of the session's last activity.
9978
- * @param now - current epoch ms (injected for pure rendering).
9979
- * @returns the row's trailing time bucket and magnitude.
9980
- */
9981
- function relativeTime(updatedAt, now) {
9982
- const MIN = 6e4;
9983
- const HOUR = 36e5;
9984
- const DAY = 864e5;
9985
- const diff = Math.max(0, now - updatedAt);
9986
- if (diff < MIN) return {
9987
- unit: "now",
9988
- n: 0
9989
- };
9990
- if (diff < HOUR) return {
9991
- unit: "minutes",
9992
- n: Math.floor(diff / MIN)
9993
- };
9994
- if (diff < DAY) return {
9995
- unit: "hours",
9996
- n: Math.floor(diff / HOUR)
9997
- };
9998
- if (diff < 30 * DAY) return {
9999
- unit: "days",
10000
- n: Math.floor(diff / DAY)
10001
- };
10002
- if (diff < 365 * DAY) return {
10003
- unit: "months",
10004
- n: Math.floor(diff / (30 * DAY))
10005
- };
10006
- return {
10007
- unit: "years",
10008
- n: Math.floor(diff / (365 * DAY))
10009
- };
10010
- }
10011
- const css$2 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:6px;padding:0 8px;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;cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;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;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_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{height:32px;animation:YDXeBa_row-in .15s var(--ds-ease-in-out);gap:0}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_flatSessionRowWithoutStatus .YDXeBa_title{margin-left:0}@keyframes YDXeBa_row-in{0%{opacity:0}}.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:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;border-radius:4px;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.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:12px;line-height:20px}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:12px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time{display:none}.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_iconButton{cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:4px;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_sessionRow,.YDXeBa_arrow{transition:none;animation:none}}";
10205
+ const css$2 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:6px;padding:0 8px;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;cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;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_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{height:32px;animation:YDXeBa_row-in .15s var(--ds-ease-in-out);gap:0}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_flatSessionRowWithoutStatus .YDXeBa_title{margin-left:0}@keyframes YDXeBa_row-in{0%{opacity:0}}.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);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;border-radius:4px;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.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:12px;line-height:20px}.YDXeBa_scheduleIndicator{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;margin-right:6px;display:inline-flex}.YDXeBa_searchScheduleIndicator{margin-left:4px;margin-right:0}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:12px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time{display:none}.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_iconButton{cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:4px;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_sessionRow,.YDXeBa_arrow{transition:none;animation:none}}";
10012
10206
  const tagId$2 = "@deepseek-ai/dsh-client-ui-workspace/Rows.module.css";
10013
10207
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
10014
10208
  const tag = document.createElement("style");
@@ -10040,12 +10234,14 @@ const official = ((require$1) => {
10040
10234
  "renameInput": "YDXeBa_renameInput",
10041
10235
  "row-in": "YDXeBa_row-in",
10042
10236
  "rowActions": "YDXeBa_rowActions",
10237
+ "scheduleIndicator": "YDXeBa_scheduleIndicator",
10043
10238
  "searchResultHeading": "YDXeBa_searchResultHeading",
10044
10239
  "searchResultMeta": "YDXeBa_searchResultMeta",
10045
10240
  "searchResultRow": "YDXeBa_searchResultRow",
10046
10241
  "searchResultSnippet": "YDXeBa_searchResultSnippet",
10047
10242
  "searchResultTitle": "YDXeBa_searchResultTitle",
10048
10243
  "searchResultWorkspace": "YDXeBa_searchResultWorkspace",
10244
+ "searchScheduleIndicator": "YDXeBa_searchScheduleIndicator",
10049
10245
  "selected": "YDXeBa_selected",
10050
10246
  "sessionRow": "YDXeBa_sessionRow",
10051
10247
  "slot": "YDXeBa_slot",
@@ -10066,12 +10262,12 @@ const official = ((require$1) => {
10066
10262
  }
10067
10263
  /** Localized compact relative time ("刚刚"/"5分钟" in zh, "now"/"5min" in en). */
10068
10264
  function timeLabel(updatedAt, now, t) {
10069
- const { unit, n } = relativeTime(updatedAt, now);
10265
+ const { unit, n } = (0, _deepseek_ai_dsh_client_ui_primitives.relativeTime)(updatedAt, now);
10070
10266
  return unit === "now" ? t("time.now") : t(`time.${unit}`, { n });
10071
10267
  }
10072
10268
  /** Hover-card variant: distances wrap in the ago template; the now bucket stays bare (no "now ago"). */
10073
10269
  function hoverTimeLabel(updatedAt, now, t) {
10074
- const { unit, n } = relativeTime(updatedAt, now);
10270
+ const { unit, n } = (0, _deepseek_ai_dsh_client_ui_primitives.relativeTime)(updatedAt, now);
10075
10271
  return unit === "now" ? t("time.now") : t("time.ago", { t: t(`time.${unit}`, { n }) });
10076
10272
  }
10077
10273
  /**
@@ -10180,7 +10376,7 @@ const official = ((require$1) => {
10180
10376
  items: workspaceMenuItems,
10181
10377
  onSelect: (id) => {
10182
10378
  setMenuOpen(false);
10183
- /* v8 ignore next -- workspaceMenuItems carries exactly these two rows today. */
10379
+ /* v8 ignore next -- Menu can emit only the rename and delete rows supplied above. */
10184
10380
  if (id !== "rename" && id !== "delete") return;
10185
10381
  if (id === "rename") actions.rename();
10186
10382
  else actions.delete();
@@ -10215,7 +10411,7 @@ const official = ((require$1) => {
10215
10411
  anchor: ownRow,
10216
10412
  content: (0, react_jsx_runtime$1.jsx)(WorkspaceHoverContent, {
10217
10413
  label: row.label,
10218
- cwd: row.cwd === void 0 ? void 0 : (0, _deepseek_ai_dsh_client_runtime_client.abbreviateHomePath)(row.cwd, home),
10414
+ cwd: row.cwd === void 0 ? void 0 : abbreviateHomePath(row.cwd, home),
10219
10415
  createdAt: row.createdAt,
10220
10416
  t
10221
10417
  }),
@@ -10286,6 +10482,17 @@ const official = ((require$1) => {
10286
10482
  children: status.label
10287
10483
  }, status.label))] });
10288
10484
  }
10485
+ /** Non-interactive active-Schedule marker; the enclosing row remains the only action. */
10486
+ function ActiveScheduleIndicator({ t, search = false }) {
10487
+ const label = t("schedule.active");
10488
+ return (0, react_jsx_runtime$1.jsx)("span", {
10489
+ className: clsx(Rows_module_css_default.scheduleIndicator, search && Rows_module_css_default.searchScheduleIndicator),
10490
+ role: "img",
10491
+ "aria-label": label,
10492
+ title: label,
10493
+ children: (0, react_jsx_runtime$1.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconAlarmClockOutline16, {})
10494
+ });
10495
+ }
10289
10496
  function managedWorktreeDecoration(node, t) {
10290
10497
  const value = node.__dshGitWorktree;
10291
10498
  if (value?.kind !== "managed-worktree" || typeof value.state !== "string") return void 0;
@@ -10373,13 +10580,17 @@ const official = ((require$1) => {
10373
10580
  (0, react_jsx_runtime$1.jsx)("span", {
10374
10581
  className: Rows_module_css_default.searchResultTitle,
10375
10582
  children: result.title
10583
+ }),
10584
+ result.hasActiveSchedule && (0, react_jsx_runtime$1.jsx)(ActiveScheduleIndicator, {
10585
+ t,
10586
+ search: true
10376
10587
  })
10377
10588
  ]
10378
10589
  }), (0, react_jsx_runtime$1.jsxs)("span", {
10379
10590
  className: Rows_module_css_default.searchResultMeta,
10380
10591
  children: [(0, react_jsx_runtime$1.jsx)("span", {
10381
10592
  className: Rows_module_css_default.searchResultWorkspace,
10382
- children: result.workspace
10593
+ children: result.workspace || t("group.ungrouped")
10383
10594
  }), result.snippet !== void 0 && (0, react_jsx_runtime$1.jsx)("span", {
10384
10595
  className: Rows_module_css_default.searchResultSnippet,
10385
10596
  children: result.snippet
@@ -10468,6 +10679,7 @@ const official = ((require$1) => {
10468
10679
  className: Rows_module_css_default.title,
10469
10680
  children: title
10470
10681
  }),
10682
+ row.hasActiveSchedule && (0, react_jsx_runtime$1.jsx)(ActiveScheduleIndicator, { t }),
10471
10683
  !row.blank && (0, react_jsx_runtime$1.jsx)("span", {
10472
10684
  className: Rows_module_css_default.time,
10473
10685
  children: timeLabel(row.updatedAt, now, t)
@@ -10679,7 +10891,7 @@ const official = ((require$1) => {
10679
10891
  onClose
10680
10892
  });
10681
10893
  }
10682
- const css = ".qDHVXG_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:8px;--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}.qDHVXG_root.qDHVXG_rail{padding-right:0}.qDHVXG_iconButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_sectionHeader{box-sizing:border-box;height:36px;color:var(--dsw-alias-label-tertiary);border-radius:12px;flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;display:flex;overflow:hidden}.qDHVXG_root:not(.qDHVXG_rail) .qDHVXG_sectionHeader{margin-top:2px;margin-right:-4px}.qDHVXG_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}.qDHVXG_sectionLabelHidden{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transition-delay:0s,0s,0s,0s,.18s;transform:translate(-4px)}.qDHVXG_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}.qDHVXG_searchSlotExpanded{max-width:100%;padding-left:0}.qDHVXG_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}.qDHVXG_headerActionsHidden{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transition-delay:0s,0s,0s,.18s;transform:translate(4px)}.qDHVXG_search{box-sizing:border-box;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;border-radius:50%;flex:none;align-items:center;gap:0;margin:0;padding:0;display:flex;overflow:hidden}.qDHVXG_searchExpanded{border:1px solid var(--dsw-alias-border-l2);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;border-radius:10px;margin-inline:-2px;padding:0 4px 0 0}.qDHVXG_searchButton{cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_searchExpanded .qDHVXG_searchButton{width:28px;height:30px}.qDHVXG_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_searchExpanded .qDHVXG_searchButton:hover{background:0 0}.qDHVXG_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}.qDHVXG_searchExpanded .qDHVXG_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.qDHVXG_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.qDHVXG_clearButton{cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_rail .qDHVXG_sectionHeader{justify-content:flex-start;gap:0;margin-bottom:12px;padding-left:0}.qDHVXG_rail .qDHVXG_headerActions{max-width:none}.qDHVXG_rail .qDHVXG_iconButton{width:36px;height:36px;color:var(--dsw-alias-label-primary)}.qDHVXG_rail .qDHVXG_search{background:0 0;border-color:#0000;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.qDHVXG_rail .qDHVXG_searchButton{width:36px;height:36px;color:var(--dsw-alias-label-primary)}.qDHVXG_rail .qDHVXG_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_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}.qDHVXG_rail .qDHVXG_listArea{margin-left:0;margin-right:0;padding-left:0}.qDHVXG_treeBody{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.qDHVXG_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}.qDHVXG_wide{animation:qDHVXG_wide-in .2s var(--ds-ease-in-out)}@keyframes qDHVXG_wide-in{0%{opacity:0}}.qDHVXG_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}.qDHVXG_flatList>*+*,.qDHVXG_searchTree>[role=treeitem]+[role=treeitem],.qDHVXG_groupSection>*+*{margin-top:2px}.qDHVXG_searchStatus,.qDHVXG_searchWarning{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.qDHVXG_searchWarning{color:var(--dsw-alias-label-secondary)}.qDHVXG_groupSection{position:relative}.qDHVXG_groupSection+.qDHVXG_groupSection{margin-top:4px}.qDHVXG_listTopDropIndicator,.qDHVXG_workspaceDropBefore:before,.qDHVXG_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}.qDHVXG_listTopDropIndicator{top:-8px;left:0;right:var(--dsh-session-list-edge-inset)}.qDHVXG_listTopDropActive>.qDHVXG_workspaceDropBefore:first-child:before{display:none}.qDHVXG_workspaceDropBefore:before{top:-8px}.qDHVXG_workspaceDropAfter:after{bottom:-8px}.qDHVXG_sessionOverflowButton{cursor:pointer;text-align:left;width:100%;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:8px;padding:0 12px 0 28px;font-size:12px}.qDHVXG_groupSection>.qDHVXG_sessionOverflowButton{margin-top:0}.qDHVXG_sessionOverflowButton:hover{color:var(--dsw-alias-label-secondary);background:0 0}.qDHVXG_empty{color:var(--dsw-alias-label-tertiary);padding:16px 12px;font-size:13px}.qDHVXG_renameInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:22px;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.qDHVXG_renameInput:disabled{color:var(--dsw-alias-label-dimmed)}.qDHVXG_renameError{color:var(--dsw-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}.qDHVXG_deleteAction:not(:disabled){color:var(--dsw-alias-state-error-primary)}.qDHVXG_deleteStatus{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}@media (prefers-reduced-motion:reduce){.qDHVXG_wide{animation:none}.qDHVXG_search,.qDHVXG_sectionLabel,.qDHVXG_searchSlot,.qDHVXG_searchInput,.qDHVXG_headerActions{transition:none}}";
10894
+ const css = ".bhn1Oq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:8px;--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{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_sectionHeader{box-sizing:border-box;height:36px;color:var(--dsw-alias-label-tertiary);border-radius:12px;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;corner-shape:round;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;border-radius:50%;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);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;border-radius:10px;margin-inline:-2px;padding:0 4px 0 0}.bhn1Oq_searchButton{corner-shape:round;cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;border-radius:50%;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{corner-shape:round;cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;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{width:36px;height:36px;color:var(--dsw-alias-label-primary)}.bhn1Oq_rail .bhn1Oq_search{background:0 0;border-color:#0000;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.bhn1Oq_rail .bhn1Oq_searchButton{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}.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,.bhn1Oq_searchWarning{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.bhn1Oq_searchWarning{color:var(--dsw-alias-label-secondary)}.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{cursor:pointer;text-align:left;width:100%;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:8px;padding:0 12px 0 28px;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_renameInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:22px;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}@media (prefers-reduced-motion:reduce){.bhn1Oq_wide{animation:none}.bhn1Oq_search,.bhn1Oq_sectionLabel,.bhn1Oq_searchSlot,.bhn1Oq_searchInput,.bhn1Oq_headerActions{transition:none}}";
10683
10895
  const tagId = "@deepseek-ai/dsh-client-ui-workspace/WorkspaceBrowser.module.css";
10684
10896
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
10685
10897
  const tag = document.createElement("style");
@@ -10689,42 +10901,42 @@ const official = ((require$1) => {
10689
10901
  document.head.appendChild(tag);
10690
10902
  }
10691
10903
  var WorkspaceBrowser_module_css_default = {
10692
- "clearButton": "qDHVXG_clearButton",
10693
- "deleteAction": "qDHVXG_deleteAction",
10694
- "deleteStatus": "qDHVXG_deleteStatus",
10695
- "empty": "qDHVXG_empty",
10696
- "fade": "qDHVXG_fade",
10697
- "flatList": "qDHVXG_flatList",
10698
- "groupSection": "qDHVXG_groupSection",
10699
- "headerActions": "qDHVXG_headerActions",
10700
- "headerActionsHidden": "qDHVXG_headerActionsHidden",
10701
- "iconButton": "qDHVXG_iconButton",
10702
- "list": "qDHVXG_list",
10703
- "listArea": "qDHVXG_listArea",
10704
- "listTopDropActive": "qDHVXG_listTopDropActive",
10705
- "listTopDropIndicator": "qDHVXG_listTopDropIndicator",
10706
- "rail": "qDHVXG_rail",
10707
- "renameError": "qDHVXG_renameError",
10708
- "renameInput": "qDHVXG_renameInput",
10709
- "root": "qDHVXG_root",
10710
- "search": "qDHVXG_search",
10711
- "searchButton": "qDHVXG_searchButton",
10712
- "searchExpanded": "qDHVXG_searchExpanded",
10713
- "searchInput": "qDHVXG_searchInput",
10714
- "searchSlot": "qDHVXG_searchSlot",
10715
- "searchSlotExpanded": "qDHVXG_searchSlotExpanded",
10716
- "searchStatus": "qDHVXG_searchStatus",
10717
- "searchTree": "qDHVXG_searchTree",
10718
- "searchWarning": "qDHVXG_searchWarning",
10719
- "sectionHeader": "qDHVXG_sectionHeader",
10720
- "sectionLabel": "qDHVXG_sectionLabel",
10721
- "sectionLabelHidden": "qDHVXG_sectionLabelHidden",
10722
- "sessionOverflowButton": "qDHVXG_sessionOverflowButton",
10723
- "treeBody": "qDHVXG_treeBody",
10724
- "wide": "qDHVXG_wide",
10725
- "wide-in": "qDHVXG_wide-in",
10726
- "workspaceDropAfter": "qDHVXG_workspaceDropAfter",
10727
- "workspaceDropBefore": "qDHVXG_workspaceDropBefore"
10904
+ "clearButton": "bhn1Oq_clearButton",
10905
+ "deleteAction": "bhn1Oq_deleteAction",
10906
+ "deleteStatus": "bhn1Oq_deleteStatus",
10907
+ "empty": "bhn1Oq_empty",
10908
+ "fade": "bhn1Oq_fade",
10909
+ "flatList": "bhn1Oq_flatList",
10910
+ "groupSection": "bhn1Oq_groupSection",
10911
+ "headerActions": "bhn1Oq_headerActions",
10912
+ "headerActionsHidden": "bhn1Oq_headerActionsHidden",
10913
+ "iconButton": "bhn1Oq_iconButton",
10914
+ "list": "bhn1Oq_list",
10915
+ "listArea": "bhn1Oq_listArea",
10916
+ "listTopDropActive": "bhn1Oq_listTopDropActive",
10917
+ "listTopDropIndicator": "bhn1Oq_listTopDropIndicator",
10918
+ "rail": "bhn1Oq_rail",
10919
+ "renameError": "bhn1Oq_renameError",
10920
+ "renameInput": "bhn1Oq_renameInput",
10921
+ "root": "bhn1Oq_root",
10922
+ "search": "bhn1Oq_search",
10923
+ "searchButton": "bhn1Oq_searchButton",
10924
+ "searchExpanded": "bhn1Oq_searchExpanded",
10925
+ "searchInput": "bhn1Oq_searchInput",
10926
+ "searchSlot": "bhn1Oq_searchSlot",
10927
+ "searchSlotExpanded": "bhn1Oq_searchSlotExpanded",
10928
+ "searchStatus": "bhn1Oq_searchStatus",
10929
+ "searchTree": "bhn1Oq_searchTree",
10930
+ "searchWarning": "bhn1Oq_searchWarning",
10931
+ "sectionHeader": "bhn1Oq_sectionHeader",
10932
+ "sectionLabel": "bhn1Oq_sectionLabel",
10933
+ "sectionLabelHidden": "bhn1Oq_sectionLabelHidden",
10934
+ "sessionOverflowButton": "bhn1Oq_sessionOverflowButton",
10935
+ "treeBody": "bhn1Oq_treeBody",
10936
+ "wide": "bhn1Oq_wide",
10937
+ "wide-in": "bhn1Oq_wide-in",
10938
+ "workspaceDropAfter": "bhn1Oq_workspaceDropAfter",
10939
+ "workspaceDropBefore": "bhn1Oq_workspaceDropBefore"
10728
10940
  };
10729
10941
  /**
10730
10942
  * The workspace/session browsing region filling the sidebar shell's
@@ -10748,6 +10960,20 @@ const official = ((require$1) => {
10748
10960
  const SEARCH_QUERY_MAX_CODE_UNITS = 500;
10749
10961
  /** Session rows visible per Workspace before the local overflow control. */
10750
10962
  const COLLAPSED_SESSION_LIMIT = 5;
10963
+ /** Fold one Workspace without charging its provisional New Session against the ordinary-row limit. */
10964
+ function collapsedSessionRows(sessions) {
10965
+ let ordinaryCount = 0;
10966
+ const rows = sessions.filter((session) => {
10967
+ if (session.blank) return true;
10968
+ if (ordinaryCount >= COLLAPSED_SESSION_LIMIT) return false;
10969
+ ordinaryCount += 1;
10970
+ return true;
10971
+ });
10972
+ return {
10973
+ rows,
10974
+ hiddenCount: sessions.length - rows.length
10975
+ };
10976
+ }
10751
10977
  /** Keep controlled input and RPC payload inside the session.search wire contract. */
10752
10978
  function sanitizeSearchQuery(value) {
10753
10979
  const withoutNul = value.replaceAll("\0", "");
@@ -10908,8 +11134,9 @@ const official = ((require$1) => {
10908
11134
  return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
10909
11135
  }
10910
11136
  /** The scrolling session tree; unmounting drops the sessions subscription and expand-all state. */
10911
- function SessionTree({ useSessions, startSession, open, forkSession, workspaces, archivedSessionIds, onRenameRequest, onDeleteRequest, onSessionRename, onSessionArchive, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, home, t }) {
11137
+ function SessionTree({ useSessions, useSessionPendingInteraction, startSession, open, forkSession, workspaces, archivedSessionIds, onRenameRequest, onDeleteRequest, onSessionRename, onSessionArchive, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, home, t }) {
10912
11138
  const list = useSessions((s) => s);
11139
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
10913
11140
  const current = list.current;
10914
11141
  const [expandedSessionGroups, setExpandedSessionGroups] = (0, react$1.useState)([]);
10915
11142
  const [drag, setDrag] = (0, react$1.useState)(null);
@@ -10976,13 +11203,14 @@ const official = ((require$1) => {
10976
11203
  });
10977
11204
  }, [sessionOrderByAccount, workspaces]);
10978
11205
  const orderedUngroupedSessionIds = (0, react$1.useMemo)(() => reconciledSessionOrder(ungroupedSessionIds, sessionOrderByAccount[""]), [sessionOrderByAccount, ungroupedSessionIds]);
10979
- const groups = (0, react$1.useMemo)(() => deriveGroups(list, orderedWorkspaces, archivedSessionIds, {
11206
+ const groups = (0, react$1.useMemo)(() => deriveGroups(list, orderedWorkspaces, archivedSessionIds, pendingInteractions, {
10980
11207
  expandedGroups,
10981
11208
  ...sessionOrderByAccount[""] === void 0 ? {} : { ungroupedOrder: sessionOrderByAccount[""] }
10982
11209
  }), [
10983
11210
  list,
10984
11211
  orderedWorkspaces,
10985
11212
  archivedSessionIds,
11213
+ pendingInteractions,
10986
11214
  expandedGroups,
10987
11215
  sessionOrderByAccount
10988
11216
  ]);
@@ -10993,18 +11221,40 @@ const official = ((require$1) => {
10993
11221
  setDrag(null);
10994
11222
  const group = groups.find((candidate) => candidate.key === activeDrag.accountKey);
10995
11223
  if (group === void 0) return;
10996
- const targetIndex = group.sessions.findIndex((session) => session.id === over.id);
11224
+ const sessionsExpanded = expandedSessionGroups.includes(group.key);
11225
+ const renderedSessions = sessionsExpanded ? group.sessions : collapsedSessionRows(group.sessions).rows;
11226
+ const targetIndex = renderedSessions.findIndex((session) => session.id === over.id);
10997
11227
  if (targetIndex === -1) return;
10998
- const anchor = over.half === "before" ? over.id : group.sessions[targetIndex + 1]?.id;
10999
- if (anchor === activeDrag.sessionId) return;
11000
- const sourceIndex = group.sessions.findIndex((session) => session.id === activeDrag.sessionId);
11001
- const anchorIndex = anchor === void 0 ? group.sessions.length : group.sessions.findIndex((session) => session.id === anchor);
11002
- if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
11228
+ const sourceIndex = renderedSessions.findIndex((session) => session.id === activeDrag.sessionId);
11229
+ if (over.id === activeDrag.sessionId) return;
11230
+ const withoutSource = renderedSessions.filter((session) => session.id !== activeDrag.sessionId);
11231
+ const targetWithoutSourceIndex = withoutSource.findIndex((session) => session.id === over.id);
11232
+ if (targetWithoutSourceIndex === -1) return;
11233
+ const visibleInsertAt = over.half === "before" ? targetWithoutSourceIndex : targetWithoutSourceIndex + 1;
11234
+ if (sourceIndex !== -1 && visibleInsertAt === sourceIndex) return;
11003
11235
  const accountSessionIds = activeDrag.accountKey === "" ? orderedUngroupedSessionIds : orderedWorkspaces.find((workspace) => workspace.workspaceId === activeDrag.accountKey)?.sessionIds;
11004
11236
  if (accountSessionIds === void 0) return;
11005
11237
  const nextOrder = accountSessionIds.filter((id) => id !== activeDrag.sessionId);
11238
+ let anchor;
11239
+ if (sessionsExpanded) anchor = over.half === "before" ? over.id : renderedSessions[targetIndex + 1]?.id;
11240
+ else {
11241
+ const previousVisible = withoutSource[visibleInsertAt - 1]?.id;
11242
+ if (previousVisible === void 0) anchor = nextOrder[0];
11243
+ else {
11244
+ const previousIndex = nextOrder.indexOf(previousVisible);
11245
+ if (previousIndex === -1) return;
11246
+ anchor = nextOrder[previousIndex + 1];
11247
+ }
11248
+ }
11006
11249
  const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
11007
11250
  nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
11251
+ if (!sessionsExpanded && sourceIndex !== -1) {
11252
+ const nodes = new Map(group.sessions.map((node) => [node.id, node]));
11253
+ if (!collapsedSessionRows(nextOrder.flatMap((id) => {
11254
+ const node = nodes.get(id);
11255
+ return node === void 0 ? [] : [node];
11256
+ })).rows.some((node) => node.id === activeDrag.sessionId)) return;
11257
+ }
11008
11258
  setSessionOrder(activeDrag.accountKey, nextOrder.map((id) => id));
11009
11259
  if (orderBy === "updated" || activeDrag.accountKey === "") return;
11010
11260
  insertSessionBefore(activeDrag.accountKey, activeDrag.sessionId, anchor).catch((reason) => {
@@ -11043,6 +11293,8 @@ const official = ((require$1) => {
11043
11293
  children: t("empty.none")
11044
11294
  }), groups.map((group) => {
11045
11295
  const workspaceId = group.workspaceId;
11296
+ const collapsed = collapsedSessionRows(group.sessions);
11297
+ const sessionsExpanded = expandedSessionGroups.includes(group.key);
11046
11298
  const workspaceMarker = workspaceId !== void 0 && workspaceDrag?.over?.id === workspaceId ? workspaceDrag.over.half : null;
11047
11299
  const workspaceDragProps = workspaceId === void 0 ? void 0 : {
11048
11300
  start: () => {
@@ -11112,7 +11364,7 @@ const official = ((require$1) => {
11112
11364
  }
11113
11365
  }
11114
11366
  }),
11115
- (expandedSessionGroups.includes(group.key) ? group.sessions : group.sessions.slice(0, COLLAPSED_SESSION_LIMIT)).map((node) => {
11367
+ (sessionsExpanded ? group.sessions : collapsed.rows).map((node) => {
11116
11368
  const sameGroupDrag = drag !== null && drag.accountKey === group.key;
11117
11369
  return (0, react_jsx_runtime$1.jsx)(SessionNodeItem, {
11118
11370
  node,
@@ -11160,14 +11412,14 @@ const official = ((require$1) => {
11160
11412
  t
11161
11413
  }, node.id);
11162
11414
  }),
11163
- group.sessions.length > COLLAPSED_SESSION_LIMIT && (0, react_jsx_runtime$1.jsx)("button", {
11415
+ collapsed.hiddenCount > 0 && (0, react_jsx_runtime$1.jsx)("button", {
11164
11416
  type: "button",
11165
11417
  className: WorkspaceBrowser_module_css_default.sessionOverflowButton,
11166
- "aria-expanded": expandedSessionGroups.includes(group.key),
11418
+ "aria-expanded": sessionsExpanded,
11167
11419
  onClick: () => {
11168
11420
  setExpandedSessionGroups((keys) => toggled(keys, group.key));
11169
11421
  },
11170
- children: expandedSessionGroups.includes(group.key) ? t("sessions.collapse") : t("sessions.expand", { n: group.sessions.length - COLLAPSED_SESSION_LIMIT })
11422
+ children: sessionsExpanded ? t("sessions.collapse") : t("sessions.expand", { n: collapsed.hiddenCount })
11171
11423
  })
11172
11424
  ]
11173
11425
  }, group.key);
@@ -11178,9 +11430,14 @@ const official = ((require$1) => {
11178
11430
  });
11179
11431
  }
11180
11432
  /** The flat "In one list" body: every session is one draggable top-level row. */
11181
- function FlatList({ useSessions, open, forkSession, onSessionRename, onSessionArchive, archivedSessionIds, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
11433
+ function FlatList({ useSessions, useSessionPendingInteraction, open, forkSession, onSessionRename, onSessionArchive, archivedSessionIds, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
11182
11434
  const list = useSessions((s) => s);
11183
- const baseRows = (0, react$1.useMemo)(() => deriveFlat(list, archivedSessionIds), [list, archivedSessionIds]);
11435
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
11436
+ const baseRows = (0, react$1.useMemo)(() => deriveFlat(list, archivedSessionIds, pendingInteractions), [
11437
+ list,
11438
+ archivedSessionIds,
11439
+ pendingInteractions
11440
+ ]);
11184
11441
  const sessionIds = (0, react$1.useMemo)(() => baseRows.map((row) => row.id), [baseRows]);
11185
11442
  const previousOrderBy = (0, react$1.useRef)(orderBy);
11186
11443
  (0, react$1.useEffect)(() => {
@@ -11296,19 +11553,21 @@ const official = ((require$1) => {
11296
11553
  });
11297
11554
  }
11298
11555
  /** Flat search body: local metadata matches plus the current Host result page. */
11299
- function SearchResults({ useSessions, open, workspaces, archivedSessionIds, query, remote, resultLimit, t }) {
11556
+ function SearchResults({ useSessions, useSessionPendingInteraction, open, workspaces, archivedSessionIds, query, remote, resultLimit, t }) {
11300
11557
  const list = useSessions((s) => s);
11558
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
11301
11559
  const currentRemote = remote.query === query ? remote : {
11302
11560
  query,
11303
11561
  status: "loading",
11304
11562
  items: [],
11305
11563
  hasMore: false
11306
11564
  };
11307
- const results = (0, react$1.useMemo)(() => deriveSearchResults(list, workspaces, query, archivedSessionIds, currentRemote, resultLimit), [
11565
+ const results = (0, react$1.useMemo)(() => deriveSearchResults(list, workspaces, query, archivedSessionIds, pendingInteractions, currentRemote, resultLimit), [
11308
11566
  list,
11309
11567
  workspaces,
11310
11568
  query,
11311
11569
  archivedSessionIds,
11570
+ pendingInteractions,
11312
11571
  currentRemote,
11313
11572
  resultLimit
11314
11573
  ]);
@@ -11357,8 +11616,8 @@ const official = ((require$1) => {
11357
11616
  * @param props - composed slot props (shell owner share + store + injected actions).
11358
11617
  * @returns the region element tree.
11359
11618
  */
11360
- function WorkspaceBrowser({ wide, expandSidebar, useSessions, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostDescription, renderSlot, t }) {
11361
- const home = useHostDescription((description) => description?.home);
11619
+ function WorkspaceBrowser({ wide, expandSidebar, useSessions, useSessionPendingInteraction, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostInfo, renderSlot, t }) {
11620
+ const home = useHostInfo((info) => info.home);
11362
11621
  const workspaces = useWorkspaces((state) => state.items);
11363
11622
  const workspacePhase = useWorkspaces((state) => state.phase);
11364
11623
  const archivedSessionIds = useWorkspaces((state) => state.archivedSessionIds);
@@ -11379,7 +11638,8 @@ const official = ((require$1) => {
11379
11638
  promotedBlank.current = void 0;
11380
11639
  return;
11381
11640
  }
11382
- if (promotedBlank.current?.sessionId === currentBlankSessionId && promotedBlank.current.accountKey === currentBlankAccount) return;
11641
+ const promoted = promotedBlank.current;
11642
+ if (promoted !== void 0 && promoted.sessionId === currentBlankSessionId && promoted.accountKey === currentBlankAccount) return;
11383
11643
  promotedBlank.current = {
11384
11644
  sessionId: currentBlankSessionId,
11385
11645
  accountKey: currentBlankAccount
@@ -11725,6 +11985,7 @@ const official = ((require$1) => {
11725
11985
  className: WorkspaceBrowser_module_css_default.listArea,
11726
11986
  children: wide && (normalizedQuery !== "" ? (0, react_jsx_runtime$1.jsx)(SearchResults, {
11727
11987
  useSessions,
11988
+ useSessionPendingInteraction,
11728
11989
  open,
11729
11990
  workspaces,
11730
11991
  archivedSessionIds,
@@ -11734,6 +11995,7 @@ const official = ((require$1) => {
11734
11995
  t
11735
11996
  }) : groupBy === "flat" ? (0, react_jsx_runtime$1.jsx)(FlatList, {
11736
11997
  useSessions,
11998
+ useSessionPendingInteraction,
11737
11999
  open,
11738
12000
  forkSession,
11739
12001
  onSessionRename,
@@ -11747,6 +12009,7 @@ const official = ((require$1) => {
11747
12009
  t
11748
12010
  }) : (0, react_jsx_runtime$1.jsx)(SessionTree, {
11749
12011
  useSessions,
12012
+ useSessionPendingInteraction,
11750
12013
  onSessionRename,
11751
12014
  onSessionArchive,
11752
12015
  forkSession,
@@ -11982,6 +12245,7 @@ const official = ((require$1) => {
11982
12245
  "status.planReview": "计划待审",
11983
12246
  "status.waitingAnswer": "等待回答",
11984
12247
  "status.completed": "已完成",
12248
+ "schedule.active": "有活动定时任务",
11985
12249
  "hover.created": "创建于 {time}",
11986
12250
  "hover.copied": "已复制",
11987
12251
  "date.ymd": "{y}年{m}月{d}日",
@@ -12055,6 +12319,7 @@ const official = ((require$1) => {
12055
12319
  "status.planReview": "Plan awaiting review",
12056
12320
  "status.waitingAnswer": "Waiting for answer",
12057
12321
  "status.completed": "Completed",
12322
+ "schedule.active": "Has active scheduled task",
12058
12323
  "hover.created": "Created {time}",
12059
12324
  "hover.copied": "Copied",
12060
12325
  "date.ymd": "{y}-{m}-{d}",
@@ -12081,7 +12346,8 @@ const official = ((require$1) => {
12081
12346
  "sessions",
12082
12347
  "workspaces",
12083
12348
  "locale",
12084
- "connection"
12349
+ "remote",
12350
+ "remote.directoryPicker"
12085
12351
  ];
12086
12352
  /**
12087
12353
  * Register the browser and picker once their slot declarations are on the
@@ -12090,13 +12356,16 @@ const official = ((require$1) => {
12090
12356
  * @param ctx - client root context.
12091
12357
  */
12092
12358
  function apply$3(ctx) {
12093
- const hostDescription = ctx.get("connection").hostDescription;
12359
+ const sessions = ctx.get("sessions");
12360
+ const workspaces = ctx.get("workspaces");
12361
+ const uiWorkspace = new UiWorkspaceService(ctx, ctx.remote.directoryPicker, workspaces, sessions);
12362
+ ctx.slots.provideRoot({ hooks: { workspaces: workspaces.list } });
12094
12363
  ctx.effect(() => ctx.locale.register(NS, {
12095
12364
  zh,
12096
12365
  en
12097
12366
  }), "ui-workspace: dictionaries");
12098
12367
  const searchSessions = async (query, signal) => {
12099
- const result = await ctx.sessions.search(query, signal);
12368
+ const result = await sessions.search(query, signal);
12100
12369
  if (!result.ok) throw new Error(result.error.message);
12101
12370
  return result.value;
12102
12371
  };
@@ -12105,53 +12374,57 @@ const official = ((require$1) => {
12105
12374
  subscribe: (listener) => ctx.slots.subscribe(hole, listener)
12106
12375
  });
12107
12376
  const browserFlowSource = flowSource("sidebar.workspaces.directoryFlow");
12377
+ const hostInfo = {
12378
+ getSnapshot: () => ctx.remote.$host,
12379
+ subscribe: (listener) => ctx.on("connection/reset", listener)
12380
+ };
12108
12381
  const pickerFlowSource = flowSource("conversation.hero.workspace.directoryFlow");
12109
12382
  const browserInjected = () => ({
12110
12383
  startSession: (workspaceId) => {
12111
- ctx.workspaces.startSession(workspaceId);
12384
+ uiWorkspace.startSession(workspaceId);
12112
12385
  },
12113
12386
  open: (sessionId) => {
12114
- ctx.sessions.open(sessionId);
12387
+ sessions.open(sessionId);
12115
12388
  },
12116
12389
  searchSessions,
12117
- searchResultLimit: ctx.sessions.searchResultLimit,
12390
+ searchResultLimit: sessions.searchResultLimit,
12118
12391
  renameSession: async (sessionId, title) => {
12119
- const session = ctx.sessions.binding(sessionId)?.session;
12392
+ const session = sessions.binding(sessionId)?.session;
12120
12393
  if (session === void 0) throw new Error(`unknown session "${sessionId}"`);
12121
12394
  const result = await session.rename(title);
12122
12395
  if (!result.ok) throw new Error(result.error.message);
12123
12396
  },
12124
12397
  forkSession: (sessionId) => {
12125
- ctx.sessions.fork({
12398
+ sessions.fork({
12126
12399
  sessionId,
12127
12400
  increaseTitle: true
12128
12401
  }).then((childId) => {
12129
- ctx.sessions.open(childId);
12402
+ sessions.open(childId);
12130
12403
  }).catch(() => {});
12131
12404
  },
12132
12405
  renameWorkspace: async (workspaceId, title) => {
12133
- await ctx.workspaces.rename(workspaceId, title);
12406
+ await workspaces.rename(workspaceId, title);
12134
12407
  },
12135
12408
  deleteWorkspace: async (workspaceId) => {
12136
- await ctx.workspaces.delete(workspaceId);
12409
+ await workspaces.delete(workspaceId);
12137
12410
  },
12138
12411
  insertWorkspaceBefore: async (workspaceId, beforeWorkspaceId) => {
12139
- await ctx.workspaces.insertBefore(workspaceId, beforeWorkspaceId);
12412
+ await workspaces.insertBefore(workspaceId, beforeWorkspaceId);
12140
12413
  },
12141
12414
  archiveSession: async (sessionId) => {
12142
- await ctx.workspaces.archiveSession(sessionId);
12415
+ await uiWorkspace.archiveSession(sessionId);
12143
12416
  },
12144
12417
  insertSessionBefore: async (workspaceId, sessionId, beforeSessionId) => {
12145
- await ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId);
12418
+ await workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId);
12146
12419
  },
12147
- createWorkspace: (input) => ctx.workspaces.create(input),
12420
+ createWorkspace: (input) => workspaces.create(input),
12148
12421
  hooks: {
12149
12422
  directoryFlow: browserFlowSource,
12150
- hostDescription
12423
+ hostInfo
12151
12424
  }
12152
12425
  });
12153
12426
  const pickerInjected = () => ({
12154
- createWorkspace: (input) => ctx.workspaces.create(input),
12427
+ createWorkspace: (input) => workspaces.create(input),
12155
12428
  hooks: { directoryFlow: pickerFlowSource }
12156
12429
  });
12157
12430
  ctx.slots.inject("sidebar.workspaces", () => ctx.slots.register({