dsh-session-flow 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/client.js +842 -183
  2. package/lib/host.js +63 -5
  3. package/package.json +4 -1
package/lib/host.js CHANGED
@@ -10,10 +10,11 @@
10
10
  // searchAll { query, workspace? } → 跨会话全文检索(最近 20 会话/总 5s 预算/取消支持)
11
11
  // stats → 环境信息(dsh home、索引目录、各工作区缓存状态)
12
12
  //
13
- // 依赖 cordis 服务:webServer(HTTP 载体)。
13
+ // 依赖 cordis 服务:webServer(HTTP 载体);settings(插件设置命名空间,软依赖)。
14
14
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFile } from 'node:fs'
15
15
  import { join } from 'node:path'
16
16
  import { deflateRawSync } from 'node:zlib'
17
+ import z from 'schemastery'
17
18
  import { decodeFile, listSessionDirs, listWorkspaces, looksLikePath, parseSession, summarizeParsed } from './archive.js'
18
19
  import { deriveTimeline } from './timeline.js'
19
20
  import {
@@ -69,17 +70,71 @@ function sendJson(res, status, obj) {
69
70
  // ── 卡死监控(stall-monitor):健康分类 ─────────────────────────────
70
71
  // 「进行中但长时间无输出」≠ 卡死(模型长思考/长工具执行都静默)。
71
72
  // 分类只看结构事实:运行中 + 无流式 chunk + 无未闭合工具 + 静默超阈值 → 疑似卡死。
72
- // TODO(设置页待办):STALL_THRESHOLD_MS 待插件设置页落地后可配置化(见 docs HANDOVER §7)。
73
+ // 阈值可在设置页配置(settings 命名空间 session-flow / stallThresholdMin,分钟);
74
+ // STALL_THRESHOLD_MS 保留为默认值(verify 引用)。
73
75
  export const STALL_THRESHOLD_MS = 3 * 60 * 1000
74
76
  export const HEALTH_ACTIVE_WINDOW_MS = 60 * 1000
75
77
 
78
+ // ── 插件设置(settings 命名空间 'session-flow')────────────────────
79
+ // 默认值必须与 client.js 的 SETTINGS_DEFAULTS 完全一致(无用户设置时行为零变化)。
80
+ export const SETTINGS_DEFAULTS = {
81
+ pianoWindow: 12, // 轮次悬浮条可见行数
82
+ pianoWheelSpeed: 0.012, // 滚轮灵敏度(行/px)
83
+ pianoSnapMs: 170, // 静止吸附延迟(ms)
84
+ livePollMs: 3000, // 实时轮询间隔(ms)
85
+ liveFollowPx: 40, // 实时吸底阈值(px)
86
+ liveHistoryTurns: 3, // 详情页实时模式保留的历史回合数
87
+ stallThresholdMin: 3, // 疑似卡死阈值(分钟)
88
+ }
89
+
90
+ /** schemastery schema:settings 服务 resolve 时调用 schema(merged),并需要 toJSON()(describe 用)。 */
91
+ const SETTINGS_SCHEMA = z.object({
92
+ pianoWindow: z.number().step(1).min(6).max(18).default(SETTINGS_DEFAULTS.pianoWindow),
93
+ pianoWheelSpeed: z.number().min(0.005).max(0.03).default(SETTINGS_DEFAULTS.pianoWheelSpeed),
94
+ pianoSnapMs: z.number().step(1).min(100).max(400).default(SETTINGS_DEFAULTS.pianoSnapMs),
95
+ livePollMs: z.number().step(1).min(1500).max(10000).default(SETTINGS_DEFAULTS.livePollMs),
96
+ liveFollowPx: z.number().step(1).min(20).max(120).default(SETTINGS_DEFAULTS.liveFollowPx),
97
+ liveHistoryTurns: z.number().step(1).min(0).max(10).default(SETTINGS_DEFAULTS.liveHistoryTurns),
98
+ stallThresholdMin: z.number().step(1).min(1).max(10).default(SETTINGS_DEFAULTS.stallThresholdMin),
99
+ })
100
+
101
+ /** 解析后的当前设置值(base + user 层);host 侧消费点(卡死阈值)从这里读。 */
102
+ const liveSettings = { ...SETTINGS_DEFAULTS }
103
+
104
+ /**
105
+ * 注册 settings 命名空间(软依赖:宿主无 settings 服务时跳过,行为回退默认值)。
106
+ * 模式参照 aionui-panel installSettingsSection:ctx.inject(['settings'], ...) +
107
+ * scope.watch 同步当前值。客户端经 settingsScope 直接读写(pet 同款),无需额外路由。
108
+ */
109
+ function installSettings(ctx) {
110
+ try {
111
+ if (typeof ctx.inject !== 'function') return
112
+ ctx.inject(['settings'], (sctx) => {
113
+ try {
114
+ const scope = sctx.settings.register('session-flow', SETTINGS_SCHEMA, { base: SETTINGS_DEFAULTS })
115
+ const sync = () => {
116
+ const value = scope.get()
117
+ if (value && typeof value === 'object') Object.assign(liveSettings, SETTINGS_DEFAULTS, value)
118
+ }
119
+ sync()
120
+ scope.watch(sync)
121
+ } catch (error) {
122
+ console.error('[dsh-session-flow] settings registration failed:', error)
123
+ }
124
+ })
125
+ } catch (error) {
126
+ console.error('[dsh-session-flow] settings service unavailable:', error)
127
+ }
128
+ }
129
+
76
130
  /**
77
131
  * 健康分类(纯函数,verify 可测)。
78
132
  * @param {{running:boolean,lastEventTime:number|null,openTool:boolean,inflight:boolean}} facts
79
133
  * @param {number} now - 调用方时间戳(client 传 Date.now(),避免 host/client 时钟偏差语义混乱)。
134
+ * @param {number} [stallMs] - 卡死阈值(缺省 STALL_THRESHOLD_MS;设置页 stallThresholdMin 下发)。
80
135
  * @returns {{kind:'active'|'tool-wait'|'quiet'|'stalled'|'ended'|'unknown', idleMs:number|null}}
81
136
  */
82
- export function classifyHealth(facts, now) {
137
+ export function classifyHealth(facts, now, stallMs = STALL_THRESHOLD_MS) {
83
138
  if (!facts || typeof facts !== 'object') return { kind: 'unknown', idleMs: null }
84
139
  const idleMs = typeof facts.lastEventTime === 'number' ? Math.max(0, now - facts.lastEventTime) : null
85
140
  if (facts.running !== true) return { kind: 'ended', idleMs }
@@ -88,7 +143,7 @@ export function classifyHealth(facts, now) {
88
143
  // 有未闭合工具调用 → 静默是工具在执行(长跑命令正常),不算卡死。
89
144
  if (facts.openTool === true) return { kind: 'tool-wait', idleMs }
90
145
  if (idleMs === null) return { kind: 'unknown', idleMs }
91
- if (idleMs >= STALL_THRESHOLD_MS) return { kind: 'stalled', idleMs }
146
+ if (idleMs >= stallMs) return { kind: 'stalled', idleMs }
92
147
  return { kind: 'quiet', idleMs }
93
148
  }
94
149
 
@@ -630,6 +685,9 @@ export function apply(ctx) {
630
685
  return
631
686
  }
632
687
 
688
+ // 插件设置命名空间(软依赖;卡死阈值等 host 侧参数经 liveSettings 下发)。
689
+ installSettings(ctx)
690
+
633
691
  webServer.register({
634
692
  kind: 'exact',
635
693
  path: '/api/session-flow',
@@ -1040,7 +1098,7 @@ export function apply(ctx) {
1040
1098
  counts,
1041
1099
  timeline,
1042
1100
  running,
1043
- health: { ...healthFacts, ...classifyHealth(healthFacts, now) },
1101
+ health: { ...healthFacts, ...classifyHealth(healthFacts, now, liveSettings.stallThresholdMin * 60000) },
1044
1102
  })
1045
1103
  }
1046
1104
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-session-flow",
3
3
  "description": "DSH 会话回顾与归档插件:可折叠信息流 + 会话级汇总——总览工作台、折叠时间线、血缘树、双模式摘要、全文检索、ZIP 导出、实时跟踪、会话重命名(官方数据源对齐)、健康监控",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "main": "lib/host.js",
7
7
  "exports": {
@@ -42,6 +42,9 @@
42
42
  "platform": "web"
43
43
  }
44
44
  },
45
+ "dependencies": {
46
+ "schemastery": "^3.18.0"
47
+ },
45
48
  "peerDependencies": {
46
49
  "react": "^18.2.0",
47
50
  "react-dom": "^18.2.0",