@wenbin_wb/dsh-bridge 2.10.8 → 2.10.9

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.
@@ -1,117 +1,117 @@
1
- // DSH 私有存储读取(workspace.json / session_projcache.json 兜底)
2
- // 自 conversation-bridge.js 拆出。策略:内存服务(workspaceRegistry)优先,
3
- // 仅当内存服务缺失时才落盘读 DSH 存储;文件不存在时安全返回空值。
4
- // 注意:不再以 ctx._mock 作为跳过依据——测试通过提供内存服务或注入 DSH_HOME 保持隔离。
5
- import { existsSync, readFileSync } from 'node:fs'
6
- import { join, basename } from 'node:path'
7
- import { homedir } from 'node:os'
8
-
9
- export function getArchivedSessionIds(ctx) {
10
- const archived = new Set()
11
- // 1. 尝试从 ctx.workspaceRegistry 内存服务读取
12
- try {
13
- const list = ctx?.workspaceRegistry?.archivedSessionIds
14
- if (Array.isArray(list)) {
15
- for (const id of list) {
16
- if (id) archived.add(String(id))
17
- }
18
- return archived
19
- }
20
- } catch { /* ignore */ }
21
-
22
- // 2. 尝试从 DSH workspace 存储文件($DSH_HOME/storages/workspace.json)读取兜底
23
- {
24
- try {
25
- const home = process.env.DSH_HOME || join(homedir(), '.dsh')
26
- const wsFile = join(home, 'storages', 'workspace.json')
27
- if (existsSync(wsFile)) {
28
- const data = JSON.parse(readFileSync(wsFile, 'utf8'))
29
- const fileArchived = data?.global?.archivedSessionIds
30
- if (Array.isArray(fileArchived)) {
31
- for (const id of fileArchived) {
32
- if (id) archived.add(String(id))
33
- }
34
- }
35
- }
36
- } catch { /* ignore */ }
37
- }
38
-
39
- return archived
40
- }
41
-
42
- /**
43
- * 安全探测 ctx 上的非 inject 属性。
44
- * 宿主 cordis 上下文对插件未在 inject 中声明的属性读取会直接抛错
45
- * ('cannot get property "x" without inject'),因此内存注入点(测试夹具用)
46
- * 必须经 try/catch 探测,绝不能让异常外溢到命令路径。
47
- */
48
- function peekCtxProperty(ctx, key) {
49
- if (!ctx) return undefined
50
- try { return ctx[key] } catch { return undefined }
51
- }
52
-
53
- /** 读取 DSH 官方持久化会话缓存元数据(标题、是否空白、创建时间等) */
54
- export function getSessionProjCache(ctx) {
55
- const injected = peekCtxProperty(ctx, 'sessionProjCache')
56
- if (injected) return injected
57
- try {
58
- const home = process.env.DSH_HOME || join(homedir(), '.dsh')
59
- const cacheFile = join(home, 'storages', 'session_projcache.json')
60
- if (existsSync(cacheFile)) {
61
- const data = JSON.parse(readFileSync(cacheFile, 'utf8'))
62
- return data?.tables?.sessions || {}
63
- }
64
- } catch { /* ignore */ }
65
- return {}
66
- }
67
-
68
- /** 读取 DSH 官方注册的工作区列表及各自绑定的 sessionIds 列表 */
69
- export async function getRegisteredWorkspaces(ctx) {
70
- const workspaces = []
71
-
72
- // 优先从内存服务获取
73
- if (ctx?.workspaceRegistry) {
74
- try {
75
- const list = await ctx.workspaceRegistry.list?.()
76
- if (Array.isArray(list)) {
77
- for (const w of list) {
78
- if (w && w.path) {
79
- workspaces.push({
80
- id: w.id || w.path,
81
- path: w.path,
82
- title: w.title || basename(w.path),
83
- sessionIds: Array.isArray(w.sessionIds) ? [...w.sessionIds] : [],
84
- })
85
- }
86
- }
87
- return workspaces
88
- }
89
- } catch { /* ignore */ }
90
- }
91
-
92
- // 兜底从 workspace.json 存储文件读取
93
- {
94
- try {
95
- const home = process.env.DSH_HOME || join(homedir(), '.dsh')
96
- const wsFile = join(home, 'storages', 'workspace.json')
97
- if (existsSync(wsFile)) {
98
- const data = JSON.parse(readFileSync(wsFile, 'utf8'))
99
- const wsIds = data?.global?.workspaceIds || Object.keys(data?.tables?.workspaces || {})
100
- const table = data?.tables?.workspaces || {}
101
- for (const wId of wsIds) {
102
- const ws = table[wId]
103
- if (ws && ws.path) {
104
- workspaces.push({
105
- id: wId,
106
- path: ws.path,
107
- title: ws.title || basename(ws.path),
108
- sessionIds: Array.isArray(ws.sessionIds) ? [...ws.sessionIds] : [],
109
- })
110
- }
111
- }
112
- }
113
- } catch { /* ignore */ }
114
- }
115
-
116
- return workspaces
117
- }
1
+ // DSH 私有存储读取(workspace.json / session_projcache.json 兜底)
2
+ // 自 conversation-bridge.js 拆出。策略:内存服务(workspaceRegistry)优先,
3
+ // 仅当内存服务缺失时才落盘读 DSH 存储;文件不存在时安全返回空值。
4
+ // 注意:不再以 ctx._mock 作为跳过依据——测试通过提供内存服务或注入 DSH_HOME 保持隔离。
5
+ import { existsSync, readFileSync } from 'node:fs'
6
+ import { join, basename } from 'node:path'
7
+ import { homedir } from 'node:os'
8
+
9
+ export function getArchivedSessionIds(ctx) {
10
+ const archived = new Set()
11
+ // 1. 尝试从 ctx.workspaceRegistry 内存服务读取
12
+ try {
13
+ const list = ctx?.workspaceRegistry?.archivedSessionIds
14
+ if (Array.isArray(list)) {
15
+ for (const id of list) {
16
+ if (id) archived.add(String(id))
17
+ }
18
+ return archived
19
+ }
20
+ } catch { /* ignore */ }
21
+
22
+ // 2. 尝试从 DSH workspace 存储文件($DSH_HOME/storages/workspace.json)读取兜底
23
+ {
24
+ try {
25
+ const home = process.env.DSH_HOME || join(homedir(), '.dsh')
26
+ const wsFile = join(home, 'storages', 'workspace.json')
27
+ if (existsSync(wsFile)) {
28
+ const data = JSON.parse(readFileSync(wsFile, 'utf8'))
29
+ const fileArchived = data?.global?.archivedSessionIds
30
+ if (Array.isArray(fileArchived)) {
31
+ for (const id of fileArchived) {
32
+ if (id) archived.add(String(id))
33
+ }
34
+ }
35
+ }
36
+ } catch { /* ignore */ }
37
+ }
38
+
39
+ return archived
40
+ }
41
+
42
+ /**
43
+ * 安全探测 ctx 上的非 inject 属性。
44
+ * 宿主 cordis 上下文对插件未在 inject 中声明的属性读取会直接抛错
45
+ * ('cannot get property "x" without inject'),因此内存注入点(测试夹具用)
46
+ * 必须经 try/catch 探测,绝不能让异常外溢到命令路径。
47
+ */
48
+ function peekCtxProperty(ctx, key) {
49
+ if (!ctx) return undefined
50
+ try { return ctx[key] } catch { return undefined }
51
+ }
52
+
53
+ /** 读取 DSH 官方持久化会话缓存元数据(标题、是否空白、创建时间等) */
54
+ export function getSessionProjCache(ctx) {
55
+ const injected = peekCtxProperty(ctx, 'sessionProjCache')
56
+ if (injected) return injected
57
+ try {
58
+ const home = process.env.DSH_HOME || join(homedir(), '.dsh')
59
+ const cacheFile = join(home, 'storages', 'session_projcache.json')
60
+ if (existsSync(cacheFile)) {
61
+ const data = JSON.parse(readFileSync(cacheFile, 'utf8'))
62
+ return data?.tables?.sessions || {}
63
+ }
64
+ } catch { /* ignore */ }
65
+ return {}
66
+ }
67
+
68
+ /** 读取 DSH 官方注册的工作区列表及各自绑定的 sessionIds 列表 */
69
+ export async function getRegisteredWorkspaces(ctx) {
70
+ const workspaces = []
71
+
72
+ // 优先从内存服务获取
73
+ if (ctx?.workspaceRegistry) {
74
+ try {
75
+ const list = await ctx.workspaceRegistry.list?.()
76
+ if (Array.isArray(list)) {
77
+ for (const w of list) {
78
+ if (w && w.path) {
79
+ workspaces.push({
80
+ id: w.id || w.path,
81
+ path: w.path,
82
+ title: w.title || basename(w.path),
83
+ sessionIds: Array.isArray(w.sessionIds) ? [...w.sessionIds] : [],
84
+ })
85
+ }
86
+ }
87
+ return workspaces
88
+ }
89
+ } catch { /* ignore */ }
90
+ }
91
+
92
+ // 兜底从 workspace.json 存储文件读取
93
+ {
94
+ try {
95
+ const home = process.env.DSH_HOME || join(homedir(), '.dsh')
96
+ const wsFile = join(home, 'storages', 'workspace.json')
97
+ if (existsSync(wsFile)) {
98
+ const data = JSON.parse(readFileSync(wsFile, 'utf8'))
99
+ const wsIds = data?.global?.workspaceIds || Object.keys(data?.tables?.workspaces || {})
100
+ const table = data?.tables?.workspaces || {}
101
+ for (const wId of wsIds) {
102
+ const ws = table[wId]
103
+ if (ws && ws.path) {
104
+ workspaces.push({
105
+ id: wId,
106
+ path: ws.path,
107
+ title: ws.title || basename(ws.path),
108
+ sessionIds: Array.isArray(ws.sessionIds) ? [...ws.sessionIds] : [],
109
+ })
110
+ }
111
+ }
112
+ }
113
+ } catch { /* ignore */ }
114
+ }
115
+
116
+ return workspaces
117
+ }
@@ -1,10 +1,10 @@
1
- // dsh-bridge 平台抽象层统一导出
2
- //
3
- // 提供多平台 IM 接入的基础设施:
4
- // Platform 平台适配器基类(协议/连接/登录/收发消息)
5
- // ConversationBridge 平台无关会话桥(白名单/会话/审批/命令/digest)
6
- // PlatformManager 多平台注册与状态聚合
7
-
8
- export { Platform } from './base.js'
9
- export { ConversationBridge, conversationBridgeHelpers, textOfAssistantMessage } from './conversation-bridge.js'
10
- export { PlatformManager } from './manager.js'
1
+ // dsh-bridge 平台抽象层统一导出
2
+ //
3
+ // 提供多平台 IM 接入的基础设施:
4
+ // Platform 平台适配器基类(协议/连接/登录/收发消息)
5
+ // ConversationBridge 平台无关会话桥(白名单/会话/审批/命令/digest)
6
+ // PlatformManager 多平台注册与状态聚合
7
+
8
+ export { Platform } from './base.js'
9
+ export { ConversationBridge, conversationBridgeHelpers, textOfAssistantMessage } from './conversation-bridge.js'
10
+ export { PlatformManager } from './manager.js'