dsh-obsidian-notes 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +47 -14
- package/package.json +1 -1
- package/src/client.js +47 -14
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ not enough.
|
|
|
64
64
|
2. Search for **`dsh-obsidian-notes`** and install it.
|
|
65
65
|
3. Restart DeepSeek Harness.
|
|
66
66
|
|
|
67
|
-
> This path requires the package to be published on npm (
|
|
67
|
+
> This path requires the package to be published on npm (current release **0.5.2**).
|
|
68
68
|
> If search shows nothing, use one of the two paths below.
|
|
69
69
|
|
|
70
70
|
### 2. CLI (after the npm release)
|
package/README.zh.md
CHANGED
package/lib/client.js
CHANGED
|
@@ -2043,6 +2043,38 @@ window.__ModuleLoader__.load({
|
|
|
2043
2043
|
return `${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, "0")}/${String(d.getDate()).padStart(2, "0")}`;
|
|
2044
2044
|
}
|
|
2045
2045
|
|
|
2046
|
+
/**
|
|
2047
|
+
* 会话行次序:与 DSH 内置侧边栏的**默认**排序(`orderBy: 'updated'`,
|
|
2048
|
+
* 「最近更新」)一致。
|
|
2049
|
+
*
|
|
2050
|
+
* 不能直接用 Workspace 的 `sessionIds` 次序:那是**挂载次序**(host 侧
|
|
2051
|
+
* `attachSession` 把新会话 prepend 到数组头),一个很久以前创建、现在仍在
|
|
2052
|
+
* 用的会话会停在旧位置(表现为「当前会话排在倒数第二」)。DSH 默认视图
|
|
2053
|
+
* 的做法是:按会话的 `updatedAt` 降序;时间相同时按 id 升序 —— 官方
|
|
2054
|
+
* `compareSessionRecency` 就是这两个比较,id 作稳定 tie-break 是为了同一份
|
|
2055
|
+
* 数据每次渲染次序稳定,不随 Map 迭代顺序抖动。
|
|
2056
|
+
* @param a - 会话 id。
|
|
2057
|
+
* @param b - 会话 id。
|
|
2058
|
+
* @param byId - 会话 id → 会话摘要(`updatedAt` 为 epoch ms)。
|
|
2059
|
+
* @returns 排序比较值(负 = a 更靠前)。
|
|
2060
|
+
*/
|
|
2061
|
+
function compareSessionRecency(a, b, byId) {
|
|
2062
|
+
const ta = byId[a]?.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
2063
|
+
const tb = byId[b]?.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
2064
|
+
if (ta !== tb) return tb - ta;
|
|
2065
|
+
return a < b ? -1 : 1;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
/**
|
|
2069
|
+
* 按「最近更新」排会话 id 列表(不修改入参)。
|
|
2070
|
+
* @param sessionIds - 待排的会话 id。
|
|
2071
|
+
* @param byId - 会话 id → 会话摘要。
|
|
2072
|
+
* @returns 新的已排序数组。
|
|
2073
|
+
*/
|
|
2074
|
+
function sortedSessionIds(sessionIds, byId) {
|
|
2075
|
+
return [...sessionIds].sort((a, b) => compareSessionRecency(a, b, byId));
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2046
2078
|
/**
|
|
2047
2079
|
* 一个会话及其全部子代理后代(闭包,含自身)。
|
|
2048
2080
|
* 删父会话必须连子代理日志一起删:父级日志消失后,子会话会变成无法归属的
|
|
@@ -2718,7 +2750,9 @@ window.__ModuleLoader__.load({
|
|
|
2718
2750
|
return true;
|
|
2719
2751
|
};
|
|
2720
2752
|
|
|
2721
|
-
// 分组:工作区 sessionIds 账户为主,cwd === path
|
|
2753
|
+
// 分组:工作区 sessionIds 账户为主,cwd === path 兜底;其余入「未分组」。
|
|
2754
|
+
// 组内次序**不**沿用 Workspace 的 sessionIds:那是挂载次序(新会话 prepend),
|
|
2755
|
+
// 会让人气正旺的旧会话沉底。统一按「最近更新」排,与 DSH 内置侧边栏默认一致。
|
|
2722
2756
|
const groups = useMemo(() => {
|
|
2723
2757
|
const accounted = new Set();
|
|
2724
2758
|
const list = [];
|
|
@@ -2737,11 +2771,12 @@ window.__ModuleLoader__.load({
|
|
|
2737
2771
|
accounted.add(sid);
|
|
2738
2772
|
}
|
|
2739
2773
|
}
|
|
2740
|
-
list.push({ key: w.workspaceId, workspace: w, sessionIds: wsIds });
|
|
2774
|
+
list.push({ key: w.workspaceId, workspace: w, sessionIds: sortedSessionIds(wsIds, byId) });
|
|
2741
2775
|
}
|
|
2742
|
-
const ungrouped =
|
|
2743
|
-
.filter((sid) => !accounted.has(sid) && visibleSession(sid))
|
|
2744
|
-
|
|
2776
|
+
const ungrouped = sortedSessionIds(
|
|
2777
|
+
ids.filter((sid) => !accounted.has(sid) && visibleSession(sid)),
|
|
2778
|
+
byId,
|
|
2779
|
+
);
|
|
2745
2780
|
return { list, ungrouped };
|
|
2746
2781
|
}, [items, ids, byId, archived, current, purged]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
2747
2782
|
|
|
@@ -2796,15 +2831,13 @@ window.__ModuleLoader__.load({
|
|
|
2796
2831
|
const q = query.trim().toLowerCase();
|
|
2797
2832
|
const matched = useMemo(() => {
|
|
2798
2833
|
if (q === "") return [];
|
|
2799
|
-
return ids
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
})
|
|
2807
|
-
.sort((a, b) => (byId[b].updatedAt ?? 0) - (byId[a].updatedAt ?? 0));
|
|
2834
|
+
return sortedSessionIds(ids.filter((sid) => {
|
|
2835
|
+
if (!visibleSession(sid)) return false;
|
|
2836
|
+
const s = byId[sid];
|
|
2837
|
+
const title = (s.title ?? "").toLowerCase();
|
|
2838
|
+
const display = (s.displayTitle ?? "").toLowerCase();
|
|
2839
|
+
return title.includes(q) || display.includes(q);
|
|
2840
|
+
}), byId);
|
|
2808
2841
|
}, [ids, byId, archived, q, current, purged]);
|
|
2809
2842
|
|
|
2810
2843
|
// ── 批量操作 ──────────────────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-obsidian-notes",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Obsidian-style notes panel for DeepSeek Harness Web: vault directory tree, Markdown preview/edit/save, cite-to-chat, batch archive/delete of sessions and workspaces. DSH 内嵌 Obsidian 风格笔记面板:目录树 + Markdown 预览/编辑/保存 + 引用到对话 + 会话/工作区批量操作。",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^22.19 || >=24"
|
package/src/client.js
CHANGED
|
@@ -946,6 +946,38 @@
|
|
|
946
946
|
return `${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, "0")}/${String(d.getDate()).padStart(2, "0")}`;
|
|
947
947
|
}
|
|
948
948
|
|
|
949
|
+
/**
|
|
950
|
+
* 会话行次序:与 DSH 内置侧边栏的**默认**排序(`orderBy: 'updated'`,
|
|
951
|
+
* 「最近更新」)一致。
|
|
952
|
+
*
|
|
953
|
+
* 不能直接用 Workspace 的 `sessionIds` 次序:那是**挂载次序**(host 侧
|
|
954
|
+
* `attachSession` 把新会话 prepend 到数组头),一个很久以前创建、现在仍在
|
|
955
|
+
* 用的会话会停在旧位置(表现为「当前会话排在倒数第二」)。DSH 默认视图
|
|
956
|
+
* 的做法是:按会话的 `updatedAt` 降序;时间相同时按 id 升序 —— 官方
|
|
957
|
+
* `compareSessionRecency` 就是这两个比较,id 作稳定 tie-break 是为了同一份
|
|
958
|
+
* 数据每次渲染次序稳定,不随 Map 迭代顺序抖动。
|
|
959
|
+
* @param a - 会话 id。
|
|
960
|
+
* @param b - 会话 id。
|
|
961
|
+
* @param byId - 会话 id → 会话摘要(`updatedAt` 为 epoch ms)。
|
|
962
|
+
* @returns 排序比较值(负 = a 更靠前)。
|
|
963
|
+
*/
|
|
964
|
+
function compareSessionRecency(a, b, byId) {
|
|
965
|
+
const ta = byId[a]?.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
966
|
+
const tb = byId[b]?.updatedAt ?? Number.NEGATIVE_INFINITY;
|
|
967
|
+
if (ta !== tb) return tb - ta;
|
|
968
|
+
return a < b ? -1 : 1;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* 按「最近更新」排会话 id 列表(不修改入参)。
|
|
973
|
+
* @param sessionIds - 待排的会话 id。
|
|
974
|
+
* @param byId - 会话 id → 会话摘要。
|
|
975
|
+
* @returns 新的已排序数组。
|
|
976
|
+
*/
|
|
977
|
+
function sortedSessionIds(sessionIds, byId) {
|
|
978
|
+
return [...sessionIds].sort((a, b) => compareSessionRecency(a, b, byId));
|
|
979
|
+
}
|
|
980
|
+
|
|
949
981
|
/**
|
|
950
982
|
* 一个会话及其全部子代理后代(闭包,含自身)。
|
|
951
983
|
* 删父会话必须连子代理日志一起删:父级日志消失后,子会话会变成无法归属的
|
|
@@ -1621,7 +1653,9 @@
|
|
|
1621
1653
|
return true;
|
|
1622
1654
|
};
|
|
1623
1655
|
|
|
1624
|
-
// 分组:工作区 sessionIds 账户为主,cwd === path
|
|
1656
|
+
// 分组:工作区 sessionIds 账户为主,cwd === path 兜底;其余入「未分组」。
|
|
1657
|
+
// 组内次序**不**沿用 Workspace 的 sessionIds:那是挂载次序(新会话 prepend),
|
|
1658
|
+
// 会让人气正旺的旧会话沉底。统一按「最近更新」排,与 DSH 内置侧边栏默认一致。
|
|
1625
1659
|
const groups = useMemo(() => {
|
|
1626
1660
|
const accounted = new Set();
|
|
1627
1661
|
const list = [];
|
|
@@ -1640,11 +1674,12 @@
|
|
|
1640
1674
|
accounted.add(sid);
|
|
1641
1675
|
}
|
|
1642
1676
|
}
|
|
1643
|
-
list.push({ key: w.workspaceId, workspace: w, sessionIds: wsIds });
|
|
1677
|
+
list.push({ key: w.workspaceId, workspace: w, sessionIds: sortedSessionIds(wsIds, byId) });
|
|
1644
1678
|
}
|
|
1645
|
-
const ungrouped =
|
|
1646
|
-
.filter((sid) => !accounted.has(sid) && visibleSession(sid))
|
|
1647
|
-
|
|
1679
|
+
const ungrouped = sortedSessionIds(
|
|
1680
|
+
ids.filter((sid) => !accounted.has(sid) && visibleSession(sid)),
|
|
1681
|
+
byId,
|
|
1682
|
+
);
|
|
1648
1683
|
return { list, ungrouped };
|
|
1649
1684
|
}, [items, ids, byId, archived, current, purged]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
1650
1685
|
|
|
@@ -1699,15 +1734,13 @@
|
|
|
1699
1734
|
const q = query.trim().toLowerCase();
|
|
1700
1735
|
const matched = useMemo(() => {
|
|
1701
1736
|
if (q === "") return [];
|
|
1702
|
-
return ids
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
})
|
|
1710
|
-
.sort((a, b) => (byId[b].updatedAt ?? 0) - (byId[a].updatedAt ?? 0));
|
|
1737
|
+
return sortedSessionIds(ids.filter((sid) => {
|
|
1738
|
+
if (!visibleSession(sid)) return false;
|
|
1739
|
+
const s = byId[sid];
|
|
1740
|
+
const title = (s.title ?? "").toLowerCase();
|
|
1741
|
+
const display = (s.displayTitle ?? "").toLowerCase();
|
|
1742
|
+
return title.includes(q) || display.includes(q);
|
|
1743
|
+
}), byId);
|
|
1711
1744
|
}, [ids, byId, archived, q, current, purged]);
|
|
1712
1745
|
|
|
1713
1746
|
// ── 批量操作 ──────────────────────────────────────────────────────────────
|