dsh-prime-memory 0.11.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 (151) hide show
  1. package/CHANGELOG.en.md +28 -0
  2. package/CHANGELOG.ja.md +30 -0
  3. package/CHANGELOG.ko.md +30 -0
  4. package/CHANGELOG.md +1220 -0
  5. package/ENGINEERING-NOTES.md +452 -0
  6. package/INSTALL.en.md +92 -0
  7. package/INSTALL.ja.md +92 -0
  8. package/INSTALL.ko.md +92 -0
  9. package/INSTALL.md +92 -0
  10. package/LICENSE +21 -0
  11. package/README.en.md +458 -0
  12. package/README.ja.md +306 -0
  13. package/README.ko.md +306 -0
  14. package/README.md +425 -0
  15. package/assets/changelog/0.8.10/01-write-only-pill.png +0 -0
  16. package/assets/changelog/0.8.9/01-panel.png +0 -0
  17. package/assets/changelog/0.8.9/02-halo.png +0 -0
  18. package/assets/changelog/0.8.9/03-layer-segmented-panel.png +0 -0
  19. package/assets/changelog/0.8.9/04-layer-l1-panel.png +0 -0
  20. package/assets/img/EmbeddingSource.png +0 -0
  21. package/assets/img/Hero.png +0 -0
  22. package/assets/img/Layers.png +0 -0
  23. package/assets/img/MemoryTools.png +0 -0
  24. package/assets/img/Modes.png +0 -0
  25. package/assets/img/ToolTrajectory.png +0 -0
  26. package/assets/img/ui-dark.jpg +0 -0
  27. package/assets/img/ui-light.jpg +0 -0
  28. package/assets/readme/bench-dialog.svg +70 -0
  29. package/assets/readme/bench-workflow.svg +79 -0
  30. package/assets/readme/flow.svg +189 -0
  31. package/assets/readme/storage.svg +115 -0
  32. package/cordis.patch.yml +16 -0
  33. package/dist/bench-control.d.ts +34 -0
  34. package/dist/bench-control.js +16 -0
  35. package/dist/client.js +4293 -0
  36. package/dist/config.d.ts +683 -0
  37. package/dist/config.js +129 -0
  38. package/dist/contract.d.ts +820 -0
  39. package/dist/contract.js +1 -0
  40. package/dist/embedding-worker.cjs +176 -0
  41. package/dist/graph/apply.d.ts +37 -0
  42. package/dist/graph/apply.js +270 -0
  43. package/dist/graph/constraints.d.ts +47 -0
  44. package/dist/graph/constraints.js +38 -0
  45. package/dist/graph/search.d.ts +16 -0
  46. package/dist/graph/search.js +115 -0
  47. package/dist/graph/types.d.ts +142 -0
  48. package/dist/graph/types.js +14 -0
  49. package/dist/hooks/capture.d.ts +32 -0
  50. package/dist/hooks/capture.js +194 -0
  51. package/dist/hooks/recall.d.ts +63 -0
  52. package/dist/hooks/recall.js +429 -0
  53. package/dist/index.d.ts +534 -0
  54. package/dist/index.js +344 -0
  55. package/dist/llm-usage.d.ts +26 -0
  56. package/dist/llm-usage.js +37 -0
  57. package/dist/llm.d.ts +153 -0
  58. package/dist/llm.js +530 -0
  59. package/dist/pipeline/graph.d.ts +35 -0
  60. package/dist/pipeline/graph.js +104 -0
  61. package/dist/pipeline/l1.d.ts +19 -0
  62. package/dist/pipeline/l1.js +271 -0
  63. package/dist/pipeline/l2.d.ts +13 -0
  64. package/dist/pipeline/l2.js +83 -0
  65. package/dist/pipeline/l3.d.ts +15 -0
  66. package/dist/pipeline/l3.js +78 -0
  67. package/dist/pipeline/rebuild.d.ts +61 -0
  68. package/dist/pipeline/rebuild.js +307 -0
  69. package/dist/pipeline/ruminate.d.ts +89 -0
  70. package/dist/pipeline/ruminate.js +298 -0
  71. package/dist/pipeline/runner.d.ts +167 -0
  72. package/dist/pipeline/runner.js +638 -0
  73. package/dist/pipeline/trigger.d.ts +40 -0
  74. package/dist/pipeline/trigger.js +75 -0
  75. package/dist/prompts/graph-projection.d.ts +70 -0
  76. package/dist/prompts/graph-projection.js +167 -0
  77. package/dist/prompts/l1-dedup.d.ts +22 -0
  78. package/dist/prompts/l1-dedup.js +251 -0
  79. package/dist/prompts/l1-extraction.d.ts +22 -0
  80. package/dist/prompts/l1-extraction.js +457 -0
  81. package/dist/prompts/persona.d.ts +23 -0
  82. package/dist/prompts/persona.js +240 -0
  83. package/dist/prompts/scene.d.ts +32 -0
  84. package/dist/prompts/scene.js +414 -0
  85. package/dist/runtime-package-lock.json +982 -0
  86. package/dist/settings.d.ts +50 -0
  87. package/dist/settings.js +355 -0
  88. package/dist/stats.d.ts +109 -0
  89. package/dist/stats.js +929 -0
  90. package/dist/store/bm25.d.ts +19 -0
  91. package/dist/store/bm25.js +63 -0
  92. package/dist/store/cost-ledger.d.ts +75 -0
  93. package/dist/store/cost-ledger.js +171 -0
  94. package/dist/store/download-queue.d.ts +79 -0
  95. package/dist/store/download-queue.js +424 -0
  96. package/dist/store/embedding-source.d.ts +118 -0
  97. package/dist/store/embedding-source.js +443 -0
  98. package/dist/store/embedding.d.ts +90 -0
  99. package/dist/store/embedding.js +206 -0
  100. package/dist/store/graph-store.d.ts +94 -0
  101. package/dist/store/graph-store.js +641 -0
  102. package/dist/store/l0.d.ts +40 -0
  103. package/dist/store/l0.js +197 -0
  104. package/dist/store/l1.d.ts +93 -0
  105. package/dist/store/l1.js +297 -0
  106. package/dist/store/local-embedding.d.ts +89 -0
  107. package/dist/store/local-embedding.js +227 -0
  108. package/dist/store/model-catalog.d.ts +48 -0
  109. package/dist/store/model-catalog.js +81 -0
  110. package/dist/store/occupancy.d.ts +30 -0
  111. package/dist/store/occupancy.js +134 -0
  112. package/dist/store/pending.d.ts +36 -0
  113. package/dist/store/pending.js +103 -0
  114. package/dist/store/persona.d.ts +15 -0
  115. package/dist/store/persona.js +60 -0
  116. package/dist/store/recall-dedupe.d.ts +26 -0
  117. package/dist/store/recall-dedupe.js +138 -0
  118. package/dist/store/runtime-installer.d.ts +59 -0
  119. package/dist/store/runtime-installer.js +243 -0
  120. package/dist/store/scenes.d.ts +24 -0
  121. package/dist/store/scenes.js +160 -0
  122. package/dist/store/search-utils.d.ts +38 -0
  123. package/dist/store/search-utils.js +100 -0
  124. package/dist/store/session-modes.d.ts +35 -0
  125. package/dist/store/session-modes.js +144 -0
  126. package/dist/store/sqlite.d.ts +246 -0
  127. package/dist/store/sqlite.js +1491 -0
  128. package/dist/store/state.d.ts +41 -0
  129. package/dist/store/state.js +72 -0
  130. package/dist/token-cost.d.ts +23 -0
  131. package/dist/token-cost.js +185 -0
  132. package/dist/tools/index.d.ts +34 -0
  133. package/dist/tools/index.js +758 -0
  134. package/dist/types.d.ts +139 -0
  135. package/dist/types.js +38 -0
  136. package/dist/util/context-occupancy.d.ts +68 -0
  137. package/dist/util/context-occupancy.js +92 -0
  138. package/dist/util/filelog.d.ts +6 -0
  139. package/dist/util/filelog.js +108 -0
  140. package/dist/util/io.d.ts +18 -0
  141. package/dist/util/io.js +97 -0
  142. package/dist/util/recall-budget.d.ts +31 -0
  143. package/dist/util/recall-budget.js +84 -0
  144. package/dist/util/sanitize.d.ts +11 -0
  145. package/dist/util/sanitize.js +67 -0
  146. package/dist/util/text.d.ts +16 -0
  147. package/dist/util/text.js +61 -0
  148. package/dist/util/tokenizer.d.ts +9 -0
  149. package/dist/util/tokenizer.js +50 -0
  150. package/dsh.plugin.json +22 -0
  151. package/package.json +118 -0
@@ -0,0 +1,820 @@
1
+ /**
2
+ * RPC 契约单一事实源(types-only,零运行时代码)。
3
+ *
4
+ * host(stats 端点路由)与 client(浏览器侧)共用的全部 `dsh-memory/*` 端点
5
+ * 请求/响应类型收敛于此,两端各自 `import type`,契约漂移在编译期暴露。
6
+ *
7
+ * 铁律:
8
+ * - 本文件只允许 type/interface 与纯类型推导,不 import 任何运行时值
9
+ * (tsc 产出空 contract.js,client bundle 里 import type 被 esbuild 擦除);
10
+ * - 响应类型按端点实际返回逐字段建模,含 `chain.current[].reasoningEffort` 与
11
+ * `chain.effectiveChain[].effort` 这对故意不同名的字段——链上两种条目形状
12
+ * 不同,不合并;
13
+ * - 端点全集为 26 个(含面板高权限删除 records-delete 与图谱两端点)。
14
+ */
15
+ import type { MemoryFamily, MemoryMode } from './types.js';
16
+ import type { GraphEdge, GraphNode } from './graph/types.js';
17
+ /** 蒸馏思考档位:'' = 自动(模型默认档 → high)。运行时词汇表源是 config.ts 的
18
+ * EFFORT_CHOICES(satisfies readonly EffortChoice[] 反向锁定防漂移)。 */
19
+ export type EffortChoice = '' | 'off' | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
20
+ /** 蒸馏用量/成本记账的层标识(调用点口径)。graph = 知识图谱投影调用。 */
21
+ export type DistillLayer = 'l1-extract' | 'l1-dedup' | 'l2' | 'l3' | 'graph';
22
+ /** 分层输出预算的层键(与 DistillLayer 不同:预算按管线阶段,用量按调用点)。 */
23
+ export type DistillBudgetLayer = 'extract' | 'dedup' | 'l2' | 'l3' | 'graph';
24
+ /** 分层输出预算(token):0 = 跟随内置默认。 */
25
+ export type DistillBudgets = Record<DistillBudgetLayer, number>;
26
+ /**
27
+ * 运行时统一路由链条目:[0] = 主路由(provider/model 双空 = 跟随默认模型),
28
+ * [1..] = 回退链(按序降级);reasoningEffort 为该路由的档位覆盖('' = 跟随部署全局)。
29
+ */
30
+ export interface DistillChainEntry {
31
+ provider: string;
32
+ model: string;
33
+ reasoningEffort: EffortChoice;
34
+ }
35
+ /** 部署静态回退链条目(config.llm.fallbacks):reasoningEffort 可选——与运行时链
36
+ * DistillChainEntry(必填)形状不同,不共用类型。 */
37
+ export interface StaticFallbackEntry {
38
+ provider: string;
39
+ model: string;
40
+ reasoningEffort?: string;
41
+ }
42
+ /** 按层路由的层键:l1 同管 l1-extract + l1-dedup 两个调用点(与成本看板按层归并同源);
43
+ * graph 投影不配层链(回全局解析);预算键(DistillBudgetLayer)是另一套五键词表,不混用。 */
44
+ export type LayerRouteKey = 'l1' | 'l2' | 'l3';
45
+ /** 记忆模式运行时开关(settings-get/set 的 settings 载荷)。 */
46
+ export interface MemoryLiveSettings {
47
+ /** 总开关:关 = 捕获/蒸馏/召回注入全停(数据保留) */
48
+ enabled: boolean;
49
+ /** L0 捕获(原始对话落盘) */
50
+ capture: boolean;
51
+ /** L1 抽取 + L2/L3 蒸馏 */
52
+ distill: boolean;
53
+ /** 召回注入(画像/记忆上下文) */
54
+ recall: boolean;
55
+ /** 蒸馏思考档位运行时覆盖:'' = 跟随静态 config(llm.reasoningEffort) */
56
+ reasoningEffort: EffortChoice;
57
+ /** 蒸馏模型运行时覆盖(供应商 id):'' = 跟随静态 config/默认选择。
58
+ * 与 distillModel 成对生效(单字段不算);部署静态 pin(provider+model 双字段)优先。 */
59
+ distillProvider: string;
60
+ /** 蒸馏模型运行时覆盖(模型 id):'' = 跟随静态 config/默认选择。 */
61
+ distillModel: string;
62
+ /** 运行时统一路由链;非空即权威(旧 distillProvider/distillModel/reasoningEffort 不再参与),
63
+ * 空数组 = 跟随部署静态配置与默认模型。 */
64
+ distillChain: DistillChainEntry[];
65
+ /** 分层输出预算运行时覆盖(token):extract/dedup/l2/l3/graph 五层,0 = 跟随内置默认;
66
+ * 思考档 high/max 的 ×4 放大在覆盖值之上照常生效。 */
67
+ distillBudgets: DistillBudgets;
68
+ /** 输入预算运行时覆盖(字符,≈token):单次蒸馏调用的输入上限,L1 按此分块、
69
+ * 超限截断;0 = 跟随静态配置 llm.maxInputChars。 */
70
+ distillMaxInputChars: number;
71
+ /** 运行时按层路由链:层键 l1/l2/l3 各一条完整链;非空即完整接管该层解析
72
+ * (压过静态 layerRoutes,层内第一优先级);空数组 = 该层跟随(静态层链 → 全局解析逐级兜底)。
73
+ * 写入经 settings-set 逐层校验(头行必须显式)。 */
74
+ distillLayerChains: Record<LayerRouteKey, DistillChainEntry[]>;
75
+ /** 蒸馏通道运行时覆盖:'' = 跟随部署 config(llm.mode);'host' = 复用宿主 ctx.llm;
76
+ * 'direct' = 插件原生直连 llm.baseURL。经 effectiveCfg 注入 cfg.llm.mode。 */
77
+ distillMode: '' | 'host' | 'direct';
78
+ /** 运行时直连端点覆盖(OpenAI 兼容 /v1,'direct' 用):经 effectiveCfg 注入 cfg.llm.baseURL。
79
+ * 非机密,可原样回显。 */
80
+ directBaseURL: string;
81
+ /** 运行时直连 API Key 覆盖(仅 'direct' 用,可空 = 本地免 key):
82
+ * 经 effectiveCfg 注入 cfg.llm.apiKey。属机密,任何回读/日志须脱敏。 */
83
+ directApiKey: string;
84
+ /** 远程嵌入端点运行时覆盖:注入 cfg.embedding.baseUrl。
85
+ * (远程嵌入连接从部署 YAML 改为可在设置 UI 编辑——D 系列评审的 UX 缺口。) */
86
+ embedRemoteBaseURL: string;
87
+ /** 远程嵌入 API Key 运行时覆盖:注入 cfg.embedding.apiKey。属机密,不回读明文、不落日志。 */
88
+ embedRemoteApiKey: string;
89
+ /** 远程嵌入模型名运行时覆盖:注入 cfg.embedding.model。 */
90
+ embedRemoteModel: string;
91
+ /** 远程嵌入维度运行时覆盖:注入 cfg.embedding.dimensions;0 = 未配置/跟随部署。 */
92
+ embedRemoteDimensions: number;
93
+ /** 记忆写删权限门:true 才允许写删记忆工具(memory_add/memory_delete)与面板高权限删除
94
+ * (records-delete)。默认 false(模型写删风险高,须显式在面板开启高权限模式)。 */
95
+ memoryMutate: boolean;
96
+ }
97
+ /** 召回停用原因(session-stats recall.enabled=false 时带出;短路序第一个为假的因子)。 */
98
+ export type RecallDisabledReason = 'deploy' | 'global' | 'session' | 'mode';
99
+ /** 单会话召回统计(悬浮卡信息区数据源)。 */
100
+ export interface RecallSessionStats {
101
+ /** 发生过召回检索的轮次数(含零命中、全量压制与超时)。 */
102
+ injectedTurns: number;
103
+ /** 命中(≥1 条实际注入,或有命中但被去重全量压制)轮次数。 */
104
+ hitTurns: number;
105
+ /** 累计注入条数(去重过滤后、预算截断前)。 */
106
+ totalHits: number;
107
+ /** 总预算超时跳过次数。 */
108
+ timeouts: number;
109
+ /** 累计被去重压制的命中条数(同会话已注入过,不重复注入)。 */
110
+ suppressedRecalls: number;
111
+ /** 最近一轮实际注入条数(0 = 零命中/超时/全量压制;工具指南门控沿用此信号)。 */
112
+ lastHits: number;
113
+ /** 最近一轮检索耗时 ms。 */
114
+ lastDurationMs: number;
115
+ /** 最近一次记账时间(LRU 清理依据)。 */
116
+ updatedAt: number;
117
+ }
118
+ /**
119
+ * 单会话记忆上下文占用(session-stats.memoryOccupancy;悬浮卡与输入栏占用指示器共用)。
120
+ * 形状与算术的唯一来源是 util/context-occupancy 的 OccupancyLedger,禁止任何一侧另写换算。
121
+ * null = 本会话从未注入过。
122
+ */
123
+ export type MemoryOccupancy = import('./util/context-occupancy.js').OccupancyLedger;
124
+ /** 重建阶段。 */
125
+ export type RebuildPhase = 'idle' | 'preparing' | 'distilling' | 'finalizing' | 'done' | 'cancelled' | 'failed';
126
+ /** 重建状态(rebuild-status/start/cancel 端点返回值)。 */
127
+ export interface RebuildStatus {
128
+ running: boolean;
129
+ phase: RebuildPhase;
130
+ /** 已完成的会话块数 / 总块数。 */
131
+ done: number;
132
+ total: number;
133
+ /** L0 体量(idle 时为实时预估,运行中为快照值)。 */
134
+ sessionCount: number;
135
+ messageCount: number;
136
+ /** 预计 LLM 抽取调用次数(下界估算:块数与字符预算取大)。 */
137
+ estCalls: number;
138
+ /** 重建产出的 L1 记录累计条数。 */
139
+ recordsBuilt: number;
140
+ cancelRequested: boolean;
141
+ startedAt: number | null;
142
+ finishedAt: number | null;
143
+ error: string | null;
144
+ /** 归档产物名(提示用户可手工找回)。 */
145
+ archiveNote: string | null;
146
+ }
147
+ /** 反刍阶段。 */
148
+ export type RuminatePhase = 'idle' | 'refreshing' | 'distilling' | 'consolidating' | 'updating' | 'done' | 'cancelled' | 'failed';
149
+ /** 反刍状态(ruminate-status/start/cancel 端点返回值)。 */
150
+ export interface RuminateStatus {
151
+ running: boolean;
152
+ phase: RuminatePhase;
153
+ /** 已完成的会话数(反刍中为已完成蒸馏的切片数,轻量刷新为已完成步骤数)。 */
154
+ done: number;
155
+ /** 待处理会话数(distilling 阶段为会话组数;轻量刷新为待执行步骤数)。 */
156
+ total: number;
157
+ /** 反刍产出的 L1 记录累计条数(反刍控制器追踪)。 */
158
+ recordsBuilt: number;
159
+ /** 当前动作的人类可读描述(L2/L3 单次调用可达分钟级,无此字段界面只能显示"运行中")。 */
160
+ detail?: string | null;
161
+ cancelRequested: boolean;
162
+ startedAt: number | null;
163
+ finishedAt: number | null;
164
+ error: string | null;
165
+ }
166
+ /** 反刍结果(含按族分组摘要)。 */
167
+ export interface RuminateResult {
168
+ status: RuminateStatus;
169
+ byFamily: {
170
+ chat: {
171
+ l1Extracted: number;
172
+ l2Scenes: number;
173
+ l3Updated: boolean;
174
+ };
175
+ work: {
176
+ l1Extracted: number;
177
+ l2Scenes: number;
178
+ l3Updated: boolean;
179
+ };
180
+ };
181
+ }
182
+ /** 概览统计(dsh-memory/stats 端点返回值)。 */
183
+ export interface MemoryStats {
184
+ ok: boolean;
185
+ dataDir: string;
186
+ /** 新会话默认记忆档位(auto/chat/work)。 */
187
+ family: string;
188
+ version: string;
189
+ l0Today: number;
190
+ l1Count: number;
191
+ l1TotalExtracted: number;
192
+ sceneCount: number;
193
+ personaChars: number;
194
+ hasPersona: boolean;
195
+ lastExtractAt: string | null;
196
+ lastL2At: string | null;
197
+ lastL3At: string | null;
198
+ memoriesSinceL2: number;
199
+ memoriesSinceL3: number;
200
+ pendingExtract: number;
201
+ message: string;
202
+ /** 实际生效的阈值(概览进度分母用,避免 UI 硬编码与部署配置脱节)。 */
203
+ thresholds: {
204
+ l2MinNewMemories: number;
205
+ l3Interval: number;
206
+ };
207
+ }
208
+ /** 成本看板时间粒度(趋势图 + 统计口径共用)。 */
209
+ export type Granularity = 'day' | 'week' | 'month';
210
+ /** 成本看板单个时间窗口(day/week/month/all)。 */
211
+ export interface CostWindow {
212
+ range: 'day' | 'week' | 'month' | 'all';
213
+ /** 窗口起点(毫秒;all 为 0)。 */
214
+ since: number;
215
+ calls: number;
216
+ inputChars: number;
217
+ outputTokens: number;
218
+ reasoningTokens: number;
219
+ avgOutputTokens: number;
220
+ medianOutputTokens: number;
221
+ }
222
+ /** 每模型统计指标(层级表格行;均值/中位数按 since=0 全量历史的活跃桶口径)。 */
223
+ export interface ModelMetrics {
224
+ model: string;
225
+ dayCalls: number;
226
+ weekCalls: number;
227
+ monthCalls: number;
228
+ dayOutput: number;
229
+ dayMedian: number;
230
+ weekOutput: number;
231
+ weekMedian: number;
232
+ monthOutput: number;
233
+ monthMedian: number;
234
+ }
235
+ /** 每层级(l1/l2/l3)的模型统计(层级表格)。 */
236
+ export interface LayerMetrics {
237
+ layer: 'l1' | 'l2' | 'l3';
238
+ models: ModelMetrics[];
239
+ }
240
+ /** 层级 × 窗口矩阵里的单个窗口格子。 */
241
+ export interface LayerWindow {
242
+ range: 'day' | 'week' | 'month' | 'all';
243
+ calls: number;
244
+ inputChars: number;
245
+ outputTokens: number;
246
+ reasoningTokens: number;
247
+ avgOutputTokens: number;
248
+ medianOutputTokens: number;
249
+ }
250
+ /** 单个层级在四个窗口的聚合(层级×窗口表格行)。 */
251
+ export interface LayerCost {
252
+ layer: 'l1' | 'l2' | 'l3';
253
+ windows: LayerWindow[];
254
+ }
255
+ /** 趋势单桶。 */
256
+ export interface TrendBucket {
257
+ ts: number;
258
+ total: number;
259
+ byModel: Record<string, number>;
260
+ }
261
+ /** 趋势快照:三个层级各一份连续桶序列。 */
262
+ export interface TrendSnapshot {
263
+ granularity: Granularity;
264
+ byLayer: Record<'l1' | 'l2' | 'l3', TrendBucket[]>;
265
+ }
266
+ /** 按 model 分组的成本行(成本看板用)。 */
267
+ export interface CostByModel {
268
+ provider: string;
269
+ model: string;
270
+ calls: number;
271
+ inputChars: number;
272
+ outputTokens: number;
273
+ reasoningTokens: number;
274
+ }
275
+ /** 成本快照(dsh-memory/token-cost 端点返回值)。 */
276
+ export interface CostSnapshot {
277
+ /** day/week/month/all 四窗口聚合。 */
278
+ windows: CostWindow[];
279
+ /** 全量窗口(all)按 model 分组。 */
280
+ byModel: CostByModel[];
281
+ /** 按层级(l1/l2/l3 归并)在四个窗口的聚合(层级×窗口表格)。 */
282
+ byLayer: LayerCost[];
283
+ /** 每层级的模型统计指标(层级表格)。 */
284
+ byLayerStats: LayerMetrics[];
285
+ /** 趋势图数据。 */
286
+ trend: TrendSnapshot;
287
+ }
288
+ /** 嵌入源:远程 / 本地 / 关闭。 */
289
+ export type EmbeddingSourceKind = 'remote' | 'local' | 'off';
290
+ /** 嵌入运行时安装进度(runtime-installer)。 */
291
+ export interface RuntimeProgress {
292
+ phase: 'idle' | 'installing' | 'ready' | 'error' | 'cancelled';
293
+ /** 插件钉死的目标版本。 */
294
+ targetVersion: string;
295
+ /** runtime 里实际就位的版本(未安装为 null)。 */
296
+ installedVersion: string | null;
297
+ startedAt: number;
298
+ /** 已运行毫秒(读时计算)。 */
299
+ elapsedMs: number;
300
+ /** npm 输出尾行(最近 5 行,让用户看到 npm 在干什么)。 */
301
+ lastLines: string[];
302
+ error?: string;
303
+ }
304
+ /** 下载阶段。 */
305
+ export type DownloadPhase = 'downloading' | 'verifying' | 'done' | 'cancelled' | 'error';
306
+ /** 模型下载进度(下载器 getProgress;无活动下载为 null)。 */
307
+ export interface DownloadProgress {
308
+ modelId: string;
309
+ phase: DownloadPhase;
310
+ /** 当前文件序号(1-based)。 */
311
+ fileIndex: number;
312
+ fileCount: number;
313
+ /** 当前文件已收字节(含续传基线)。 */
314
+ fileReceived: number;
315
+ fileTotal: number;
316
+ /** 整模型累计字节(含已完成文件;分母 = 目录总大小)。 */
317
+ overallReceived: number;
318
+ overallTotal: number;
319
+ /** EMA 平滑速度(字节/秒)。 */
320
+ speedBps: number;
321
+ startedAt: number;
322
+ /** phase=error 时的原因。 */
323
+ error?: string;
324
+ }
325
+ /** 嵌入源活切换阶段。 */
326
+ export type ApplyPhase = 'idle' | 'installing-runtime' | 'warming' | 'switching' | 'reindexing' | 'done' | 'error';
327
+ /** 重嵌入进度。 */
328
+ export interface ReindexProgressState {
329
+ running: boolean;
330
+ l1Done: number;
331
+ l1Total: number;
332
+ l0Done: number;
333
+ l0Total: number;
334
+ startedAt: number;
335
+ cancelled: boolean;
336
+ error?: string;
337
+ }
338
+ /** 嵌入源状态视图(embedding-state-get 端点的主体)。 */
339
+ export interface EmbeddingStateView {
340
+ source: EmbeddingSourceKind;
341
+ activeModel: string | null;
342
+ ceilings: {
343
+ remote: boolean;
344
+ local: boolean;
345
+ };
346
+ /** 生效的远程嵌入连接(运行时覆盖优先于部署;key 明文不回传只给布尔)。 */
347
+ remote: {
348
+ baseURL: string;
349
+ model: string;
350
+ dimensions: number;
351
+ apiKeySet: boolean;
352
+ };
353
+ runtime: RuntimeProgress;
354
+ models: Array<{
355
+ id: string;
356
+ name: string;
357
+ dims: number;
358
+ contextTokens: number;
359
+ tags: string[];
360
+ description: string;
361
+ totalBytes: number;
362
+ bytesOnDisk: number;
363
+ state: 'none' | 'partial' | 'downloaded';
364
+ }>;
365
+ download: DownloadProgress | null;
366
+ apply: {
367
+ phase: ApplyPhase;
368
+ message: string;
369
+ startedAt: number;
370
+ busy: boolean;
371
+ };
372
+ local: {
373
+ state: 'idle' | 'loading' | 'ready' | 'failed' | 'terminated';
374
+ error: string | null;
375
+ } | null;
376
+ reindex: ReindexProgressState;
377
+ activeNote?: string;
378
+ }
379
+ /** dsh-memory/stats */
380
+ export interface StatsResponse extends MemoryStats {
381
+ }
382
+ /** dsh-memory/token-cost */
383
+ export interface TokenCostRequest {
384
+ granularity?: Granularity;
385
+ /** 正整数且 ≤ 明细保留期(0/非法回退全量窗口)。 */
386
+ rangeDays?: number;
387
+ }
388
+ export interface TokenCostResponse extends CostSnapshot {
389
+ }
390
+ /** dsh-memory/session-mode-get | set */
391
+ export interface SessionModeGetRequest {
392
+ sessionId: string;
393
+ }
394
+ export interface SessionModeGetResponse {
395
+ sessionId: string;
396
+ mode: MemoryMode;
397
+ defaultMode: MemoryMode;
398
+ /** 会话级注入覆盖:null = 未覆盖(跟随全局)——线上 JSON 用 null 不用 undefined(序列化丢包)。 */
399
+ recall: boolean | null;
400
+ /** host 解析后的注入生效值(会话覆盖 ?? 全局开关):pill 面文直接消费。 */
401
+ recallResolved: boolean;
402
+ }
403
+ export interface SessionModeSetRequest {
404
+ sessionId: string;
405
+ mode: MemoryMode;
406
+ /** 会话级注入覆盖:布尔 = 设置覆盖;显式 null = 清除(跟随全局);缺省 = 不动
407
+ * (旧 client 纯切档兼容,覆盖不丢)。mode 与 recall 可独立设置。 */
408
+ recall?: boolean | null;
409
+ }
410
+ export interface SessionModeSetResponse {
411
+ sessionId: string;
412
+ mode: MemoryMode;
413
+ /** 设置后的覆盖态(null = 跟随全局)。 */
414
+ recall: boolean | null;
415
+ /** 设置后的注入生效值(client 面文直接消费;清除覆盖后由 host 告知解析结果)。 */
416
+ recallResolved: boolean;
417
+ }
418
+ /** dsh-memory/session-stats(悬浮卡信息区;热路径端点)。 */
419
+ export interface SessionStatsRequest {
420
+ sessionId: string;
421
+ }
422
+ /** 蒸馏管线会话视图(runner 投影,lastDistillAt 已转 ISO)。 */
423
+ export interface SessionDistillView {
424
+ pendingSlice: number;
425
+ parkedSlices: number;
426
+ threshold: number | null;
427
+ producedRecords: number;
428
+ lastDistillAt: string | null;
429
+ }
430
+ export type SessionStatsResponse = {
431
+ supported: false;
432
+ } | {
433
+ supported: true;
434
+ sessionId: string;
435
+ mode: MemoryMode;
436
+ defaultMode: MemoryMode;
437
+ /** 注入统计 + 生效位;enabled=false 时 reason 带短路序第一个为假因子
438
+ * (deploy 部署上限 / global 全局开关 / session 会话只写 / mode 档位关闭)。 */
439
+ recall: {
440
+ enabled: boolean;
441
+ reason?: RecallDisabledReason;
442
+ } & RecallSessionStats;
443
+ /** 记忆上下文占用账本(未注入过的会话为 null)。 */
444
+ memoryOccupancy: MemoryOccupancy | null;
445
+ /** 旧会话回填:host 侧估出的双通道份额——召回按 live 会话 surface 现扫
446
+ * (null = 会话不在 store),稳定区按当前组词折算。账本存在时客户端取两者较大值。 */
447
+ occupancyBackfill: {
448
+ recallTokens: number | null;
449
+ profileTokens: number;
450
+ } | null;
451
+ /** 主对话模型的官方声明上下文窗口(占用占比分母;null = 未声明/解析失败,UI 降级隐藏占比)。 */
452
+ contextWindowTokens: number | null;
453
+ distill: SessionDistillView;
454
+ l0Count: number;
455
+ retrieval: 'hybrid' | 'vector' | 'keyword' | 'none';
456
+ global: {
457
+ degraded: boolean;
458
+ pendingTotal: number;
459
+ lastExtractAt: string | null;
460
+ };
461
+ };
462
+ /** dsh-memory/settings-get */
463
+ export interface SettingsGetResponse {
464
+ supported: boolean;
465
+ settings: MemoryLiveSettings;
466
+ /** 静态部署上限(cordis.patch.yml):运行时开关与它取 AND。 */
467
+ ceilings: {
468
+ capture: boolean;
469
+ distill: boolean;
470
+ recall: boolean;
471
+ };
472
+ effort: {
473
+ current: EffortChoice;
474
+ effective: EffortChoice;
475
+ fallback: EffortChoice;
476
+ options: string[];
477
+ route?: {
478
+ provider: string;
479
+ model: string;
480
+ };
481
+ };
482
+ budgets: {
483
+ current: DistillBudgets;
484
+ defaults: DistillBudgets;
485
+ effective: DistillBudgets;
486
+ };
487
+ inputBudget: {
488
+ current: number;
489
+ fallback: number;
490
+ effective: number;
491
+ };
492
+ }
493
+ /** dsh-memory/settings-set(patch 语义:只带要改的键)。 */
494
+ export interface SettingsSetRequest {
495
+ enabled?: boolean;
496
+ capture?: boolean;
497
+ distill?: boolean;
498
+ recall?: boolean;
499
+ distillChain?: DistillChainEntry[];
500
+ /** 运行时按层路由链:逐层 patch(只带要改的层;空数组 = 该层回到跟随)。 */
501
+ distillLayerChains?: Partial<Record<LayerRouteKey, DistillChainEntry[]>>;
502
+ reasoningEffort?: EffortChoice;
503
+ distillProvider?: string;
504
+ distillModel?: string;
505
+ distillBudgets?: {
506
+ extract: number;
507
+ dedup: number;
508
+ l2: number;
509
+ l3: number;
510
+ graph: number;
511
+ };
512
+ distillMaxInputChars?: number;
513
+ /** 蒸馏通道运行时覆盖:'' = 跟随部署 config;'host' = 复用宿主;'direct' = 插件原生直连。 */
514
+ distillMode?: '' | 'host' | 'direct';
515
+ /** 运行时直连端点覆盖('direct' 用;非机密,可回显)。 */
516
+ directBaseURL?: string;
517
+ /** 运行时直连 API Key 覆盖('direct' 用;属机密,写入后不回读、不落日志)。 */
518
+ directApiKey?: string;
519
+ /** 远程嵌入端点/模型运行时覆盖(非机密可回显)。 */
520
+ embedRemoteBaseURL?: string;
521
+ embedRemoteModel?: string;
522
+ /** 远程嵌入维度运行时覆盖(0 = 未配置)。 */
523
+ embedRemoteDimensions?: number;
524
+ /** 远程嵌入 API Key 运行时覆盖(属机密,写入后不回读、不落日志)。 */
525
+ embedRemoteApiKey?: string;
526
+ /** 记忆写删权限门(true = 允许写删工具与面板高权限删除)。 */
527
+ memoryMutate?: boolean;
528
+ }
529
+ export interface SettingsSetResponse {
530
+ ok: true;
531
+ settings: MemoryLiveSettings;
532
+ }
533
+ /** dsh-memory/list-records(记忆浏览器;hitToUiRecord 投影)。 */
534
+ export interface ListRecordsRequest {
535
+ query?: string;
536
+ type?: string;
537
+ scene?: string;
538
+ /** Hall 过滤(metadata.hall == 该值;空 = 不过滤)。 */
539
+ hall?: string;
540
+ /** 1~200,默认 50。 */
541
+ limit?: number;
542
+ /** 0~1_000_000。 */
543
+ offset?: number;
544
+ }
545
+ /** 浏览器卡片字段(比 MemoryRecord 精简,去掉大 metadata;epoch→ISO、snake→camel)。 */
546
+ export interface UiRecord {
547
+ id: string;
548
+ content: string;
549
+ type: string;
550
+ priority: number;
551
+ scene: string;
552
+ family: MemoryFamily | null;
553
+ /** Hall 标签(metadata.hall,可空)。 */
554
+ hall: string | null;
555
+ timestamps: string[];
556
+ createdAt: string | null;
557
+ updatedAt: string | null;
558
+ version: number;
559
+ sourceMessageIds: string[];
560
+ /** 检索相关度(列表路径无 score → null)。 */
561
+ score: number | null;
562
+ }
563
+ export interface ListRecordsResponse {
564
+ items: UiRecord[];
565
+ hasMore: boolean;
566
+ /** 列表路径给总数;检索路径无法便宜计数 → null。 */
567
+ total: number | null;
568
+ /** 检索单次上限截断(结果可能不完整)。 */
569
+ truncated: boolean;
570
+ /** 场景筛选下拉选项(仅 offset===0 时附带)。 */
571
+ scenes?: string[];
572
+ }
573
+ /** dsh-memory/records-delete(面板高权限删除指定记忆;须 memoryMutate 开启)。 */
574
+ export interface RecordsDeleteRequest {
575
+ /** 要删除的 L1 record id 列表(≤200)。 */
576
+ ids: string[];
577
+ }
578
+ export interface RecordsDeleteResponse {
579
+ deleted: number;
580
+ }
581
+ /** dsh-memory/graph-search(图谱节点检索;紧凑节点卡)。 */
582
+ export interface GraphSearchRequest {
583
+ /** 自然语言查询(≤4096 字符;空查询返回空)。 */
584
+ query?: string;
585
+ /** 1~20,默认 8。 */
586
+ limit?: number;
587
+ }
588
+ export interface GraphSearchResponse {
589
+ items: Array<{
590
+ node: GraphNode;
591
+ /** 排序分(仅排序语义,非事实置信度)。 */
592
+ score: number;
593
+ matchedFields: string[];
594
+ matchReason: string;
595
+ }>;
596
+ }
597
+ /** dsh-memory/graph-node-get(节点详情展开;悬挂 id 返回 node=null 不解析)。 */
598
+ export interface GraphNodeGetRequest {
599
+ id: string;
600
+ }
601
+ export interface GraphNodeGetResponse {
602
+ node: GraphNode | null;
603
+ /** 与该节点相连的 active 边。 */
604
+ edges: GraphEdge[];
605
+ }
606
+ /** dsh-memory/scenes(两族拼接的混合视图)。 */
607
+ export interface ScenesResponse {
608
+ items: Array<{
609
+ path: string;
610
+ family: MemoryFamily;
611
+ summary: string;
612
+ updated: string;
613
+ heat: number;
614
+ content: string;
615
+ }>;
616
+ }
617
+ /** dsh-memory/persona(两族以 family 注释 + 分隔线拼接)。 */
618
+ export interface PersonaResponse {
619
+ content: string;
620
+ }
621
+ /** dsh-memory/log-tail */
622
+ export interface LogTailRequest {
623
+ /** 1~1000,默认 200。 */
624
+ lines?: number;
625
+ }
626
+ export interface LogTailResponse {
627
+ lines: string[];
628
+ }
629
+ /** dsh-memory/rebuild-* */
630
+ export type RebuildStatusResponse = {
631
+ supported: false;
632
+ running: false;
633
+ phase: 'idle';
634
+ } | RebuildStatus;
635
+ /** dsh-memory/ruminate-* */
636
+ export type RuminateStatusResponse = {
637
+ supported: false;
638
+ running: false;
639
+ phase: 'idle';
640
+ } | RuminateStatus;
641
+ /** dsh-memory/llm-providers(蒸馏路由链编辑器数据源)。 */
642
+ /** 生效链条目:effort 与 DistillChainEntry.reasoningEffort 不同名不合并(链上两种条目形状的事实)。 */
643
+ export interface EffectiveChainRoute {
644
+ provider: string;
645
+ model: string;
646
+ effort: string;
647
+ }
648
+ /** 按层层链视图:runtime = 设置页运行时层链(pinned 下不生效,视图照实返回存量);
649
+ * static = 部署 YAML layerRoutes;effectiveChain = 该层实际链(层链完整替换,或跟随全局时
650
+ * 与全局链同值);source 三态:runtime 接管 / static 生效 / global 跟随全局解析。 */
651
+ export interface LayerChainView {
652
+ runtime: DistillChainEntry[];
653
+ static: StaticFallbackEntry[];
654
+ effectiveChain: EffectiveChainRoute[];
655
+ source: 'runtime' | 'static' | 'global';
656
+ }
657
+ export interface LlmProvidersResponse {
658
+ supported: true;
659
+ providers: Array<{
660
+ id: string;
661
+ name: string;
662
+ }>;
663
+ default: {
664
+ provider: string;
665
+ model: string;
666
+ } | null;
667
+ /** 部署静态 pin(provider+model 双字段)优先于运行时选择,UI 据此禁用选择器。 */
668
+ pinned: boolean;
669
+ current: {
670
+ provider: string;
671
+ model: string;
672
+ };
673
+ /** 所选供应商是否仍在已注册路由中(用户删掉供应商后提示回退)。 */
674
+ currentRegistered: boolean;
675
+ effective: {
676
+ provider: string;
677
+ model: string;
678
+ } | null;
679
+ chain: {
680
+ current: DistillChainEntry[];
681
+ static: StaticFallbackEntry[];
682
+ effectiveChain: EffectiveChainRoute[];
683
+ source: 'runtime' | 'static';
684
+ };
685
+ /** 按层层链(l1/l2/l3;l1 同管抽取+去重两个调用点)。 */
686
+ layerChains: Record<LayerRouteKey, LayerChainView>;
687
+ /** 蒸馏通道视图(direct 解耦通道的运行时/部署态)。apiKey 不回传明文,只给布尔。 */
688
+ channel: DirectChannelView;
689
+ }
690
+ /** 蒸馏通道视图(llm-providers 的 channel 块数据源)。 */
691
+ export interface DirectChannelView {
692
+ /** 运行时覆盖档:'' = 跟随部署 config;'host'/'direct' = 运行时锁定。 */
693
+ runtime: '' | 'host' | 'direct';
694
+ /** 实际生效档(runtime override → 部署 cfg.llm.mode,缺省 'host')。 */
695
+ effective: 'host' | 'direct';
696
+ /** 运行时直连端点覆盖值(settings 存;非机密可回显)。 */
697
+ runtimeBaseURL: string;
698
+ /** 部署直连端点(cfg.llm.baseURL,供「跟随部署」预览)。 */
699
+ deployedBaseURL: string;
700
+ /** 部署通道档(cfg.llm.mode)。 */
701
+ deployed: 'host' | 'direct';
702
+ /** 运行时直连 apiKey 是否已填(明文不回传)。 */
703
+ runtimeApiKeySet: boolean;
704
+ /** 部署直连 apiKey 是否已配置(cfg.llm.apiKey 非空?)。 */
705
+ deployedApiKeySet: boolean;
706
+ /** 生效为 direct 时是否配置齐(directBaseURL+model 都非空);未齐时给 tooltip 提示。 */
707
+ directReady: boolean;
708
+ }
709
+ /** dsh-memory/llm-models */
710
+ export interface LlmModelsRequest {
711
+ provider: string;
712
+ }
713
+ /** 模型条目(附思考档位能力表,探询失败/未声明 → 空表)。 */
714
+ export interface ModelWithEfforts {
715
+ id: string;
716
+ name: string;
717
+ description: string | null;
718
+ efforts: string[];
719
+ }
720
+ export interface LlmModelsResponse {
721
+ provider: string;
722
+ models: ModelWithEfforts[];
723
+ }
724
+ /** dsh-memory/embedding-state-get */
725
+ export type EmbeddingStateResponse = {
726
+ supported: false;
727
+ } | ({
728
+ supported: true;
729
+ } & EmbeddingStateView);
730
+ /** dsh-memory/embedding-source-set */
731
+ export interface EmbeddingSourceSetRequest {
732
+ source: EmbeddingSourceKind;
733
+ activeModel?: string | null;
734
+ }
735
+ export interface EmbeddingSourceSetResponse {
736
+ accepted: true;
737
+ }
738
+ /** dsh-memory/embedding-download-start */
739
+ export interface EmbeddingDownloadStartRequest {
740
+ modelId: string;
741
+ }
742
+ export interface EmbeddingDownloadStartResponse {
743
+ accepted: true;
744
+ }
745
+ /** dsh-memory/embedding-download-cancel | runtime-cancel | reindex-cancel */
746
+ export interface EmbeddingCancelResponse {
747
+ cancelled: boolean;
748
+ }
749
+ /** dsh-memory/embedding-model-delete */
750
+ export interface EmbeddingModelDeleteRequest {
751
+ modelId: string;
752
+ }
753
+ export interface EmbeddingModelDeleteResponse {
754
+ ok: boolean;
755
+ error?: string;
756
+ }
757
+ export interface DshMemoryRequestMap {
758
+ 'dsh-memory/stats': Record<string, never>;
759
+ 'dsh-memory/token-cost': TokenCostRequest;
760
+ 'dsh-memory/session-mode-get': SessionModeGetRequest;
761
+ 'dsh-memory/session-mode-set': SessionModeSetRequest;
762
+ 'dsh-memory/session-stats': SessionStatsRequest;
763
+ 'dsh-memory/settings-get': Record<string, never>;
764
+ 'dsh-memory/settings-set': SettingsSetRequest;
765
+ 'dsh-memory/list-records': ListRecordsRequest;
766
+ 'dsh-memory/records-delete': RecordsDeleteRequest;
767
+ 'dsh-memory/graph-search': GraphSearchRequest;
768
+ 'dsh-memory/graph-node-get': GraphNodeGetRequest;
769
+ 'dsh-memory/scenes': Record<string, never>;
770
+ 'dsh-memory/persona': Record<string, never>;
771
+ 'dsh-memory/log-tail': LogTailRequest;
772
+ 'dsh-memory/rebuild-status': Record<string, never>;
773
+ 'dsh-memory/rebuild-start': Record<string, never>;
774
+ 'dsh-memory/rebuild-cancel': Record<string, never>;
775
+ 'dsh-memory/ruminate-status': Record<string, never>;
776
+ 'dsh-memory/ruminate-start': Record<string, never>;
777
+ 'dsh-memory/ruminate-cancel': Record<string, never>;
778
+ 'dsh-memory/llm-providers': Record<string, never>;
779
+ 'dsh-memory/llm-models': LlmModelsRequest;
780
+ 'dsh-memory/embedding-state-get': Record<string, never>;
781
+ 'dsh-memory/embedding-source-set': EmbeddingSourceSetRequest;
782
+ 'dsh-memory/embedding-download-start': EmbeddingDownloadStartRequest;
783
+ 'dsh-memory/embedding-download-cancel': Record<string, never>;
784
+ 'dsh-memory/embedding-model-delete': EmbeddingModelDeleteRequest;
785
+ 'dsh-memory/embedding-runtime-cancel': Record<string, never>;
786
+ 'dsh-memory/embedding-reindex-cancel': Record<string, never>;
787
+ }
788
+ export interface DshMemoryResponseMap {
789
+ 'dsh-memory/stats': StatsResponse;
790
+ 'dsh-memory/token-cost': TokenCostResponse;
791
+ 'dsh-memory/session-mode-get': SessionModeGetResponse;
792
+ 'dsh-memory/session-mode-set': SessionModeSetResponse;
793
+ 'dsh-memory/session-stats': SessionStatsResponse;
794
+ 'dsh-memory/settings-get': SettingsGetResponse;
795
+ 'dsh-memory/settings-set': SettingsSetResponse;
796
+ 'dsh-memory/list-records': ListRecordsResponse;
797
+ 'dsh-memory/records-delete': RecordsDeleteResponse;
798
+ 'dsh-memory/graph-search': GraphSearchResponse;
799
+ 'dsh-memory/graph-node-get': GraphNodeGetResponse;
800
+ 'dsh-memory/scenes': ScenesResponse;
801
+ 'dsh-memory/persona': PersonaResponse;
802
+ 'dsh-memory/log-tail': LogTailResponse;
803
+ 'dsh-memory/rebuild-status': RebuildStatusResponse;
804
+ 'dsh-memory/rebuild-start': RebuildStatus;
805
+ 'dsh-memory/rebuild-cancel': RebuildStatus;
806
+ 'dsh-memory/ruminate-status': RuminateStatusResponse;
807
+ 'dsh-memory/ruminate-start': RuminateStatus;
808
+ 'dsh-memory/ruminate-cancel': RuminateStatus;
809
+ 'dsh-memory/llm-providers': LlmProvidersResponse;
810
+ 'dsh-memory/llm-models': LlmModelsResponse;
811
+ 'dsh-memory/embedding-state-get': EmbeddingStateResponse;
812
+ 'dsh-memory/embedding-source-set': EmbeddingSourceSetResponse;
813
+ 'dsh-memory/embedding-download-start': EmbeddingDownloadStartResponse;
814
+ 'dsh-memory/embedding-download-cancel': EmbeddingCancelResponse;
815
+ 'dsh-memory/embedding-model-delete': EmbeddingModelDeleteResponse;
816
+ 'dsh-memory/embedding-runtime-cancel': EmbeddingCancelResponse;
817
+ 'dsh-memory/embedding-reindex-cancel': EmbeddingCancelResponse;
818
+ }
819
+ /** 全部端点名(client 调用与 host case 表的共用字面量来源)。 */
820
+ export type DshMemoryEndpoint = keyof DshMemoryResponseMap;