agentcache 0.4.1 → 0.4.2
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 +101 -181
- package/dist/chunk-5UO7NJPQ.js +71 -0
- package/dist/{chunk-JVLMZU5I.js → chunk-SLRKWMSE.js} +15 -84
- package/dist/{chunk-IGCH7SZT.js → chunk-WTXSZBQE.js} +112 -5
- package/dist/cli.js +90 -31
- package/dist/{compile-all-7ESDEBFG.js → compile-all-PTWTZVP5.js} +19 -9
- package/dist/ide-detector-5TRCR4F5.js +7 -0
- package/dist/mcp.js +7 -7
- package/dist/postinstall.js +7 -5
- package/dist/{session-start-EIHYCS3J.js → session-start-DGMGEAJU.js} +14 -4
- package/dist/{setup-45BVUDXN.js → setup-CVG35TUZ.js} +7 -5
- package/dist/transcript-JWSGSDSF.js +24 -0
- package/package.json +1 -1
- package/dist/{pre-tool-use-7F7NTHCS.js → pre-tool-use-A4AJHZOJ.js} +3 -3
- package/dist/{stop-TPCRE7RE.js → stop-WGGRX6TQ.js} +3 -3
package/README.md
CHANGED
|
@@ -1,243 +1,163 @@
|
|
|
1
1
|
# AgentCache
|
|
2
2
|
|
|
3
|
-
Your
|
|
4
|
-
|
|
5
|
-
> "Don't mock the database in integration tests — we got burned when mocked tests passed but prod migration failed"
|
|
6
|
-
|
|
7
|
-
That lesson, learned once, becomes a permanent rule. Every future session with every IDE gets it. You never say it again.
|
|
8
|
-
|
|
9
|
-
## What it does
|
|
10
|
-
|
|
11
|
-
AgentCache observes your coding sessions and compiles reusable knowledge — rules, lessons, architectural decisions, project context — into a local database. Every future session gets that knowledge injected at the start, regardless of IDE or LLM.
|
|
12
|
-
|
|
13
|
-
- **Learns** from what your agents discover during sessions
|
|
14
|
-
- **Injects** relevant knowledge at the start of every new session
|
|
15
|
-
- **Works everywhere** — any IDE, any LLM, simultaneously
|
|
16
|
-
- **Stays local** — SQLite on your machine, nothing leaves your disk
|
|
17
|
-
|
|
18
|
-
## Install
|
|
3
|
+
**Your codebase learns.** AgentCache compiles what your AI agents discover into a `SKILL.md` that every future session — in any IDE, with any LLM — reads automatically.
|
|
19
4
|
|
|
20
5
|
```bash
|
|
21
6
|
npm install -g agentcache
|
|
22
7
|
```
|
|
23
8
|
|
|
24
|
-
|
|
9
|
+
That's it. No config. No accounts. No sync server.
|
|
25
10
|
|
|
26
|
-
|
|
11
|
+
---
|
|
27
12
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
4. Sets up Claude Code hooks for automatic transcript recovery
|
|
32
|
-
5. Spawns `compile-all` in background to process your existing transcript history
|
|
13
|
+
## The Problem
|
|
14
|
+
|
|
15
|
+
You tell Claude "don't mock the database in integration tests." It forgets. You tell Cursor the same thing. You tell Codex. You repeat yourself across every IDE, every session, every project.
|
|
33
16
|
|
|
34
|
-
|
|
17
|
+
Your agents are amnesiac. Your knowledge evaporates.
|
|
35
18
|
|
|
36
|
-
|
|
19
|
+
## What AgentCache Does
|
|
20
|
+
|
|
21
|
+
After a few sessions, AgentCache produces a `SKILL.md` in your repo:
|
|
37
22
|
|
|
38
23
|
```markdown
|
|
24
|
+
# Project Knowledge
|
|
25
|
+
|
|
26
|
+
## Rules
|
|
27
|
+
- Never mock the database in integration tests — we got burned when mocks passed but prod migration failed
|
|
28
|
+
- Always use snake_case for database columns
|
|
29
|
+
- Run type-check before committing
|
|
30
|
+
|
|
39
31
|
## Decisions
|
|
40
32
|
- Using Drizzle ORM over Prisma for raw SQL escape hatches
|
|
41
33
|
- PostgreSQL for all persistent state, Redis for ephemeral cache only
|
|
42
34
|
|
|
43
|
-
##
|
|
35
|
+
## Context
|
|
44
36
|
- Migrating from REST to GraphQL, both coexist until Q3
|
|
37
|
+
- Auth service rewrite driven by compliance (not tech debt)
|
|
45
38
|
```
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
This file lives at `<repo>/.agentcache/skills/project-knowledge/SKILL.md`. It's auto-discovered by **38+ tools** that support the Agent Skills spec — no MCP connection required. Commit it. Every teammate gets your team's accumulated knowledge on clone.
|
|
41
|
+
|
|
42
|
+
**The database is local. The output is git.**
|
|
48
43
|
|
|
49
|
-
## How
|
|
44
|
+
## How It Works
|
|
50
45
|
|
|
51
46
|
```
|
|
52
|
-
|
|
53
|
-
│
|
|
54
|
-
|
|
55
|
-
│
|
|
56
|
-
|
|
57
|
-
│
|
|
58
|
-
|
|
59
|
-
│
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
│ └────────────┬────────────┘ │
|
|
64
|
-
│ │ │
|
|
65
|
-
│ ┌─────────┴──────────┐ │
|
|
66
|
-
│ │ ~/.agentcache/ │ │
|
|
67
|
-
│ │ agentcache.db │ │
|
|
68
|
-
│ │ (SQLite + WAL) │ │
|
|
69
|
-
│ └────────────────────┘ │
|
|
70
|
-
└────────────────────────────────────────────────────────────────────────┘
|
|
47
|
+
Session 1 (Claude Code) Session 2 (Cursor) Session 3 (Codex)
|
|
48
|
+
│ │ │
|
|
49
|
+
└───────────────────────────┴───────────────────────┘
|
|
50
|
+
│
|
|
51
|
+
AgentCache (MCP Server)
|
|
52
|
+
│
|
|
53
|
+
┌───────────────┴───────────────┐
|
|
54
|
+
│ │
|
|
55
|
+
~/.agentcache/ <repo>/.agentcache/
|
|
56
|
+
agentcache.db skills/.../SKILL.md
|
|
57
|
+
(local SQLite) (committed to git)
|
|
71
58
|
```
|
|
72
59
|
|
|
73
|
-
|
|
60
|
+
1. **Session starts** → agent calls `inject_context` → gets compiled rules, lessons, decisions
|
|
61
|
+
2. **During session** → agent calls `compile_submit` as it learns things
|
|
62
|
+
3. **Session ends** → knowledge compiles into the database
|
|
63
|
+
4. **Periodically** → database projects into `SKILL.md` for git distribution
|
|
74
64
|
|
|
75
|
-
|
|
76
|
-
2. **During session** — agent calls `compile_submit` incrementally as it learns things
|
|
77
|
-
3. **Session ends** — observations are already saved. If the session terminates unexpectedly, transcript recovery handles it next time.
|
|
65
|
+
Knowledge compounds. One lesson stated once propagates to every future session across every IDE.
|
|
78
66
|
|
|
79
|
-
|
|
67
|
+
## Install
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
| Lesson | Global | "Don't mock the database in integration tests — mocked tests passed but prod migration failed" |
|
|
85
|
-
| Decision | Project | "Using Drizzle ORM over Prisma because we need raw SQL escape hatches" |
|
|
86
|
-
| Context | Project | "Currently migrating from REST to GraphQL, both coexist" |
|
|
69
|
+
```bash
|
|
70
|
+
npm install -g agentcache
|
|
71
|
+
```
|
|
87
72
|
|
|
88
|
-
|
|
73
|
+
The install automatically:
|
|
74
|
+
1. Creates `~/.agentcache/agentcache.db`
|
|
75
|
+
2. Detects your IDEs (Claude Code, Cursor, Roo Code, Windsurf, Continue, Codex)
|
|
76
|
+
3. Registers as an MCP server in each — with auto-approve
|
|
77
|
+
4. Sets up Claude Code hooks for transcript recovery
|
|
78
|
+
5. Compiles your existing transcript history in the background
|
|
79
|
+
|
|
80
|
+
**Zero config. Zero setup. Start a session and it's working.**
|
|
89
81
|
|
|
90
|
-
##
|
|
82
|
+
## Supported IDEs
|
|
91
83
|
|
|
92
|
-
|
|
84
|
+
| IDE | MCP | Auto-Approve | Transcript Recovery |
|
|
85
|
+
|-----|-----|-------------|-------------------|
|
|
86
|
+
| Claude Code | ✓ | ✓ | Full (hooks + JSONL) |
|
|
87
|
+
| Cursor | ✓ | ✓ | Full (agent transcripts) |
|
|
88
|
+
| Roo Code (VS Code) | ✓ | ✓ | Full (task history) |
|
|
89
|
+
| Codex | ✓ | ✓ | Full (session JSONL) |
|
|
90
|
+
| Continue | ✓ | ✓ | Full (session JSON) |
|
|
91
|
+
| Windsurf | ✓ | ✓ | Incremental only |
|
|
92
|
+
| Goose | — | — | Full (SQLite) |
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
All IDEs share the same knowledge database. A rule learned in Claude Code is injected in Cursor the next time you open it.
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
- **Enforced rules are human-only** — The enforce mechanism (which blocks agent tool calls) can only be set via CLI (`agentcache add-rule --enforce`). No MCP tool can create policy an agent is subject to.
|
|
98
|
-
- **Scope gate** — Agent-submitted observations are always project-scoped. Promotion to global scope requires explicit human action (USER authority). An agent cannot write a global rule.
|
|
99
|
-
- **Quarantine ≠ absent** — Quarantined items are captured and visible in `agentcache review`. They just don't inject. The review command is how you clear or promote them.
|
|
96
|
+
## Security Model
|
|
100
97
|
|
|
101
|
-
|
|
98
|
+
AgentCache creates a feedback loop: agents write observations → observations compile → knowledge injects into future sessions. This is the product's value **and** its attack surface.
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
- `locked` mode disables `compile_submit` entirely and requires human-triggered batch compilation. It reduces the attack surface significantly but `compile-all` against a poisoned transcript is still a vector.
|
|
100
|
+
**Quarantine gate**: Agent-submitted observations require confirmation across 2+ independent sessions before injection. A single prompt-injected `compile_submit` cannot poison your knowledge.
|
|
105
101
|
|
|
106
|
-
|
|
102
|
+
**Human-only enforcement**: Policy rules (that block tool calls) can only be created via CLI. No MCP tool can create policy.
|
|
107
103
|
|
|
108
|
-
|
|
104
|
+
**Scope gate**: Agent-submitted observations are always project-scoped. Global requires explicit human action.
|
|
105
|
+
|
|
106
|
+
### Security Modes
|
|
109
107
|
|
|
110
108
|
```json
|
|
111
109
|
{ "security": "auto" }
|
|
112
110
|
```
|
|
113
111
|
|
|
114
|
-
| Mode | Behavior |
|
|
115
|
-
|
|
116
|
-
| `auto`
|
|
117
|
-
| `review` |
|
|
118
|
-
| `locked` | `compile_submit` disabled.
|
|
112
|
+
| Mode | Behavior |
|
|
113
|
+
|------|----------|
|
|
114
|
+
| `auto` | Quarantine — new items inject after 2+ session confirmations |
|
|
115
|
+
| `review` | Nothing injects until `agentcache review` approves it |
|
|
116
|
+
| `locked` | `compile_submit` disabled. Human-triggered batch only |
|
|
119
117
|
|
|
120
|
-
## CLI
|
|
118
|
+
## CLI
|
|
121
119
|
|
|
122
120
|
```bash
|
|
123
|
-
agentcache
|
|
124
|
-
agentcache
|
|
125
|
-
agentcache review
|
|
126
|
-
agentcache promote <id>
|
|
127
|
-
agentcache add-rule "never
|
|
128
|
-
agentcache
|
|
129
|
-
agentcache
|
|
130
|
-
agentcache setup # Re-register with IDEs (only if postinstall failed)
|
|
121
|
+
agentcache doctor # Diagnose installation
|
|
122
|
+
agentcache status # Knowledge stats
|
|
123
|
+
agentcache review # Approve/reject quarantined items
|
|
124
|
+
agentcache promote <id> # Approve a single item
|
|
125
|
+
agentcache add-rule "never force push" --enforce # Create policy (human-only)
|
|
126
|
+
agentcache compile-all # Batch-compile all transcripts
|
|
127
|
+
agentcache setup # Re-register with IDEs
|
|
131
128
|
```
|
|
132
129
|
|
|
133
|
-
## compile-all
|
|
134
|
-
|
|
135
|
-
Processes all pending transcripts without depending on active MCP sessions.
|
|
130
|
+
## compile-all
|
|
136
131
|
|
|
137
|
-
|
|
132
|
+
Processes all uncompiled transcripts from all IDEs using the first available LLM backend:
|
|
138
133
|
|
|
139
|
-
1. CLI tools
|
|
134
|
+
1. CLI tools: `claude`, `codex`, `gemini`, `copilot`, `aider`, `goose`
|
|
140
135
|
2. Ollama at `localhost:11434`
|
|
141
136
|
3. `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`
|
|
142
137
|
|
|
143
|
-
|
|
138
|
+
Runs automatically on install and when pending transcripts exceed 20.
|
|
144
139
|
|
|
145
|
-
|
|
146
|
-
- When pending transcripts exceed 20 (background janitor)
|
|
147
|
-
- Lockfile prevents concurrent runs
|
|
148
|
-
|
|
149
|
-
## MCP tools
|
|
150
|
-
|
|
151
|
-
| Tool | Purpose |
|
|
152
|
-
|------|---------|
|
|
153
|
-
| `inject_context` | Load compiled knowledge at session start |
|
|
154
|
-
| `compile_submit` | Submit observations incrementally during session |
|
|
155
|
-
| `compile_cluster` | Resolve clustering when observations overlap existing knowledge |
|
|
156
|
-
| `compile_extract` | Process queued transcripts from previous sessions |
|
|
157
|
-
| `enforce` | Check tool calls against enforced policy rules |
|
|
158
|
-
| `save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
|
|
159
|
-
| `get_knowledge` | Query the knowledge database |
|
|
160
|
-
| `deprecate_knowledge` | Mark knowledge as deprecated |
|
|
161
|
-
|
|
162
|
-
## How knowledge compiles
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
Observations (raw)
|
|
166
|
-
│
|
|
167
|
-
▼
|
|
168
|
-
Extract → Normalize → Canonicalize → Cluster → Detect Contradictions → Compile
|
|
169
|
-
│
|
|
170
|
-
┌───────────────────────────────────────────┘
|
|
171
|
-
│
|
|
172
|
-
PENDING store
|
|
173
|
-
│
|
|
174
|
-
┌─────────┴──────────┐
|
|
175
|
-
│ │
|
|
176
|
-
AUTO items USER items
|
|
177
|
-
(quarantine gate) (inject immediately)
|
|
178
|
-
2+ sessions before
|
|
179
|
-
injection
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**Two compilation paths:**
|
|
183
|
-
|
|
184
|
-
- **In-session** — agent processes extraction via MCP tools in your IDE
|
|
185
|
-
- **Batch** — `compile-all` runs independently, processes full backlog
|
|
186
|
-
|
|
187
|
-
**Two output formats:**
|
|
188
|
-
|
|
189
|
-
- **MCP injection** — structured context via `inject_context`
|
|
190
|
-
- **SKILL.md** — Agent Skills spec files auto-discovered by 38+ tools without MCP
|
|
191
|
-
|
|
192
|
-
## Design principles
|
|
193
|
-
|
|
194
|
-
**Zero config** — `npm install -g agentcache` is the only step. No dotfiles, no init, no config to maintain.
|
|
195
|
-
|
|
196
|
-
**Universal** — MCP is the only interface. Any IDE, any LLM. No IDE-specific code paths.
|
|
197
|
-
|
|
198
|
-
**Developer-scoped** — One database per developer, not per project. Global knowledge (rules, lessons) benefits all your projects. Project knowledge stays scoped.
|
|
199
|
-
|
|
200
|
-
**Resilient to abrupt exits** — Incremental submission + transcript recovery + pipe-independent compilation means knowledge survives crashes, ctrl-c, and MCP disconnects.
|
|
201
|
-
|
|
202
|
-
**Anti-bloat** — Confidence promotion, 30-day decay on unused items, budget caps (20 rules / 10 lessons / 10 decisions / 5 context per session), priority ranking.
|
|
203
|
-
|
|
204
|
-
## Supported IDEs
|
|
205
|
-
|
|
206
|
-
| IDE | MCP | Auto-Approve | Transcript Recovery | Hooks |
|
|
207
|
-
|-----|-----|-------------|-------------------|-------|
|
|
208
|
-
| Claude Code | Yes | Yes | Full (JSONL) | Stop, SessionStart, PreToolUse |
|
|
209
|
-
| Cursor | Yes | Yes | Incremental only | — |
|
|
210
|
-
| Roo Code | Yes | Yes | Full (JSON via compile-all) | — |
|
|
211
|
-
| Windsurf | Yes | Yes | Incremental only | — |
|
|
212
|
-
| Continue | Yes | Yes | Full (JSON) | — |
|
|
213
|
-
| Codex | Yes | Yes | Full (JSONL via compile-all) | — |
|
|
214
|
-
| Goose | — | — | Full (SQLite via compile-all) | — |
|
|
215
|
-
| Aider | Coming soon | | | |
|
|
216
|
-
| GitHub Copilot | Coming soon | | | |
|
|
217
|
-
| Zed AI | Coming soon | | | |
|
|
218
|
-
|
|
219
|
-
## Data storage
|
|
140
|
+
## Data
|
|
220
141
|
|
|
221
142
|
```
|
|
222
143
|
~/.agentcache/
|
|
223
|
-
├── agentcache.db
|
|
224
|
-
├── config.json
|
|
225
|
-
|
|
226
|
-
└── skills/developer-knowledge/SKILL.md # Global skill (auto-generated)
|
|
227
|
-
```
|
|
144
|
+
├── agentcache.db # Knowledge database (SQLite + WAL)
|
|
145
|
+
├── config.json # Security mode
|
|
146
|
+
└── compile-all.lock # Prevents concurrent compilation
|
|
228
147
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
148
|
+
<repo>/.agentcache/
|
|
149
|
+
└── skills/project-knowledge/SKILL.md # Git-committed team knowledge
|
|
150
|
+
```
|
|
232
151
|
|
|
233
|
-
|
|
152
|
+
No network calls. No telemetry. No accounts. Everything stays on your machine (except what you choose to commit).
|
|
234
153
|
|
|
235
|
-
##
|
|
154
|
+
## Principles
|
|
236
155
|
|
|
237
|
-
- **
|
|
238
|
-
- **
|
|
239
|
-
- **
|
|
240
|
-
- **
|
|
156
|
+
- **Zero config** — `npm install -g` is the only step
|
|
157
|
+
- **Universal** — MCP protocol, any IDE, any LLM
|
|
158
|
+
- **Git-native output** — SKILL.md is the distribution mechanism
|
|
159
|
+
- **Secure by default** — quarantine gate, scope restrictions, human-only policy
|
|
160
|
+
- **Anti-bloat** — 30-day decay, budget caps, confidence promotion
|
|
241
161
|
|
|
242
162
|
## Contributing
|
|
243
163
|
|
|
@@ -246,7 +166,7 @@ git clone https://github.com/raghav-a21ai/agentcache
|
|
|
246
166
|
cd agentcache
|
|
247
167
|
npm install
|
|
248
168
|
npm run build
|
|
249
|
-
npm test
|
|
169
|
+
npm test # 205 tests
|
|
250
170
|
```
|
|
251
171
|
|
|
252
172
|
## License
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/utils/ide-detector.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
function getRooConfigPath() {
|
|
6
|
+
const home = homedir();
|
|
7
|
+
if (process.platform === "darwin") {
|
|
8
|
+
return join(home, "Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
9
|
+
}
|
|
10
|
+
if (process.platform === "win32") {
|
|
11
|
+
return join(process.env.APPDATA || join(home, "AppData/Roaming"), "Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
12
|
+
}
|
|
13
|
+
return join(home, ".config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
14
|
+
}
|
|
15
|
+
function getWindsurfConfigPath() {
|
|
16
|
+
const home = homedir();
|
|
17
|
+
return join(home, ".codeium", "windsurf", "mcp_config.json");
|
|
18
|
+
}
|
|
19
|
+
function getContinueConfigPath() {
|
|
20
|
+
const home = homedir();
|
|
21
|
+
return join(home, ".continue", "mcpServers", "agentcache.json");
|
|
22
|
+
}
|
|
23
|
+
function getCodexConfigPath() {
|
|
24
|
+
const home = homedir();
|
|
25
|
+
return join(home, ".codex", "config.toml");
|
|
26
|
+
}
|
|
27
|
+
function detectInstalledIdes() {
|
|
28
|
+
const home = homedir();
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
name: "Claude Code",
|
|
32
|
+
detected: existsSync(join(home, ".claude")),
|
|
33
|
+
mcpConfigPath: join(home, ".claude.json"),
|
|
34
|
+
mcpConfigFormat: "claude-settings"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "Cursor",
|
|
38
|
+
detected: existsSync(join(home, ".cursor")),
|
|
39
|
+
mcpConfigPath: join(home, ".cursor", "mcp.json"),
|
|
40
|
+
mcpConfigFormat: "mcp-json"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "Roo Code",
|
|
44
|
+
detected: existsSync(getRooConfigPath()),
|
|
45
|
+
mcpConfigPath: getRooConfigPath(),
|
|
46
|
+
mcpConfigFormat: "mcp-json"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "Windsurf",
|
|
50
|
+
detected: existsSync(join(home, ".codeium", "windsurf")) || existsSync(join(home, ".windsurf")),
|
|
51
|
+
mcpConfigPath: getWindsurfConfigPath(),
|
|
52
|
+
mcpConfigFormat: "mcp-json"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "Continue",
|
|
56
|
+
detected: existsSync(join(home, ".continue")),
|
|
57
|
+
mcpConfigPath: getContinueConfigPath(),
|
|
58
|
+
mcpConfigFormat: "continue-dir"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "Codex",
|
|
62
|
+
detected: existsSync(join(home, ".codex")),
|
|
63
|
+
mcpConfigPath: getCodexConfigPath(),
|
|
64
|
+
mcpConfigFormat: "codex-toml"
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
detectInstalledIdes
|
|
71
|
+
};
|
|
@@ -1,75 +1,7 @@
|
|
|
1
|
-
// src/utils/ide-detector.ts
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { homedir } from "os";
|
|
5
|
-
function getRooConfigPath() {
|
|
6
|
-
const home = homedir();
|
|
7
|
-
if (process.platform === "darwin") {
|
|
8
|
-
return join(home, "Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
9
|
-
}
|
|
10
|
-
if (process.platform === "win32") {
|
|
11
|
-
return join(process.env.APPDATA || join(home, "AppData/Roaming"), "Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
12
|
-
}
|
|
13
|
-
return join(home, ".config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
|
|
14
|
-
}
|
|
15
|
-
function getWindsurfConfigPath() {
|
|
16
|
-
const home = homedir();
|
|
17
|
-
return join(home, ".codeium", "windsurf", "mcp_config.json");
|
|
18
|
-
}
|
|
19
|
-
function getContinueConfigPath() {
|
|
20
|
-
const home = homedir();
|
|
21
|
-
return join(home, ".continue", "mcpServers", "agentcache.json");
|
|
22
|
-
}
|
|
23
|
-
function getCodexConfigPath() {
|
|
24
|
-
const home = homedir();
|
|
25
|
-
return join(home, ".codex", "config.toml");
|
|
26
|
-
}
|
|
27
|
-
function detectInstalledIdes() {
|
|
28
|
-
const home = homedir();
|
|
29
|
-
return [
|
|
30
|
-
{
|
|
31
|
-
name: "Claude Code",
|
|
32
|
-
detected: existsSync(join(home, ".claude")),
|
|
33
|
-
mcpConfigPath: join(home, ".claude.json"),
|
|
34
|
-
mcpConfigFormat: "claude-settings"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: "Cursor",
|
|
38
|
-
detected: existsSync(join(home, ".cursor")),
|
|
39
|
-
mcpConfigPath: join(home, ".cursor", "mcp.json"),
|
|
40
|
-
mcpConfigFormat: "mcp-json"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: "Roo Code",
|
|
44
|
-
detected: existsSync(getRooConfigPath()),
|
|
45
|
-
mcpConfigPath: getRooConfigPath(),
|
|
46
|
-
mcpConfigFormat: "mcp-json"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: "Windsurf",
|
|
50
|
-
detected: existsSync(join(home, ".codeium", "windsurf")) || existsSync(join(home, ".windsurf")),
|
|
51
|
-
mcpConfigPath: getWindsurfConfigPath(),
|
|
52
|
-
mcpConfigFormat: "mcp-json"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: "Continue",
|
|
56
|
-
detected: existsSync(join(home, ".continue")),
|
|
57
|
-
mcpConfigPath: getContinueConfigPath(),
|
|
58
|
-
mcpConfigFormat: "continue-dir"
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: "Codex",
|
|
62
|
-
detected: existsSync(join(home, ".codex")),
|
|
63
|
-
mcpConfigPath: getCodexConfigPath(),
|
|
64
|
-
mcpConfigFormat: "codex-toml"
|
|
65
|
-
}
|
|
66
|
-
];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
1
|
// src/utils/ide-registrar.ts
|
|
70
|
-
import { existsSync
|
|
71
|
-
import { join
|
|
72
|
-
import { homedir
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
73
5
|
import { execSync } from "child_process";
|
|
74
6
|
function findNodeBinary() {
|
|
75
7
|
try {
|
|
@@ -83,7 +15,7 @@ function findAgentcacheScript() {
|
|
|
83
15
|
const binPath = execSync("which agentcache", { encoding: "utf-8" }).trim();
|
|
84
16
|
return binPath;
|
|
85
17
|
} catch {
|
|
86
|
-
return
|
|
18
|
+
return join(dirname(dirname(__dirname)), "dist", "cli.js");
|
|
87
19
|
}
|
|
88
20
|
}
|
|
89
21
|
function isVscodeExtensionIde(ide) {
|
|
@@ -116,9 +48,9 @@ function registerMcpServer(ide) {
|
|
|
116
48
|
return false;
|
|
117
49
|
}
|
|
118
50
|
function registerClaudeCode() {
|
|
119
|
-
const claudeJsonPath =
|
|
51
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
120
52
|
let config = {};
|
|
121
|
-
if (
|
|
53
|
+
if (existsSync(claudeJsonPath)) {
|
|
122
54
|
try {
|
|
123
55
|
config = JSON.parse(readFileSync(claudeJsonPath, "utf-8"));
|
|
124
56
|
} catch {
|
|
@@ -137,10 +69,10 @@ function registerClaudeCode() {
|
|
|
137
69
|
writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
|
|
138
70
|
serverRegistered = true;
|
|
139
71
|
}
|
|
140
|
-
const settingsPath =
|
|
141
|
-
if (
|
|
72
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
73
|
+
if (existsSync(join(homedir(), ".claude"))) {
|
|
142
74
|
let settings = {};
|
|
143
|
-
if (
|
|
75
|
+
if (existsSync(settingsPath)) {
|
|
144
76
|
try {
|
|
145
77
|
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
146
78
|
} catch {
|
|
@@ -164,7 +96,7 @@ function registerClaudeCode() {
|
|
|
164
96
|
}
|
|
165
97
|
function registerMcpJson(ide) {
|
|
166
98
|
let config = {};
|
|
167
|
-
if (
|
|
99
|
+
if (existsSync(ide.mcpConfigPath)) {
|
|
168
100
|
try {
|
|
169
101
|
config = JSON.parse(readFileSync(ide.mcpConfigPath, "utf-8"));
|
|
170
102
|
} catch {
|
|
@@ -212,7 +144,7 @@ function registerContinue(ide) {
|
|
|
212
144
|
}
|
|
213
145
|
function registerCodex(ide) {
|
|
214
146
|
const configPath = ide.mcpConfigPath;
|
|
215
|
-
if (
|
|
147
|
+
if (existsSync(configPath)) {
|
|
216
148
|
const content = readFileSync(configPath, "utf-8");
|
|
217
149
|
if (content.includes("[mcp_servers.agentcache]")) return false;
|
|
218
150
|
}
|
|
@@ -223,7 +155,7 @@ args = ["serve"]
|
|
|
223
155
|
default_tools_approval_mode = "auto"
|
|
224
156
|
`;
|
|
225
157
|
mkdirSync(dirname(configPath), { recursive: true });
|
|
226
|
-
if (
|
|
158
|
+
if (existsSync(configPath)) {
|
|
227
159
|
appendFileSync(configPath, tomlBlock);
|
|
228
160
|
} else {
|
|
229
161
|
writeFileSync(configPath, tomlBlock.trimStart());
|
|
@@ -231,10 +163,10 @@ default_tools_approval_mode = "auto"
|
|
|
231
163
|
return true;
|
|
232
164
|
}
|
|
233
165
|
function registerClaudeHooks() {
|
|
234
|
-
const settingsPath =
|
|
235
|
-
if (!
|
|
166
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
167
|
+
if (!existsSync(join(homedir(), ".claude"))) return false;
|
|
236
168
|
let settings = {};
|
|
237
|
-
if (
|
|
169
|
+
if (existsSync(settingsPath)) {
|
|
238
170
|
try {
|
|
239
171
|
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
240
172
|
} catch {
|
|
@@ -265,7 +197,6 @@ function registerClaudeHooks() {
|
|
|
265
197
|
}
|
|
266
198
|
|
|
267
199
|
export {
|
|
268
|
-
detectInstalledIdes,
|
|
269
200
|
registerMcpServer,
|
|
270
201
|
registerClaudeHooks
|
|
271
202
|
};
|
|
@@ -139,19 +139,62 @@ function parse3(path) {
|
|
|
139
139
|
return events;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
// src/utils/transcript-parsers/
|
|
143
|
-
var
|
|
144
|
-
__export(
|
|
142
|
+
// src/utils/transcript-parsers/cursor-jsonl.ts
|
|
143
|
+
var cursor_jsonl_exports = {};
|
|
144
|
+
__export(cursor_jsonl_exports, {
|
|
145
145
|
canParse: () => canParse4,
|
|
146
146
|
parse: () => parse4
|
|
147
147
|
});
|
|
148
148
|
import { readFileSync as readFileSync4 } from "fs";
|
|
149
149
|
function canParse4(path) {
|
|
150
|
-
|
|
150
|
+
if (!path.endsWith(".jsonl")) return false;
|
|
151
|
+
return path.includes(".cursor/projects/") && path.includes("/agent-transcripts/");
|
|
151
152
|
}
|
|
152
153
|
function parse4(path) {
|
|
153
154
|
const content = readFileSync4(path, "utf-8");
|
|
154
155
|
const events = [];
|
|
156
|
+
for (const line of content.split("\n")) {
|
|
157
|
+
if (!line.trim()) continue;
|
|
158
|
+
try {
|
|
159
|
+
const obj = JSON.parse(line);
|
|
160
|
+
if (obj.role === "user" && obj.message?.content) {
|
|
161
|
+
const blocks = Array.isArray(obj.message.content) ? obj.message.content : [{ type: "text", text: obj.message.content }];
|
|
162
|
+
const text = blocks.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
163
|
+
if (text) events.push({ type: "message", role: "user", content: text });
|
|
164
|
+
} else if (obj.role === "assistant" && obj.message?.content) {
|
|
165
|
+
const blocks = Array.isArray(obj.message.content) ? obj.message.content : [{ type: "text", text: obj.message.content }];
|
|
166
|
+
for (const block of blocks) {
|
|
167
|
+
if (block.type === "text" && block.text) {
|
|
168
|
+
events.push({ type: "message", role: "assistant", content: block.text });
|
|
169
|
+
} else if (block.type === "tool_use") {
|
|
170
|
+
events.push({
|
|
171
|
+
type: "tool_use",
|
|
172
|
+
tool_name: block.name,
|
|
173
|
+
tool_input: block.input
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return events;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/utils/transcript-parsers/roo-code-json.ts
|
|
186
|
+
var roo_code_json_exports = {};
|
|
187
|
+
__export(roo_code_json_exports, {
|
|
188
|
+
canParse: () => canParse5,
|
|
189
|
+
parse: () => parse5
|
|
190
|
+
});
|
|
191
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
192
|
+
function canParse5(path) {
|
|
193
|
+
return path.includes("roo-cline/tasks/") && path.endsWith("api_conversation_history.json");
|
|
194
|
+
}
|
|
195
|
+
function parse5(path) {
|
|
196
|
+
const content = readFileSync5(path, "utf-8");
|
|
197
|
+
const events = [];
|
|
155
198
|
try {
|
|
156
199
|
const messages = JSON.parse(content);
|
|
157
200
|
if (!Array.isArray(messages)) return [];
|
|
@@ -182,7 +225,7 @@ function parse4(path) {
|
|
|
182
225
|
}
|
|
183
226
|
|
|
184
227
|
// src/utils/transcript-parsers/index.ts
|
|
185
|
-
var parsers = [codex_jsonl_exports, roo_code_json_exports, claude_jsonl_exports, continue_json_exports];
|
|
228
|
+
var parsers = [codex_jsonl_exports, cursor_jsonl_exports, roo_code_json_exports, claude_jsonl_exports, continue_json_exports];
|
|
186
229
|
function parseTranscriptAuto(path) {
|
|
187
230
|
for (const parser of parsers) {
|
|
188
231
|
if (parser.canParse(path)) return parser.parse(path);
|
|
@@ -194,6 +237,31 @@ function parseTranscriptAuto(path) {
|
|
|
194
237
|
function parseTranscript(path) {
|
|
195
238
|
return parseTranscriptAuto(path);
|
|
196
239
|
}
|
|
240
|
+
function findLatestTranscript() {
|
|
241
|
+
const baseDir = getClaudeTranscriptsDir();
|
|
242
|
+
if (!existsSync(baseDir)) return null;
|
|
243
|
+
let latest = null;
|
|
244
|
+
try {
|
|
245
|
+
const dirs = readdirSync(baseDir).map((d) => join(baseDir, d)).filter((d) => statSync(d).isDirectory());
|
|
246
|
+
for (const dir of dirs) {
|
|
247
|
+
try {
|
|
248
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
249
|
+
for (const file of files) {
|
|
250
|
+
const fullPath = join(dir, file);
|
|
251
|
+
const mtime = statSync(fullPath).mtimeMs;
|
|
252
|
+
if (!latest || mtime > latest.mtime) {
|
|
253
|
+
latest = { path: fullPath, mtime };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
} catch {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
return latest?.path ?? null;
|
|
264
|
+
}
|
|
197
265
|
function findAllClaudeTranscripts() {
|
|
198
266
|
const baseDir = getClaudeTranscriptsDir();
|
|
199
267
|
if (!existsSync(baseDir)) return [];
|
|
@@ -247,6 +315,37 @@ function findAllCodexTranscripts() {
|
|
|
247
315
|
walkDir(baseDir);
|
|
248
316
|
return transcripts;
|
|
249
317
|
}
|
|
318
|
+
function findAllCursorTranscripts() {
|
|
319
|
+
const baseDir = join(homedir(), ".cursor", "projects");
|
|
320
|
+
if (!existsSync(baseDir)) return [];
|
|
321
|
+
const transcripts = [];
|
|
322
|
+
try {
|
|
323
|
+
for (const projectDir of readdirSync(baseDir)) {
|
|
324
|
+
const agentDir = join(baseDir, projectDir, "agent-transcripts");
|
|
325
|
+
if (!existsSync(agentDir)) continue;
|
|
326
|
+
try {
|
|
327
|
+
for (const sessionDir of readdirSync(agentDir)) {
|
|
328
|
+
const sessionPath = join(agentDir, sessionDir);
|
|
329
|
+
if (!statSync(sessionPath).isDirectory()) continue;
|
|
330
|
+
try {
|
|
331
|
+
for (const file of readdirSync(sessionPath)) {
|
|
332
|
+
if (file.endsWith(".jsonl")) {
|
|
333
|
+
const full = join(sessionPath, file);
|
|
334
|
+
if (statSync(full).size > 100) {
|
|
335
|
+
transcripts.push(full);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} catch {
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
return transcripts;
|
|
348
|
+
}
|
|
250
349
|
function findAllRooCodeTranscripts() {
|
|
251
350
|
const possibleDirs = [
|
|
252
351
|
join(homedir(), "Library", "Application Support", "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline", "tasks"),
|
|
@@ -267,15 +366,23 @@ function findAllRooCodeTranscripts() {
|
|
|
267
366
|
}
|
|
268
367
|
return transcripts;
|
|
269
368
|
}
|
|
369
|
+
function findAllGooseSessionIds() {
|
|
370
|
+
const dbPath = join(homedir(), ".local", "share", "goose", "sessions", "sessions.db");
|
|
371
|
+
if (!existsSync(dbPath)) return [];
|
|
372
|
+
return [dbPath];
|
|
373
|
+
}
|
|
270
374
|
function getGooseDbPath() {
|
|
271
375
|
return join(homedir(), ".local", "share", "goose", "sessions", "sessions.db");
|
|
272
376
|
}
|
|
273
377
|
|
|
274
378
|
export {
|
|
275
379
|
parseTranscript,
|
|
380
|
+
findLatestTranscript,
|
|
276
381
|
findAllClaudeTranscripts,
|
|
277
382
|
findAllContinueTranscripts,
|
|
278
383
|
findAllCodexTranscripts,
|
|
384
|
+
findAllCursorTranscripts,
|
|
279
385
|
findAllRooCodeTranscripts,
|
|
386
|
+
findAllGooseSessionIds,
|
|
280
387
|
getGooseDbPath
|
|
281
388
|
};
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ 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.1");
|
|
7
7
|
program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
|
|
8
|
-
const { runSetup } = await import("./setup-
|
|
8
|
+
const { runSetup } = await import("./setup-CVG35TUZ.js");
|
|
9
9
|
await runSetup();
|
|
10
10
|
});
|
|
11
11
|
program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").action(async () => {
|
|
@@ -14,7 +14,7 @@ program.command("serve").description("Start AgentCache MCP server (spawned by ID
|
|
|
14
14
|
});
|
|
15
15
|
program.command("compile-session").description("Stop hook: queue transcript for compilation").action(async () => {
|
|
16
16
|
try {
|
|
17
|
-
const { handleStop } = await import("./stop-
|
|
17
|
+
const { handleStop } = await import("./stop-WGGRX6TQ.js");
|
|
18
18
|
let payload;
|
|
19
19
|
try {
|
|
20
20
|
let data = "";
|
|
@@ -34,7 +34,7 @@ program.command("compile-session").description("Stop hook: queue transcript for
|
|
|
34
34
|
});
|
|
35
35
|
program.command("discover").description("SessionStart hook: discover uncompiled transcripts").action(async () => {
|
|
36
36
|
try {
|
|
37
|
-
const { handleSessionStart } = await import("./session-start-
|
|
37
|
+
const { handleSessionStart } = await import("./session-start-DGMGEAJU.js");
|
|
38
38
|
await handleSessionStart();
|
|
39
39
|
} catch (err) {
|
|
40
40
|
process.stderr.write(`agentcache discover: ${err.message}
|
|
@@ -47,7 +47,7 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
|
|
|
47
47
|
data += chunk;
|
|
48
48
|
}
|
|
49
49
|
try {
|
|
50
|
-
const { handlePreToolUse } = await import("./pre-tool-use-
|
|
50
|
+
const { handlePreToolUse } = await import("./pre-tool-use-A4AJHZOJ.js");
|
|
51
51
|
const input = JSON.parse(data);
|
|
52
52
|
const result = handlePreToolUse(input);
|
|
53
53
|
process.stdout.write(JSON.stringify(result));
|
|
@@ -202,40 +202,99 @@ program.command("doctor").description("Diagnose AgentCache installation and repo
|
|
|
202
202
|
warning("Not initialized yet \u2014 run: agentcache setup");
|
|
203
203
|
}
|
|
204
204
|
console.log("\nIDE registrations:");
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
const { detectInstalledIdes } = await import("./ide-detector-5TRCR4F5.js");
|
|
206
|
+
const ides = detectInstalledIdes();
|
|
207
|
+
for (const ide of ides) {
|
|
208
|
+
if (!ide.detected) continue;
|
|
209
|
+
if (ide.mcpConfigFormat === "claude-settings") {
|
|
210
|
+
const claudeJson = join(homedir(), ".claude.json");
|
|
211
|
+
if (existsSync(claudeJson)) {
|
|
212
|
+
try {
|
|
213
|
+
const config = JSON.parse(readFileSync(claudeJson, "utf-8"));
|
|
214
|
+
if (config.mcpServers?.agentcache) {
|
|
215
|
+
pass("Claude Code: registered");
|
|
216
|
+
} else {
|
|
217
|
+
warning("Claude Code: detected but not registered");
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
warning("Claude Code: config unreadable");
|
|
221
|
+
}
|
|
211
222
|
} else {
|
|
212
|
-
warning("Claude Code:
|
|
223
|
+
warning("Claude Code: detected but not registered");
|
|
213
224
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
226
|
+
if (existsSync(settingsPath)) {
|
|
227
|
+
try {
|
|
228
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
229
|
+
const perms = settings.permissions?.allow || [];
|
|
230
|
+
if (perms.some((p) => p.includes("agentcache"))) {
|
|
231
|
+
pass("Claude Code permissions: auto-approved");
|
|
232
|
+
} else {
|
|
233
|
+
warning("Claude Code permissions: not in allow list");
|
|
234
|
+
}
|
|
235
|
+
if (settings.hooks?.Stop?.some((h) => JSON.stringify(h).includes("agentcache"))) {
|
|
236
|
+
pass("Claude Code hooks: registered");
|
|
237
|
+
} else {
|
|
238
|
+
warning("Claude Code hooks: not registered");
|
|
239
|
+
}
|
|
240
|
+
} catch {
|
|
241
|
+
warning("Claude Code settings: unreadable");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
} else if (ide.mcpConfigFormat === "codex-toml") {
|
|
245
|
+
if (existsSync(ide.mcpConfigPath)) {
|
|
246
|
+
try {
|
|
247
|
+
const content = readFileSync(ide.mcpConfigPath, "utf-8");
|
|
248
|
+
if (content.includes("[mcp_servers.agentcache]")) {
|
|
249
|
+
pass(`${ide.name}: registered`);
|
|
250
|
+
} else {
|
|
251
|
+
warning(`${ide.name}: detected but not registered`);
|
|
252
|
+
}
|
|
253
|
+
} catch {
|
|
254
|
+
warning(`${ide.name}: config unreadable`);
|
|
255
|
+
}
|
|
227
256
|
} else {
|
|
228
|
-
warning(
|
|
257
|
+
warning(`${ide.name}: detected but not registered`);
|
|
229
258
|
}
|
|
230
|
-
|
|
231
|
-
|
|
259
|
+
} else {
|
|
260
|
+
if (existsSync(ide.mcpConfigPath)) {
|
|
261
|
+
try {
|
|
262
|
+
const config = JSON.parse(readFileSync(ide.mcpConfigPath, "utf-8"));
|
|
263
|
+
if (config.mcpServers?.agentcache) {
|
|
264
|
+
pass(`${ide.name}: registered`);
|
|
265
|
+
} else {
|
|
266
|
+
warning(`${ide.name}: detected but not registered`);
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
warning(`${ide.name}: config unreadable`);
|
|
270
|
+
}
|
|
232
271
|
} else {
|
|
233
|
-
warning(
|
|
272
|
+
warning(`${ide.name}: detected but not registered`);
|
|
234
273
|
}
|
|
235
|
-
} catch {
|
|
236
|
-
warning("Claude Code settings: unreadable");
|
|
237
274
|
}
|
|
238
275
|
}
|
|
276
|
+
const notDetected = ides.filter((i) => !i.detected).map((i) => i.name);
|
|
277
|
+
if (notDetected.length > 0) {
|
|
278
|
+
console.log(` \xB7 Not detected: ${notDetected.join(", ")}`);
|
|
279
|
+
}
|
|
280
|
+
console.log("\nTranscript sources:");
|
|
281
|
+
const { findAllClaudeTranscripts, findAllCursorTranscripts, findAllContinueTranscripts, findAllCodexTranscripts, findAllRooCodeTranscripts } = await import("./transcript-JWSGSDSF.js");
|
|
282
|
+
const sources = [
|
|
283
|
+
{ name: "Claude Code", fn: findAllClaudeTranscripts },
|
|
284
|
+
{ name: "Cursor", fn: findAllCursorTranscripts },
|
|
285
|
+
{ name: "Continue", fn: findAllContinueTranscripts },
|
|
286
|
+
{ name: "Codex", fn: findAllCodexTranscripts },
|
|
287
|
+
{ name: "Roo Code", fn: findAllRooCodeTranscripts }
|
|
288
|
+
];
|
|
289
|
+
let totalTranscripts = 0;
|
|
290
|
+
for (const src of sources) {
|
|
291
|
+
const count = src.fn().length;
|
|
292
|
+
totalTranscripts += count;
|
|
293
|
+
if (count > 0) pass(`${src.name}: ${count} transcripts`);
|
|
294
|
+
}
|
|
295
|
+
if (totalTranscripts === 0) {
|
|
296
|
+
warning("No transcripts found from any IDE");
|
|
297
|
+
}
|
|
239
298
|
console.log("\nLLM backends (for compile-all):");
|
|
240
299
|
const backends = ["claude", "codex", "gemini", "copilot", "aider", "goose"];
|
|
241
300
|
const found = [];
|
|
@@ -267,7 +326,7 @@ ${ok} passed, ${warn} warnings, ${fail} errors`);
|
|
|
267
326
|
if (fail > 0) process.exit(1);
|
|
268
327
|
});
|
|
269
328
|
program.command("compile-all").description("Batch-compile all unprocessed transcripts using an available LLM CLI").action(async () => {
|
|
270
|
-
const { runCompileAll } = await import("./compile-all-
|
|
329
|
+
const { runCompileAll } = await import("./compile-all-PTWTZVP5.js");
|
|
271
330
|
await runCompileAll();
|
|
272
331
|
});
|
|
273
332
|
program.command("status").description("Show AgentCache knowledge stats").action(async () => {
|
|
@@ -3,28 +3,29 @@ import {
|
|
|
3
3
|
processExtraction,
|
|
4
4
|
startCompile
|
|
5
5
|
} from "./chunk-CUBZRYS5.js";
|
|
6
|
+
import "./chunk-GGAATZKM.js";
|
|
7
|
+
import {
|
|
8
|
+
acquireLock,
|
|
9
|
+
releaseLock
|
|
10
|
+
} from "./chunk-JUDLOBOC.js";
|
|
11
|
+
import {
|
|
12
|
+
SqliteKnowledgeRepository
|
|
13
|
+
} from "./chunk-PSASDZQE.js";
|
|
6
14
|
import {
|
|
7
15
|
findAllClaudeTranscripts,
|
|
8
16
|
findAllCodexTranscripts,
|
|
9
17
|
findAllContinueTranscripts,
|
|
18
|
+
findAllCursorTranscripts,
|
|
10
19
|
findAllRooCodeTranscripts,
|
|
11
20
|
getGooseDbPath,
|
|
12
21
|
parseTranscript
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import {
|
|
15
|
-
acquireLock,
|
|
16
|
-
releaseLock
|
|
17
|
-
} from "./chunk-JUDLOBOC.js";
|
|
18
|
-
import "./chunk-GGAATZKM.js";
|
|
22
|
+
} from "./chunk-WTXSZBQE.js";
|
|
19
23
|
import {
|
|
20
24
|
getDbPath,
|
|
21
25
|
getGitRoot,
|
|
22
26
|
getProjectId,
|
|
23
27
|
isInitialized
|
|
24
28
|
} from "./chunk-T4COG3XD.js";
|
|
25
|
-
import {
|
|
26
|
-
SqliteKnowledgeRepository
|
|
27
|
-
} from "./chunk-PSASDZQE.js";
|
|
28
29
|
import {
|
|
29
30
|
__esm,
|
|
30
31
|
__export,
|
|
@@ -294,6 +295,7 @@ function discoverAllTranscripts(repo) {
|
|
|
294
295
|
const results = [];
|
|
295
296
|
const allPaths = [
|
|
296
297
|
...findAllClaudeTranscripts(),
|
|
298
|
+
...findAllCursorTranscripts(),
|
|
297
299
|
...findAllContinueTranscripts(),
|
|
298
300
|
...findAllCodexTranscripts(),
|
|
299
301
|
...findAllRooCodeTranscripts()
|
|
@@ -311,6 +313,14 @@ function inferProjectRoot(transcriptPath) {
|
|
|
311
313
|
const slug = transcriptPath.split(".claude/projects/")[1]?.split("/")[0] || "";
|
|
312
314
|
if (slug.startsWith("-")) return slug.replace(/-/g, "/");
|
|
313
315
|
}
|
|
316
|
+
if (transcriptPath.includes(".cursor/projects/")) {
|
|
317
|
+
const slug = transcriptPath.split(".cursor/projects/")[1]?.split("/")[0] || "";
|
|
318
|
+
if (slug) {
|
|
319
|
+
const asPath = "/" + slug.replace(/-/g, "/");
|
|
320
|
+
const root = getGitRoot(asPath);
|
|
321
|
+
if (root) return root;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
314
324
|
try {
|
|
315
325
|
const events = parseTranscript(transcriptPath);
|
|
316
326
|
for (const event of events) {
|
package/dist/mcp.js
CHANGED
|
@@ -7,14 +7,17 @@ import {
|
|
|
7
7
|
startCompile
|
|
8
8
|
} from "./chunk-CUBZRYS5.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
10
|
+
computeCanonicalHash
|
|
11
|
+
} from "./chunk-GGAATZKM.js";
|
|
12
12
|
import {
|
|
13
13
|
spawnCompileAll
|
|
14
14
|
} from "./chunk-JUDLOBOC.js";
|
|
15
15
|
import {
|
|
16
|
-
|
|
17
|
-
} from "./chunk-
|
|
16
|
+
SqliteKnowledgeRepository
|
|
17
|
+
} from "./chunk-PSASDZQE.js";
|
|
18
|
+
import {
|
|
19
|
+
parseTranscript
|
|
20
|
+
} from "./chunk-WTXSZBQE.js";
|
|
18
21
|
import {
|
|
19
22
|
findProjectRoot,
|
|
20
23
|
getDataDir,
|
|
@@ -22,9 +25,6 @@ import {
|
|
|
22
25
|
getProjectId,
|
|
23
26
|
isInitialized
|
|
24
27
|
} from "./chunk-T4COG3XD.js";
|
|
25
|
-
import {
|
|
26
|
-
SqliteKnowledgeRepository
|
|
27
|
-
} from "./chunk-PSASDZQE.js";
|
|
28
28
|
import "./chunk-KFQGP6VL.js";
|
|
29
29
|
|
|
30
30
|
// src/mcp.ts
|
package/dist/postinstall.js
CHANGED
|
@@ -2,18 +2,20 @@ import {
|
|
|
2
2
|
spawnCompileAll
|
|
3
3
|
} from "./chunk-JUDLOBOC.js";
|
|
4
4
|
import {
|
|
5
|
-
detectInstalledIdes,
|
|
6
5
|
registerClaudeHooks,
|
|
7
6
|
registerMcpServer
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SLRKWMSE.js";
|
|
8
|
+
import {
|
|
9
|
+
SqliteKnowledgeRepository
|
|
10
|
+
} from "./chunk-PSASDZQE.js";
|
|
11
|
+
import {
|
|
12
|
+
detectInstalledIdes
|
|
13
|
+
} from "./chunk-5UO7NJPQ.js";
|
|
9
14
|
import {
|
|
10
15
|
getDataDir,
|
|
11
16
|
getDbPath,
|
|
12
17
|
migrateFromLegacy
|
|
13
18
|
} from "./chunk-T4COG3XD.js";
|
|
14
|
-
import {
|
|
15
|
-
SqliteKnowledgeRepository
|
|
16
|
-
} from "./chunk-PSASDZQE.js";
|
|
17
19
|
import "./chunk-KFQGP6VL.js";
|
|
18
20
|
|
|
19
21
|
// src/postinstall.ts
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SqliteKnowledgeRepository
|
|
3
|
+
} from "./chunk-PSASDZQE.js";
|
|
1
4
|
import {
|
|
2
5
|
findAllClaudeTranscripts,
|
|
3
6
|
findAllCodexTranscripts,
|
|
4
7
|
findAllContinueTranscripts,
|
|
8
|
+
findAllCursorTranscripts,
|
|
5
9
|
findAllRooCodeTranscripts
|
|
6
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WTXSZBQE.js";
|
|
7
11
|
import {
|
|
8
12
|
getDbPath,
|
|
9
13
|
getProjectId,
|
|
10
14
|
isInitialized
|
|
11
15
|
} from "./chunk-T4COG3XD.js";
|
|
12
|
-
import {
|
|
13
|
-
SqliteKnowledgeRepository
|
|
14
|
-
} from "./chunk-PSASDZQE.js";
|
|
15
16
|
import "./chunk-KFQGP6VL.js";
|
|
16
17
|
|
|
17
18
|
// src/hooks/session-start.ts
|
|
@@ -19,6 +20,14 @@ import { statSync } from "fs";
|
|
|
19
20
|
import { basename, dirname } from "path";
|
|
20
21
|
import { randomUUID } from "crypto";
|
|
21
22
|
function inferProjectRootFromTranscriptPath(path) {
|
|
23
|
+
if (path.includes(".claude/projects/")) {
|
|
24
|
+
const slug2 = path.split(".claude/projects/")[1]?.split("/")[0] || "";
|
|
25
|
+
if (slug2.startsWith("-")) return slug2.replace(/-/g, "/");
|
|
26
|
+
}
|
|
27
|
+
if (path.includes(".cursor/projects/")) {
|
|
28
|
+
const slug2 = path.split(".cursor/projects/")[1]?.split("/")[0] || "";
|
|
29
|
+
if (slug2) return "/" + slug2.replace(/-/g, "/");
|
|
30
|
+
}
|
|
22
31
|
const dir = dirname(path);
|
|
23
32
|
const slug = basename(dir);
|
|
24
33
|
if (slug.startsWith("-")) {
|
|
@@ -32,6 +41,7 @@ async function handleSessionStart() {
|
|
|
32
41
|
const compiledPaths = new Set(repo.getAllCompiledTranscriptPaths());
|
|
33
42
|
const allTranscripts = [
|
|
34
43
|
...findAllClaudeTranscripts(),
|
|
44
|
+
...findAllCursorTranscripts(),
|
|
35
45
|
...findAllContinueTranscripts(),
|
|
36
46
|
...findAllCodexTranscripts(),
|
|
37
47
|
...findAllRooCodeTranscripts()
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
detectInstalledIdes,
|
|
3
2
|
registerClaudeHooks,
|
|
4
3
|
registerMcpServer
|
|
5
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SLRKWMSE.js";
|
|
5
|
+
import {
|
|
6
|
+
SqliteKnowledgeRepository
|
|
7
|
+
} from "./chunk-PSASDZQE.js";
|
|
8
|
+
import {
|
|
9
|
+
detectInstalledIdes
|
|
10
|
+
} from "./chunk-5UO7NJPQ.js";
|
|
6
11
|
import {
|
|
7
12
|
getDataDir,
|
|
8
13
|
getDbPath,
|
|
9
14
|
migrateFromLegacy
|
|
10
15
|
} from "./chunk-T4COG3XD.js";
|
|
11
|
-
import {
|
|
12
|
-
SqliteKnowledgeRepository
|
|
13
|
-
} from "./chunk-PSASDZQE.js";
|
|
14
16
|
import "./chunk-KFQGP6VL.js";
|
|
15
17
|
|
|
16
18
|
// src/setup.ts
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findAllClaudeTranscripts,
|
|
3
|
+
findAllCodexTranscripts,
|
|
4
|
+
findAllContinueTranscripts,
|
|
5
|
+
findAllCursorTranscripts,
|
|
6
|
+
findAllGooseSessionIds,
|
|
7
|
+
findAllRooCodeTranscripts,
|
|
8
|
+
findLatestTranscript,
|
|
9
|
+
getGooseDbPath,
|
|
10
|
+
parseTranscript
|
|
11
|
+
} from "./chunk-WTXSZBQE.js";
|
|
12
|
+
import "./chunk-T4COG3XD.js";
|
|
13
|
+
import "./chunk-KFQGP6VL.js";
|
|
14
|
+
export {
|
|
15
|
+
findAllClaudeTranscripts,
|
|
16
|
+
findAllCodexTranscripts,
|
|
17
|
+
findAllContinueTranscripts,
|
|
18
|
+
findAllCursorTranscripts,
|
|
19
|
+
findAllGooseSessionIds,
|
|
20
|
+
findAllRooCodeTranscripts,
|
|
21
|
+
findLatestTranscript,
|
|
22
|
+
getGooseDbPath,
|
|
23
|
+
parseTranscript
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluatePolicy
|
|
3
3
|
} from "./chunk-T7BJPANN.js";
|
|
4
|
+
import {
|
|
5
|
+
SqliteKnowledgeRepository
|
|
6
|
+
} from "./chunk-PSASDZQE.js";
|
|
4
7
|
import {
|
|
5
8
|
findProjectRoot,
|
|
6
9
|
getDbPath,
|
|
7
10
|
getProjectId,
|
|
8
11
|
isInitialized
|
|
9
12
|
} from "./chunk-T4COG3XD.js";
|
|
10
|
-
import {
|
|
11
|
-
SqliteKnowledgeRepository
|
|
12
|
-
} from "./chunk-PSASDZQE.js";
|
|
13
13
|
import "./chunk-KFQGP6VL.js";
|
|
14
14
|
|
|
15
15
|
// src/hooks/pre-tool-use.ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SqliteKnowledgeRepository
|
|
3
|
+
} from "./chunk-PSASDZQE.js";
|
|
1
4
|
import {
|
|
2
5
|
findProjectRoot,
|
|
3
6
|
getDbPath,
|
|
4
7
|
getProjectId,
|
|
5
8
|
isInitialized
|
|
6
9
|
} from "./chunk-T4COG3XD.js";
|
|
7
|
-
import {
|
|
8
|
-
SqliteKnowledgeRepository
|
|
9
|
-
} from "./chunk-PSASDZQE.js";
|
|
10
10
|
import "./chunk-KFQGP6VL.js";
|
|
11
11
|
|
|
12
12
|
// src/hooks/stop.ts
|