agentcache 0.1.4 → 0.2.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/README.md +19 -18
- package/dist/{chunk-MKQKD2PY.js → chunk-LDQPTAZ7.js} +34 -25
- package/dist/{chunk-QGG25FWV.js → chunk-OSFK44XC.js} +1 -1
- package/dist/{chunk-PYGRUQNL.js → chunk-T7BJPANN.js} +3 -3
- package/dist/{chunk-VPEEZXLK.js → chunk-WHP4Z32Z.js} +17 -8
- package/dist/cli.js +11 -11
- package/dist/mcp.js +32 -32
- package/dist/{paths-TWJ7GAJY.js → paths-LEZQCRKI.js} +7 -5
- package/dist/postinstall.js +6 -4
- package/dist/{pre-tool-use-2P5P6JWE.js → pre-tool-use-TPCPTJXS.js} +4 -4
- package/dist/{session-start-ILEPFZZC.js → session-start-BIY7CBXU.js} +4 -4
- package/dist/{setup-YHD2FO4N.js → setup-YCFTG2KT.js} +8 -6
- package/dist/{stop-DRL3LXFQ.js → stop-6MKD743B.js} +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ npm install -g agentcache
|
|
|
23
23
|
Done. Start a new session in any IDE. AgentCache is already running.
|
|
24
24
|
|
|
25
25
|
No `init`. No `setup`. No config. No second command. The install itself:
|
|
26
|
-
1. Creates `~/.
|
|
26
|
+
1. Creates `~/.agentcache/agentcache.db` (your knowledge store)
|
|
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
|
|
@@ -49,7 +49,8 @@ No `init`. No `setup`. No config. No second command. The install itself:
|
|
|
49
49
|
│ └────────────┬────────────┘ │
|
|
50
50
|
│ │ │
|
|
51
51
|
│ ┌─────────┴─────────┐ │
|
|
52
|
-
│ │
|
|
52
|
+
│ │ ~/.agentcache/ │ │
|
|
53
|
+
│ │ agentcache.db │ │
|
|
53
54
|
│ │ (SQLite + WAL) │ │
|
|
54
55
|
│ └───────────────────┘ │
|
|
55
56
|
└─────────────────────────────────────────────────────────────────┘
|
|
@@ -57,8 +58,8 @@ No `init`. No `setup`. No config. No second command. The install itself:
|
|
|
57
58
|
|
|
58
59
|
### The Cycle
|
|
59
60
|
|
|
60
|
-
1. **Session starts** — agent calls `
|
|
61
|
-
2. **During session** — agent calls `
|
|
61
|
+
1. **Session starts** — agent calls `agentcache_inject_context` → gets compiled rules, lessons, decisions
|
|
62
|
+
2. **During session** — agent calls `agentcache_compile_submit` incrementally as it learns things
|
|
62
63
|
3. **Session ends** — knowledge is already saved. If agent didn't submit (abrupt exit), transcript recovery handles it next session.
|
|
63
64
|
|
|
64
65
|
### Knowledge Types
|
|
@@ -78,14 +79,14 @@ AgentCache exposes 8 tools via the Model Context Protocol:
|
|
|
78
79
|
|
|
79
80
|
| Tool | Purpose |
|
|
80
81
|
|------|---------|
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
82
|
+
| `agentcache_inject_context` | Load compiled knowledge at session start |
|
|
83
|
+
| `agentcache_compile_submit` | Submit observations incrementally during session |
|
|
84
|
+
| `agentcache_compile_cluster` | Resolve clustering when observations overlap existing knowledge |
|
|
85
|
+
| `agentcache_compile_extract` | Process queued transcripts from previous sessions |
|
|
86
|
+
| `agentcache_enforce` | Check tool calls against enforced policy rules |
|
|
87
|
+
| `agentcache_save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
|
|
88
|
+
| `agentcache_get_knowledge` | Query the knowledge database |
|
|
89
|
+
| `agentcache_deprecate_knowledge` | Mark knowledge as deprecated when it's no longer valid |
|
|
89
90
|
|
|
90
91
|
## CLI Commands
|
|
91
92
|
|
|
@@ -114,7 +115,7 @@ AgentCache uses MCP (Model Context Protocol) as its only interface. Any IDE that
|
|
|
114
115
|
|
|
115
116
|
### Developer-Scoped
|
|
116
117
|
|
|
117
|
-
One database per developer (`~/.
|
|
118
|
+
One database per developer (`~/.agentcache/agentcache.db`), not per project. Rules and lessons learned in one project benefit all your projects. Project-specific decisions stay scoped to their project.
|
|
118
119
|
|
|
119
120
|
### Resilient to Abrupt Exits
|
|
120
121
|
|
|
@@ -154,11 +155,11 @@ Cursor does not support programmatic auto-approve for MCP tools. After installin
|
|
|
154
155
|
|
|
155
156
|
## Data Storage
|
|
156
157
|
|
|
157
|
-
All data lives in `~/.
|
|
158
|
+
All data lives in `~/.agentcache/agentcache.db` (SQLite with WAL mode for concurrent access).
|
|
158
159
|
|
|
159
160
|
```
|
|
160
|
-
~/.
|
|
161
|
-
└──
|
|
161
|
+
~/.agentcache/
|
|
162
|
+
└── agentcache.db # All knowledge, observations, sessions, pending queue
|
|
162
163
|
```
|
|
163
164
|
|
|
164
165
|
No data leaves your machine. No network calls. No telemetry. No accounts.
|
|
@@ -193,8 +194,8 @@ Projects are identified by a hash of their full filesystem path, not just the fo
|
|
|
193
194
|
## Contributing
|
|
194
195
|
|
|
195
196
|
```bash
|
|
196
|
-
git clone https://github.com/raghav-a21ai/
|
|
197
|
-
cd
|
|
197
|
+
git clone https://github.com/raghav-a21ai/agentcache
|
|
198
|
+
cd agentcache
|
|
198
199
|
npm install
|
|
199
200
|
npm run build
|
|
200
201
|
npm test
|
|
@@ -90,14 +90,14 @@ function isVscodeExtensionIde(ide) {
|
|
|
90
90
|
return ide.name === "Roo Code" || ide.name === "Continue";
|
|
91
91
|
}
|
|
92
92
|
var ALL_TOOLS = [
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
93
|
+
"agentcache_inject_context",
|
|
94
|
+
"agentcache_compile_submit",
|
|
95
|
+
"agentcache_compile_cluster",
|
|
96
|
+
"agentcache_compile_extract",
|
|
97
|
+
"agentcache_enforce",
|
|
98
|
+
"agentcache_save_observation",
|
|
99
|
+
"agentcache_get_knowledge",
|
|
100
|
+
"agentcache_deprecate_knowledge"
|
|
101
101
|
];
|
|
102
102
|
function registerMcpServer(ide) {
|
|
103
103
|
if (!ide.detected) return false;
|
|
@@ -126,14 +126,17 @@ function registerClaudeCode() {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
if (!config.mcpServers) config.mcpServers = {};
|
|
129
|
-
|
|
130
|
-
config.mcpServers.agentcache
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
129
|
+
let serverRegistered = false;
|
|
130
|
+
if (!config.mcpServers.agentcache) {
|
|
131
|
+
config.mcpServers.agentcache = {
|
|
132
|
+
type: "stdio",
|
|
133
|
+
command: "agentcache",
|
|
134
|
+
args: ["serve"],
|
|
135
|
+
env: {}
|
|
136
|
+
};
|
|
137
|
+
writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
|
|
138
|
+
serverRegistered = true;
|
|
139
|
+
}
|
|
137
140
|
const settingsPath = join2(homedir2(), ".claude", "settings.json");
|
|
138
141
|
if (existsSync2(join2(homedir2(), ".claude"))) {
|
|
139
142
|
let settings = {};
|
|
@@ -148,14 +151,18 @@ function registerClaudeCode() {
|
|
|
148
151
|
if (!settings.permissions.allow) settings.permissions.allow = [];
|
|
149
152
|
const allowList = settings.permissions.allow;
|
|
150
153
|
const mcpPerms = ALL_TOOLS.map((t) => `mcp__agentcache__${t}`);
|
|
154
|
+
let permsUpdated = false;
|
|
151
155
|
for (const perm of mcpPerms) {
|
|
152
156
|
if (!allowList.includes(perm)) {
|
|
153
157
|
allowList.push(perm);
|
|
158
|
+
permsUpdated = true;
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
|
-
|
|
161
|
+
if (permsUpdated) {
|
|
162
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
163
|
+
}
|
|
157
164
|
}
|
|
158
|
-
return
|
|
165
|
+
return serverRegistered;
|
|
159
166
|
}
|
|
160
167
|
function registerMcpJson(ide) {
|
|
161
168
|
let config = {};
|
|
@@ -167,7 +174,7 @@ function registerMcpJson(ide) {
|
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
176
|
if (!config.mcpServers) config.mcpServers = {};
|
|
170
|
-
|
|
177
|
+
const existing = config.mcpServers.agentcache;
|
|
171
178
|
if (isVscodeExtensionIde(ide)) {
|
|
172
179
|
const nodeBin = findNodeBinary();
|
|
173
180
|
const script = findAgentcacheScript();
|
|
@@ -177,16 +184,18 @@ function registerMcpJson(ide) {
|
|
|
177
184
|
alwaysAllow: ALL_TOOLS,
|
|
178
185
|
disabled: false
|
|
179
186
|
};
|
|
180
|
-
} else {
|
|
187
|
+
} else if (!existing) {
|
|
181
188
|
const agentcacheBin = findAgentcacheScript();
|
|
182
189
|
config.mcpServers.agentcache = {
|
|
183
190
|
command: agentcacheBin,
|
|
184
191
|
args: ["serve"]
|
|
185
192
|
};
|
|
193
|
+
} else {
|
|
194
|
+
return false;
|
|
186
195
|
}
|
|
187
196
|
mkdirSync(dirname(ide.mcpConfigPath), { recursive: true });
|
|
188
197
|
writeFileSync(ide.mcpConfigPath, JSON.stringify(config, null, 2));
|
|
189
|
-
return
|
|
198
|
+
return !existing;
|
|
190
199
|
}
|
|
191
200
|
function registerContinue(ide) {
|
|
192
201
|
const configPath = ide.mcpConfigPath;
|
|
@@ -245,17 +254,17 @@ function registerClaudeHooks() {
|
|
|
245
254
|
}
|
|
246
255
|
if (!settings.hooks) settings.hooks = {};
|
|
247
256
|
const hooks = settings.hooks;
|
|
248
|
-
const
|
|
257
|
+
const agentcacheHooks = {
|
|
249
258
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: "agentcache compile-session" }] }],
|
|
250
259
|
SessionStart: [{ matcher: "", hooks: [{ type: "command", command: "agentcache discover" }] }],
|
|
251
260
|
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: "agentcache enforce" }] }]
|
|
252
261
|
};
|
|
253
262
|
let registered = false;
|
|
254
|
-
for (const [event, hookConfig] of Object.entries(
|
|
263
|
+
for (const [event, hookConfig] of Object.entries(agentcacheHooks)) {
|
|
255
264
|
if (!hooks[event]) hooks[event] = [];
|
|
256
265
|
const existing = hooks[event];
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
266
|
+
const hasAgentcache = existing.some((h) => h.hooks?.some((hh) => hh.command?.includes("agentcache")));
|
|
267
|
+
if (!hasAgentcache) {
|
|
259
268
|
hooks[event].push(...hookConfig);
|
|
260
269
|
registered = true;
|
|
261
270
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/policy/engine.ts
|
|
2
2
|
var HARDCODED_BLOCKS = [
|
|
3
|
-
{ pattern: /git\s+push\s+--force\s+(origin\s+)?(main|master)/i, reason: "Force-push to main/master is blocked by
|
|
4
|
-
{ pattern: /rm\s+-rf\s+[\/~]/i, reason: "Destructive rm -rf on root or home is blocked by
|
|
5
|
-
{ pattern: />\s*(.*\.(env|pem|key))/i, reason: "Writing to sensitive files (.env, .pem, .key) is blocked by
|
|
3
|
+
{ pattern: /git\s+push\s+--force\s+(origin\s+)?(main|master)/i, reason: "Force-push to main/master is blocked by AgentCache policy" },
|
|
4
|
+
{ pattern: /rm\s+-rf\s+[\/~]/i, reason: "Destructive rm -rf on root or home is blocked by AgentCache policy" },
|
|
5
|
+
{ pattern: />\s*(.*\.(env|pem|key))/i, reason: "Writing to sensitive files (.env, .pem, .key) is blocked by AgentCache policy" }
|
|
6
6
|
];
|
|
7
7
|
function evaluatePolicy(input, enforcedRules) {
|
|
8
8
|
const command = extractCommand(input.tool_name, input.tool_input);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/utils/paths.ts
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import { join } from "path";
|
|
2
|
+
import { existsSync, renameSync, mkdirSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
4
|
import { homedir } from "os";
|
|
5
5
|
import { createHash } from "crypto";
|
|
6
6
|
|
|
@@ -26,15 +26,23 @@ function getGitRoot(cwd) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// src/utils/paths.ts
|
|
29
|
-
function
|
|
30
|
-
return join(homedir(), ".
|
|
29
|
+
function getDataDir() {
|
|
30
|
+
return join(homedir(), ".agentcache");
|
|
31
31
|
}
|
|
32
32
|
function getDbPath() {
|
|
33
|
-
return join(
|
|
33
|
+
return join(getDataDir(), "agentcache.db");
|
|
34
34
|
}
|
|
35
|
-
function
|
|
35
|
+
function isInitialized() {
|
|
36
36
|
return existsSync(getDbPath());
|
|
37
37
|
}
|
|
38
|
+
function migrateFromLegacy() {
|
|
39
|
+
const legacyDb = join(homedir(), ".loop", "loop.db");
|
|
40
|
+
const newDb = getDbPath();
|
|
41
|
+
if (existsSync(legacyDb) && !existsSync(newDb)) {
|
|
42
|
+
mkdirSync(dirname(newDb), { recursive: true });
|
|
43
|
+
renameSync(legacyDb, newDb);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
38
46
|
function findProjectRoot(cwd) {
|
|
39
47
|
const dir = cwd || process.cwd();
|
|
40
48
|
const gitRoot = getGitRoot(dir);
|
|
@@ -57,9 +65,10 @@ function getContinueSessionsDir() {
|
|
|
57
65
|
|
|
58
66
|
export {
|
|
59
67
|
getGitContext,
|
|
60
|
-
|
|
68
|
+
getDataDir,
|
|
61
69
|
getDbPath,
|
|
62
|
-
|
|
70
|
+
isInitialized,
|
|
71
|
+
migrateFromLegacy,
|
|
63
72
|
findProjectRoot,
|
|
64
73
|
getProjectId,
|
|
65
74
|
getProjectDisplayName,
|
package/dist/cli.js
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
var program = new Command();
|
|
6
6
|
program.name("agentcache").description("Engineering Knowledge Compiler \u2014 universal, zero-config").version("0.3.0");
|
|
7
|
-
program.command("setup").description("Detect IDEs and register
|
|
8
|
-
const { runSetup } = await import("./setup-
|
|
7
|
+
program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
|
|
8
|
+
const { runSetup } = await import("./setup-YCFTG2KT.js");
|
|
9
9
|
await runSetup();
|
|
10
10
|
});
|
|
11
|
-
program.command("serve").description("Start
|
|
11
|
+
program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").action(async () => {
|
|
12
12
|
const { startMcpServer } = await import("./mcp.js");
|
|
13
13
|
await startMcpServer();
|
|
14
14
|
});
|
|
15
15
|
program.command("compile-session").description("Stop hook: queue transcript for compilation").action(async () => {
|
|
16
|
-
const { handleStop } = await import("./stop-
|
|
16
|
+
const { handleStop } = await import("./stop-6MKD743B.js");
|
|
17
17
|
let payload;
|
|
18
18
|
try {
|
|
19
19
|
let data = "";
|
|
@@ -28,11 +28,11 @@ program.command("compile-session").description("Stop hook: queue transcript for
|
|
|
28
28
|
await handleStop(payload);
|
|
29
29
|
});
|
|
30
30
|
program.command("discover").description("SessionStart hook: discover uncompiled transcripts").action(async () => {
|
|
31
|
-
const { handleSessionStart } = await import("./session-start-
|
|
31
|
+
const { handleSessionStart } = await import("./session-start-BIY7CBXU.js");
|
|
32
32
|
await handleSessionStart();
|
|
33
33
|
});
|
|
34
34
|
program.command("enforce").description("PreToolUse hook: policy enforcement").action(async () => {
|
|
35
|
-
const { handlePreToolUse } = await import("./pre-tool-use-
|
|
35
|
+
const { handlePreToolUse } = await import("./pre-tool-use-TPCPTJXS.js");
|
|
36
36
|
let data = "";
|
|
37
37
|
for await (const chunk of process.stdin) {
|
|
38
38
|
data += chunk;
|
|
@@ -45,10 +45,10 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
|
|
|
45
45
|
process.stdout.write("{}");
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
-
program.command("status").description("Show
|
|
49
|
-
const { getDbPath,
|
|
50
|
-
if (!
|
|
51
|
-
console.log("
|
|
48
|
+
program.command("status").description("Show AgentCache knowledge stats").action(async () => {
|
|
49
|
+
const { getDbPath, isInitialized, findProjectRoot, getProjectId, getProjectDisplayName } = await import("./paths-LEZQCRKI.js");
|
|
50
|
+
if (!isInitialized()) {
|
|
51
|
+
console.log("AgentCache not initialized. Run: agentcache setup");
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
const { SqliteKnowledgeRepository } = await import("./sqlite-5V565IV3.js");
|
|
@@ -65,7 +65,7 @@ program.command("status").description("Show Loop knowledge stats").action(async
|
|
|
65
65
|
const projectItems = items.filter((i) => i.scope === "project");
|
|
66
66
|
const pending = repo.getPendingCount();
|
|
67
67
|
repo.close();
|
|
68
|
-
console.log(`
|
|
68
|
+
console.log(`AgentCache \u2014 ${displayName} (${project})`);
|
|
69
69
|
console.log(` ${items.length} items (${globalItems.length} global, ${projectItems.length} project)`);
|
|
70
70
|
console.log(` ${rules.length} rules | ${lessons.length} lessons | ${decisions.length} decisions | ${context.length} context`);
|
|
71
71
|
if (pending > 0) console.log(` ${pending} sessions pending compilation`);
|
package/dist/mcp.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluatePolicy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-T7BJPANN.js";
|
|
4
4
|
import {
|
|
5
5
|
parseTranscript
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OSFK44XC.js";
|
|
7
7
|
import {
|
|
8
8
|
findProjectRoot,
|
|
9
9
|
getDbPath,
|
|
10
10
|
getGitContext,
|
|
11
11
|
getProjectId,
|
|
12
|
-
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
isInitialized
|
|
13
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
14
14
|
import {
|
|
15
15
|
SqliteKnowledgeRepository
|
|
16
16
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -528,7 +528,7 @@ function saveCompileRun(repo, sessionId, project, observationsProcessed, autoRei
|
|
|
528
528
|
}
|
|
529
529
|
function formatDiagnostics(extracted, autoReinforced, created, reinforced, superseded, deprecated, ignored, project, sessionId) {
|
|
530
530
|
return [
|
|
531
|
-
`
|
|
531
|
+
`AgentCache Compiler v${COMPILER_VERSION}`,
|
|
532
532
|
`Project: ${project} | Session: ${sessionId}`,
|
|
533
533
|
` ${extracted} observations processed`,
|
|
534
534
|
autoReinforced > 0 ? ` ${autoReinforced} auto-reinforced (no LLM needed)` : "",
|
|
@@ -570,7 +570,7 @@ async function startMcpServer() {
|
|
|
570
570
|
{ name: "agentcache", version: "0.1.0" },
|
|
571
571
|
{
|
|
572
572
|
capabilities: { tools: {} },
|
|
573
|
-
instructions: "AgentCache is your knowledge cache. At the START of every session, call
|
|
573
|
+
instructions: "AgentCache is your knowledge cache. At the START of every session, call agentcache_inject_context to load compiled rules, lessons, decisions, and context. Submit observations INCREMENTALLY via agentcache_compile_submit as you learn them \u2014 do not wait until session end."
|
|
574
574
|
}
|
|
575
575
|
);
|
|
576
576
|
server.oninitialized = async () => {
|
|
@@ -582,7 +582,7 @@ async function startMcpServer() {
|
|
|
582
582
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
583
583
|
tools: [
|
|
584
584
|
{
|
|
585
|
-
name: "
|
|
585
|
+
name: "agentcache_inject_context",
|
|
586
586
|
description: "Get compiled engineering knowledge for this project. Returns global rules/lessons (apply everywhere) + project-specific decisions/context. Call this at the START of every session.",
|
|
587
587
|
inputSchema: {
|
|
588
588
|
type: "object",
|
|
@@ -593,7 +593,7 @@ async function startMcpServer() {
|
|
|
593
593
|
}
|
|
594
594
|
},
|
|
595
595
|
{
|
|
596
|
-
name: "
|
|
596
|
+
name: "agentcache_compile_submit",
|
|
597
597
|
description: "Submit observations extracted from your session. Call this INCREMENTALLY \u2014 each time you learn a rule, lesson, decision, or context item. Do NOT batch until end of session; sessions can terminate without warning.",
|
|
598
598
|
inputSchema: {
|
|
599
599
|
type: "object",
|
|
@@ -619,12 +619,12 @@ async function startMcpServer() {
|
|
|
619
619
|
}
|
|
620
620
|
},
|
|
621
621
|
{
|
|
622
|
-
name: "
|
|
623
|
-
description: "Submit clustering decisions when
|
|
622
|
+
name: "agentcache_compile_cluster",
|
|
623
|
+
description: "Submit clustering decisions when agentcache_compile_submit returns needs_clustering. Determines whether observations create new knowledge or relate to existing items.",
|
|
624
624
|
inputSchema: {
|
|
625
625
|
type: "object",
|
|
626
626
|
properties: {
|
|
627
|
-
sessionId: { type: "string", description: "Session ID from
|
|
627
|
+
sessionId: { type: "string", description: "Session ID from agentcache_compile_submit response" },
|
|
628
628
|
clusters: {
|
|
629
629
|
type: "array",
|
|
630
630
|
items: {
|
|
@@ -644,8 +644,8 @@ async function startMcpServer() {
|
|
|
644
644
|
}
|
|
645
645
|
},
|
|
646
646
|
{
|
|
647
|
-
name: "
|
|
648
|
-
description: "For PREVIOUS sessions stored as transcript files. Reads a queued transcript and returns an extraction prompt for you to process. After processing, call
|
|
647
|
+
name: "agentcache_compile_extract",
|
|
648
|
+
description: "For PREVIOUS sessions stored as transcript files. Reads a queued transcript and returns an extraction prompt for you to process. After processing, call agentcache_compile_submit with the results.",
|
|
649
649
|
inputSchema: {
|
|
650
650
|
type: "object",
|
|
651
651
|
properties: {
|
|
@@ -655,8 +655,8 @@ async function startMcpServer() {
|
|
|
655
655
|
}
|
|
656
656
|
},
|
|
657
657
|
{
|
|
658
|
-
name: "
|
|
659
|
-
description: "Check if a tool call is allowed by
|
|
658
|
+
name: "agentcache_enforce",
|
|
659
|
+
description: "Check if a tool call is allowed by AgentCache policy rules. Call this BEFORE executing risky operations (file deletions, force pushes, etc). Returns allow or block with reason.",
|
|
660
660
|
inputSchema: {
|
|
661
661
|
type: "object",
|
|
662
662
|
properties: {
|
|
@@ -668,7 +668,7 @@ async function startMcpServer() {
|
|
|
668
668
|
}
|
|
669
669
|
},
|
|
670
670
|
{
|
|
671
|
-
name: "
|
|
671
|
+
name: "agentcache_save_observation",
|
|
672
672
|
description: "Save a single observation immediately with USER authority (never overwritten by compiler). Use for important rules or decisions that should persist permanently.",
|
|
673
673
|
inputSchema: {
|
|
674
674
|
type: "object",
|
|
@@ -683,8 +683,8 @@ async function startMcpServer() {
|
|
|
683
683
|
}
|
|
684
684
|
},
|
|
685
685
|
{
|
|
686
|
-
name: "
|
|
687
|
-
description: "Query knowledge items from
|
|
686
|
+
name: "agentcache_get_knowledge",
|
|
687
|
+
description: "Query knowledge items from AgentCache knowledge database.",
|
|
688
688
|
inputSchema: {
|
|
689
689
|
type: "object",
|
|
690
690
|
properties: {
|
|
@@ -697,7 +697,7 @@ async function startMcpServer() {
|
|
|
697
697
|
}
|
|
698
698
|
},
|
|
699
699
|
{
|
|
700
|
-
name: "
|
|
700
|
+
name: "agentcache_deprecate_knowledge",
|
|
701
701
|
description: "Mark a knowledge item as deprecated. Use when a rule, lesson, or decision is no longer valid. Works on both auto-compiled and user-saved items.",
|
|
702
702
|
inputSchema: {
|
|
703
703
|
type: "object",
|
|
@@ -711,15 +711,15 @@ async function startMcpServer() {
|
|
|
711
711
|
]
|
|
712
712
|
}));
|
|
713
713
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
714
|
-
if (!
|
|
715
|
-
return { content: [{ type: "text", text: "
|
|
714
|
+
if (!isInitialized()) {
|
|
715
|
+
return { content: [{ type: "text", text: "AgentCache not initialized. Run: agentcache setup" }], isError: true };
|
|
716
716
|
}
|
|
717
717
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
718
718
|
const projectRoot = getResolvedProjectRoot();
|
|
719
719
|
const detectedProject = getResolvedProjectId();
|
|
720
720
|
try {
|
|
721
721
|
switch (request.params.name) {
|
|
722
|
-
case "
|
|
722
|
+
case "agentcache_inject_context": {
|
|
723
723
|
const args = request.params.arguments || {};
|
|
724
724
|
const project = args.project || detectedProject;
|
|
725
725
|
const items = repo.getKnowledgeForContext(project);
|
|
@@ -740,17 +740,17 @@ async function startMcpServer() {
|
|
|
740
740
|
if (context.length) {
|
|
741
741
|
output += "# Context\n" + context.map((c) => `- ${c.content}`).join("\n") + "\n\n";
|
|
742
742
|
}
|
|
743
|
-
if (!output) output = "No compiled knowledge yet. This will populate as you use
|
|
743
|
+
if (!output) output = "No compiled knowledge yet. This will populate as you use AgentCache across sessions.\n";
|
|
744
744
|
const pendingCount = repo.getPendingCount();
|
|
745
745
|
if (pendingCount > 0) {
|
|
746
|
-
output = `<!-- ${pendingCount} previous session(s) pending compilation. Call
|
|
746
|
+
output = `<!-- ${pendingCount} previous session(s) pending compilation. Call agentcache_compile_extract to process. -->
|
|
747
747
|
|
|
748
748
|
` + output;
|
|
749
749
|
}
|
|
750
|
-
output += "\n---\nIMPORTANT: Submit observations incrementally as they happen during this session.\nWhen you learn something (rule, lesson, decision, context), call
|
|
750
|
+
output += "\n---\nIMPORTANT: Submit observations incrementally as they happen during this session.\nWhen you learn something (rule, lesson, decision, context), call agentcache_compile_submit immediately.\nDo NOT wait until the end \u2014 sessions can terminate without warning.\n";
|
|
751
751
|
return { content: [{ type: "text", text: output.trim() }] };
|
|
752
752
|
}
|
|
753
|
-
case "
|
|
753
|
+
case "agentcache_compile_submit": {
|
|
754
754
|
const args = request.params.arguments;
|
|
755
755
|
const project = args.project || detectedProject;
|
|
756
756
|
const sessionId = `sess_${randomUUID4().slice(0, 8)}`;
|
|
@@ -768,14 +768,14 @@ async function startMcpServer() {
|
|
|
768
768
|
content: [{ type: "text", text: JSON.stringify({ status: "needs_clustering", sessionId: result.sessionId, clusteringContext: result.clusteringPrompt }) }]
|
|
769
769
|
};
|
|
770
770
|
}
|
|
771
|
-
case "
|
|
771
|
+
case "agentcache_compile_cluster": {
|
|
772
772
|
const args = request.params.arguments;
|
|
773
773
|
const project = args.project || detectedProject;
|
|
774
774
|
const responseText = JSON.stringify({ clusters: args.clusters });
|
|
775
775
|
const result = processClustering(repo, responseText, args.sessionId, project, projectRoot);
|
|
776
776
|
return { content: [{ type: "text", text: JSON.stringify({ status: "complete", diagnostics: result.diagnostics }) }] };
|
|
777
777
|
}
|
|
778
|
-
case "
|
|
778
|
+
case "agentcache_compile_extract": {
|
|
779
779
|
const args = request.params.arguments || {};
|
|
780
780
|
const entry = repo.popPendingTranscript();
|
|
781
781
|
if (!entry) {
|
|
@@ -793,14 +793,14 @@ async function startMcpServer() {
|
|
|
793
793
|
const state = startCompile(events, sessionId, project, entry.projectRoot || projectRoot, repo, entry.transcriptPath);
|
|
794
794
|
return { content: [{ type: "text", text: JSON.stringify({ sessionId: state.sessionId, prompt: state.prompt }) }] };
|
|
795
795
|
}
|
|
796
|
-
case "
|
|
796
|
+
case "agentcache_enforce": {
|
|
797
797
|
const args = request.params.arguments;
|
|
798
798
|
const project = args.project || detectedProject;
|
|
799
799
|
const input = { tool_name: args.tool_name, tool_input: args.tool_input || {} };
|
|
800
800
|
const result = evaluatePolicy(input, repo.getEnforcedRules(project));
|
|
801
801
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
802
802
|
}
|
|
803
|
-
case "
|
|
803
|
+
case "agentcache_save_observation": {
|
|
804
804
|
const args = request.params.arguments;
|
|
805
805
|
const project = args.project || detectedProject;
|
|
806
806
|
const scope = args.scope || defaultScope(args.type);
|
|
@@ -849,7 +849,7 @@ async function startMcpServer() {
|
|
|
849
849
|
});
|
|
850
850
|
return { content: [{ type: "text", text: JSON.stringify({ saved: true, scope }) }] };
|
|
851
851
|
}
|
|
852
|
-
case "
|
|
852
|
+
case "agentcache_get_knowledge": {
|
|
853
853
|
const args = request.params.arguments || {};
|
|
854
854
|
const project = args.project || detectedProject;
|
|
855
855
|
const items = repo.getKnowledgeItems(project, {
|
|
@@ -860,7 +860,7 @@ async function startMcpServer() {
|
|
|
860
860
|
const summary = filtered.map((i) => `[${i.id}] [${i.scope}/${i.confidence}] (${i.type}) ${i.content}`).join("\n");
|
|
861
861
|
return { content: [{ type: "text", text: summary || "No knowledge items found." }] };
|
|
862
862
|
}
|
|
863
|
-
case "
|
|
863
|
+
case "agentcache_deprecate_knowledge": {
|
|
864
864
|
const args = request.params.arguments;
|
|
865
865
|
const item = repo.getKnowledgeItem(args.id);
|
|
866
866
|
if (!item) {
|
|
@@ -2,20 +2,22 @@ import {
|
|
|
2
2
|
findProjectRoot,
|
|
3
3
|
getClaudeTranscriptsDir,
|
|
4
4
|
getContinueSessionsDir,
|
|
5
|
+
getDataDir,
|
|
5
6
|
getDbPath,
|
|
6
|
-
getGlobalLoopDir,
|
|
7
7
|
getProjectDisplayName,
|
|
8
8
|
getProjectId,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
isInitialized,
|
|
10
|
+
migrateFromLegacy
|
|
11
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
11
12
|
import "./chunk-MLKGABMK.js";
|
|
12
13
|
export {
|
|
13
14
|
findProjectRoot,
|
|
14
15
|
getClaudeTranscriptsDir,
|
|
15
16
|
getContinueSessionsDir,
|
|
17
|
+
getDataDir,
|
|
16
18
|
getDbPath,
|
|
17
|
-
getGlobalLoopDir,
|
|
18
19
|
getProjectDisplayName,
|
|
19
20
|
getProjectId,
|
|
20
|
-
|
|
21
|
+
isInitialized,
|
|
22
|
+
migrateFromLegacy
|
|
21
23
|
};
|
package/dist/postinstall.js
CHANGED
|
@@ -2,11 +2,12 @@ import {
|
|
|
2
2
|
detectInstalledIdes,
|
|
3
3
|
registerClaudeHooks,
|
|
4
4
|
registerMcpServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LDQPTAZ7.js";
|
|
6
6
|
import {
|
|
7
|
+
getDataDir,
|
|
7
8
|
getDbPath,
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
migrateFromLegacy
|
|
10
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
10
11
|
import {
|
|
11
12
|
SqliteKnowledgeRepository
|
|
12
13
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -18,7 +19,8 @@ if (process.env.CI) {
|
|
|
18
19
|
process.exit(0);
|
|
19
20
|
}
|
|
20
21
|
try {
|
|
21
|
-
|
|
22
|
+
migrateFromLegacy();
|
|
23
|
+
mkdirSync(getDataDir(), { recursive: true });
|
|
22
24
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
23
25
|
repo.close();
|
|
24
26
|
const ides = detectInstalledIdes().filter((i) => i.detected);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluatePolicy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-T7BJPANN.js";
|
|
4
4
|
import {
|
|
5
5
|
findProjectRoot,
|
|
6
6
|
getDbPath,
|
|
7
7
|
getProjectId,
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
isInitialized
|
|
9
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
10
10
|
import {
|
|
11
11
|
SqliteKnowledgeRepository
|
|
12
12
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -14,7 +14,7 @@ import "./chunk-MLKGABMK.js";
|
|
|
14
14
|
|
|
15
15
|
// src/hooks/pre-tool-use.ts
|
|
16
16
|
function handlePreToolUse(input) {
|
|
17
|
-
if (!
|
|
17
|
+
if (!isInitialized()) return {};
|
|
18
18
|
const projectRoot = findProjectRoot();
|
|
19
19
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
20
20
|
try {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findAllClaudeTranscripts,
|
|
3
3
|
findAllContinueTranscripts
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OSFK44XC.js";
|
|
5
5
|
import {
|
|
6
6
|
getDbPath,
|
|
7
7
|
getProjectId,
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
isInitialized
|
|
9
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
10
10
|
import {
|
|
11
11
|
SqliteKnowledgeRepository
|
|
12
12
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -25,7 +25,7 @@ function inferProjectRootFromTranscriptPath(path) {
|
|
|
25
25
|
return dir;
|
|
26
26
|
}
|
|
27
27
|
async function handleSessionStart() {
|
|
28
|
-
if (!
|
|
28
|
+
if (!isInitialized()) return;
|
|
29
29
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
30
30
|
const compiledPaths = new Set(repo.getAllCompiledTranscriptPaths());
|
|
31
31
|
const allTranscripts = [
|
|
@@ -2,11 +2,12 @@ import {
|
|
|
2
2
|
detectInstalledIdes,
|
|
3
3
|
registerClaudeHooks,
|
|
4
4
|
registerMcpServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LDQPTAZ7.js";
|
|
6
6
|
import {
|
|
7
|
+
getDataDir,
|
|
7
8
|
getDbPath,
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
migrateFromLegacy
|
|
10
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
10
11
|
import {
|
|
11
12
|
SqliteKnowledgeRepository
|
|
12
13
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -15,13 +16,14 @@ import "./chunk-MLKGABMK.js";
|
|
|
15
16
|
// src/setup.ts
|
|
16
17
|
import { mkdirSync } from "fs";
|
|
17
18
|
async function runSetup() {
|
|
18
|
-
|
|
19
|
+
migrateFromLegacy();
|
|
20
|
+
mkdirSync(getDataDir(), { recursive: true });
|
|
19
21
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
20
22
|
repo.close();
|
|
21
23
|
const ides = detectInstalledIdes();
|
|
22
24
|
const detected = ides.filter((i) => i.detected);
|
|
23
25
|
console.log(`
|
|
24
|
-
|
|
26
|
+
AgentCache setup complete.`);
|
|
25
27
|
console.log(` Central DB: ${getDbPath()}
|
|
26
28
|
`);
|
|
27
29
|
if (detected.length === 0) {
|
|
@@ -40,7 +42,7 @@ Loop setup complete.`);
|
|
|
40
42
|
Claude Code hooks: registered (Stop, SessionStart, PreToolUse)`);
|
|
41
43
|
}
|
|
42
44
|
console.log(`
|
|
43
|
-
Done.
|
|
45
|
+
Done. AgentCache compiles knowledge across all sessions and IDEs.`);
|
|
44
46
|
}
|
|
45
47
|
export {
|
|
46
48
|
runSetup
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findLatestTranscript
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OSFK44XC.js";
|
|
4
4
|
import {
|
|
5
5
|
findProjectRoot,
|
|
6
6
|
getDbPath,
|
|
7
7
|
getProjectId,
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
isInitialized
|
|
9
|
+
} from "./chunk-WHP4Z32Z.js";
|
|
10
10
|
import {
|
|
11
11
|
SqliteKnowledgeRepository
|
|
12
12
|
} from "./chunk-MMSMDJ4O.js";
|
|
@@ -15,7 +15,7 @@ import "./chunk-MLKGABMK.js";
|
|
|
15
15
|
// src/hooks/stop.ts
|
|
16
16
|
import { randomUUID } from "crypto";
|
|
17
17
|
async function handleStop(payload) {
|
|
18
|
-
if (!
|
|
18
|
+
if (!isInitialized()) return;
|
|
19
19
|
const transcriptPath = payload?.transcript_path || findLatestTranscript();
|
|
20
20
|
if (!transcriptPath) return;
|
|
21
21
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|