@michengai/dsh-archive-manager 0.1.22 → 0.1.23

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/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@
4
4
 
5
5
  Published release notes are retained below; new versions are added without removing earlier entries.
6
6
 
7
+ ## 0.1.23 — 2026-09-01
8
+
9
+ - Fixed missing sidebar pending-state indicators on DSH `v0.1.2-alpha.2`: workspace rows now read pending UI interactions from the `ui-session` `pendingInteractions` Map.
10
+ - Whitelisted the official visible pending states (`question`, `approval`, and `plan-review`) before passing them to row rendering, so unknown future states are ignored safely.
11
+ - Kept the legacy `SessionSummary.pendingInteraction` fallback and added regression coverage for grouped, flat, and search result rows.
12
+
13
+ Published package: [`@michengai/dsh-archive-manager@0.1.23`](https://www.npmjs.com/package/@michengai/dsh-archive-manager/v/0.1.23).
14
+
7
15
  ## 0.1.22 — 2026-09-01
8
16
 
9
17
  - Added arbitrary archived-chat selection in **Settings → Archived**, including per-row checkboxes, select-all for the current filtered results, cross-project selection, batch restore, and confirmed batch permanent deletion.
@@ -4,6 +4,14 @@
4
4
 
5
5
  以下发布说明会持续保留;新增版本时不再删除较早记录。
6
6
 
7
+ ## 0.1.23 — 2026-09-01
8
+
9
+ - 修复 DSH `v0.1.2-alpha.2` 后会话侧栏“等待回答 / 等待审批”状态点不显示的问题:侧栏行现在从 `ui-session` 的 `pendingInteractions` Map 读取待处理交互状态。
10
+ - 对 `question`、`approval`、`plan-review` 三种官方可见状态做白名单透传,未知状态会被忽略,避免触发行渲染断言。
11
+ - 保留旧版 `SessionSummary.pendingInteraction` 兜底,并补充分组、扁平列表和搜索结果三条路径的回归测试。
12
+
13
+ 已发布包:[`@michengai/dsh-archive-manager@0.1.23`](https://www.npmjs.com/package/@michengai/dsh-archive-manager/v/0.1.23)。
14
+
7
15
  ## 0.1.22 — 2026-09-01
8
16
 
9
17
  - 在「设置 → 已归档」新增任意多选:每行复选框、全选当前筛选结果、跨项目保留选择、批量恢复和确认后的批量永久删除。
package/lib/client.js CHANGED
@@ -603,7 +603,26 @@ window.__ModuleLoader__.load({
603
603
  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"));
604
604
  return groups;
605
605
  }
606
- function sessionNode(s, descendants, archived) {
606
+ /** 只把侧栏已支持的待处理交互类型交给行渲染,避免未知类型触发断言。 */
607
+ function visiblePendingKind(kind) {
608
+ switch (kind) {
609
+ case "approval":
610
+ case "plan-review":
611
+ case "question": return kind;
612
+ default: return;
613
+ }
614
+ }
615
+ function pendingInteractionForSession(session, pendingInteractions) {
616
+ const entry = pendingInteractions.get(session.id);
617
+ const kind = entry === void 0 ? session.pendingInteraction : entry.kind;
618
+ return visiblePendingKind(kind);
619
+ }
620
+ const EMPTY_PENDING_INTERACTIONS = /* @__PURE__ */ new Map();
621
+ function useEmptySessionPendingInteraction(selector) {
622
+ return selector(EMPTY_PENDING_INTERACTIONS);
623
+ }
624
+ function sessionNode(s, descendants, archived, pendingInteractions) {
625
+ const pendingInteraction = pendingInteractionForSession(s, pendingInteractions);
607
626
  return {
608
627
  id: s.id,
609
628
  title: sessionTitle(s),
@@ -613,7 +632,7 @@ window.__ModuleLoader__.load({
613
632
  completed: s.completed === true,
614
633
  updatedAt: s.updatedAt,
615
634
  archived: archived.has(s.id),
616
- ...s.pendingInteraction === void 0 ? {} : { pendingInteraction: s.pendingInteraction }
635
+ ...pendingInteraction === void 0 ? {} : { pendingInteraction }
617
636
  };
618
637
  }
619
638
  /**
@@ -628,10 +647,11 @@ window.__ModuleLoader__.load({
628
647
  * @param list - sessions list snapshot (`current` feeds containsCurrent).
629
648
  * @param workspaces - real workspaces in stable Host order.
630
649
  * @param archivedSessionIds - registry-global archive set.
650
+ * @param pendingInteractions - pending UI interactions by Session.
631
651
  * @param view - local expansion arrays and the show-archived toggle.
632
652
  * @returns group sections in render order.
633
653
  */
634
- function deriveGroups(list, workspaces, archivedSessionIds, view) {
654
+ function deriveGroups(list, workspaces, archivedSessionIds, pendingInteractions, view) {
635
655
  const archived = new Set(archivedSessionIds);
636
656
  const expandedGroups = new Set(view.expandedGroups);
637
657
  const descendants = indexSubagentDescendants(list.byId);
@@ -648,7 +668,7 @@ window.__ModuleLoader__.load({
648
668
  sessionCount: g.sessions.length,
649
669
  expanded,
650
670
  containsCurrent: g.key === currentGroup,
651
- sessions: expanded ? g.sessions.map((session) => sessionNode(session, descendants, archived)) : []
671
+ sessions: expanded ? g.sessions.map((session) => sessionNode(session, descendants, archived, pendingInteractions)) : []
652
672
  });
653
673
  }
654
674
  return groups;
@@ -662,10 +682,11 @@ window.__ModuleLoader__.load({
662
682
  * (see {@link deriveSearchResults}).
663
683
  * @param list - sessions list snapshot.
664
684
  * @param archivedSessionIds - registry-global archive set.
685
+ * @param pendingInteractions - pending UI interactions by Session.
665
686
  * @param showArchived - "show archived" view toggle.
666
687
  * @returns flat rows in render order.
667
688
  */
668
- function deriveFlat(list, archivedSessionIds, showArchived) {
689
+ function deriveFlat(list, archivedSessionIds, pendingInteractions, showArchived) {
669
690
  const archived = new Set(archivedSessionIds);
670
691
  const descendants = indexSubagentDescendants(list.byId);
671
692
  const rows = [];
@@ -675,7 +696,7 @@ window.__ModuleLoader__.load({
675
696
  rows.push(s);
676
697
  }
677
698
  rows.sort(byRecency);
678
- return rows.map((session) => sessionNode(session, descendants, archived));
699
+ return rows.map((session) => sessionNode(session, descendants, archived, pendingInteractions));
679
700
  }
680
701
  /**
681
702
  * Merge immediate title/Workspace substring matches with ranked Host content
@@ -686,12 +707,13 @@ window.__ModuleLoader__.load({
686
707
  * @param workspaces - Workspace membership and display labels.
687
708
  * @param query - caller text; surrounding whitespace is ignored.
688
709
  * @param archivedSessionIds - registry-global archive set.
710
+ * @param pendingInteractions - pending UI interactions by Session.
689
711
  * @param content - ranked Host content-search page.
690
712
  * @param limit - protocol-owned maximum merged row count.
691
713
  * @param showArchived - "show archived" view toggle.
692
714
  * @returns bounded deduplicated flat rows and a refine-query hint bit.
693
715
  */
694
- function deriveSearchResults(list, workspaces, query, archivedSessionIds, content, limit, showArchived) {
716
+ function deriveSearchResults(list, workspaces, query, archivedSessionIds, pendingInteractions, content, limit, showArchived) {
695
717
  const q = query.trim().toLowerCase();
696
718
  if (q === "") return {
697
719
  items: [],
@@ -726,6 +748,7 @@ window.__ModuleLoader__.load({
726
748
  return {
727
749
  items: ordered.slice(0, limit).map((summary) => {
728
750
  const match = contentBySession.get(summary.id);
751
+ const pendingInteraction = pendingInteractionForSession(summary, pendingInteractions);
729
752
  return {
730
753
  id: summary.id,
731
754
  title: sessionTitle(summary),
@@ -733,7 +756,7 @@ window.__ModuleLoader__.load({
733
756
  running: summary.running,
734
757
  runningSubagentCount: descendants.get(summary.id)?.runningCount ?? 0,
735
758
  archived: archived.has(summary.id),
736
- ...summary.pendingInteraction === void 0 ? {} : { pendingInteraction: summary.pendingInteraction },
759
+ ...pendingInteraction === void 0 ? {} : { pendingInteraction },
737
760
  completed: summary.completed === true,
738
761
  ...match === void 0 ? {} : { snippet: match.snippet }
739
762
  };
@@ -1713,8 +1736,9 @@ window.__ModuleLoader__.load({
1713
1736
  return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
1714
1737
  }
1715
1738
  /** The scrolling session tree; unmounting drops the sessions subscription and expand-all state. */
1716
- function SessionTree({ useSessions, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
1739
+ function SessionTree({ useSessions, useSessionPendingInteraction, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
1717
1740
  const list = useSessions((s) => s);
1741
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
1718
1742
  const current = list.current;
1719
1743
  const [expandedSessionGroups, setExpandedSessionGroups] = (0, react.useState)([]);
1720
1744
  const [drag, setDrag] = (0, react.useState)(null);
@@ -1781,7 +1805,7 @@ window.__ModuleLoader__.load({
1781
1805
  });
1782
1806
  }, [sessionOrderByAccount, workspaces]);
1783
1807
  const orderedUngroupedSessionIds = (0, react.useMemo)(() => reconciledSessionOrder(ungroupedSessionIds, sessionOrderByAccount[""]), [sessionOrderByAccount, ungroupedSessionIds]);
1784
- const groups = (0, react.useMemo)(() => deriveGroups(list, orderedWorkspaces, archivedSessionIds, {
1808
+ const groups = (0, react.useMemo)(() => deriveGroups(list, orderedWorkspaces, archivedSessionIds, pendingInteractions, {
1785
1809
  expandedGroups,
1786
1810
  showArchived,
1787
1811
  ...sessionOrderByAccount[""] === void 0 ? {} : { ungroupedOrder: sessionOrderByAccount[""] }
@@ -1789,6 +1813,7 @@ window.__ModuleLoader__.load({
1789
1813
  list,
1790
1814
  orderedWorkspaces,
1791
1815
  archivedSessionIds,
1816
+ pendingInteractions,
1792
1817
  showArchived,
1793
1818
  expandedGroups,
1794
1819
  sessionOrderByAccount
@@ -1990,9 +2015,15 @@ window.__ModuleLoader__.load({
1990
2015
  });
1991
2016
  }
1992
2017
  /** The flat "In one list" body: every session is one draggable top-level row. */
1993
- function FlatList({ useSessions, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
2018
+ function FlatList({ useSessions, useSessionPendingInteraction, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t }) {
1994
2019
  const list = useSessions((s) => s);
1995
- const baseRows = (0, react.useMemo)(() => deriveFlat(list, archivedSessionIds, showArchived), [list, archivedSessionIds, showArchived]);
2020
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
2021
+ const baseRows = (0, react.useMemo)(() => deriveFlat(list, archivedSessionIds, pendingInteractions, showArchived), [
2022
+ list,
2023
+ archivedSessionIds,
2024
+ pendingInteractions,
2025
+ showArchived
2026
+ ]);
1996
2027
  const sessionIds = (0, react.useMemo)(() => baseRows.map((row) => row.id), [baseRows]);
1997
2028
  const previousOrderBy = (0, react.useRef)(orderBy);
1998
2029
  (0, react.useEffect)(() => {
@@ -2114,19 +2145,21 @@ window.__ModuleLoader__.load({
2114
2145
  });
2115
2146
  }
2116
2147
  /** Flat search body: local metadata matches plus the current Host result page. */
2117
- function SearchResults({ useSessions, open, workspaces, archivedSessionIds, showArchived, query, remote, resultLimit, t }) {
2148
+ function SearchResults({ useSessions, useSessionPendingInteraction, open, workspaces, archivedSessionIds, showArchived, query, remote, resultLimit, t }) {
2118
2149
  const list = useSessions((s) => s);
2150
+ const pendingInteractions = useSessionPendingInteraction((s) => s);
2119
2151
  const currentRemote = remote.query === query ? remote : {
2120
2152
  query,
2121
2153
  status: "loading",
2122
2154
  items: [],
2123
2155
  hasMore: false
2124
2156
  };
2125
- const results = (0, react.useMemo)(() => deriveSearchResults(list, workspaces, query, archivedSessionIds, currentRemote, resultLimit, showArchived), [
2157
+ const results = (0, react.useMemo)(() => deriveSearchResults(list, workspaces, query, archivedSessionIds, pendingInteractions, currentRemote, resultLimit, showArchived), [
2126
2158
  list,
2127
2159
  workspaces,
2128
2160
  query,
2129
2161
  archivedSessionIds,
2162
+ pendingInteractions,
2130
2163
  currentRemote,
2131
2164
  resultLimit,
2132
2165
  showArchived
@@ -2176,7 +2209,8 @@ window.__ModuleLoader__.load({
2176
2209
  * @param props - composed slot props (shell owner share + store + injected actions).
2177
2210
  * @returns the region element tree.
2178
2211
  */
2179
- function WorkspaceBrowser({ wide, expandSidebar, useSessions, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, unarchiveSession, deleteSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, renderSlot, t }) {
2212
+ function WorkspaceBrowser({ wide, expandSidebar, useSessions, useSessionPendingInteraction, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, unarchiveSession, deleteSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, renderSlot, t }) {
2213
+ const useEffectiveSessionPendingInteraction = useSessionPendingInteraction ?? useEmptySessionPendingInteraction;
2180
2214
  const workspaces = useWorkspaces((state) => state.items);
2181
2215
  const workspacePhase = useWorkspaces((state) => state.phase);
2182
2216
  const archivedSessionIds = useWorkspaces((state) => state.archivedSessionIds);
@@ -2571,6 +2605,7 @@ window.__ModuleLoader__.load({
2571
2605
  className: WorkspaceBrowser_module_css_default.listArea,
2572
2606
  children: wide && (normalizedQuery !== "" ? (0, react_jsx_runtime.jsx)(SearchResults, {
2573
2607
  useSessions,
2608
+ useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
2574
2609
  open: guardedOpen,
2575
2610
  workspaces,
2576
2611
  archivedSessionIds,
@@ -2581,6 +2616,7 @@ window.__ModuleLoader__.load({
2581
2616
  t
2582
2617
  }) : groupBy === "flat" ? (0, react_jsx_runtime.jsx)(FlatList, {
2583
2618
  useSessions,
2619
+ useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
2584
2620
  open: guardedOpen,
2585
2621
  forkSession,
2586
2622
  onSessionRename,
@@ -2600,6 +2636,7 @@ window.__ModuleLoader__.load({
2600
2636
  t
2601
2637
  }) : (0, react_jsx_runtime.jsx)(SessionTree, {
2602
2638
  useSessions,
2639
+ useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
2603
2640
  onSessionRename,
2604
2641
  onSessionArchive,
2605
2642
  onSessionUnarchive,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-archive-manager",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "NPM-installable DSH Web plugin for managing archived sessions.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.21.0",