memory-eternal 0.16.0 → 0.17.0
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +138 -656
- package/README.zh-CN.md +138 -0
- package/bin/dsh-memory.mjs +33 -3
- package/cursor-extension/package.json +1 -1
- package/dsh-tui-plugin/dsh-plugin.json +1 -1
- package/dsh-tui-plugin/package.json +1 -1
- package/index.js +26 -3
- package/lib/api.js +9 -0
- package/lib/capture-run.js +35 -8
- package/lib/client.js +17 -17
- package/lib/db.js +19 -0
- package/lib/ledger.js +107 -0
- package/lib/mcp.js +8 -2
- package/orca-plugin/orca-plugin.json +1 -1
- package/package.json +145 -145
- package/scripts/release.mjs +5 -4
- package/web/app.js +15 -15
- package/README.en.md +0 -623
package/lib/db.js
CHANGED
|
@@ -221,6 +221,25 @@ function initTables(db) {
|
|
|
221
221
|
created_at TEXT DEFAULT (datetime('now'))
|
|
222
222
|
);
|
|
223
223
|
|
|
224
|
+
-- 记忆账本:召回注入 / 蒸馏调用的开销流水(回答「到底省不省 token」)
|
|
225
|
+
CREATE TABLE IF NOT EXISTS ledger (
|
|
226
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
227
|
+
ts INTEGER NOT NULL,
|
|
228
|
+
kind TEXT NOT NULL,
|
|
229
|
+
session TEXT DEFAULT '',
|
|
230
|
+
results INTEGER DEFAULT 0,
|
|
231
|
+
chars INTEGER DEFAULT 0,
|
|
232
|
+
chars_in INTEGER DEFAULT 0,
|
|
233
|
+
llm_calls INTEGER DEFAULT 0,
|
|
234
|
+
provider TEXT DEFAULT '',
|
|
235
|
+
model TEXT DEFAULT '',
|
|
236
|
+
ms INTEGER DEFAULT 0,
|
|
237
|
+
ok INTEGER DEFAULT 1,
|
|
238
|
+
note TEXT DEFAULT ''
|
|
239
|
+
);
|
|
240
|
+
CREATE INDEX IF NOT EXISTS idx_ledger_ts ON ledger(ts);
|
|
241
|
+
CREATE INDEX IF NOT EXISTS idx_ledger_kind ON ledger(kind);
|
|
242
|
+
|
|
224
243
|
-- 审核日志:记录所有 status 变更,不可篡改
|
|
225
244
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
226
245
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
package/lib/ledger.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// 记忆账本:记录「记忆本身的开销」——召回注入了多少字符、蒸馏调了多少次 LLM。
|
|
2
|
+
//
|
|
3
|
+
// 为什么要有它:README 一直说「省 token」,但省不省取决于「被避免的上下文开销」是否大于
|
|
4
|
+
// 「注入 + 蒸馏调用」的成本。没有账本,所有调参都是猜;有账本后至少能回答「我们花了多少」,
|
|
5
|
+
// 再结合召回有用率(feedback 表)判断净收益方向。
|
|
6
|
+
//
|
|
7
|
+
// 只记账,不参与主流程:任何异常都吞掉,绝不能让统计把沉淀/召回弄失败。
|
|
8
|
+
|
|
9
|
+
import { getDb } from './db.js'
|
|
10
|
+
|
|
11
|
+
const DAY_MS = 86400000
|
|
12
|
+
|
|
13
|
+
/** 记一条流水。失败静默返回 false。 */
|
|
14
|
+
export function recordLedger(root, entry = {}) {
|
|
15
|
+
try {
|
|
16
|
+
const db = getDb(root)
|
|
17
|
+
db.prepare(`
|
|
18
|
+
INSERT INTO ledger (ts, kind, session, results, chars, chars_in, llm_calls, provider, model, ms, ok, note)
|
|
19
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
20
|
+
`).run(
|
|
21
|
+
Number(entry.ts) || Date.now(),
|
|
22
|
+
String(entry.kind || 'other').slice(0, 20),
|
|
23
|
+
String(entry.session || '').slice(0, 80),
|
|
24
|
+
Math.max(0, Number(entry.results) || 0),
|
|
25
|
+
Math.max(0, Number(entry.chars) || 0),
|
|
26
|
+
Math.max(0, Number(entry.charsIn) || 0),
|
|
27
|
+
Math.max(0, Number(entry.llmCalls) || 0),
|
|
28
|
+
String(entry.provider || '').slice(0, 60),
|
|
29
|
+
String(entry.model || '').slice(0, 80),
|
|
30
|
+
Math.max(0, Number(entry.ms) || 0),
|
|
31
|
+
entry.ok === false ? 0 : 1,
|
|
32
|
+
String(entry.note || '').slice(0, 200),
|
|
33
|
+
)
|
|
34
|
+
return true
|
|
35
|
+
} catch { return false }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const localDay = (ts) => {
|
|
39
|
+
const d = new Date(Number(ts) || 0)
|
|
40
|
+
const p = (n) => String(n).padStart(2, '0')
|
|
41
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 近 N 天汇总(默认 7 天,最多 90 天)。
|
|
46
|
+
* - totals:召回次数/注入字符、沉淀次数/LLM 调用/输入输出字符、粗估 token
|
|
47
|
+
* - byDay:逐日明细(used by 面板画趋势)
|
|
48
|
+
* - feedback:召回有用率(feedback 表,只有 agent 显式标记才有数据)
|
|
49
|
+
*/
|
|
50
|
+
export function ledgerSummary(root, { days = 7, now = Date.now() } = {}) {
|
|
51
|
+
const db = getDb(root)
|
|
52
|
+
const n = Math.min(Math.max(Math.floor(Number(days) || 7), 1), 90)
|
|
53
|
+
const cutoff = Number(now) - n * DAY_MS
|
|
54
|
+
const rows = db.prepare('SELECT * FROM ledger WHERE ts >= ? ORDER BY ts').all(cutoff)
|
|
55
|
+
const recalls = rows.filter((r) => r.kind === 'recall')
|
|
56
|
+
const captures = rows.filter((r) => r.kind === 'capture')
|
|
57
|
+
const sum = (arr, k) => arr.reduce((s, r) => s + (Number(r[k]) || 0), 0)
|
|
58
|
+
|
|
59
|
+
const byDay = []
|
|
60
|
+
const index = new Map()
|
|
61
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
62
|
+
const key = localDay(Number(now) - i * DAY_MS)
|
|
63
|
+
const row = { date: key, recalls: 0, injectedChars: 0, captures: 0, llmCalls: 0, captureInChars: 0, captureOutChars: 0 }
|
|
64
|
+
index.set(key, row)
|
|
65
|
+
byDay.push(row)
|
|
66
|
+
}
|
|
67
|
+
for (const r of rows) {
|
|
68
|
+
const row = index.get(localDay(r.ts))
|
|
69
|
+
if (!row) continue
|
|
70
|
+
if (r.kind === 'recall') { row.recalls += 1; row.injectedChars += Number(r.chars) || 0 }
|
|
71
|
+
if (r.kind === 'capture') { row.captures += 1; row.llmCalls += Number(r.llm_calls) || 0; row.captureInChars += Number(r.chars_in) || 0; row.captureOutChars += Number(r.chars) || 0 }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 召回有用率:只有调用方显式回传 useful 时才有数据;没有数据时 rate = null(不要假装 0%)
|
|
75
|
+
let useful = 0
|
|
76
|
+
let useless = 0
|
|
77
|
+
try {
|
|
78
|
+
const fb = db.prepare("SELECT useful, COUNT(*) AS n FROM feedback WHERE created_at >= datetime('now', ?) GROUP BY useful").all(`-${n} days`)
|
|
79
|
+
for (const r of fb) { if (Number(r.useful) === 1) useful = Number(r.n) || 0; else useless = Number(r.n) || 0 }
|
|
80
|
+
} catch { /* feedback 表缺失也不影响账本 */ }
|
|
81
|
+
|
|
82
|
+
const injectedChars = sum(recalls, 'chars')
|
|
83
|
+
const captureInChars = sum(captures, 'chars_in')
|
|
84
|
+
const captureOutChars = sum(captures, 'chars')
|
|
85
|
+
// 粗估 token:中英混排约 2 字符 ≈ 1 token(保守口径,只用于看量级,不做计费)
|
|
86
|
+
const estTokens = Math.round((injectedChars + captureInChars + captureOutChars) / 2)
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
days: n,
|
|
91
|
+
since: cutoff,
|
|
92
|
+
totals: {
|
|
93
|
+
recalls: recalls.length,
|
|
94
|
+
recallResults: sum(recalls, 'results'),
|
|
95
|
+
injectedChars,
|
|
96
|
+
captures: captures.length,
|
|
97
|
+
captureOk: captures.filter((r) => Number(r.ok) === 1).length,
|
|
98
|
+
captureFail: captures.filter((r) => Number(r.ok) !== 1).length,
|
|
99
|
+
llmCalls: sum(captures, 'llm_calls'),
|
|
100
|
+
captureInChars,
|
|
101
|
+
captureOutChars,
|
|
102
|
+
estTokens,
|
|
103
|
+
},
|
|
104
|
+
byDay,
|
|
105
|
+
feedback: { useful, useless, total: useful + useless, rate: useful + useless ? useful / (useful + useless) : null },
|
|
106
|
+
}
|
|
107
|
+
}
|
package/lib/mcp.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import readline from 'node:readline'
|
|
17
17
|
import { search, overview, stats, ensureVault, listCards, countCards } from './vault.js'
|
|
18
18
|
import { runStandaloneCapture, defaultVaultDir } from './capture-run.js'
|
|
19
|
+
import { recordLedger } from './ledger.js'
|
|
19
20
|
|
|
20
21
|
const SUPPORTED_PROTOCOL_VERSIONS = ['2025-06-18', '2025-03-26', '2024-11-05']
|
|
21
22
|
const DEFAULT_PROTOCOL_VERSION = '2024-11-05'
|
|
@@ -83,13 +84,18 @@ export async function callTool(name, args, vaultRoot, meta = {}) {
|
|
|
83
84
|
if (!query) return toolResult('(未提供检索词)')
|
|
84
85
|
const limit = Math.min(Math.max(Number(args?.limit) || 5, 1), 20)
|
|
85
86
|
const hits = await search(vaultRoot, query, { limit, minScore: 2 })
|
|
86
|
-
if (hits.length === 0)
|
|
87
|
+
if (hits.length === 0) {
|
|
88
|
+
recordLedger(vaultRoot, { kind: 'recall', results: 0, chars: 0, note: query.slice(0, 120) })
|
|
89
|
+
return toolResult(`记忆库中没有与「${query}」相关的内容。`)
|
|
90
|
+
}
|
|
87
91
|
const lines = hits.map((h, i) => {
|
|
88
92
|
const tags = h.tags.length ? ` [${h.tags.join(', ')}]` : ''
|
|
89
93
|
const snippet = String(h.summary || '').replace(/\s+/g, ' ').trim().slice(0, 130)
|
|
90
94
|
return `### ${i + 1}. ${h.title}${tags}\n路径:${h.path}\n${snippet}`
|
|
91
95
|
})
|
|
92
|
-
|
|
96
|
+
const out = `从记忆核心检索到 ${hits.length} 条相关卡片:\n\n${lines.join('\n\n')}`
|
|
97
|
+
recordLedger(vaultRoot, { kind: 'recall', results: hits.length, chars: out.length, note: query.slice(0, 120) })
|
|
98
|
+
return toolResult(out)
|
|
93
99
|
}
|
|
94
100
|
case 'memory_capture': {
|
|
95
101
|
const text = String(args?.text || '')
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"id": "memory-eternal",
|
|
4
4
|
"publisher": "eternalnight996",
|
|
5
5
|
"name": "memory-eternal",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.17.0",
|
|
7
7
|
"description": "Memory Atlas for Orca: open the local memory vault, pending review and knowledge graph from a sandboxed Orca panel.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "EternalNight996",
|
package/package.json
CHANGED
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "memory-eternal",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "记忆核心(Memory Eternal):自研的 DeepSeek Harness 记忆插件,不移植任何既有记忆框架——对话结束后自动沉淀知识卡到本地 Markdown Vault(自研去重、自研 CJK 检索、可 git 管理),设置页提供图形化知识库(统计 / 搜索 / 知识图谱 + 侧边栏一键弹窗),Agent 通过 memory_recall 工具按需召回历史上下文。零人工干预。",
|
|
5
|
-
"icon": "assets/icon.png",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/EternalNight996/memory-eternal.git"
|
|
10
|
-
},
|
|
11
|
-
"homepage": "https://github.com/EternalNight996/memory-eternal",
|
|
12
|
-
"author": "EternalNight996",
|
|
13
|
-
"publishConfig": {
|
|
14
|
-
"registry": "https://registry.npmjs.org/"
|
|
15
|
-
},
|
|
16
|
-
"type": "module",
|
|
17
|
-
"main": "index.js",
|
|
18
|
-
"bin": {
|
|
19
|
-
"dsh-memory": "bin/dsh-memory.mjs"
|
|
20
|
-
},
|
|
21
|
-
"exports": {
|
|
22
|
-
".": "./index.js",
|
|
23
|
-
"./client": "./lib/client.js",
|
|
24
|
-
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
25
|
-
"./package.json": "./package.json"
|
|
26
|
-
},
|
|
27
|
-
"files": [
|
|
28
|
-
"index.js",
|
|
29
|
-
"lib",
|
|
30
|
-
"bin",
|
|
31
|
-
"scripts",
|
|
32
|
-
"examples",
|
|
33
|
-
"web",
|
|
34
|
-
"hooks",
|
|
35
|
-
"skills",
|
|
36
|
-
"assets/icon.png",
|
|
37
|
-
"orca-plugin",
|
|
38
|
-
"dsh-tui-plugin",
|
|
39
|
-
"cursor-extension",
|
|
40
|
-
".claude-plugin",
|
|
41
|
-
".codex-plugin",
|
|
42
|
-
".cursor-plugin",
|
|
43
|
-
".mcp.json",
|
|
44
|
-
"cordis.patch.yml",
|
|
45
|
-
"README.md",
|
|
46
|
-
"README.
|
|
47
|
-
"LICENSE"
|
|
48
|
-
],
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=22",
|
|
51
|
-
"dsh": ">=0.1.5-alpha.2 <0.3.0-0"
|
|
52
|
-
},
|
|
53
|
-
"keywords": [
|
|
54
|
-
"deepseek-harness",
|
|
55
|
-
"dsh",
|
|
56
|
-
"dsh-plugin",
|
|
57
|
-
"plugin",
|
|
58
|
-
"memory",
|
|
59
|
-
"knowledge-base",
|
|
60
|
-
"vault",
|
|
61
|
-
"markdown",
|
|
62
|
-
"knowledge-graph",
|
|
63
|
-
"rag",
|
|
64
|
-
"second-brain"
|
|
65
|
-
],
|
|
66
|
-
"scripts": {
|
|
67
|
-
"build": "node build.mjs",
|
|
68
|
-
"build:client": "node build.mjs",
|
|
69
|
-
"prepublishOnly": "node build.mjs",
|
|
70
|
-
"release": "node scripts/release.mjs",
|
|
71
|
-
"release:dry": "node scripts/release.mjs --dry-run",
|
|
72
|
-
"panel-check": "node scripts/panel-check.mjs",
|
|
73
|
-
"test": "node build.mjs && node tests/vault.test.mjs && node tests/capture.test.mjs && node tests/capture-route.test.mjs && node tests/stall.test.mjs && node tests/vault-path.test.mjs && node tests/vault-resolve.test.mjs && node tests/minhash.test.mjs && node tests/settings-save.test.mjs && node tests/config-coverage.test.mjs && node tests/config-sync.test.mjs && node tests/config-merge.test.mjs && node tests/sse.test.mjs && node tests/api.test.mjs && node tests/import-roundtrip.test.mjs && node tests/graph-perf.test.mjs && node tests/settings-compat.test.mjs && node tests/node-bin.test.mjs && node tests/watchdog-lock.test.mjs && node tests/markdown.test.mjs && node tests/feedback.test.mjs && node tests/graph-lod.test.mjs && node tests/graph-warmup.test.mjs && node tests/loading-hints.test.mjs && node tests/web-entry.test.mjs && node tests/tui-scroll.test.mjs && node tests/tui-audit-scene.test.mjs && node tests/tui-plugin-boot.test.mjs && node tests/capture-session-id.test.mjs && node tests/ssr.test.mjs && node tests/window-controls.test.mjs && node tests/web-assets.test.mjs && node tests/manifests.test.mjs && node tests/two-store.test.mjs && node tests/noise-gate.test.mjs && node tests/e2e-recall.test.mjs && node tests/issue-fixes.test.mjs && node tests/issue-fixes-2.test.mjs && node tests/issue-fixes-3.test.mjs && node tests/watchdog-orphans.test.mjs && node tests/watchdog-restart.test.mjs && node tests/readme-i18n.test.mjs && node tests/issue-fixes-4.test.mjs && node tests/host-drain.test.mjs && node tests/e2e-host-drain.mjs && node tests/issue-fixes-5.test.mjs && node tests/issue-fixes-6.test.mjs && node tests/capture-json-repair.test.mjs && node tests/csrf-origin.test.mjs && node tests/watchdog-orphan-web.test.mjs && node tests/config-validate.test.mjs && node tests/issue-fixes-8.test.mjs && node tests/issue-fixes-9.test.mjs && node tests/release-verify.test.mjs && node tests/refine.test.mjs && node tests/db-restore.test.mjs && node tests/align.test.mjs && node tests/tags-normalize.test.mjs && node tests/resident-state.test.mjs && node tests/llm-route.test.mjs && node tests/host-managed.test.mjs && node tests/replace-claim.test.mjs && node tests/version-check-self.test.mjs && node tests/setup-codex.test.mjs && node tests/listener-netstat.test.mjs && node tests/issue-46-overlay.test.mjs && node tests/graph-initial-zoom.test.mjs && node tests/card-head-actions.test.mjs && node tests/card-reader-ux.test.mjs && node tests/tag-filter.test.mjs && node tests/ui-overflow.test.mjs && node tests/version-card-state.test.mjs && node tests/llm-routes-proxy.test.mjs && node tests/model-strikes.test.mjs && node tests/support-bundle.test.mjs && node tests/health-panel.test.mjs && node tests/issue-48-timeout.test.mjs"
|
|
74
|
-
},
|
|
75
|
-
"dependencies": {
|
|
76
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
77
|
-
},
|
|
78
|
-
"peerDependencies": {
|
|
79
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
80
|
-
"@deepseek-ai/dsh-llm": ">=0.1.0-rc.2 <0.3.0-0",
|
|
81
|
-
"@deepseek-ai/dsh-tools": ">=0.1.0-rc.2 <0.3.0-0"
|
|
82
|
-
},
|
|
83
|
-
"devDependencies": {
|
|
84
|
-
"@types/react": "^18.3.1",
|
|
85
|
-
"esbuild": "^0.24.0",
|
|
86
|
-
"react": "18.3.1",
|
|
87
|
-
"react-dom": "18.3.1"
|
|
88
|
-
},
|
|
89
|
-
"dsh": {
|
|
90
|
-
"client": {
|
|
91
|
-
"platform": "web",
|
|
92
|
-
"inject": [
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-settings",
|
|
94
|
-
"@deepseek-ai/dsh-client-locale"
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
"bundle": {
|
|
98
|
-
"patch": "./cordis.patch.yml"
|
|
99
|
-
},
|
|
100
|
-
"marketplace": {
|
|
101
|
-
"profiles": [
|
|
102
|
-
"web",
|
|
103
|
-
"desktop"
|
|
104
|
-
],
|
|
105
|
-
"requiresBuildApproval": false,
|
|
106
|
-
"requiresRestart": true,
|
|
107
|
-
"manualSteps": false
|
|
108
|
-
},
|
|
109
|
-
"permissions": {
|
|
110
|
-
"level": "medium",
|
|
111
|
-
"files": "read-write",
|
|
112
|
-
"network": "none",
|
|
113
|
-
"commands": "node",
|
|
114
|
-
"credentials": [],
|
|
115
|
-
"externalServices": [],
|
|
116
|
-
"notes": "Read/write under ~/.dsh/memory-vault only (plugin-private Markdown vault). No outbound network, no credentials, no shell. Hooks/MCP run via the `node` binary that hosts the DSH process."
|
|
117
|
-
},
|
|
118
|
-
"lifecycle": {
|
|
119
|
-
"scripts": [
|
|
120
|
-
"prepare",
|
|
121
|
-
"prepublishOnly"
|
|
122
|
-
],
|
|
123
|
-
"details": {
|
|
124
|
-
"prepare": "node build.mjs",
|
|
125
|
-
"prepublishOnly": "node build.mjs"
|
|
126
|
-
},
|
|
127
|
-
"notes": "Only `prepare` and `prepublishOnly` run `node build.mjs` (esbuild client bundling). No preinstall/install/postinstall hooks, no remote downloads, no native builds."
|
|
128
|
-
},
|
|
129
|
-
"compatibility": {
|
|
130
|
-
"dsh": ">=0.1.5-alpha.2 <0.3.0-0",
|
|
131
|
-
"dshReleases": {
|
|
132
|
-
"0.1.5-alpha.2": "compatible",
|
|
133
|
-
"0.1.5-rc.1": "compatible",
|
|
134
|
-
"0.1.5-rc.2": "compatible",
|
|
135
|
-
"0.1.7-rc.2": "compatible",
|
|
136
|
-
"0.2.0-rc.2": "compatible"
|
|
137
|
-
},
|
|
138
|
-
"node": ">=22",
|
|
139
|
-
"profiles": [
|
|
140
|
-
"web",
|
|
141
|
-
"desktop"
|
|
142
|
-
]
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "memory-eternal",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"description": "记忆核心(Memory Eternal):自研的 DeepSeek Harness 记忆插件,不移植任何既有记忆框架——对话结束后自动沉淀知识卡到本地 Markdown Vault(自研去重、自研 CJK 检索、可 git 管理),设置页提供图形化知识库(统计 / 搜索 / 知识图谱 + 侧边栏一键弹窗),Agent 通过 memory_recall 工具按需召回历史上下文。零人工干预。",
|
|
5
|
+
"icon": "assets/icon.png",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/EternalNight996/memory-eternal.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/EternalNight996/memory-eternal",
|
|
12
|
+
"author": "EternalNight996",
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"registry": "https://registry.npmjs.org/"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "index.js",
|
|
18
|
+
"bin": {
|
|
19
|
+
"dsh-memory": "bin/dsh-memory.mjs"
|
|
20
|
+
},
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./index.js",
|
|
23
|
+
"./client": "./lib/client.js",
|
|
24
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"index.js",
|
|
29
|
+
"lib",
|
|
30
|
+
"bin",
|
|
31
|
+
"scripts",
|
|
32
|
+
"examples",
|
|
33
|
+
"web",
|
|
34
|
+
"hooks",
|
|
35
|
+
"skills",
|
|
36
|
+
"assets/icon.png",
|
|
37
|
+
"orca-plugin",
|
|
38
|
+
"dsh-tui-plugin",
|
|
39
|
+
"cursor-extension",
|
|
40
|
+
".claude-plugin",
|
|
41
|
+
".codex-plugin",
|
|
42
|
+
".cursor-plugin",
|
|
43
|
+
".mcp.json",
|
|
44
|
+
"cordis.patch.yml",
|
|
45
|
+
"README.md",
|
|
46
|
+
"README.zh-CN.md",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22",
|
|
51
|
+
"dsh": ">=0.1.5-alpha.2 <0.3.0-0"
|
|
52
|
+
},
|
|
53
|
+
"keywords": [
|
|
54
|
+
"deepseek-harness",
|
|
55
|
+
"dsh",
|
|
56
|
+
"dsh-plugin",
|
|
57
|
+
"plugin",
|
|
58
|
+
"memory",
|
|
59
|
+
"knowledge-base",
|
|
60
|
+
"vault",
|
|
61
|
+
"markdown",
|
|
62
|
+
"knowledge-graph",
|
|
63
|
+
"rag",
|
|
64
|
+
"second-brain"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "node build.mjs",
|
|
68
|
+
"build:client": "node build.mjs",
|
|
69
|
+
"prepublishOnly": "node build.mjs",
|
|
70
|
+
"release": "node scripts/release.mjs",
|
|
71
|
+
"release:dry": "node scripts/release.mjs --dry-run",
|
|
72
|
+
"panel-check": "node scripts/panel-check.mjs",
|
|
73
|
+
"test": "node build.mjs && node tests/vault.test.mjs && node tests/capture.test.mjs && node tests/capture-route.test.mjs && node tests/stall.test.mjs && node tests/vault-path.test.mjs && node tests/vault-resolve.test.mjs && node tests/minhash.test.mjs && node tests/settings-save.test.mjs && node tests/config-coverage.test.mjs && node tests/config-sync.test.mjs && node tests/config-merge.test.mjs && node tests/sse.test.mjs && node tests/api.test.mjs && node tests/import-roundtrip.test.mjs && node tests/graph-perf.test.mjs && node tests/settings-compat.test.mjs && node tests/node-bin.test.mjs && node tests/watchdog-lock.test.mjs && node tests/markdown.test.mjs && node tests/feedback.test.mjs && node tests/graph-lod.test.mjs && node tests/graph-warmup.test.mjs && node tests/loading-hints.test.mjs && node tests/web-entry.test.mjs && node tests/tui-scroll.test.mjs && node tests/tui-audit-scene.test.mjs && node tests/tui-plugin-boot.test.mjs && node tests/capture-session-id.test.mjs && node tests/ssr.test.mjs && node tests/window-controls.test.mjs && node tests/web-assets.test.mjs && node tests/manifests.test.mjs && node tests/two-store.test.mjs && node tests/noise-gate.test.mjs && node tests/e2e-recall.test.mjs && node tests/issue-fixes.test.mjs && node tests/issue-fixes-2.test.mjs && node tests/issue-fixes-3.test.mjs && node tests/watchdog-orphans.test.mjs && node tests/watchdog-restart.test.mjs && node tests/readme-i18n.test.mjs && node tests/issue-fixes-4.test.mjs && node tests/host-drain.test.mjs && node tests/e2e-host-drain.mjs && node tests/issue-fixes-5.test.mjs && node tests/issue-fixes-6.test.mjs && node tests/capture-json-repair.test.mjs && node tests/csrf-origin.test.mjs && node tests/watchdog-orphan-web.test.mjs && node tests/config-validate.test.mjs && node tests/issue-fixes-8.test.mjs && node tests/issue-fixes-9.test.mjs && node tests/release-verify.test.mjs && node tests/refine.test.mjs && node tests/db-restore.test.mjs && node tests/align.test.mjs && node tests/tags-normalize.test.mjs && node tests/resident-state.test.mjs && node tests/llm-route.test.mjs && node tests/host-managed.test.mjs && node tests/replace-claim.test.mjs && node tests/version-check-self.test.mjs && node tests/setup-codex.test.mjs && node tests/listener-netstat.test.mjs && node tests/issue-46-overlay.test.mjs && node tests/graph-initial-zoom.test.mjs && node tests/card-head-actions.test.mjs && node tests/card-reader-ux.test.mjs && node tests/tag-filter.test.mjs && node tests/ui-overflow.test.mjs && node tests/version-card-state.test.mjs && node tests/llm-routes-proxy.test.mjs && node tests/model-strikes.test.mjs && node tests/support-bundle.test.mjs && node tests/health-panel.test.mjs && node tests/issue-48-timeout.test.mjs && node tests/ledger.test.mjs"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
77
|
+
},
|
|
78
|
+
"peerDependencies": {
|
|
79
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
80
|
+
"@deepseek-ai/dsh-llm": ">=0.1.0-rc.2 <0.3.0-0",
|
|
81
|
+
"@deepseek-ai/dsh-tools": ">=0.1.0-rc.2 <0.3.0-0"
|
|
82
|
+
},
|
|
83
|
+
"devDependencies": {
|
|
84
|
+
"@types/react": "^18.3.1",
|
|
85
|
+
"esbuild": "^0.24.0",
|
|
86
|
+
"react": "18.3.1",
|
|
87
|
+
"react-dom": "18.3.1"
|
|
88
|
+
},
|
|
89
|
+
"dsh": {
|
|
90
|
+
"client": {
|
|
91
|
+
"platform": "web",
|
|
92
|
+
"inject": [
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
94
|
+
"@deepseek-ai/dsh-client-locale"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"bundle": {
|
|
98
|
+
"patch": "./cordis.patch.yml"
|
|
99
|
+
},
|
|
100
|
+
"marketplace": {
|
|
101
|
+
"profiles": [
|
|
102
|
+
"web",
|
|
103
|
+
"desktop"
|
|
104
|
+
],
|
|
105
|
+
"requiresBuildApproval": false,
|
|
106
|
+
"requiresRestart": true,
|
|
107
|
+
"manualSteps": false
|
|
108
|
+
},
|
|
109
|
+
"permissions": {
|
|
110
|
+
"level": "medium",
|
|
111
|
+
"files": "read-write",
|
|
112
|
+
"network": "none",
|
|
113
|
+
"commands": "node",
|
|
114
|
+
"credentials": [],
|
|
115
|
+
"externalServices": [],
|
|
116
|
+
"notes": "Read/write under ~/.dsh/memory-vault only (plugin-private Markdown vault). No outbound network, no credentials, no shell. Hooks/MCP run via the `node` binary that hosts the DSH process."
|
|
117
|
+
},
|
|
118
|
+
"lifecycle": {
|
|
119
|
+
"scripts": [
|
|
120
|
+
"prepare",
|
|
121
|
+
"prepublishOnly"
|
|
122
|
+
],
|
|
123
|
+
"details": {
|
|
124
|
+
"prepare": "node build.mjs",
|
|
125
|
+
"prepublishOnly": "node build.mjs"
|
|
126
|
+
},
|
|
127
|
+
"notes": "Only `prepare` and `prepublishOnly` run `node build.mjs` (esbuild client bundling). No preinstall/install/postinstall hooks, no remote downloads, no native builds."
|
|
128
|
+
},
|
|
129
|
+
"compatibility": {
|
|
130
|
+
"dsh": ">=0.1.5-alpha.2 <0.3.0-0",
|
|
131
|
+
"dshReleases": {
|
|
132
|
+
"0.1.5-alpha.2": "compatible",
|
|
133
|
+
"0.1.5-rc.1": "compatible",
|
|
134
|
+
"0.1.5-rc.2": "compatible",
|
|
135
|
+
"0.1.7-rc.2": "compatible",
|
|
136
|
+
"0.2.0-rc.2": "compatible"
|
|
137
|
+
},
|
|
138
|
+
"node": ">=22",
|
|
139
|
+
"profiles": [
|
|
140
|
+
"web",
|
|
141
|
+
"desktop"
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
package/scripts/release.mjs
CHANGED
|
@@ -132,15 +132,16 @@ let notes = ''
|
|
|
132
132
|
if (notesFile) {
|
|
133
133
|
notes = fs.readFileSync(path.resolve(ROOT, notesFile), 'utf8')
|
|
134
134
|
} else {
|
|
135
|
-
// 从
|
|
136
|
-
const
|
|
137
|
-
const
|
|
135
|
+
// 从 docs/CHANGELOG.md 取该版本那一行(| **v0.10.0** | 日期 | 说明 |);README 精简为落地页后兼容旧位置
|
|
136
|
+
const logFile = ['docs/CHANGELOG.md', 'README.md'].map((f) => path.join(ROOT, f)).find((f) => fs.existsSync(f))
|
|
137
|
+
const logText = logFile ? fs.readFileSync(logFile, 'utf8') : ''
|
|
138
|
+
const row = logText.split(/\r?\n/).find((l) => l.startsWith(`| **${tag}**`))
|
|
138
139
|
notes = [
|
|
139
140
|
`## ${tag}`,
|
|
140
141
|
'',
|
|
141
142
|
`npm: https://www.npmjs.com/package/memory-eternal/v/${pkg.version}`,
|
|
142
143
|
'',
|
|
143
|
-
row ? row.replace(/^\|\s*/, '').replace(/\s*\|\s*$/, '').split(/\s*\|\s*/).slice(1).join(' — ') : '(
|
|
144
|
+
row ? row.replace(/^\|\s*/, '').replace(/\s*\|\s*$/, '').split(/\s*\|\s*/).slice(1).join(' — ') : '(CHANGELOG 里没有这一版,请用 --notes-file 指定)',
|
|
144
145
|
].join('\n')
|
|
145
146
|
}
|
|
146
147
|
say(notes.split('\n').slice(0, 6).join('\n') + (notes.split('\n').length > 6 ? '\n…' : ''))
|