@martian-engineering/lossless-claw 0.5.2 → 0.6.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 +49 -11
- package/docs/configuration.md +44 -0
- package/openclaw.plugin.json +114 -0
- package/package.json +2 -1
- package/skills/lossless-claw/SKILL.md +33 -0
- package/skills/lossless-claw/references/architecture.md +52 -0
- package/skills/lossless-claw/references/config.md +263 -0
- package/skills/lossless-claw/references/diagnostics.md +79 -0
- package/skills/lossless-claw/references/recall-tools.md +55 -0
- package/skills/lossless-claw/references/session-lifecycle.md +59 -0
- package/src/assembler.ts +321 -34
- package/src/compaction.ts +220 -19
- package/src/db/config.ts +74 -21
- package/src/db/migration.ts +50 -13
- package/src/engine.ts +742 -133
- package/src/plugin/index.ts +156 -73
- package/src/plugin/lcm-command.ts +759 -0
- package/src/plugin/lcm-doctor-apply.ts +546 -0
- package/src/plugin/lcm-doctor-shared.ts +210 -0
- package/src/store/conversation-store.ts +60 -21
- package/src/store/parse-utc-timestamp.ts +25 -0
- package/src/store/summary-store.ts +460 -11
- package/src/summarize.ts +553 -224
- package/src/tools/lcm-expand-query-tool.ts +195 -59
- package/src/tools/lcm-expansion-recursion-guard.ts +87 -0
- package/src/types.ts +1 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
This reference covers the current `lossless-claw` config surface on `main`, based on `openclaw.plugin.json`.
|
|
4
|
+
|
|
5
|
+
`lossless-claw` is most effective when the operator understands which settings change compaction behavior and why.
|
|
6
|
+
|
|
7
|
+
## First checks
|
|
8
|
+
|
|
9
|
+
- Ensure the plugin is installed and enabled.
|
|
10
|
+
- Ensure the context-engine slot points at `lossless-claw` when you want it to own compaction.
|
|
11
|
+
- Run `/lossless` (`/lcm` alias) to confirm the plugin is active and see the live DB path.
|
|
12
|
+
|
|
13
|
+
## High-impact settings
|
|
14
|
+
|
|
15
|
+
These are the settings most operators should understand first.
|
|
16
|
+
|
|
17
|
+
### `contextThreshold`
|
|
18
|
+
|
|
19
|
+
Controls how full the model context can get before LCM compacts older material.
|
|
20
|
+
|
|
21
|
+
- Lower values compact earlier.
|
|
22
|
+
- Higher values compact later.
|
|
23
|
+
|
|
24
|
+
Why it matters:
|
|
25
|
+
|
|
26
|
+
- Too low increases summarization cost and churn.
|
|
27
|
+
- Too high risks hitting the model window with large tool output or long replies.
|
|
28
|
+
|
|
29
|
+
Good default:
|
|
30
|
+
|
|
31
|
+
- `0.75`
|
|
32
|
+
|
|
33
|
+
### `freshTailCount`
|
|
34
|
+
|
|
35
|
+
Keeps the newest messages raw instead of compacting them.
|
|
36
|
+
|
|
37
|
+
Why it matters:
|
|
38
|
+
|
|
39
|
+
- Higher values preserve near-term conversational nuance.
|
|
40
|
+
- Lower values free context budget sooner.
|
|
41
|
+
|
|
42
|
+
Good starting range:
|
|
43
|
+
|
|
44
|
+
- `32` to `64`
|
|
45
|
+
|
|
46
|
+
### `leafChunkTokens`
|
|
47
|
+
|
|
48
|
+
Caps how much raw material gets summarized into one leaf summary.
|
|
49
|
+
|
|
50
|
+
Why it matters:
|
|
51
|
+
|
|
52
|
+
- Larger chunks reduce summarization frequency.
|
|
53
|
+
- Smaller chunks create more summaries and more DAG fragmentation.
|
|
54
|
+
|
|
55
|
+
Use this when:
|
|
56
|
+
|
|
57
|
+
- Your summarizer is rate-limited or expensive.
|
|
58
|
+
- You want fewer but broader leaf summaries.
|
|
59
|
+
|
|
60
|
+
### `incrementalMaxDepth`
|
|
61
|
+
|
|
62
|
+
Controls how far automatic condensation cascades after leaf compaction.
|
|
63
|
+
|
|
64
|
+
Why it matters:
|
|
65
|
+
|
|
66
|
+
- `0` keeps only leaf summaries moving automatically.
|
|
67
|
+
- `1` is a practical default for long-running sessions.
|
|
68
|
+
- `-1` allows unlimited cascading, which can be useful for very long histories but is more aggressive.
|
|
69
|
+
|
|
70
|
+
### `summaryModel` and `summaryProvider`
|
|
71
|
+
|
|
72
|
+
Override the model used for compaction summarization.
|
|
73
|
+
|
|
74
|
+
Why they matter:
|
|
75
|
+
|
|
76
|
+
- Summary quality compounds upward in the DAG.
|
|
77
|
+
- Cheaper models can reduce cost, but weak summaries create weak recalled context later.
|
|
78
|
+
|
|
79
|
+
Guidance:
|
|
80
|
+
|
|
81
|
+
- Pick a cheaper model only if it remains reliably structured and faithful.
|
|
82
|
+
- `summaryProvider` only matters when `summaryModel` is a bare model name rather than a canonical provider/model ref.
|
|
83
|
+
|
|
84
|
+
### `expansionModel` and `expansionProvider`
|
|
85
|
+
|
|
86
|
+
Override the model used by delegated recall flows such as `lcm_expand_query`.
|
|
87
|
+
|
|
88
|
+
Why they matter:
|
|
89
|
+
|
|
90
|
+
- This lets recall-heavy work use a different cost/latency profile than normal compaction.
|
|
91
|
+
- These are recall-path settings, not compaction-path settings.
|
|
92
|
+
|
|
93
|
+
## Complete config surface
|
|
94
|
+
|
|
95
|
+
## Core enablement and storage
|
|
96
|
+
|
|
97
|
+
### `enabled`
|
|
98
|
+
|
|
99
|
+
Boolean on/off switch for the plugin entry.
|
|
100
|
+
|
|
101
|
+
Use this when:
|
|
102
|
+
|
|
103
|
+
- you need the plugin installed but temporarily disabled
|
|
104
|
+
- you want to distinguish “installed” from “selected and active”
|
|
105
|
+
|
|
106
|
+
### `dbPath`
|
|
107
|
+
|
|
108
|
+
Overrides the SQLite DB location.
|
|
109
|
+
|
|
110
|
+
Why it matters:
|
|
111
|
+
|
|
112
|
+
- useful for custom deployments, testing, or isolating environments
|
|
113
|
+
- wrong path selection is a common reason operators think LCM is empty or not growing
|
|
114
|
+
|
|
115
|
+
### `largeFileThresholdTokens`
|
|
116
|
+
|
|
117
|
+
Threshold for externalizing oversized tool/file payloads out of the main transcript into large-file storage.
|
|
118
|
+
|
|
119
|
+
Why it matters:
|
|
120
|
+
|
|
121
|
+
- lower values externalize more aggressively
|
|
122
|
+
- higher values keep more payload inline but can bloat storage and compaction inputs
|
|
123
|
+
|
|
124
|
+
## Compaction timing and shape
|
|
125
|
+
|
|
126
|
+
### `contextThreshold`
|
|
127
|
+
|
|
128
|
+
See high-impact settings above.
|
|
129
|
+
|
|
130
|
+
### `freshTailCount`
|
|
131
|
+
|
|
132
|
+
See high-impact settings above.
|
|
133
|
+
|
|
134
|
+
### `leafChunkTokens`
|
|
135
|
+
|
|
136
|
+
See high-impact settings above.
|
|
137
|
+
|
|
138
|
+
### `leafMinFanout`
|
|
139
|
+
|
|
140
|
+
Minimum number of leaf items required before creating a leaf compaction grouping.
|
|
141
|
+
|
|
142
|
+
Why it matters:
|
|
143
|
+
|
|
144
|
+
- higher values avoid tiny leaf summaries
|
|
145
|
+
- lower values compact sooner but can create overly granular summaries
|
|
146
|
+
|
|
147
|
+
### `condensedMinFanout`
|
|
148
|
+
|
|
149
|
+
Preferred minimum fanout for condensed summaries during normal condensation.
|
|
150
|
+
|
|
151
|
+
Why it matters:
|
|
152
|
+
|
|
153
|
+
- controls how eagerly summaries get grouped upward
|
|
154
|
+
- affects DAG breadth and readability of higher-level summaries
|
|
155
|
+
|
|
156
|
+
### `condensedMinFanoutHard`
|
|
157
|
+
|
|
158
|
+
Hard lower bound for condensed fanout decisions.
|
|
159
|
+
|
|
160
|
+
Why it matters:
|
|
161
|
+
|
|
162
|
+
- acts as the guardrail when normal fanout preferences cannot be met cleanly
|
|
163
|
+
- mostly useful for advanced tuning or pathological summary-tree shapes
|
|
164
|
+
|
|
165
|
+
### `incrementalMaxDepth`
|
|
166
|
+
|
|
167
|
+
See high-impact settings above.
|
|
168
|
+
|
|
169
|
+
## Session-selection controls
|
|
170
|
+
|
|
171
|
+
### `ignoreSessionPatterns`
|
|
172
|
+
|
|
173
|
+
Glob-style session-key patterns that should never enter LCM.
|
|
174
|
+
|
|
175
|
+
Why it matters:
|
|
176
|
+
|
|
177
|
+
- keeps low-value automation or noisy sessions out of the DB
|
|
178
|
+
- useful for excluding certain agent lanes or ephemeral traffic entirely
|
|
179
|
+
|
|
180
|
+
### `statelessSessionPatterns`
|
|
181
|
+
|
|
182
|
+
Patterns for sessions that may read from LCM but should not write to it.
|
|
183
|
+
|
|
184
|
+
Why it matters:
|
|
185
|
+
|
|
186
|
+
- useful for sub-agents and ephemeral workers
|
|
187
|
+
- prevents recall helpers from polluting the main history
|
|
188
|
+
|
|
189
|
+
### `skipStatelessSessions`
|
|
190
|
+
|
|
191
|
+
Boolean that changes how stateless matches are treated.
|
|
192
|
+
|
|
193
|
+
Why it matters:
|
|
194
|
+
|
|
195
|
+
- when enabled, matching stateless sessions skip LCM persistence entirely
|
|
196
|
+
- use carefully, because it affects whether those sessions behave as readers only or are effectively bypassed for writes
|
|
197
|
+
|
|
198
|
+
## Recall-path and delegation controls
|
|
199
|
+
|
|
200
|
+
### `expansionModel`
|
|
201
|
+
|
|
202
|
+
See high-impact settings above.
|
|
203
|
+
|
|
204
|
+
### `expansionProvider`
|
|
205
|
+
|
|
206
|
+
See high-impact settings above.
|
|
207
|
+
|
|
208
|
+
### `delegationTimeoutMs`
|
|
209
|
+
|
|
210
|
+
Maximum time to wait for delegated recall completion.
|
|
211
|
+
|
|
212
|
+
Why it matters:
|
|
213
|
+
|
|
214
|
+
- lower values fail faster under slow sub-agent paths
|
|
215
|
+
- higher values tolerate deeper recall but can make calls feel stuck longer
|
|
216
|
+
|
|
217
|
+
### `maxAssemblyTokenBudget`
|
|
218
|
+
|
|
219
|
+
Hard ceiling for assembled LCM token budget.
|
|
220
|
+
|
|
221
|
+
Why it matters:
|
|
222
|
+
|
|
223
|
+
- useful when the runtime model window is smaller than the surrounding system assumes
|
|
224
|
+
- can prevent oversized assembly on smaller-context models
|
|
225
|
+
|
|
226
|
+
## Summary quality and prompt controls
|
|
227
|
+
|
|
228
|
+
### `summaryMaxOverageFactor`
|
|
229
|
+
|
|
230
|
+
Maximum allowed overage factor before an oversized summary is truncated/downgraded.
|
|
231
|
+
|
|
232
|
+
Why it matters:
|
|
233
|
+
|
|
234
|
+
- guards against runaway summaries that are much larger than their target budget
|
|
235
|
+
- useful when summary models are verbose or unstable
|
|
236
|
+
|
|
237
|
+
### `customInstructions`
|
|
238
|
+
|
|
239
|
+
Natural-language instructions injected into summarization prompts.
|
|
240
|
+
|
|
241
|
+
Why it matters:
|
|
242
|
+
|
|
243
|
+
- lets operators steer formatting or emphasis without patching code
|
|
244
|
+
- should be used sparingly; low-quality instructions can degrade summary quality system-wide
|
|
245
|
+
|
|
246
|
+
## Practical operator workflow
|
|
247
|
+
|
|
248
|
+
1. Install and enable the plugin.
|
|
249
|
+
2. Set the context-engine slot to `lossless-claw`.
|
|
250
|
+
3. Start with conservative defaults.
|
|
251
|
+
4. Run `/lossless` after startup to confirm path, size, and summary health.
|
|
252
|
+
5. If recall feels weak, revisit `freshTailCount`, `leafChunkTokens`, and summarizer model quality before changing anything else.
|
|
253
|
+
6. Touch advanced knobs like fanout, large-file thresholds, custom instructions, and assembly caps only after a concrete symptom appears.
|
|
254
|
+
|
|
255
|
+
## Reading the status output
|
|
256
|
+
|
|
257
|
+
`/lossless` is the right command for LCM-local metrics.
|
|
258
|
+
|
|
259
|
+
Useful interpretation notes:
|
|
260
|
+
|
|
261
|
+
- `tokens in context` is the current LCM frontier token count in the live LCM state.
|
|
262
|
+
- `compression ratio` is shown as a rounded `1:N`, which is easier to read than a tiny percentage for heavily compacted conversations.
|
|
263
|
+
- `/status` may still show a different context number because it reflects the runtime prompt that was actually assembled and sent on the last turn.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Diagnostics
|
|
2
|
+
|
|
3
|
+
For the MVP, use the native command surface first.
|
|
4
|
+
|
|
5
|
+
## Fast path
|
|
6
|
+
|
|
7
|
+
### `/lossless` (`/lcm` alias)
|
|
8
|
+
|
|
9
|
+
Use this when you need a quick health snapshot.
|
|
10
|
+
|
|
11
|
+
It should answer:
|
|
12
|
+
|
|
13
|
+
- Is `lossless-claw` enabled?
|
|
14
|
+
- Is it selected as the context engine?
|
|
15
|
+
- Which DB is active?
|
|
16
|
+
- Is the DB growing as expected?
|
|
17
|
+
- Are summaries present?
|
|
18
|
+
- Are broken or truncated summaries present?
|
|
19
|
+
|
|
20
|
+
### `/lossless doctor`
|
|
21
|
+
|
|
22
|
+
Use this when summary corruption or truncation is suspected.
|
|
23
|
+
|
|
24
|
+
It is the single user-facing diagnostic entrypoint for summary-health issues in the MVP.
|
|
25
|
+
|
|
26
|
+
What it should help confirm:
|
|
27
|
+
|
|
28
|
+
- whether broken summaries exist
|
|
29
|
+
- whether truncation markers exist
|
|
30
|
+
- which conversations are affected most
|
|
31
|
+
|
|
32
|
+
## Interpreting common states
|
|
33
|
+
|
|
34
|
+
### `/lossless` tokens vs `/status` context
|
|
35
|
+
|
|
36
|
+
These numbers are related, but they are not the same metric.
|
|
37
|
+
|
|
38
|
+
- `/lossless` reports LCM-side conversation metrics such as the current frontier token count and compression ratio.
|
|
39
|
+
- `/status` reports the last assembled runtime prompt snapshot for the active model.
|
|
40
|
+
|
|
41
|
+
Why they can differ:
|
|
42
|
+
|
|
43
|
+
- runtime assembly can trim or omit frontier material before the request is sent
|
|
44
|
+
- model-specific token budgeting and packing happen after LCM frontier selection
|
|
45
|
+
- `/status` reflects a last-run snapshot, while `/lossless` reads live LCM state from the DB
|
|
46
|
+
|
|
47
|
+
Treat `/lossless` as the LCM health/shape view, and `/status` as the runtime request view.
|
|
48
|
+
|
|
49
|
+
### No summaries yet
|
|
50
|
+
|
|
51
|
+
Usually means one of:
|
|
52
|
+
|
|
53
|
+
- the conversation has not crossed compaction thresholds yet
|
|
54
|
+
- the plugin is not selected as the context engine
|
|
55
|
+
- writes are being skipped because the session matches stateless or ignored patterns
|
|
56
|
+
|
|
57
|
+
### DB exists but stays tiny
|
|
58
|
+
|
|
59
|
+
Usually means one of:
|
|
60
|
+
|
|
61
|
+
- the plugin is not receiving traffic
|
|
62
|
+
- the wrong DB path is configured
|
|
63
|
+
- the plugin is enabled but not selected
|
|
64
|
+
|
|
65
|
+
### Broken or truncated summaries detected
|
|
66
|
+
|
|
67
|
+
Treat this as a signal to inspect summary health before trusting compacted context heavily.
|
|
68
|
+
|
|
69
|
+
For MVP guidance:
|
|
70
|
+
|
|
71
|
+
- keep the user on `/lossless doctor`
|
|
72
|
+
- explain the count and affected conversations
|
|
73
|
+
- avoid advertising separate repair-vs-doctor command families
|
|
74
|
+
|
|
75
|
+
## Safe operator advice
|
|
76
|
+
|
|
77
|
+
- Do not guess exact historical details from compacted context alone.
|
|
78
|
+
- When a user wants a fact pattern verified, use recall tools to recover evidence.
|
|
79
|
+
- Prefer changing one configuration knob at a time and then re-checking `/lossless`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Recall Tools
|
|
2
|
+
|
|
3
|
+
Use recall tools when the question depends on exact historical evidence from compacted context.
|
|
4
|
+
|
|
5
|
+
## Tool selection
|
|
6
|
+
|
|
7
|
+
### `lcm_grep`
|
|
8
|
+
|
|
9
|
+
Use for:
|
|
10
|
+
|
|
11
|
+
- finding whether a term, file name, error string, or identifier appears in compacted history
|
|
12
|
+
- narrowing the search space before deeper inspection
|
|
13
|
+
|
|
14
|
+
Do not use it for:
|
|
15
|
+
|
|
16
|
+
- answering detail-heavy questions by itself
|
|
17
|
+
|
|
18
|
+
### `lcm_describe`
|
|
19
|
+
|
|
20
|
+
Use for:
|
|
21
|
+
|
|
22
|
+
- inspecting a specific summary or stored-file record by ID
|
|
23
|
+
- reading lineage and content for a known summary node
|
|
24
|
+
|
|
25
|
+
Do not use it for:
|
|
26
|
+
|
|
27
|
+
- broad discovery when you do not know the target ID yet
|
|
28
|
+
|
|
29
|
+
### `lcm_expand_query`
|
|
30
|
+
|
|
31
|
+
Use for:
|
|
32
|
+
|
|
33
|
+
- focused questions that need richer detail recovered from summaries
|
|
34
|
+
- evidence-oriented follow-up after `lcm_grep` or `lcm_describe`
|
|
35
|
+
|
|
36
|
+
This is the best recall tool when the user asks for:
|
|
37
|
+
|
|
38
|
+
- exact commands
|
|
39
|
+
- exact file paths
|
|
40
|
+
- precise timestamps
|
|
41
|
+
- root-cause chains
|
|
42
|
+
|
|
43
|
+
### `lcm_expand`
|
|
44
|
+
|
|
45
|
+
Treat as a specialized sub-agent flow, not the default first step.
|
|
46
|
+
|
|
47
|
+
## Recommended workflow
|
|
48
|
+
|
|
49
|
+
1. Start with `lcm_grep` to find likely evidence.
|
|
50
|
+
2. Use `lcm_describe` when you have a summary or file ID.
|
|
51
|
+
3. Use `lcm_expand_query` when the answer requires precise recovery rather than a high-level summary.
|
|
52
|
+
|
|
53
|
+
## Important guardrail
|
|
54
|
+
|
|
55
|
+
Do not infer exact details from summaries alone when the user needs evidence. Expand first or state that the answer still needs expansion.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Session lifecycle (`/new` and `/reset`)
|
|
2
|
+
|
|
3
|
+
This reference describes the current behavior on `main`.
|
|
4
|
+
|
|
5
|
+
## Short version
|
|
6
|
+
|
|
7
|
+
For stock `lossless-claw` on current main:
|
|
8
|
+
|
|
9
|
+
- OpenClaw handles `/new` and `/reset` as session-reset operations.
|
|
10
|
+
- `lossless-claw` does **not** currently register its own `before_reset` hook or a custom reset policy.
|
|
11
|
+
- `lossless-claw` prefers **`sessionKey`** as the stable identity for an LCM conversation.
|
|
12
|
+
- When the same `sessionKey` reappears with a new `sessionId`, `lossless-claw` updates the stored `sessionId` on the existing LCM conversation row instead of creating a brand-new LCM conversation.
|
|
13
|
+
|
|
14
|
+
## What that means in practice
|
|
15
|
+
|
|
16
|
+
If a user asks whether `/new` or `/reset` gives them a fresh LCM conversation, the answer is usually **no** under the current implementation.
|
|
17
|
+
|
|
18
|
+
They get a fresh OpenClaw session runtime, but LCM continuity still follows the stable `sessionKey` when one is available.
|
|
19
|
+
|
|
20
|
+
So today:
|
|
21
|
+
|
|
22
|
+
- `/new` and `/reset` can reset the runtime session
|
|
23
|
+
- but LCM history may continue in the same conversation row if the chat/thread keeps the same `sessionKey`
|
|
24
|
+
|
|
25
|
+
## Why
|
|
26
|
+
|
|
27
|
+
Current lossless-claw conversation resolution does this:
|
|
28
|
+
|
|
29
|
+
1. look up by `sessionKey` first
|
|
30
|
+
2. fall back to `sessionId` only when no `sessionKey` match exists
|
|
31
|
+
3. if the `sessionKey` already exists but the `sessionId` changed, update the stored `sessionId` on that same conversation
|
|
32
|
+
|
|
33
|
+
That behavior preserves continuity across session resets for the same chat identity.
|
|
34
|
+
|
|
35
|
+
## Important limitation
|
|
36
|
+
|
|
37
|
+
There is currently **no plugin-specific `/new` vs `/reset` split** in stock lossless-claw docs or runtime behavior.
|
|
38
|
+
|
|
39
|
+
If someone is asking for semantics like:
|
|
40
|
+
|
|
41
|
+
- `/new` keeps LCM history but rotates transcript
|
|
42
|
+
- `/reset` archives old LCM conversation and starts a new one
|
|
43
|
+
|
|
44
|
+
that is a **design/spec topic**, not current stock behavior.
|
|
45
|
+
|
|
46
|
+
## Safe operator guidance
|
|
47
|
+
|
|
48
|
+
When answering users:
|
|
49
|
+
|
|
50
|
+
- do not promise that `/new` or `/reset` clears LCM history
|
|
51
|
+
- explain that current stock behavior follows `sessionKey` continuity
|
|
52
|
+
- if they need a truly separate LCM history, use a different session key context (for example a different chat/thread/binding) or explicit non-MVP migration/surgery tools
|
|
53
|
+
|
|
54
|
+
## Relation to `/status`
|
|
55
|
+
|
|
56
|
+
This session behavior is separate from `/status` metrics.
|
|
57
|
+
|
|
58
|
+
- `/status` reflects runtime session state and the last assembled request snapshot
|
|
59
|
+
- `/lossless` reflects LCM conversation state keyed by the plugin's conversation mapping rules
|