cogmem 3.6.2 → 3.6.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/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +2 -2
- package/README.md +21 -6
- package/RELEASE_CHECKLIST.md +6 -4
- package/dist/bin/migrate.js +4 -2
- package/dist/bin/openclaw.js +53 -2
- package/dist/bin/update.js +79 -22
- package/dist/factory.js +1 -1
- package/dist/host/openclaw/AutoMemoryPluginInstaller.js +31 -7
- package/dist/migrations/SchemaMigrationRunner.d.ts +9 -1
- package/dist/migrations/SchemaMigrationRunner.js +47 -6
- package/examples/hermes-backend/README.md +9 -1
- package/examples/hermes-backend/SKILL.md +9 -1
- package/examples/hermes-backend/references/operations.md +11 -3
- package/examples/openclaw-backend/README.md +10 -2
- package/examples/openclaw-backend/SKILL.md +12 -2
- package/examples/openclaw-backend/references/operations.md +15 -6
- package/install.sh +6 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.6.3
|
|
4
|
+
|
|
5
|
+
- Added a GitHub Release `published` workflow for npm Trusted Publishing with OIDC provenance, full tests, build, version-tag validation, and package dry-run verification before `npm publish`.
|
|
6
|
+
- Fixed `cogmem migrate --dry-run` so it opens SQLite read-only and plans legacy `_meta.schema_version` adoption without creating `_schema_migrations` or writing migration rows.
|
|
7
|
+
- Hardened `cogmem update` target resolution for npm global installs, one-line installer homes, local project dependencies, and source checkouts so `cogmem update --yes` does not silently install into an arbitrary current directory.
|
|
8
|
+
- Updated OpenClaw diagnostics and generated bridge behavior to propagate `rememberDrainTimeoutMs`, recover stale `.processing` queue files, and report pending/dead/lock/processing queue state.
|
|
9
|
+
|
|
3
10
|
## 3.6.2
|
|
4
11
|
|
|
5
12
|
- Switched the public distribution channel to the npm registry while keeping GitHub as the source and review mirror.
|
package/CONTRIBUTING.md
CHANGED
|
@@ -18,10 +18,10 @@ bun run typecheck
|
|
|
18
18
|
bun test
|
|
19
19
|
npm pack --dry-run --json
|
|
20
20
|
npm publish --dry-run --access public
|
|
21
|
-
npm publish --access public
|
|
21
|
+
npm publish --provenance --access public
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
`cogmem` is distributed through the npm registry. Use `npm pack --dry-run --json` to verify package contents
|
|
24
|
+
`cogmem` is distributed through the npm registry. Use `npm pack --dry-run --json` to verify package contents. Normal publishing happens by creating a GitHub Release from the matching version tag; `.github/workflows/publish.yml` is intentionally triggered by the release `published` event, not by tag pushes. Use `npm publish --provenance --access public` only as an emergency manual fallback.
|
|
25
25
|
|
|
26
26
|
## API Discipline
|
|
27
27
|
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ It is not a knowledge-base app, a note-taking app, a vector RAG wrapper, an Obsi
|
|
|
11
11
|
|
|
12
12
|
## Status
|
|
13
13
|
|
|
14
|
-
Current version: `3.6.
|
|
14
|
+
Current version: `3.6.3`
|
|
15
15
|
|
|
16
16
|
Distribution: npm registry. GitHub remains the source mirror and hosts this installer, but package install and upgrade resolve `cogmem` from npm by default.
|
|
17
17
|
|
|
@@ -178,6 +178,13 @@ npm install cogmem@latest
|
|
|
178
178
|
./node_modules/.bin/cogmem init
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
Or install globally with npm when Bun is already on PATH:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
npm install -g cogmem@latest
|
|
185
|
+
cogmem init
|
|
186
|
+
```
|
|
187
|
+
|
|
181
188
|
Validate configuration:
|
|
182
189
|
|
|
183
190
|
```bash
|
|
@@ -190,7 +197,7 @@ Upgrade from npm and migrate an existing database:
|
|
|
190
197
|
cogmem update --yes
|
|
191
198
|
```
|
|
192
199
|
|
|
193
|
-
`cogmem update --yes` installs `cogmem@latest` from npm, then runs the newly installed `cogmem migrate --yes --backup --config <resolved-config>`. If OpenClaw is configured, the updater also runs the newly installed plugin-only repair command so stale `index.js` and `bridge.mjs` files are refreshed before you restart the agent. To inspect changes without writing:
|
|
200
|
+
`cogmem update --yes` installs `cogmem@latest` from npm, then runs the newly installed `cogmem migrate --yes --backup --config <resolved-config>`. It updates npm-global installs with `npm install -g`, the one-line installer home under `~/.cogmem/pkg`, or the current workspace dependency when Cogmem is a project dependency. If OpenClaw is configured, the updater also runs the newly installed plugin-only repair command so stale `index.js` and `bridge.mjs` files are refreshed before you restart the agent. To inspect changes without writing:
|
|
194
201
|
|
|
195
202
|
```bash
|
|
196
203
|
cogmem update --dry-run --json
|
|
@@ -199,7 +206,7 @@ cogmem migrate --dry-run --json
|
|
|
199
206
|
|
|
200
207
|
For a manual migration, run `cogmem migrate --yes --backup`. The migration runner adopts the existing `_meta.schema_version`, applies only later idempotent migrations, preserves Raw Ledger rows, and creates a timestamped, transaction-consistent standalone database backup before changing an on-disk database. The backup includes committed SQLite WAL pages instead of copying only the main database file.
|
|
201
208
|
|
|
202
|
-
Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.
|
|
209
|
+
Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.3 schema set with one command:
|
|
203
210
|
|
|
204
211
|
```bash
|
|
205
212
|
cogmem migrate --yes --backup --json
|
|
@@ -241,7 +248,7 @@ For a host timer, call `dream tick`; the timer only wakes the scheduler. An empt
|
|
|
241
248
|
cogmem dream tick --project my-agent --mode auto --max-episodes 10 --json
|
|
242
249
|
```
|
|
243
250
|
|
|
244
|
-
Raw events are always written first. `KernelAgentMemoryBackend` and OpenClaw plugin 0.6.
|
|
251
|
+
Raw events are always written first. `KernelAgentMemoryBackend` and OpenClaw plugin 0.6.3 assemble live turns automatically. The foreground hook uses deterministic rules and previous assistant/user context; background import and repair paths may use the advisory hybrid classifier. Advisory output is allow-listed and cannot directly mutate durable memory. Unknown turns now fail closed as ambiguous. Continuation requires explicit continuation language or project/topic/entity/semantic overlap; Cogmem does not route domains with an expanding hard-coded keyword dictionary.
|
|
245
252
|
|
|
246
253
|
Hookless MCP agents can call `cogmem_episode_append` or bounded `cogmem_episode_import`. Existing OpenClaw/Hermes import commands use stable content identities and the same episode schema. Low-confidence imported groups soft-seal for review unless an operator explicitly forces sealing. Episode semantic summaries and closure receipts are control hints, never durable evidence; every Dream candidate must cite a non-empty subset of the episode's raw event IDs and still pass CPU governance.
|
|
247
254
|
|
|
@@ -337,7 +344,7 @@ cogmem strategy plan --project hermes --query "我当时的原话是什么?" -
|
|
|
337
344
|
cogmem strategy outcomes --project hermes --json
|
|
338
345
|
```
|
|
339
346
|
|
|
340
|
-
OpenClaw plugin 0.6.
|
|
347
|
+
OpenClaw plugin 0.6.3 skips Cogmem entirely for greetings, uses only session state/turn bridge for short continuations, and applies Strategy Cortex before full recall. Navigation turns use one bridge/kernel lifecycle for Atlas exploration, evidence-bearing node/timeline drill-down, and recall. The bounded volatile `<COGMEM_MEMORY_ATLAS>` block includes evidence event IDs and drill-down commands; OpenClaw does not need MCP for this path.
|
|
341
348
|
|
|
342
349
|
`ProspectiveMemoryService` stores future intentions, commitments, reminders, open loops, and plans as candidates only. A candidate is not actionable until an explicit user event confirms it. Rejected candidates stay suppressed unless genuinely new evidence creates a new version. The service and `cogmem prospective` CLI manage state only; they expose no task or tool execution capability.
|
|
343
350
|
|
|
@@ -732,7 +739,15 @@ npm pack --dry-run --json
|
|
|
732
739
|
npm publish --dry-run --access public
|
|
733
740
|
```
|
|
734
741
|
|
|
735
|
-
|
|
742
|
+
Create a GitHub Release from the matching version tag, for example `v3.6.3`. The `.github/workflows/publish.yml` workflow publishes to npm only when the release is published, not when a tag is pushed. The npm Trusted Publisher entry must match repository `liuqin164/cogmem`, workflow file `publish.yml`, and environment `npm publish`.
|
|
743
|
+
|
|
744
|
+
Publish manually only for emergency fallback:
|
|
745
|
+
|
|
746
|
+
```bash
|
|
747
|
+
npm publish --provenance --access public
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Keep GitHub branches/releases in sync so old GitHub-installed users have a discoverable bridge to the npm-first updater.
|
|
736
751
|
|
|
737
752
|
## Security and Privacy
|
|
738
753
|
|
package/RELEASE_CHECKLIST.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# cogmem 3.6.
|
|
1
|
+
# cogmem 3.6.3 Release Checklist
|
|
2
2
|
|
|
3
3
|
This release is distributed through the npm registry. GitHub remains the source and review mirror.
|
|
4
4
|
|
|
5
5
|
## Required Metadata
|
|
6
6
|
|
|
7
7
|
- `package.json` name is `cogmem`.
|
|
8
|
-
- `package.json` version is `3.6.
|
|
8
|
+
- `package.json` version is `3.6.3`.
|
|
9
9
|
- `package.json` has `publishConfig.access = public`.
|
|
10
10
|
- Public export `.` points to `dist/public.js` and `dist/public.d.ts`.
|
|
11
11
|
- Internal subpath `./internal` exists only as an explicit advanced subpath.
|
|
@@ -85,8 +85,10 @@ npm publish --dry-run --access public
|
|
|
85
85
|
|
|
86
86
|
The pack dry-run must include built public API files, CLI files, examples, docs, and `install.sh`. It must not include local databases or machine-specific files.
|
|
87
87
|
|
|
88
|
-
After verification, publish
|
|
88
|
+
After verification, create a GitHub Release from the matching version tag, for example `v3.6.3`. The release workflow publishes through npm Trusted Publishing when the release is published. It must not publish on tag push alone.
|
|
89
|
+
|
|
90
|
+
Emergency manual fallback:
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
|
-
npm publish --access public
|
|
93
|
+
npm publish --provenance --access public
|
|
92
94
|
```
|
package/dist/bin/migrate.js
CHANGED
|
@@ -62,11 +62,13 @@ async function main() {
|
|
|
62
62
|
const args = parseArgs(process.argv.slice(2));
|
|
63
63
|
const dbPath = resolveDbPath(args);
|
|
64
64
|
const shouldBackup = !args.dryRun && args.backup && dbPath !== ':memory:' && existsSync(dbPath);
|
|
65
|
-
const db = new Database(dbPath);
|
|
65
|
+
const db = new Database(dbPath, args.dryRun && dbPath !== ':memory:' ? { readonly: true, create: false } : undefined);
|
|
66
66
|
db.exec('PRAGMA busy_timeout = 5000;');
|
|
67
|
+
if (args.dryRun)
|
|
68
|
+
db.exec('PRAGMA query_only = ON;');
|
|
67
69
|
try {
|
|
68
70
|
const backupPath = shouldBackup ? backupDatabase(db, dbPath) : undefined;
|
|
69
|
-
const runner = new SchemaMigrationRunner(db, ALL_MIGRATIONS);
|
|
71
|
+
const runner = new SchemaMigrationRunner(db, ALL_MIGRATIONS, { readonly: args.dryRun });
|
|
70
72
|
const result = runner.run({ dryRun: args.dryRun });
|
|
71
73
|
if (!args.dryRun) {
|
|
72
74
|
db.exec(`CREATE TABLE IF NOT EXISTS _meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);`);
|
package/dist/bin/openclaw.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { defaultOpenClawAutoMemoryPluginDir, inspectOpenClawAutoMemoryPlugin, } from '../host/openclaw/AutoMemoryPluginInstaller.js';
|
|
5
5
|
function readArg(name) {
|
|
6
6
|
const index = process.argv.indexOf(name);
|
|
@@ -42,6 +42,54 @@ function readAudit(workspaceRoot) {
|
|
|
42
42
|
recentErrors: records.filter((record) => record.action === 'error').slice(-20),
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
+
function countJsonlLines(path) {
|
|
46
|
+
if (!existsSync(path))
|
|
47
|
+
return 0;
|
|
48
|
+
return readFileSync(path, 'utf8').split('\n').map((line) => line.trim()).filter(Boolean).length;
|
|
49
|
+
}
|
|
50
|
+
function readLock(path) {
|
|
51
|
+
if (!existsSync(path))
|
|
52
|
+
return undefined;
|
|
53
|
+
const ownerPath = join(path, 'owner.json');
|
|
54
|
+
let owner;
|
|
55
|
+
if (existsSync(ownerPath)) {
|
|
56
|
+
try {
|
|
57
|
+
owner = JSON.parse(readFileSync(ownerPath, 'utf8'));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
owner = { parseError: true };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const stat = statSync(path);
|
|
64
|
+
return {
|
|
65
|
+
path,
|
|
66
|
+
mtimeMs: stat.mtimeMs,
|
|
67
|
+
ageMs: Date.now() - stat.mtimeMs,
|
|
68
|
+
owner,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function inspectQueue(workspaceRoot) {
|
|
72
|
+
const queuePath = join(workspaceRoot, '.cogmem', 'queue', 'openclaw-remember.jsonl');
|
|
73
|
+
const queueDir = dirname(queuePath);
|
|
74
|
+
const processingFiles = existsSync(queueDir)
|
|
75
|
+
? readdirSync(queueDir)
|
|
76
|
+
.filter((entry) => entry.startsWith('openclaw-remember.jsonl.') && entry.endsWith('.processing'))
|
|
77
|
+
.map((entry) => {
|
|
78
|
+
const path = join(queueDir, entry);
|
|
79
|
+
const stat = statSync(path);
|
|
80
|
+
return { path, lines: countJsonlLines(path), mtimeMs: stat.mtimeMs, ageMs: Date.now() - stat.mtimeMs };
|
|
81
|
+
})
|
|
82
|
+
: [];
|
|
83
|
+
return {
|
|
84
|
+
queuePath,
|
|
85
|
+
pendingLines: countJsonlLines(queuePath),
|
|
86
|
+
deadPath: `${queuePath}.dead.jsonl`,
|
|
87
|
+
deadLines: countJsonlLines(`${queuePath}.dead.jsonl`),
|
|
88
|
+
lock: readLock(`${queuePath}.lock`),
|
|
89
|
+
spawnLock: readLock(`${queuePath}.spawn.lock`),
|
|
90
|
+
processingFiles,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
45
93
|
function main() {
|
|
46
94
|
const [command] = process.argv.slice(2).filter((arg) => !arg.startsWith('--'));
|
|
47
95
|
if (command !== 'diagnose' || hasFlag('--help') || hasFlag('-h')) {
|
|
@@ -55,12 +103,14 @@ function main() {
|
|
|
55
103
|
const pluginDir = readArg('--plugin-dir') || defaultOpenClawAutoMemoryPluginDir(workspaceRoot);
|
|
56
104
|
const plugin = inspectOpenClawAutoMemoryPlugin({ workspaceRoot, pluginDir });
|
|
57
105
|
const audit = readAudit(workspaceRoot);
|
|
106
|
+
const queue = inspectQueue(workspaceRoot);
|
|
58
107
|
const payload = {
|
|
59
108
|
schemaVersion: 'cogmem.cli.v1',
|
|
60
109
|
command: 'openclaw diagnose',
|
|
61
110
|
workspaceRoot,
|
|
62
111
|
plugin,
|
|
63
112
|
audit,
|
|
113
|
+
queue,
|
|
64
114
|
};
|
|
65
115
|
if (hasFlag('--json')) {
|
|
66
116
|
console.log(JSON.stringify(payload));
|
|
@@ -74,5 +124,6 @@ function main() {
|
|
|
74
124
|
else {
|
|
75
125
|
console.log('last before_prompt_build: none');
|
|
76
126
|
}
|
|
127
|
+
console.log(`queue: pending=${queue.pendingLines} dead=${queue.deadLines} processing=${Array.isArray(queue.processingFiles) ? queue.processingFiles.length : 0}`);
|
|
77
128
|
}
|
|
78
129
|
main();
|
package/dist/bin/update.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
4
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
5
6
|
import { loadCogmemConfig, resolveCogmemConfigPath } from '../config/CogmemConfig.js';
|
|
6
7
|
import { printCliJson } from './CliJson.js';
|
|
7
8
|
import { DEFAULT_NPM_PACKAGE, resolveLatestNpmSpec } from './update-release.js';
|
|
@@ -29,6 +30,8 @@ function readArgs(argv) {
|
|
|
29
30
|
json: values.json === true,
|
|
30
31
|
from: typeof values.from === 'string' ? values.from : 'latest',
|
|
31
32
|
installHome: typeof values['install-home'] === 'string' ? values['install-home'] : undefined,
|
|
33
|
+
global: values.global === true,
|
|
34
|
+
localDev: values['local-dev'] === true,
|
|
32
35
|
manager,
|
|
33
36
|
configPath: typeof values.config === 'string' ? values.config : undefined,
|
|
34
37
|
skipMigrate: values['skip-migrate'] === true,
|
|
@@ -42,7 +45,10 @@ function detectManager(cwd) {
|
|
|
42
45
|
return 'pnpm';
|
|
43
46
|
return 'npm';
|
|
44
47
|
}
|
|
45
|
-
function buildCommand(
|
|
48
|
+
function buildCommand(target, spec) {
|
|
49
|
+
if (target.kind === 'npm_global')
|
|
50
|
+
return ['npm', 'install', '-g', `cogmem@${spec}`];
|
|
51
|
+
const manager = target.manager;
|
|
46
52
|
if (manager === 'bun')
|
|
47
53
|
return ['bun', 'add', `cogmem@${spec}`];
|
|
48
54
|
if (manager === 'pnpm')
|
|
@@ -52,18 +58,18 @@ function buildCommand(manager, spec) {
|
|
|
52
58
|
function localCogmemBin(cwd) {
|
|
53
59
|
return join(cwd, 'node_modules', '.bin', 'cogmem');
|
|
54
60
|
}
|
|
55
|
-
function
|
|
61
|
+
function buildMigrationExecForTarget(target, configPath) {
|
|
56
62
|
return [
|
|
57
|
-
|
|
63
|
+
target.bin,
|
|
58
64
|
'migrate',
|
|
59
65
|
'--yes',
|
|
60
66
|
'--backup',
|
|
61
67
|
...(configPath ? ['--config', configPath] : []),
|
|
62
68
|
];
|
|
63
69
|
}
|
|
64
|
-
function
|
|
70
|
+
function buildOpenClawRepairExecForTarget(target, configPath, workspaceRoot) {
|
|
65
71
|
return [
|
|
66
|
-
|
|
72
|
+
target.bin,
|
|
67
73
|
'doctor',
|
|
68
74
|
'--fix',
|
|
69
75
|
'--agent',
|
|
@@ -99,16 +105,57 @@ function shouldUpdateCwd(cwd) {
|
|
|
99
105
|
const manifest = readPackageManifest(cwd);
|
|
100
106
|
return manifest?.name === 'cogmem' || installedSpec(cwd) !== undefined;
|
|
101
107
|
}
|
|
102
|
-
function
|
|
108
|
+
function isCogmemSourceCheckout(cwd) {
|
|
109
|
+
const manifest = readPackageManifest(cwd);
|
|
110
|
+
return manifest?.name === 'cogmem'
|
|
111
|
+
&& existsSync(join(cwd, 'src', 'bin', 'update.ts'))
|
|
112
|
+
&& existsSync(join(cwd, '.git'));
|
|
113
|
+
}
|
|
114
|
+
function ownPackageRoot() {
|
|
115
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
116
|
+
}
|
|
117
|
+
function isLikelyNpmGlobalInstall(env) {
|
|
118
|
+
if (env.COGMEM_INSTALL_KIND === 'npm_global')
|
|
119
|
+
return true;
|
|
120
|
+
const root = ownPackageRoot();
|
|
121
|
+
const marker = `${sep}node_modules${sep}cogmem`;
|
|
122
|
+
if (!root.includes(marker))
|
|
123
|
+
return false;
|
|
124
|
+
const cwd = resolve(process.cwd());
|
|
125
|
+
return !cwd.startsWith(root + sep);
|
|
126
|
+
}
|
|
127
|
+
function resolveUpdateTarget(args, env) {
|
|
103
128
|
const cwd = process.cwd();
|
|
104
|
-
if (args.
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
if (args.global || isLikelyNpmGlobalInstall(env)) {
|
|
130
|
+
return { cwd, kind: 'npm_global', manager: 'npm', bin: 'cogmem' };
|
|
131
|
+
}
|
|
132
|
+
if (args.installHome) {
|
|
133
|
+
const targetCwd = args.installHome;
|
|
134
|
+
return { cwd: targetCwd, kind: 'install_home', manager: args.manager || detectManager(targetCwd), bin: localCogmemBin(targetCwd) };
|
|
135
|
+
}
|
|
136
|
+
if (isCogmemSourceCheckout(cwd)) {
|
|
137
|
+
return {
|
|
138
|
+
cwd,
|
|
139
|
+
kind: 'source_checkout',
|
|
140
|
+
manager: args.manager || detectManager(cwd),
|
|
141
|
+
bin: localCogmemBin(cwd),
|
|
142
|
+
warning: args.localDev ? undefined : 'source_checkout_requires_local_dev_for_write',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (shouldUpdateCwd(cwd)) {
|
|
146
|
+
return { cwd, kind: 'local_project', manager: args.manager || detectManager(cwd), bin: localCogmemBin(cwd) };
|
|
147
|
+
}
|
|
108
148
|
const installHome = defaultInstallHome(env);
|
|
109
|
-
if (existsSync(join(installHome, 'package.json')))
|
|
110
|
-
return installHome;
|
|
111
|
-
|
|
149
|
+
if (existsSync(join(installHome, 'package.json'))) {
|
|
150
|
+
return { cwd: installHome, kind: 'install_home', manager: args.manager || detectManager(installHome), bin: localCogmemBin(installHome) };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
cwd,
|
|
154
|
+
kind: 'cwd_fallback',
|
|
155
|
+
manager: args.manager || detectManager(cwd),
|
|
156
|
+
bin: localCogmemBin(cwd),
|
|
157
|
+
warning: 'no_install_home_or_project_dependency_detected',
|
|
158
|
+
};
|
|
112
159
|
}
|
|
113
160
|
function loadConfigForUpdate(args) {
|
|
114
161
|
const resolution = resolveCogmemConfigPath({ configPath: args.configPath, cwd: process.cwd() });
|
|
@@ -136,18 +183,24 @@ async function main() {
|
|
|
136
183
|
const resolvedSpec = args.from === 'latest'
|
|
137
184
|
? resolveLatestNpmSpec({ env: process.env })
|
|
138
185
|
: args.from;
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
186
|
+
const target = resolveUpdateTarget(args, process.env);
|
|
187
|
+
if (!args.dryRun && target.kind === 'source_checkout' && !args.localDev) {
|
|
188
|
+
throw new Error('Refusing to update the Cogmem source checkout. Pass --local-dev for an intentional development update, --global for npm global, or --install-home <dir> for the one-line installer home.');
|
|
189
|
+
}
|
|
190
|
+
if (!args.dryRun && target.kind === 'cwd_fallback') {
|
|
191
|
+
throw new Error('Unable to find an installed Cogmem package to update. Pass --global for npm global installs or --install-home <dir> for the one-line installer home.');
|
|
192
|
+
}
|
|
193
|
+
const manager = target.manager;
|
|
194
|
+
const command = buildCommand(target, resolvedSpec);
|
|
142
195
|
const config = loadConfigForUpdate(args);
|
|
143
196
|
const migrationExec = !args.skipMigrate && config.configPath
|
|
144
|
-
?
|
|
197
|
+
? buildMigrationExecForTarget(target, config.configPath)
|
|
145
198
|
: undefined;
|
|
146
199
|
const openclawWorkspace = config.loaded?.integrations.openclaw.enabled
|
|
147
200
|
? config.loaded.integrations.openclaw.workspaceDir || process.cwd()
|
|
148
201
|
: undefined;
|
|
149
202
|
const openclawRepairExec = !args.skipAgentRefresh && openclawWorkspace && config.configPath
|
|
150
|
-
?
|
|
203
|
+
? buildOpenClawRepairExecForTarget(target, config.configPath, openclawWorkspace)
|
|
151
204
|
: undefined;
|
|
152
205
|
const restartRequired = [
|
|
153
206
|
...(openclawWorkspace ? ['restart OpenClaw gateway or agent host'] : []),
|
|
@@ -157,13 +210,15 @@ async function main() {
|
|
|
157
210
|
command: 'update',
|
|
158
211
|
dryRun: args.dryRun,
|
|
159
212
|
manager,
|
|
213
|
+
installKind: target.kind,
|
|
160
214
|
from: args.from,
|
|
161
215
|
source: 'npm',
|
|
162
216
|
npmPackage: DEFAULT_NPM_PACKAGE,
|
|
163
217
|
packageSpec: resolvedSpec,
|
|
164
|
-
targetCwd,
|
|
165
|
-
currentSpec: installedSpec(
|
|
218
|
+
targetCwd: target.cwd,
|
|
219
|
+
currentSpec: target.kind === 'npm_global' ? 'npm:global' : installedSpec(target.cwd),
|
|
166
220
|
nextCommand: command.join(' '),
|
|
221
|
+
updateWarning: target.warning,
|
|
167
222
|
configPath: config.configPath,
|
|
168
223
|
migrationCommand: migrationExec?.join(' '),
|
|
169
224
|
migrationSkippedReason: migrationExec ? undefined : (args.skipMigrate ? 'skip_migrate_flag' : config.skippedReason),
|
|
@@ -182,6 +237,8 @@ async function main() {
|
|
|
182
237
|
else {
|
|
183
238
|
console.log(`cogmem update ${args.dryRun ? 'dry-run' : 'running'}`);
|
|
184
239
|
console.log(`target: ${result.targetCwd}`);
|
|
240
|
+
if (result.updateWarning)
|
|
241
|
+
console.log(`warning: ${result.updateWarning}`);
|
|
185
242
|
console.log(`current: ${result.currentSpec || 'not listed in package.json'}`);
|
|
186
243
|
console.log(`command: ${result.nextCommand}`);
|
|
187
244
|
if (result.migrationCommand)
|
|
@@ -191,7 +248,7 @@ async function main() {
|
|
|
191
248
|
console.log(result.followUp);
|
|
192
249
|
}
|
|
193
250
|
if (!args.dryRun) {
|
|
194
|
-
const updateExitCode = await runCommand(command,
|
|
251
|
+
const updateExitCode = await runCommand(command, target.cwd);
|
|
195
252
|
if (updateExitCode !== 0)
|
|
196
253
|
process.exit(updateExitCode);
|
|
197
254
|
if (migrationExec) {
|
package/dist/factory.js
CHANGED
|
@@ -83,7 +83,7 @@ import { SqliteVecStore } from './store/SqliteVecStore.js';
|
|
|
83
83
|
import { VectorStore } from './store/VectorStore.js';
|
|
84
84
|
import { config } from './utils/Config.js';
|
|
85
85
|
import { KernelRunningError, SnapshotExporter, SnapshotImporter, } from './snapshot/index.js';
|
|
86
|
-
const CORE_VERSION = '3.6.
|
|
86
|
+
const CORE_VERSION = '3.6.3';
|
|
87
87
|
const LATEST_SCHEMA_VERSION = 27;
|
|
88
88
|
export class MemoryKernel {
|
|
89
89
|
options;
|
|
@@ -5,7 +5,7 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { resolveCogmemConfigPath } from '../../config/CogmemConfig.js';
|
|
7
7
|
const PLUGIN_ID = 'cogmem-auto-memory';
|
|
8
|
-
const PLUGIN_VERSION = '0.6.
|
|
8
|
+
const PLUGIN_VERSION = '0.6.3';
|
|
9
9
|
function defaultPublicEntrypoint() {
|
|
10
10
|
return join(resolve(dirname(fileURLToPath(import.meta.url)), '../..'), 'public.js');
|
|
11
11
|
}
|
|
@@ -735,6 +735,7 @@ function bridgeConfig(config) {
|
|
|
735
735
|
rememberQueuePath: rememberQueuePath(config),
|
|
736
736
|
rememberMaxAttempts: config.rememberMaxAttempts || 3,
|
|
737
737
|
rememberDrainBatchSize: config.rememberDrainBatchSize || 20,
|
|
738
|
+
rememberDrainTimeoutMs: config.rememberDrainTimeoutMs || 60000,
|
|
738
739
|
};
|
|
739
740
|
}
|
|
740
741
|
|
|
@@ -988,7 +989,7 @@ function audit(config, record) {
|
|
|
988
989
|
const plugin = {
|
|
989
990
|
id: PLUGIN_ID,
|
|
990
991
|
name: 'CogMem Auto Memory',
|
|
991
|
-
version: '0.6.
|
|
992
|
+
version: '0.6.3',
|
|
992
993
|
register(api) {
|
|
993
994
|
if (!api || typeof api.on !== 'function') {
|
|
994
995
|
throw new Error('OpenClaw plugin API missing api.on');
|
|
@@ -1231,7 +1232,7 @@ module.exports.__testing = {
|
|
|
1231
1232
|
}
|
|
1232
1233
|
function pluginBridgeMjs() {
|
|
1233
1234
|
return String.raw `#!/usr/bin/env bun
|
|
1234
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
1235
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
1235
1236
|
import { dirname, join } from 'node:path';
|
|
1236
1237
|
import { pathToFileURL } from 'node:url';
|
|
1237
1238
|
|
|
@@ -1581,7 +1582,8 @@ function acquireRememberQueueLock(bridgeConfig) {
|
|
|
1581
1582
|
if (!queuePath) throw new Error('missing rememberQueuePath');
|
|
1582
1583
|
mkdirSync(dirname(queuePath), { recursive: true });
|
|
1583
1584
|
const lockPath = queuePath + '.lock';
|
|
1584
|
-
|
|
1585
|
+
const recoveredProcessing = recoverStaleProcessingFiles(bridgeConfig);
|
|
1586
|
+
if (!existsSync(queuePath)) return { acquired: false, locked: false, empty: true, lockPath, recoveredProcessing };
|
|
1585
1587
|
const timeoutMs = Number(bridgeConfig.rememberDrainTimeoutMs || 60000);
|
|
1586
1588
|
try {
|
|
1587
1589
|
mkdirSync(lockPath);
|
|
@@ -1602,12 +1604,12 @@ function acquireRememberQueueLock(bridgeConfig) {
|
|
|
1602
1604
|
staleLockRecovered: true,
|
|
1603
1605
|
queuePath,
|
|
1604
1606
|
}) + '\n');
|
|
1605
|
-
return { acquired: true, locked: false, empty: false, lockPath, staleRecovered: true };
|
|
1607
|
+
return { acquired: true, locked: false, empty: false, lockPath, staleRecovered: true, recoveredProcessing };
|
|
1606
1608
|
}
|
|
1607
1609
|
} catch {}
|
|
1608
1610
|
return { acquired: false, locked: true, empty: false, lockPath };
|
|
1609
1611
|
}
|
|
1610
|
-
return { acquired: true, locked: false, empty: false, lockPath };
|
|
1612
|
+
return { acquired: true, locked: false, empty: false, lockPath, recoveredProcessing };
|
|
1611
1613
|
}
|
|
1612
1614
|
|
|
1613
1615
|
async function drainRememberQueueWithLock(bridgeConfig, queueLock, kernel, memory) {
|
|
@@ -1655,7 +1657,29 @@ async function drainRememberQueueWithLock(bridgeConfig, queueLock, kernel, memor
|
|
|
1655
1657
|
} finally {
|
|
1656
1658
|
if (queueLock.acquired) rmSync(queueLock.lockPath, { recursive: true, force: true });
|
|
1657
1659
|
}
|
|
1658
|
-
return { drained, failed, deferred, locked: false, staleRecovered: queueLock.staleRecovered === true };
|
|
1660
|
+
return { drained, failed, deferred, locked: false, staleRecovered: queueLock.staleRecovered === true, recoveredProcessing: queueLock.recoveredProcessing || 0 };
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
function recoverStaleProcessingFiles(bridgeConfig) {
|
|
1664
|
+
const queuePath = bridgeConfig.rememberQueuePath;
|
|
1665
|
+
const dir = dirname(queuePath);
|
|
1666
|
+
const prefix = queuePath.split('/').pop() + '.';
|
|
1667
|
+
const timeoutMs = Number(bridgeConfig.rememberDrainTimeoutMs || 60000);
|
|
1668
|
+
let recovered = 0;
|
|
1669
|
+
if (!existsSync(dir)) return recovered;
|
|
1670
|
+
for (const entry of readdirSync(dir)) {
|
|
1671
|
+
if (!entry.startsWith(prefix) || !entry.endsWith('.processing')) continue;
|
|
1672
|
+
const path = join(dir, entry);
|
|
1673
|
+
try {
|
|
1674
|
+
const ageMs = Date.now() - statSync(path).mtimeMs;
|
|
1675
|
+
if (!Number.isFinite(ageMs) || ageMs < timeoutMs) continue;
|
|
1676
|
+
const lines = readFileSync(path, 'utf8').split('\n').map((line) => line.trim()).filter(Boolean);
|
|
1677
|
+
for (const line of lines) appendFileSync(queuePath, line + '\n');
|
|
1678
|
+
rmSync(path, { force: true });
|
|
1679
|
+
recovered += lines.length;
|
|
1680
|
+
} catch {}
|
|
1681
|
+
}
|
|
1682
|
+
return recovered;
|
|
1659
1683
|
}
|
|
1660
1684
|
|
|
1661
1685
|
function compactRecallItems(items, config) {
|
|
@@ -3,6 +3,9 @@ import type { Migration } from '../types/Migration.js';
|
|
|
3
3
|
export interface SchemaMigrationRunOptions {
|
|
4
4
|
dryRun?: boolean;
|
|
5
5
|
}
|
|
6
|
+
export interface SchemaMigrationRunnerOptions {
|
|
7
|
+
readonly?: boolean;
|
|
8
|
+
}
|
|
6
9
|
export interface SchemaMigrationResult {
|
|
7
10
|
pending: string[];
|
|
8
11
|
applied: string[];
|
|
@@ -12,10 +15,15 @@ export interface SchemaMigrationResult {
|
|
|
12
15
|
export declare class SchemaMigrationRunner {
|
|
13
16
|
private readonly db;
|
|
14
17
|
private readonly migrations;
|
|
15
|
-
|
|
18
|
+
private readonly options;
|
|
19
|
+
constructor(db: Database, migrations: Migration[], options?: SchemaMigrationRunnerOptions);
|
|
16
20
|
plan(): Migration[];
|
|
17
21
|
run(options?: SchemaMigrationRunOptions): SchemaMigrationResult;
|
|
18
22
|
currentVersion(): string | undefined;
|
|
23
|
+
private appliedVersions;
|
|
24
|
+
private schemaMigrationsTableExists;
|
|
25
|
+
private legacySchemaVersion;
|
|
26
|
+
private legacyCurrentVersion;
|
|
19
27
|
private adoptLegacyVersion;
|
|
20
28
|
}
|
|
21
29
|
//# sourceMappingURL=SchemaMigrationRunner.d.ts.map
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export class SchemaMigrationRunner {
|
|
2
2
|
db;
|
|
3
3
|
migrations;
|
|
4
|
-
|
|
4
|
+
options;
|
|
5
|
+
constructor(db, migrations, options = {}) {
|
|
5
6
|
this.db = db;
|
|
6
7
|
this.migrations = migrations;
|
|
8
|
+
this.options = options;
|
|
9
|
+
if (this.options.readonly)
|
|
10
|
+
return;
|
|
7
11
|
this.db.exec(`
|
|
8
12
|
CREATE TABLE IF NOT EXISTS _schema_migrations (
|
|
9
13
|
version TEXT PRIMARY KEY,
|
|
@@ -14,7 +18,7 @@ export class SchemaMigrationRunner {
|
|
|
14
18
|
this.adoptLegacyVersion();
|
|
15
19
|
}
|
|
16
20
|
plan() {
|
|
17
|
-
const applied =
|
|
21
|
+
const applied = this.appliedVersions();
|
|
18
22
|
return [...this.migrations]
|
|
19
23
|
.sort((a, b) => a.version.localeCompare(b.version))
|
|
20
24
|
.filter((migration) => !applied.has(migration.version));
|
|
@@ -39,20 +43,57 @@ export class SchemaMigrationRunner {
|
|
|
39
43
|
return { pending: pending.map((item) => item.version), applied, currentVersion: this.currentVersion(), dryRun: false };
|
|
40
44
|
}
|
|
41
45
|
currentVersion() {
|
|
46
|
+
const legacyCurrent = this.legacyCurrentVersion();
|
|
47
|
+
if (!this.schemaMigrationsTableExists()) {
|
|
48
|
+
return legacyCurrent;
|
|
49
|
+
}
|
|
42
50
|
const row = this.db.prepare(`
|
|
43
51
|
SELECT version FROM _schema_migrations ORDER BY version DESC LIMIT 1
|
|
44
52
|
`).get();
|
|
45
|
-
return row?.version;
|
|
53
|
+
return [row?.version, legacyCurrent].filter((version) => Boolean(version)).sort((a, b) => b.localeCompare(a))[0];
|
|
46
54
|
}
|
|
47
|
-
|
|
55
|
+
appliedVersions() {
|
|
56
|
+
const applied = new Set();
|
|
57
|
+
const legacyVersion = this.legacySchemaVersion();
|
|
58
|
+
for (const migration of this.migrations) {
|
|
59
|
+
if (legacyVersion !== undefined && Number.parseInt(migration.version, 10) <= legacyVersion) {
|
|
60
|
+
applied.add(migration.version);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!this.schemaMigrationsTableExists()) {
|
|
64
|
+
return applied;
|
|
65
|
+
}
|
|
66
|
+
for (const row of this.db.prepare(`SELECT version FROM _schema_migrations`).all()) {
|
|
67
|
+
applied.add(row.version);
|
|
68
|
+
}
|
|
69
|
+
return applied;
|
|
70
|
+
}
|
|
71
|
+
schemaMigrationsTableExists() {
|
|
72
|
+
return Boolean(this.db.prepare(`
|
|
73
|
+
SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_schema_migrations'
|
|
74
|
+
`).get());
|
|
75
|
+
}
|
|
76
|
+
legacySchemaVersion() {
|
|
48
77
|
const metaExists = this.db.prepare(`
|
|
49
78
|
SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_meta'
|
|
50
79
|
`).get();
|
|
51
80
|
if (!metaExists)
|
|
52
|
-
return;
|
|
81
|
+
return undefined;
|
|
53
82
|
const row = this.db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
54
83
|
const legacyVersion = Number.parseInt(row?.value || '', 10);
|
|
55
|
-
|
|
84
|
+
return Number.isFinite(legacyVersion) ? legacyVersion : undefined;
|
|
85
|
+
}
|
|
86
|
+
legacyCurrentVersion() {
|
|
87
|
+
const legacyVersion = this.legacySchemaVersion();
|
|
88
|
+
if (legacyVersion === undefined)
|
|
89
|
+
return undefined;
|
|
90
|
+
return [...this.migrations]
|
|
91
|
+
.filter((migration) => Number.parseInt(migration.version, 10) <= legacyVersion)
|
|
92
|
+
.sort((a, b) => b.version.localeCompare(a.version))[0]?.version;
|
|
93
|
+
}
|
|
94
|
+
adoptLegacyVersion() {
|
|
95
|
+
const legacyVersion = this.legacySchemaVersion();
|
|
96
|
+
if (legacyVersion === undefined)
|
|
56
97
|
return;
|
|
57
98
|
const insert = this.db.prepare(`
|
|
58
99
|
INSERT OR IGNORE INTO _schema_migrations (version, description, applied_at)
|
|
@@ -21,6 +21,14 @@ cogmem connect hermes --workspace . --auto
|
|
|
21
21
|
cogmem connect hermes --workspace .
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
If Bun is already installed, npm global install is also supported:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g cogmem@latest
|
|
28
|
+
cogmem init --yes --agent hermes
|
|
29
|
+
cogmem connect hermes --workspace . --auto --force
|
|
30
|
+
```
|
|
31
|
+
|
|
24
32
|
Hermes integration is currently a skill plus MCP bridge. It does not replace a native Hermes memory provider and it does not patch Hermes runtime internals.
|
|
25
33
|
|
|
26
34
|
## Local Quantized Embeddings
|
|
@@ -89,7 +97,7 @@ Dream stores explicit user clarification as organizational correction evidence r
|
|
|
89
97
|
|
|
90
98
|
After upgrades, reload MCP. Rerun `cogmem connect hermes --workspace . --auto --force` when MCP wiring, allow-listed tools, or the installed skill bundle changed.
|
|
91
99
|
|
|
92
|
-
Cogmem 3.6.
|
|
100
|
+
Cogmem 3.6.3 exposes seven read-only/idempotent Memory Atlas query tools plus explicit `cogmem_graph_touch`, and installs from npm by default. Use explore for broad memory inventory/history, search and node for a known concept, path/neighbors for relations, timeline for ordered reconstruction, and normal recall for a direct fact. Query facets combine the user's actual project, time, topic, entity/target, memory-kind, action, and keyword conditions like table filters, so cold memory can be revived without requiring an entity-time-action tuple. Touch only nodes actually used, and follow returned event IDs to raw evidence before quoting exact wording.
|
|
93
101
|
|
|
94
102
|
## Runtime
|
|
95
103
|
|
|
@@ -40,6 +40,14 @@ cogmem doctor
|
|
|
40
40
|
cogmem connect hermes --workspace . --auto --force
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
If Bun is already installed and the operator wants npm global installation instead of the one-line installer, use:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g cogmem@latest
|
|
47
|
+
cogmem init --yes --agent hermes
|
|
48
|
+
cogmem connect hermes --workspace . --auto --force
|
|
49
|
+
```
|
|
50
|
+
|
|
43
51
|
Use project-local config only when this workspace needs isolation:
|
|
44
52
|
|
|
45
53
|
```bash
|
|
@@ -98,7 +106,7 @@ cogmem update --yes
|
|
|
98
106
|
# Manual equivalent: cogmem migrate --yes --backup
|
|
99
107
|
```
|
|
100
108
|
|
|
101
|
-
`cogmem update --yes` installs `cogmem@latest` from npm, runs the newly installed backed-up migration with the resolved config, and then reports that the Hermes MCP server or agent host must be reloaded. Agents should inspect `cogmem update --dry-run --json` or `cogmem migrate --dry-run --json` when an operator wants a preview. Schema migration preserves Raw Ledger events;
|
|
109
|
+
`cogmem update --yes` installs `cogmem@latest` from npm, runs the newly installed backed-up migration with the resolved config, and then reports that the Hermes MCP server or agent host must be reloaded. For npm global installs, `cogmem update --yes` resolves to `npm install -g cogmem@latest` instead of writing into the current directory. Agents should inspect `cogmem update --dry-run --json` or `cogmem migrate --dry-run --json` when an operator wants a preview. Schema migration preserves Raw Ledger events; dry-run is read-only and updates governed projections and indexes only during apply.
|
|
102
110
|
|
|
103
111
|
Default Hermes memory contract:
|
|
104
112
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Cogmem 3.6.
|
|
1
|
+
# Cogmem 3.6.3 Operations Reference for Hermes
|
|
2
2
|
|
|
3
3
|
Read this file when installing, upgrading, importing, repairing, or operating Cogmem. `SKILL.md` contains the decision rules; this file records the operational commands.
|
|
4
4
|
|
|
@@ -28,6 +28,14 @@ cogmem doctor
|
|
|
28
28
|
cogmem connect hermes --workspace . --auto --force --json
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
If Bun is already installed and the operator prefers npm global installation:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g cogmem@latest
|
|
35
|
+
cogmem init --yes --agent hermes
|
|
36
|
+
cogmem connect hermes --workspace . --auto --force --json
|
|
37
|
+
```
|
|
38
|
+
|
|
31
39
|
Then run `/reload-mcp` inside Hermes. `connect --auto` installs this skill bundle and updates the Hermes MCP allow-list; it does not claim a native `memory.provider` integration.
|
|
32
40
|
|
|
33
41
|
## Upgrade and migrate
|
|
@@ -38,7 +46,7 @@ For normal upgrades, use one command:
|
|
|
38
46
|
cogmem update --yes
|
|
39
47
|
```
|
|
40
48
|
|
|
41
|
-
`cogmem update --yes` installs `cogmem@latest` from npm, then runs post-install work through the newly installed
|
|
49
|
+
`cogmem update --yes` installs `cogmem@latest` from npm, then runs post-install work through the newly installed CLI. For npm global installs it uses `npm install -g cogmem@latest`; for the one-line installer it updates `~/.cogmem/pkg`; for a workspace dependency it updates that workspace. With a valid config it runs `cogmem migrate --yes --backup --config <config>` and reports that the Hermes MCP server or agent host must be reloaded.
|
|
42
50
|
|
|
43
51
|
Preview the package and migration plan without writing:
|
|
44
52
|
|
|
@@ -53,7 +61,7 @@ cogmem doctor
|
|
|
53
61
|
cogmem connect hermes --workspace . --auto --force --json
|
|
54
62
|
```
|
|
55
63
|
|
|
56
|
-
The backed-up command upgrades 3.5.2 schema 24, an existing 3.6.0 schema-26 database, or a pre-release schema-25 test database to the 3.6.
|
|
64
|
+
The backed-up command upgrades 3.5.2 schema 24, an existing 3.6.0 schema-26 database, or a pre-release schema-25 test database to the 3.6.3 schema-27 state in one run and preserves Raw Ledger evidence. `--dry-run` is read-only and does not create `_schema_migrations`. Reload MCP after reconnecting.
|
|
57
65
|
|
|
58
66
|
## Import Hermes memory
|
|
59
67
|
|
|
@@ -16,6 +16,14 @@ cogmem connect openclaw --workspace .
|
|
|
16
16
|
cogmem connect openclaw --workspace . --auto --force
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
If Bun is already installed, npm global install is also supported:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g cogmem@latest
|
|
23
|
+
cogmem init --yes --agent openclaw --scope project
|
|
24
|
+
cogmem connect openclaw --workspace . --auto --force
|
|
25
|
+
```
|
|
26
|
+
|
|
19
27
|
## Local Quantized Embeddings
|
|
20
28
|
|
|
21
29
|
Imports use the configured kernel embedder. To import existing OpenClaw memory through a local quantized model, configure the kernel before running the import command:
|
|
@@ -78,7 +86,7 @@ cogmem memory tick --project openclaw --json
|
|
|
78
86
|
cogmem memory bind --project openclaw --json
|
|
79
87
|
```
|
|
80
88
|
|
|
81
|
-
Cogmem 3.6.
|
|
89
|
+
Cogmem 3.6.3 keeps the 3.6.x Memory Atlas and OpenClaw reliability work, then makes npm the default install and update channel. The auto plugin uses one shared bridge/kernel lifecycle for graph exploration, evidence-bearing node/timeline drill-down, and recall, so OpenClaw does not need MCP for broad inventory/history questions. Atlas combines the query's actual project, time, topic, entity/target, memory-kind, action, and keyword conditions like table filters; no fixed entity-time-action tuple is required.
|
|
82
90
|
|
|
83
91
|
```bash
|
|
84
92
|
cogmem memory graph-explore --project openclaw --query "去年与 Hermes 有关的决定" --json
|
|
@@ -206,7 +214,7 @@ To make future OpenClaw turns automatically recall and record memory, run:
|
|
|
206
214
|
cogmem connect openclaw --workspace . --auto --force
|
|
207
215
|
```
|
|
208
216
|
|
|
209
|
-
`--auto` installs `<workspace>/extensions/cogmem-auto-memory/`, patches OpenClaw `plugins.load.paths`, and enables a local plugin wrapper with `before_prompt_build` and `agent_end` hooks. The wrapper calls `KernelAgentMemoryBackend` through the public `cogmem` API via a Bun bridge; core still does not import OpenClaw. Plugin 0.6.
|
|
217
|
+
`--auto` installs `<workspace>/extensions/cogmem-auto-memory/`, patches OpenClaw `plugins.load.paths`, and enables a local plugin wrapper with `before_prompt_build` and `agent_end` hooks. The wrapper calls `KernelAgentMemoryBackend` through the public `cogmem` API via a Bun bridge; core still does not import OpenClaw. Plugin 0.6.3 uses singleton queue/spawn locks, stale-lock and stale-processing recovery, and bounded remember batches so queued `agent_end` recording does not hold SQLite open longer than necessary.
|
|
210
218
|
|
|
211
219
|
The wrapper does not rewrite OpenClaw's native prompt, tool instructions, skills, or conversation order. It only prepends Cogmem-owned blocks:
|
|
212
220
|
|
|
@@ -40,6 +40,14 @@ cogmem doctor
|
|
|
40
40
|
cogmem connect openclaw --workspace . --auto --force
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
If Bun is already installed and the operator wants npm global installation instead of the one-line installer, use:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g cogmem@latest
|
|
47
|
+
cogmem init --yes --agent openclaw --scope project
|
|
48
|
+
cogmem connect openclaw --workspace . --auto --force
|
|
49
|
+
```
|
|
50
|
+
|
|
43
51
|
This creates project-local kernel config and storage under `.cogmem/`, which is the recommended OpenClaw workspace setup.
|
|
44
52
|
|
|
45
53
|
```bash
|
|
@@ -98,7 +106,7 @@ cogmem update --yes
|
|
|
98
106
|
# Manual equivalent: cogmem migrate --yes --backup && cogmem doctor --fix --agent openclaw --workspace . --plugin-only
|
|
99
107
|
```
|
|
100
108
|
|
|
101
|
-
`cogmem update --yes` installs `cogmem@latest` from npm, runs the newly installed backed-up migration with the resolved config, refreshes OpenClaw's generated plugin files when the integration is configured, and then reports that the OpenClaw gateway or agent host must be restarted. Agents should inspect `cogmem update --dry-run --json` or `cogmem migrate --dry-run --json` when an operator wants a preview. Schema migration preserves Raw Ledger events;
|
|
109
|
+
`cogmem update --yes` installs `cogmem@latest` from npm, runs the newly installed backed-up migration with the resolved config, refreshes OpenClaw's generated plugin files when the integration is configured, and then reports that the OpenClaw gateway or agent host must be restarted. For npm global installs, `cogmem update --yes` resolves to `npm install -g cogmem@latest` instead of writing into the current directory. Agents should inspect `cogmem update --dry-run --json` or `cogmem migrate --dry-run --json` when an operator wants a preview. Schema migration preserves Raw Ledger events; dry-run is read-only and updates governed projections and indexes only during apply.
|
|
102
110
|
|
|
103
111
|
After any 3.5.2 -> 3.6.x OpenClaw upgrade, refresh the generated OpenClaw plugin files. Use the plugin-only path first when OpenClaw is misbehaving, because it does not open the Cogmem database:
|
|
104
112
|
|
|
@@ -298,7 +306,7 @@ cogmem connect openclaw --workspace . --auto --force
|
|
|
298
306
|
|
|
299
307
|
`--auto` writes `<workspace>/extensions/cogmem-auto-memory/`, patches `plugins.load.paths`, and enables `hooks.allowPromptInjection=true` and `hooks.allowConversationAccess=true` for the wrapper. The wrapper registers `before_prompt_build` for governed recall and `agent_end` for turn recording, then calls `KernelAgentMemoryBackend` through `cogmem` public API via a Bun bridge. Core does not import OpenClaw.
|
|
300
308
|
|
|
301
|
-
Queued remember is the default. `agent_end` appends a durable JSONL job under `.cogmem/queue/openclaw-remember.jsonl` and starts a singleton drainer, so Telegram or gateway responses are not blocked by embeddings, SQLite writes, or slow local models. Plugin 0.6.
|
|
309
|
+
Queued remember is the default. `agent_end` appends a durable JSONL job under `.cogmem/queue/openclaw-remember.jsonl` and starts a singleton drainer, so Telegram or gateway responses are not blocked by embeddings, SQLite writes, or slow local models. Plugin 0.6.3 acquires the queue lock before opening Cogmem, recovers stale lock directories and stale `.processing` queue files older than `rememberDrainTimeoutMs`, writes `owner.json` lock metadata, and processes bounded batches controlled by `rememberDrainBatchSize` (default `20`). If a drain fails, the job is retried and then moved to a dead-letter file instead of being silently discarded.
|
|
302
310
|
|
|
303
311
|
When automatic memory recording looks stuck, do not delete queue files first. Diagnose the plugin and locks:
|
|
304
312
|
|
|
@@ -309,6 +317,8 @@ cat .cogmem/queue/openclaw-remember.jsonl.lock/owner.json 2>/dev/null || true
|
|
|
309
317
|
cat .cogmem/queue/openclaw-remember.jsonl.spawn.lock/owner.json 2>/dev/null || true
|
|
310
318
|
```
|
|
311
319
|
|
|
320
|
+
`openclaw diagnose` reports pending queue lines, dead-letter lines, active lock metadata, spawn-lock metadata, and stale `.processing` files. Use that JSON before deleting anything manually.
|
|
321
|
+
|
|
312
322
|
If `plugin.current=false`, refresh without opening the database:
|
|
313
323
|
|
|
314
324
|
```bash
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Cogmem 3.6.
|
|
1
|
+
# Cogmem 3.6.3 Operations Reference for OpenClaw
|
|
2
2
|
|
|
3
3
|
Read this file when installing, upgrading, importing, repairing, or operating Cogmem. `SKILL.md` contains the decision rules; this file is the command reference.
|
|
4
4
|
|
|
@@ -33,6 +33,14 @@ cogmem doctor
|
|
|
33
33
|
cogmem connect openclaw --workspace . --auto --force --json
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
If Bun is already installed and the operator prefers npm global installation:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g cogmem@latest
|
|
40
|
+
cogmem init --yes --agent openclaw --scope project
|
|
41
|
+
cogmem connect openclaw --workspace . --auto --force --json
|
|
42
|
+
```
|
|
43
|
+
|
|
36
44
|
Restart the OpenClaw Gateway after plugin or config changes. `connect --auto` installs the direct OpenClaw hook bridge; OpenClaw does not need MCP for automatic recall, recording, or Atlas navigation.
|
|
37
45
|
|
|
38
46
|
## Upgrade and migrate
|
|
@@ -44,7 +52,7 @@ cogmem update --yes
|
|
|
44
52
|
openclaw gateway restart
|
|
45
53
|
```
|
|
46
54
|
|
|
47
|
-
`cogmem update --yes` installs `cogmem@latest` from npm, then runs post-install work through the newly installed
|
|
55
|
+
`cogmem update --yes` installs `cogmem@latest` from npm, then runs post-install work through the newly installed CLI. For npm global installs it uses `npm install -g cogmem@latest`; for the one-line installer it updates `~/.cogmem/pkg`; for a workspace dependency it updates that workspace. With a valid config it runs `cogmem migrate --yes --backup --config <config>`. When OpenClaw integration is enabled, it also runs `cogmem doctor --fix --agent openclaw --plugin-only --config <config> --workspace <workspace>` so stale generated plugin files are replaced before restart.
|
|
48
56
|
|
|
49
57
|
Preview the package, migration, and plugin-refresh plan without writing:
|
|
50
58
|
|
|
@@ -62,7 +70,7 @@ openclaw gateway restart
|
|
|
62
70
|
cogmem openclaw diagnose --workspace . --json
|
|
63
71
|
```
|
|
64
72
|
|
|
65
|
-
The second command upgrades 3.5.2 schema 24, an existing 3.6.0 schema-26 database, or a pre-release schema-25 test database to the 3.6.
|
|
73
|
+
The second command upgrades 3.5.2 schema 24, an existing 3.6.0 schema-26 database, or a pre-release schema-25 test database to the 3.6.3 schema-27 state in one run. It preserves Raw Ledger evidence. Keep the returned `backupPath` until verification passes. `--dry-run` is read-only and does not create `_schema_migrations`.
|
|
66
74
|
|
|
67
75
|
After upgrading the package/database, refresh OpenClaw's generated plugin files. `doctor --plugin-only` avoids opening the Cogmem kernel, so it can repair stale `extensions/cogmem-auto-memory/index.js` and `bridge.mjs` even when an old drainer has SQLite busy. Use `connect --auto --force` when intentionally reinstalling the full integration and patching OpenClaw config:
|
|
68
76
|
|
|
@@ -75,15 +83,16 @@ Use `cogmem openclaw diagnose --workspace . --json` when automatic memory blocks
|
|
|
75
83
|
- `plugin.current=false`: generated files are stale; run plugin-only fix and restart gateway.
|
|
76
84
|
- no `audit.lastBeforePromptBuild`: plugin is not loaded or the hook did not fire.
|
|
77
85
|
- `audit.lastBeforePromptBuild.action=error`: bridge or DB failure; inspect `reason`, `bridgeCommand`, and `dbLocked`.
|
|
78
|
-
- `action=inject` but no visible block: inspect `returnedInjectionShape`. Plugin 0.6.
|
|
86
|
+
- `action=inject` but no visible block: inspect `returnedInjectionShape`. Plugin 0.6.3 returns `prependContext`, `context`, and `promptPrefix`; if OpenClaw still ignores all three, the host hook contract changed and the OpenClaw plugin API must be checked before blaming recall.
|
|
79
87
|
|
|
80
|
-
Plugin 0.6.
|
|
88
|
+
Plugin 0.6.3 queue behavior:
|
|
81
89
|
|
|
82
90
|
- `agent_end` only appends durable JSONL jobs, then starts at most one drainer through queue/spawn locks.
|
|
83
91
|
- `drain-remember-queue` acquires the queue lock before opening Cogmem or SQLite. A second drainer exits without opening the DB.
|
|
84
|
-
- Stale `.cogmem/queue/openclaw-remember.jsonl.lock
|
|
92
|
+
- Stale `.cogmem/queue/openclaw-remember.jsonl.lock`, `.spawn.lock`, and `.processing` files older than `rememberDrainTimeoutMs` are recovered automatically and carry enough metadata for diagnosis.
|
|
85
93
|
- `rememberDrainBatchSize` defaults to `20`, so a busy workspace drains bounded batches and releases DB handles quickly. Lower it temporarily if OpenClaw shares a slow SQLite disk.
|
|
86
94
|
- Failed jobs retry up to `rememberMaxAttempts`; exhausted jobs move to `.dead.jsonl`.
|
|
95
|
+
- `cogmem openclaw diagnose --workspace . --json` reports pending queue lines, dead-letter lines, lock owners, spawn-lock owners, and `.processing` files.
|
|
87
96
|
|
|
88
97
|
If the queue is not draining, diagnose before deleting files:
|
|
89
98
|
|
package/install.sh
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogmem",
|
|
3
3
|
|
|
4
|
-
"version": "3.6.
|
|
4
|
+
"version": "3.6.3",
|
|
5
5
|
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "cogmem — agent-native memory kernel for a single local-first AI agent",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/liuqin164/cogmem.git"
|
|
11
|
+
},
|
|
8
12
|
"main": "./dist/public.js",
|
|
9
13
|
"types": "./dist/public.d.ts",
|
|
10
14
|
"exports": {
|
|
@@ -46,7 +50,7 @@
|
|
|
46
50
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
47
51
|
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
48
52
|
"prepare": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
49
|
-
"prepublishOnly": "bun run typecheck && bun test __tests__
|
|
53
|
+
"prepublishOnly": "bun run typecheck && bun test __tests__ && bun run build && npm pack --dry-run --json",
|
|
50
54
|
"type": "tsc -p tsconfig.json --noEmit",
|
|
51
55
|
"test": "bun test __tests__",
|
|
52
56
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|