dsh-tdai-memory 0.2.11 → 0.2.12
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 +10 -2
- package/README.zh.md +6 -1
- package/client.js +1 -0
- package/index.js +0 -7
- package/package.json +14 -10
- package/vendor/dsh-settings-expose.js +0 -75
package/README.md
CHANGED
|
@@ -110,8 +110,15 @@ settings page (记忆 / Memory) or directly in `settings.yaml` under
|
|
|
110
110
|
> the plugin patches it automatically on first start — **restart `dsh web`
|
|
111
111
|
> once more** and the section appears. A dsh update overwrites the patch;
|
|
112
112
|
> the next plugin start re-applies it.
|
|
113
|
-
> - Settings changes apply **after a restart** (TdaiCore is built at startup).
|
|
114
|
-
> - Tested against DSH `0.1.0-rc.6`, `0.1.0-rc.7`,
|
|
113
|
+
> - Settings changes apply **after a restart** (TdaiCore is built at startup).
|
|
114
|
+
> - Tested against DSH `0.1.0-rc.6`, `0.1.0-rc.7`, `0.1.0-rc.8`, and
|
|
115
|
+
> `0.1.1-rc.1`.
|
|
116
|
+
|
|
117
|
+
`node-llama-cpp` is an optional peer used only by the fully local embedding
|
|
118
|
+
backend. It is intentionally not installed by default because its native build
|
|
119
|
+
requires explicit pnpm build approval. Remote OpenAI-compatible embeddings do
|
|
120
|
+
not need it. Users who select the local backend should install and approve
|
|
121
|
+
`node-llama-cpp` in the target DSH profile separately.
|
|
115
122
|
|
|
116
123
|
## Known trade-offs
|
|
117
124
|
|
|
@@ -128,3 +135,4 @@ settings page (记忆 / Memory) or directly in `settings.yaml` under
|
|
|
128
135
|
## License
|
|
129
136
|
|
|
130
137
|
MIT
|
|
138
|
+
|
package/README.zh.md
CHANGED
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
- **自动召回注入**:每次组装提示词时,按当前用户消息检索相关记忆 + 画像,作为动态上下文注入(模型"凭空想起")
|
|
17
17
|
- **工具**:`tdai_memory_search`(L1 结构化检索)、`tdai_conversation_search`(L0 原文检索)
|
|
18
18
|
|
|
19
|
-
数据目录复用现有 `~/.memory-tencentdb/memory-tdai`,**旧记忆无缝继承**。
|
|
19
|
+
数据目录复用现有 `~/.memory-tencentdb/memory-tdai`,**旧记忆无缝继承**。
|
|
20
|
+
|
|
21
|
+
`node-llama-cpp` 仅供完全本地的 embedding 后端使用,现在声明为可选 peer,默认安装不会再触发原生构建脚本。使用 OpenAI 兼容远程 embedding 时不需要它;选择本地后端的用户需在目标 DSH profile 中单独安装并批准 `node-llama-cpp` 的构建。
|
|
22
|
+
|
|
23
|
+
已针对 DSH `0.1.0-rc.6`、`0.1.0-rc.7`、`0.1.0-rc.8` 和 `0.1.1-rc.1` 测试。
|
|
20
24
|
|
|
21
25
|
## 架构(移植方式)
|
|
22
26
|
|
|
@@ -70,3 +74,4 @@ tdai-memory:
|
|
|
70
74
|
- **dedup**:LLM 冲突检测输出解析不稳(曾导致 stored=0),默认关闭;开启需换更稳的模型
|
|
71
75
|
- **L1 记忆向量**:随存储写入(8088 embedding 快);L0 向量走后台任务,headless 退出时由 `destroy()` drain
|
|
72
76
|
- **升级**:上游拉新代码后,在 tdai 项目目录重跑 `npx tsc -p dsh-tsconfig.json`(产物在 `dist-dsh/`)
|
|
77
|
+
|
package/client.js
CHANGED
package/index.js
CHANGED
|
@@ -25,7 +25,6 @@ import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-sett
|
|
|
25
25
|
import { TdaiCore } from "./vendor/tdai/core/tdai-core.js";
|
|
26
26
|
import { parseConfig } from "./vendor/tdai/config.js";
|
|
27
27
|
import { StandaloneHostAdapter } from "./vendor/tdai/adapters/standalone/host-adapter.js";
|
|
28
|
-
import { ensureSettingsNamespaceExposed } from "./vendor/dsh-settings-expose.js";
|
|
29
28
|
|
|
30
29
|
/** Cordis plugin name. */
|
|
31
30
|
const name = "tdai-memory";
|
|
@@ -382,12 +381,6 @@ function apply(ctx, config) {
|
|
|
382
381
|
},
|
|
383
382
|
});
|
|
384
383
|
|
|
385
|
-
// dsh-host-apiproxy hard-codes which settings namespaces the Web client may
|
|
386
|
-
// see; without this, the settings section answers `settings-not-exposed`
|
|
387
|
-
// on any stock install. Patch the allowlist idempotently (self-heals after
|
|
388
|
-
// dsh updates overwrite the file).
|
|
389
|
-
ensureSettingsNamespaceExposed(ctx, "tdai-memory", ctx.logger);
|
|
390
|
-
|
|
391
384
|
// Fallback when no settings service ever mounts: build from the entry
|
|
392
385
|
// config. One-shot — if the settings mount arrives later, its build
|
|
393
386
|
// supersedes this one. Delayed past the 0ms window so headless/web boots
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-tdai-memory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "DeepSeek Harness 的 TencentDB Agent Memory 移植:L0 对话捕获 → L1 结构化记忆提取 → L2 场景/L3 画像,自动召回注入 + 记忆/对话搜索工具;复用现有 ~/.memory-tencentdb/memory-tdai 数据;附 Web UI 设置栏。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -61,15 +61,19 @@
|
|
|
61
61
|
"sqlite-vec": "0.1.7-alpha.2",
|
|
62
62
|
"undici": "^8.1.0"
|
|
63
63
|
},
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
70
|
-
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6"
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"react": "^18.2.0",
|
|
66
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || ^0.1.1-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6 || ^0.1.1-rc.1",
|
|
68
|
+
"node-llama-cpp": "^3.19.1"
|
|
71
69
|
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"node-llama-cpp": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
72
75
|
"scripts": {
|
|
73
|
-
"test": "node tests/settings-scope-compat.test.mjs"
|
|
76
|
+
"test": "node tests/settings-scope-compat.test.mjs && node tests/install-contract.test.mjs"
|
|
74
77
|
}
|
|
75
|
-
}
|
|
78
|
+
}
|
|
79
|
+
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-host-apiproxy exposes only namespaces listed in its hard-coded
|
|
3
|
-
* WEB_SETTINGS_NAMESPACES allowlist to the Web settings client. A namespace
|
|
4
|
-
* registered by a third-party plugin answers `settings-not-exposed` even
|
|
5
|
-
* though it is registered — upstream explicitly defers letting plugins
|
|
6
|
-
* expose their own configuration.
|
|
7
|
-
*
|
|
8
|
-
* This module idempotently patches that allowlist in the dsh installation
|
|
9
|
-
* actually loaded by the host process, so the plugin's settings section
|
|
10
|
-
* becomes visible in the Web UI without manual edits. A dsh update
|
|
11
|
-
* overwrites the file; the next plugin start re-patches it.
|
|
12
|
-
*/
|
|
13
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
-
import { createRequire } from "node:module";
|
|
15
|
-
import { dirname, join, sep } from "node:path";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Ensure `nsName` is present in dsh-host-apiproxy's WEB_SETTINGS_NAMESPACES.
|
|
19
|
-
* No-op when already exposed or when the file cannot be located/patched.
|
|
20
|
-
* @param {import("cordis").Context} ctx
|
|
21
|
-
* @param {string} nsName - settings namespace short name (e.g. "tdai-memory").
|
|
22
|
-
* @param {{info?: Function, warn?: Function}} logger - dsh logger.
|
|
23
|
-
*/
|
|
24
|
-
export function ensureSettingsNamespaceExposed(ctx, nsName, logger) {
|
|
25
|
-
void ctx;
|
|
26
|
-
try {
|
|
27
|
-
const target = findApiproxyIndex();
|
|
28
|
-
if (!target) {
|
|
29
|
-
logger?.warn?.(`[settings-expose] could not locate dsh-host-apiproxy; add "${nsName}" to WEB_SETTINGS_NAMESPACES in dsh-host-apiproxy/lib/index.js to get a Web settings section`);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
let src;
|
|
33
|
-
try {
|
|
34
|
-
src = readFileSync(target, "utf8");
|
|
35
|
-
} catch (error) {
|
|
36
|
-
logger?.warn?.(`[settings-expose] cannot read ${target}: ${String(error)}`);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const body = src.match(/const WEB_SETTINGS_NAMESPACES = \[([\s\S]*?)\];/)?.[1] ?? "";
|
|
40
|
-
if (body.includes(`"${nsName}"`)) return; // already exposed (manual or previous patch)
|
|
41
|
-
const patched = src.replace(/(const WEB_SETTINGS_NAMESPACES = \[[\s\S]*?)(\n\s*\];)/, (_, pre, post) => {
|
|
42
|
-
const trailingComma = /,\s*$/.test(pre) ? "" : ",";
|
|
43
|
-
const sep2 = pre.trimEnd().endsWith("[") ? "" : trailingComma;
|
|
44
|
-
return `${pre}${sep2}\n\t"${nsName}"${post}`;
|
|
45
|
-
});
|
|
46
|
-
if (patched === src) {
|
|
47
|
-
logger?.warn?.(`[settings-expose] allowlist pattern not found in ${target}; add "${nsName}" to WEB_SETTINGS_NAMESPACES manually`);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
writeFileSync(target, patched, "utf8");
|
|
51
|
-
logger?.info?.(`[settings-expose] added "${nsName}" to WEB_SETTINGS_NAMESPACES (${target}) — restart dsh web for the settings section to appear`);
|
|
52
|
-
} catch (error) {
|
|
53
|
-
logger?.warn?.(`[settings-expose] failed: ${String(error)}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function findApiproxyIndex() {
|
|
58
|
-
// 1) The host process has already loaded dsh-host-apiproxy: read the real
|
|
59
|
-
// module path from the CommonJS module cache (any install layout).
|
|
60
|
-
try {
|
|
61
|
-
const Module = createRequire(import.meta.url)("module");
|
|
62
|
-
const cache = Module._cache ?? {};
|
|
63
|
-
for (const key of Object.keys(cache)) {
|
|
64
|
-
if (key.includes(`${sep}dsh-host-apiproxy${sep}`) && key.endsWith(`${sep}index.js`)) return key;
|
|
65
|
-
}
|
|
66
|
-
} catch { /* fall through */ }
|
|
67
|
-
// 2) Fallback: sibling of @deepseek-ai/dsh-settings (dsh's nested layout).
|
|
68
|
-
try {
|
|
69
|
-
const require = createRequire(import.meta.url);
|
|
70
|
-
const settingsEntry = require.resolve("@deepseek-ai/dsh-settings");
|
|
71
|
-
const candidate = join(dirname(dirname(dirname(settingsEntry))), "dsh-host-apiproxy", "lib", "index.js");
|
|
72
|
-
if (existsSync(candidate)) return candidate;
|
|
73
|
-
} catch { /* fall through */ }
|
|
74
|
-
return "";
|
|
75
|
-
}
|