cogmem 3.6.2 → 3.6.4
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 +14 -0
- package/CONTRIBUTING.md +2 -2
- package/README.md +60 -14
- package/RELEASE_CHECKLIST.md +13 -5
- package/dist/bin/connect.js +39 -27
- package/dist/bin/import-support.d.ts +1 -0
- package/dist/bin/import-support.js +15 -2
- package/dist/bin/mcp.js +2 -1
- package/dist/bin/migrate.js +4 -2
- package/dist/bin/openclaw.js +53 -2
- package/dist/bin/update.js +79 -22
- package/dist/episode/EpisodeStore.d.ts +7 -0
- package/dist/episode/EpisodeStore.js +75 -6
- package/dist/factory.js +3 -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/AGENTS.md +27 -13
- package/examples/hermes-backend/README.md +25 -7
- package/examples/hermes-backend/SKILL.md +54 -17
- package/examples/hermes-backend/references/operations.md +45 -8
- package/examples/openclaw-backend/AGENTS.md +27 -6
- package/examples/openclaw-backend/README.md +26 -8
- package/examples/openclaw-backend/SKILL.md +60 -12
- package/examples/openclaw-backend/references/operations.md +49 -10
- package/install.sh +6 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.6.4
|
|
4
|
+
|
|
5
|
+
- Fixed OpenClaw/Hermes imports so empty imported episode boundaries are not batch-sealed into Dream work, and mature empty soft seals no longer abort `dream tick`.
|
|
6
|
+
- Added Dream queue cleanup for legacy empty episode jobs so one bad upgraded/imported episode is marked skipped and does not consume maintenance batch slots.
|
|
7
|
+
- Updated OpenClaw and Hermes auto-installed skills, runbooks, and README examples to prefer npm workspace-local installs, reserve `cogmem init` for interactive operator setup, and document the full import -> dream -> candidate governance -> `needs_confirmation` review flow.
|
|
8
|
+
- Standardized MCP guidance on `cogmem mcp` for new Hermes/OpenClaw host configs while keeping `cogmem-mcp` as a compatibility bin for existing configs.
|
|
9
|
+
|
|
10
|
+
## 3.6.3
|
|
11
|
+
|
|
12
|
+
- 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`.
|
|
13
|
+
- 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.
|
|
14
|
+
- 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.
|
|
15
|
+
- Updated OpenClaw diagnostics and generated bridge behavior to propagate `rememberDrainTimeoutMs`, recover stale `.processing` queue files, and report pending/dead/lock/processing queue state.
|
|
16
|
+
|
|
3
17
|
## 3.6.2
|
|
4
18
|
|
|
5
19
|
- 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,15 +11,24 @@ 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.4`
|
|
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
|
|
|
18
|
+
Default workspace install:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install cogmem@latest --save
|
|
22
|
+
./node_modules/.bin/cogmem doctor
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
One-line installer for machines that need Bun bootstrapping:
|
|
26
|
+
|
|
18
27
|
```bash
|
|
19
28
|
curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
|
|
20
29
|
```
|
|
21
30
|
|
|
22
|
-
The installer:
|
|
31
|
+
The one-line installer:
|
|
23
32
|
|
|
24
33
|
1. Ensures Bun is available.
|
|
25
34
|
2. Installs `cogmem@latest` from the npm registry into `~/.cogmem/pkg`.
|
|
@@ -158,10 +167,11 @@ High-dimensional vectors grow quickly. Prefer `raw_then_dream` or `selective_com
|
|
|
158
167
|
|
|
159
168
|
## Quick Start
|
|
160
169
|
|
|
161
|
-
Install
|
|
170
|
+
Install into an agent workspace with npm:
|
|
162
171
|
|
|
163
172
|
```bash
|
|
164
|
-
|
|
173
|
+
npm install cogmem@latest --save
|
|
174
|
+
./node_modules/.bin/cogmem doctor
|
|
165
175
|
```
|
|
166
176
|
|
|
167
177
|
Or install into an existing Bun workspace:
|
|
@@ -178,6 +188,26 @@ npm install cogmem@latest
|
|
|
178
188
|
./node_modules/.bin/cogmem init
|
|
179
189
|
```
|
|
180
190
|
|
|
191
|
+
Or install globally with npm when Bun is already on PATH:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm install -g cogmem@latest
|
|
195
|
+
cogmem init
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Or use the one-line installer for machines that do not already have Bun:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
For agent-run installs, skip the interactive wizard and connect the host explicitly:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
COGMEM_SKIP_INIT=1 curl -fsSL https://raw.githubusercontent.com/liuqin164/cogmem/main/install.sh | bash
|
|
208
|
+
cogmem doctor
|
|
209
|
+
```
|
|
210
|
+
|
|
181
211
|
Validate configuration:
|
|
182
212
|
|
|
183
213
|
```bash
|
|
@@ -190,7 +220,7 @@ Upgrade from npm and migrate an existing database:
|
|
|
190
220
|
cogmem update --yes
|
|
191
221
|
```
|
|
192
222
|
|
|
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:
|
|
223
|
+
`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
224
|
|
|
195
225
|
```bash
|
|
196
226
|
cogmem update --dry-run --json
|
|
@@ -199,7 +229,7 @@ cogmem migrate --dry-run --json
|
|
|
199
229
|
|
|
200
230
|
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
231
|
|
|
202
|
-
Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.
|
|
232
|
+
Upgrade a 3.5.2 database, a 3.6.0 database, or a pre-release schema-25 test database into the 3.6.4 schema set with one command:
|
|
203
233
|
|
|
204
234
|
```bash
|
|
205
235
|
cogmem migrate --yes --backup --json
|
|
@@ -230,9 +260,14 @@ cogmem repair project-scope --from "" --to openclaw --apply --json
|
|
|
230
260
|
Inspect and conditionally process sealed conversation episodes:
|
|
231
261
|
|
|
232
262
|
```bash
|
|
263
|
+
cogmem memory status --project my-agent --json
|
|
233
264
|
cogmem episode status --project my-agent --json
|
|
234
|
-
cogmem dream
|
|
265
|
+
cogmem dream status --project my-agent --json
|
|
266
|
+
cogmem dream tick --project my-agent --mode auto --max-episodes 20 --json
|
|
267
|
+
cogmem memory candidates --project my-agent --status candidate --json
|
|
235
268
|
cogmem memory govern --project my-agent --json
|
|
269
|
+
cogmem memory candidates --project my-agent --status needs_confirmation --json
|
|
270
|
+
cogmem memory review --project my-agent --id <candidate-id> --action approve --actor <operator> --reason "confirmed" --confirmation-event <user-event-id> --json
|
|
236
271
|
```
|
|
237
272
|
|
|
238
273
|
For a host timer, call `dream tick`; the timer only wakes the scheduler. An empty backlog performs no Dream work:
|
|
@@ -241,9 +276,9 @@ For a host timer, call `dream tick`; the timer only wakes the scheduler. An empt
|
|
|
241
276
|
cogmem dream tick --project my-agent --mode auto --max-episodes 10 --json
|
|
242
277
|
```
|
|
243
278
|
|
|
244
|
-
Raw events are always written first. `KernelAgentMemoryBackend` and OpenClaw plugin 0.6.
|
|
279
|
+
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
280
|
|
|
246
|
-
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.
|
|
281
|
+
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. Cogmem 3.6.4 skips import batch sealing for empty episode boundaries and skips legacy empty Dream jobs so one bad imported episode cannot block the queue. 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
282
|
|
|
248
283
|
User-shaped topic state is project-scoped. Explicit user operations become active and auditable; model-proposed topics, aliases, and relations remain candidates. Use MCP `cogmem_topic_list` to inspect nodes, `cogmem_topic_operate` to create, rename, alias, move, merge, split, or relate topics, and `cogmem_topic_rollback` to reverse an audited operation. Alias collisions fail closed as `needs_review`; applications can also call `TopicGovernance.rollback()` through the public API.
|
|
249
284
|
|
|
@@ -337,7 +372,7 @@ cogmem strategy plan --project hermes --query "我当时的原话是什么?" -
|
|
|
337
372
|
cogmem strategy outcomes --project hermes --json
|
|
338
373
|
```
|
|
339
374
|
|
|
340
|
-
OpenClaw plugin 0.6.
|
|
375
|
+
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
376
|
|
|
342
377
|
`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
378
|
|
|
@@ -475,8 +510,8 @@ Hermes integration is MCP-based in this release. cogmem does not claim to be a n
|
|
|
475
510
|
Install the skill and patch Hermes MCP config:
|
|
476
511
|
|
|
477
512
|
```bash
|
|
478
|
-
cogmem
|
|
479
|
-
cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
|
|
513
|
+
npm install cogmem@latest --save
|
|
514
|
+
./node_modules/.bin/cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
|
|
480
515
|
```
|
|
481
516
|
|
|
482
517
|
This installs the agent-facing skill bundle at:
|
|
@@ -494,6 +529,8 @@ With `--auto`, it adds or updates a `cogmem` MCP server entry in:
|
|
|
494
529
|
~/.hermes/config.yaml
|
|
495
530
|
```
|
|
496
531
|
|
|
532
|
+
New Hermes configs start the server with `cogmem mcp`. Existing `cogmem-mcp` entries remain supported and are updated in place for tool allow-list changes.
|
|
533
|
+
|
|
497
534
|
Then reload MCP inside Hermes:
|
|
498
535
|
|
|
499
536
|
```text
|
|
@@ -681,7 +718,7 @@ For Hermes after an update, reload the MCP server or restart the agent host. If
|
|
|
681
718
|
cogmem connect hermes --workspace /path/to/hermes/workspace --auto --force
|
|
682
719
|
```
|
|
683
720
|
|
|
684
|
-
This also updates existing Hermes
|
|
721
|
+
This also updates existing Hermes MCP blocks with missing strategy, episode, Dream, memory-map, maintenance, and prospective tools. New configs use `cogmem mcp`; `cogmem-mcp` remains a compatibility bin.
|
|
685
722
|
|
|
686
723
|
## Documentation
|
|
687
724
|
|
|
@@ -703,6 +740,7 @@ Installed OpenClaw and Hermes skills include their own `references/operations.md
|
|
|
703
740
|
cogmem init
|
|
704
741
|
cogmem doctor
|
|
705
742
|
cogmem connect openclaw|hermes
|
|
743
|
+
cogmem mcp
|
|
706
744
|
cogmem update
|
|
707
745
|
cogmem memory recall|search|show|dream|govern|candidates|review|status|map|tick|bind
|
|
708
746
|
cogmem memory graph|graph-search|graph-explore|graph-node|graph-neighbors|graph-path|graph-timeline
|
|
@@ -732,7 +770,15 @@ npm pack --dry-run --json
|
|
|
732
770
|
npm publish --dry-run --access public
|
|
733
771
|
```
|
|
734
772
|
|
|
735
|
-
|
|
773
|
+
Create a GitHub Release from the matching version tag, for example `v3.6.4`. 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`.
|
|
774
|
+
|
|
775
|
+
Publish manually only for emergency fallback:
|
|
776
|
+
|
|
777
|
+
```bash
|
|
778
|
+
npm publish --provenance --access public
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Keep GitHub branches/releases in sync so old GitHub-installed users have a discoverable bridge to the npm-first updater.
|
|
736
782
|
|
|
737
783
|
## Security and Privacy
|
|
738
784
|
|
package/RELEASE_CHECKLIST.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# cogmem 3.6.
|
|
1
|
+
# cogmem 3.6.4 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.4`.
|
|
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.
|
|
@@ -19,12 +19,13 @@ This release is distributed through the npm registry. GitHub remains the source
|
|
|
19
19
|
- `cogmem doctor`
|
|
20
20
|
- `cogmem connect`
|
|
21
21
|
- `cogmem update`
|
|
22
|
+
- `cogmem mcp`
|
|
22
23
|
- `cogmem openclaw diagnose`
|
|
23
24
|
- `cogmem-compact`
|
|
24
25
|
- `cogmem memory`
|
|
25
26
|
- `cogmem repair`
|
|
26
27
|
- `cogmem explain-recall`
|
|
27
|
-
- `cogmem-mcp`
|
|
28
|
+
- `cogmem-mcp` compatibility bin for existing host configs
|
|
28
29
|
- `cogmem import-openclaw`
|
|
29
30
|
- `cogmem import-hermes`
|
|
30
31
|
- `cogmem normalize-transcript`
|
|
@@ -43,6 +44,8 @@ MCP `tools/list` includes strategy, episode append/import/status/seal/repair, to
|
|
|
43
44
|
## Required Documentation
|
|
44
45
|
|
|
45
46
|
- README explains the vision, architecture, limits, and one-line install command.
|
|
47
|
+
- README and skills document npm as the default install path: workspace-local `npm install cogmem@latest --save` for OpenClaw/Hermes projects, global npm only when the operator wants one shared CLI, and the one-line installer as compatibility.
|
|
48
|
+
- README and skills state that `cogmem init` is an interactive operator wizard and must not be scripted by an unattended agent; agents should use resolved `cogmem` commands, `cogmem doctor`, and `cogmem connect <agent>`.
|
|
46
49
|
- README says this is a single-agent memory kernel, not an agent team shared brain.
|
|
47
50
|
- README distinguishes embedding models from Dream Curator memory-model LLMs.
|
|
48
51
|
- README and integration docs explain labeled `sourceContext`, strict before/after window metadata, `charRange` / `sourceRange`, and OpenClaw `sourceWindow` / `sourceTruncation` injection.
|
|
@@ -56,6 +59,9 @@ MCP `tools/list` includes strategy, episode append/import/status/seal/repair, to
|
|
|
56
59
|
- README and skills explain that Prospective Memory is confirmed-only state with no task execution capability, and how to use BrainEval as a release gate.
|
|
57
60
|
- README and skills explain Strategy Cortex templates, no-instruction-authority lifecycle, one-retry replanning, strategy-conditioned retrieval, offline-only rollout comparison, and read-only MemoryUseJudge telemetry.
|
|
58
61
|
- README and skills explain Raw Ledger-first episode assembly, soft/hard sealing, explicit conditional Dream ticks, raw-event evidence grounding, repair/retry, and hookless Hermes MCP/import usage.
|
|
62
|
+
- README and skills give the full post-import maintenance sequence: status, episode status, Dream status, bounded Dream tick, candidate listing, govern candidate, needs-confirmation listing, explicit review, and recall verification.
|
|
63
|
+
- README and skills explain that 3.6.4 skips empty imported episode boundaries and legacy empty Dream jobs instead of letting them abort `dream tick`.
|
|
64
|
+
- README and skills document `cogmem mcp` as the preferred MCP server command for new configs while preserving `cogmem-mcp` as a compatibility bin.
|
|
59
65
|
- README and skills explain CPU foreground versus hybrid background classification, contextual short replies, registry-aware topic boundaries, safe reopen, semantic-summary non-evidence status, per-job Dream modes/failures, stable import identity, and schema migration 24.
|
|
60
66
|
- README and skills explain user-shaped topic operations, user-explicit versus model-candidate authority, alias collision review, operation rollback, and project isolation.
|
|
61
67
|
- README, `MEMORY_ATLAS.md`, and skills distinguish the system anatomy map from the content Atlas; explain graph overview/search/explore/node/neighbors/path/timeline, generic multi-facet cold-memory resurrection, activation visibility, source drill-down, and project isolation.
|
|
@@ -85,8 +91,10 @@ npm publish --dry-run --access public
|
|
|
85
91
|
|
|
86
92
|
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
93
|
|
|
88
|
-
After verification, publish
|
|
94
|
+
After verification, create a GitHub Release from the matching version tag, for example `v3.6.4`. The release workflow publishes through npm Trusted Publishing when the release is published. It must not publish on tag push alone.
|
|
95
|
+
|
|
96
|
+
Emergency manual fallback:
|
|
89
97
|
|
|
90
98
|
```bash
|
|
91
|
-
npm publish --access public
|
|
99
|
+
npm publish --provenance --access public
|
|
92
100
|
```
|
package/dist/bin/connect.js
CHANGED
|
@@ -92,19 +92,18 @@ function defaultSkillPath(agent, workspaceRoot) {
|
|
|
92
92
|
function nextCommands(agent) {
|
|
93
93
|
if (agent === 'openclaw') {
|
|
94
94
|
return [
|
|
95
|
-
'./node_modules/.bin/cogmem
|
|
96
|
-
'./node_modules/.bin/cogmem
|
|
97
|
-
'./node_modules/.bin/cogmem
|
|
98
|
-
'./node_modules/.bin/cogmem
|
|
99
|
-
'./node_modules/.bin/cogmem
|
|
95
|
+
'./node_modules/.bin/cogmem doctor',
|
|
96
|
+
'./node_modules/.bin/cogmem openclaw diagnose --workspace . --json',
|
|
97
|
+
'./node_modules/.bin/cogmem import-openclaw --workspace . --project openclaw --dry-run',
|
|
98
|
+
'./node_modules/.bin/cogmem import-openclaw --workspace . --project openclaw',
|
|
99
|
+
'./node_modules/.bin/cogmem memory status --project openclaw --json',
|
|
100
100
|
];
|
|
101
101
|
}
|
|
102
102
|
return [
|
|
103
|
-
'./node_modules/.bin/cogmem
|
|
104
|
-
'./node_modules/.bin/cogmem-
|
|
105
|
-
'./node_modules/.bin/cogmem-
|
|
106
|
-
'./node_modules/.bin/cogmem
|
|
107
|
-
'./node_modules/.bin/cogmem-import-hermes --workspace . --project hermes',
|
|
103
|
+
'./node_modules/.bin/cogmem doctor',
|
|
104
|
+
'./node_modules/.bin/cogmem import-hermes --workspace . --project hermes --dry-run',
|
|
105
|
+
'./node_modules/.bin/cogmem import-hermes --workspace . --project hermes',
|
|
106
|
+
'./node_modules/.bin/cogmem memory status --project hermes --json',
|
|
108
107
|
];
|
|
109
108
|
}
|
|
110
109
|
function usage() {
|
|
@@ -138,33 +137,45 @@ function hostConfigSnippet(agent, workspaceRoot, auto) {
|
|
|
138
137
|
'// Add host config only after installing a real OpenClaw plugin wrapper with a valid manifest/schema.',
|
|
139
138
|
].join('\n');
|
|
140
139
|
}
|
|
141
|
-
const
|
|
140
|
+
const mcpServer = resolveCogmemMcpServer(workspaceRoot);
|
|
142
141
|
return [
|
|
143
142
|
'mcp_servers:',
|
|
144
143
|
' cogmem:',
|
|
145
|
-
` command: "${
|
|
146
|
-
|
|
144
|
+
` command: "${mcpServer.command}"`,
|
|
145
|
+
` args: ${JSON.stringify(mcpServer.args)}`,
|
|
147
146
|
' enabled: true',
|
|
148
147
|
' tools:',
|
|
149
148
|
' include:',
|
|
150
149
|
...HERMES_COGMEM_TOOLS.map((tool) => ` - ${tool}`),
|
|
151
150
|
].join('\n');
|
|
152
151
|
}
|
|
153
|
-
function
|
|
152
|
+
function resolveCogmemMcpServer(workspaceRoot) {
|
|
154
153
|
if (process.env.COGMEM_MCP_BIN)
|
|
155
|
-
return process.env.COGMEM_MCP_BIN;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
return { command: process.env.COGMEM_MCP_BIN, args: [] };
|
|
155
|
+
if (process.env.COGMEM_BIN)
|
|
156
|
+
return { command: process.env.COGMEM_BIN, args: ['mcp'] };
|
|
157
|
+
const workspaceCli = join(workspaceRoot, 'node_modules', '.bin', 'cogmem');
|
|
158
|
+
if (existsSync(workspaceCli))
|
|
159
|
+
return { command: workspaceCli, args: ['mcp'] };
|
|
159
160
|
const pathValue = process.env.PATH || '';
|
|
161
|
+
for (const segment of pathValue.split(':')) {
|
|
162
|
+
if (!segment)
|
|
163
|
+
continue;
|
|
164
|
+
const candidate = join(segment, 'cogmem');
|
|
165
|
+
if (existsSync(candidate))
|
|
166
|
+
return { command: candidate, args: ['mcp'] };
|
|
167
|
+
}
|
|
168
|
+
const workspaceMcp = join(workspaceRoot, 'node_modules', '.bin', 'cogmem-mcp');
|
|
169
|
+
if (existsSync(workspaceMcp))
|
|
170
|
+
return { command: workspaceMcp, args: [] };
|
|
160
171
|
for (const segment of pathValue.split(':')) {
|
|
161
172
|
if (!segment)
|
|
162
173
|
continue;
|
|
163
174
|
const candidate = join(segment, 'cogmem-mcp');
|
|
164
175
|
if (existsSync(candidate))
|
|
165
|
-
return candidate;
|
|
176
|
+
return { command: candidate, args: [] };
|
|
166
177
|
}
|
|
167
|
-
return 'cogmem
|
|
178
|
+
return { command: 'cogmem', args: ['mcp'] };
|
|
168
179
|
}
|
|
169
180
|
function installSkill(args) {
|
|
170
181
|
if (!args.agent)
|
|
@@ -237,9 +248,9 @@ function defaultHermesConfigPath(env = process.env) {
|
|
|
237
248
|
}
|
|
238
249
|
function installHermesMcpConfig(input) {
|
|
239
250
|
const configPath = resolve(input.configPath || defaultHermesConfigPath());
|
|
240
|
-
const
|
|
251
|
+
const server = resolveCogmemMcpServer(resolve(input.workspaceRoot));
|
|
241
252
|
const original = existsSync(configPath) ? readFileSync(configPath, 'utf8') : '';
|
|
242
|
-
const patched = patchHermesMcpConfig(original,
|
|
253
|
+
const patched = patchHermesMcpConfig(original, server.command, server.args);
|
|
243
254
|
const changed = patched !== original;
|
|
244
255
|
let backupPath;
|
|
245
256
|
if (!input.dryRun && (changed || input.force)) {
|
|
@@ -253,21 +264,22 @@ function installHermesMcpConfig(input) {
|
|
|
253
264
|
return {
|
|
254
265
|
enabled: true,
|
|
255
266
|
configPath,
|
|
256
|
-
serverCommand,
|
|
267
|
+
serverCommand: server.command,
|
|
268
|
+
serverArgs: server.args,
|
|
257
269
|
dryRun: input.dryRun,
|
|
258
270
|
configUpdated: changed || input.force,
|
|
259
271
|
backupPath,
|
|
260
272
|
};
|
|
261
273
|
}
|
|
262
|
-
function patchHermesMcpConfig(original, serverCommand) {
|
|
263
|
-
if (/^\s+cogmem\s*:/m.test(original)
|
|
274
|
+
function patchHermesMcpConfig(original, serverCommand, serverArgs) {
|
|
275
|
+
if (/^\s+cogmem\s*:/m.test(original)) {
|
|
264
276
|
return patchExistingHermesCogmemConfig(original);
|
|
265
277
|
}
|
|
266
278
|
const lines = original.replace(/\r\n/g, '\n').split('\n');
|
|
267
279
|
const serverBlock = [
|
|
268
280
|
' cogmem:',
|
|
269
281
|
` command: "${serverCommand}"`,
|
|
270
|
-
|
|
282
|
+
` args: ${JSON.stringify(serverArgs)}`,
|
|
271
283
|
' enabled: true',
|
|
272
284
|
' tools:',
|
|
273
285
|
' include:',
|
|
@@ -366,7 +378,7 @@ function printHuman(result) {
|
|
|
366
378
|
console.log('');
|
|
367
379
|
console.log('Hermes MCP integration:');
|
|
368
380
|
console.log(` config: ${result.hermesMcp.configPath}`);
|
|
369
|
-
console.log(` command: ${result.hermesMcp.serverCommand}
|
|
381
|
+
console.log(` command: ${result.hermesMcp.serverCommand} ${result.hermesMcp.serverArgs.join(' ')}`.trimEnd());
|
|
370
382
|
if (result.hermesMcp.backupPath)
|
|
371
383
|
console.log(` backup: ${result.hermesMcp.backupPath}`);
|
|
372
384
|
console.log(' reload: /reload-mcp');
|
|
@@ -152,6 +152,7 @@ function previewSources(input) {
|
|
|
152
152
|
recordsIngested: 0,
|
|
153
153
|
skippedRecords: 0,
|
|
154
154
|
rawRecordsAnchored: 0,
|
|
155
|
+
emptyEpisodesSkipped: 0,
|
|
155
156
|
reindexRaw: false,
|
|
156
157
|
processedSourceIds: [],
|
|
157
158
|
diagnostics,
|
|
@@ -161,6 +162,7 @@ function previewSources(input) {
|
|
|
161
162
|
async function importSources(input) {
|
|
162
163
|
const opened = openKernel(input.args, input.workspaceRoot);
|
|
163
164
|
const importedEpisodeIds = new Set();
|
|
165
|
+
let emptyEpisodesSkipped = 0;
|
|
164
166
|
const processor = new InstalledBatchProcessor({
|
|
165
167
|
cursorStore: opened.kernel.cursorStore,
|
|
166
168
|
ingestBatch: async (items) => {
|
|
@@ -190,7 +192,7 @@ async function importSources(input) {
|
|
|
190
192
|
for (const episodeId of importedEpisodeIds) {
|
|
191
193
|
const episode = opened.kernel.getEpisode(episodeId);
|
|
192
194
|
if (episode?.status !== 'sealed') {
|
|
193
|
-
opened.kernel
|
|
195
|
+
emptyEpisodesSkipped += sealImportedEpisodeIfReady(opened.kernel, episodeId, `${input.agent}_import_batch_boundary`) ? 0 : 1;
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
return {
|
|
@@ -207,6 +209,7 @@ async function importSources(input) {
|
|
|
207
209
|
recordsIngested: summary.recordsIngested,
|
|
208
210
|
skippedRecords: summary.skippedRecords,
|
|
209
211
|
rawRecordsAnchored: summary.recordsIngested,
|
|
212
|
+
emptyEpisodesSkipped,
|
|
210
213
|
reindexRaw: false,
|
|
211
214
|
processedSourceIds: summary.processedSourceIds,
|
|
212
215
|
diagnostics: summary.adapterDiagnostics,
|
|
@@ -238,6 +241,7 @@ async function reindexRawSources(input) {
|
|
|
238
241
|
let rawRecordsAnchored = 0;
|
|
239
242
|
let skippedRecords = 0;
|
|
240
243
|
const importedEpisodeIds = new Set();
|
|
244
|
+
let emptyEpisodesSkipped = 0;
|
|
241
245
|
try {
|
|
242
246
|
for (const source of input.sources) {
|
|
243
247
|
const adapter = adapters.get(source.adapterKind);
|
|
@@ -279,7 +283,7 @@ async function reindexRawSources(input) {
|
|
|
279
283
|
for (const episodeId of importedEpisodeIds) {
|
|
280
284
|
const episode = opened.kernel.getEpisode(episodeId);
|
|
281
285
|
if (episode?.status !== 'sealed') {
|
|
282
|
-
opened.kernel
|
|
286
|
+
emptyEpisodesSkipped += sealImportedEpisodeIfReady(opened.kernel, episodeId, `${input.agent}_reindex_batch_boundary`) ? 0 : 1;
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
return {
|
|
@@ -297,6 +301,7 @@ async function reindexRawSources(input) {
|
|
|
297
301
|
recordsIngested: rawRecordsAnchored,
|
|
298
302
|
skippedRecords,
|
|
299
303
|
rawRecordsAnchored,
|
|
304
|
+
emptyEpisodesSkipped,
|
|
300
305
|
processedSourceIds,
|
|
301
306
|
diagnostics,
|
|
302
307
|
sourceResults,
|
|
@@ -307,6 +312,12 @@ async function reindexRawSources(input) {
|
|
|
307
312
|
opened.kernel.close();
|
|
308
313
|
}
|
|
309
314
|
}
|
|
315
|
+
function sealImportedEpisodeIfReady(kernel, episodeId, reason) {
|
|
316
|
+
if (kernel.listEpisodeEventLinks(episodeId).length === 0)
|
|
317
|
+
return false;
|
|
318
|
+
kernel.sealImportedEpisode(episodeId, { reason });
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
310
321
|
async function recordRawImportedEvidence(kernel, projectId, envelope) {
|
|
311
322
|
const sourceRef = envelope.ingestInput.sourceRefs?.[0];
|
|
312
323
|
const record = envelope.record;
|
|
@@ -483,6 +494,8 @@ function printHumanSummary(result) {
|
|
|
483
494
|
console.log(`records ${action}: ${result.dryRun ? result.recordsWouldIngest : result.recordsIngested}`);
|
|
484
495
|
if (result.rawRecordsAnchored !== undefined)
|
|
485
496
|
console.log(`raw ledger anchors: ${result.rawRecordsAnchored}`);
|
|
497
|
+
if (result.emptyEpisodesSkipped)
|
|
498
|
+
console.log(`empty episodes skipped: ${result.emptyEpisodesSkipped}`);
|
|
486
499
|
console.log(`records skipped: ${result.skippedRecords}`);
|
|
487
500
|
if (result.diagnostics.length > 0) {
|
|
488
501
|
console.log('diagnostics:');
|
package/dist/bin/mcp.js
CHANGED
|
@@ -29,7 +29,8 @@ function stringArg(values, key) {
|
|
|
29
29
|
}
|
|
30
30
|
function usage() {
|
|
31
31
|
return [
|
|
32
|
-
'Usage: cogmem
|
|
32
|
+
'Usage: cogmem mcp [--db <memory.db>|--config <config.toml>] [--cwd <dir>]',
|
|
33
|
+
' cogmem-mcp [--db <memory.db>|--config <config.toml>] [--cwd <dir>]',
|
|
33
34
|
'',
|
|
34
35
|
'Starts a stdio MCP server exposing recall, strategy, episode append/import/status/seal, conditional dream tick/status, memory map, maintenance, and prospective-memory tools.',
|
|
35
36
|
].join('\n');
|
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();
|