@martian-engineering/lossless-claw 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -4
- package/docs/agent-tools.md +7 -1
- package/docs/configuration.md +200 -200
- package/openclaw.plugin.json +123 -0
- package/package.json +1 -1
- package/skills/lossless-claw/references/config.md +135 -3
- package/src/assembler.ts +5 -1
- package/src/compaction.ts +149 -38
- package/src/db/config.ts +102 -4
- package/src/db/connection.ts +20 -2
- package/src/db/migration.ts +57 -0
- package/src/engine.ts +980 -122
- package/src/lcm-log.ts +37 -0
- package/src/plugin/index.ts +407 -74
- package/src/plugin/lcm-command.ts +10 -4
- package/src/plugin/shared-init.ts +59 -0
- package/src/prune.ts +391 -0
- package/src/retrieval.ts +7 -5
- package/src/startup-banner-log.ts +1 -0
- package/src/store/compaction-telemetry-store.ts +156 -0
- package/src/store/conversation-store.ts +6 -1
- package/src/store/fts5-sanitize.ts +25 -4
- package/src/store/full-text-sort.ts +21 -0
- package/src/store/index.ts +8 -0
- package/src/store/summary-store.ts +21 -14
- package/src/summarize.ts +54 -30
- package/src/tools/lcm-describe-tool.ts +9 -4
- package/src/tools/lcm-expand-query-tool.ts +11 -6
- package/src/tools/lcm-expand-tool.ts +9 -4
- package/src/tools/lcm-grep-tool.ts +22 -8
- package/src/types.ts +1 -0
package/README.md
CHANGED
|
@@ -30,11 +30,23 @@ Nothing is lost. Raw messages stay in the database. Summaries link back to their
|
|
|
30
30
|
|
|
31
31
|
## Commands And Skill
|
|
32
32
|
|
|
33
|
-
The plugin now ships a bundled `lossless-claw` skill plus a small native command
|
|
33
|
+
The plugin now ships a bundled `lossless-claw` skill plus a small plugin command surface for supported OpenClaw chat/native command providers:
|
|
34
34
|
|
|
35
35
|
- `/lcm` shows version, enablement/selection state, DB path and size, summary counts, and summary-health status
|
|
36
36
|
- `/lcm doctor` scans for broken or truncated summaries
|
|
37
|
-
- `/lossless` is an alias for `/lcm` on native command surfaces
|
|
37
|
+
- `/lossless` is an alias for `/lcm` on supported native command surfaces
|
|
38
|
+
|
|
39
|
+
These are plugin slash/native commands, not root shell CLI subcommands. Supported examples:
|
|
40
|
+
|
|
41
|
+
- `/lcm`
|
|
42
|
+
- `/lcm doctor`
|
|
43
|
+
- `/lossless`
|
|
44
|
+
|
|
45
|
+
Not currently supported as root CLI commands:
|
|
46
|
+
|
|
47
|
+
- `openclaw lcm`
|
|
48
|
+
- `openclaw lossless`
|
|
49
|
+
- `openclaw /lcm`
|
|
38
50
|
|
|
39
51
|
The bundled skill focuses on configuration, diagnostics, architecture, and recall-tool usage. Its reference set lives under `skills/lossless-claw/references/`.
|
|
40
52
|
|
|
@@ -70,7 +82,7 @@ openclaw plugins install --link /path/to/lossless-claw
|
|
|
70
82
|
|
|
71
83
|
The install command records the plugin, enables it, and applies compatible slot selection (including `contextEngine` when applicable).
|
|
72
84
|
|
|
73
|
-
> **Note:** If your OpenClaw config uses `plugins.allow`,
|
|
85
|
+
> **Note:** If your OpenClaw config uses `plugins.allow`, allowlist the plugin id `lossless-claw` plus any other active plugins you rely on. Do not add command tokens or aliases like `lossless` or `/lcm` to `plugins.allow`; that setting only accepts plugin ids. In some setups, narrowing the allowlist can prevent plugin-backed integrations from loading, even if `lossless-claw` itself is installed correctly. Restart the gateway after plugin config changes.
|
|
74
86
|
|
|
75
87
|
### Configure OpenClaw
|
|
76
88
|
|
|
@@ -246,7 +258,7 @@ Lossless-claw distinguishes OpenClaw's two session-reset commands:
|
|
|
246
258
|
- `2`: keep d2+ summaries; recommended default
|
|
247
259
|
- `3+`: keep only deeper, more abstract summaries
|
|
248
260
|
|
|
249
|
-
Lossless-claw
|
|
261
|
+
Lossless-claw applies `/new` pruning through `before_reset` and uses `session_end` to catch transcript rollovers such as `/reset`, idle or daily session rotation, compaction session replacement, and deletions. User-facing confirmation text after `/new` or `/reset` must still be emitted by OpenClaw's command handlers.
|
|
250
262
|
|
|
251
263
|
Use `ignoreSessionPatterns` or `LCM_IGNORE_SESSION_PATTERNS` to keep low-value sessions completely out of LCM. Matching sessions do not create conversations, do not store messages, and do not participate in compaction or delegated expansion grants.
|
|
252
264
|
|
package/docs/agent-tools.md
CHANGED
|
@@ -32,6 +32,8 @@ Summaries are lossy by design. The "Expand for details about:" footer at the end
|
|
|
32
32
|
|
|
33
33
|
Search across messages and/or summaries using regex or full-text search.
|
|
34
34
|
|
|
35
|
+
Use `mode: "full_text"` for keyword or topical recall. Wrap exact multi-word phrases in quotes to preserve phrase matching. Keep the default `sort: "recency"` for recent events, switch to `sort: "relevance"` when looking for the best older match on a topic, and use `sort: "hybrid"` when you want relevance without giving up recency entirely.
|
|
36
|
+
|
|
35
37
|
**Parameters:**
|
|
36
38
|
|
|
37
39
|
| Param | Type | Required | Default | Description |
|
|
@@ -44,6 +46,7 @@ Search across messages and/or summaries using regex or full-text search.
|
|
|
44
46
|
| `since` | string | | — | ISO timestamp lower bound |
|
|
45
47
|
| `before` | string | | — | ISO timestamp upper bound |
|
|
46
48
|
| `limit` | number | | 50 | Max results (1–200) |
|
|
49
|
+
| `sort` | string | | `"recency"` | `"recency"`, `"relevance"`, or `"hybrid"` for full-text ranking |
|
|
47
50
|
|
|
48
51
|
**Returns:** Array of matches with:
|
|
49
52
|
- `id` — Message or summary ID
|
|
@@ -59,6 +62,9 @@ Search across messages and/or summaries using regex or full-text search.
|
|
|
59
62
|
# Full-text search across all conversations
|
|
60
63
|
lcm_grep(pattern: "database migration", mode: "full_text", allConversations: true)
|
|
61
64
|
|
|
65
|
+
# Older-topic recall ranked by FTS relevance
|
|
66
|
+
lcm_grep(pattern: "\"error handling\" retries", mode: "full_text", sort: "relevance")
|
|
67
|
+
|
|
62
68
|
# Regex search in summaries only
|
|
63
69
|
lcm_grep(pattern: "config\\.threshold.*0\\.[0-9]+", scope: "summaries")
|
|
64
70
|
|
|
@@ -167,7 +173,7 @@ Add instructions to your agent's system prompt so it knows when to use LCM tools
|
|
|
167
173
|
## Memory & Context
|
|
168
174
|
|
|
169
175
|
Use LCM tools for recall:
|
|
170
|
-
1. `lcm_grep` — Search all conversations by keyword/regex
|
|
176
|
+
1. `lcm_grep` — Search all conversations by keyword/regex. Prefer `mode: "full_text"` for topic recall, quote exact phrases, use `sort: "relevance"` for older-topic lookups, and `sort: "hybrid"` when recency should still matter.
|
|
171
177
|
2. `lcm_describe` — Inspect a specific summary (cheap, no sub-agent)
|
|
172
178
|
3. `lcm_expand_query` — Deep recall with sub-agent expansion
|
|
173
179
|
|
package/docs/configuration.md
CHANGED
|
@@ -1,272 +1,274 @@
|
|
|
1
|
-
# Configuration
|
|
1
|
+
# Configuration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lossless-claw reads plugin configuration from `plugins.entries.lossless-claw.config`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Configuration precedence is:
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
1. Environment variables
|
|
8
|
+
2. `plugins.entries.lossless-claw.config`
|
|
9
|
+
3. Built-in defaults from [`src/db/config.ts`](../src/db/config.ts)
|
|
10
10
|
|
|
11
|
-
If you
|
|
11
|
+
Most installations only need to override a handful of keys. If you want a complete starting point, use the full example below and then delete entries you do not need.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
## Complete `plugins.entries.lossless-claw.config` example
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"enabled": true,
|
|
18
|
+
"databasePath": "/Users/alice/.openclaw/lcm.db",
|
|
19
|
+
"ignoreSessionPatterns": [],
|
|
20
|
+
"statelessSessionPatterns": [],
|
|
21
|
+
"skipStatelessSessions": true,
|
|
22
|
+
"contextThreshold": 0.75,
|
|
23
|
+
"freshTailCount": 64,
|
|
24
|
+
"newSessionRetainDepth": 2,
|
|
25
|
+
"leafMinFanout": 8,
|
|
26
|
+
"condensedMinFanout": 4,
|
|
27
|
+
"condensedMinFanoutHard": 2,
|
|
28
|
+
"incrementalMaxDepth": 1,
|
|
29
|
+
"leafChunkTokens": 20000,
|
|
30
|
+
"bootstrapMaxTokens": 6000,
|
|
31
|
+
"leafTargetTokens": 2400,
|
|
32
|
+
"condensedTargetTokens": 2000,
|
|
33
|
+
"maxExpandTokens": 4000,
|
|
34
|
+
"largeFileThresholdTokens": 25000,
|
|
35
|
+
"summaryProvider": "",
|
|
36
|
+
"summaryModel": "",
|
|
37
|
+
"largeFileSummaryProvider": "",
|
|
38
|
+
"largeFileSummaryModel": "",
|
|
39
|
+
"expansionProvider": "",
|
|
40
|
+
"expansionModel": "",
|
|
41
|
+
"delegationTimeoutMs": 120000,
|
|
42
|
+
"summaryTimeoutMs": 60000,
|
|
43
|
+
"timezone": "America/Los_Angeles",
|
|
44
|
+
"pruneHeartbeatOk": false,
|
|
45
|
+
"maxAssemblyTokenBudget": 30000,
|
|
46
|
+
"summaryMaxOverageFactor": 3,
|
|
47
|
+
"customInstructions": "",
|
|
48
|
+
"circuitBreakerThreshold": 5,
|
|
49
|
+
"circuitBreakerCooldownMs": 1800000,
|
|
50
|
+
"fallbackProviders": [],
|
|
51
|
+
"cacheAwareCompaction": {
|
|
52
|
+
"enabled": true,
|
|
53
|
+
"maxColdCacheCatchupPasses": 2,
|
|
54
|
+
"hotCachePressureFactor": 4,
|
|
55
|
+
"hotCacheBudgetHeadroomRatio": 0.2
|
|
56
|
+
},
|
|
57
|
+
"dynamicLeafChunkTokens": {
|
|
58
|
+
"enabled": true,
|
|
59
|
+
"max": 40000
|
|
60
|
+
}
|
|
61
|
+
}
|
|
15
62
|
```
|
|
16
63
|
|
|
17
|
-
|
|
64
|
+
Notes on the example:
|
|
18
65
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
66
|
+
- Values shown are the runtime defaults when a fixed default exists.
|
|
67
|
+
- `databasePath` shows the expanded default path shape. Use an absolute path in config rather than `~`.
|
|
68
|
+
- `timezone` has no fixed hardcoded default; at runtime it resolves from `TZ` first, then the system timezone. The example uses `America/Los_Angeles`.
|
|
69
|
+
- `maxAssemblyTokenBudget` has no default. The example uses `30000` as a realistic cap for a 32k-class model.
|
|
70
|
+
- `databasePath` is the preferred key. `dbPath` is an accepted alias.
|
|
71
|
+
- `largeFileThresholdTokens` is the preferred key. `largeFileTokenThreshold` is an accepted alias.
|
|
22
72
|
|
|
23
|
-
|
|
73
|
+
## Install and enable
|
|
24
74
|
|
|
25
|
-
|
|
75
|
+
Install with OpenClaw's plugin installer:
|
|
26
76
|
|
|
27
77
|
```bash
|
|
28
|
-
|
|
29
|
-
export LCM_NEW_SESSION_RETAIN_DEPTH=2
|
|
30
|
-
export LCM_INCREMENTAL_MAX_DEPTH=-1
|
|
78
|
+
openclaw plugins install @martian-engineering/lossless-claw
|
|
31
79
|
```
|
|
32
80
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
## Tuning guide
|
|
36
|
-
|
|
37
|
-
### Context threshold
|
|
38
|
-
|
|
39
|
-
`LCM_CONTEXT_THRESHOLD` (default `0.75`) controls when compaction triggers as a fraction of the model's context window.
|
|
40
|
-
|
|
41
|
-
- **Lower values** (e.g., 0.5) trigger compaction earlier, keeping context smaller but doing more LLM calls for summarization.
|
|
42
|
-
- **Higher values** (e.g., 0.85) let conversations grow longer before compacting, reducing summarization cost but risking overflow with large model responses.
|
|
43
|
-
|
|
44
|
-
For most use cases, 0.75 is a good balance.
|
|
45
|
-
|
|
46
|
-
### Fresh tail count
|
|
47
|
-
|
|
48
|
-
`LCM_FRESH_TAIL_COUNT` (default `32`) is the number of most recent messages that are never compacted. These raw messages give the model immediate conversational continuity.
|
|
49
|
-
|
|
50
|
-
- **Smaller values** (e.g., 8–16) save context space for summaries but may lose recent nuance.
|
|
51
|
-
- **Larger values** (e.g., 32–64) give better continuity at the cost of a larger mandatory context floor.
|
|
52
|
-
|
|
53
|
-
For coding conversations with tool calls (which generate many messages per logical turn), 32 is recommended.
|
|
54
|
-
|
|
55
|
-
### /new retain depth
|
|
56
|
-
|
|
57
|
-
`LCM_NEW_SESSION_RETAIN_DEPTH` (default `2`) controls what survives OpenClaw's `/new` command.
|
|
58
|
-
|
|
59
|
-
- `-1` keeps all existing context items, making `/new` a transcript-only reset from lossless-claw's perspective.
|
|
60
|
-
- `0` drops only fresh-tail message items and keeps all summaries.
|
|
61
|
-
- `1` drops d0 summaries and keeps d1+.
|
|
62
|
-
- `2` drops d0 and d1 summaries, keeping d2+ project-arc context. This is the recommended default.
|
|
63
|
-
- `3+` keeps only deeper, more abstract summaries.
|
|
64
|
-
|
|
65
|
-
`/new` never deletes the summaries themselves. It only prunes `context_items`, so the summary DAG remains available for later retrieval and expansion.
|
|
66
|
-
|
|
67
|
-
### Leaf fanout
|
|
68
|
-
|
|
69
|
-
`LCM_LEAF_MIN_FANOUT` (default `8`) is the minimum number of raw messages that must be available outside the fresh tail before a leaf pass runs.
|
|
70
|
-
|
|
71
|
-
- Lower values create summaries more frequently (more, smaller summaries).
|
|
72
|
-
- Higher values create larger, more comprehensive summaries less often.
|
|
73
|
-
|
|
74
|
-
### Condensed fanout
|
|
75
|
-
|
|
76
|
-
`LCM_CONDENSED_MIN_FANOUT` (default `4`) controls how many same-depth summaries accumulate before they're condensed into a higher-level summary.
|
|
77
|
-
|
|
78
|
-
- Lower values create deeper DAGs with more levels of abstraction.
|
|
79
|
-
- Higher values keep the DAG shallower but with more nodes at each level.
|
|
80
|
-
|
|
81
|
-
### Incremental max depth
|
|
82
|
-
|
|
83
|
-
`LCM_INCREMENTAL_MAX_DEPTH` (default `0`) controls whether condensation happens automatically after leaf passes.
|
|
84
|
-
|
|
85
|
-
- **0** — Only leaf summaries are created incrementally. Condensation only happens during manual `/compact` or overflow.
|
|
86
|
-
- **1** — After each leaf pass, attempt to condense d0 summaries into d1.
|
|
87
|
-
- **2+** — Deeper automatic condensation up to the specified depth.
|
|
88
|
-
- **-1** — Unlimited depth. Condensation cascades as deep as needed after each leaf pass. Recommended for long-running sessions.
|
|
89
|
-
|
|
90
|
-
### Summary target tokens
|
|
91
|
-
|
|
92
|
-
`LCM_LEAF_TARGET_TOKENS` (default `1200`) and `LCM_CONDENSED_TARGET_TOKENS` (default `2000`) control the target size of generated summaries.
|
|
93
|
-
|
|
94
|
-
- Larger targets preserve more detail but consume more context space.
|
|
95
|
-
- Smaller targets are more aggressive, losing detail faster.
|
|
96
|
-
|
|
97
|
-
The actual summary size depends on the LLM's output; these values are guidelines passed in the prompt's token target instruction.
|
|
98
|
-
|
|
99
|
-
### Leaf chunk tokens
|
|
100
|
-
|
|
101
|
-
`LCM_LEAF_CHUNK_TOKENS` (default `20000`) caps the amount of source material per leaf compaction pass.
|
|
102
|
-
|
|
103
|
-
- Larger chunks create more comprehensive summaries from more material.
|
|
104
|
-
- Smaller chunks create summaries more frequently from less material.
|
|
105
|
-
- This also affects the condensed minimum input threshold (10% of this value).
|
|
106
|
-
|
|
107
|
-
### Maximum assembly token budget
|
|
108
|
-
|
|
109
|
-
`LCM_MAX_ASSEMBLY_TOKEN_BUDGET` (default: none) caps the token budget used for context assembly and compaction threshold evaluation. When set, this takes precedence over both the 128k fallback and runtime-provided budgets.
|
|
110
|
-
|
|
111
|
-
Set this if you're using a model with a smaller context window:
|
|
81
|
+
If you are running from a local OpenClaw checkout:
|
|
112
82
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
### Summary size cap
|
|
118
|
-
|
|
119
|
-
`LCM_SUMMARY_MAX_OVERAGE_FACTOR` (default: `3`) controls the hard ceiling on summary sizes relative to the target tokens (`leafTargetTokens` for leaf summaries, `condensedTargetTokens` for condensed summaries).
|
|
120
|
-
|
|
121
|
-
If a summary exceeds `overage_factor * target_tokens`, it is deterministically truncated. A warning is logged when any summary exceeds `1.5 * target_tokens`.
|
|
122
|
-
|
|
123
|
-
- **Lower values** (e.g., 2) enforce tighter summaries but may truncate more often with weaker summarizer models.
|
|
124
|
-
- **Higher values** (e.g., 5) allow more LLM flexibility but risk storing oversized summaries.
|
|
125
|
-
|
|
126
|
-
## Model selection
|
|
83
|
+
```bash
|
|
84
|
+
pnpm openclaw plugins install @martian-engineering/lossless-claw
|
|
85
|
+
```
|
|
127
86
|
|
|
128
|
-
|
|
87
|
+
For local plugin development, link a working copy:
|
|
129
88
|
|
|
130
89
|
```bash
|
|
131
|
-
|
|
132
|
-
export LCM_SUMMARY_MODEL=anthropic/claude-sonnet-4-20250514
|
|
133
|
-
export LCM_SUMMARY_PROVIDER=anthropic
|
|
134
|
-
export LCM_SUMMARY_BASE_URL=https://api.anthropic.com
|
|
90
|
+
openclaw plugins install --link /path/to/lossless-claw
|
|
135
91
|
```
|
|
136
92
|
|
|
137
|
-
|
|
93
|
+
## Reference
|
|
94
|
+
|
|
95
|
+
### Core storage and session behavior
|
|
96
|
+
|
|
97
|
+
| Key | Type | Default | Env override | Purpose |
|
|
98
|
+
| --- | --- | --- | --- | --- |
|
|
99
|
+
| `enabled` | `boolean` | `true` | `LCM_ENABLED` | Enables or disables lossless-claw without uninstalling it. |
|
|
100
|
+
| `databasePath` | `string` | `${HOME}/.openclaw/lcm.db` | `LCM_DATABASE_PATH` | Preferred path for the SQLite database. |
|
|
101
|
+
| `dbPath` | `string` | alias of `databasePath` | `LCM_DATABASE_PATH` | Legacy alias for `databasePath`. Prefer `databasePath` in new config. |
|
|
102
|
+
| `ignoreSessionPatterns` | `string[]` | `[]` | `LCM_IGNORE_SESSION_PATTERNS` | Session-key glob patterns that skip LCM entirely. |
|
|
103
|
+
| `statelessSessionPatterns` | `string[]` | `[]` | `LCM_STATELESS_SESSION_PATTERNS` | Session-key glob patterns that may read from LCM but never write to it. |
|
|
104
|
+
| `skipStatelessSessions` | `boolean` | `true` | `LCM_SKIP_STATELESS_SESSIONS` | Enforces `statelessSessionPatterns` when enabled. |
|
|
105
|
+
| `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
|
+
| `timezone` | `string` | `TZ` or system timezone | `TZ` | IANA timezone used for timestamp rendering in summaries. |
|
|
107
|
+
| `pruneHeartbeatOk` | `boolean` | `false` | `LCM_PRUNE_HEARTBEAT_OK` | Retroactively removes `HEARTBEAT_OK` turn cycles from persisted storage. |
|
|
138
108
|
|
|
139
|
-
|
|
109
|
+
### Compaction thresholds and summary sizing
|
|
140
110
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
111
|
+
| Key | Type | Default | Env override | Purpose |
|
|
112
|
+
| --- | --- | --- | --- | --- |
|
|
113
|
+
| `contextThreshold` | `number` | `0.75` | `LCM_CONTEXT_THRESHOLD` | Fraction of the active model context window that triggers compaction. |
|
|
114
|
+
| `freshTailCount` | `integer` | `64` | `LCM_FRESH_TAIL_COUNT` | Number of newest messages always kept raw. |
|
|
115
|
+
| `leafMinFanout` | `integer` | `8` | `LCM_LEAF_MIN_FANOUT` | Minimum number of raw messages required before a leaf pass runs. |
|
|
116
|
+
| `condensedMinFanout` | `integer` | `4` | `LCM_CONDENSED_MIN_FANOUT` | Number of same-depth summaries needed before condensation is attempted. |
|
|
117
|
+
| `condensedMinFanoutHard` | `integer` | `2` | `LCM_CONDENSED_MIN_FANOUT_HARD` | Hard floor for condensation grouping during maintenance and repair flows. |
|
|
118
|
+
| `incrementalMaxDepth` | `integer` | `1` | `LCM_INCREMENTAL_MAX_DEPTH` | Maximum automatic condensation depth after leaf compaction. Use `0` for leaf-only and `-1` for unlimited depth. |
|
|
119
|
+
| `leafChunkTokens` | `integer` | `20000` | `LCM_LEAF_CHUNK_TOKENS` | Maximum source-token budget for a leaf compaction chunk. |
|
|
120
|
+
| `bootstrapMaxTokens` | `integer` | `max(6000, floor(leafChunkTokens * 0.3))` | `LCM_BOOTSTRAP_MAX_TOKENS` | Maximum parent-history tokens imported when a new LCM conversation bootstraps. |
|
|
121
|
+
| `leafTargetTokens` | `integer` | `2400` | `LCM_LEAF_TARGET_TOKENS` | Prompt target for leaf summary size. |
|
|
122
|
+
| `condensedTargetTokens` | `integer` | `2000` | `LCM_CONDENSED_TARGET_TOKENS` | Prompt target for condensed summary size. |
|
|
123
|
+
| `summaryMaxOverageFactor` | `number` | `3` | `LCM_SUMMARY_MAX_OVERAGE_FACTOR` | Hard ceiling multiplier before oversized summaries are deterministically truncated. |
|
|
124
|
+
| `largeFileThresholdTokens` | `integer` | `25000` | `LCM_LARGE_FILE_TOKEN_THRESHOLD` | Preferred key for the token threshold that routes text attachments into large-file summarization. |
|
|
125
|
+
| `largeFileTokenThreshold` | `integer` | alias of `largeFileThresholdTokens` | `LCM_LARGE_FILE_TOKEN_THRESHOLD` | Legacy alias accepted by the runtime. Prefer `largeFileThresholdTokens` in new config. |
|
|
126
|
+
| `maxAssemblyTokenBudget` | `integer` | unset | `LCM_MAX_ASSEMBLY_TOKEN_BUDGET` | Optional hard cap for assembly and threshold evaluation, useful with smaller-context models. |
|
|
127
|
+
| `maxExpandTokens` | `integer` | `4000` | `LCM_MAX_EXPAND_TOKENS` | Default token cap for `lcm_expand_query` responses. |
|
|
145
128
|
|
|
146
|
-
|
|
129
|
+
### Model selection, execution, and prompts
|
|
147
130
|
|
|
148
|
-
|
|
131
|
+
| Key | Type | Default | Env override | Purpose |
|
|
132
|
+
| --- | --- | --- | --- | --- |
|
|
133
|
+
| `summaryModel` | `string` | `""` | `LCM_SUMMARY_MODEL` | Summarizer model override. Bare model names reuse the chosen provider; `provider/model` strings force a specific provider. |
|
|
134
|
+
| `summaryProvider` | `string` | `""` | `LCM_SUMMARY_PROVIDER` | Provider hint used only when `summaryModel` is a bare model name. |
|
|
135
|
+
| `largeFileSummaryModel` | `string` | `""` | `LCM_LARGE_FILE_SUMMARY_MODEL` | Large-file summarizer model override. |
|
|
136
|
+
| `largeFileSummaryProvider` | `string` | `""` | `LCM_LARGE_FILE_SUMMARY_PROVIDER` | Large-file summarizer provider hint for bare model names. |
|
|
137
|
+
| `expansionModel` | `string` | `""` | `LCM_EXPANSION_MODEL` | `lcm_expand_query` sub-agent model override. |
|
|
138
|
+
| `expansionProvider` | `string` | `""` | `LCM_EXPANSION_PROVIDER` | `lcm_expand_query` sub-agent provider hint for bare model names. |
|
|
139
|
+
| `delegationTimeoutMs` | `integer` | `120000` | `LCM_DELEGATION_TIMEOUT_MS` | Maximum time to wait for delegated expansion work. |
|
|
140
|
+
| `summaryTimeoutMs` | `integer` | `60000` | `LCM_SUMMARY_TIMEOUT_MS` | Maximum time to wait for one model-backed summarizer call. |
|
|
141
|
+
| `customInstructions` | `string` | `""` | `LCM_CUSTOM_INSTRUCTIONS` | Extra natural-language instructions injected into every summarization prompt. |
|
|
149
142
|
|
|
150
|
-
|
|
143
|
+
### Fallbacks, circuit breaking, and safety rails
|
|
151
144
|
|
|
152
|
-
|
|
145
|
+
| Key | Type | Default | Env override | Purpose |
|
|
146
|
+
| --- | --- | --- | --- | --- |
|
|
147
|
+
| `fallbackProviders` | `Array<{ provider: string; model: string }>` | `[]` | `LCM_FALLBACK_PROVIDERS` | Explicit provider/model fallback chain for compaction summarization. Format for env vars is `provider/model,provider/model`. |
|
|
148
|
+
| `circuitBreakerThreshold` | `integer` | `5` | `LCM_CIRCUIT_BREAKER_THRESHOLD` | Consecutive auth failures before the summarization circuit breaker trips. |
|
|
149
|
+
| `circuitBreakerCooldownMs` | `integer` | `1800000` | `LCM_CIRCUIT_BREAKER_COOLDOWN_MS` | Cooldown before the summarization circuit breaker resets automatically. |
|
|
153
150
|
|
|
154
|
-
###
|
|
151
|
+
### Nested objects
|
|
155
152
|
|
|
156
|
-
|
|
153
|
+
#### `cacheAwareCompaction`
|
|
157
154
|
|
|
158
|
-
|
|
159
|
-
|
|
155
|
+
| Key | Type | Default | Env override | Purpose |
|
|
156
|
+
| --- | --- | --- | --- | --- |
|
|
157
|
+
| `cacheAwareCompaction.enabled` | `boolean` | `true` | `LCM_CACHE_AWARE_COMPACTION_ENABLED` | Defers incremental leaf compaction more aggressively when prompt-cache telemetry indicates a hot cache. |
|
|
158
|
+
| `cacheAwareCompaction.maxColdCacheCatchupPasses` | `integer` | `2` | `LCM_MAX_COLD_CACHE_CATCHUP_PASSES` | Maximum bounded catch-up passes allowed in one maintenance cycle when cache telemetry is cold. |
|
|
159
|
+
| `cacheAwareCompaction.hotCachePressureFactor` | `number` | `4` | `LCM_HOT_CACHE_PRESSURE_FACTOR` | Multiplier applied to the hot-cache leaf trigger before raw-history pressure overrides cache preservation. |
|
|
160
|
+
| `cacheAwareCompaction.hotCacheBudgetHeadroomRatio` | `number` | `0.2` | `LCM_HOT_CACHE_BUDGET_HEADROOM_RATIO` | Minimum fraction of the real token budget that must remain free before hot-cache incremental compaction is skipped entirely. |
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
OpenClaw's command handlers still own the user-facing post-command disclosure text; lossless-claw applies only the underlying storage transition through `before_reset`.
|
|
162
|
+
#### `dynamicLeafChunkTokens`
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
| Key | Type | Default | Env override | Purpose |
|
|
165
|
+
| --- | --- | --- | --- | --- |
|
|
166
|
+
| `dynamicLeafChunkTokens.enabled` | `boolean` | `true` | `LCM_DYNAMIC_LEAF_CHUNK_TOKENS_ENABLED` | Enables dynamic working leaf chunk sizes for busier sessions. |
|
|
167
|
+
| `dynamicLeafChunkTokens.max` | `integer` | `max(leafChunkTokens, floor(leafChunkTokens * 2))` | `LCM_DYNAMIC_LEAF_CHUNK_TOKENS_MAX` | Upper bound for the dynamic working chunk size. With the default `leafChunkTokens=20000`, this resolves to `40000`. |
|
|
165
168
|
|
|
166
|
-
-
|
|
167
|
-
- `*` matches any characters except `:`.
|
|
168
|
-
- `**` matches anything, including `:`.
|
|
169
|
+
### Cache-aware incremental compaction
|
|
169
170
|
|
|
170
|
-
|
|
171
|
+
When cache-aware compaction is enabled:
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
- hot cache stretches the incremental leaf trigger to `dynamicLeafChunkTokens.max`
|
|
174
|
+
- hot cache skips incremental maintenance entirely when the assembled context is still comfortably below the real token budget
|
|
175
|
+
- hot cache also gets a short hysteresis window so one ambiguous turn does not immediately discard a recently healthy cache signal
|
|
176
|
+
- cold cache still allows bounded catch-up passes via `cacheAwareCompaction.maxColdCacheCatchupPasses`
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
When incremental leaf compaction still runs on a hot cache, follow-on condensed passes are suppressed so the maintenance cycle only pays for the leaf pass that was explicitly justified.
|
|
177
179
|
|
|
178
|
-
|
|
180
|
+
## Behavior notes
|
|
179
181
|
|
|
180
|
-
|
|
182
|
+
### Summary model resolution
|
|
181
183
|
|
|
182
|
-
|
|
184
|
+
Compaction summarization resolves candidates in this order:
|
|
183
185
|
|
|
184
|
-
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
-
|
|
188
|
-
|
|
186
|
+
1. `LCM_SUMMARY_MODEL` and `LCM_SUMMARY_PROVIDER`
|
|
187
|
+
2. `plugins.entries.lossless-claw.config.summaryModel` and `summaryProvider`
|
|
188
|
+
3. OpenClaw's default compaction model
|
|
189
|
+
4. Legacy per-call provider and model hints
|
|
190
|
+
5. `fallbackProviders`
|
|
189
191
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
If `summaryModel` already contains a provider prefix such as `anthropic/claude-sonnet-4-20250514`, `summaryProvider` is ignored for that candidate.
|
|
193
|
+
|
|
194
|
+
### Session pattern matching
|
|
195
|
+
|
|
196
|
+
`ignoreSessionPatterns` and `statelessSessionPatterns` use full session keys.
|
|
197
|
+
|
|
198
|
+
- `*` matches any characters except `:`
|
|
199
|
+
- `**` matches anything, including `:`
|
|
196
200
|
|
|
197
|
-
|
|
201
|
+
Example:
|
|
198
202
|
|
|
199
203
|
```json
|
|
200
204
|
{
|
|
201
|
-
"
|
|
202
|
-
"
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
"agent:*:subagent:**",
|
|
210
|
-
"agent:ops:subagent:**"
|
|
211
|
-
],
|
|
212
|
-
"skipStatelessSessions": true
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
205
|
+
"ignoreSessionPatterns": [
|
|
206
|
+
"agent:*:cron:**"
|
|
207
|
+
],
|
|
208
|
+
"statelessSessionPatterns": [
|
|
209
|
+
"agent:*:subagent:**",
|
|
210
|
+
"agent:ops:subagent:**"
|
|
211
|
+
],
|
|
212
|
+
"skipStatelessSessions": true
|
|
217
213
|
}
|
|
218
214
|
```
|
|
219
215
|
|
|
220
|
-
|
|
216
|
+
### `/new` and `/reset`
|
|
221
217
|
|
|
222
|
-
|
|
218
|
+
Lossless-claw treats OpenClaw reset commands differently:
|
|
223
219
|
|
|
224
|
-
-
|
|
225
|
-
-
|
|
220
|
+
- `/new` keeps the active LCM conversation and prunes active context according to `newSessionRetainDepth`
|
|
221
|
+
- `/reset` archives the active conversation row and creates a fresh active row for the same stable `sessionKey`
|
|
226
222
|
|
|
227
|
-
|
|
223
|
+
This keeps long-term history available while still giving users a real clean-slate reset.
|
|
228
224
|
|
|
229
|
-
|
|
225
|
+
## Environment-only knobs outside plugin config
|
|
230
226
|
|
|
231
|
-
|
|
227
|
+
These settings are not part of `plugins.entries.lossless-claw.config`, but they still affect the system:
|
|
228
|
+
|
|
229
|
+
| Env var | Default | Purpose |
|
|
230
|
+
| --- | --- | --- |
|
|
231
|
+
| `LCM_TUI_CONVERSATION_WINDOW_SIZE` | `200` | Number of messages `lcm-tui` loads per keyset-paged conversation window. |
|
|
232
|
+
|
|
233
|
+
## Database operations
|
|
234
|
+
|
|
235
|
+
The SQLite database lives at `databasePath` or `LCM_DATABASE_PATH`. The default path is `${HOME}/.openclaw/lcm.db`.
|
|
236
|
+
|
|
237
|
+
Inspect it with:
|
|
232
238
|
|
|
233
239
|
```bash
|
|
234
240
|
sqlite3 ~/.openclaw/lcm.db
|
|
235
241
|
|
|
236
|
-
# Count conversations
|
|
237
242
|
SELECT COUNT(*) FROM conversations;
|
|
238
|
-
|
|
239
|
-
# See context items for a conversation
|
|
240
243
|
SELECT * FROM context_items WHERE conversation_id = 1 ORDER BY ordinal;
|
|
241
|
-
|
|
242
|
-
# Check summary depth distribution
|
|
243
244
|
SELECT depth, COUNT(*) FROM summaries GROUP BY depth;
|
|
244
|
-
|
|
245
|
-
# Find large summaries
|
|
246
245
|
SELECT summary_id, depth, token_count FROM summaries ORDER BY token_count DESC LIMIT 10;
|
|
247
246
|
```
|
|
248
247
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
The database is a single file. Back it up with:
|
|
248
|
+
Back it up with:
|
|
252
249
|
|
|
253
250
|
```bash
|
|
254
251
|
cp ~/.openclaw/lcm.db ~/.openclaw/lcm.db.backup
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
Or use SQLite's online backup:
|
|
258
|
-
|
|
259
|
-
```bash
|
|
260
252
|
sqlite3 ~/.openclaw/lcm.db ".backup ~/.openclaw/lcm.db.backup"
|
|
261
253
|
```
|
|
262
254
|
|
|
263
|
-
##
|
|
255
|
+
## Disabling lossless-claw
|
|
264
256
|
|
|
265
|
-
|
|
257
|
+
To disable the plugin but keep it installed:
|
|
266
258
|
|
|
267
|
-
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"plugins": {
|
|
262
|
+
"entries": {
|
|
263
|
+
"lossless-claw": {
|
|
264
|
+
"enabled": false
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
268
270
|
|
|
269
|
-
To
|
|
271
|
+
To switch back to OpenClaw's legacy context engine instead:
|
|
270
272
|
|
|
271
273
|
```json
|
|
272
274
|
{
|
|
@@ -277,5 +279,3 @@ To fall back to OpenClaw's built-in compaction:
|
|
|
277
279
|
}
|
|
278
280
|
}
|
|
279
281
|
```
|
|
280
|
-
|
|
281
|
-
Or set `LCM_ENABLED=false` to disable the plugin while keeping it registered.
|