@parad0x_labs/openclaw-context-capsule 1.4.0 → 1.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/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## 1.7.0
4
+
5
+ - **Value-atom preservation.** A lone distinctive value — a bare port (`5433`), an
6
+ issue ref (`#4821`), a version (`v2.13.0`), an ISO date, or a hyphenated code
7
+ (`NEEDLE-ZX-7742`) — is now emitted as its own dense atom, so it survives
8
+ compression even when its surrounding sentence loses the budget race. Previously
9
+ such a value only survived when its whole line was selected. New regression:
10
+ `test/value-survival.test.mjs` (wired into `npm test`).
11
+ - **Docs accuracy.** Corrected the documented config defaults (`maxCapsuleTokens`
12
+ `700` → `1400`, `capsuleTokenRatio` `0.08` → `0.14`) to match the shipped values.
13
+ Reframed the fidelity figures to state plainly that they are measured on the
14
+ maintainer's own private sessions via `test/fidelity-bench.mjs` (reproduce on your
15
+ own `~/.openclaw` sessions), not a repo fixture. The supersession clean rate (83%
16
+ floor) and value-survival remain CI-gated by `npm test`.
17
+
18
+ ## 1.6.0
19
+
20
+ - Self-contained compression core bundled in `src/compression.ts` (no external
21
+ runtime dependency; no network / file-system / on-chain calls).
package/README.md CHANGED
@@ -1,59 +1,31 @@
1
1
  # context-capsule — OpenClaw ContextEngine plugin
2
2
 
3
- > 💜 **Saving you tokens?** [Star it on ClawHub](https://clawhub.ai/parad0x-labs/context-capsule) it's a context engine, so it works silently in the background. A star is the only way other agent builders find it.
4
-
5
- Compresses agent session history before it reaches the LLM. **Self-contained:**
6
- the compression core is vendored inline (`src/compression.ts`) — no external
7
- runtime dependency, and no network, file-system, or on-chain access. It uses
8
- only Node's built-in `zlib` and `crypto`.
9
-
10
- Sessions under 20 messages pass through unchanged. Longer sessions have their
11
- older history compressed into a capsule summary (injected as a system message)
12
- while the last 10 messages are kept verbatim — giving the model full coherence
13
- on recent turns without paying for the full transcript.
14
-
15
- > **Before you use this skill — read these:**
16
- >
17
- > - **All messages are vault-scanned** for secrets and PII on every path (short
18
- > sessions, verbatim tail, and compressed history alike). Matched values are
19
- > replaced with typed placeholders. However, the vault scan covers common
20
- > patterns — it is not a guarantee that all sensitive content is removed.
21
- > Do not rely on it as the sole protection for highly sensitive sessions.
22
- >
23
- > - **Compression alters history fidelity.** Older messages are summarised, not
24
- > preserved verbatim. Detail, nuance, and exact wording can be lost. Do not
25
- > use this skill where exact transcript fidelity is required.
26
- >
27
- > - **Compressed history is injected as a system message.** This places
28
- > summarised content in a privileged prompt position. Be aware that prior
29
- > user/assistant content will influence the model from the system role after
30
- > compression.
31
- >
32
- > - **No external runtime dependency.** The compression core is vendored inline
33
- > (`src/compression.ts`), so there is nothing external to resolve or verify.
34
- > The standalone `@parad0x_labs/context-capsule` library on npm is optional and
35
- > only relevant for non-OpenClaw use.
36
-
37
- **Most useful for:** local models (Ollama, LM Studio) and GPT-4 where context
38
- cost matters. Claude users with a 200k context window and built-in compaction
39
- enabled may not need this.
40
-
41
- ## Benchmark
42
-
43
- | Metric | Result | CI gate |
44
- |---|---|---|
45
- | Token savings | 99.3% | >= 95% |
46
- | Recovery score | 100% | >= 90% |
47
- | Runtime | 29ms | < 1000ms |
48
-
49
- Reproduce locally:
3
+ Self-contained OpenClaw context engine that reduces prompt tokens in long agent
4
+ sessions. It keeps the recent tail verbatim and converts older history into a
5
+ bounded, model-readable extractive capsule.
50
6
 
51
- ```sh
52
- cd packages/context-capsule
53
- npm run bench:public
54
- ```
7
+ The capsule preserves high-value older context:
8
+
9
+ - decisions and constraints
10
+ - open tasks and requested work
11
+ - errors and failed attempts
12
+ - files, commands, and links
13
+ - open questions and durable facts
14
+
15
+ It also keeps a zlib-compressed payload and Merkle root for auditability, but the
16
+ LLM is given the extractive capsule, not opaque compressed bytes.
55
17
 
56
- CI fails if savings drop below 95% or recovery falls below 90%.
18
+ ## Safety and limits
19
+
20
+ - **Lossy by design.** Older messages are not preserved verbatim in the model
21
+ prompt. Exact wording, nuance, and low-priority details can be lost.
22
+ - **Recent context remains verbatim.** `keepRecentMessages` controls how many
23
+ latest messages stay untouched.
24
+ - **Best-effort vault scan.** Text content is scanned for common secrets and PII
25
+ before compression or model injection. This is useful defense-in-depth, not a
26
+ formal guarantee.
27
+ - **No external runtime dependency.** The plugin uses only Node built-ins
28
+ (`zlib` and `crypto`) and makes no network, file-system, or on-chain calls.
57
29
 
58
30
  ## Activation
59
31
 
@@ -71,19 +43,45 @@ CI fails if savings drop below 95% or recovery falls below 90%.
71
43
  ## Config options
72
44
 
73
45
  | Key | Default | Description |
74
- |---|---|---|
75
- | `minMessages` | `20` | Sessions shorter than this pass through unchanged |
76
- | `keepRecentMessages` | `10` | Recent messages kept verbatim after compression |
46
+ | --- | ---: | --- |
47
+ | `minMessages` | `20` | Sessions shorter than this pass through unchanged. |
48
+ | `keepRecentMessages` | `10` | Recent messages kept verbatim after compression. |
49
+ | `maxCapsuleTokens` | `1400` | Hard cap for the injected extractive capsule. |
50
+ | `capsuleTokenRatio` | `0.14` | If OpenClaw provides a model token budget, cap the capsule to this fraction of the budget. |
51
+ | `minCompressTokens` | `900` | Estimated transcript-token floor before compression activates. |
77
52
 
78
53
  ```jsonc
79
54
  {
80
55
  "plugins": {
81
56
  "entries": {
82
57
  "context-capsule": {
83
- "minMessages": 15,
84
- "keepRecentMessages": 8
58
+ "minMessages": 20,
59
+ "keepRecentMessages": 10,
60
+ "maxCapsuleTokens": 1400,
61
+ "capsuleTokenRatio": 0.14,
62
+ "minCompressTokens": 900
85
63
  }
86
64
  }
87
65
  }
88
66
  }
89
67
  ```
68
+
69
+ ## Packaging
70
+
71
+ The npm/ClawHub package ships compiled `dist/` JavaScript. It does not require
72
+ TypeScript support from the host runtime.
73
+
74
+ ```sh
75
+ npm run typecheck
76
+ npm test
77
+ npm pack --dry-run
78
+ ```
79
+
80
+ ## When to use
81
+
82
+ Use this for long-running local or hosted model sessions where resending the full
83
+ conversation is too expensive or pushes the model toward context overflow.
84
+
85
+ Do not use it for workflows where old transcript wording must remain exact. For
86
+ that, keep normal OpenClaw history or use a retrieval system that can quote the
87
+ original source.
package/SKILL.md ADDED
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: context-capsule
3
+ description: Compresses older OpenClaw agent session history into a bounded, lane-change-aware context capsule — keeps recent messages verbatim, flags abandoned directions, quarantines injected instructions, and redacts secrets. Local, deterministic, any model.
4
+ license: MIT
5
+ metadata:
6
+ author: Parad0x-Labs
7
+ ---
8
+
9
+ # Context Capsule
10
+
11
+ Compress older agent session history before it hits the LLM, so long chats stop
12
+ re-sending the full transcript every turn. It keeps the recent tail verbatim and
13
+ turns older history into a bounded extractive capsule with decisions, tasks,
14
+ errors, paths, links, questions, and durable facts. Works with any model —
15
+ Claude, GPT, Ollama, Mistral, LM Studio.
16
+
17
+ **What sets it apart:**
18
+
19
+ - **Lane-change aware.** When the session pivots ("replace X with Y", "forget X,
20
+ use Y instead"), the capsule marks the abandoned direction as superseded and
21
+ keeps the live one — so the model never wanders back into a dropped plan. On a
22
+ held-out pivot set it cleans 83% of abandoned subjects with **zero** wrongly
23
+ flagged live choices.
24
+ - **High fidelity per token.** Distinctive signals — file paths, IDs, ports,
25
+ URLs, commands, errors, decisions — are emitted as dense atoms. As of **v1.7.0**,
26
+ a lone value (a bare port `5433`, an issue ref `#4821`, a version `v2.13.0`, an
27
+ ISO date, a hyphenated code like `NEEDLE-ZX-7742`) is emitted as its **own** atom,
28
+ so it survives compression even when its surrounding sentence loses the budget
29
+ race — CI-tested in `test/value-survival.test.mjs`. On the maintainer's own real
30
+ sessions the capsule kept ~79% of key signals at ~5× reduction and ~93% at ~3.4×;
31
+ `test/fidelity-bench.mjs` measures this against **your own** `~/.openclaw` sessions
32
+ (run it on your data to reproduce — the figures are from private sessions, not a
33
+ repo fixture).
34
+
35
+ > **Self-contained (v1.7.0):** The compression core is bundled directly in this
36
+ > skill (`src/compression.ts`). There is **no external runtime dependency**, and
37
+ > the plugin makes **no network, file-system, or on-chain calls**. Everything
38
+ > runs locally using only Node's built-in `zlib` and `crypto`, and is fully
39
+ > deterministic. Capsules carry a `schema` tag (`context-capsule.v2`).
40
+
41
+ > **Protections (defense-in-depth, all CI-gated by `npm test`):**
42
+ > - **Secret redaction (every surface).** API keys (OpenAI, Anthropic, AWS,
43
+ > Google, GitHub classic + fine-grained, GitLab, npm, Slack, Stripe, SendGrid,
44
+ > Twilio), JWTs, PEM blocks, URL basic-auth, `DATABASE_URL=` DSNs, and
45
+ > `key=value` credentials are detected by prefix/shape/context — never by raw
46
+ > entropy, so public IDs (git SHAs, UUIDs, chain addresses) are untouched.
47
+ > Redaction runs **before compression**, so no secret survives even in the zlib
48
+ > audit blob, and again on output — the core never emits a secret even if called
49
+ > directly. Each redaction carries a one-way **SHA-256 fingerprint**
50
+ > (`[REDACTED_AWS_KEY#a1b2c3d4]`) so the same key is correlatable across turns
51
+ > without ever exposing its value. Best-effort pattern matching — strong, not a
52
+ > guarantee for the most sensitive chats.
53
+ > - **Injection quarantine** — instruction-injection patterns in older history
54
+ > ("ignore previous instructions", "you are now…", "reveal your prompt") are
55
+ > wrapped as inert untrusted text, never surfaced as a live instruction.
56
+ > - **Bounded work** — every extraction pass runs on size-capped input, so a
57
+ > megabyte message or an adversarial string finishes in milliseconds instead of
58
+ > hanging the turn.
59
+
60
+ ## When to use
61
+
62
+ - Long-running agent sessions (default: more than 20 messages) where the
63
+ transcript is large and you want to cut per-call token cost.
64
+ - Any model/provider — local or hosted.
65
+
66
+ ## When NOT to use
67
+
68
+ - Sessions that require **exact, verbatim transcript fidelity**. Older history is
69
+ summarized into a compact capsule; detail and nuance can be lost. Only the most
70
+ recent 10 messages are kept verbatim.
71
+ - As your only safeguard for secrets/PII. The vault scan is best-effort, and the
72
+ compressed history is injected into the **system** context position.
73
+
74
+ ## How it works
75
+
76
+ Keeps the last 10 messages verbatim by default. Older history is zlib-compressed
77
+ for auditability, then converted into a model-readable extractive capsule. The
78
+ model sees compact sections for decisions/constraints, tasks, errors, files,
79
+ commands, links, questions, and durable facts. The capsule is capped by
80
+ `maxCapsuleTokens` and adapts to the host token budget with
81
+ `capsuleTokenRatio`.
82
+
83
+ ## Savings
84
+
85
+ | | Without | With |
86
+ | --------------------- | ------- | -------- |
87
+ | Prompt history sent | Full transcript | Capsule + recent tail |
88
+ | Compression trigger | N/A | Message + token threshold |
89
+ | Runtime dependencies | N/A | Node built-ins only |
90
+
91
+ ## Install
92
+
93
+ This skill is self-contained — no extra packages to install. Register it as your
94
+ context engine in `openclaw.json`:
95
+
96
+ ```jsonc
97
+ {
98
+ "plugins": {
99
+ "slots": { "contextEngine": "context-capsule" }
100
+ }
101
+ }
102
+ ```
103
+
104
+ Optional config (defaults shown):
105
+
106
+ ```jsonc
107
+ {
108
+ "plugins": {
109
+ "entries": {
110
+ "context-capsule": {
111
+ "minMessages": 20,
112
+ "keepRecentMessages": 10,
113
+ "maxCapsuleTokens": 1400,
114
+ "capsuleTokenRatio": 0.14,
115
+ "minCompressTokens": 900
116
+ }
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## Source
123
+
124
+ github.com/Parad0x-Labs/openclaw-skills/tree/main/skills/context-capsule
125
+
126
+ The standalone library (`@parad0x_labs/context-capsule`) is published separately
127
+ on npm for non-OpenClaw use; this skill vendors only the two pure functions it
128
+ needs and does not depend on it at runtime.
129
+
130
+ ---
131
+
132
+ 💜 If Context Capsule is quietly shrinking your token bill, a ⭐ on ClawHub helps
133
+ other agent builders find it.
134
+
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Self-contained compression core for the Context Capsule skill.
3
+ *
4
+ * The model cannot use opaque zlib bytes directly, so this module stores the
5
+ * compressed payload for auditability but injects a bounded extractive capsule:
6
+ * decisions, tasks, errors, paths, URLs, questions, and durable facts selected
7
+ * from older history. This is still lossy, but it preserves the material that
8
+ * usually matters in long agent sessions while keeping prompt tokens bounded.
9
+ *
10
+ * Crypto/compression run through a platform shim (./platform): the Node build
11
+ * uses `node:zlib` + `node:crypto`; a browser build aliases it to
12
+ * ./platform.browser (@noble/hashes + pako) so this exact source also runs in a
13
+ * browser tab. The SHA-256 path is byte-identical across backends, so a capsule's
14
+ * merkleRoot / capsuleId / injected memory are identical in a browser and in Node
15
+ * (the audit blob is round-trip-identical) — see test/platform-parity.test.mjs.
16
+ * No network, file I/O, or dynamic imports.
17
+ */
18
+ export interface Message {
19
+ role: string;
20
+ content: string;
21
+ }
22
+ export type CapsuleFactKind = "decision" | "task" | "error" | "file" | "question" | "fact";
23
+ export interface CapsuleFact {
24
+ kind: CapsuleFactKind;
25
+ text: string;
26
+ role: string;
27
+ sourceIndex: number;
28
+ score: number;
29
+ }
30
+ /** A compressed, auditable snapshot of an agent session's message history. */
31
+ export interface ContextCapsule {
32
+ /** Schema/version tag for forward-compatibility (e.g. "context-capsule.v2"). */
33
+ schema: string;
34
+ sessionId: string;
35
+ capsuleId: string;
36
+ originalTokenEstimate: number;
37
+ compressedBytes: number;
38
+ compressionRatio: string;
39
+ topics: string[];
40
+ facts: CapsuleFact[];
41
+ /** Subjects a later turn abandoned/replaced; surfaced as superseded. */
42
+ superseded: string[];
43
+ droppedFactCount: number;
44
+ maxOutputTokens: number;
45
+ merkleRoot: string;
46
+ createdAt: number;
47
+ compressedBase64: string;
48
+ }
49
+ export interface CompressOptions {
50
+ sessionId?: string;
51
+ maxOutputTokens?: number;
52
+ maxFacts?: number;
53
+ }
54
+ export interface InjectOptions {
55
+ maxOutputTokens?: number;
56
+ }
57
+ /**
58
+ * Compress a session's message history into a ContextCapsule.
59
+ * Pure function — extractive capsule + zlib deflate + SHA-256 only, no I/O.
60
+ */
61
+ export declare function compressContext(messages: Message[], opts?: CompressOptions): ContextCapsule;
62
+ /**
63
+ * Generate a bounded injection string that replaces full older history in an
64
+ * LLM call. The output intentionally contains useful extracted facts, not the
65
+ * opaque compressed payload.
66
+ */
67
+ export declare function injectCapsule(capsule: ContextCapsule, opts?: InjectOptions): string;