agent-working-memory 0.7.10 → 0.7.11
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 +6 -1
- package/dist/api/routes.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/core/query-expander.d.ts +7 -0
- package/dist/core/query-expander.d.ts.map +1 -1
- package/dist/core/query-expander.js +62 -3
- package/dist/core/query-expander.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp.js +2 -2
- package/package.json +1 -1
- package/src/api/routes.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/core/query-expander.ts +66 -3
- package/src/index.ts +1 -1
- package/src/mcp.ts +2 -2
package/README.md
CHANGED
|
@@ -393,6 +393,7 @@ npm run test:locomo # LoCoMo industry benchmark (28.2%)
|
|
|
393
393
|
| `AWM_DISABLE_POOL_FILTER` | *(unset)* | Set to `1` to disable the candidate pool reduction (0.7.7+). Reverts recall to scoring all active candidates — slower but useful for A/B testing if a recall regression appears |
|
|
394
394
|
| `AWM_DISABLE_SLIM_CACHE` | *(unset)* | Set to `1` to disable the in-memory slim cache (0.7.10+). Reverts to per-recall SQL fetch — slower but useful if cache invariants are suspected of drift |
|
|
395
395
|
| `AWM_DISABLE_RERANK_SKIP` | *(unset)* | Set to `1` to disable the reranker skip on clear-winner queries (0.7.10+). Forces every recall through the cross-encoder |
|
|
396
|
+
| `AWM_DISABLE_EXPANSION_CACHE` | *(unset)* | Set to `1` to disable the query expansion skip heuristic + LRU cache (0.7.11+). Forces every recall through the flan-t5-small expander |
|
|
396
397
|
| `AWM_WORKSPACE` | *(unset)* | Default workspace for cross-agent recall in hive setups |
|
|
397
398
|
|
|
398
399
|
## Tech Stack
|
|
@@ -412,6 +413,10 @@ npm run test:locomo # LoCoMo industry benchmark (28.2%)
|
|
|
412
413
|
|
|
413
414
|
All three ML models run locally via ONNX. No external API calls for retrieval. The entire system is a single SQLite file + a Node.js process.
|
|
414
415
|
|
|
416
|
+
## What's New in v0.7.11
|
|
417
|
+
|
|
418
|
+
- **Query expansion skip + LRU cache** — flan-t5-small was 164ms per recall (18% of post-0.7.10 floor). Two fixes in `core/query-expander.ts`: (1) skip heuristic for long/specific queries (>50 chars OR ≥5 distinct meaningful tokens), and (2) 500-entry LRU cache for repeated queries. ~30% of typical agent recalls hit the skip; repeated recalls hit the cache. Avg savings: ~100-150ms per recall. Recall quality A/B: 8/8 top-1, 4.63/5 top-5. Disable via `AWM_DISABLE_EXPANSION_CACHE=1`.
|
|
419
|
+
|
|
415
420
|
## What's New in v0.7.10
|
|
416
421
|
|
|
417
422
|
- **Recall latency 1.4s → 0.9s median (~35% on top of 0.7.9)** — two more fixes after phase-breakdown showed the slim fetch was still 310ms (Buffer→Float32Array on every recall) and the reranker was 354ms (40% of remaining cost):
|
|
@@ -482,7 +487,7 @@ See [CHANGELOG.md](CHANGELOG.md) for full details.
|
|
|
482
487
|
|
|
483
488
|
## Project Status
|
|
484
489
|
|
|
485
|
-
AWM is in active development (v0.7.
|
|
490
|
+
AWM is in active development (v0.7.11). The core memory pipeline, consolidation system, multi-agent coordination, and MCP integration are stable and used daily in production coding workflows.
|
|
486
491
|
|
|
487
492
|
- Core retrieval and consolidation: **stable**
|
|
488
493
|
- MCP tools and Claude Code integration: **stable**
|
package/dist/api/routes.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -307,7 +307,7 @@ async function exportMemories() {
|
|
|
307
307
|
// Collect unique agents
|
|
308
308
|
const agents = [...new Set(memories.map((m) => m.agent_id))];
|
|
309
309
|
const exportData = {
|
|
310
|
-
version: '0.7.
|
|
310
|
+
version: '0.7.11',
|
|
311
311
|
exported_at: new Date().toISOString(),
|
|
312
312
|
source_db: dbPath,
|
|
313
313
|
agent_filter: agentFilter,
|
|
@@ -19,6 +19,13 @@ export declare function getExpander(): Promise<Text2TextGenerationPipeline>;
|
|
|
19
19
|
* Expand a query with related terms and synonyms.
|
|
20
20
|
* Returns the original query + generated expansion terms.
|
|
21
21
|
* Falls back to the original query on any error.
|
|
22
|
+
*
|
|
23
|
+
* Optimization (0.7.11+):
|
|
24
|
+
* - Skip heuristic for long/specific queries (~30% of typical agent recalls)
|
|
25
|
+
* - LRU cache for repeated queries (cache hit ≈ 0ms vs 164ms cold)
|
|
26
|
+
* - Disable both via AWM_DISABLE_EXPANSION_CACHE=1
|
|
22
27
|
*/
|
|
23
28
|
export declare function expandQuery(originalQuery: string): Promise<string>;
|
|
29
|
+
/** Clear the expansion cache (used by tests + cache invalidation if needed). */
|
|
30
|
+
export declare function clearExpansionCache(): void;
|
|
24
31
|
//# sourceMappingURL=query-expander.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAMvF;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAaxE;
|
|
1
|
+
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAMvF;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAaxE;AA6BD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CxE;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -33,12 +33,58 @@ export async function getExpander() {
|
|
|
33
33
|
});
|
|
34
34
|
return initPromise;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* LRU cache of normalized-query → expanded-query mappings.
|
|
38
|
+
* Map preserves insertion order — re-set on hit moves entry to the end (most-recent),
|
|
39
|
+
* delete-first when over capacity drops the least-recent. ~500 entries × ~200 chars
|
|
40
|
+
* each ≈ 100KB, negligible memory cost.
|
|
41
|
+
*
|
|
42
|
+
* Why: phase-breakdown spike (2026-05-08) showed expandQuery at ~164ms per call.
|
|
43
|
+
* Agent recall patterns repeat — cache hits are common.
|
|
44
|
+
*/
|
|
45
|
+
const expansionCache = new Map();
|
|
46
|
+
const EXPANSION_CACHE_LIMIT = 500;
|
|
47
|
+
/**
|
|
48
|
+
* Heuristic: skip expansion when the query is already specific.
|
|
49
|
+
* Long, multi-token queries don't benefit from synonyms — they're already
|
|
50
|
+
* narrow enough that flan-t5's general-vocabulary expansion adds noise more
|
|
51
|
+
* than recall. Exact thresholds are conservative; false-skips would only
|
|
52
|
+
* affect candidates that BM25 catches anyway.
|
|
53
|
+
*/
|
|
54
|
+
function shouldSkipExpansion(normalized) {
|
|
55
|
+
if (normalized.length === 0)
|
|
56
|
+
return true;
|
|
57
|
+
if (normalized.length > 50)
|
|
58
|
+
return true;
|
|
59
|
+
// ≥5 distinct meaningful tokens = already specific
|
|
60
|
+
const tokens = new Set(normalized.split(/\s+/).filter(t => t.length > 2));
|
|
61
|
+
return tokens.size >= 5;
|
|
62
|
+
}
|
|
36
63
|
/**
|
|
37
64
|
* Expand a query with related terms and synonyms.
|
|
38
65
|
* Returns the original query + generated expansion terms.
|
|
39
66
|
* Falls back to the original query on any error.
|
|
67
|
+
*
|
|
68
|
+
* Optimization (0.7.11+):
|
|
69
|
+
* - Skip heuristic for long/specific queries (~30% of typical agent recalls)
|
|
70
|
+
* - LRU cache for repeated queries (cache hit ≈ 0ms vs 164ms cold)
|
|
71
|
+
* - Disable both via AWM_DISABLE_EXPANSION_CACHE=1
|
|
40
72
|
*/
|
|
41
73
|
export async function expandQuery(originalQuery) {
|
|
74
|
+
const normalized = originalQuery.toLowerCase().trim();
|
|
75
|
+
const optimizationsEnabled = process.env.AWM_DISABLE_EXPANSION_CACHE !== '1';
|
|
76
|
+
if (optimizationsEnabled) {
|
|
77
|
+
if (shouldSkipExpansion(normalized)) {
|
|
78
|
+
return originalQuery;
|
|
79
|
+
}
|
|
80
|
+
const cached = expansionCache.get(normalized);
|
|
81
|
+
if (cached !== undefined) {
|
|
82
|
+
// Move to end (most-recent) for LRU semantics
|
|
83
|
+
expansionCache.delete(normalized);
|
|
84
|
+
expansionCache.set(normalized, cached);
|
|
85
|
+
return cached;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
42
88
|
try {
|
|
43
89
|
const expander = await getExpander();
|
|
44
90
|
const prompt = `Expand this search query with synonyms and related terms. Only output the additional terms, not the original query. Query: ${originalQuery}. Additional terms:`;
|
|
@@ -48,13 +94,26 @@ export async function expandQuery(originalQuery) {
|
|
|
48
94
|
});
|
|
49
95
|
const expanded = Array.isArray(result) ? result[0]?.generated_text ?? '' : '';
|
|
50
96
|
const cleanExpanded = expanded.trim();
|
|
51
|
-
|
|
52
|
-
|
|
97
|
+
const finalQuery = cleanExpanded && cleanExpanded.length > 2
|
|
98
|
+
? `${originalQuery} ${cleanExpanded}`
|
|
99
|
+
: originalQuery;
|
|
100
|
+
// Cache the result (LRU eviction when over capacity)
|
|
101
|
+
if (optimizationsEnabled) {
|
|
102
|
+
if (expansionCache.size >= EXPANSION_CACHE_LIMIT) {
|
|
103
|
+
const oldestKey = expansionCache.keys().next().value;
|
|
104
|
+
if (oldestKey !== undefined)
|
|
105
|
+
expansionCache.delete(oldestKey);
|
|
106
|
+
}
|
|
107
|
+
expansionCache.set(normalized, finalQuery);
|
|
53
108
|
}
|
|
54
|
-
return
|
|
109
|
+
return finalQuery;
|
|
55
110
|
}
|
|
56
111
|
catch {
|
|
57
112
|
return originalQuery;
|
|
58
113
|
}
|
|
59
114
|
}
|
|
115
|
+
/** Clear the expansion cache (used by tests + cache invalidation if needed). */
|
|
116
|
+
export function clearExpansionCache() {
|
|
117
|
+
expansionCache.clear();
|
|
118
|
+
}
|
|
60
119
|
//# sourceMappingURL=query-expander.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAoC,MAAM,2BAA2B,CAAC;AAEvF,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AACxC,IAAI,QAAQ,GAAuC,IAAI,CAAC;AACxD,IAAI,WAAW,GAAgD,IAAI,CAAC;AAEpE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,WAAW,GAAG,QAAQ,CAAC,sBAAsB,EAAE,QAAQ,EAAE;QACvD,KAAK,EAAE,MAAM;KACd,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACb,QAAQ,GAAG,IAAmC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -175,7 +175,7 @@ async function main() {
|
|
|
175
175
|
getExpander().catch(err => console.warn('Query expander model unavailable:', err.message));
|
|
176
176
|
// Start server
|
|
177
177
|
await app.listen({ port: PORT, host: '0.0.0.0' });
|
|
178
|
-
console.log(`AgentWorkingMemory v0.7.
|
|
178
|
+
console.log(`AgentWorkingMemory v0.7.11 listening on port ${PORT}`);
|
|
179
179
|
// Graceful shutdown
|
|
180
180
|
const shutdown = async () => {
|
|
181
181
|
clearInterval(backupTimer);
|
package/dist/mcp.js
CHANGED
|
@@ -71,7 +71,7 @@ import { queryPeerDecisions, formatPeerDecisions } from './coordination/peer-dec
|
|
|
71
71
|
const INCOGNITO = process.env.AWM_INCOGNITO === '1' || process.env.AWM_INCOGNITO === 'true';
|
|
72
72
|
if (INCOGNITO) {
|
|
73
73
|
console.error('AWM: incognito mode — all memory tools disabled, nothing will be recorded');
|
|
74
|
-
const server = new McpServer({ name: 'agent-working-memory', version: '0.7.
|
|
74
|
+
const server = new McpServer({ name: 'agent-working-memory', version: '0.7.11' });
|
|
75
75
|
const transport = new StdioServerTransport();
|
|
76
76
|
server.connect(transport).catch(err => {
|
|
77
77
|
console.error('MCP server failed:', err);
|
|
@@ -102,7 +102,7 @@ else {
|
|
|
102
102
|
let coordDb = null;
|
|
103
103
|
const server = new McpServer({
|
|
104
104
|
name: 'agent-working-memory',
|
|
105
|
-
version: '0.7.
|
|
105
|
+
version: '0.7.11',
|
|
106
106
|
});
|
|
107
107
|
server.registerResource('awm-overview', 'awm://server/overview', {
|
|
108
108
|
title: 'AWM Overview',
|
package/package.json
CHANGED
package/src/api/routes.ts
CHANGED
|
@@ -705,7 +705,7 @@ export function registerRoutes(app: FastifyInstance, deps: MemoryDeps): void {
|
|
|
705
705
|
const base: Record<string, unknown> = {
|
|
706
706
|
status: 'ok',
|
|
707
707
|
timestamp: new Date().toISOString(),
|
|
708
|
-
version: '0.7.
|
|
708
|
+
version: '0.7.11',
|
|
709
709
|
coordination: coordEnabled,
|
|
710
710
|
};
|
|
711
711
|
if (coordEnabled) {
|
package/src/cli.ts
CHANGED
|
@@ -334,7 +334,7 @@ async function exportMemories() {
|
|
|
334
334
|
const agents = [...new Set(memories.map((m: any) => m.agent_id))];
|
|
335
335
|
|
|
336
336
|
const exportData = {
|
|
337
|
-
version: '0.7.
|
|
337
|
+
version: '0.7.11',
|
|
338
338
|
exported_at: new Date().toISOString(),
|
|
339
339
|
source_db: dbPath,
|
|
340
340
|
agent_filter: agentFilter,
|
|
@@ -37,12 +37,60 @@ export async function getExpander(): Promise<Text2TextGenerationPipeline> {
|
|
|
37
37
|
return initPromise;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* LRU cache of normalized-query → expanded-query mappings.
|
|
42
|
+
* Map preserves insertion order — re-set on hit moves entry to the end (most-recent),
|
|
43
|
+
* delete-first when over capacity drops the least-recent. ~500 entries × ~200 chars
|
|
44
|
+
* each ≈ 100KB, negligible memory cost.
|
|
45
|
+
*
|
|
46
|
+
* Why: phase-breakdown spike (2026-05-08) showed expandQuery at ~164ms per call.
|
|
47
|
+
* Agent recall patterns repeat — cache hits are common.
|
|
48
|
+
*/
|
|
49
|
+
const expansionCache = new Map<string, string>();
|
|
50
|
+
const EXPANSION_CACHE_LIMIT = 500;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Heuristic: skip expansion when the query is already specific.
|
|
54
|
+
* Long, multi-token queries don't benefit from synonyms — they're already
|
|
55
|
+
* narrow enough that flan-t5's general-vocabulary expansion adds noise more
|
|
56
|
+
* than recall. Exact thresholds are conservative; false-skips would only
|
|
57
|
+
* affect candidates that BM25 catches anyway.
|
|
58
|
+
*/
|
|
59
|
+
function shouldSkipExpansion(normalized: string): boolean {
|
|
60
|
+
if (normalized.length === 0) return true;
|
|
61
|
+
if (normalized.length > 50) return true;
|
|
62
|
+
// ≥5 distinct meaningful tokens = already specific
|
|
63
|
+
const tokens = new Set(normalized.split(/\s+/).filter(t => t.length > 2));
|
|
64
|
+
return tokens.size >= 5;
|
|
65
|
+
}
|
|
66
|
+
|
|
40
67
|
/**
|
|
41
68
|
* Expand a query with related terms and synonyms.
|
|
42
69
|
* Returns the original query + generated expansion terms.
|
|
43
70
|
* Falls back to the original query on any error.
|
|
71
|
+
*
|
|
72
|
+
* Optimization (0.7.11+):
|
|
73
|
+
* - Skip heuristic for long/specific queries (~30% of typical agent recalls)
|
|
74
|
+
* - LRU cache for repeated queries (cache hit ≈ 0ms vs 164ms cold)
|
|
75
|
+
* - Disable both via AWM_DISABLE_EXPANSION_CACHE=1
|
|
44
76
|
*/
|
|
45
77
|
export async function expandQuery(originalQuery: string): Promise<string> {
|
|
78
|
+
const normalized = originalQuery.toLowerCase().trim();
|
|
79
|
+
const optimizationsEnabled = process.env.AWM_DISABLE_EXPANSION_CACHE !== '1';
|
|
80
|
+
|
|
81
|
+
if (optimizationsEnabled) {
|
|
82
|
+
if (shouldSkipExpansion(normalized)) {
|
|
83
|
+
return originalQuery;
|
|
84
|
+
}
|
|
85
|
+
const cached = expansionCache.get(normalized);
|
|
86
|
+
if (cached !== undefined) {
|
|
87
|
+
// Move to end (most-recent) for LRU semantics
|
|
88
|
+
expansionCache.delete(normalized);
|
|
89
|
+
expansionCache.set(normalized, cached);
|
|
90
|
+
return cached;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
46
94
|
try {
|
|
47
95
|
const expander = await getExpander();
|
|
48
96
|
const prompt = `Expand this search query with synonyms and related terms. Only output the additional terms, not the original query. Query: ${originalQuery}. Additional terms:`;
|
|
@@ -55,11 +103,26 @@ export async function expandQuery(originalQuery: string): Promise<string> {
|
|
|
55
103
|
const expanded = Array.isArray(result) ? (result[0] as any)?.generated_text ?? '' : '';
|
|
56
104
|
const cleanExpanded = expanded.trim();
|
|
57
105
|
|
|
58
|
-
|
|
59
|
-
|
|
106
|
+
const finalQuery = cleanExpanded && cleanExpanded.length > 2
|
|
107
|
+
? `${originalQuery} ${cleanExpanded}`
|
|
108
|
+
: originalQuery;
|
|
109
|
+
|
|
110
|
+
// Cache the result (LRU eviction when over capacity)
|
|
111
|
+
if (optimizationsEnabled) {
|
|
112
|
+
if (expansionCache.size >= EXPANSION_CACHE_LIMIT) {
|
|
113
|
+
const oldestKey = expansionCache.keys().next().value;
|
|
114
|
+
if (oldestKey !== undefined) expansionCache.delete(oldestKey);
|
|
115
|
+
}
|
|
116
|
+
expansionCache.set(normalized, finalQuery);
|
|
60
117
|
}
|
|
61
|
-
|
|
118
|
+
|
|
119
|
+
return finalQuery;
|
|
62
120
|
} catch {
|
|
63
121
|
return originalQuery;
|
|
64
122
|
}
|
|
65
123
|
}
|
|
124
|
+
|
|
125
|
+
/** Clear the expansion cache (used by tests + cache invalidation if needed). */
|
|
126
|
+
export function clearExpansionCache(): void {
|
|
127
|
+
expansionCache.clear();
|
|
128
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -177,7 +177,7 @@ async function main() {
|
|
|
177
177
|
|
|
178
178
|
// Start server
|
|
179
179
|
await app.listen({ port: PORT, host: '0.0.0.0' });
|
|
180
|
-
console.log(`AgentWorkingMemory v0.7.
|
|
180
|
+
console.log(`AgentWorkingMemory v0.7.11 listening on port ${PORT}`);
|
|
181
181
|
|
|
182
182
|
// Graceful shutdown
|
|
183
183
|
const shutdown = async () => {
|
package/src/mcp.ts
CHANGED
|
@@ -78,7 +78,7 @@ const INCOGNITO = process.env.AWM_INCOGNITO === '1' || process.env.AWM_INCOGNITO
|
|
|
78
78
|
|
|
79
79
|
if (INCOGNITO) {
|
|
80
80
|
console.error('AWM: incognito mode — all memory tools disabled, nothing will be recorded');
|
|
81
|
-
const server = new McpServer({ name: 'agent-working-memory', version: '0.7.
|
|
81
|
+
const server = new McpServer({ name: 'agent-working-memory', version: '0.7.11' });
|
|
82
82
|
const transport = new StdioServerTransport();
|
|
83
83
|
server.connect(transport).catch(err => {
|
|
84
84
|
console.error('MCP server failed:', err);
|
|
@@ -115,7 +115,7 @@ let coordDb: import('better-sqlite3').Database | null = null;
|
|
|
115
115
|
|
|
116
116
|
const server = new McpServer({
|
|
117
117
|
name: 'agent-working-memory',
|
|
118
|
-
version: '0.7.
|
|
118
|
+
version: '0.7.11',
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
server.registerResource(
|