@martian-engineering/lossless-claw 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/index.js +19240 -0
- package/docs/configuration.md +15 -5
- package/openclaw.plugin.json +27 -3
- package/package.json +7 -6
- package/skills/lossless-claw/references/config.md +37 -0
- package/index.ts +0 -2
- package/src/assembler.ts +0 -1196
- package/src/compaction.ts +0 -1753
- package/src/db/config.ts +0 -345
- package/src/db/connection.ts +0 -151
- package/src/db/features.ts +0 -61
- package/src/db/migration.ts +0 -868
- package/src/engine.ts +0 -4486
- package/src/estimate-tokens.ts +0 -80
- package/src/expansion-auth.ts +0 -365
- package/src/expansion-policy.ts +0 -303
- package/src/expansion.ts +0 -383
- package/src/integrity.ts +0 -600
- package/src/large-files.ts +0 -546
- package/src/lcm-log.ts +0 -37
- package/src/openclaw-bridge.ts +0 -22
- package/src/plugin/index.ts +0 -2037
- package/src/plugin/lcm-command.ts +0 -1040
- package/src/plugin/lcm-doctor-apply.ts +0 -540
- package/src/plugin/lcm-doctor-cleaners.ts +0 -655
- package/src/plugin/lcm-doctor-shared.ts +0 -210
- package/src/plugin/shared-init.ts +0 -59
- package/src/prune.ts +0 -391
- package/src/retrieval.ts +0 -360
- package/src/session-patterns.ts +0 -23
- package/src/startup-banner-log.ts +0 -49
- package/src/store/compaction-telemetry-store.ts +0 -156
- package/src/store/conversation-store.ts +0 -929
- package/src/store/fts5-sanitize.ts +0 -50
- package/src/store/full-text-fallback.ts +0 -83
- package/src/store/full-text-sort.ts +0 -21
- package/src/store/index.ts +0 -39
- package/src/store/parse-utc-timestamp.ts +0 -25
- package/src/store/summary-store.ts +0 -1519
- package/src/summarize.ts +0 -1508
- package/src/tools/common.ts +0 -53
- package/src/tools/lcm-conversation-scope.ts +0 -127
- package/src/tools/lcm-describe-tool.ts +0 -245
- package/src/tools/lcm-expand-query-tool.ts +0 -1235
- package/src/tools/lcm-expand-tool.delegation.ts +0 -580
- package/src/tools/lcm-expand-tool.ts +0 -453
- package/src/tools/lcm-expansion-recursion-guard.ts +0 -373
- package/src/tools/lcm-grep-tool.ts +0 -228
- package/src/transaction-mutex.ts +0 -136
- package/src/transcript-repair.ts +0 -301
- package/src/types.ts +0 -165
package/docs/configuration.md
CHANGED
|
@@ -16,11 +16,13 @@ Most installations only need to override a handful of keys. If you want a comple
|
|
|
16
16
|
{
|
|
17
17
|
"enabled": true,
|
|
18
18
|
"databasePath": "/Users/alice/.openclaw/lcm.db",
|
|
19
|
+
"largeFilesDir": "/Users/alice/.openclaw/lcm-files",
|
|
19
20
|
"ignoreSessionPatterns": [],
|
|
20
21
|
"statelessSessionPatterns": [],
|
|
21
22
|
"skipStatelessSessions": true,
|
|
22
23
|
"contextThreshold": 0.75,
|
|
23
24
|
"freshTailCount": 64,
|
|
25
|
+
"freshTailMaxTokens": 24000,
|
|
24
26
|
"newSessionRetainDepth": 2,
|
|
25
27
|
"leafMinFanout": 8,
|
|
26
28
|
"condensedMinFanout": 4,
|
|
@@ -42,6 +44,7 @@ Most installations only need to override a handful of keys. If you want a comple
|
|
|
42
44
|
"summaryTimeoutMs": 60000,
|
|
43
45
|
"timezone": "America/Los_Angeles",
|
|
44
46
|
"pruneHeartbeatOk": false,
|
|
47
|
+
"transcriptGcEnabled": false,
|
|
45
48
|
"maxAssemblyTokenBudget": 30000,
|
|
46
49
|
"summaryMaxOverageFactor": 3,
|
|
47
50
|
"customInstructions": "",
|
|
@@ -65,6 +68,7 @@ Notes on the example:
|
|
|
65
68
|
|
|
66
69
|
- Values shown are the runtime defaults when a fixed default exists.
|
|
67
70
|
- `databasePath` shows the expanded default path shape. Use an absolute path in config rather than `~`.
|
|
71
|
+
- `largeFilesDir` shows the expanded default path shape. Both `databasePath` and `largeFilesDir` default to paths under `OPENCLAW_STATE_DIR` (which in turn falls back to `~/.openclaw`).
|
|
68
72
|
- `timezone` has no fixed hardcoded default; at runtime it resolves from `TZ` first, then the system timezone. The example uses `America/Los_Angeles`.
|
|
69
73
|
- `maxAssemblyTokenBudget` has no default. The example uses `30000` as a realistic cap for a 32k-class model.
|
|
70
74
|
- `databasePath` is the preferred key. `dbPath` is an accepted alias.
|
|
@@ -97,14 +101,18 @@ openclaw plugins install --link /path/to/lossless-claw
|
|
|
97
101
|
| Key | Type | Default | Env override | Purpose |
|
|
98
102
|
| --- | --- | --- | --- | --- |
|
|
99
103
|
| `enabled` | `boolean` | `true` | `LCM_ENABLED` | Enables or disables lossless-claw without uninstalling it. |
|
|
100
|
-
| `databasePath` | `string` | `${
|
|
104
|
+
| `databasePath` | `string` | `${OPENCLAW_STATE_DIR}/lcm.db` | `LCM_DATABASE_PATH` | Preferred path for the SQLite database. |
|
|
101
105
|
| `dbPath` | `string` | alias of `databasePath` | `LCM_DATABASE_PATH` | Legacy alias for `databasePath`. Prefer `databasePath` in new config. |
|
|
106
|
+
| `largeFilesDir` | `string` | `${OPENCLAW_STATE_DIR}/lcm-files` | `LCM_LARGE_FILES_DIR` | Directory where large-file text payloads are persisted. Automatically follows the active state directory. |
|
|
102
107
|
| `ignoreSessionPatterns` | `string[]` | `[]` | `LCM_IGNORE_SESSION_PATTERNS` | Session-key glob patterns that skip LCM entirely. |
|
|
103
108
|
| `statelessSessionPatterns` | `string[]` | `[]` | `LCM_STATELESS_SESSION_PATTERNS` | Session-key glob patterns that may read from LCM but never write to it. |
|
|
104
109
|
| `skipStatelessSessions` | `boolean` | `true` | `LCM_SKIP_STATELESS_SESSIONS` | Enforces `statelessSessionPatterns` when enabled. |
|
|
105
110
|
| `newSessionRetainDepth` | `integer` | `2` | `LCM_NEW_SESSION_RETAIN_DEPTH` | Controls what survives `/new`. `-1` keeps all context, `0` keeps summaries only, higher values keep only deeper summaries. |
|
|
106
111
|
| `timezone` | `string` | `TZ` or system timezone | `TZ` | IANA timezone used for timestamp rendering in summaries. |
|
|
107
112
|
| `pruneHeartbeatOk` | `boolean` | `false` | `LCM_PRUNE_HEARTBEAT_OK` | Retroactively removes `HEARTBEAT_OK` turn cycles from persisted storage. |
|
|
113
|
+
| `transcriptGcEnabled` | `boolean` | `false` | `LCM_TRANSCRIPT_GC_ENABLED` | Enables transcript rewrite GC during `maintain()`; disabled by default so transcript rewrites stay opt-in. |
|
|
114
|
+
|
|
115
|
+
> **Multi-profile note:** `OPENCLAW_STATE_DIR` (set by the host OpenClaw gateway) controls where state is stored. When two gateways run on the same host (e.g. separate bot personas), each gateway sets its own `OPENCLAW_STATE_DIR` and lossless-claw automatically uses that directory for the database, large-file payloads, auth-profile lookups, and legacy secrets — no per-profile plugin config is needed.
|
|
108
116
|
|
|
109
117
|
### Compaction thresholds and summary sizing
|
|
110
118
|
|
|
@@ -112,6 +120,7 @@ openclaw plugins install --link /path/to/lossless-claw
|
|
|
112
120
|
| --- | --- | --- | --- | --- |
|
|
113
121
|
| `contextThreshold` | `number` | `0.75` | `LCM_CONTEXT_THRESHOLD` | Fraction of the active model context window that triggers compaction. |
|
|
114
122
|
| `freshTailCount` | `integer` | `64` | `LCM_FRESH_TAIL_COUNT` | Number of newest messages always kept raw. |
|
|
123
|
+
| `freshTailMaxTokens` | `integer` | unset | `LCM_FRESH_TAIL_MAX_TOKENS` | Optional token cap for the protected fresh tail. The newest message is always preserved even if it exceeds the cap. |
|
|
115
124
|
| `leafMinFanout` | `integer` | `8` | `LCM_LEAF_MIN_FANOUT` | Minimum number of raw messages required before a leaf pass runs. |
|
|
116
125
|
| `condensedMinFanout` | `integer` | `4` | `LCM_CONDENSED_MIN_FANOUT` | Number of same-depth summaries needed before condensation is attempted. |
|
|
117
126
|
| `condensedMinFanoutHard` | `integer` | `2` | `LCM_CONDENSED_MIN_FANOUT_HARD` | Hard floor for condensation grouping during maintenance and repair flows. |
|
|
@@ -237,16 +246,17 @@ These settings are not part of `plugins.entries.lossless-claw.config`, but they
|
|
|
237
246
|
|
|
238
247
|
| Env var | Default | Purpose |
|
|
239
248
|
| --- | --- | --- |
|
|
249
|
+
| `OPENCLAW_STATE_DIR` | `~/.openclaw` | Active state directory for the OpenClaw gateway. When set, all path defaults (database, large files, auth profiles, secrets) resolve relative to this directory instead of `~/.openclaw`. Set automatically by OpenClaw for non-default profiles. |
|
|
240
250
|
| `LCM_TUI_CONVERSATION_WINDOW_SIZE` | `200` | Number of messages `lcm-tui` loads per keyset-paged conversation window. |
|
|
241
251
|
|
|
242
252
|
## Database operations
|
|
243
253
|
|
|
244
|
-
The SQLite database lives at `databasePath` or `LCM_DATABASE_PATH`. The default path is `${
|
|
254
|
+
The SQLite database lives at `databasePath` or `LCM_DATABASE_PATH`. The default path is `${OPENCLAW_STATE_DIR}/lcm.db` (resolves to `~/.openclaw/lcm.db` when `OPENCLAW_STATE_DIR` is not set).
|
|
245
255
|
|
|
246
256
|
Inspect it with:
|
|
247
257
|
|
|
248
258
|
```bash
|
|
249
|
-
sqlite3
|
|
259
|
+
sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db"
|
|
250
260
|
|
|
251
261
|
SELECT COUNT(*) FROM conversations;
|
|
252
262
|
SELECT * FROM context_items WHERE conversation_id = 1 ORDER BY ordinal;
|
|
@@ -257,8 +267,8 @@ SELECT summary_id, depth, token_count FROM summaries ORDER BY token_count DESC L
|
|
|
257
267
|
Back it up with:
|
|
258
268
|
|
|
259
269
|
```bash
|
|
260
|
-
cp
|
|
261
|
-
sqlite3
|
|
270
|
+
cp "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"
|
|
271
|
+
sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" ".backup ${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"
|
|
262
272
|
```
|
|
263
273
|
|
|
264
274
|
## Disabling lossless-claw
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "lossless-claw",
|
|
3
|
+
"kind": "context-engine",
|
|
3
4
|
"skills": [
|
|
4
5
|
"skills/lossless-claw"
|
|
5
6
|
],
|
|
@@ -20,6 +21,10 @@
|
|
|
20
21
|
"label": "Fresh Tail Count",
|
|
21
22
|
"help": "Number of recent messages protected from compaction"
|
|
22
23
|
},
|
|
24
|
+
"freshTailMaxTokens": {
|
|
25
|
+
"label": "Fresh Tail Max Tokens",
|
|
26
|
+
"help": "Optional token cap for the protected fresh tail; the newest message is always preserved"
|
|
27
|
+
},
|
|
23
28
|
"leafChunkTokens": {
|
|
24
29
|
"label": "Leaf Chunk Tokens",
|
|
25
30
|
"help": "Maximum source tokens per leaf compaction chunk before summarization"
|
|
@@ -58,11 +63,15 @@
|
|
|
58
63
|
},
|
|
59
64
|
"dbPath": {
|
|
60
65
|
"label": "Database Path",
|
|
61
|
-
"help": "Path to LCM SQLite database (default: ~/.openclaw/lcm.db)"
|
|
66
|
+
"help": "Path to LCM SQLite database (default: <OPENCLAW_STATE_DIR>/lcm.db; falls back to ~/.openclaw/lcm.db)"
|
|
62
67
|
},
|
|
63
68
|
"databasePath": {
|
|
64
69
|
"label": "Database Path",
|
|
65
|
-
"help": "Path to LCM SQLite database (preferred key; alias of dbPath)"
|
|
70
|
+
"help": "Path to LCM SQLite database (preferred key; alias of dbPath, default: <OPENCLAW_STATE_DIR>/lcm.db)"
|
|
71
|
+
},
|
|
72
|
+
"largeFilesDir": {
|
|
73
|
+
"label": "Large Files Directory",
|
|
74
|
+
"help": "Directory for persisting large-file text payloads (default: <stateDir>/lcm-files). Uses OPENCLAW_STATE_DIR when set."
|
|
66
75
|
},
|
|
67
76
|
"ignoreSessionPatterns": {
|
|
68
77
|
"label": "Ignored Sessions",
|
|
@@ -168,6 +177,10 @@
|
|
|
168
177
|
"label": "Prune HEARTBEAT_OK",
|
|
169
178
|
"help": "Retroactively delete HEARTBEAT_OK turn cycles from LCM storage"
|
|
170
179
|
},
|
|
180
|
+
"transcriptGcEnabled": {
|
|
181
|
+
"label": "Transcript GC",
|
|
182
|
+
"help": "Enable transcript rewrite GC during maintain(); disabled by default"
|
|
183
|
+
},
|
|
171
184
|
"fallbackProviders": {
|
|
172
185
|
"label": "Fallback Providers",
|
|
173
186
|
"help": "Explicit fallback provider/model pairs for compaction summarization (e.g., [{\"provider\": \"anthropic\", \"model\": \"claude-haiku-4-5\"}])"
|
|
@@ -193,6 +206,10 @@
|
|
|
193
206
|
"type": "integer",
|
|
194
207
|
"minimum": 1
|
|
195
208
|
},
|
|
209
|
+
"freshTailMaxTokens": {
|
|
210
|
+
"type": "integer",
|
|
211
|
+
"minimum": 0
|
|
212
|
+
},
|
|
196
213
|
"leafChunkTokens": {
|
|
197
214
|
"type": "integer",
|
|
198
215
|
"minimum": 1
|
|
@@ -341,8 +358,15 @@
|
|
|
341
358
|
"pruneHeartbeatOk": {
|
|
342
359
|
"type": "boolean"
|
|
343
360
|
},
|
|
361
|
+
"transcriptGcEnabled": {
|
|
362
|
+
"type": "boolean"
|
|
363
|
+
},
|
|
344
364
|
"databasePath": {
|
|
345
|
-
"description": "Path to LCM SQLite database (alias
|
|
365
|
+
"description": "Path to LCM SQLite database (preferred key; alias of dbPath, default: <OPENCLAW_STATE_DIR>/lcm.db)",
|
|
366
|
+
"type": "string"
|
|
367
|
+
},
|
|
368
|
+
"largeFilesDir": {
|
|
369
|
+
"description": "Directory for persisting large-file text payloads (default: <OPENCLAW_STATE_DIR>/lcm-files)",
|
|
346
370
|
"type": "string"
|
|
347
371
|
},
|
|
348
372
|
"fallbackProviders": {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martian-engineering/lossless-claw",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Lossless Context Management plugin for OpenClaw — DAG-based conversation summarization with incremental compaction",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "index.
|
|
6
|
+
"main": "dist/index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "Josh Lehman <josh@martian.engineering>",
|
|
9
9
|
"keywords": [
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"dag"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
+
"build": "esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@mariozechner/*\"",
|
|
19
20
|
"changeset": "changeset",
|
|
20
|
-
"release:verify": "npm test && npm pack --dry-run",
|
|
21
|
+
"release:verify": "npm run build && npm test && npm pack --dry-run",
|
|
21
22
|
"test": "vitest run --dir test",
|
|
22
23
|
"version-packages": "changeset version"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
25
|
-
"
|
|
26
|
-
"src/**/*.ts",
|
|
26
|
+
"dist/",
|
|
27
27
|
"skills/",
|
|
28
28
|
"openclaw.plugin.json",
|
|
29
29
|
"docs/",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@changesets/changelog-github": "^0.6.0",
|
|
40
40
|
"@changesets/cli": "^2.30.0",
|
|
41
|
+
"esbuild": "^0.28.0",
|
|
41
42
|
"typescript": "^5.7.0",
|
|
42
43
|
"vitest": "^3.0.0"
|
|
43
44
|
},
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
},
|
|
50
51
|
"openclaw": {
|
|
51
52
|
"extensions": [
|
|
52
|
-
"./index.
|
|
53
|
+
"./dist/index.js"
|
|
53
54
|
]
|
|
54
55
|
},
|
|
55
56
|
"repository": {
|
|
@@ -43,6 +43,20 @@ Good starting range:
|
|
|
43
43
|
|
|
44
44
|
- `32` to `64`
|
|
45
45
|
|
|
46
|
+
### `freshTailMaxTokens`
|
|
47
|
+
|
|
48
|
+
Optional token cap for the protected fresh tail.
|
|
49
|
+
|
|
50
|
+
Why it matters:
|
|
51
|
+
|
|
52
|
+
- Prevents a few huge tool results from making the "fresh" suffix effectively uncompactable.
|
|
53
|
+
- Still preserves the newest message even if that single message exceeds the cap.
|
|
54
|
+
|
|
55
|
+
Good starting range:
|
|
56
|
+
|
|
57
|
+
- Leave unset unless large tool outputs are forcing avoidable cost or overflow.
|
|
58
|
+
- Start around `12000` to `32000` when you want a softer, size-aware fresh tail.
|
|
59
|
+
|
|
46
60
|
### `leafChunkTokens`
|
|
47
61
|
|
|
48
62
|
Caps how much raw material gets summarized into one leaf summary.
|
|
@@ -154,6 +168,7 @@ Why it matters:
|
|
|
154
168
|
|
|
155
169
|
- useful for custom deployments, testing, or isolating environments
|
|
156
170
|
- wrong path selection is a common reason operators think LCM is empty or not growing
|
|
171
|
+
- the default resolves to `${OPENCLAW_STATE_DIR}/lcm.db` (falls back to `~/.openclaw/lcm.db`)
|
|
157
172
|
|
|
158
173
|
### `databasePath`
|
|
159
174
|
|
|
@@ -164,6 +179,15 @@ Why it matters:
|
|
|
164
179
|
- this is the documented key new config should use
|
|
165
180
|
- `dbPath` is still accepted for compatibility
|
|
166
181
|
|
|
182
|
+
### `largeFilesDir`
|
|
183
|
+
|
|
184
|
+
Directory for persisting large-file text payloads externalised from the transcript.
|
|
185
|
+
|
|
186
|
+
Why it matters:
|
|
187
|
+
|
|
188
|
+
- defaults to `${OPENCLAW_STATE_DIR}/lcm-files`; on multi-profile hosts each profile stores files in its own state directory automatically
|
|
189
|
+
- override with `LCM_LARGE_FILES_DIR` or set `largeFilesDir` in plugin config when you want an explicit path
|
|
190
|
+
|
|
167
191
|
### `largeFileThresholdTokens`
|
|
168
192
|
|
|
169
193
|
Threshold for externalizing oversized tool/file payloads out of the main transcript into large-file storage.
|
|
@@ -173,6 +197,15 @@ Why it matters:
|
|
|
173
197
|
- lower values externalize more aggressively
|
|
174
198
|
- higher values keep more payload inline but can bloat storage and compaction inputs
|
|
175
199
|
|
|
200
|
+
### `transcriptGcEnabled`
|
|
201
|
+
|
|
202
|
+
Controls whether `maintain()` rewrites transcript entries for already-externalized tool results.
|
|
203
|
+
|
|
204
|
+
Why it matters:
|
|
205
|
+
|
|
206
|
+
- keep this off unless you want transcript GC to mutate the live session file during maintenance
|
|
207
|
+
- the default is `false`
|
|
208
|
+
|
|
176
209
|
## Compaction timing and shape
|
|
177
210
|
|
|
178
211
|
### `contextThreshold`
|
|
@@ -183,6 +216,10 @@ See high-impact settings above.
|
|
|
183
216
|
|
|
184
217
|
See high-impact settings above.
|
|
185
218
|
|
|
219
|
+
### `freshTailMaxTokens`
|
|
220
|
+
|
|
221
|
+
See high-impact settings above.
|
|
222
|
+
|
|
186
223
|
### `leafChunkTokens`
|
|
187
224
|
|
|
188
225
|
See high-impact settings above.
|
package/index.ts
DELETED