@a9i5k4/dsh-auto-memory 2.1.7 → 2.1.8

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
@@ -1223,6 +1223,17 @@ window.__ModuleLoader__.load({
1223
1223
  var pollPair = useState(null)
1224
1224
  var poll = pollPair[0]
1225
1225
  var setPoll = pollPair[1]
1226
+ var gpuPair = useState(function () { try { return localStorage.getItem('dsh-auto-memory.pyGpu') === '1' } catch (eG) { return false } })
1227
+ var gpuPref = gpuPair[0]
1228
+ var setGpuPref = function (v) {
1229
+ gpuPair[1](v)
1230
+ try { localStorage.setItem('dsh-auto-memory.pyGpu', v ? '1' : '0') } catch (eG) {}
1231
+ }
1232
+ var actGpu = function () {
1233
+ if (busy) return
1234
+ setBusy(true)
1235
+ apiPost(API.pyDeps, { gpu: gpuPref }).then(function (d) { setData(d); setBusy(false); setPoll(true); var ph = d && d.phase; if (ph === 'ready' || ph === 'error' || ph === 'idle') setPoll(false) }).catch(function () { setBusy(false); setPoll(false) })
1236
+ }
1226
1237
  var refresh = function () { apiGet(API.pyStatus).then(function (d) { if (d) setData(d) }).catch(function () {}) }
1227
1238
  useEffect(function () {
1228
1239
  var alive = true
@@ -1267,7 +1278,11 @@ window.__ModuleLoader__.load({
1267
1278
  stepRow(t('pyWizStep2'), data.venvOk ? true : 'run',
1268
1279
  (!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
1280
  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),
1281
+ (data.venvOk && !data.depsOk) ? h('span', { style: { display: 'flex', gap: '8px', alignItems: 'center' } },
1282
+ h('label', { style: { display: 'flex', gap: '4px', alignItems: 'center', fontSize: 'calc(10.5px * var(--dam-scale))' } },
1283
+ h('input', { type: 'checkbox', checked: gpuPref, onChange: function (e) { setGpuPref(e.target.checked) } }),
1284
+ locale === 'zh' ? 'GPU 推理(NVIDIA,需已装 CUDA;否则自动回退 CPU)' : 'GPU inference (NVIDIA + CUDA; auto-falls back to CPU)'),
1285
+ h('button', Object.assign({}, btnCls, { onClick: function () { actGpu() } }), t('pyWizInstall'))) : null),
1271
1286
  stepRow(t('pyWizStep4'), data.modelReady ? true : 'run',
1272
1287
  (!data.modelReady && !dlActive) ? h('button', Object.assign({}, btnCls, { onClick: function () { act(API.pyModel, true) } }), t('pyWizDownload')) : null,
1273
1288
  dlActive ? h('button', { 'data-dam-btn': '', onClick: function () { apiPost(API.pyCancel, {}).then(refresh).catch(function () {}) } }, t('pyWizCancel')) : null),
@@ -3421,7 +3436,7 @@ window.__ModuleLoader__.load({
3421
3436
  h('option', { value: 'auto' }, t('mAuto')),
3422
3437
  h('option', { value: 'cn' }, t('mCn')),
3423
3438
  h('option', { value: 'intl' }, t('mIntl'))) : null,
3424
- ready ? h('button', { 'data-dam-btn': '', onClick: function () { setGuide(''); var n2 = Object.assign({}, cfg); n2.semanticEngineMode = guide; if (guide === 'js') { n2.activationSource = 'js'; n2.contextSinkMode = 'null' } else if (guide === 'python') { n2.activationSource = 'python'; n2.contextSinkMode = 'python' } setCfg(n2); setDirty(true) } }, locale === 'zh' ? '启用并继续' : 'Enable & continue') : null,
3439
+ ready ? h('button', { 'data-dam-btn': '', onClick: function () { setGuide(''); var n2 = Object.assign({}, cfg); n2.semanticEngineMode = guide; if (guide === 'js') { n2.activationSource = 'js'; n2.contextSinkMode = 'null' } else if (guide === 'python') { n2.activationSource = 'python'; n2.contextSinkMode = 'python'; try { var gp = localStorage.getItem('dsh-auto-memory.pyGpu'); if (gp === '1') n2.pythonGpu = true } catch (eL) {} } setCfg(n2); setDirty(true) } }, locale === 'zh' ? '启用并继续' : 'Enable & continue') : null,
3425
3440
  !ready && isJs && !dlActive ? h('button', { 'data-dam-btn': '', onClick: startDl }, (dl.phase === 'error' || dl.phase === 'cancelled') ? t('semDlRetry') : t('semDlStart')) : null,
3426
3441
  !ready && isJs && dlActive ? h('button', { 'data-dam-btn': '', onClick: cancelDl }, t('semDlCancel')) : null,
3427
3442
  h('button', { 'data-dam-btn': '', onClick: function () { setGuide('') } }, t('gotIt'))))
package/lib/index.js CHANGED
@@ -5458,7 +5458,8 @@ export function apply(ctx, config) {
5458
5458
  handler: async (req, res) => {
5459
5459
  if (!isLoopbackRequest(req)) return writeJson(res, 403, { error: 'forbidden: loopback-only' })
5460
5460
  if ((req.method || 'POST') !== 'POST') return writeJson(res, 405, { error: 'method not allowed' })
5461
- try { writeJson(res, 200, await engine._pythonSetup.ensureDeps()) } catch (e) { writeJson(res, 500, { error: String(e && e.message || e) }) }
5461
+ const body = await readJsonBody(req).catch(() => ({}))
5462
+ try { writeJson(res, 200, await engine._pythonSetup.ensureDeps({ gpu: !!(body && body.gpu) })) } catch (e) { writeJson(res, 500, { error: String(e && e.message || e) }) }
5462
5463
  },
5463
5464
  },
5464
5465
  {
@@ -35,8 +35,9 @@ const MODEL_SPEC = {
35
35
  ],
36
36
  }
37
37
 
38
- /** venv 内 pip 依赖:与 bench 校准环境同源(transformers AutoTokenizer + onnxruntime;torch 为张量构造所需;池化/精度契约冻结自 R@5 0.925 基线,fastembed 注册表无 BGE-M3 且池化契约不同,不可用)。 */
39
- const PIP_DEPS = ['transformers', 'onnxruntime', 'torch']
38
+ /** venv 内 pip 依赖:#19 实测(int8 档 encode_ids 全程 numpy+onnxruntime,tokenizer 走 Rust 快速路径)——基础集无 torch,venv 体积 ~400MB。GPU 推理开关追加 onnxruntime-gpu(CUDAExecutionProvider)。池化/精度契约冻结自 R@5 0.925 基线,fastembed 注册表无 BGE-M3 且池化契约不同,不可用。 */
39
+ const PIP_DEPS_CPU = ['transformers', 'onnxruntime']
40
+ const PIP_DEPS_GPU_EXTRA = ['onnxruntime-gpu']
40
41
 
41
42
  export function createPythonSetupPre(opts = {}) {
42
43
  const dshHomeOf = typeof opts.dshHome === 'function' ? opts.dshHome : () => opts.dshHome || path.join(homedir(), '.dsh')
@@ -110,7 +111,7 @@ export function createPythonSetupPre(opts = {}) {
110
111
  return {
111
112
  phase: st.phase, error: st.error,
112
113
  pythons: st.pythons, chosenPython: st.chosenPython,
113
- venvOk: st.venvOk, depsOk: st.depsOk, modelReady: st.modelReady,
114
+ venvOk: st.venvOk, depsOk: st.depsOk, modelReady: st.modelReady, wantGpu: !!st.wantGpu,
114
115
  modelPath: modelPath(), venvPython: venvPython(),
115
116
  modelBytes: st.modelReady ? statSync(modelPath()).size : 0, modelExpectedBytes: MODEL_SPEC.bytes,
116
117
  dl: { ...st.dl },
@@ -136,14 +137,17 @@ export function createPythonSetupPre(opts = {}) {
136
137
  return snapshot()
137
138
  }
138
139
 
139
- /** ③deps:venv 内 pip 装 transformers+onnxruntime+torch;官方源失败切清华镜像。 */
140
- async function ensureDeps() {
140
+ /** ③deps:venv 内 pip 装 transformers+onnxruntime(CPU 基础集);opts.gpu=true 追加 onnxruntime-gpu(用户选 GPU 推理时)。官方源失败切清华镜像。 */
141
+ async function ensureDeps(opts2) {
142
+ const wantGpu = !!(opts2 && opts2.gpu)
141
143
  if (!st.venvOk) { st.error = 'venv 未就绪,先执行 venv 步骤'; st.phase = 'error'; return snapshot() }
142
144
  st.phase = 'deps'
145
+ st.wantGpu = wantGpu
146
+ const deps = PIP_DEPS_CPU.concat(wantGpu ? PIP_DEPS_GPU_EXTRA : [])
143
147
  const runPip = async (extra) => {
144
148
  try {
145
- const r = await execFileP(venvPython(), ['-m', 'pip', 'install', '--quiet'].concat(PIP_DEPS).concat(extra || []),
146
- { timeout: 600000, windowsHide: true, maxBuffer: 4 * 1024 * 1024 })
149
+ const r = await execFileP(venvPython(), ['-m', 'pip', 'install', '--quiet'].concat(deps).concat(extra || []),
150
+ { timeout: 900000, windowsHide: true, maxBuffer: 4 * 1024 * 1024 })
147
151
  return { ok: true }
148
152
  } catch (e) { return { ok: false, tail: String((e && (e.stderr || e.message)) || e).slice(-300) } }
149
153
  }
@@ -151,7 +155,18 @@ export function createPythonSetupPre(opts = {}) {
151
155
  if (!r.ok) r = await runPip(['-i', 'https://pypi.tuna.tsinghua.edu.cn/simple'])
152
156
  st.depsOk = !!r.ok
153
157
  if (!r.ok) { st.error = '依赖安装失败: ' + (r.tail || ''); st.phase = 'error'; return snapshot() }
154
- diagOf('python-setup: deps installed into venv')
158
+ // GPU 偏好写入 embedding-config.json(worker 读 config['gpu'] 选 CUDA/CPU provider;read-modify-write 不覆盖既有键)
159
+ try {
160
+ const cfgDir = path.join(dshHomeOf(), 'memory', 'semantic')
161
+ mkdirSync(cfgDir, { recursive: true })
162
+ const cfgPath = path.join(cfgDir, 'embedding-config.json')
163
+ let cfg = {}
164
+ try { cfg = JSON.parse(await readFile(cfgPath, 'utf8')) } catch (_) {}
165
+ if (!cfg || typeof cfg !== 'object') cfg = {}
166
+ cfg.gpu = wantGpu
167
+ await writeFile(cfgPath, JSON.stringify(cfg, null, 2), 'utf8')
168
+ } catch (eCfg) { diagOf('python-setup: gpu pref write failed: ' + String(eCfg && eCfg.message || eCfg)) }
169
+ diagOf('python-setup: deps installed into venv (gpu=' + wantGpu + ')')
155
170
  return snapshot()
156
171
  }
157
172
 
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.1.7",
4
+ "version": "2.1.8",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {