agentcache 0.3.0 → 0.3.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
CHANGED
|
@@ -27,33 +27,43 @@ No `init`. No `setup`. No config. No second command. The install itself:
|
|
|
27
27
|
2. Detects installed IDEs (Claude Code, Cursor, Roo Code, Windsurf, Continue, Codex)
|
|
28
28
|
3. Registers itself as an MCP server in each
|
|
29
29
|
4. Sets up Claude Code hooks for automatic transcript recovery
|
|
30
|
+
5. Spawns `compile-all` in background — compiles your entire transcript history from all IDEs immediately
|
|
30
31
|
|
|
31
32
|
## How It Works
|
|
32
33
|
|
|
33
34
|
```
|
|
34
|
-
|
|
35
|
-
│
|
|
36
|
-
│
|
|
37
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
38
|
-
│ │ Claude │ │ Cursor │ │ Roo │ │ Codex │ ...
|
|
39
|
-
│ │ Code │ │ │ │ Code │ │ │
|
|
40
|
-
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
41
|
-
│ │ │ │ │
|
|
42
|
-
│ └──────────────┴──────────────┴──────────────┘
|
|
43
|
-
│ │
|
|
44
|
-
│ MCP Protocol (stdio)
|
|
45
|
-
│ │
|
|
46
|
-
│ ┌────────────┴────────────┐
|
|
47
|
-
│ │ AgentCache MCP Server │
|
|
48
|
-
│ │ (agentcache serve) │
|
|
49
|
-
│
|
|
50
|
-
│
|
|
51
|
-
│
|
|
52
|
-
│
|
|
53
|
-
│
|
|
54
|
-
│
|
|
55
|
-
│
|
|
56
|
-
|
|
35
|
+
┌──────────────────────────────────────────────────────────────────────┐
|
|
36
|
+
│ Your Machine │
|
|
37
|
+
│ │
|
|
38
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
39
|
+
│ │ Claude │ │ Cursor │ │ Roo │ │ Codex │ ... │
|
|
40
|
+
│ │ Code │ │ │ │ Code │ │ │ │
|
|
41
|
+
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
|
42
|
+
│ │ │ │ │ │
|
|
43
|
+
│ └──────────────┴──────────────┴──────────────┘ │
|
|
44
|
+
│ │ │
|
|
45
|
+
│ MCP Protocol (stdio) │
|
|
46
|
+
│ │ │
|
|
47
|
+
│ ┌────────────┴────────────┐ ┌────────────────────┐ │
|
|
48
|
+
│ │ AgentCache MCP Server │ │ agentcache │ │
|
|
49
|
+
│ │ (agentcache serve) │ │ compile-all │ │
|
|
50
|
+
│ │ │ │ (standalone CLI) │ │
|
|
51
|
+
│ │ spawns compile-all ─────┼───▶│ │ │
|
|
52
|
+
│ │ when pending > 20 │ │ Uses: claude, │ │
|
|
53
|
+
│ └────────────┬────────────┘ │ codex, gemini, │ │
|
|
54
|
+
│ │ │ ollama, API keys │ │
|
|
55
|
+
│ │ └─────────┬──────────┘ │
|
|
56
|
+
│ │ │ │
|
|
57
|
+
│ ┌─────────┴────────────────────────────┘ │
|
|
58
|
+
│ │ │
|
|
59
|
+
│ ▼ │
|
|
60
|
+
│ ┌───────────────────┐ │
|
|
61
|
+
│ │ ~/.agentcache/ │ │
|
|
62
|
+
│ │ agentcache.db │ │
|
|
63
|
+
│ │ compile-all.lock │ │
|
|
64
|
+
│ │ (SQLite + WAL) │ │
|
|
65
|
+
│ └───────────────────┘ │
|
|
66
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
57
67
|
```
|
|
58
68
|
|
|
59
69
|
### The Cycle
|
|
@@ -92,9 +102,33 @@ AgentCache exposes 8 tools via the Model Context Protocol (prefixed as `mcp--age
|
|
|
92
102
|
|
|
93
103
|
```bash
|
|
94
104
|
agentcache status # Show knowledge stats for current project
|
|
105
|
+
agentcache compile-all # Batch-compile all unprocessed transcripts
|
|
95
106
|
agentcache setup # Re-register with IDEs (only if postinstall failed)
|
|
96
107
|
```
|
|
97
108
|
|
|
109
|
+
### `compile-all` — Standalone Batch Compilation
|
|
110
|
+
|
|
111
|
+
Processes all pending transcripts across every IDE without depending on MCP pipes or active sessions. Runs independently in a terminal.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
agentcache compile-all
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**LLM backend detection** (first available wins):
|
|
118
|
+
1. CLI tools with stored auth: `claude`, `codex`, `gemini`, `copilot`, `aider`, `goose`
|
|
119
|
+
2. Ollama running locally (`localhost:11434`)
|
|
120
|
+
3. `ANTHROPIC_API_KEY` environment variable
|
|
121
|
+
4. `OPENAI_API_KEY` environment variable
|
|
122
|
+
|
|
123
|
+
No API keys needed if you have any coding CLI installed — it uses their stored authentication.
|
|
124
|
+
|
|
125
|
+
**Automatic triggers:**
|
|
126
|
+
- Runs as a background process after `npm install -g agentcache` (clears initial backlog)
|
|
127
|
+
- Spawned by the MCP server when pending transcripts exceed 20 (ongoing janitor)
|
|
128
|
+
- Lockfile (`~/.agentcache/compile-all.lock`) prevents concurrent runs
|
|
129
|
+
|
|
130
|
+
**Transcript sources:** Claude Code, Continue, Codex, Roo Code, Goose
|
|
131
|
+
|
|
98
132
|
Internal commands (called by hooks automatically, never by users):
|
|
99
133
|
```bash
|
|
100
134
|
agentcache serve # MCP server (IDEs spawn this)
|
|
@@ -119,9 +153,10 @@ One database per developer (`~/.agentcache/agentcache.db`), not per project. Rul
|
|
|
119
153
|
|
|
120
154
|
### Resilient to Abrupt Exits
|
|
121
155
|
|
|
122
|
-
Sessions can end without warning (crash, ctrl-c, network drop). AgentCache handles this through:
|
|
156
|
+
Sessions can end without warning (crash, ctrl-c, network drop, MCP pipe death). AgentCache handles this through:
|
|
123
157
|
- **Incremental submission** — observations are saved as they happen, not batched at the end
|
|
124
|
-
- **Transcript recovery** —
|
|
158
|
+
- **Transcript recovery** — transcripts persist on disk across 5 IDEs (Claude Code, Continue, Codex, Roo Code, Goose) and are compiled by `compile-all`
|
|
159
|
+
- **Pipe-independent compilation** — `compile-all` runs as a standalone process, not through MCP stdio pipes that can break during long operations
|
|
125
160
|
- **Pending queue in SQLite** — concurrent access is safe, nothing lost to race conditions
|
|
126
161
|
|
|
127
162
|
### Anti-Bloat
|
|
@@ -138,15 +173,18 @@ AgentCache prevents knowledge from growing unbounded:
|
|
|
138
173
|
|-----|-----|-------------|--------------------|----|
|
|
139
174
|
| Claude Code | Yes | Yes (automatic) | Full (JSONL) | Stop, SessionStart, PreToolUse |
|
|
140
175
|
| Cursor | Yes | Yes (automatic) | Incremental only | — |
|
|
141
|
-
| Roo Code | Yes | Yes (automatic) |
|
|
176
|
+
| Roo Code | Yes | Yes (automatic) | Full (JSON via compile-all) | — |
|
|
142
177
|
| Windsurf | Yes | Yes (automatic) | Incremental only | — |
|
|
143
178
|
| Continue | Yes | Yes (automatic) | Full (JSON) | — |
|
|
144
|
-
| Codex | Yes | Yes (automatic) |
|
|
179
|
+
| Codex | Yes | Yes (automatic) | Full (JSONL via compile-all) | — |
|
|
180
|
+
| Goose | — | — | Full (SQLite via compile-all) | — |
|
|
145
181
|
|
|
146
182
|
All IDEs are fully auto-approved at install time — no manual steps required.
|
|
147
183
|
|
|
148
184
|
"Incremental only" means if the agent submits observations during the session, they're saved. If the session terminates before any submission, those observations are lost (no transcript access).
|
|
149
185
|
|
|
186
|
+
"via compile-all" means `agentcache compile-all` discovers and processes these transcripts in batch, independent of any active MCP session.
|
|
187
|
+
|
|
150
188
|
## Data Storage
|
|
151
189
|
|
|
152
190
|
All data lives in `~/.agentcache/agentcache.db` (SQLite with WAL mode for concurrent access).
|
|
@@ -176,7 +214,9 @@ Extract → Normalize → Canonicalize → Cluster → Detect Contradictions →
|
|
|
176
214
|
- authority: AUTO/USER
|
|
177
215
|
```
|
|
178
216
|
|
|
179
|
-
|
|
217
|
+
**Two compilation paths:**
|
|
218
|
+
- **In-session** — the agent in your IDE processes extraction prompts via MCP tools (no separate LLM calls needed)
|
|
219
|
+
- **Batch (`compile-all`)** — runs independently using any available LLM CLI or API, processes the full backlog without depending on active sessions
|
|
180
220
|
|
|
181
221
|
## Project Identity
|
|
182
222
|
|
|
@@ -197,7 +237,7 @@ Projects are identified by a hash of their full filesystem path, not just the fo
|
|
|
197
237
|
| Windsurf | Supported |
|
|
198
238
|
| Continue | Supported |
|
|
199
239
|
| Codex | Supported |
|
|
200
|
-
| Goose (
|
|
240
|
+
| Goose | Supported (transcript recovery via SQLite) |
|
|
201
241
|
| Aider | Coming soon |
|
|
202
242
|
| GitHub Copilot | Coming soon |
|
|
203
243
|
| Zed AI | Coming soon |
|
|
@@ -428,6 +428,97 @@ function formatItems(items) {
|
|
|
428
428
|
}).join("\n") + "\n";
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
+
// src/knowledge/passes/7b-skill-projector.ts
|
|
432
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
433
|
+
import { join } from "path";
|
|
434
|
+
import { homedir } from "os";
|
|
435
|
+
var MAX_SKILL_TOKENS = 5e3;
|
|
436
|
+
var AVG_CHARS_PER_TOKEN = 4;
|
|
437
|
+
var MAX_SKILL_CHARS = MAX_SKILL_TOKENS * AVG_CHARS_PER_TOKEN;
|
|
438
|
+
function projectToSkills(items, projectRoot) {
|
|
439
|
+
const active = items.filter((i) => i.status === "active");
|
|
440
|
+
const globalItems = active.filter((i) => i.scope === "global");
|
|
441
|
+
const projectItems = active.filter((i) => i.scope === "project");
|
|
442
|
+
writeGlobalSkill(globalItems);
|
|
443
|
+
writeProjectSkill(projectItems, projectRoot);
|
|
444
|
+
}
|
|
445
|
+
function writeGlobalSkill(items) {
|
|
446
|
+
const skillDir = join(homedir(), ".agentcache", "skills", "developer-knowledge");
|
|
447
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
448
|
+
const rules = items.filter((i) => i.type === "rule").sort(byConfidence);
|
|
449
|
+
const lessons = items.filter((i) => i.type === "lesson").sort(byConfidence);
|
|
450
|
+
const body = buildSkillBody(rules, lessons, [], []);
|
|
451
|
+
const content = buildSkillFile(
|
|
452
|
+
"developer-knowledge",
|
|
453
|
+
"Engineering rules and lessons learned across all projects \u2014 compiled automatically from coding sessions by AgentCache",
|
|
454
|
+
body
|
|
455
|
+
);
|
|
456
|
+
writeFileSync2(join(skillDir, "SKILL.md"), truncateToLimit(content), "utf-8");
|
|
457
|
+
}
|
|
458
|
+
function writeProjectSkill(items, projectRoot) {
|
|
459
|
+
if (!projectRoot || projectRoot === process.cwd()) return;
|
|
460
|
+
if (items.length === 0) return;
|
|
461
|
+
const skillDir = join(projectRoot, ".agentcache", "skills", "project-knowledge");
|
|
462
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
463
|
+
const rules = items.filter((i) => i.type === "rule").sort(byConfidence);
|
|
464
|
+
const lessons = items.filter((i) => i.type === "lesson").sort(byConfidence);
|
|
465
|
+
const decisions = items.filter((i) => i.type === "decision").sort(byConfidence);
|
|
466
|
+
const context = items.filter((i) => i.type === "context").sort((a, b) => b.lastSeenAt - a.lastSeenAt);
|
|
467
|
+
const body = buildSkillBody(rules, lessons, decisions, context);
|
|
468
|
+
const content = buildSkillFile(
|
|
469
|
+
"project-knowledge",
|
|
470
|
+
"Project-specific decisions, rules, context, and lessons \u2014 compiled automatically from coding sessions by AgentCache",
|
|
471
|
+
body
|
|
472
|
+
);
|
|
473
|
+
writeFileSync2(join(skillDir, "SKILL.md"), truncateToLimit(content), "utf-8");
|
|
474
|
+
}
|
|
475
|
+
function buildSkillFile(name, description, body) {
|
|
476
|
+
return `---
|
|
477
|
+
name: ${name}
|
|
478
|
+
description: "${description}"
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
${body}`;
|
|
482
|
+
}
|
|
483
|
+
function buildSkillBody(rules, lessons, decisions, context) {
|
|
484
|
+
let out = "";
|
|
485
|
+
if (rules.length > 0) {
|
|
486
|
+
out += "## Rules\n\nFollow these without exception:\n\n";
|
|
487
|
+
out += rules.map((r) => `- ${r.content}${enforceTag(r)}`).join("\n") + "\n\n";
|
|
488
|
+
}
|
|
489
|
+
if (lessons.length > 0) {
|
|
490
|
+
out += "## Lessons\n\nPitfalls learned from past sessions:\n\n";
|
|
491
|
+
out += lessons.map((l) => `- ${l.content}`).join("\n") + "\n\n";
|
|
492
|
+
}
|
|
493
|
+
if (decisions.length > 0) {
|
|
494
|
+
out += "## Decisions\n\nArchitectural choices in effect \u2014 do not contradict:\n\n";
|
|
495
|
+
out += decisions.map((d) => `- ${d.content}`).join("\n") + "\n\n";
|
|
496
|
+
}
|
|
497
|
+
if (context.length > 0) {
|
|
498
|
+
out += "## Current Context\n\nActive project state (may be temporal):\n\n";
|
|
499
|
+
out += context.map((c) => `- ${c.content}`).join("\n") + "\n\n";
|
|
500
|
+
}
|
|
501
|
+
return out.trimEnd() + "\n";
|
|
502
|
+
}
|
|
503
|
+
function enforceTag(item) {
|
|
504
|
+
return item.enforce ? " [ENFORCED]" : "";
|
|
505
|
+
}
|
|
506
|
+
function byConfidence(a, b) {
|
|
507
|
+
const order = { high: 3, medium: 2, low: 1 };
|
|
508
|
+
return (order[b.confidence] || 0) - (order[a.confidence] || 0);
|
|
509
|
+
}
|
|
510
|
+
function truncateToLimit(content) {
|
|
511
|
+
if (content.length <= MAX_SKILL_CHARS) return content;
|
|
512
|
+
const lines = content.split("\n");
|
|
513
|
+
let result = "";
|
|
514
|
+
for (const line of lines) {
|
|
515
|
+
if ((result + line + "\n").length > MAX_SKILL_CHARS - 50) break;
|
|
516
|
+
result += line + "\n";
|
|
517
|
+
}
|
|
518
|
+
result += "\n<!-- Truncated to stay within 5000 token skill budget -->\n";
|
|
519
|
+
return result;
|
|
520
|
+
}
|
|
521
|
+
|
|
431
522
|
// src/knowledge/compiler.ts
|
|
432
523
|
var COMPILER_VERSION = "0.1.0";
|
|
433
524
|
function startCompile(events, sessionId, project, projectRoot, repo, transcriptPath) {
|
|
@@ -472,7 +563,9 @@ function processExtraction(repo, responseText, sessionId, project, projectRoot)
|
|
|
472
563
|
repo.saveObservations(normalized);
|
|
473
564
|
if (canonicalized.needsClustering.length === 0) {
|
|
474
565
|
saveCompileRun(repo, sessionId, project, normalized.length, canonicalized.autoReinforced.length, 0, 0, 0, 0, 0, Date.now());
|
|
475
|
-
|
|
566
|
+
const activeItems = repo.getKnowledgeItems(project, { status: "active" });
|
|
567
|
+
projectToMarkdown(activeItems, getDataDir(), COMPILER_VERSION);
|
|
568
|
+
projectToSkills(activeItems, projectRoot);
|
|
476
569
|
return {
|
|
477
570
|
status: "complete",
|
|
478
571
|
diagnostics: formatDiagnostics(normalized.length, canonicalized.autoReinforced.length, 0, 0, 0, 0, 0, project, sessionId)
|
|
@@ -539,7 +632,9 @@ function processClustering(repo, responseText, sessionId, project, projectRoot)
|
|
|
539
632
|
}
|
|
540
633
|
const totalObs = sessionObs.length;
|
|
541
634
|
saveCompileRun(repo, sessionId, project, totalObs, 0, compiled.created.length, compiled.reinforced.length, compiled.superseded.length, compiled.deprecated.length, compiled.ignored, startedAt);
|
|
542
|
-
|
|
635
|
+
const activeItems = repo.getKnowledgeItems(project, { status: "active" });
|
|
636
|
+
projectToMarkdown(activeItems, getDataDir(), COMPILER_VERSION);
|
|
637
|
+
projectToSkills(activeItems, projectRoot);
|
|
543
638
|
return {
|
|
544
639
|
status: "complete",
|
|
545
640
|
diagnostics: formatDiagnostics(totalObs, 0, compiled.created.length, compiled.reinforced.length, compiled.superseded.length, compiled.deprecated.length, compiled.ignored, project, sessionId)
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
var program = new Command();
|
|
6
|
-
program.name("agentcache").description("Engineering Knowledge Compiler \u2014 universal, zero-config").version("0.3.
|
|
6
|
+
program.name("agentcache").description("Engineering Knowledge Compiler \u2014 universal, zero-config").version("0.3.1");
|
|
7
7
|
program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
|
|
8
8
|
const { runSetup } = await import("./setup-5APZETPV.js");
|
|
9
9
|
await runSetup();
|
|
@@ -46,7 +46,7 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
|
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
program.command("compile-all").description("Batch-compile all unprocessed transcripts using an available LLM CLI").action(async () => {
|
|
49
|
-
const { runCompileAll } = await import("./compile-all-
|
|
49
|
+
const { runCompileAll } = await import("./compile-all-DOQ5XU5K.js");
|
|
50
50
|
await runCompileAll();
|
|
51
51
|
});
|
|
52
52
|
program.command("status").description("Show AgentCache knowledge stats").action(async () => {
|
package/dist/mcp.js
CHANGED