agent-working-memory 0.16.0 → 0.16.1
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 +3 -2
- package/dist/core/reranker.d.ts.map +1 -1
- package/dist/core/reranker.js +10 -2
- package/dist/core/reranker.js.map +1 -1
- package/package.json +106 -106
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/README.md +1 -1
- package/plugin/bin/awm-mcp-launcher.cjs +2 -2
- package/plugin/skills/awm-memory/SKILL.md +1 -1
- package/src/core/reranker.ts +150 -142
package/README.md
CHANGED
|
@@ -181,10 +181,11 @@ compatible, and the store is the same SQLite file before and after.
|
|
|
181
181
|
|
|
182
182
|
---
|
|
183
183
|
|
|
184
|
-
## What's new — v0.16.
|
|
184
|
+
## What's new — v0.16.1
|
|
185
185
|
|
|
186
186
|
| | |
|
|
187
187
|
|---|---|
|
|
188
|
+
| **0.16.1** | A tokenizer option the reranker had been passing since 0.5.2 turned out never to have existed in transformers.js — silently ignored for six months, and the library default was what the code wanted anyway, so no ranking behavior changes. Found by a dependency sweep that also clears every advisory in the published tree: an install of 0.16.0 audits at 7 (3 high), this one at **0**. Accuracy reproduced identically across two transformers majors, token spend to the token |
|
|
188
189
|
| **0.16.0** | Two recall defaults changed, each after being measured for the first time. A pseudo-relevance feedback pass that ran on **every** query is now opt-in — it cost 7% of every recall and bought nothing measurable across 950 probes. A reranker shortcut that had never once fired on any store benchmarked here is deleted; forced on, it cost success@1 93.0% → 91.7%. Identifier recall is now **93.0%** success@1 / **97.0%** success@5. Re-run `awm setup` for the corrected agent guidance |
|
|
189
190
|
| **0.15.9** | A memory that consolidation archived as a near-duplicate — even at high confidence — could never be reinforced again, so the same recurring fact kept spawning new copies instead of strengthening one. An archived match is now revived on reinforcement |
|
|
190
191
|
| **0.15.6–8** | **Data-loss fix.** The default store used to sit inside the installed npm package, where `npm install -g` deletes it on upgrade. It is now `~/.awm/memory.db`; re-running `awm setup` copies an affected store to safety and `awm doctor` fails on it. 0.15.7 corrects the docs that still taught the old location |
|
|
@@ -307,7 +308,7 @@ npm run test:linux # build + full suite on Linux (802/802)
|
|
|
307
308
|
|
|
308
309
|
## Status
|
|
309
310
|
|
|
310
|
-
Active development, v0.16.
|
|
311
|
+
Active development, v0.16.1. Core retrieval, consolidation, MCP integration, hooks, task
|
|
311
312
|
management, and the HTTP API are stable and in daily production use. PGlite backend stable;
|
|
312
313
|
networked Postgres experimental.
|
|
313
314
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAqHH,iCAAiC;AACjC,wBAAsB,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,CAGhD;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAGvF"}
|
package/dist/core/reranker.js
CHANGED
|
@@ -68,7 +68,14 @@ async function inProcessRerank(args) {
|
|
|
68
68
|
text_pair: passages,
|
|
69
69
|
padding: true,
|
|
70
70
|
truncation: true,
|
|
71
|
-
|
|
71
|
+
// NOT 'return_tensors'. That key never existed in transformers.js -- it is the
|
|
72
|
+
// PyTorch Python spelling -- so from 0.5.2 (commit 1ccbf95, 2026-03-21) until
|
|
73
|
+
// 2026-10-09 it was silently ignored and the library default
|
|
74
|
+
// (return_tensor=true, i.e. Tensors) applied.
|
|
75
|
+
// Stating it explicitly preserves exactly the behaviour that was already
|
|
76
|
+
// running, and survives a future change of default. transformers 4.x turned
|
|
77
|
+
// the typo into a type error, which is the only reason it was ever noticed.
|
|
78
|
+
return_tensor: true,
|
|
72
79
|
});
|
|
73
80
|
const output = await model(inputs);
|
|
74
81
|
const logits = output.logits ?? output.last_hidden_state;
|
|
@@ -90,7 +97,8 @@ async function inProcessRerank(args) {
|
|
|
90
97
|
text_pair: passages[i],
|
|
91
98
|
padding: true,
|
|
92
99
|
truncation: true,
|
|
93
|
-
|
|
100
|
+
// Same ignored-key story as the batch path above.
|
|
101
|
+
return_tensor: true,
|
|
94
102
|
});
|
|
95
103
|
const output = await model(inputs);
|
|
96
104
|
const logits = output.logits ?? output.last_hidden_state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,aAAa,EACb,kCAAkC,GAGnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,aAAa,GAAG,+BAA+B,CAAC;AACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,aAAa,CAAC;AAEjE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAqD,CAAC;AAE7G,8BAA8B;AAE9B,IAAI,SAAS,GAA+B,IAAI,CAAC;AACjD,IAAI,KAAK,GAA2B,IAAI,CAAC;AACzC,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,KAAK,UAAU,YAAY;IACzB,IAAI,SAAS,IAAI,KAAK;QAAE,OAAO;IAC/B,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QACxB,mBAAmB,EAAE,CAAC;QACtB,SAAS,GAAG,MAAM,aAAa,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1D,KAAK,GAAG,MAAM,kCAAkC,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7F,OAAO,CAAC,KAAK,CAAC,sCAAsC,QAAQ,KAAK,KAAK,GAAG,CAAC,CAAC;IAC7E,CAAC,CAAC,EAAE,CAAC;IACL,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAA2C;IACxE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACjC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,YAAY,EAAE,CAAC;IAErB,aAAa;IACb,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,SAAU,CAAC,OAAO,EAAE;YACjC,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,
|
|
1
|
+
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-working-memory",
|
|
3
|
-
"version": "0.16.
|
|
4
|
-
"mcpName": "io.github.CompleteIdeas/agent-working-memory",
|
|
5
|
-
"description": "Persistent, local-first memory for AI agents. Selective by design: filters what's worth keeping, links what's related, and says nothing when it doesn't know. SQLite + ONNX, no cloud, no API keys.",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"ai-agents",
|
|
8
|
-
"agent-memory",
|
|
9
|
-
"memory",
|
|
10
|
-
"mcp",
|
|
11
|
-
"model-context-protocol",
|
|
12
|
-
"claude-code",
|
|
13
|
-
"local-first",
|
|
14
|
-
"sqlite",
|
|
15
|
-
"onnx",
|
|
16
|
-
"retrieval",
|
|
17
|
-
"cognitive-architecture",
|
|
18
|
-
"act-r",
|
|
19
|
-
"hebbian",
|
|
20
|
-
"embeddings",
|
|
21
|
-
"reranker",
|
|
22
|
-
"typescript"
|
|
23
|
-
],
|
|
24
|
-
"type": "module",
|
|
25
|
-
"main": "dist/index.js",
|
|
26
|
-
"bin": {
|
|
27
|
-
"awm": "dist/cli.js"
|
|
28
|
-
},
|
|
29
|
-
"scripts": {
|
|
30
|
-
"build": "tsc",
|
|
31
|
-
"build:plugin": "node scripts/build-plugin.mjs",
|
|
32
|
-
"build:mcpb": "node scripts/build-mcpb.mjs",
|
|
33
|
-
"pack:mcpb": "node scripts/build-mcpb.mjs --pack",
|
|
34
|
-
"prepublishOnly": "npm run build && npm run build:plugin && npm run build:mcpb && npm run check:release",
|
|
35
|
-
"dev": "tsx watch src/index.ts",
|
|
36
|
-
"start": "node dist/index.js",
|
|
37
|
-
"test": "vitest",
|
|
38
|
-
"test:run": "vitest run",
|
|
39
|
-
"mcp": "tsx src/mcp.ts",
|
|
40
|
-
"test:mcp": "tsx tests/mcp-smoke.ts",
|
|
41
|
-
"test:self": "tsx tests/self-test/runner.ts",
|
|
42
|
-
"test:workday": "tsx tests/workday-eval/runner.ts",
|
|
43
|
-
"test:locomo": "tsx tests/locomo-eval/runner.ts",
|
|
44
|
-
"test:tokens": "tsx tests/token-savings/runner.ts",
|
|
45
|
-
"test:realworld": "tsx tests/realworld-eval/runner.ts",
|
|
46
|
-
"test:ab": "tsx tests/ab-test/runner.ts",
|
|
47
|
-
"test:sleep": "tsx tests/sleep-cycle/runner.ts",
|
|
48
|
-
"test:stress": "tsx tests/stress-test/runner.ts",
|
|
49
|
-
"test:edge": "tsx tests/edge-cases/runner.ts",
|
|
50
|
-
"test:pilot": "tsx tests/pilot-metrics/runner.ts",
|
|
51
|
-
"test:perf": "tsx tests/perf-test/runner.ts",
|
|
52
|
-
"eval": "tsx tests/eval/run.ts",
|
|
53
|
-
"eval:generate": "tsx tests/eval/generate.ts",
|
|
54
|
-
"test:all": "vitest run && tsx tests/mcp-smoke.ts",
|
|
55
|
-
"check:release": "node scripts/check-release.mjs",
|
|
56
|
-
"bench": "node scripts/bench-current.mjs",
|
|
57
|
-
"bench:public:build": "tsx tests/realstore-eval/build-public-snapshot.ts",
|
|
58
|
-
"bench:public": "node scripts/bench-public.mjs",
|
|
59
|
-
"profile:recall": "node scripts/profile-recall.mjs",
|
|
60
|
-
"test:docker": "bash scripts/docker-release-test.sh",
|
|
61
|
-
"test:linux": "bash scripts/docker-release-test.sh linux",
|
|
62
|
-
"test:desktop": "bash scripts/docker-release-test.sh desktop"
|
|
63
|
-
},
|
|
64
|
-
"engines": {
|
|
65
|
-
"node": ">=22.0.0"
|
|
66
|
-
},
|
|
67
|
-
"license": "Apache-2.0",
|
|
68
|
-
"files": [
|
|
69
|
-
"dist/",
|
|
70
|
-
"src/",
|
|
71
|
-
"plugin/",
|
|
72
|
-
".claude-plugin/",
|
|
73
|
-
"package.json",
|
|
74
|
-
"README.md",
|
|
75
|
-
"AGENTS.md",
|
|
76
|
-
"llms.txt",
|
|
77
|
-
"LICENSE"
|
|
78
|
-
],
|
|
79
|
-
"dependencies": {
|
|
80
|
-
"@electric-sql/pglite": "
|
|
81
|
-
"@electric-sql/pglite-pgvector": "^0.0.7",
|
|
82
|
-
"@huggingface/transformers": "^3.
|
|
83
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
84
|
-
"@toon-format/toon": "^2.3.0",
|
|
85
|
-
"better-sqlite3": "^12.6.2",
|
|
86
|
-
"fastify": "^5.
|
|
87
|
-
"pg": "^8.13.1",
|
|
88
|
-
"zod": "^4.3.6"
|
|
89
|
-
},
|
|
90
|
-
"devDependencies": {
|
|
91
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
92
|
-
"@types/node": "^25.3.5",
|
|
93
|
-
"@types/pg": "^8.11.10",
|
|
94
|
-
"tsx": "^4.21.0",
|
|
95
|
-
"typescript": "^5.9.3",
|
|
96
|
-
"vitest": "^4.0.18"
|
|
97
|
-
},
|
|
98
|
-
"repository": {
|
|
99
|
-
"type": "git",
|
|
100
|
-
"url": "git+https://github.com/CompleteIdeas/agent-working-memory.git"
|
|
101
|
-
},
|
|
102
|
-
"homepage": "https://github.com/CompleteIdeas/agent-working-memory#readme",
|
|
103
|
-
"bugs": {
|
|
104
|
-
"url": "https://github.com/CompleteIdeas/agent-working-memory/issues"
|
|
105
|
-
}
|
|
106
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-working-memory",
|
|
3
|
+
"version": "0.16.1",
|
|
4
|
+
"mcpName": "io.github.CompleteIdeas/agent-working-memory",
|
|
5
|
+
"description": "Persistent, local-first memory for AI agents. Selective by design: filters what's worth keeping, links what's related, and says nothing when it doesn't know. SQLite + ONNX, no cloud, no API keys.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ai-agents",
|
|
8
|
+
"agent-memory",
|
|
9
|
+
"memory",
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"claude-code",
|
|
13
|
+
"local-first",
|
|
14
|
+
"sqlite",
|
|
15
|
+
"onnx",
|
|
16
|
+
"retrieval",
|
|
17
|
+
"cognitive-architecture",
|
|
18
|
+
"act-r",
|
|
19
|
+
"hebbian",
|
|
20
|
+
"embeddings",
|
|
21
|
+
"reranker",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"bin": {
|
|
27
|
+
"awm": "dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"build:plugin": "node scripts/build-plugin.mjs",
|
|
32
|
+
"build:mcpb": "node scripts/build-mcpb.mjs",
|
|
33
|
+
"pack:mcpb": "node scripts/build-mcpb.mjs --pack",
|
|
34
|
+
"prepublishOnly": "npm run build && npm run build:plugin && npm run build:mcpb && npm run check:release",
|
|
35
|
+
"dev": "tsx watch src/index.ts",
|
|
36
|
+
"start": "node dist/index.js",
|
|
37
|
+
"test": "vitest",
|
|
38
|
+
"test:run": "vitest run",
|
|
39
|
+
"mcp": "tsx src/mcp.ts",
|
|
40
|
+
"test:mcp": "tsx tests/mcp-smoke.ts",
|
|
41
|
+
"test:self": "tsx tests/self-test/runner.ts",
|
|
42
|
+
"test:workday": "tsx tests/workday-eval/runner.ts",
|
|
43
|
+
"test:locomo": "tsx tests/locomo-eval/runner.ts",
|
|
44
|
+
"test:tokens": "tsx tests/token-savings/runner.ts",
|
|
45
|
+
"test:realworld": "tsx tests/realworld-eval/runner.ts",
|
|
46
|
+
"test:ab": "tsx tests/ab-test/runner.ts",
|
|
47
|
+
"test:sleep": "tsx tests/sleep-cycle/runner.ts",
|
|
48
|
+
"test:stress": "tsx tests/stress-test/runner.ts",
|
|
49
|
+
"test:edge": "tsx tests/edge-cases/runner.ts",
|
|
50
|
+
"test:pilot": "tsx tests/pilot-metrics/runner.ts",
|
|
51
|
+
"test:perf": "tsx tests/perf-test/runner.ts",
|
|
52
|
+
"eval": "tsx tests/eval/run.ts",
|
|
53
|
+
"eval:generate": "tsx tests/eval/generate.ts",
|
|
54
|
+
"test:all": "vitest run && tsx tests/mcp-smoke.ts",
|
|
55
|
+
"check:release": "node scripts/check-release.mjs",
|
|
56
|
+
"bench": "node scripts/bench-current.mjs",
|
|
57
|
+
"bench:public:build": "tsx tests/realstore-eval/build-public-snapshot.ts",
|
|
58
|
+
"bench:public": "node scripts/bench-public.mjs",
|
|
59
|
+
"profile:recall": "node scripts/profile-recall.mjs",
|
|
60
|
+
"test:docker": "bash scripts/docker-release-test.sh",
|
|
61
|
+
"test:linux": "bash scripts/docker-release-test.sh linux",
|
|
62
|
+
"test:desktop": "bash scripts/docker-release-test.sh desktop"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=22.0.0"
|
|
66
|
+
},
|
|
67
|
+
"license": "Apache-2.0",
|
|
68
|
+
"files": [
|
|
69
|
+
"dist/",
|
|
70
|
+
"src/",
|
|
71
|
+
"plugin/",
|
|
72
|
+
".claude-plugin/",
|
|
73
|
+
"package.json",
|
|
74
|
+
"README.md",
|
|
75
|
+
"AGENTS.md",
|
|
76
|
+
"llms.txt",
|
|
77
|
+
"LICENSE"
|
|
78
|
+
],
|
|
79
|
+
"dependencies": {
|
|
80
|
+
"@electric-sql/pglite": "0.5.6",
|
|
81
|
+
"@electric-sql/pglite-pgvector": "^0.0.7",
|
|
82
|
+
"@huggingface/transformers": "^4.3.1",
|
|
83
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
84
|
+
"@toon-format/toon": "^2.3.0",
|
|
85
|
+
"better-sqlite3": "^12.6.2",
|
|
86
|
+
"fastify": "^5.12.5",
|
|
87
|
+
"pg": "^8.13.1",
|
|
88
|
+
"zod": "^4.3.6"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
92
|
+
"@types/node": "^25.3.5",
|
|
93
|
+
"@types/pg": "^8.11.10",
|
|
94
|
+
"tsx": "^4.21.0",
|
|
95
|
+
"typescript": "^5.9.3",
|
|
96
|
+
"vitest": "^4.0.18"
|
|
97
|
+
},
|
|
98
|
+
"repository": {
|
|
99
|
+
"type": "git",
|
|
100
|
+
"url": "git+https://github.com/CompleteIdeas/agent-working-memory.git"
|
|
101
|
+
},
|
|
102
|
+
"homepage": "https://github.com/CompleteIdeas/agent-working-memory#readme",
|
|
103
|
+
"bugs": {
|
|
104
|
+
"url": "https://github.com/CompleteIdeas/agent-working-memory/issues"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "awm",
|
|
3
3
|
"displayName": "Agent Working Memory",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.1",
|
|
5
5
|
"description": "Persistent, local-first memory for AI agents. Selective by design: filters what's worth keeping, links what's related, and says nothing when it doesn't know. SQLite + ONNX, no cloud, no API keys.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Robert Winter"
|
package/plugin/README.md
CHANGED
|
@@ -22,7 +22,7 @@ The launcher defaults `AWM_DB_PATH` to `~/.awm/memory.db` — **the same file
|
|
|
22
22
|
than quietly starting an empty one. Set `AWM_DB_PATH` yourself to override.
|
|
23
23
|
|
|
24
24
|
It prefers an installed copy of the package (global, or a local `node_modules`) and falls
|
|
25
|
-
back to `npx -p agent-working-memory@0.16.
|
|
25
|
+
back to `npx -p agent-working-memory@0.16.1`. The npx path rebuilds
|
|
26
26
|
`better-sqlite3` on a cold cache, which is slow enough to look like a hang, so a real
|
|
27
27
|
install is worth having:
|
|
28
28
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
// This is a REAL source file, not a string inside the generator, because it is real code:
|
|
8
8
|
// it gets syntax-checked, linted and tested like everything else. `npm run build:plugin`
|
|
9
|
-
// copies it to plugin/bin/ and substitutes 0.16.
|
|
9
|
+
// copies it to plugin/bin/ and substitutes 0.16.1.
|
|
10
10
|
//
|
|
11
11
|
// Two jobs a bare `mcpServers` entry in plugin.json cannot do:
|
|
12
12
|
//
|
|
@@ -95,7 +95,7 @@ if (found) {
|
|
|
95
95
|
const isWin = process.platform === 'win32';
|
|
96
96
|
const child = spawn(
|
|
97
97
|
isWin ? 'npx.cmd' : 'npx',
|
|
98
|
-
['-y', '-p', 'agent-working-memory@0.16.
|
|
98
|
+
['-y', '-p', 'agent-working-memory@0.16.1', 'awm', 'mcp'],
|
|
99
99
|
{ stdio: 'inherit', env: process.env, shell: isWin }
|
|
100
100
|
);
|
|
101
101
|
child.on('error', (e) => {
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
|
|
11
11
|
# Agent Working Memory
|
|
12
12
|
|
|
13
|
-
Generated from `src/adapters/common.ts` (AWM v0.16.
|
|
13
|
+
Generated from `src/adapters/common.ts` (AWM v0.16.1) — the same guidance
|
|
14
14
|
`awm setup` writes into CLAUDE.md. Do not edit here; edit the source and re-run
|
|
15
15
|
`npm run build:plugin`.
|
|
16
16
|
|
package/src/core/reranker.ts
CHANGED
|
@@ -1,142 +1,150 @@
|
|
|
1
|
-
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
/**
|
|
4
|
-
* Cross-Encoder Re-Ranker - scores (query, passage) pairs for relevance.
|
|
5
|
-
*
|
|
6
|
-
* Uses Xenova/ms-marco-MiniLM-L-6-v2 (91MB ONNX at the fp32 default; the 23MB
|
|
7
|
-
* quantized file is what AWM_RERANKER_DTYPE=q8 loads) trained on MS-MARCO
|
|
8
|
-
* passage ranking. Unlike bi-encoders, cross-encoders see both query and
|
|
9
|
-
* passage together via full attention - much better at judging if a
|
|
10
|
-
* passage actually answers a question.
|
|
11
|
-
*
|
|
12
|
-
* AWM 0.8.x: inference dispatches through ml-worker.ts (currently in-process
|
|
13
|
-
* — see ml-worker.ts for the worker_threads → in-process revert rationale).
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
AutoTokenizer,
|
|
18
|
-
AutoModelForSequenceClassification,
|
|
19
|
-
type PreTrainedTokenizer,
|
|
20
|
-
type PreTrainedModel,
|
|
21
|
-
} from '@huggingface/transformers';
|
|
22
|
-
import { dispatchRerank, registerInProcessHandlers } from './ml-worker.js';
|
|
23
|
-
import { ensureModelCacheDir } from './model-cache.js';
|
|
24
|
-
|
|
25
|
-
const DEFAULT_MODEL = 'Xenova/ms-marco-MiniLM-L-6-v2';
|
|
26
|
-
const MODEL_ID = process.env.AWM_RERANKER_MODEL || DEFAULT_MODEL;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Weight precision for the cross-encoder. fp32 is the shipped default and the
|
|
30
|
-
* only value any published number was measured at.
|
|
31
|
-
*
|
|
32
|
-
* It is exposed because the cross-encoder is 83% of warm recall latency
|
|
33
|
-
* (measured, `npm run profile:recall`), which makes precision the largest
|
|
34
|
-
* single latency lever in the system — and an unmeasurable one while it was a
|
|
35
|
-
* literal. RE-MEASURED 2026-10-09 on the pipeline that ships: 'q8' cuts total
|
|
36
|
-
* recall latency 26-33% across three suites, for ONE QUERY in 450 — identifier
|
|
37
|
-
* success@1 unchanged at 93.0%, topic 92.2% -> 92.0%. Correct abstention is
|
|
38
|
-
* unmoved on all three suites; success@5 is unmoved on both private suites and
|
|
39
|
-
* moves +0.5pp on the public corpus, inside its 4pp seed-noise floor. It is deterministic (two runs agree
|
|
40
|
-
* on all 450 queries to 1e-6), and because no model is bundled it SHRINKS the
|
|
41
|
-
* first-run fetch: the ONNX file it loads is 23MB against fp32's 91MB. 'q4' is dominated: equal
|
|
42
|
-
* accuracy, only -3% latency, 6.1s cold start against fp32's 1.6s. The default
|
|
43
|
-
* is untouched because it is a product decision, not because the cost is
|
|
44
|
-
* unknown; see docs/recall-latency.md.
|
|
45
|
-
*/
|
|
46
|
-
const DTYPE = (process.env.AWM_RERANKER_DTYPE || 'fp32') as 'fp32' | 'fp16' | 'q8' | 'int8' | 'uint8' | 'q4';
|
|
47
|
-
|
|
48
|
-
// --- In-process fallback ---
|
|
49
|
-
|
|
50
|
-
let tokenizer: PreTrainedTokenizer | null = null;
|
|
51
|
-
let model: PreTrainedModel | null = null;
|
|
52
|
-
let initPromise: Promise<void> | null = null;
|
|
53
|
-
|
|
54
|
-
async function ensureLoaded(): Promise<void> {
|
|
55
|
-
if (tokenizer && model) return;
|
|
56
|
-
if (initPromise) return initPromise;
|
|
57
|
-
initPromise = (async () => {
|
|
58
|
-
ensureModelCacheDir();
|
|
59
|
-
tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
|
|
60
|
-
model = await AutoModelForSequenceClassification.from_pretrained(MODEL_ID, { dtype: DTYPE });
|
|
61
|
-
console.error(`Re-ranker model loaded in-process: ${MODEL_ID} (${DTYPE})`);
|
|
62
|
-
})();
|
|
63
|
-
return initPromise;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function sigmoid(x: number): number {
|
|
67
|
-
return 1 / (1 + Math.exp(-x));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function inProcessRerank(args: { query: string; passages: string[] }): Promise<Array<{ index: number; score: number }>> {
|
|
71
|
-
const { query, passages } = args;
|
|
72
|
-
if (passages.length === 0) return [];
|
|
73
|
-
await ensureLoaded();
|
|
74
|
-
|
|
75
|
-
// Batch path
|
|
76
|
-
try {
|
|
77
|
-
const queries = passages.map(() => query);
|
|
78
|
-
const inputs = tokenizer!(queries, {
|
|
79
|
-
text_pair: passages,
|
|
80
|
-
padding: true,
|
|
81
|
-
truncation: true,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Cross-Encoder Re-Ranker - scores (query, passage) pairs for relevance.
|
|
5
|
+
*
|
|
6
|
+
* Uses Xenova/ms-marco-MiniLM-L-6-v2 (91MB ONNX at the fp32 default; the 23MB
|
|
7
|
+
* quantized file is what AWM_RERANKER_DTYPE=q8 loads) trained on MS-MARCO
|
|
8
|
+
* passage ranking. Unlike bi-encoders, cross-encoders see both query and
|
|
9
|
+
* passage together via full attention - much better at judging if a
|
|
10
|
+
* passage actually answers a question.
|
|
11
|
+
*
|
|
12
|
+
* AWM 0.8.x: inference dispatches through ml-worker.ts (currently in-process
|
|
13
|
+
* — see ml-worker.ts for the worker_threads → in-process revert rationale).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
AutoTokenizer,
|
|
18
|
+
AutoModelForSequenceClassification,
|
|
19
|
+
type PreTrainedTokenizer,
|
|
20
|
+
type PreTrainedModel,
|
|
21
|
+
} from '@huggingface/transformers';
|
|
22
|
+
import { dispatchRerank, registerInProcessHandlers } from './ml-worker.js';
|
|
23
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
24
|
+
|
|
25
|
+
const DEFAULT_MODEL = 'Xenova/ms-marco-MiniLM-L-6-v2';
|
|
26
|
+
const MODEL_ID = process.env.AWM_RERANKER_MODEL || DEFAULT_MODEL;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Weight precision for the cross-encoder. fp32 is the shipped default and the
|
|
30
|
+
* only value any published number was measured at.
|
|
31
|
+
*
|
|
32
|
+
* It is exposed because the cross-encoder is 83% of warm recall latency
|
|
33
|
+
* (measured, `npm run profile:recall`), which makes precision the largest
|
|
34
|
+
* single latency lever in the system — and an unmeasurable one while it was a
|
|
35
|
+
* literal. RE-MEASURED 2026-10-09 on the pipeline that ships: 'q8' cuts total
|
|
36
|
+
* recall latency 26-33% across three suites, for ONE QUERY in 450 — identifier
|
|
37
|
+
* success@1 unchanged at 93.0%, topic 92.2% -> 92.0%. Correct abstention is
|
|
38
|
+
* unmoved on all three suites; success@5 is unmoved on both private suites and
|
|
39
|
+
* moves +0.5pp on the public corpus, inside its 4pp seed-noise floor. It is deterministic (two runs agree
|
|
40
|
+
* on all 450 queries to 1e-6), and because no model is bundled it SHRINKS the
|
|
41
|
+
* first-run fetch: the ONNX file it loads is 23MB against fp32's 91MB. 'q4' is dominated: equal
|
|
42
|
+
* accuracy, only -3% latency, 6.1s cold start against fp32's 1.6s. The default
|
|
43
|
+
* is untouched because it is a product decision, not because the cost is
|
|
44
|
+
* unknown; see docs/recall-latency.md.
|
|
45
|
+
*/
|
|
46
|
+
const DTYPE = (process.env.AWM_RERANKER_DTYPE || 'fp32') as 'fp32' | 'fp16' | 'q8' | 'int8' | 'uint8' | 'q4';
|
|
47
|
+
|
|
48
|
+
// --- In-process fallback ---
|
|
49
|
+
|
|
50
|
+
let tokenizer: PreTrainedTokenizer | null = null;
|
|
51
|
+
let model: PreTrainedModel | null = null;
|
|
52
|
+
let initPromise: Promise<void> | null = null;
|
|
53
|
+
|
|
54
|
+
async function ensureLoaded(): Promise<void> {
|
|
55
|
+
if (tokenizer && model) return;
|
|
56
|
+
if (initPromise) return initPromise;
|
|
57
|
+
initPromise = (async () => {
|
|
58
|
+
ensureModelCacheDir();
|
|
59
|
+
tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
|
|
60
|
+
model = await AutoModelForSequenceClassification.from_pretrained(MODEL_ID, { dtype: DTYPE });
|
|
61
|
+
console.error(`Re-ranker model loaded in-process: ${MODEL_ID} (${DTYPE})`);
|
|
62
|
+
})();
|
|
63
|
+
return initPromise;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function sigmoid(x: number): number {
|
|
67
|
+
return 1 / (1 + Math.exp(-x));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function inProcessRerank(args: { query: string; passages: string[] }): Promise<Array<{ index: number; score: number }>> {
|
|
71
|
+
const { query, passages } = args;
|
|
72
|
+
if (passages.length === 0) return [];
|
|
73
|
+
await ensureLoaded();
|
|
74
|
+
|
|
75
|
+
// Batch path
|
|
76
|
+
try {
|
|
77
|
+
const queries = passages.map(() => query);
|
|
78
|
+
const inputs = tokenizer!(queries, {
|
|
79
|
+
text_pair: passages,
|
|
80
|
+
padding: true,
|
|
81
|
+
truncation: true,
|
|
82
|
+
// NOT 'return_tensors'. That key never existed in transformers.js -- it is the
|
|
83
|
+
// PyTorch Python spelling -- so from 0.5.2 (commit 1ccbf95, 2026-03-21) until
|
|
84
|
+
// 2026-10-09 it was silently ignored and the library default
|
|
85
|
+
// (return_tensor=true, i.e. Tensors) applied.
|
|
86
|
+
// Stating it explicitly preserves exactly the behaviour that was already
|
|
87
|
+
// running, and survives a future change of default. transformers 4.x turned
|
|
88
|
+
// the typo into a type error, which is the only reason it was ever noticed.
|
|
89
|
+
return_tensor: true,
|
|
90
|
+
});
|
|
91
|
+
const output = await model!(inputs);
|
|
92
|
+
const logits = output.logits ?? output.last_hidden_state;
|
|
93
|
+
const data = logits.data as Float32Array | number[];
|
|
94
|
+
const results: Array<{ index: number; score: number }> = [];
|
|
95
|
+
for (let i = 0; i < passages.length; i++) {
|
|
96
|
+
const rawLogit = Number(data[i] ?? 0);
|
|
97
|
+
results.push({ index: i, score: sigmoid(rawLogit) });
|
|
98
|
+
}
|
|
99
|
+
results.sort((a, b) => b.score - a.score);
|
|
100
|
+
return results;
|
|
101
|
+
} catch {
|
|
102
|
+
// Per-passage fallback (the original 0.7.13 path)
|
|
103
|
+
const results: Array<{ index: number; score: number }> = [];
|
|
104
|
+
for (let i = 0; i < passages.length; i++) {
|
|
105
|
+
try {
|
|
106
|
+
const inputs = tokenizer!(query, {
|
|
107
|
+
text_pair: passages[i],
|
|
108
|
+
padding: true,
|
|
109
|
+
truncation: true,
|
|
110
|
+
// Same ignored-key story as the batch path above.
|
|
111
|
+
return_tensor: true,
|
|
112
|
+
});
|
|
113
|
+
const output = await model!(inputs);
|
|
114
|
+
const logits = output.logits ?? output.last_hidden_state;
|
|
115
|
+
const rawLogit = logits.data[0] as number;
|
|
116
|
+
results.push({ index: i, score: sigmoid(rawLogit) });
|
|
117
|
+
} catch {
|
|
118
|
+
results.push({ index: i, score: 0 });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
results.sort((a, b) => b.score - a.score);
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Register the in-process handler with the pool
|
|
127
|
+
registerInProcessHandlers({ rerank: inProcessRerank });
|
|
128
|
+
|
|
129
|
+
// --- Public API ---
|
|
130
|
+
|
|
131
|
+
/** Kept for backwards compat. */
|
|
132
|
+
export async function getReranker(): Promise<any> {
|
|
133
|
+
await ensureLoaded();
|
|
134
|
+
return model;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface RerankResult {
|
|
138
|
+
index: number;
|
|
139
|
+
score: number; // sigmoid-normalized relevance (0-1)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Re-rank candidate passages against a query using the cross-encoder.
|
|
144
|
+
* Returns results sorted by relevance score (descending).
|
|
145
|
+
* Dispatches to the worker pool (or in-process fallback).
|
|
146
|
+
*/
|
|
147
|
+
export async function rerank(query: string, passages: string[]): Promise<RerankResult[]> {
|
|
148
|
+
if (passages.length === 0) return [];
|
|
149
|
+
return dispatchRerank({ query, passages });
|
|
150
|
+
}
|