clawmem 0.1.3 → 0.1.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/AGENTS.md +2 -0
- package/CLAUDE.md +2 -0
- package/README.md +15 -0
- package/SKILL.md +2 -0
- package/package.json +1 -1
- package/src/config.ts +12 -3
- package/src/hooks/context-surfacing.ts +23 -2
package/AGENTS.md
CHANGED
|
@@ -257,6 +257,8 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
|
|
|
257
257
|
|
|
258
258
|
**Hook blind spots (by design):** Hooks filter out `_clawmem/` system artifacts, enforce score thresholds, and cap token budget. Absence in `<vault-context>` does NOT mean absence in memory. If you expect a memory to exist but it wasn't surfaced, escalate to Tier 3.
|
|
259
259
|
|
|
260
|
+
**Adaptive thresholds:** Context-surfacing uses ratio-based scoring that adapts to vault characteristics (size, document quality, content age, embedding model). Results are kept within a percentage of the best result's composite score rather than a fixed absolute threshold. An activation floor prevents surfacing when all results are weak. Profiles control the ratio: `speed` (65%), `balanced` (55%), `deep` (45% + query expansion + reranking). `CLAWMEM_PROFILE=deep` is recommended for vaults with older content or lower-quality documents. MCP tools use fixed absolute thresholds, not adaptive.
|
|
261
|
+
|
|
260
262
|
### Tier 3 — Agent-Initiated (one targeted MCP call)
|
|
261
263
|
|
|
262
264
|
**Escalate ONLY when one of these three rules fires:**
|
package/CLAUDE.md
CHANGED
|
@@ -257,6 +257,8 @@ ClawMem hooks handle ~90% of retrieval automatically. Agent-initiated MCP calls
|
|
|
257
257
|
|
|
258
258
|
**Hook blind spots (by design):** Hooks filter out `_clawmem/` system artifacts, enforce score thresholds, and cap token budget. Absence in `<vault-context>` does NOT mean absence in memory. If you expect a memory to exist but it wasn't surfaced, escalate to Tier 3.
|
|
259
259
|
|
|
260
|
+
**Adaptive thresholds:** Context-surfacing uses ratio-based scoring that adapts to vault characteristics (size, document quality, content age, embedding model). Results are kept within a percentage of the best result's composite score rather than a fixed absolute threshold. An activation floor prevents surfacing when all results are weak. Profiles control the ratio: `speed` (65%), `balanced` (55%), `deep` (45% + query expansion + reranking). `CLAWMEM_PROFILE=deep` is recommended for vaults with older content or lower-quality documents. MCP tools use fixed absolute thresholds, not adaptive.
|
|
261
|
+
|
|
260
262
|
### Tier 3 — Agent-Initiated (one targeted MCP call)
|
|
261
263
|
|
|
262
264
|
**Escalate ONLY when one of these three rules fires:**
|
package/README.md
CHANGED
|
@@ -1015,6 +1015,21 @@ Built on the shoulders of:
|
|
|
1015
1015
|
- [SAME](https://github.com/sgx-labs/statelessagent) — agent memory concepts (recency decay, confidence scoring, session tracking)
|
|
1016
1016
|
- [supermemory](https://github.com/supermemoryai/clawdbot-supermemory) — hook patterns and context surfacing ideas
|
|
1017
1017
|
|
|
1018
|
+
## Roadmap
|
|
1019
|
+
|
|
1020
|
+
| Status | Feature | Description |
|
|
1021
|
+
|--------|---------|-------------|
|
|
1022
|
+
| :white_check_mark: | Adaptive thresholds | Ratio-based filtering that adapts to vault characteristics (v0.1.3) |
|
|
1023
|
+
| :white_check_mark: | Deep escalation | Budget-aware query expansion + cross-encoder reranking for `deep` profile |
|
|
1024
|
+
| :white_check_mark: | Cloud embedding providers | Jina, OpenAI, Voyage, Cohere with batch embedding + TPM pacing |
|
|
1025
|
+
| :construction: | Calibration probes | One-time `clawmem calibrate` command that measures your vault's score distribution and tunes thresholds automatically |
|
|
1026
|
+
| :construction: | Rolling threshold learning | Learns optimal activation floor from actual usage patterns (which surfaced content gets referenced vs ignored) |
|
|
1027
|
+
| :memo: | Multi-vault namespacing | Isolated vaults with independent calibration and lifecycle policies |
|
|
1028
|
+
| :memo: | REST API authentication | Token-scoped access for multi-agent deployments |
|
|
1029
|
+
| :memo: | Streaming rerank | Cross-encoder reranking within the hook timeout budget for larger candidate sets |
|
|
1030
|
+
|
|
1031
|
+
:white_check_mark: Shipped  :construction: Planned  :memo: Exploring
|
|
1032
|
+
|
|
1018
1033
|
## License
|
|
1019
1034
|
|
|
1020
1035
|
MIT
|
package/SKILL.md
CHANGED
|
@@ -191,6 +191,8 @@ Hooks handle ~90% of retrieval. Zero agent effort.
|
|
|
191
191
|
|
|
192
192
|
**Hook blind spots (by design):** Hooks filter out `_clawmem/` system artifacts, enforce score thresholds, and cap token budget. Absence in `<vault-context>` does NOT mean absence in memory. Escalate to Tier 3 if expected memory wasn't surfaced.
|
|
193
193
|
|
|
194
|
+
**Adaptive thresholds:** Context-surfacing uses ratio-based scoring that adapts to vault characteristics. Results are kept within a percentage of the best result's composite score (speed: 65%, balanced: 55%, deep: 45%). An activation floor prevents surfacing when all results are weak. `CLAWMEM_PROFILE=deep` adds query expansion + reranking. MCP tools use fixed absolute thresholds, not adaptive.
|
|
195
|
+
|
|
194
196
|
---
|
|
195
197
|
|
|
196
198
|
## Tier 3 — Agent-Initiated Retrieval (MCP Tools)
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -70,7 +70,16 @@ export interface ProfileConfig {
|
|
|
70
70
|
maxResults: number;
|
|
71
71
|
useVector: boolean;
|
|
72
72
|
vectorTimeout: number;
|
|
73
|
+
/** Legacy absolute threshold — used by MCP tools and as fallback when thresholdMode="absolute" */
|
|
73
74
|
minScore: number;
|
|
75
|
+
/** Adaptive: keep results within this ratio of best score (e.g., 0.55 = top 55%) */
|
|
76
|
+
minScoreRatio: number;
|
|
77
|
+
/** Adaptive: never surface below this regardless of ratio */
|
|
78
|
+
absoluteFloor: number;
|
|
79
|
+
/** Adaptive: if best result is below this, return empty (prevents all-weak surfacing) */
|
|
80
|
+
activationFloor: number;
|
|
81
|
+
/** "adaptive" uses ratio-based filtering; "absolute" uses legacy minScore */
|
|
82
|
+
thresholdMode: "adaptive" | "absolute";
|
|
74
83
|
/** Budget-aware escalation: if fast path finishes early, spend remaining time on expansion + reranking */
|
|
75
84
|
deepEscalation: boolean;
|
|
76
85
|
/** Max time (ms) allowed for the fast path before escalation is considered */
|
|
@@ -78,9 +87,9 @@ export interface ProfileConfig {
|
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
export const PROFILES: Record<PerformanceProfile, ProfileConfig> = {
|
|
81
|
-
speed: { tokenBudget: 400, maxResults: 5, useVector: false, vectorTimeout: 0, minScore: 0.55, deepEscalation: false, escalationBudgetMs: 0 },
|
|
82
|
-
balanced: { tokenBudget: 800, maxResults: 10, useVector: true, vectorTimeout: 900, minScore: 0.45, deepEscalation: false, escalationBudgetMs: 0 },
|
|
83
|
-
deep: { tokenBudget: 1200, maxResults: 15, useVector: true, vectorTimeout: 2000, minScore: 0.25, deepEscalation: true, escalationBudgetMs: 4000 },
|
|
90
|
+
speed: { tokenBudget: 400, maxResults: 5, useVector: false, vectorTimeout: 0, minScore: 0.55, minScoreRatio: 0.65, absoluteFloor: 0.18, activationFloor: 0.24, thresholdMode: "adaptive", deepEscalation: false, escalationBudgetMs: 0 },
|
|
91
|
+
balanced: { tokenBudget: 800, maxResults: 10, useVector: true, vectorTimeout: 900, minScore: 0.45, minScoreRatio: 0.55, absoluteFloor: 0.15, activationFloor: 0.20, thresholdMode: "adaptive", deepEscalation: false, escalationBudgetMs: 0 },
|
|
92
|
+
deep: { tokenBudget: 1200, maxResults: 15, useVector: true, vectorTimeout: 2000, minScore: 0.25, minScoreRatio: 0.45, absoluteFloor: 0.12, activationFloor: 0.16, thresholdMode: "adaptive", deepEscalation: true, escalationBudgetMs: 4000 },
|
|
84
93
|
};
|
|
85
94
|
|
|
86
95
|
export function getActiveProfile(): ProfileConfig {
|
|
@@ -178,7 +178,10 @@ export async function contextSurfacing(
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
// Phase 2: Cross-encoder reranking — reorder with deeper relevance signal
|
|
181
|
+
// Sort by score first so reranking covers the best candidates, not just
|
|
182
|
+
// the first-inserted (expansion hits appended later would otherwise be missed)
|
|
181
183
|
if (Date.now() - startTime < 6000 && results.length >= 3) {
|
|
184
|
+
results.sort((a, b) => b.score - a.score);
|
|
182
185
|
const toRerank = results.slice(0, 15).map(r => ({
|
|
183
186
|
file: r.filepath,
|
|
184
187
|
text: (r.body || "").slice(0, 2000),
|
|
@@ -253,8 +256,26 @@ export async function contextSurfacing(
|
|
|
253
256
|
}
|
|
254
257
|
|
|
255
258
|
// Apply composite scoring
|
|
256
|
-
const
|
|
257
|
-
|
|
259
|
+
const allScored = applyCompositeScoring(enriched, prompt);
|
|
260
|
+
|
|
261
|
+
// Threshold filtering — adaptive (ratio-based) or absolute (legacy)
|
|
262
|
+
let scored: typeof allScored;
|
|
263
|
+
if (profile.thresholdMode === "adaptive") {
|
|
264
|
+
// Use max composite score across the set (not positional [0], which may be
|
|
265
|
+
// reordered by recency-intent sorting in applyCompositeScoring)
|
|
266
|
+
const bestScore = allScored.length > 0
|
|
267
|
+
? Math.max(...allScored.map(r => r.compositeScore))
|
|
268
|
+
: 0;
|
|
269
|
+
|
|
270
|
+
// Activation floor: if even the best result is too weak, bail entirely
|
|
271
|
+
if (bestScore < profile.activationFloor) return makeEmptyOutput("context-surfacing");
|
|
272
|
+
|
|
273
|
+
const adaptiveMin = Math.max(bestScore * profile.minScoreRatio, profile.absoluteFloor);
|
|
274
|
+
scored = allScored.filter(r => r.compositeScore >= adaptiveMin);
|
|
275
|
+
} else {
|
|
276
|
+
// Legacy absolute threshold (backward compat)
|
|
277
|
+
scored = allScored.filter(r => r.compositeScore >= minScore);
|
|
278
|
+
}
|
|
258
279
|
|
|
259
280
|
if (scored.length === 0) return makeEmptyOutput("context-surfacing");
|
|
260
281
|
|