@a9i5k4/dsh-auto-memory 2.1.3 → 2.1.5

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/lib/client.js CHANGED
@@ -147,6 +147,8 @@ window.__ModuleLoader__.load({
147
147
  storageScanHint: '语料健康 = 逐源比对索引(sidecar)与正文的 digest。手动改动记忆文件后索引会失配,该记忆会退出检索直到重建索引。',
148
148
  storageDeleteHint: '删除记忆 = 正文原子删除 + 在途唤起包清理 + 派生事实撤销(三联动)。已产生的 seen 证据不改写。',
149
149
  secSemantic: '自动记忆引擎', semMode: '检索模式', semAuto: '自动(推荐)', semLexOnly: '仅词法', semJs: '内置语义', semPy: '高级 Python',
150
+ pyWizTitle: 'Python 引擎一键安装', pyWizStep1: '① 检测 Python 环境', pyWizStep2: '② 创建独立虚拟环境(~/.dsh/python-engine/.venv,不污染系统)', pyWizStep3: '③ 安装引擎依赖(fastembed + onnxruntime)', pyWizStep4: '④ 下载 BGE-M3 int8 模型(~539MB,断点续传,失败自动换源)',
151
+ pyWizDetect: '开始检测', pyWizRedetect: '重新检测', pyWizCreate: '创建虚拟环境', pyWizInstall: '安装依赖', pyWizDownload: '开始下载', pyWizCancel: '取消下载', pyWizDone: '全部就绪 ✓ — 回上方启用即可', pyWizOk: 'ok', pyWizMissing: '未找到', pyWizTooOld: '版本不兼容(需 3.9-3.12)', pyWizVenvRec: '推荐', pyWizEta: '剩余', pyWizSec: '秒', pyWizModelHint: '模型与虚拟环境安装在 ~/.dsh/python-engine/(用户目录),升级/重装插件不受影响。',
150
152
  semModeHint: '自动=内置语义就绪即用,否则词法保底;高级 Python 需另行安装。',
151
153
  fAssocEngine: '启用自动记忆引擎', fAssocEngineHint: '总开关。开启后自动观测上下文、语义检索并适时唤起记忆注入(消费少量 token)。关闭则整个引擎不运行——不检索、不判定、不注入、不生成唤起记录。介意 token 消耗或担心动作跑偏的用户可关闭。默认关。',
152
154
  secMemoryHubHint: '记忆中枢 = 三层记忆(经历/事实/技能)的编排器。开启后自动从对话沉淀经历、固化事实、把反复成功的流程固化为技能(skill),并在相似场景自动召回注入。',
@@ -284,6 +286,8 @@ window.__ModuleLoader__.load({
284
286
  storageScanHint: 'Corpus health = compare each source\'s index (sidecar) against its body digest. After you hand-edit a memory file the index no longer matches, and that memory drops out of retrieval until the index is rebuilt.',
285
287
  storageDeleteHint: 'Delete = atomic body removal + in-flight activation purge + derived-fact revocation (cascading). Evidence already recorded (seen) is never rewritten.',
286
288
  secSemantic: 'Semantic engine', semMode: 'Retrieval mode', semAuto: 'Auto (recommended)', semLexOnly: 'Lexical only', semJs: 'Built-in semantic', semPy: 'Advanced Python',
289
+ pyWizTitle: 'One-click Python engine setup', pyWizStep1: '1. Detect Python environment', pyWizStep2: '2. Create isolated venv (~/.dsh/python-engine/.venv, system untouched)', pyWizStep3: '3. Install engine deps (fastembed + onnxruntime)', pyWizStep4: '4. Download BGE-M3 int8 model (~539MB, resumable, auto mirror failover)',
290
+ pyWizDetect: 'Detect', pyWizRedetect: 'Re-detect', pyWizCreate: 'Create venv', pyWizInstall: 'Install deps', pyWizDownload: 'Start download', pyWizCancel: 'Cancel download', pyWizDone: 'All ready - enable it above', pyWizOk: 'ok', pyWizMissing: 'not found', pyWizTooOld: 'incompatible (need 3.9-3.12)', pyWizVenvRec: 'recommended', pyWizEta: 'eta', pyWizSec: 's', pyWizModelHint: 'Model and venv live in ~/.dsh/python-engine/ (user dir) - plugin upgrades never touch them.',
287
291
  fAssocEngine: 'Enable automatic memory engine', fAssocEngineHint: 'Master switch. On = auto-observe context, semantic retrieval, and timely memory-activation injection (costs a little token). Off = the whole engine stops — no retrieval, no decide, no injection, no activation records. For users concerned about token cost or off-course actions. Default off.',
288
292
  secMemoryHubHint: 'Memory Hub = the orchestrator for three memory layers (episodic / semantic / procedural). When on, it distills episodes from dialogue, solidifies facts, and turns repeatedly-successful workflows into skills that are auto-recalled in similar contexts.',
289
293
  fMemoryHub: 'Enable Memory Hub', fMemoryHubHint: 'Master switch. On = the three memory layers (episodic / semantic / procedural) start running; Off = keep existing memories but stop distilling new ones. Default off.',
@@ -684,6 +688,12 @@ window.__ModuleLoader__.load({
684
688
  notices: '/api/dsh-auto-memory/notices',
685
689
  models: '/api/dsh-auto-memory/models',
686
690
  semanticDeepDetect: '/api/dsh-auto-memory/semantic-deep-detect',
691
+ pyDetect: '/api/dsh-auto-memory/python-setup/detect',
692
+ pyVenv: '/api/dsh-auto-memory/python-setup/venv',
693
+ pyDeps: '/api/dsh-auto-memory/python-setup/deps',
694
+ pyModel: '/api/dsh-auto-memory/python-setup/model',
695
+ pyCancel: '/api/dsh-auto-memory/python-setup/cancel',
696
+ pyStatus: '/api/dsh-auto-memory/python-setup/status',
687
697
  handoffState: '/api/dsh-auto-memory/handoff-state',
688
698
  semanticDownload: '/api/dsh-auto-memory/semantic-download',
689
699
  }
@@ -1203,6 +1213,73 @@ window.__ModuleLoader__.load({
1203
1213
  return h(Card, { title: (g.period || '') + ' · ' + segLabel }, rows)
1204
1214
  }
1205
1215
 
1216
+ function PySetupWizard() {
1217
+ var dataPair = useState(null)
1218
+ var data = dataPair[0]
1219
+ var setData = dataPair[1]
1220
+ var busyPair = useState(false)
1221
+ var busy = busyPair[0]
1222
+ var setBusy = busyPair[1]
1223
+ var pollPair = useState(null)
1224
+ var poll = pollPair[0]
1225
+ var setPoll = pollPair[1]
1226
+ var refresh = function () { apiGet(API.pyStatus).then(function (d) { if (d) setData(d) }).catch(function () {}) }
1227
+ useEffect(function () {
1228
+ var alive = true
1229
+ apiGet(API.pyDetect).then(function (d) { if (alive && d) setData(d) }).catch(function () {})
1230
+ return function () { alive = false }
1231
+ }, [])
1232
+ useEffect(function () {
1233
+ if (!poll) return
1234
+ var t = setInterval(refresh, 1200)
1235
+ return function () { clearInterval(t) }
1236
+ }, [poll])
1237
+ var act = function (api, poll2) {
1238
+ if (busy) return
1239
+ setBusy(true)
1240
+ var done = function (d) { setData(d); setBusy(false); if (poll2) setPoll(true); var ph = d && d.phase; if (!poll2 || ph === 'ready' || ph === 'error' || ph === 'idle') setPoll(false) }
1241
+ apiPost(api, {}).then(done).catch(function () { setBusy(false); setPoll(false) })
1242
+ }
1243
+ if (!data) return h('div', { style: { border: '1px solid color-mix(in srgb, var(--dam-accent, #2456c4) 40%, transparent)', borderRadius: '10px', padding: '10px 12px', marginBottom: '8px', fontSize: 'calc(11.5px * var(--dam-scale))' } }, t('pyWizTitle'), ' — ', t('detecting'))
1244
+ var dl = data.dl || {}
1245
+ var dlActive = data.phase === 'downloading' || data.phase === 'verifying'
1246
+ var progress = dlActive ? Math.min(100, Math.round(((dl.bytesDone || 0) / Math.max(1, dl.bytesTotal || 1)) * 100)) : (data.modelReady ? 100 : 0)
1247
+ var fmtMB = function (b) { return b ? (b / 1048576).toFixed(1) + ' MB' : '—' }
1248
+ var stepRow = function (label, status, btn) {
1249
+ var badge = status === true ? { txt: t('pyWizOk'), bg: 'rgba(47,164,106,.24)' } : status === 'run' ? { txt: '…', bg: 'rgba(36,86,196,.2)' } : { txt: '○', bg: 'rgba(128,128,128,.16)' }
1250
+ return h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', margin: '6px 0' } },
1251
+ h('span', { style: { fontSize: 'calc(10px * var(--dam-scale))', padding: '2px 8px', borderRadius: '6px', background: badge.bg, fontWeight: 700, minWidth: '28px', textAlign: 'center' } }, badge.txt),
1252
+ h('span', { style: { flex: 1 } }, label),
1253
+ btn || null)
1254
+ }
1255
+ var btnCls = { 'data-dam-btn': '', disabled: busy }
1256
+ var pythonRows = (data.pythons || []).map(function (p2, idx) {
1257
+ var st = p2.status === 'ok' ? t('pyWizOk') + (p2.isVenv ? ' · ' + t('pyWizVenvRec') : '') + (p2.version ? ' (' + p2.version + ')' : '') : p2.status === 'too-old' ? t('pyWizTooOld') + (p2.version ? ' (' + p2.version + ')' : '') : t('pyWizMissing')
1258
+ return h('div', { key: idx, style: { fontSize: 'calc(10.5px * var(--dam-scale))', opacity: p2.status === 'ok' ? 1 : 0.55, margin: '2px 0' } }, '· ' + p2.label + ' — ' + st)
1259
+ })
1260
+ var allReady = data.venvOk && data.depsOk && data.modelReady
1261
+ return h('div', { style: { border: '1px solid color-mix(in srgb, var(--dam-accent, #2456c4) 40%, transparent)', borderRadius: '10px', padding: '10px 12px', marginBottom: '8px', fontSize: 'calc(11.5px * var(--dam-scale))', lineHeight: 1.6 } },
1262
+ h('div', { style: { fontWeight: 700, marginBottom: '4px' } }, t('pyWizTitle')),
1263
+ h('div', { style: { opacity: .6, fontSize: 'calc(10.5px * var(--dam-scale))', marginBottom: '6px' } }, t('pyWizModelHint')),
1264
+ stepRow(t('pyWizStep1'), data.pythons && data.pythons.some(function (p2) { return p2.status === 'ok' }) ? true : 'run',
1265
+ h('button', { 'data-dam-btn': '', onClick: function () { act(API.pyDetect) } }, t('pyWizRedetect'))),
1266
+ h('div', { style: { margin: '0 0 6px 36px' } }, pythonRows),
1267
+ stepRow(t('pyWizStep2'), data.venvOk ? true : 'run',
1268
+ (!data.venvOk && (data.pythons || []).some(function (p2) { return p2.status === 'ok' && !p2.isVenv })) ? h('button', Object.assign({}, btnCls, { onClick: function () { act(API.pyVenv, true) } }), t('pyWizCreate')) : null),
1269
+ stepRow(t('pyWizStep3'), data.depsOk ? true : 'run',
1270
+ (data.venvOk && !data.depsOk) ? h('button', Object.assign({}, btnCls, { onClick: function () { act(API.pyDeps, true) } }), t('pyWizInstall')) : null),
1271
+ stepRow(t('pyWizStep4'), data.modelReady ? true : 'run',
1272
+ (!data.modelReady && !dlActive) ? h('button', Object.assign({}, btnCls, { onClick: function () { act(API.pyModel, true) } }), t('pyWizDownload')) : null,
1273
+ dlActive ? h('button', { 'data-dam-btn': '', onClick: function () { apiPost(API.pyCancel, {}).then(refresh).catch(function () {}) } }, t('pyWizCancel')) : null),
1274
+ dlActive || data.modelReady ? h('div', { style: { margin: '4px 0 6px 36px' } },
1275
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 'calc(10px * var(--dam-scale))', opacity: .7, marginBottom: '2px' } },
1276
+ h('span', null, dlActive ? (data.phase === 'verifying' ? t('dlVerifying') : t('dlDownloading')) + ' · ' + fmtMB(dl.bytesDone) + ' / ' + fmtMB(dl.bytesTotal) : t('pyWizDone')),
1277
+ h('span', null, progress + '%')),
1278
+ h('div', { style: { height: '7px', borderRadius: '99px', background: 'rgba(128,128,128,.14)', overflow: 'hidden' } },
1279
+ h('div', { style: { height: '100%', width: progress + '%', borderRadius: '99px', background: 'linear-gradient(90deg, var(--dam-accent, #2456c4), #6f9bff)', transition: 'width .4s ease' } }))) : null,
1280
+ data.error ? h('div', { style: { color: '#c44a4a', fontSize: 'calc(10.5px * var(--dam-scale))', marginTop: '4px' } }, data.error) : null,
1281
+ allReady ? h('div', { style: { color: '#2fa46a', fontWeight: 700, marginTop: '4px' } }, t('pyWizDone')) : null)
1282
+ }
1206
1283
  function OverviewTab(props) {
1207
1284
  var statePair = useState(null)
1208
1285
  var state = statePair[0]
@@ -3261,7 +3338,7 @@ window.__ModuleLoader__.load({
3261
3338
  h('div', { 'data-dam-settings-content': '' },
3262
3339
  section('semantic', sectionLabels.secSemantic, [
3263
3340
  field(t('fAssocEngine'), h('input', { type: 'checkbox', checked: !!cfg.associativeMemoryEnabled, onChange: function (e) { set('associativeMemoryEnabled', e.target.checked) } }), t('fAssocEngineHint')),
3264
- field(t('fJsCooldown'), h('input', { 'data-dam-input': '', type: 'number', min: 0, max: 60, value: cfg.jsDecideCooldownRounds === undefined ? 1 : cfg.jsDecideCooldownRounds, onChange: function (e) { set('jsDecideCooldownRounds', Number(e.target.value) || 1) } }), t('fJsCooldownHint')),
3341
+ field(t('fJsCooldown'), h('input', { 'data-dam-input': '', type: 'number', min: 0, max: 60, value: cfg.jsDecideCooldownRounds === undefined ? 1 : cfg.jsDecideCooldownRounds, onChange: function (e) { set('jsDecideCooldownRounds', (function () { var v = Number(e.target.value); return (Number.isFinite(v) && v >= 0) ? v : 1 })()) /* #19: 0=不冷却 是合法值,|| 1 会吃掉 0 */ } }), t('fJsCooldownHint')),
3265
3342
  field(t('fJsDelta'), h('input', { 'data-dam-input': '', type: 'number', min: 0, max: 1, step: 0.005, value: cfg.jsDecideDeltaExp === undefined ? 0.01 : cfg.jsDecideDeltaExp, onChange: function (e) { var v = Number(e.target.value); set('jsDecideDeltaExp', Number.isFinite(v) && v >= 0 ? v : 0.01) } }), t('fJsDeltaHint')),
3266
3343
  field(t('fJsExcerpt'), h('input', { 'data-dam-input': '', type: 'number', min: 20, max: 480, value: cfg.jsDecideExcerptChars === undefined ? 40 : cfg.jsDecideExcerptChars, onChange: function (e) { set('jsDecideExcerptChars', Math.max(20, Math.min(480, Number(e.target.value) || 40))) } }), t('fJsExcerptHint')),
3267
3344
  field(t('fEmitMode'), h('select', { 'data-dam-select': '', value: (sem && sem.activationEmitMode) || 'shadow', onChange: function (e) { var m = e.target.value; apiPost('/api/dsh-auto-memory/semantic-emit', { mode: m }).then(function () { try { fetch('/api/dsh-auto-memory/semantic-status').then(function (r2) { return r2.json() }).then(function (j2) { setSem(Object.assign({ loaded: true }, j2)) }).catch(function () {}) } catch (_) {} }).catch(function () {}) } },
@@ -3281,6 +3358,7 @@ window.__ModuleLoader__.load({
3281
3358
  sem.loaded ? h('div', { 'data-dam-hint': '', style: { marginTop: '-4px', marginBottom: '8px' } },
3282
3359
  t('semResolved') + ': ' + (sem.resolvedTier === 'c2' ? t('tierC2') + ' ✓' : sem.resolvedTier === 'c3' ? t('tierC3') + ' ✓' : t('tierC1')))
3283
3360
  : null,
3361
+ guide === 'python' ? h(PySetupWizard) : null,
3284
3362
  guide === 'js' || guide === 'python' ? (function () {
3285
3363
  // 安装引导卡(对齐 ui-assets 原型:进度条/下载源/体积/状态)——资产检测由 sem 状态机驱动
3286
3364
  var isJs = guide === 'js'