@a9i5k4/dsh-auto-memory 2.2.1 → 2.2.3

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 (113) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/docs/A3-RISK-ASSESSMENT-20260830.md +61 -0
  4. package/docs/COT-WATCH-RFC.md +88 -0
  5. package/docs/DUAL-TIER-RATIFICATION-PROMPT.md +71 -0
  6. package/docs/HANDOFF-HARNESS.md +78 -0
  7. package/docs/HANDOFF-M8-M9-M10.md +203 -0
  8. package/docs/HY4-TOUR-LOGO-HANDOFF-2.md +60 -0
  9. package/docs/HY4-TOUR-LOGO-HANDOFF.md +100 -0
  10. package/docs/ISSUE-REPLY-UNATTENDED.md +31 -0
  11. package/docs/K3-LANDING-HANDOFF.md +76 -0
  12. package/docs/LANDING-OUTLINE.md +85 -0
  13. package/docs/M-CM-PLAN.md +166 -0
  14. package/docs/M-CM-STATE.md +64 -0
  15. package/docs/M3B-CONTRACT.md +461 -0
  16. package/docs/M4-CONTRACT.md +1207 -0
  17. package/docs/M5-CONTRACT.md +383 -0
  18. package/docs/M6-CONTRACT.md +342 -0
  19. package/docs/M7-ACTIVATION-ALGO-REFERENCES.md +104 -0
  20. package/docs/M7-ACTIVATION-CALIBRATION.md +144 -0
  21. package/docs/M7-ACTIVATION-FEATURE-AGENT-PROMPT.md +79 -0
  22. package/docs/M7-ACTIVATION-FEATURE-CALIBRATION.md +58 -0
  23. package/docs/M7-ACTIVATION-FEATURE-DESIGN.md +124 -0
  24. package/docs/M7-ACTIVATION-V2-CONTROLLED-SHADOW.md +127 -0
  25. package/docs/M7-ACTIVATION-V2-HANDOFF.md +132 -0
  26. package/docs/M7-ACTIVATION-V2-HOLDEDOUT-EVAL.md +94 -0
  27. package/docs/M7-ACTIVATION-V2-HOLDEDOUT-SHADOW.md +60 -0
  28. package/docs/M7-ACTIVATION-V2-LIVE-SHADOW-PLAN.md +85 -0
  29. package/docs/M7-ACTIVATION-V2-PAPER.md +303 -0
  30. package/docs/M7-AGENT-HANDOFF-PROMPT.md +63 -0
  31. package/docs/M7-ALGORITHM-DECISION.md +174 -0
  32. package/docs/M7-AUTONOMOUS-STATE.md +252 -0
  33. package/docs/M7-BENCHMARK-PLAN.md +78 -0
  34. package/docs/M7-CLOSED-LOOP-WIRING.md +110 -0
  35. package/docs/M7-EMBEDDING-BENCHMARK.md +164 -0
  36. package/docs/M7-INTERFACE-DIGEST.md +144 -0
  37. package/docs/M7-LABEL-REVIEW-REPORT.md +107 -0
  38. package/docs/M7-LEXICAL-TUNING.md +58 -0
  39. package/docs/M7-LIVE-SHADOW-SCRIPT.md +30 -0
  40. package/docs/M7-PYTHON-IMPLEMENTATION-REPORT.md +92 -0
  41. package/docs/M7-RESEARCH-PAPER.md +442 -0
  42. package/docs/M7-TASKSET-DISPATCH.md +213 -0
  43. package/docs/M8-MEMORY-HUB.md +105 -0
  44. package/docs/MEMORY-SYSTEMS-SURVEY-2026-09.md +166 -0
  45. package/docs/NEXT-MAJOR-PROMO.md +363 -0
  46. package/docs/NEXT-MAJOR-README-DRAFT.zh.md +205 -0
  47. package/docs/NEXT-MAJOR-VISION.md +112 -0
  48. package/docs/PREVIEW-NEXT-STEPS.md +229 -0
  49. package/docs/PROJECT-FREEZE-AND-ROADMAP.md +200 -0
  50. package/docs/PROMO-STYLE-GUIDE.md +84 -0
  51. package/docs/PYTHON-SIDECAR-CONTRACT.md +539 -0
  52. package/docs/R2-POLICY-PLUMBING-BLUEPRINT.md +99 -0
  53. package/docs/RELEASE-READINESS-PLAN.md +91 -0
  54. package/docs/RELEASE-SEMANTIC-OPTION.md +181 -0
  55. package/docs/S1-SCIENTIFIC-RIGOR.md +269 -0
  56. package/docs/S2-DEEP-ABSORPTION.md +259 -0
  57. package/docs/S3-TARGET-ARCHITECTURE.md +172 -0
  58. package/docs/USER-GUIDE.zh-CN.md +98 -0
  59. package/docs/banner.jpg +0 -0
  60. package/docs/implementation-handoff-context.zh-CN.md +429 -0
  61. package/docs/landing/index.html +1745 -0
  62. package/docs/paper-figures/fig1_model_quality.png +0 -0
  63. package/docs/paper-figures/fig2_chunk_reversal.png +0 -0
  64. package/docs/paper-figures/fig3_latency.png +0 -0
  65. package/docs/paper-figures/fig4_hybrid.png +0 -0
  66. package/docs/paper-figures/fig5_rerank_tradeoff.png +0 -0
  67. package/docs/paper-figures/fig6_cluster_sweep.png +0 -0
  68. package/docs/paper-figures/fig7_resource.png +0 -0
  69. package/docs/paper-figures-v2/fig1_echo_trap.png +0 -0
  70. package/docs/paper-figures-v2/fig2_pr_paths.png +0 -0
  71. package/docs/paper-figures-v2/fig3_coefficients.png +0 -0
  72. package/docs/paper-figures-v2/fig4_calibration.png +0 -0
  73. package/docs/paper-figures-v2/fig5_order_ablation.png +0 -0
  74. package/docs/paper-figures-v2/fig6_containment.png +0 -0
  75. package/docs/proactive-associative-memory-architecture.html +659 -0
  76. package/docs/proactive-associative-memory-meta-code.html +1058 -0
  77. package/docs/proactive-associative-memory-research-report.zh-CN.md +685 -0
  78. package/docs/proactive-associative-memory-system-map.html +1580 -0
  79. package/docs/promo/first-run-guide.html +397 -0
  80. package/docs/promo/homepage.html +384 -0
  81. package/docs/screenshots/calendar-en.png +0 -0
  82. package/docs/screenshots/calendar-zh.png +0 -0
  83. package/docs/screenshots/connect-en.png +0 -0
  84. package/docs/screenshots/connect-zh.png +0 -0
  85. package/docs/screenshots/main-connect-en.png +0 -0
  86. package/docs/screenshots/main-connect-zh.png +0 -0
  87. package/docs/screenshots/overview-en.png +0 -0
  88. package/docs/screenshots/overview-zh.png +0 -0
  89. package/docs/screenshots/panel-hub.png +0 -0
  90. package/docs/screenshots/panel-overview.png +0 -0
  91. package/docs/screenshots/panel-refine.png +0 -0
  92. package/docs/screenshots/promo/promo-0-banner-v2.png +0 -0
  93. package/docs/screenshots/promo/promo-1-hero.png +0 -0
  94. package/docs/screenshots/promo/promo-2-tour.png +0 -0
  95. package/docs/screenshots/promo/promo-3-recall.png +0 -0
  96. package/docs/screenshots/promo/promo-4-unattended.png +0 -0
  97. package/docs/screenshots/promo/promo-5-external.png +0 -0
  98. package/docs/screenshots/promo/promo-6-greeting.png +0 -0
  99. package/docs/screenshots/reflections-en.png +0 -0
  100. package/docs/screenshots/search-zh.png +0 -0
  101. package/docs/screenshots/settings-2-zh.png +0 -0
  102. package/docs/screenshots/settings-debug-zh.png +0 -0
  103. package/docs/screenshots/settings-en.png +0 -0
  104. package/docs/screenshots/settings-zh.png +0 -0
  105. package/docs/screenshots/tour-core.png +0 -0
  106. package/docs/screenshots/tour-external.png +0 -0
  107. package/docs/screenshots/tour-toggles.png +0 -0
  108. package/docs/screenshots/tour-welcome.png +0 -0
  109. package/docs/screenshots/workspace-map-zh.png +0 -0
  110. package/docs/social-preview.png +0 -0
  111. package/lib/client.js +207 -4
  112. package/lib/index.js +25 -5
  113. package/package.json +3 -1
package/lib/client.js CHANGED
@@ -271,6 +271,7 @@ window.__ModuleLoader__.load({
271
271
  fMaintSchedule: '定时 30 天蒸馏', fMaintScheduleHint: '每天到点自动把超过 30 天的旧日志蒸馏归档(等价 memory_maintain);无旧日志时零成本跳过。',
272
272
  fMaintScheduleTime: '蒸馏触发时间', fMaintScheduleTimeHint: 'HH:MM,默认 10:00(与固化时间错开)。',
273
273
  waterCardTitle: '上下文水位', waterAutoSrc: '自动检测', waterManualSrc: '手动设定', waterMeterOfficial: '官方计量', waterMeterHeuristic: '启发式降级', waterThresholdHint: '水位达到 {t} 时注入交接建议并自动补写账本;计量优先用官方 token-meter(与聊天框 context ring 同源),不可用时降级启发式估算;窗口大小自动取自当前模型(settings.yaml contextWindow),也可在下方手动覆盖。',
274
+ autoContTitle: '自动接续', autoContHint: '开启后:水位达到阈值且会话空闲(连续两轮水位不增长)时,倒计时 30 秒自动执行一键接续(总结→写账本→同工作区开新会话→注入接续材料);触发后 30 分钟内不重复;随时可取消。', autoContOn: '自动接续:开', autoContOff: '自动接续:关', autoContThreshold: '阈值', autoContCountdown: '⏳ {s} 秒后自动接续(总结并开新会话)…', autoContCancel: '取消',
274
275
  continueCardTitle: '一键接续', continueCardHint: '写好交接账本→创建新会话→把交接材料作为首条消息预载,并自动切换到新会话继续任务(接续材料含白板节选+最新账本;当前工作区无账本时自动取全局最近一篇)。', continueBtn: '一键接续到新会话', continueBusy: '处理中…',
275
276
  fStyle: '反思风格', fStyleHint: '生活化 / 专业性 / 由内容决定。',
276
277
  fLocale: '界面语言', fLocaleHint: '默认跟随 DSH 系统语言;也可手动指定中文 / English。', followSystem: '跟随系统语言',
@@ -418,6 +419,7 @@ window.__ModuleLoader__.load({
418
419
  fMaintSchedule: 'Scheduled 30-day distill', fMaintScheduleHint: 'Once a day at the set time, distill & archive logs older than 30 days (same flow as memory_maintain); zero cost when nothing to archive.',
419
420
  fMaintScheduleTime: 'Distill time', fMaintScheduleTimeHint: 'HH:MM, default 10:00 (staggered from the consolidation time).',
420
421
  waterCardTitle: 'Context water level', waterAutoSrc: 'auto-detected', waterManualSrc: 'manual', waterMeterOfficial: 'official meter', waterMeterHeuristic: 'heuristic fallback', waterThresholdHint: 'Past {t} of the window, the handoff advisory is injected and the skeleton ledger is backfilled; metering prefers the official token-meter (same source as the chat context ring), falling back to the heuristic when unavailable; the window auto-follows the active model (settings.yaml contextWindow) or your manual override below.',
422
+ autoContTitle: 'Auto continue', autoContHint: 'When on: once the water level passes the threshold and the session is idle (level unchanged across two polls), a 30s countdown auto-runs One-click continue (summarize → write ledger → open a new session in the same workspace → inject the handoff prompt); suppressed for 30 minutes after each run; cancel anytime.', autoContOn: 'Auto continue: on', autoContOff: 'Auto continue: off', autoContThreshold: 'Threshold', autoContCountdown: '⏳ Auto-continue in {s}s (summarize & open new session)…', autoContCancel: 'Cancel',
421
423
  continueCardTitle: 'One-click continue', continueCardHint: 'Writes the handoff ledger → creates a new session → injects the handoff material as the first message → switches to the new session automatically (material = PLAN excerpt + latest ledger; falls back to the most recent global ledger when this workspace has none).', continueBtn: 'Continue in a new session', continueBusy: 'Working…',
422
424
  fStyle: 'Reflection style', fStyleHint: 'Life-style / Professional / Auto.',
423
425
  fLocale: 'UI language', fLocaleHint: 'Follows the DSH system language by default; you can also pin Chinese / English.', followSystem: 'Follow system language',
@@ -499,6 +501,22 @@ window.__ModuleLoader__.load({
499
501
 
500
502
  // ───────────────────────── 更新弹窗 / 首次指导 ─────────────────────────
501
503
  var CHANGELOG = {
504
+ '2.2.3': { zh: [
505
+ '打包修复:npm 包 files 现包含 docs/,用户文档随包发布——README 的「📖 用户文档」链接在 GitHub 与 npm 包页均可打开。',
506
+ ], en: [
507
+ 'Packaging: the npm package now ships docs/ via the files field, so the README user-guide link works on both GitHub and the npm package page.',
508
+ ] },
509
+ '2.2.2': { zh: [
510
+ '修复:一键接续在部分环境报「harness 未提供 remote.session」——补上官方 remote 注入面(@deepseek-ai/dsh-api-remotes),重启后自动建会话/切换/注入恢复可用。',
511
+ '修复:语义引擎检测面板「未就绪」与「一切就绪」同屏矛盾、缺失时不弹安装引导——检测面补 Python int8 探测(无装=未就绪),按当前引擎模式自动弹出对应安装引导卡。',
512
+ '★ 新增自动接续:水位达阈值(默认 0.8,可调)且会话空闲时,右下角 30 秒可取消倒计时后自动完成「写交接账本→建新会话→注入接续材料」并切换,无需任何按钮或打开面板(常驻监听,默认开;触发后 30 分钟冷却)。',
513
+ '📖 新增用户文档(README 下载区旁「📖 用户文档」):逐组说明每个设置项怎么调,含语义引擎/自动接续/交接白板/常见问题排查。',
514
+ ], en: [
515
+ 'Fix: one-click continue reported "remote.session unavailable" in some environments — the official remote inject surface (@deepseek-ai/dsh-api-remotes) is now declared; session create/switch/inject works again after a restart.',
516
+ 'Fix: semantic detect panel showed "not ready" and "everything ready" at once, and no setup guide appeared when assets were missing — the probe now checks Python int8 too, and the matching setup guide auto-opens per engine mode.',
517
+ '★ New: auto-continue — when the water level passes the threshold (default 0.8, adjustable) and the session is idle, a cancelable 30s countdown auto-runs "write ledger → create session → inject handoff material" and switches; no button or open panel needed (resident watcher, on by default, 30min cooldown).',
518
+ '📖 New user guide (link next to the install command in the README): every settings group explained, incl. semantic engines / auto-continue / whiteboard / troubleshooting.',
519
+ ] },
502
520
  '2.2.1': { zh: [
503
521
  '★ 一键接续:白板页签新增「一键接续」——自动写交接账本 → 创建新会话(沿用工作区/权限/模型)→ 接续材料作为首条消息预载并自动切换;材料附旧会话完整对话转写文件,新窗口的 AI 可随时回读旧会话全部内容。',
504
522
  '★ 水位 v2:计量优先官方 token-meter(与聊天框 context ring 同源,免疫重启/压缩/流式干扰),启发式仅作降级;水位卡标注当前计量来源,窗口自动取官方路由容量。',
@@ -1836,6 +1854,9 @@ window.__ModuleLoader__.load({
1836
1854
  err ? h('div', { 'data-dam-error': '' }, err) : null)
1837
1855
  }
1838
1856
 
1857
+ // M-CM6-C 自动接续跨渲染状态(apply 作用域,插件生命周期存活;组件重挂不重置)
1858
+ var autoState = { cdIv: null, lastTokens: null }
1859
+
1839
1860
  function PlanTab() {
1840
1861
  var dataPair = useState(null)
1841
1862
  var data = dataPair[0]
@@ -1853,6 +1874,39 @@ window.__ModuleLoader__.load({
1853
1874
  var contMsgPair = useState('')
1854
1875
  var contMsg = contMsgPair[0]
1855
1876
  var setContMsg = contMsgPair[1]
1877
+ // M-CM6-C 自动接续(水位阈值触发,默认关;轮询 handoff-state,连续两轮水位不增长视为会话空闲)
1878
+ var autoPair = useState(null)
1879
+ var autoCfg = autoPair[0]
1880
+ var setAutoCfg = autoPair[1]
1881
+ var cdPair = useState(0)
1882
+ var cd = cdPair[0]
1883
+ var setCd = cdPair[1]
1884
+ useEffect(function () {
1885
+ apiGet(API.config).then(function (c) {
1886
+ setAutoCfg({ enabled: !(c && c.autoContinueEnabled === false), threshold: (c && Number(c.autoContinueThreshold)) || 0.8 })
1887
+ }).catch(function () { setAutoCfg({ enabled: false, threshold: 0.7 }) })
1888
+ }, [])
1889
+ var autoSave = function (patch) {
1890
+ setAutoCfg(function (p) { return Object.assign({}, p, patch) })
1891
+ apiPost(API.config, patch).catch(function () {})
1892
+ }
1893
+ var autoCancel = function () {
1894
+ if (autoState.cdIv) { clearInterval(autoState.cdIv); autoState.cdIv = null }
1895
+ setCd(0)
1896
+ }
1897
+ var autoStartCountdown = function () {
1898
+ if (autoState.cdIv) return
1899
+ var left = 30
1900
+ setCd(left)
1901
+ autoState.cdIv = setInterval(function () {
1902
+ left -= 1
1903
+ if (left <= 0) {
1904
+ clearInterval(autoState.cdIv); autoState.cdIv = null; setCd(0)
1905
+ try { localStorage.setItem('dsh-auto-memory.autoCont.last', String(Date.now())) } catch (eL) {}
1906
+ oneClickContinue()
1907
+ } else setCd(left)
1908
+ }, 1000)
1909
+ }
1856
1910
  async function oneClickContinue() {
1857
1911
  if (contBusy) return
1858
1912
  setContBusy(true)
@@ -1892,6 +1946,30 @@ window.__ModuleLoader__.load({
1892
1946
  apiGet(API.handoffState, { file: open }).then(function (d) { if (alive) setContent(d.text || '') }).catch(function () {})
1893
1947
  return function () { alive = false }
1894
1948
  }, [open])
1949
+ useEffect(function () {
1950
+ if (!autoCfg || !autoCfg.enabled) return
1951
+ var alive = true
1952
+ var tick = function () {
1953
+ apiGet(API.handoffState).then(function (d) {
1954
+ if (!alive || !d || !d.enabled) return
1955
+ var wl = d.waterLevel || {}
1956
+ if (!wl.window || !(wl.ratio >= (autoCfg.threshold || 0.7))) { autoState.lastTokens = null; return }
1957
+ var idle = autoState.lastTokens !== null && wl.tokens === autoState.lastTokens
1958
+ autoState.lastTokens = wl.tokens
1959
+ if (!idle) return
1960
+ var last = 0
1961
+ try { last = Number(localStorage.getItem('dsh-auto-memory.autoCont.last') || 0) } catch (eL) {}
1962
+ if (Date.now() - last < 30 * 60 * 1000) return
1963
+ autoStartCountdown()
1964
+ }).catch(function () {})
1965
+ }
1966
+ var iv = setInterval(tick, 20000)
1967
+ tick()
1968
+ return function () { alive = false; clearInterval(iv) }
1969
+ }, [autoCfg && autoCfg.enabled, autoCfg && autoCfg.threshold])
1970
+ useEffect(function () {
1971
+ return function () { if (autoState.cdIv) { clearInterval(autoState.cdIv); autoState.cdIv = null } }
1972
+ }, [])
1895
1973
  if (!data) return h(Loading)
1896
1974
  if (!data.enabled) return h(Card, { title: t('planTitle') }, h('div', { 'data-dam-hint': '' }, t('planDisabled')))
1897
1975
  var wl = data.waterLevel || {}
@@ -1909,6 +1987,16 @@ window.__ModuleLoader__.load({
1909
1987
  h('div', { 'data-dam-hint': '', style: { marginTop: '4px' } }, t('waterThresholdHint').replace('{t}', String(wl.threshold || 0.8))),
1910
1988
  ])))
1911
1989
  }
1990
+ if (autoCfg && wl.window > 0) {
1991
+ rows.unshift(h(Card, { title: t('autoContTitle') }, h('div', { 'data-dam-content': '' }, [
1992
+ h('div', { 'data-dam-hint': '', style: { marginBottom: '6px' } }, t('autoContHint')),
1993
+ h('div', { 'data-dam-row': '' },
1994
+ h('button', { 'data-dam-btn': '', onClick: function () { autoCancel(); autoSave({ autoContinueEnabled: !autoCfg.enabled }) } }, autoCfg.enabled ? t('autoContOn') : t('autoContOff')),
1995
+ h('label', { 'data-dam-hint': '', style: { marginLeft: '8px' } }, t('autoContThreshold') + ' ',
1996
+ h('input', { 'data-dam-input': '', type: 'number', min: 0.5, max: 0.95, step: 0.05, value: String(autoCfg.threshold), style: { width: '64px' }, onChange: function (e) { var v = Number(e.target.value); if (v >= 0.5 && v <= 0.95) autoSave({ autoContinueThreshold: v }) } }))),
1997
+ cd > 0 ? h('div', { 'data-dam-hint': '', style: { marginTop: '6px', color: '#d4744f' } }, t('autoContCountdown').replace('{s}', String(cd)) + ' ', h('button', { 'data-dam-btn': '', onClick: autoCancel }, t('autoContCancel'))) : null,
1998
+ ])))
1999
+ }
1912
2000
  if (open) {
1913
2001
  rows.unshift(h(Card, { title: t('planFileTitle') + ' · ' + open }, h('div', { 'data-dam-content': '' }, content || t('empty'))))
1914
2002
  rows.push(h('button', { 'data-dam-btn': '', onClick: function () { setOpen(null); setContent('') } }, t('back')))
@@ -3198,6 +3286,105 @@ window.__ModuleLoader__.load({
3198
3286
  // ───────────────────────── 设置页 ─────────────────────────
3199
3287
  var STYLE_IDS = ['auto', 'life', 'professional']
3200
3288
  var LOCALE_IDS_LIST = ['system', 'zh', 'en']
3289
+ // M-CM6-C v2·常驻自动接续 watcher(2026-09-08):全局生效,与面板/页签是否打开无关。
3290
+ // 条件:autoContinueEnabled !== false(缺省=开)&& 水位≥阈值(缺省0.8)&& 连续两轮 tokens 不增长(会话空闲)
3291
+ // && 距上次触发>30min → 30s 可取消倒计时 → 自动执行接续(写账本→建会话→切换→注入材料)。
3292
+ function AutoContinueHost() {
3293
+ var cfgP = useState(null)
3294
+ var acCfg = cfgP[0]
3295
+ var setAcCfg = cfgP[1]
3296
+ var cdP = useState(0)
3297
+ var acCd = cdP[0]
3298
+ var setAcCd = cdP[1]
3299
+ var stP = useState(null)
3300
+ var acSt = stP[0]
3301
+ var setAcSt = stP[1]
3302
+ var bsP = useState(false)
3303
+ var acBusy = bsP[0]
3304
+ var setAcBusy = bsP[1]
3305
+ useEffect(function () {
3306
+ var alive = true
3307
+ var load = function () {
3308
+ apiGet(API.config).then(function (c) { if (alive) setAcCfg(c || {}) }).catch(function () {})
3309
+ }
3310
+ load()
3311
+ var iv = setInterval(load, 30000)
3312
+ return function () { alive = false; clearInterval(iv) }
3313
+ }, [])
3314
+ useEffect(function () {
3315
+ var on = !(acCfg && acCfg.autoContinueEnabled === false)
3316
+ if (!on) return
3317
+ var thr = (acCfg && Number(acCfg.autoContinueThreshold)) || 0.8
3318
+ var alive = true
3319
+ var tick = function () {
3320
+ apiGet(API.handoffState).then(function (d) {
3321
+ if (!alive || !d || !d.enabled) return
3322
+ var wl = d.waterLevel || {}
3323
+ if (!wl.window || !(wl.ratio >= thr)) { autoState.lastTokens = null; return }
3324
+ var idle = autoState.lastTokens !== null && wl.tokens === autoState.lastTokens
3325
+ autoState.lastTokens = wl.tokens
3326
+ if (!idle || autoState.cdIv || acBusy) return
3327
+ var last = 0
3328
+ try { last = Number(localStorage.getItem('dsh-auto-memory.autoCont.last') || 0) } catch (eL) {}
3329
+ if (Date.now() - last < 30 * 60 * 1000) return
3330
+ setAcSt(null)
3331
+ var left = 30
3332
+ setAcCd(left)
3333
+ autoState.cdIv = setInterval(function () {
3334
+ left -= 1
3335
+ if (left <= 0) {
3336
+ clearInterval(autoState.cdIv); autoState.cdIv = null; setAcCd(0)
3337
+ runAutoContinue()
3338
+ } else setAcCd(left)
3339
+ }, 1000)
3340
+ }).catch(function () {})
3341
+ }
3342
+ var iv = setInterval(tick, 20000)
3343
+ tick()
3344
+ return function () { alive = false; clearInterval(iv) }
3345
+ }, [acCfg && acCfg.autoContinueEnabled === false, acCfg && (Number(acCfg.autoContinueThreshold) || 0.8), acBusy])
3346
+ var cancelAc = function () {
3347
+ if (autoState.cdIv) { clearInterval(autoState.cdIv); autoState.cdIv = null }
3348
+ setAcCd(0)
3349
+ }
3350
+ var runAutoContinue = function () {
3351
+ if (acBusy) return
3352
+ if (!remoteFace || !remoteFace.session || typeof remoteFace.session.create !== 'function') {
3353
+ setAcSt(locale === 'zh' ? '✗ remote.session 不可用——请重启 dsh web 后重试' : '✗ remote.session unavailable — restart dsh web')
3354
+ return
3355
+ }
3356
+ setAcBusy(true)
3357
+ setAcSt(locale === 'zh' ? '正在自动接续:写账本→建新会话→注入材料…' : 'Auto-continuing: ledger → new session → inject…')
3358
+ apiPost(API.handoffContinue, {}).then(function (d) {
3359
+ if (!d || !d.ok) throw new Error((d && d.error) || 'no handoff material')
3360
+ var p
3361
+ try { p = remoteFace.session.create(d.ws ? { cwd: d.ws } : {}) } catch (eC) { p = remoteFace.session.create({}) }
3362
+ return p.then(function (created) {
3363
+ var newId = created && (created.sessionId || created.id)
3364
+ if (!newId) throw new Error('create: no sessionId')
3365
+ var chain = Promise.resolve()
3366
+ if (d.provider && d.model && typeof remoteFace.session.selectModel === 'function') {
3367
+ chain = chain.then(function () { try { return remoteFace.session.selectModel({ sessionId: newId, provider: d.provider, model: d.model }) } catch (eM) { return null } })
3368
+ }
3369
+ return chain.then(function () {
3370
+ try { if (sessions && typeof sessions.open === 'function') sessions.open(newId) } catch (eO) {}
3371
+ var reqId = (window.crypto && typeof crypto.randomUUID === 'function') ? crypto.randomUUID() : 'ac-' + Date.now() + '-' + Math.random().toString(36).slice(2)
3372
+ return remoteFace.session.prompt({ requestId: reqId, sessionId: newId, mode: 'queue', content: [{ type: 'text', text: d.carryText }] })
3373
+ })
3374
+ })
3375
+ }).then(function () {
3376
+ try { localStorage.setItem('dsh-auto-memory.autoCont.last', String(Date.now())) } catch (eL) {}
3377
+ setAcSt(locale === 'zh' ? '✓ 已自动接续到新会话,可直接上手' : '✓ Auto-continued into a new session')
3378
+ setAcBusy(false)
3379
+ }).catch(function (e) { setAcSt('✗ ' + String(e && e.message ? e.message : e)); setAcBusy(false) })
3380
+ }
3381
+ if (acCd > 0 || acSt) {
3382
+ return h('div', { 'data-dam-autocont': '', style: { position: 'fixed', right: '16px', bottom: '16px', zIndex: 9000, maxWidth: 'min(440px, calc(100vw - 32px))', boxSizing: 'border-box', padding: '10px 12px', borderRadius: '12px', border: '1px solid rgba(128,128,128,.35)', background: 'rgba(18,22,30,.93)', color: '#e8eaed', fontSize: '12px', lineHeight: '1.55', fontFamily: 'system-ui', boxShadow: '0 10px 30px rgba(0,0,0,.35)', backdropFilter: 'blur(10px)' } },
3383
+ acCd > 0 ? h('div', null, t('autoContCountdown').replace('{s}', String(acCd)), ' ', h('button', { style: { marginLeft: '6px', border: '1px solid rgba(232,234,237,.45)', borderRadius: '8px', background: 'transparent', color: '#e8eaed', cursor: 'pointer', padding: '2px 10px' }, onClick: cancelAc }, t('autoContCancel'))) : null,
3384
+ acSt ? h('div', { style: acCd > 0 ? { marginTop: '4px' } : {} }, acSt) : null)
3385
+ }
3386
+ return null
3387
+ }
3201
3388
  function SettingsPage() {
3202
3389
  var tickPair = useTick()
3203
3390
  var cfgPair = useState(null)
@@ -3423,7 +3610,15 @@ window.__ModuleLoader__.load({
3423
3610
  if (detBusy) return
3424
3611
  setDetOpen(true)
3425
3612
  setDetBusy(true)
3426
- apiGet(API.semanticDeepDetect).then(function (d) { setDet(d || {}); setDetBusy(false) }).catch(function () { setDet({ failed: true }); setDetBusy(false) })
3613
+ apiGet(API.semanticDeepDetect).then(function (d) {
3614
+ setDet(d || {}); setDetBusy(false)
3615
+ // 2026-09-08:检测发现缺失时按当前模式自动打开对应安装引导卡(兑现「缺失时自动弹安装引导」)
3616
+ var rec = d && d.recommendation
3617
+ var mode = (cfg && cfg.semanticEngineMode) || 'auto'
3618
+ if (rec === 'setup-python' && mode === 'python') setGuide('python')
3619
+ else if ((rec === 'download-model' || rec === 'install-peer' || rec === 'setup-both') && mode !== 'python') setGuide('js')
3620
+ else if (rec === 'setup-both' && mode === 'python') setGuide('python')
3621
+ }).catch(function () { setDet({ failed: true }); setDetBusy(false) })
3427
3622
  fetch('/api/dsh-auto-memory/semantic-status').then(function (r2) { return r2.json() }).then(function (j2) { setSem(Object.assign({ loaded: true }, j2)) }).catch(function () {})
3428
3623
  }
3429
3624
  function onEngineModeChange(e) {
@@ -3517,18 +3712,23 @@ window.__ModuleLoader__.load({
3517
3712
  } else if (det) {
3518
3713
  kids.push(row('JS 引擎模型', det.ready ? '✓ 就绪' : '✗ 未就绪'))
3519
3714
  if (det.assetPath) kids.push(row('模型路径', String(det.assetPath).slice(-72) + (det.assetBytes ? ' (' + Math.round(det.assetBytes / 1048576) + 'MB)' : '')))
3520
- kids.push(row('Python 模型(int8)', sem.pythonInt8Present ? '✓ 就绪' : '✗ 未就绪'))
3715
+ var pyReady = (det && det.pythonInt8Present !== undefined) ? det.pythonInt8Present : sem.pythonInt8Present
3716
+ kids.push(row('Python 模型(int8)', (pyReady === undefined || pyReady === null) ? (locale === 'zh' ? '状态未知' : 'unknown') : (pyReady ? '✓ 就绪' : '✗ 未就绪')))
3521
3717
  kids.push(row('当前生效档位', tierText))
3522
3718
  if (det.deep && det.deep.integrated) kids.push(row('深度扫描', locale === 'zh' ? '发现并热接入 ' + (det.deep.foundDirs || []).length + ' 处推理库(无需重启即生效)' : 'Hot-adopted ' + (det.deep.foundDirs || []).length + ' runtime dir(s) (no restart needed)'))
3523
3719
  if (det.recommendation && det.recommendation !== 'none') {
3524
3720
  kids.push(h('div', { 'data-dam-hint': '', style: { margin: '8px 0 6px' } }, locale === 'zh' ? '检测到缺失项,联动安装助手:' : 'Missing assets detected — open the setup assistant:'))
3525
3721
  var btns = []
3526
3722
  if (det.recommendation === 'download-model' || det.recommendation === 'setup-both') btns.push(h('button', { key: 'js', 'data-dam-btn': '', style: { marginRight: '6px' }, onClick: function () { setGuide('js'); setDetOpen(false) } }, locale === 'zh' ? '打开 JS 安装引导' : 'Open JS setup'))
3527
- if (det.recommendation === 'setup-both') btns.push(h('button', { key: 'py', 'data-dam-btn': '', onClick: function () { setGuide('python'); setDetOpen(false) } }, locale === 'zh' ? '打开 Python 向导' : 'Open Python wizard'))
3723
+ if (det.recommendation === 'setup-both' || det.recommendation === 'setup-python') btns.push(h('button', { key: 'py', 'data-dam-btn': '', onClick: function () { setGuide('python'); setDetOpen(false) } }, locale === 'zh' ? '打开 Python 向导' : 'Open Python wizard'))
3528
3724
  if (det.recommendation === 'install-peer') kids.push(h('div', { 'data-dam-hint': '', style: { marginTop: '4px' } }, locale === 'zh' ? '模型已就绪但推理库(@huggingface/transformers)缺失:请在其它设备安装后重试检测,或按 JS 引导重装。' : 'Model ready but runtime (@huggingface/transformers) missing: install it and re-scan, or reinstall via JS setup.'))
3529
3725
  if (btns.length) kids.push(h('div', { style: { display: 'flex', gap: '6px' } }, btns))
3530
- } else if (det.ready) {
3726
+ } else if (det.ready && det.pythonInt8Present !== false) {
3531
3727
  kids.push(h('div', { 'data-dam-hint': '', style: { marginTop: '8px' } }, locale === 'zh' ? '✓ 一切就绪,无需安装。' : '✓ Everything is ready.'))
3728
+ } else if (det.ready) {
3729
+ // 2026-09-08 修复:JS 就绪但 Python 缺失不再显示「一切就绪」(此前 recommendation=none 导致矛盾+无引导)
3730
+ kids.push(h('div', { 'data-dam-hint': '', style: { margin: '8px 0 6px' } }, locale === 'zh' ? 'JS 引擎就绪;Python 模型未安装——仅影响 Python 引擎模式,当前模式不受影响。' : 'JS engine ready; the Python model is not installed — only the Python engine mode is affected.'))
3731
+ kids.push(h('div', { style: { display: 'flex', gap: '6px' } }, [h('button', { 'data-dam-btn': '', onClick: function () { setGuide('python'); setDetOpen(false) } }, locale === 'zh' ? '打开 Python 向导' : 'Open Python wizard')]))
3532
3732
  }
3533
3733
  }
3534
3734
  return h('div', { 'data-dam-detect-panel': '', style: panelStyle }, kids)
@@ -3953,6 +4153,9 @@ window.__ModuleLoader__.load({
3953
4153
  surfaceDisposers.push(slots.inject('shell.overlay', function () {
3954
4154
  return slots.register({ name: 'shell.overlay', id: 'auto-memory-dialogs', order: 6 }, function () { return h(DialogHost) })
3955
4155
  }))
4156
+ surfaceDisposers.push(slots.inject('shell.overlay', function () {
4157
+ return slots.register({ name: 'shell.overlay', id: 'auto-memory-autocont', order: 7 }, function () { return h(AutoContinueHost) })
4158
+ }))
3956
4159
  surfaceDisposers.push(slots.inject('settings.section', function () {
3957
4160
  return slots.register({ name: 'settings.section', id: 'auto-memory', order: 25, label: t('autoMemory') + ' (pre)' }, function (props) { return h(SettingsPage, { close: props && props.close }) })
3958
4161
  }))
package/lib/index.js CHANGED
@@ -5302,14 +5302,25 @@ export function apply(ctx, config) {
5302
5302
  } catch (_) { /* 扫描失败按未命中处理 */ }
5303
5303
  }
5304
5304
  const after = await engine.semanticAssetProbe()
5305
- const recommendation = after.ready ? 'none'
5306
- : (!after.assetPresent && !after.peerPresent) ? 'setup-both'
5307
- : (!after.peerPresent) ? 'install-peer'
5308
- : 'download-model'
5305
+ // 2026-09-08 修复:检测面补 Python int8 探测——此前 recommendation 只看 JS 的 after.ready,
5306
+ // JS 就绪+Python 模型缺失时恒报 'none',面板同屏「Python ✗ 未就绪」与「✓ 一切就绪」且永不弹安装引导。
5307
+ let pythonInt8Present = false
5308
+ try {
5309
+ const fsMod = await import('node:fs')
5310
+ const pyCands = (engine._pythonSetup ? [engine._pythonSetup.modelPath()] : []).concat([
5311
+ path.join(pluginRootDir(), 'python', 'bench', 'models-xenova-bge-m3-int8', 'onnx', 'model_int8.onnx'),
5312
+ ])
5313
+ pythonInt8Present = pyCands.some((c) => fsMod.existsSync(c))
5314
+ } catch (_) {}
5315
+ const recommendation = (after.ready && pythonInt8Present) ? 'none'
5316
+ : !after.ready ? ((!after.assetPresent && !after.peerPresent) ? 'setup-both'
5317
+ : (!after.peerPresent) ? 'install-peer' : 'download-model')
5318
+ : 'setup-python'
5309
5319
  return {
5310
5320
  assetPresent: after.assetPresent,
5311
5321
  peerPresent: after.peerPresent,
5312
5322
  ready: after.ready,
5323
+ pythonInt8Present,
5313
5324
  assetBytes: after.assetBytes,
5314
5325
  assetPath: after.assetPath,
5315
5326
  resolvedTier: await engine.resolveSemanticTier(),
@@ -5324,7 +5335,16 @@ export function apply(ctx, config) {
5324
5335
  // 2026-08-27 修正:区分引擎模式(修复「怎么切都显示 C2」)。
5325
5336
  // lexical→c1 强制;python→c3(高级档);auto/js→资产就绪 c2 否则 c1。
5326
5337
  if (mode === 'lexical') return 'c1'
5327
- if (mode === 'python') return 'c3'
5338
+ if (mode === 'python') {
5339
+ // 2026-09-08 修复:python 模式不再无条件报 C3——int8 模型缺失时实际在词法兜底,应报 c1。
5340
+ try {
5341
+ const fsMod = await import('node:fs')
5342
+ const pyCands = (engine._pythonSetup ? [engine._pythonSetup.modelPath()] : []).concat([
5343
+ path.join(pluginRootDir(), 'python', 'bench', 'models-xenova-bge-m3-int8', 'onnx', 'model_int8.onnx'),
5344
+ ])
5345
+ return pyCands.some((c) => fsMod.existsSync(c)) ? 'c3' : 'c1'
5346
+ } catch (_) { return 'c1' }
5347
+ }
5328
5348
  try { return (await engine.semanticAssetProbe()).ready ? 'c2' : 'c1' } catch (_) { return 'c1' }
5329
5349
  }
5330
5350
  // context-host refs 选择钩子:C2 就绪时返回 {scores:Map};任何失败回退词法序。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@a9i5k4/dsh-auto-memory",
3
3
  "description": "Proactive associative memory for DSH: zero-prompt recall injected before the model speaks, three-layer auto-consolidation, skill crystallization, and Astra-style context management - handoff ledgers, PLAN whiteboard, water-level sensing. Local-first, model-agnostic, zero deps. 主动联想记忆+Astra 式上下文管理:自动唤回/自动沉淀/技能固化/交接账本与白板跨窗口续命/水位感知。",
4
- "version": "2.2.1",
4
+ "version": "2.2.3",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "lib",
14
14
  "python",
15
+ "docs",
15
16
  "cordis.patch.yml",
16
17
  "!python/bench",
17
18
  "!python/__pycache__"
@@ -22,6 +23,7 @@
22
23
  },
23
24
  "client": {
24
25
  "inject": [
26
+ "@deepseek-ai/dsh-api-remotes",
25
27
  "@deepseek-ai/dsh-client-runtime",
26
28
  "@deepseek-ai/dsh-client-connection",
27
29
  "@deepseek-ai/dsh-client-ui-slots",