@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.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/docs/A3-RISK-ASSESSMENT-20260830.md +61 -0
- package/docs/COT-WATCH-RFC.md +88 -0
- package/docs/DUAL-TIER-RATIFICATION-PROMPT.md +71 -0
- package/docs/HANDOFF-HARNESS.md +78 -0
- package/docs/HANDOFF-M8-M9-M10.md +203 -0
- package/docs/HY4-TOUR-LOGO-HANDOFF-2.md +60 -0
- package/docs/HY4-TOUR-LOGO-HANDOFF.md +100 -0
- package/docs/ISSUE-REPLY-UNATTENDED.md +31 -0
- package/docs/K3-LANDING-HANDOFF.md +76 -0
- package/docs/LANDING-OUTLINE.md +85 -0
- package/docs/M-CM-PLAN.md +166 -0
- package/docs/M-CM-STATE.md +64 -0
- package/docs/M3B-CONTRACT.md +461 -0
- package/docs/M4-CONTRACT.md +1207 -0
- package/docs/M5-CONTRACT.md +383 -0
- package/docs/M6-CONTRACT.md +342 -0
- package/docs/M7-ACTIVATION-ALGO-REFERENCES.md +104 -0
- package/docs/M7-ACTIVATION-CALIBRATION.md +144 -0
- package/docs/M7-ACTIVATION-FEATURE-AGENT-PROMPT.md +79 -0
- package/docs/M7-ACTIVATION-FEATURE-CALIBRATION.md +58 -0
- package/docs/M7-ACTIVATION-FEATURE-DESIGN.md +124 -0
- package/docs/M7-ACTIVATION-V2-CONTROLLED-SHADOW.md +127 -0
- package/docs/M7-ACTIVATION-V2-HANDOFF.md +132 -0
- package/docs/M7-ACTIVATION-V2-HOLDEDOUT-EVAL.md +94 -0
- package/docs/M7-ACTIVATION-V2-HOLDEDOUT-SHADOW.md +60 -0
- package/docs/M7-ACTIVATION-V2-LIVE-SHADOW-PLAN.md +85 -0
- package/docs/M7-ACTIVATION-V2-PAPER.md +303 -0
- package/docs/M7-AGENT-HANDOFF-PROMPT.md +63 -0
- package/docs/M7-ALGORITHM-DECISION.md +174 -0
- package/docs/M7-AUTONOMOUS-STATE.md +252 -0
- package/docs/M7-BENCHMARK-PLAN.md +78 -0
- package/docs/M7-CLOSED-LOOP-WIRING.md +110 -0
- package/docs/M7-EMBEDDING-BENCHMARK.md +164 -0
- package/docs/M7-INTERFACE-DIGEST.md +144 -0
- package/docs/M7-LABEL-REVIEW-REPORT.md +107 -0
- package/docs/M7-LEXICAL-TUNING.md +58 -0
- package/docs/M7-LIVE-SHADOW-SCRIPT.md +30 -0
- package/docs/M7-PYTHON-IMPLEMENTATION-REPORT.md +92 -0
- package/docs/M7-RESEARCH-PAPER.md +442 -0
- package/docs/M7-TASKSET-DISPATCH.md +213 -0
- package/docs/M8-MEMORY-HUB.md +105 -0
- package/docs/MEMORY-SYSTEMS-SURVEY-2026-09.md +166 -0
- package/docs/NEXT-MAJOR-PROMO.md +363 -0
- package/docs/NEXT-MAJOR-README-DRAFT.zh.md +205 -0
- package/docs/NEXT-MAJOR-VISION.md +112 -0
- package/docs/PREVIEW-NEXT-STEPS.md +229 -0
- package/docs/PROJECT-FREEZE-AND-ROADMAP.md +200 -0
- package/docs/PROMO-STYLE-GUIDE.md +84 -0
- package/docs/PYTHON-SIDECAR-CONTRACT.md +539 -0
- package/docs/R2-POLICY-PLUMBING-BLUEPRINT.md +99 -0
- package/docs/RELEASE-READINESS-PLAN.md +91 -0
- package/docs/RELEASE-SEMANTIC-OPTION.md +181 -0
- package/docs/S1-SCIENTIFIC-RIGOR.md +269 -0
- package/docs/S2-DEEP-ABSORPTION.md +259 -0
- package/docs/S3-TARGET-ARCHITECTURE.md +172 -0
- package/docs/USER-GUIDE.zh-CN.md +98 -0
- package/docs/banner.jpg +0 -0
- package/docs/implementation-handoff-context.zh-CN.md +429 -0
- package/docs/landing/index.html +1745 -0
- package/docs/paper-figures/fig1_model_quality.png +0 -0
- package/docs/paper-figures/fig2_chunk_reversal.png +0 -0
- package/docs/paper-figures/fig3_latency.png +0 -0
- package/docs/paper-figures/fig4_hybrid.png +0 -0
- package/docs/paper-figures/fig5_rerank_tradeoff.png +0 -0
- package/docs/paper-figures/fig6_cluster_sweep.png +0 -0
- package/docs/paper-figures/fig7_resource.png +0 -0
- package/docs/paper-figures-v2/fig1_echo_trap.png +0 -0
- package/docs/paper-figures-v2/fig2_pr_paths.png +0 -0
- package/docs/paper-figures-v2/fig3_coefficients.png +0 -0
- package/docs/paper-figures-v2/fig4_calibration.png +0 -0
- package/docs/paper-figures-v2/fig5_order_ablation.png +0 -0
- package/docs/paper-figures-v2/fig6_containment.png +0 -0
- package/docs/proactive-associative-memory-architecture.html +659 -0
- package/docs/proactive-associative-memory-meta-code.html +1058 -0
- package/docs/proactive-associative-memory-research-report.zh-CN.md +685 -0
- package/docs/proactive-associative-memory-system-map.html +1580 -0
- package/docs/promo/first-run-guide.html +397 -0
- package/docs/promo/homepage.html +384 -0
- package/docs/screenshots/calendar-en.png +0 -0
- package/docs/screenshots/calendar-zh.png +0 -0
- package/docs/screenshots/connect-en.png +0 -0
- package/docs/screenshots/connect-zh.png +0 -0
- package/docs/screenshots/main-connect-en.png +0 -0
- package/docs/screenshots/main-connect-zh.png +0 -0
- package/docs/screenshots/overview-en.png +0 -0
- package/docs/screenshots/overview-zh.png +0 -0
- package/docs/screenshots/panel-hub.png +0 -0
- package/docs/screenshots/panel-overview.png +0 -0
- package/docs/screenshots/panel-refine.png +0 -0
- package/docs/screenshots/promo/promo-0-banner-v2.png +0 -0
- package/docs/screenshots/promo/promo-1-hero.png +0 -0
- package/docs/screenshots/promo/promo-2-tour.png +0 -0
- package/docs/screenshots/promo/promo-3-recall.png +0 -0
- package/docs/screenshots/promo/promo-4-unattended.png +0 -0
- package/docs/screenshots/promo/promo-5-external.png +0 -0
- package/docs/screenshots/promo/promo-6-greeting.png +0 -0
- package/docs/screenshots/reflections-en.png +0 -0
- package/docs/screenshots/search-zh.png +0 -0
- package/docs/screenshots/settings-2-zh.png +0 -0
- package/docs/screenshots/settings-debug-zh.png +0 -0
- package/docs/screenshots/settings-en.png +0 -0
- package/docs/screenshots/settings-zh.png +0 -0
- package/docs/screenshots/tour-core.png +0 -0
- package/docs/screenshots/tour-external.png +0 -0
- package/docs/screenshots/tour-toggles.png +0 -0
- package/docs/screenshots/tour-welcome.png +0 -0
- package/docs/screenshots/workspace-map-zh.png +0 -0
- package/docs/social-preview.png +0 -0
- package/lib/client.js +207 -4
- package/lib/index.js +25 -5
- 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) {
|
|
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
|
-
|
|
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
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
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')
|
|
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.
|
|
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",
|