@modusensus/dsh-mneme 0.7.27 → 0.7.28

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 CHANGED
@@ -174,6 +174,7 @@ Every **background LLM call** (autoDream consolidation + summary, autoSummarize
174
174
 
175
175
  | Version | Highlights |
176
176
  |------|------|
177
+ | **v0.7.28** | Connectivity test triple fix: the `POST /api/dsh-mneme/test-model` minimal call raised `maxTokens` 16→1024 — a thinking model's reasoning alone can exhaust a 16-token budget, leaving `reply` always empty ("actually answered ok, not just connected" never held for thinking models; billed on actual usage, manual button, no amplification cost); connectivity test state is now per-route (dream/sleep each hold their own) — previously a single shared state made both groups show "testing/result" and disable each other when either button was clicked; the panel's mount-time draft now includes `sleepProvider`/`sleepModel` — values were always saved server-side, but after a remount (tab switch / re-enter) the dropdowns showed "follow default route" as if the setting had been reset; the saved values restore without re-entering them; 733 tests green |
177
178
  | **v0.7.27** | v0.7.26 endpoint backfill: the v0.7.26 release tree did not include the `fix/dream-effort-trap` branch, so the `GET /api/dsh-mneme/llm-providers` + `POST /api/dsh-mneme/test-model` endpoints announced in its CHANGELOG/Release were absent from the package (the panel's cascading dropdown + connectivity test would 404); this release rebases and merges the branch (PR #100), landing the endpoints — panel connectivity test now works; 733 tests green |
178
179
  | **v0.7.26** | Consolidation `UNSUPPORTED_REASONING_EFFORT` root-cause fix + dream/sleep model connectivity test: root-caused the **defaultEffort trap** — the harness injects `reasoning.defaultEffort` when effort is omitted, so if that default tier itself is unsupported, retrying without effort never helps (whatever effort is sent gets rejected); fix: new `resolveDreamEffort` proactively queries `ctx.llm.resolveModelInfo()` for the model's supported effort tiers and sends a supported one — an unsupported configured tier auto-falls back to the model's default/first supported tier, and the field is omitted when the model declares no reasoning capability. Settings panel adds selection hints on 6 dream/sleep model fields (guiding toward non-thinking models so they don't burn the token budget on reasoning). New `GET /api/dsh-mneme/llm-providers` (host-side provider/model discovery; keys never touch the plugin side) + `POST /api/dsh-mneme/test-model` (connectivity test; empty body resolves via the consolidation route and returns `modelId`); 732 tests green |
179
180
  | **v0.7.25** | Tool-compat hardening + `memory_get`/render content preview + consolidation-model guide: new `memory_get` tool (8th model tool, read a single memory's full body by id) + `memory_search`/`memory_list` render now embeds title/metadata/body preview (the model reads actual memory content even when the host only forwards render text) + consolidation-model selection guide (config comments/README classification, non-thinking vs thinking). Fixed `memory_get` execute nested inside output crashing with `userExecute is not a function` (previous tests only counted tool names, never executed it) + tool de-dup on live patch reload + Standalone API port-collision retry (EADDRINUSE) + client inject declaration alignment + better-sidebar hardening; 718 tests green |
package/README.md CHANGED
@@ -215,6 +215,7 @@ v0.3.0 起新增**记忆基因**层:从记忆里抽取**命名实体**、**带
215
215
 
216
216
  | 版本 | 亮点 |
217
217
  |------|------|
218
+ | **v0.7.28** | 连通性测试三连修:`POST /api/dsh-mneme/test-model` 最小调用 `maxTokens` 16→1024——思考模型的推理过程足以耗尽 16 token 预算致 `reply` 恒为空(「真的答了 ok 而非只报通」对思考模型不成立;按实际用量计费,手动按钮无放大成本);连通性测试状态按巩固/睡眠路由各持一份——此前共享单份,点任一「测试连通性」按钮两组同显「测试中/结果」且互相禁用;面板挂载草稿补 `sleepProvider`/`sleepModel`——后端一直保存正常,但重挂载(切页签/退出重进)后下拉恒显「跟随默认路由」,看起来像设置被重置,补键后正常回填(历史已存值无需重填);733 测试全绿 |
218
219
  | **v0.7.27** | v0.7.26 端点遗漏补齐:v0.7.26 发版树未含 `fix/dream-effort-trap` 分支,CHANGELOG/Release 宣告的 `GET /api/dsh-mneme/llm-providers` + `POST /api/dsh-mneme/test-model` 两个端点实际不在包内(面板「级联下拉 + 测试连通性」会 404);本版将分支 rebase 后合入(PR #100),端点落地,面板连通性测试可用;733 测试全绿 |
219
220
  | **v0.7.26** | 记忆巩固 `UNSUPPORTED_REASONING_EFFORT` 根治 + 巩固/睡眠模型连通性测试:根治 **defaultEffort 陷阱**——harness 在 effort 省略时注入 `reasoning.defaultEffort`,若该默认档位本身不被模型支持,则去 effort 重试也无济于事(换什么 effort 都会被拒绝);修复:新增 `resolveDreamEffort` 经 `ctx.llm.resolveModelInfo()` 主动探测模型支持的档位再发送——配置档位不被支持时自动换用模型支持的默认/首个档位、模型声明无 reasoning 能力则省略字段;设置面板巩固/睡眠 6 字段补选型提示(引导非思考模型,避免再踩思考模型烧光 token 预算);新增 `GET /api/dsh-mneme/llm-providers`(宿主侧 provider/model 发现,密钥不经插件侧)+ `POST /api/dsh-mneme/test-model`(模型连通性测试,空 body 按巩固路由解析返回 modelId);732 测试全绿 |
220
221
  | **v0.7.25** | 工具兼容性加固 + `memory_get`/render 内容预览 + 巩固模型引导:新增 `memory_get` 工具(第 8 个模型工具,按 id 读单条记忆全文)+ `memory_search`/`memory_list` render 嵌入标题/元数据/正文预览(宿主只透传 render 文本时模型也能直接读到记忆内容)+ 巩固模型选型引导(config 注释/README 分类声明,非思考 vs 思考模型差异);修复 `memory_get` execute 嵌套进 output 的崩溃(`userExecute is not a function`,此前测试只数工具名从未执行该工具而掩盖)+ 工具重复注册去重(live patch reload)+ Standalone API 端口冲突重试(EADDRINUSE)+ client inject 声明对齐 + better-sidebar 集成加固;718 测试全绿 |
package/lib/api.js CHANGED
@@ -296,7 +296,10 @@ export function createApi(ctx, service, settings, commands, embedder, semantic =
296
296
  provider,
297
297
  model,
298
298
  purpose: "dsh-mneme-connectivity-test",
299
- maxTokens: 16,
299
+ // 给思考模型留出「思考完还有正文」的空间:16 会被 reasoning 全部吃掉,
300
+ // reply 恒为空,「真的答了 ok」对思考模型不成立。按实际用量计费,手动
301
+ // 按钮无放大风险。
302
+ maxTokens: 1024,
300
303
  ...(reasoningEffort && reasoningEffort !== "none" ? { reasoningEffort } : {}),
301
304
  messages: [{ role: "system", content: [{ type: "text", text: "Reply with exactly one word: ok" }] }]
302
305
  })) {
package/lib/client.js CHANGED
@@ -1592,7 +1592,7 @@ window.__ModuleLoader__.load({
1592
1592
  const FEATURE_ADVANCED_BOOLS = ["hybridInject", "selectiveInjectEnabled", "adaptiveThresholdEnabled", "reflectionUpdateEnabled", "reflectionFailureTracking", "conflictFreezeEnabled", "trustEpistemicWeighting"];
1593
1593
  // 字符串键(blur/Enter 提交,空串合法 = 跟随默认):巩固模型与语义
1594
1594
  // 检索路线。embedProvider 是枚举,用下拉单独渲染。
1595
- const FEATURE_STRINGS = ["dreamProvider", "dreamModel", "localEmbedModel", "ollamaBaseUrl", "ollamaModel"];
1595
+ const FEATURE_STRINGS = ["dreamProvider", "dreamModel", "sleepProvider", "sleepModel", "localEmbedModel", "ollamaBaseUrl", "ollamaModel"];
1596
1596
  const EMBED_PROVIDERS = ["openai", "local", "ollama"];
1597
1597
 
1598
1598
  function FeatureRow({ name, hint, on, disabled, onToggle }) {
@@ -1623,8 +1623,9 @@ window.__ModuleLoader__.load({
1623
1623
  // 巩固/睡眠模型路由下拉的数据源:GET /llm-providers 探测(云端 v0.7.26+
1624
1624
  // 的插件侧端点)。null = 端点不可用(404/失败)→ 回退纯文本输入,不挡旧后端。
1625
1625
  const [routes, setRoutes] = useState(null);
1626
- // 连通性测试结果:{ running: true } | { ok, ms, detail }
1627
- const [testState, setTestState] = useState(null);
1626
+ // 连通性测试结果(巩固/睡眠各一份,互不串扰):{ running: true } | { ok, ms, detail }
1627
+ const [dreamTest, setDreamTest] = useState(null);
1628
+ const [sleepTest, setSleepTest] = useState(null);
1628
1629
 
1629
1630
  useEffect(() => {
1630
1631
  let cancelled = false;
@@ -1700,7 +1701,7 @@ window.__ModuleLoader__.load({
1700
1701
  // 连通性测试:POST /test-model,空 provider/model = 按巩固路由解析
1701
1702
  // (agent 默认)。durationMs 优先后端值,缺失时客户端兜底计时;成功行
1702
1703
  // 附模型的实际回复(reply,后端截 100 字符)——「真的答了 ok」而非只报通。
1703
- const runModelTest = async (provider, model) => {
1704
+ const runModelTest = async (provider, model, setTestState) => {
1704
1705
  setTestState({ running: true });
1705
1706
  const started = Date.now();
1706
1707
  try {
@@ -1733,7 +1734,7 @@ window.__ModuleLoader__.load({
1733
1734
  // 适配器,用户不会选到不存在的模型)+ 连通性测试。空值 = 跟随默认
1734
1735
  // 路由;改动即提交(与 embedProvider 下拉一致)。当前值不在枚举里时
1735
1736
  // 保留为额外选项,避免静默改值。
1736
- const routeSelects = (providerKey, modelKey) => {
1737
+ const routeSelects = (providerKey, modelKey, testState, setTestState) => {
1737
1738
  const curP = strs[providerKey] ?? "";
1738
1739
  const curM = strs[modelKey] ?? "";
1739
1740
  const entries = Array.isArray(routes) ? routes : [];
@@ -1769,7 +1770,7 @@ window.__ModuleLoader__.load({
1769
1770
  h("button", {
1770
1771
  type: "button", className: "mneme-btn",
1771
1772
  disabled: busy || (testState && testState.running),
1772
- onClick: () => runModelTest(curP, curM)
1773
+ onClick: () => runModelTest(curP, curM, setTestState)
1773
1774
  }, t((testState && testState.running) ? "memory.features.modelTesting" : "memory.features.modelTest")),
1774
1775
  testState && !testState.running && h("div", { className: "mneme-featsubhint" },
1775
1776
  (testState.ok ? "✓ " + t("memory.features.modelTestOk") : "✗ " + t("memory.features.modelTestFail"))
@@ -1812,7 +1813,7 @@ window.__ModuleLoader__.load({
1812
1813
  // 可用时用级联下拉 + 连通性测试;旧后端(端点 404)回退纯文本输入。
1813
1814
  const dreamSub = eff.autoDream && h("div", { className: "mneme-featsub" },
1814
1815
  Array.isArray(routes)
1815
- ? routeSelects("dreamProvider", "dreamModel")
1816
+ ? routeSelects("dreamProvider", "dreamModel", dreamTest, setDreamTest)
1816
1817
  : h(react.Fragment, null, strRow("dreamProvider"), strRow("dreamModel")),
1817
1818
  h("div", { className: "mneme-featsubhint" }, t("memory.features.dreamModelHint"))
1818
1819
  );
@@ -1820,7 +1821,7 @@ window.__ModuleLoader__.load({
1820
1821
  // 睡眠模型:sleepModeEnabled 开着才展开(sleepProvider/sleepModel 随本版
1821
1822
  // 进白名单;下拉与测试复用同一 /llm-providers 数据源)。
1822
1823
  const sleepSub = eff.sleepModeEnabled && Array.isArray(routes) && h("div", { className: "mneme-featsub" },
1823
- routeSelects("sleepProvider", "sleepModel"),
1824
+ routeSelects("sleepProvider", "sleepModel", sleepTest, setSleepTest),
1824
1825
  h("div", { className: "mneme-featsubhint" }, t("memory.features.sleepModelHint"))
1825
1826
  );
1826
1827
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@modusensus/dsh-mneme",
3
3
  "description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 7 model tools, automatic injection, session summarization, user profile/rules, custom slash commands, vector (semantic) search, and a Web GUI panel",
4
- "version": "0.7.27",
4
+ "version": "0.7.28",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
package/src/api.js CHANGED
@@ -296,7 +296,10 @@ export function createApi(ctx, service, settings, commands, embedder, semantic =
296
296
  provider,
297
297
  model,
298
298
  purpose: "dsh-mneme-connectivity-test",
299
- maxTokens: 16,
299
+ // 给思考模型留出「思考完还有正文」的空间:16 会被 reasoning 全部吃掉,
300
+ // reply 恒为空,「真的答了 ok」对思考模型不成立。按实际用量计费,手动
301
+ // 按钮无放大风险。
302
+ maxTokens: 1024,
300
303
  ...(reasoningEffort && reasoningEffort !== "none" ? { reasoningEffort } : {}),
301
304
  messages: [{ role: "system", content: [{ type: "text", text: "Reply with exactly one word: ok" }] }]
302
305
  })) {
@@ -481,7 +481,7 @@ test("consolidation/sleep model routing: provider dropdowns from /llm-providers,
481
481
  "the probe must only accept a {providers: []} shape"
482
482
  );
483
483
  assert.ok(
484
- /Array\.isArray\(routes\)\s*\?\s*routeSelects\("dreamProvider", "dreamModel"\)/.test(clientSource),
484
+ /Array\.isArray\(routes\)\s*\?\s*routeSelects\("dreamProvider", "dreamModel", dreamTest, setDreamTest\)/.test(clientSource),
485
485
  "dream routing must upgrade to dropdowns only when the probe succeeded"
486
486
  );
487
487
  assert.ok(
@@ -490,9 +490,26 @@ test("consolidation/sleep model routing: provider dropdowns from /llm-providers,
490
490
  );
491
491
  // 2. 睡眠侧行:跟随 sleepModeEnabled 门控,与巩固共用数据源
492
492
  assert.ok(
493
- /const sleepSub = eff\.sleepModeEnabled && Array\.isArray\(routes\) && h\("div", \{ className: "mneme-featsub" \},\s*\n\s*routeSelects\("sleepProvider", "sleepModel"\)/.test(clientSource),
493
+ /const sleepSub = eff\.sleepModeEnabled && Array\.isArray\(routes\) && h\("div", \{ className: "mneme-featsub" \},\s*\n\s*routeSelects\("sleepProvider", "sleepModel", sleepTest, setSleepTest\)/.test(clientSource),
494
494
  "the sleep route row must gate on sleepModeEnabled and share the providers source"
495
495
  );
496
+ // 2b. 睡眠路由的值必须进初始化草稿:FEATURE_STRINGS 漏键会导致重挂载后
497
+ // 下拉永远显示「跟随默认路由」(后端存了但前端读不回来)。
498
+ assert.ok(
499
+ /const FEATURE_STRINGS = \["dreamProvider", "dreamModel", "sleepProvider", "sleepModel",/.test(clientSource),
500
+ "sleepProvider/sleepModel must be restored into the draft on mount, not only written"
501
+ );
502
+ // 2c. 连通性测试状态按路由各持一份:共享单份会让点一个按钮两个组同时
503
+ // 显示「测试中/结果」且互相禁用。
504
+ assert.ok(
505
+ /const \[dreamTest, setDreamTest\] = useState\(null\);/.test(clientSource)
506
+ && /const \[sleepTest, setSleepTest\] = useState\(null\);/.test(clientSource),
507
+ "the connectivity test state must be per-route, not shared between dream and sleep"
508
+ );
509
+ assert.ok(
510
+ /runModelTest\(curP, curM, setTestState\)/.test(clientSource),
511
+ "each route's test button must target its own test state"
512
+ );
496
513
  // 3. 连通性测试:真实最小调用 + 结果展示(成功/失败 + 耗时 + 报错原因)
497
514
  assert.ok(
498
515
  clientSource.includes('apiFetch("/api/dsh-mneme/test-model", {'),