dsh-layered-memory 0.8.7 → 0.8.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.
- package/README.en.md +47 -4
- package/README.md +51 -4
- package/assets/changelog/0.8.9/01-panel.png +0 -0
- package/assets/changelog/0.8.9/02-halo.png +0 -0
- package/assets/changelog/0.8.9/03-layer-segmented-panel.png +0 -0
- package/assets/changelog/0.8.9/04-layer-l1-panel.png +0 -0
- package/dist/client.js +3542 -3293
- package/dist/config.d.ts +286 -4
- package/dist/config.js +27 -0
- package/dist/contract.d.ts +652 -0
- package/dist/contract.js +1 -0
- package/dist/hooks/recall.d.ts +13 -18
- package/dist/hooks/recall.js +143 -20
- package/dist/index.d.ts +268 -4
- package/dist/index.js +9 -3
- package/dist/llm-usage.d.ts +2 -1
- package/dist/llm.d.ts +63 -11
- package/dist/llm.js +165 -15
- package/dist/pipeline/rebuild.d.ts +2 -21
- package/dist/pipeline/runner.d.ts +3 -3
- package/dist/pipeline/runner.js +52 -10
- package/dist/settings.d.ts +25 -29
- package/dist/settings.js +107 -1
- package/dist/stats.d.ts +9 -26
- package/dist/stats.js +149 -22
- package/dist/store/cost-ledger.d.ts +78 -0
- package/dist/store/cost-ledger.js +173 -0
- package/dist/store/download-queue.d.ts +2 -20
- package/dist/store/embedding-source.d.ts +2 -52
- package/dist/store/occupancy.d.ts +30 -0
- package/dist/store/occupancy.js +134 -0
- package/dist/store/runtime-installer.d.ts +2 -13
- package/dist/store/sqlite.d.ts +11 -61
- package/dist/store/sqlite.js +15 -150
- package/dist/token-cost.d.ts +3 -72
- package/dist/util/context-occupancy.d.ts +68 -0
- package/dist/util/context-occupancy.js +92 -0
- package/package.json +8 -4
package/README.en.md
CHANGED
|
@@ -230,8 +230,8 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
|
|
|
230
230
|
config: # keys replace whole lines (no deep merge); write out all keys you want to keep
|
|
231
231
|
family: auto # default mode for new sessions: auto | chat | work
|
|
232
232
|
llm: # static distillation route (both fields set = deployment pin,
|
|
233
|
-
provider: '' # which outranks the settings-page
|
|
234
|
-
model: '' # follows the
|
|
233
|
+
provider: '' # which outranks the settings-page route chain; when empty the route
|
|
234
|
+
model: '' # follows the route-chain primary row in the settings page or the default model)
|
|
235
235
|
```
|
|
236
236
|
|
|
237
237
|
| Field | Default | Description |
|
|
@@ -272,9 +272,11 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
|
|
|
272
272
|
| `embedding.allowLocalModels` | `true` | Allow the local embedding tier (deployment ceiling; when off, no model downloads and no local tier in settings) |
|
|
273
273
|
| `embedding.mirror` | `https://hf-mirror.com` | Download mirror root for local models (can be changed back to `https://huggingface.co`) |
|
|
274
274
|
| `embedding.proxy` | `''` | Three-state download proxy: `''` (default) = auto-detect proxy env vars (`HTTPS_PROXY`/`ALL_PROXY` etc., honoring `NO_PROXY`); `none` = disable, always direct; any other value = proxy URL (e.g. `http://127.0.0.1:7890`). Direct connections to the mirror are intermittently unreachable on some networks (connect timeouts and poisoned bytes have both been observed) — keep the default auto-detection on machines with a proxy |
|
|
275
|
-
| `llm.provider/model` | empty | Static distillation route (deployment pin): when **both** fields are set the route is locked, outranking the settings-page
|
|
275
|
+
| `llm.provider/model` | empty | Static distillation route (deployment pin): when **both** fields are set the route is locked, outranking the settings-page runtime route chain and the default model (deployments can force distillation onto a specific route); when empty the route follows "settings-page route-chain primary → default model". At runtime, configure the primary route and fallback chain in the **route-chain editor** under Settings → Memory → Overview → distillation parameters (pick from **configured providers**, including custom ones added in dsh Settings → Models; the primary row may stay empty to follow the default model) — a non-empty chain takes over this static config wholesale, effective immediately with no restart |
|
|
276
|
+
| `llm.fallbacks` | `[]` | Distillation fallback chain: an ordered list of backup routes tried one by one when the primary route fails (error / cut-off / network error / **empty output**); each entry is `{provider, model, reasoningEffort?}` (a non-empty effort overrides the global `llm.reasoningEffort`, still clamped by model capability); entries identical to the primary route are skipped; **each route gets the full `timeoutMs`**; when all routes fail, the existing per-session backoff takes over. Empty list (default) = single-route behavior unchanged (see [Distillation fallback chain & slow-TTFT models](#distillation-fallback-chain--slow-ttft-models) below); a non-empty settings-page runtime chain (`distillChain`) takes over **both** the primary route and the fallback chain (a single-row chain = explicitly no fallbacks), empty = follow this config |
|
|
277
|
+
| `llm.layerRoutes` | `{}` | **Per-layer distillation routing** (#34): keys `l1`/`l2`/`l3`, each holding a **complete chain** (entries like `llm.fallbacks`, **head row must have both provider+model explicitly**). A non-empty chain **fully replaces** that layer's resolution (its primary and fallbacks all come from the layer chain; the global chain no longer participates); empty/missing = the layer follows the global chain. `l1` covers both extraction and dedup call sites. Layers can also be edited at runtime in the segmented panel under distillation parameters on the settings page (takes priority over this static config); a deployment pin does not disable static layer chains (same deployer-owned config as the fallback-chain precedent). Orthogonal to and composable with the fallback chain — one complete chain per layer (ADR-0005) |
|
|
276
278
|
| `llm.maxTokens` | `65536` | Fallback output cap for non-layered calls. Each distillation stage has its own budget (extraction 16k / dedup 8k / L2 32k / L3 16k; auto ×4 when the reasoning effort is high/xhigh/max, so thinking can't starve the text budget); the per-layer budgets are runtime-adjustable in Settings → Memory → Overview → distillation parameters (empty/0 = built-in defaults) |
|
|
277
|
-
| `llm.reasoningEffort` | empty | Distillation reasoning effort: empty = **auto** (resolved from model capability: the model's default tier, else `high`); an explicit value (`off`/`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`) is only sent when the model declares support — effort vocabularies differ across providers (deepseek accepts `off`, OpenAI-style APIs use `none`, models that declare no tiers get nothing), and unsupported tiers degrade to not-sending with a one-time warning; output budgets auto-×4 at high/xhigh/max.
|
|
279
|
+
| `llm.reasoningEffort` | empty | Distillation reasoning effort: empty = **auto** (resolved from model capability: the model's default tier, else `high`); an explicit value (`off`/`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`) is only sent when the model declares support — effort vocabularies differ across providers (deepseek accepts `off`, OpenAI-style APIs use `none`, models that declare no tiers get nothing), and unsupported tiers degrade to not-sending with a one-time warning; output budgets auto-×4 at high/xhigh/max. At runtime, override the effort **per route** in the settings-page route-chain editor (per-row dropdown; the tier list follows each model's declared capability live, defaulting to this value) |
|
|
278
280
|
| `llm.temperature` | `0.3` | Distillation temperature |
|
|
279
281
|
| `llm.maxInputChars` | `700000` | Input character budget per distillation call (over-budget L1 inputs are chunked automatically); runtime-adjustable in Settings → distillation parameters → input budget (empty/0 = follow this value) |
|
|
280
282
|
| `llm.timeoutMs` | `120000` | Per-call distillation timeout (ms) |
|
|
@@ -282,6 +284,47 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
|
|
|
282
284
|
| `tools` | `true` | Whether to register model-callable memory tools |
|
|
283
285
|
| `benchControl` | `false` | Register the in-process bench control service (rebuild trigger / session-mode setting / distillation usage snapshot — used by the benchmark's lifecycle track). Off by default — zero surface in production deployments; do not enable casually |
|
|
284
286
|
|
|
287
|
+
### Distillation fallback chain & slow-TTFT models
|
|
288
|
+
|
|
289
|
+
Free/slow tiers of some inference providers have **first-token latencies (TTFT) upwards of 20 seconds**, while some upstream gateways cut a silent connection at ~20s — distillation calls then fail at a fixed ~20s (`llm aborted`) long before the plugin's 120s timeout could ever matter (the scenario measured in [#31](https://github.com/JunNanLYS/dsh-layered-memory/issues/31)). Three mitigations, pick as needed:
|
|
290
|
+
|
|
291
|
+
1. **Switch route** (most direct): change the primary route live in the route-chain editor under Settings → Memory → Overview → distillation parameters (or move a fast route to the head of the chain), or pin `llm.provider`/`llm.model` statically.
|
|
292
|
+
2. **Fallback chain** (automatic demotion): when the primary route fails, backup routes are tried in order with no manual intervention:
|
|
293
|
+
|
|
294
|
+
```yaml
|
|
295
|
+
llm:
|
|
296
|
+
provider: opencode-go # primary route (may be left unpinned: settings-page route-chain primary / default model)
|
|
297
|
+
model: ox-alpha-free
|
|
298
|
+
fallbacks: # entry order = demotion priority; unset = single-route behavior unchanged
|
|
299
|
+
- provider: opencode-go
|
|
300
|
+
model: deepseek-v4-flash
|
|
301
|
+
reasoningEffort: low # optional: per-route effort override (defaults to the global value)
|
|
302
|
+
- provider: deepseek-official
|
|
303
|
+
model: deepseek-v4-flash
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
3. **Per-layer routing** (each layer on its own channel): distillation layers want different things from a model (L1 is high-frequency and wants cheap/fast/stable; L3 tolerates slow first packets but needs strong capability), so diverging layers can get their own chain — one **complete fallback chain per layer**, while unconfigured layers keep using the global chain:
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
llm:
|
|
310
|
+
layerRoutes: # per-layer routing (#34); the head row must set provider+model explicitly
|
|
311
|
+
l1: # l1 covers both extraction and dedup call sites: a cheap, fast, stable chain
|
|
312
|
+
- provider: opencode-go
|
|
313
|
+
model: deepseek-v4-flash
|
|
314
|
+
reasoningEffort: low
|
|
315
|
+
- provider: deepseek-official # in-layer fallback: L1 failures demote only here, never onto the global chain
|
|
316
|
+
model: deepseek-v4-flash
|
|
317
|
+
l3: # L3 persona distillation: low frequency, large inputs — a strong-capability chain
|
|
318
|
+
- provider: deepseek-official
|
|
319
|
+
model: deepseek-v4-flash
|
|
320
|
+
reasoningEffort: high
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Layers can also be edited at runtime in the **segmented panel** (global default / L1 / L2 / L3) under Settings → Memory → Overview → distillation parameters. In-layer priority: runtime layer chain > this static YAML layer chain > global default chain, falling back level by level.
|
|
324
|
+
|
|
325
|
+
Failure = error / cut-off / network error / **empty output** (stream ends normally with 0 characters — worthless for distillation since parsing always fails, so it is treated as a route failure rather than an empty return); caller-initiated cancellation does not demote; each route gets the **full** `llm.timeoutMs` (a shared budget would give a slow-TTFT fallback route less time than its real first-packet needs, defeating the chain); token costs are recorded per attempt (failed attempts get a row too, with whatever tokens arrived before the stream broke), and successful calls are attributed to the route that actually served. The route chain can also be adjusted at runtime in the route-chain editor under Settings → Memory → Overview → distillation parameters (no config edit or restart needed); the YAML below suits deployments that want to pin the static chain.
|
|
326
|
+
4. **Raise the timeout**: `llm.timeoutMs` only helps when the route is genuinely slow but the gateway doesn't cut; if the gateway kills at 20s, raising the plugin timeout is futile — use the first two layers.
|
|
327
|
+
|
|
285
328
|
## Storage Layout
|
|
286
329
|
|
|
287
330
|
<p align="center">
|
package/README.md
CHANGED
|
@@ -232,8 +232,8 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
|
|
|
232
232
|
name: dsh-layered-memory
|
|
233
233
|
config: # 键按行整体替换(不深合并),按需写全要保留的键
|
|
234
234
|
family: auto # 新会话默认档:auto | chat | work
|
|
235
|
-
llm: # 蒸馏模型静态路由(双字段齐 = 部署 pin
|
|
236
|
-
provider: '' #
|
|
235
|
+
llm: # 蒸馏模型静态路由(双字段齐 = 部署 pin,优先于设置页路由链;
|
|
236
|
+
provider: '' # 留空则跟随设置页路由链主路由或当前默认模型)
|
|
237
237
|
model: ''
|
|
238
238
|
```
|
|
239
239
|
|
|
@@ -275,9 +275,11 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
|
|
|
275
275
|
| `embedding.allowLocalModels` | `true` | 允许本地嵌入档(部署上限:关闭后设置页不能下载模型、不能切本地档) |
|
|
276
276
|
| `embedding.mirror` | `https://hf-mirror.com` | 本地模型下载镜像根地址(可改回官方 `https://huggingface.co`) |
|
|
277
277
|
| `embedding.proxy` | `''` | 模型下载代理三态:`''`(默认)= 自动探测代理环境变量(`HTTPS_PROXY`/`ALL_PROXY` 等,尊重 `NO_PROXY`);`none` = 禁用强制直连;其他值 = 代理 URL(如 `http://127.0.0.1:7890`)。镜像直连在国内网络间歇不可达(直连超时与污染字节交替出现过),开代理的机器建议保持默认自动探测 |
|
|
278
|
-
| `llm.provider/model` | 空 | 蒸馏模型静态路由(部署 pin):provider 与 model
|
|
278
|
+
| `llm.provider/model` | 空 | 蒸馏模型静态路由(部署 pin):provider 与 model **双字段齐**时锁定蒸馏路由,优先于设置页的运行时路由链与默认模型(部署可强制蒸馏走指定路由);留空则跟随"设置页路由链主路由 → 默认模型"。运行时可在设置页 → 记忆 → 概览 → 蒸馏参数的**蒸馏路由链编辑器**里配置主路由与回退链(从**已配置的供应商**(含 dsh 设置 → 模型里添加的自定义供应商)中选择,主路由行可留空跟随默认模型),非空即整体接管本静态配置,即时生效无需重启 |
|
|
279
|
+
| `llm.fallbacks` | `[]` | 蒸馏回退链:主路由失败(报错/被掐断/网络异常/**空输出**)后按条目顺序逐个降级尝试的备用路由列表,条目 = `{provider, model, reasoningEffort?}`(档位非空覆盖全局 `llm.reasoningEffort`,仍按模型能力钳制);与主路由完全相同的条目自动跳过;**每条路由各享全额 `timeoutMs`**;全部失败交既有按会话退避重试。空数组(缺省)= 单路由行为不变(详见下方[蒸馏回退链与慢 TTFT 模型](#蒸馏回退链与慢-ttft-模型));设置页运行时路由链(`distillChain`)非空时**整体接管**主路由与回退链(单行链 = 显式无回退),空 = 跟随本配置 |
|
|
280
|
+
| `llm.layerRoutes` | `{}` | 蒸馏**按层路由**:层键 `l1`/`l2`/`l3` 各配一条**完整链**(条目同 `llm.fallbacks`,**头行必须 provider+model 双显式**),非空即**完整替换**该层解析(该层主路由与回退都归层链管,全局链对该层不参与),空/缺省 = 该层跟随全局;`l1` 同管抽取+去重两个调用点。运行时可在设置页「蒸馏参数」分段面板里按层编辑(优先于本静态配置);部署 pin 不废静态层链(同为部署配置,同回退链先例)。与回退链正交可组合——每层各自一条链(ADR-0005) |
|
|
279
281
|
| `llm.maxTokens` | `65536` | 未分层调用的兜底输出总闸。各蒸馏层有独立预算(抽取 16k / 去重 8k / L2 32k / L3 16k;思考档 high/xhigh/max 时自动 ×4,防 reasoning 吃光预算),分层预算可在设置页 → 记忆 → 概览 → 蒸馏参数运行时调整(留空/0 = 跟随内置默认) |
|
|
280
|
-
| `llm.reasoningEffort` | 空 | 蒸馏思考档位:空串 = **自动**(按模型能力解析:模型默认档 → `high`);显式值(`off`/`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`)仅在该模型声明支持时发送——跨供应商 effort 词汇表不同(deepseek 认 `off`,OpenAI 系是 `none`,未声明档位的模型不传),不支持的档位自动降级为不传并告警一次;思考档 high/xhigh/max 时输出预算自动 ×4
|
|
282
|
+
| `llm.reasoningEffort` | 空 | 蒸馏思考档位:空串 = **自动**(按模型能力解析:模型默认档 → `high`);显式值(`off`/`none`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`)仅在该模型声明支持时发送——跨供应商 effort 词汇表不同(deepseek 认 `off`,OpenAI 系是 `none`,未声明档位的模型不传),不支持的档位自动降级为不传并告警一次;思考档 high/xhigh/max 时输出预算自动 ×4。运行时可在设置页路由链编辑器里**逐路由**覆盖档位(行内下拉,词表按各模型声明的能力实时显示,缺省跟随本值) |
|
|
281
283
|
| `llm.temperature` | `0.3` | 蒸馏温度 |
|
|
282
284
|
| `llm.maxInputChars` | `700000` | 单次蒸馏输入字符预算(超限的 L1 输入自动分块抽取);运行时可在设置页 → 蒸馏参数 → 输入预算调整(留空/0 = 跟随本值) |
|
|
283
285
|
| `llm.timeoutMs` | `120000` | 单次蒸馏调用超时(ms) |
|
|
@@ -285,6 +287,51 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
|
|
|
285
287
|
| `tools` | `true` | 是否注册模型可调用的记忆工具 |
|
|
286
288
|
| `benchControl` | `false` | 注册 bench 控制服务(进程内 rebuild 触发/会话档位设置/蒸馏用量快照,供基准 lifecycle 赛道)。默认关——生产部署零表面积,勿随意开启 |
|
|
287
289
|
|
|
290
|
+
### 蒸馏回退链与慢 TTFT 模型
|
|
291
|
+
|
|
292
|
+
部分推理供应商的免费/慢速档位**首 token 延迟(TTFT)可达 20 秒以上**,而部分上游网关会在连接静默约 20 秒时掐断——蒸馏调用以固定 ~20s 失败(`llm aborted`),插件侧 120s 超时根本轮不到生效([#31](https://github.com/JunNanLYS/dsh-layered-memory/issues/31) 的实测场景)。三层缓解按需取用:
|
|
293
|
+
|
|
294
|
+
1. **换路由**(最直接):设置页 → 记忆 → 概览 → 蒸馏参数的路由链编辑器即时改主路由(或把快路由排到链首),或静态 pin `llm.provider`/`llm.model`。
|
|
295
|
+
2. **回退链**(自动降级):主路由失败时按序自动换备用路由,无需人工干预:
|
|
296
|
+
|
|
297
|
+
```yaml
|
|
298
|
+
llm:
|
|
299
|
+
provider: opencode-go # 主路由(也可不 pin,跟随设置页路由链主路由/默认模型)
|
|
300
|
+
model: ox-alpha-free
|
|
301
|
+
fallbacks: # 条目顺序 = 降级优先级;不配置 = 单路由行为不变
|
|
302
|
+
- provider: opencode-go
|
|
303
|
+
model: deepseek-v4-flash
|
|
304
|
+
reasoningEffort: low # 可选:该路由的档位覆盖(缺省跟随全局)
|
|
305
|
+
- provider: deepseek-official
|
|
306
|
+
model: deepseek-v4-flash
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
3. **按层路由**(各走各的通道):不同蒸馏层对模型诉求不同(L1 高频要便宜快稳、
|
|
310
|
+
L3 低频可容忍慢首包但要强能力),可给差异层单独配链——每层一条**完整回退链**,
|
|
311
|
+
未配置的层照走全局链:
|
|
312
|
+
|
|
313
|
+
```yaml
|
|
314
|
+
llm:
|
|
315
|
+
layerRoutes: # 按层独立路由(#34);头行必须显式 provider+model
|
|
316
|
+
l1: # l1 同管抽取 + 去重两个调用点:配条便宜快稳的链
|
|
317
|
+
- provider: opencode-go
|
|
318
|
+
model: deepseek-v4-flash
|
|
319
|
+
reasoningEffort: low
|
|
320
|
+
- provider: deepseek-official # 层内回退:L1 故障只降级到这里,不落全局链
|
|
321
|
+
model: deepseek-v4-flash
|
|
322
|
+
l3: # L3 画像蒸馏:低频大输入,配强能力链
|
|
323
|
+
- provider: deepseek-official
|
|
324
|
+
model: deepseek-v4-flash
|
|
325
|
+
reasoningEffort: high
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
也可在设置页 → 记忆 → 概览 → 蒸馏参数的**分段面板**(全局默认 / L1 / L2 / L3)
|
|
329
|
+
里按层运行时编辑,层内优先级:运行时层链 > 本 YAML 静态层链 > 全局默认链,
|
|
330
|
+
逐级兜底。
|
|
331
|
+
|
|
332
|
+
失败 = 报错 / 被掐断 / 网络异常 / **空输出**(流正常结束但 0 字符——对蒸馏而言必然在解析阶段报废,改判为该路由失败而非返回空串);调用方主动取消不降级;每条路由各享**全额** `llm.timeoutMs`(共享预算会让慢 TTFT 的回退路由拿到的窗口小于它真实需要的首包时间,回退链形同虚设);token 成本逐次尝试记账(失败尝试也计一行,含流中断前已到的 token),成功调用归因到实际服务的路由。路由链也可在设置页 → 记忆 → 概览 → 蒸馏参数的「蒸馏路由链」编辑器里运行时调整(无需改配置重启);本 YAML 适合部署者固化静态链。
|
|
333
|
+
4. **调高超时**:`llm.timeoutMs` 只在路由确实慢但网关不掐时有用;网关 20s 掐断的场景调插件超时无效,请用前两层。
|
|
334
|
+
|
|
288
335
|
## 日志与故障排查
|
|
289
336
|
|
|
290
337
|
dsh 宿主把插件日志打到控制台;插件另把 info 级以上镜像到数据目录的 `memory.log`。
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|