@agentmemory/agentmemory 0.8.11 → 0.9.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/AGENTS.md +2 -2
- package/README.md +80 -9
- package/dist/cli.mjs +47 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +866 -33
- package/dist/index.mjs.map +1 -1
- package/dist/{src-M6V9yZW5.mjs → src-B3pEsBSb.mjs} +838 -29
- package/dist/src-B3pEsBSb.mjs.map +1 -0
- package/dist/standalone-DXc-BEqr.mjs +457 -0
- package/dist/standalone-DXc-BEqr.mjs.map +1 -0
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +230 -66
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-DmTkd0if.mjs → tools-registry-DXIK5CxQ.mjs} +31 -7
- package/dist/tools-registry-DXIK5CxQ.mjs.map +1 -0
- package/dist/viewer/index.html +264 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/dist/src-M6V9yZW5.mjs.map +0 -1
- package/dist/standalone-XB9gPYmo.mjs +0 -313
- package/dist/standalone-XB9gPYmo.mjs.map +0 -1
- package/dist/tools-registry-DmTkd0if.mjs.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -111,8 +111,8 @@ Hook scripts in `src/hooks/` are standalone Node.js scripts (no iii-sdk import).
|
|
|
111
111
|
|
|
112
112
|
## Current Stats (v0.8.9)
|
|
113
113
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
114
|
+
- 44 MCP tools (8 visible by default, `AGENTMEMORY_TOOLS=all` for all)
|
|
115
|
+
- 104 REST endpoints
|
|
116
116
|
- 6 MCP resources, 3 MCP prompts
|
|
117
117
|
- 12 hooks, 4 skills
|
|
118
118
|
- 50+ iii functions
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
|
-
<a href="https://gist.github.com/rohitg00/2067ab416f7bbe447c1977edaaa681e2"><img src="https://img.shields.io/badge/Viral%20GitHub%20Gist-
|
|
11
|
+
<a href="https://gist.github.com/rohitg00/2067ab416f7bbe447c1977edaaa681e2"><img src="https://img.shields.io/badge/Viral%20GitHub%20Gist-775%20stars%20%2F%20106%20forks-FF6B35?style=for-the-badge&logo=github&logoColor=white&labelColor=1a1a1a" alt="Design doc: 775 stars / 106 forks on the gist" /></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<p align="center">
|
|
26
26
|
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-recall.svg"><img src="assets/tags/stat-recall.svg" alt="95.2% retrieval R@5" height="38" /></picture>
|
|
27
27
|
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-tokens.svg"><img src="assets/tags/stat-tokens.svg" alt="92% fewer tokens" height="38" /></picture>
|
|
28
|
-
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-tools.svg"><img src="assets/tags/stat-tools.svg" alt="
|
|
28
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-tools.svg"><img src="assets/tags/stat-tools.svg" alt="44 MCP tools" height="38" /></picture>
|
|
29
29
|
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-hooks.svg"><img src="assets/tags/stat-hooks.svg" alt="12 auto hooks" height="38" /></picture>
|
|
30
30
|
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-deps.svg"><img src="assets/tags/stat-deps.svg" alt="0 external DBs" height="38" /></picture>
|
|
31
31
|
<picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/stat-tests.svg"><img src="assets/tags/stat-tests.svg" alt="654 tests passing" height="38" /></picture>
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
<a href="#how-it-works">How It Works</a> •
|
|
44
44
|
<a href="#mcp-server">MCP</a> •
|
|
45
45
|
<a href="#real-time-viewer">Viewer</a> •
|
|
46
|
+
<a href="#iii-console--trace-level-engine-inspection">iii Console</a> •
|
|
46
47
|
<a href="#configuration">Config</a> •
|
|
47
48
|
<a href="#api">API</a>
|
|
48
49
|
</p>
|
|
@@ -133,7 +134,7 @@ agentmemory works with any agent that supports hooks, MCP, or REST API. All agen
|
|
|
133
134
|
<sub>AgentSDKProvider</sub>
|
|
134
135
|
</td>
|
|
135
136
|
<td align="center" width="12.5%">
|
|
136
|
-
<img src="https://img.shields.io/badge/
|
|
137
|
+
<img src="https://img.shields.io/badge/104-endpoints-1f6feb?style=flat-square" alt="REST API" width="48" /><br/>
|
|
137
138
|
<strong>Any agent</strong><br/>
|
|
138
139
|
<sub>REST API</sub>
|
|
139
140
|
</td>
|
|
@@ -302,6 +303,22 @@ npx @agentmemory/agentmemory demo
|
|
|
302
303
|
|
|
303
304
|
Open `http://localhost:3113` to watch the memory build live.
|
|
304
305
|
|
|
306
|
+
### Session Replay
|
|
307
|
+
|
|
308
|
+
Every session agentmemory records is replayable. Open the viewer, pick the **Replay** tab, and scrub through the timeline: prompts, tool calls, tool results, and responses render as discrete events with play/pause, speed control (0.5×–4×), and keyboard shortcuts (space to toggle, arrows to step).
|
|
309
|
+
|
|
310
|
+
Already have older Claude Code JSONL transcripts you want to bring in?
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# Import everything under the default ~/.claude/projects
|
|
314
|
+
npx @agentmemory/agentmemory import-jsonl
|
|
315
|
+
|
|
316
|
+
# Or import a single file
|
|
317
|
+
npx @agentmemory/agentmemory import-jsonl ~/.claude/projects/-my-project/abc123.jsonl
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Imported sessions show up in the Replay picker alongside native ones. Under the hood each entry routes through the `mem::replay::load`, `mem::replay::sessions`, and `mem::replay::import-jsonl` iii functions — no side-channel servers.
|
|
321
|
+
|
|
305
322
|
### Upgrade / Maintenance
|
|
306
323
|
|
|
307
324
|
Use the maintenance command when you intentionally want to update your local runtime:
|
|
@@ -317,7 +334,7 @@ Implementation details live in `src/cli.ts` (see `runUpgrade` around the `src/cl
|
|
|
317
334
|
### Claude Code (one block, paste it)
|
|
318
335
|
|
|
319
336
|
```
|
|
320
|
-
Install agentmemory: run `npx @agentmemory/agentmemory` in a separate terminal to start the memory server. Then run `/plugin marketplace add rohitg00/agentmemory` and `/plugin install agentmemory` — the plugin registers all 12 hooks, 4 skills, AND auto-wires the `@agentmemory/mcp` stdio server via its `.mcp.json`, so you get
|
|
337
|
+
Install agentmemory: run `npx @agentmemory/agentmemory` in a separate terminal to start the memory server. Then run `/plugin marketplace add rohitg00/agentmemory` and `/plugin install agentmemory` — the plugin registers all 12 hooks, 4 skills, AND auto-wires the `@agentmemory/mcp` stdio server via its `.mcp.json`, so you get 44 MCP tools (memory_smart_search, memory_save, memory_sessions, memory_governance_delete, etc.) without any extra config step. Verify with `curl http://localhost:3111/agentmemory/health`. The real-time viewer is at http://localhost:3113.
|
|
321
338
|
```
|
|
322
339
|
|
|
323
340
|
<details>
|
|
@@ -576,9 +593,9 @@ npm install @xenova/transformers
|
|
|
576
593
|
|
|
577
594
|
<h2 id="mcp-server"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/section-mcp.svg"><img src="assets/tags/section-mcp.svg" alt="MCP Server" height="32" /></picture></h2>
|
|
578
595
|
|
|
579
|
-
|
|
596
|
+
44 tools, 6 resources, 3 prompts, and 4 skills — the most comprehensive MCP memory toolkit for any agent.
|
|
580
597
|
|
|
581
|
-
###
|
|
598
|
+
### 44 Tools
|
|
582
599
|
|
|
583
600
|
<details>
|
|
584
601
|
<summary>Core tools (always available)</summary>
|
|
@@ -586,17 +603,21 @@ npm install @xenova/transformers
|
|
|
586
603
|
| Tool | Description |
|
|
587
604
|
|------|-------------|
|
|
588
605
|
| `memory_recall` | Search past observations |
|
|
606
|
+
| `memory_compress_file` | Compress markdown files while preserving structure |
|
|
589
607
|
| `memory_save` | Save an insight, decision, or pattern |
|
|
608
|
+
| `memory_patterns` | Detect recurring patterns |
|
|
590
609
|
| `memory_smart_search` | Hybrid semantic + keyword search |
|
|
591
610
|
| `memory_file_history` | Past observations about specific files |
|
|
592
611
|
| `memory_sessions` | List recent sessions |
|
|
612
|
+
| `memory_timeline` | Chronological observations |
|
|
593
613
|
| `memory_profile` | Project profile (concepts, files, patterns) |
|
|
594
614
|
| `memory_export` | Export all memory data |
|
|
615
|
+
| `memory_relations` | Query relationship graph |
|
|
595
616
|
|
|
596
617
|
</details>
|
|
597
618
|
|
|
598
619
|
<details>
|
|
599
|
-
<summary>Extended tools (
|
|
620
|
+
<summary>Extended tools (44 total — set AGENTMEMORY_TOOLS=all)</summary>
|
|
600
621
|
|
|
601
622
|
| Tool | Description |
|
|
602
623
|
|------|-------------|
|
|
@@ -698,6 +719,56 @@ open http://localhost:3113
|
|
|
698
719
|
|
|
699
720
|
The viewer server binds to `127.0.0.1` by default. The REST-served `/agentmemory/viewer` endpoint follows the normal `AGENTMEMORY_SECRET` bearer-token rules. CSP headers use a per-response script nonce and disable inline handler attributes (`script-src-attr 'none'`).
|
|
700
721
|
|
|
722
|
+
### iii console — trace-level engine inspection
|
|
723
|
+
|
|
724
|
+
agentmemory runs on the [iii engine](https://iii.dev), so the official [iii console](https://iii.dev/docs/console) gives you OpenTelemetry traces, the raw key/value state store, the stream monitor, and a direct function invoker for every piece of memory machinery. Use it to watch a `memory.search` call hit BM25 → embeddings → reranker in real time, replay a hook invocation, or poke individual functions without going through MCP.
|
|
725
|
+
|
|
726
|
+
<p align="center">
|
|
727
|
+
<img src="assets/iii-console/dashboard.png" alt="iii console dashboard — system counters, application flow, registered triggers, live WebSocket status" width="720" />
|
|
728
|
+
<br/>
|
|
729
|
+
<em>Dashboard: functions, triggers, workers, streams, live flow graph. Screenshot from <a href="https://iii.dev/docs/console">iii.dev/docs/console</a>.</em>
|
|
730
|
+
</p>
|
|
731
|
+
|
|
732
|
+
**Install once:**
|
|
733
|
+
|
|
734
|
+
```bash
|
|
735
|
+
curl -fsSL https://install.iii.dev/console/main/install.sh | sh
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
**Launch alongside agentmemory:**
|
|
739
|
+
|
|
740
|
+
```bash
|
|
741
|
+
# The agentmemory viewer already holds port 3113, so run the console on 3114.
|
|
742
|
+
iii-console --port 3114 --engine-port 3111 --ws-port 3112
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Then open `http://localhost:3114`.
|
|
746
|
+
|
|
747
|
+
**What you can do from the console:**
|
|
748
|
+
|
|
749
|
+
| Page | Use it to |
|
|
750
|
+
|------|-----------|
|
|
751
|
+
| **Functions** | Invoke any of agentmemory's ~33 functions directly with a JSON payload — handy for testing `memory.recall`, `memory.consolidate`, `graph.query` without wiring a client. |
|
|
752
|
+
| **Triggers** | Replay HTTP triggers (the agentmemory REST endpoints), fire the consolidation cron manually, or emit queue events. |
|
|
753
|
+
| **States** | Browse the KV store — sessions, memory slots, lifecycle timers, embeddings index — and edit values in place. |
|
|
754
|
+
| **Streams** | Watch live memory writes, hook events, and observation updates as they flow through iii's WebSocket stream. |
|
|
755
|
+
| **Traces** | OpenTelemetry waterfall / flame / service-breakdown views. Filter by `trace_id` to see exactly which functions, DB calls, and embedding requests a single `memory.search` produced. |
|
|
756
|
+
| **Logs** | Structured OTEL logs correlated to trace/span IDs. |
|
|
757
|
+
|
|
758
|
+
<p align="center">
|
|
759
|
+
<img src="assets/iii-console/traces-waterfall.png" alt="iii console trace waterfall view showing per-span duration" width="720" />
|
|
760
|
+
<br/>
|
|
761
|
+
<em>Traces: waterfall / flame / service breakdown for every memory operation.</em>
|
|
762
|
+
</p>
|
|
763
|
+
|
|
764
|
+
**Traces are already on:**
|
|
765
|
+
|
|
766
|
+
`iii-config.yaml` ships with the `iii-observability` worker enabled (`exporter: memory`, `sampling_ratio: 1.0`, metrics + logs). No extra config needed — the moment agentmemory starts, every memory operation emits a trace span and a structured log the console can read.
|
|
767
|
+
|
|
768
|
+
If you want to export to Jaeger/Honeycomb/Grafana Tempo instead, change `exporter: memory` to `exporter: otlp` and set the collector endpoint per iii's observability docs.
|
|
769
|
+
|
|
770
|
+
> **Heads-up:** no auth is enforced on the console itself — keep it bound to `127.0.0.1` (the default) and never expose it publicly.
|
|
771
|
+
|
|
701
772
|
---
|
|
702
773
|
|
|
703
774
|
<h2 id="configuration"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/section-config.svg"><img src="assets/tags/section-config.svg" alt="Configuration" height="32" /></picture></h2>
|
|
@@ -772,7 +843,7 @@ Create `~/.agentmemory/.env`:
|
|
|
772
843
|
# USER_ID=
|
|
773
844
|
# TEAM_MODE=private
|
|
774
845
|
|
|
775
|
-
# Tool visibility: "core" (
|
|
846
|
+
# Tool visibility: "core" (8 tools) or "all" (44 tools)
|
|
776
847
|
# AGENTMEMORY_TOOLS=core
|
|
777
848
|
```
|
|
778
849
|
|
|
@@ -780,7 +851,7 @@ Create `~/.agentmemory/.env`:
|
|
|
780
851
|
|
|
781
852
|
<h2 id="api"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/section-api.svg"><img src="assets/tags/section-api.svg" alt="API" height="32" /></picture></h2>
|
|
782
853
|
|
|
783
|
-
|
|
854
|
+
107 endpoints on port `3111`. The REST API binds to `127.0.0.1` by default. Protected endpoints require `Authorization: Bearer <secret>` when `AGENTMEMORY_SECRET` is set, and mesh sync endpoints require `AGENTMEMORY_SECRET` on both peers.
|
|
784
855
|
|
|
785
856
|
<details>
|
|
786
857
|
<summary>Key endpoints</summary>
|
package/dist/cli.mjs
CHANGED
|
@@ -91,6 +91,7 @@ Commands:
|
|
|
91
91
|
demo Seed sample sessions and show recall in action
|
|
92
92
|
upgrade Upgrade local deps + iii runtime (best effort)
|
|
93
93
|
mcp Start standalone MCP server (no engine required)
|
|
94
|
+
import-jsonl [p] Import Claude Code JSONL transcripts (default: ~/.claude/projects)
|
|
94
95
|
|
|
95
96
|
Options:
|
|
96
97
|
--help, -h Show this help
|
|
@@ -286,12 +287,12 @@ async function main() {
|
|
|
286
287
|
p.intro("agentmemory");
|
|
287
288
|
if (skipEngine) {
|
|
288
289
|
p.log.info("Skipping engine check (--no-engine)");
|
|
289
|
-
await import("./src-
|
|
290
|
+
await import("./src-B3pEsBSb.mjs");
|
|
290
291
|
return;
|
|
291
292
|
}
|
|
292
293
|
if (await isEngineRunning()) {
|
|
293
294
|
p.log.success("iii-engine is running");
|
|
294
|
-
await import("./src-
|
|
295
|
+
await import("./src-B3pEsBSb.mjs");
|
|
295
296
|
return;
|
|
296
297
|
}
|
|
297
298
|
if (!await startEngine()) {
|
|
@@ -335,7 +336,7 @@ async function main() {
|
|
|
335
336
|
process.exit(1);
|
|
336
337
|
}
|
|
337
338
|
s.stop("iii-engine is ready");
|
|
338
|
-
await import("./src-
|
|
339
|
+
await import("./src-B3pEsBSb.mjs");
|
|
339
340
|
}
|
|
340
341
|
async function runStatus() {
|
|
341
342
|
const port = getRestPort();
|
|
@@ -643,13 +644,54 @@ async function runUpgrade() {
|
|
|
643
644
|
].join("\n"), "agentmemory upgrade");
|
|
644
645
|
}
|
|
645
646
|
async function runMcp() {
|
|
646
|
-
await import("./standalone-
|
|
647
|
+
await import("./standalone-DXc-BEqr.mjs");
|
|
648
|
+
}
|
|
649
|
+
async function runImportJsonl() {
|
|
650
|
+
const pathArg = args.slice(1).filter((a) => !a.startsWith("-"))[0];
|
|
651
|
+
const port = getRestPort();
|
|
652
|
+
const base = `http://localhost:${port}`;
|
|
653
|
+
try {
|
|
654
|
+
await fetch(`${base}/agentmemory/livez`, { signal: AbortSignal.timeout(2e3) });
|
|
655
|
+
} catch {
|
|
656
|
+
p.log.error(`agentmemory is not running on port ${port}. Start it first.`);
|
|
657
|
+
process.exit(1);
|
|
658
|
+
}
|
|
659
|
+
const body = {};
|
|
660
|
+
if (pathArg) body["path"] = pathArg;
|
|
661
|
+
const headers = { "content-type": "application/json" };
|
|
662
|
+
const secret = process.env["AGENTMEMORY_SECRET"];
|
|
663
|
+
if (secret) headers["authorization"] = `Bearer ${secret}`;
|
|
664
|
+
p.log.info(`Importing JSONL from ${pathArg || "~/.claude/projects"}…`);
|
|
665
|
+
const spinner = p.spinner();
|
|
666
|
+
spinner.start("scanning files");
|
|
667
|
+
try {
|
|
668
|
+
const res = await fetch(`${base}/agentmemory/replay/import-jsonl`, {
|
|
669
|
+
method: "POST",
|
|
670
|
+
headers,
|
|
671
|
+
body: JSON.stringify(body),
|
|
672
|
+
signal: AbortSignal.timeout(12e4)
|
|
673
|
+
});
|
|
674
|
+
const json = await res.json();
|
|
675
|
+
if (!res.ok || json.success === false) {
|
|
676
|
+
spinner.stop("failed");
|
|
677
|
+
p.log.error(json.error || `HTTP ${res.status}`);
|
|
678
|
+
process.exit(1);
|
|
679
|
+
}
|
|
680
|
+
spinner.stop(`imported ${json.imported} file(s), ${json.observations} observation(s) across ${json.sessionIds?.length || 0} session(s)`);
|
|
681
|
+
if (json.sessionIds && json.sessionIds.length > 0) p.log.info(`View at http://localhost:${port + 2} → Replay tab`);
|
|
682
|
+
} catch (err) {
|
|
683
|
+
spinner.stop("failed");
|
|
684
|
+
if (err instanceof Error && err.name === "TimeoutError") p.log.error("import timed out after 2 minutes");
|
|
685
|
+
else p.log.error(err instanceof Error ? err.message : String(err));
|
|
686
|
+
process.exit(1);
|
|
687
|
+
}
|
|
647
688
|
}
|
|
648
689
|
({
|
|
649
690
|
status: runStatus,
|
|
650
691
|
demo: runDemo,
|
|
651
692
|
upgrade: runUpgrade,
|
|
652
|
-
mcp: runMcp
|
|
693
|
+
mcp: runMcp,
|
|
694
|
+
"import-jsonl": runImportJsonl
|
|
653
695
|
}[args[0] ?? ""] ?? main)().catch((err) => {
|
|
654
696
|
p.log.error(err instanceof Error ? err.message : String(err));
|
|
655
697
|
process.exit(1);
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["PATH_DELIMITER"],"sources":["../src/state/schema.ts","../src/cli.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const KV = {\n sessions: \"mem:sessions\",\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\n memories: \"mem:memories\",\n summaries: \"mem:summaries\",\n config: \"mem:config\",\n metrics: \"mem:metrics\",\n health: \"mem:health\",\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\n bm25Index: \"mem:index:bm25\",\n relations: \"mem:relations\",\n profiles: \"mem:profiles\",\n claudeBridge: \"mem:claude-bridge\",\n graphNodes: \"mem:graph:nodes\",\n graphEdges: \"mem:graph:edges\",\n semantic: \"mem:semantic\",\n procedural: \"mem:procedural\",\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\n teamUsers: (teamId: string, userId: string) =>\n `mem:team:${teamId}:users:${userId}`,\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\n audit: \"mem:audit\",\n actions: \"mem:actions\",\n actionEdges: \"mem:action-edges\",\n leases: \"mem:leases\",\n routines: \"mem:routines\",\n routineRuns: \"mem:routine-runs\",\n signals: \"mem:signals\",\n checkpoints: \"mem:checkpoints\",\n mesh: \"mem:mesh\",\n sketches: \"mem:sketches\",\n facets: \"mem:facets\",\n sentinels: \"mem:sentinels\",\n crystals: \"mem:crystals\",\n lessons: \"mem:lessons\",\n insights: \"mem:insights\",\n graphEdgeHistory: \"mem:graph:edge-history\",\n enrichedChunks: (sessionId: string) => `mem:enriched:${sessionId}`,\n latentEmbeddings: (obsId: string) => `mem:latent:${obsId}`,\n retentionScores: \"mem:retention\",\n accessLog: \"mem:access\",\n} as const;\n\nexport const STREAM = {\n name: \"mem-live\",\n group: (sessionId: string) => sessionId,\n viewerGroup: \"viewer\",\n} as const;\n\nexport function generateId(prefix: string): string {\n const ts = Date.now().toString(36);\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\n return `${prefix}_${ts}_${rand}`;\n}\n\nexport function fingerprintId(prefix: string, content: string): string {\n const hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return `${prefix}_${hash.slice(0, 16)}`;\n}\n\nexport function jaccardSimilarity(a: string, b: string): number {\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\n if (setA.size === 0 && setB.size === 0) return 1;\n if (setA.size === 0 || setB.size === 0) return 0;\n let intersection = 0;\n for (const word of setA) {\n if (setB.has(word)) intersection++;\n }\n return intersection / (setA.size + setB.size - intersection);\n}\n","#!/usr/bin/env node\n\nimport {\n spawn,\n execFileSync,\n spawnSync,\n type ChildProcess,\n} from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname, delimiter as PATH_DELIMITER } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { platform } from \"node:os\";\nimport * as p from \"@clack/prompts\";\nimport { generateId } from \"./state/schema.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\nconst IS_WINDOWS = platform() === \"win32\";\nconst IS_VERBOSE = args.includes(\"--verbose\") || args.includes(\"-v\");\n\nfunction vlog(msg: string): void {\n if (IS_VERBOSE) p.log.info(`[verbose] ${msg}`);\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [command] [options]\n\nCommands:\n (default) Start agentmemory worker\n status Show connection status, memory count, and health\n demo Seed sample sessions and show recall in action\n upgrade Upgrade local deps + iii runtime (best effort)\n mcp Start standalone MCP server (no engine required)\n\nOptions:\n --help, -h Show this help\n --verbose, -v Show engine stderr and diagnostic info on startup\n --tools all|core Tool visibility (default: core = 7 tools)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111)\n\nQuick start:\n npx @agentmemory/agentmemory # start with local iii-engine or Docker\n npx @agentmemory/agentmemory status # check health\n npx @agentmemory/agentmemory demo # try it in 30 seconds (needs server running)\n npx @agentmemory/agentmemory upgrade # upgrade agentmemory + iii runtime\n npx @agentmemory/agentmemory mcp # standalone MCP server (no engine)\n npx @agentmemory/mcp # same as above (shim package)\n`);\n process.exit(0);\n}\n\nconst toolsIdx = args.indexOf(\"--tools\");\nif (toolsIdx !== -1 && args[toolsIdx + 1]) {\n process.env[\"AGENTMEMORY_TOOLS\"] = args[toolsIdx + 1];\n}\n\nconst portIdx = args.indexOf(\"--port\");\nif (portIdx !== -1 && args[portIdx + 1]) {\n process.env[\"III_REST_PORT\"] = args[portIdx + 1];\n}\n\nconst skipEngine = args.includes(\"--no-engine\");\n\nfunction getRestPort(): number {\n return parseInt(process.env[\"III_REST_PORT\"] || \"3111\", 10) || 3111;\n}\n\nasync function isEngineRunning(): Promise<boolean> {\n try {\n await fetch(`http://localhost:${getRestPort()}/`, {\n signal: AbortSignal.timeout(2000),\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n const candidates = [\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n join(process.cwd(), \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return \"\";\n}\n\nfunction whichBinary(name: string): string | null {\n const cmd = IS_WINDOWS ? \"where\" : \"which\";\n try {\n const out = execFileSync(cmd, [name], { encoding: \"utf-8\" });\n const first = out\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n return first ?? null;\n } catch {\n return null;\n }\n}\n\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return [];\n return [\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n ];\n }\n const home = process.env[\"HOME\"];\n if (!home) return [\"/usr/local/bin/iii\"];\n return [join(home, \".local\", \"bin\", \"iii\"), \"/usr/local/bin/iii\"];\n}\n\ntype StartupFailure = {\n kind: \"no-engine\" | \"no-docker-compose\" | \"engine-crashed\" | \"docker-crashed\";\n stderr?: string;\n binary?: string;\n};\n\nlet startupFailure: StartupFailure | null = null;\n\n// Spawn a background engine and collect any startup stderr for a short\n// window. The process is unref'd so the CLI parent can exit cleanly; we\n// only care about stderr that shows up BEFORE the health check succeeds,\n// which is what surfaces early crash/config-parse errors on all platforms.\nfunction spawnEngineBackground(\n bin: string,\n spawnArgs: string[],\n label: string,\n): ChildProcess {\n vlog(`spawn: ${bin} ${spawnArgs.join(\" \")}`);\n const child = spawn(bin, spawnArgs, {\n detached: true,\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n windowsHide: true,\n });\n const stderrChunks: Buffer[] = [];\n let stderrBytes = 0;\n const MAX_STDERR_CAPTURE = 16 * 1024;\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n if (stderrBytes >= MAX_STDERR_CAPTURE) return;\n const slice = chunk.subarray(0, MAX_STDERR_CAPTURE - stderrBytes);\n stderrChunks.push(slice);\n stderrBytes += slice.length;\n });\n child.on(\"exit\", (code, signal) => {\n const abnormal =\n (code !== null && code !== 0) || (code === null && signal !== null);\n if (abnormal) {\n const stderr = Buffer.concat(stderrChunks).toString(\"utf-8\");\n startupFailure = {\n kind: label.includes(\"Docker\") ? \"docker-crashed\" : \"engine-crashed\",\n stderr:\n stderr.trim() ||\n (signal\n ? `process killed by signal ${signal}`\n : `process exited with code ${code}`),\n binary: bin,\n };\n vlog(`engine exited early: code=${code} signal=${signal}`);\n if (IS_VERBOSE && stderr.trim()) {\n p.log.error(`engine stderr:\\n${stderr}`);\n }\n }\n });\n child.unref();\n return child;\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n let iiiBin = whichBinary(\"iii\");\n vlog(`iii binary: ${iiiBin ?? \"(not on PATH)\"}, config: ${configPath || \"(not found)\"}`);\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n const dockerBin = whichBinary(\"docker\");\n vlog(`docker binary: ${dockerBin ?? \"(not on PATH)\"}`);\n const dockerComposeCandidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n const composeFile = dockerComposeCandidates.find((c) => existsSync(c));\n vlog(`docker-compose.yml: ${composeFile ?? \"(not found)\"}`);\n\n if (dockerBin && composeFile) {\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\n spawnEngineBackground(\n dockerBin,\n [\"compose\", \"-f\", composeFile, \"up\", \"-d\"],\n \"iii-engine via Docker\",\n );\n s.stop(\"Docker compose started\");\n return true;\n }\n\n for (const iiiPath of fallbackIiiPaths()) {\n if (existsSync(iiiPath)) {\n p.log.info(`Found iii at: ${iiiPath}`);\n process.env[\"PATH\"] = `${dirname(iiiPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = iiiPath;\n break;\n }\n }\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n if (!iiiBin && (!dockerBin || !composeFile)) {\n startupFailure = { kind: \"no-engine\" };\n } else if (!composeFile && dockerBin) {\n startupFailure = { kind: \"no-docker-compose\" };\n }\n return false;\n}\n\nasync function waitForEngine(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isEngineRunning()) return true;\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\nfunction installInstructions(): string[] {\n if (IS_WINDOWS) {\n return [\n \"agentmemory requires the `iii-engine` runtime. Pick one:\",\n \"\",\n \" A) Download the prebuilt Windows binary:\",\n \" 1. Open https://github.com/iii-hq/iii/releases/latest\",\n \" 2. Download iii-x86_64-pc-windows-msvc.zip\",\n \" (or iii-aarch64-pc-windows-msvc.zip on ARM)\",\n \" 3. Extract iii.exe and either add its folder to PATH\",\n \" or move it to %USERPROFILE%\\\\.local\\\\bin\\\\iii.exe\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \" B) Docker Desktop:\",\n \" 1. Install Docker Desktop for Windows\",\n \" 2. Start Docker Desktop (engine must be running)\",\n \" 3. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n ];\n }\n return [\n \"agentmemory requires the `iii-engine` runtime. Pick one:\",\n \"\",\n \" A) curl -fsSL https://install.iii.dev/iii/main/install.sh | sh\",\n \" (installs the prebuilt iii binary into ~/.local/bin/iii)\",\n \"\",\n \" B) Docker: install Docker Desktop or docker-ce, then re-run\",\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n}\n\nfunction portInUseDiagnostic(port: number): string {\n return IS_WINDOWS\n ? ` netstat -ano | findstr :${port}`\n : ` lsof -i :${port} # or: ss -tlnp | grep :${port}`;\n}\n\nasync function main() {\n p.intro(\"agentmemory\");\n\n if (skipEngine) {\n p.log.info(\"Skipping engine check (--no-engine)\");\n await import(\"./index.js\");\n return;\n }\n\n if (await isEngineRunning()) {\n p.log.success(\"iii-engine is running\");\n await import(\"./index.js\");\n return;\n }\n\n const started = await startEngine();\n if (!started) {\n p.log.error(\"Could not start iii-engine.\");\n const lines = installInstructions();\n if (startupFailure?.kind === \"no-docker-compose\") {\n lines.unshift(\n \"Docker is installed but docker-compose.yml is missing from this\",\n \"install. Re-install with: npm install -g @agentmemory/agentmemory\",\n \"\",\n );\n }\n p.note(lines.join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n\n const s = p.spinner();\n s.start(\"Waiting for iii-engine to be ready...\");\n\n const ready = await waitForEngine(15000);\n if (!ready) {\n const port = getRestPort();\n s.stop(\"iii-engine did not become ready within 15s\");\n\n if (startupFailure?.kind === \"engine-crashed\" || startupFailure?.kind === \"docker-crashed\") {\n p.log.error(\"The iii-engine process crashed on startup.\");\n if (startupFailure.binary) {\n p.log.info(`Binary: ${startupFailure.binary}`);\n }\n if (startupFailure.stderr) {\n p.note(startupFailure.stderr, \"engine stderr\");\n } else {\n p.log.info(\"No stderr was captured. Re-run with --verbose for more detail.\");\n }\n p.note(\n [\n \"Common causes:\",\n \" - iii-engine version mismatch — reinstall the latest binary\",\n \" (sh script on macOS/Linux, GitHub release zip on Windows)\",\n \" - Docker Desktop not running (if you're using the Docker path)\",\n \" - Port already in use (see below)\",\n \"\",\n \"See https://iii.dev/docs for current install instructions.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n } else {\n p.log.error(\"The engine process started but the REST API never responded.\");\n p.note(\n [\n `Check whether port ${port} is already bound by another process:`,\n portInUseDiagnostic(port),\n \"\",\n \"If it is, free the port or override: agentmemory --port <N>\",\n \"\",\n \"If it isn't, a firewall may be blocking 127.0.0.1:\" + port + \".\",\n \"Re-run with --verbose to see engine stderr.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n }\n process.exit(1);\n }\n\n s.stop(\"iii-engine is ready\");\n await import(\"./index.js\");\n}\n\nasync function runStatus() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory status\");\n\n const up = await isEngineRunning();\n if (!up) {\n p.log.error(`Not running — no response on port ${port}`);\n p.log.info(\"Start with: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n try {\n const [healthRes, sessionsRes, graphRes, memoriesRes] = await Promise.all([\n fetch(`${base}/agentmemory/health`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/sessions`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/graph/stats`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/export`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n ]);\n\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessions = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions.length : 0;\n const nodes = graphRes?.nodes || 0;\n const edges = graphRes?.edges || 0;\n const cb = healthRes?.circuitBreaker?.state || \"closed\";\n const heapMB = h?.memory ? Math.round(h.memory.heapUsed / 1048576) : 0;\n const uptime = h?.uptimeSeconds ? Math.round(h.uptimeSeconds) : 0;\n\n const obsCount = memoriesRes?.observations?.length || 0;\n const memCount = memoriesRes?.memories?.length || 0;\n const estFullTokens = obsCount * 80;\n const estInjectedTokens = Math.min(obsCount, 50) * 38;\n const tokensSaved = estFullTokens - estInjectedTokens;\n const pctSaved = estFullTokens > 0 ? Math.round((tokensSaved / estFullTokens) * 100) : 0;\n\n p.log.success(`Connected — v${version} on port ${port}`);\n\n const lines = [\n `Health: ${status === \"healthy\" ? \"✓ healthy\" : status}`,\n `Sessions: ${sessions}`,\n `Observations: ${obsCount}`,\n `Memories: ${memCount}`,\n `Graph: ${nodes} nodes, ${edges} edges`,\n `Circuit: ${cb}`,\n `Heap: ${heapMB} MB`,\n `Uptime: ${uptime}s`,\n `Viewer: http://localhost:${port + 2}`,\n ];\n\n if (obsCount > 0) {\n lines.push(\"\");\n lines.push(`Token savings: ~${tokensSaved.toLocaleString()} tokens saved (${pctSaved}% reduction)`);\n lines.push(` Full context: ~${estFullTokens.toLocaleString()} tokens`);\n lines.push(` Injected: ~${estInjectedTokens.toLocaleString()} tokens`);\n }\n\n p.note(lines.join(\"\\n\"), \"agentmemory\");\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\ntype DemoObservation = {\n toolName: string;\n toolInput: Record<string, string>;\n toolOutput: string;\n};\n\ntype DemoSession = {\n id: string;\n title: string;\n observations: DemoObservation[];\n};\n\ntype SearchResult = { query: string; hits: number; topTitle: string };\n\nfunction buildDemoSessions(): DemoSession[] {\n return [\n {\n id: generateId(\"demo\"),\n title: \"Session 1: JWT auth setup\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/auth.ts\" },\n toolOutput:\n \"Created JWT middleware using jose library. Tokens expire after 30 days. Chose jose over jsonwebtoken for Edge compatibility.\",\n },\n {\n toolName: \"Write\",\n toolInput: { file_path: \"test/auth.test.ts\" },\n toolOutput:\n \"Added token validation tests covering expired, malformed, and valid cases.\",\n },\n {\n toolName: \"Bash\",\n toolInput: { command: \"npm test\" },\n toolOutput: \"All 12 auth tests passing.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 2: Database migration debugging\",\n observations: [\n {\n toolName: \"Read\",\n toolInput: { file_path: \"prisma/schema.prisma\" },\n toolOutput:\n \"Found N+1 query issue in user relations. Need to add include on posts query.\",\n },\n {\n toolName: \"Edit\",\n toolInput: { file_path: \"src/api/users.ts\" },\n toolOutput:\n \"Fixed N+1 by adding Prisma include. Query time dropped from 450ms to 28ms.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 3: Rate limiting\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/ratelimit.ts\" },\n toolOutput:\n \"Added rate limiting middleware with 100 req/min default. Uses in-memory store for dev, Redis for prod.\",\n },\n ],\n },\n ];\n}\n\nasync function postJson<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n return (await res.json().catch(() => null)) as T | null;\n } catch {\n return null;\n }\n}\n\nasync function postJsonStrict<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n const suffix = errBody ? ` — ${errBody.slice(0, 200)}` : \"\";\n throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${suffix}`);\n }\n return (await res.json().catch(() => null)) as T | null;\n}\n\nasync function seedDemoSession(\n base: string,\n project: string,\n session: DemoSession,\n): Promise<number> {\n await postJsonStrict(`${base}/agentmemory/session/start`, {\n sessionId: session.id,\n project,\n cwd: project,\n });\n\n let stored = 0;\n for (const obs of session.observations) {\n const url = `${base}/agentmemory/observe`;\n const payload = {\n hookType: \"post_tool_use\",\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n data: {\n tool_name: obs.toolName,\n tool_input: obs.toolInput,\n tool_output: obs.toolOutput,\n },\n };\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(5000),\n });\n if (res.ok) {\n stored++;\n } else {\n const body = await res.text().catch(() => \"\");\n p.log.warn(\n `observe failed for ${obs.toolName}: ${res.status} ${res.statusText}${body ? ` — ${body.slice(0, 160)}` : \"\"}`,\n );\n }\n } catch (err) {\n p.log.warn(\n `observe request failed for ${obs.toolName}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n await postJsonStrict(`${base}/agentmemory/session/end`, { sessionId: session.id });\n return stored;\n}\n\nasync function runDemoSearch(base: string, query: string): Promise<SearchResult> {\n const data = await postJson<{ results?: Array<{ title?: string }> }>(\n `${base}/agentmemory/smart-search`,\n { query, limit: 5 },\n 10000,\n );\n const items = data?.results ?? [];\n return {\n query,\n hits: items.length,\n topTitle: items[0]?.title ?? \"(no results)\",\n };\n}\n\nasync function runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n if (!(await isEngineRunning())) {\n p.log.error(`Not running — no response on port ${port}`);\n p.log.info(\"Start the server first: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n const demoProject = \"/tmp/agentmemory-demo\";\n const sessions = buildDemoSessions();\n\n const sSeed = p.spinner();\n sSeed.start(\"Seeding 3 demo sessions with realistic observations...\");\n\n let totalObs = 0;\n for (const session of sessions) {\n totalObs += await seedDemoSession(base, demoProject, session);\n }\n\n sSeed.stop(`Seeded ${totalObs} observations across ${sessions.length} sessions`);\n\n const queries = [\n \"jwt auth middleware\",\n \"database performance optimization\",\n \"rate limiting\",\n ];\n\n const sQuery = p.spinner();\n sQuery.start(`Running ${queries.length} smart-search queries...`);\n\n const results: SearchResult[] = [];\n for (const query of queries) {\n results.push(await runDemoSearch(base, query));\n }\n\n sQuery.stop(\"Search complete\");\n\n const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n \"Search results:\",\n ...results.flatMap((r) => [\n ` \"${r.query}\"`,\n ` → ${r.hits} hit(s), top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n `Notice: searching \"database performance optimization\"`,\n `found the N+1 query fix — keyword matching can't do that.`,\n \"\",\n `Viewer: http://localhost:${port + 2}`,\n `Clean up with: curl -X DELETE \"${base}/agentmemory/sessions?project=${demoProject}\"`,\n ];\n\n p.note(lines.join(\"\\n\"), \"demo complete\");\n p.log.success(\"agentmemory is working. Point your agent at it and get back to coding.\");\n}\n\nfunction runCommand(\n command: string,\n commandArgs: string[],\n options: { cwd?: string; label: string; optional?: boolean } = { label: \"command\" },\n): boolean {\n const spinner = p.spinner();\n spinner.start(options.label);\n const result = spawnSync(command, commandArgs, {\n cwd: options.cwd || process.cwd(),\n stdio: \"pipe\",\n encoding: \"utf-8\",\n });\n\n if (result.status === 0) {\n spinner.stop(`${options.label} ✓`);\n return true;\n }\n\n const stderr = (result.stderr || \"\").toString().trim();\n const stdout = (result.stdout || \"\").toString().trim();\n const msg = stderr || stdout || \"unknown error\";\n\n if (options.optional) {\n spinner.stop(`${options.label} (skipped)`);\n p.log.warn(msg.slice(0, 300));\n return false;\n }\n\n spinner.stop(`${options.label} ✗`);\n p.log.error(msg.slice(0, 300));\n return false;\n}\n\nasync function runUpgrade() {\n p.intro(\"agentmemory upgrade\");\n\n const cwd = process.cwd();\n const hasPackageJson = existsSync(join(cwd, \"package.json\"));\n const hasPnpmLock = existsSync(join(cwd, \"pnpm-lock.yaml\"));\n\n const pnpmBin = whichBinary(\"pnpm\");\n const npmBin = whichBinary(\"npm\");\n const cargoBin = whichBinary(\"cargo\");\n const dockerBin = whichBinary(\"docker\");\n\n p.log.info(`Working directory: ${cwd}`);\n const requireSuccess = (ok: boolean, label: string): void => {\n if (!ok) {\n p.log.error(`Upgrade aborted: ${label} failed.`);\n process.exit(1);\n }\n };\n\n if (hasPackageJson) {\n const usePnpm = !!pnpmBin && hasPnpmLock;\n if (usePnpm && pnpmBin) {\n const installOk = runCommand(pnpmBin, [\"install\"], {\n label: \"Refreshing dependencies (pnpm install)\",\n });\n requireSuccess(installOk, \"pnpm install\");\n runCommand(pnpmBin, [\"up\", \"iii-sdk@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\n optional: true,\n });\n } else if (npmBin) {\n const installOk = runCommand(npmBin, [\"install\"], {\n label: \"Refreshing dependencies (npm install)\",\n });\n requireSuccess(installOk, \"npm install\");\n runCommand(npmBin, [\"install\", \"iii-sdk@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\n optional: true,\n });\n } else {\n p.log.warn(\"No package manager found (pnpm/npm). Skipping JS dependency upgrade.\");\n }\n } else {\n p.log.warn(\"No package.json in current directory. Skipping JS dependency upgrade.\");\n }\n\n if (cargoBin) {\n const upgradeEngine = await p.confirm({\n message: \"Upgrade iii-engine via cargo install --force?\",\n initialValue: true,\n });\n if (p.isCancel(upgradeEngine)) {\n p.cancel(\"Cancelled.\");\n return process.exit(0);\n }\n if (upgradeEngine === true) {\n const cargoOk = runCommand(cargoBin, [\"install\", \"iii-engine\", \"--force\"], {\n label: \"Upgrading iii-engine (cargo)\",\n });\n requireSuccess(cargoOk, \"cargo install iii-engine --force\");\n } else {\n p.log.info(\"Skipped cargo-based iii-engine upgrade.\");\n }\n } else {\n p.log.warn(\"Cargo not found. Skipping iii-engine binary upgrade.\");\n }\n\n if (dockerBin) {\n runCommand(dockerBin, [\"pull\", \"iiidev/iii:latest\"], {\n label: \"Pulling latest iii Docker image\",\n optional: true,\n });\n } else {\n p.log.info(\"Docker not found. Skipping Docker image refresh.\");\n }\n\n p.note(\n [\n \"Upgrade flow completed.\",\n \"\",\n \"Recommended next steps:\",\n \" 1) agentmemory status\",\n \" 2) npm/pnpm test\",\n \" 3) restart agentmemory process\",\n ].join(\"\\n\"),\n \"agentmemory upgrade\",\n );\n}\n\nasync function runMcp(): Promise<void> {\n await import(\"./mcp/standalone.js\");\n}\n\nconst commands: Record<string, () => Promise<void>> = {\n status: runStatus,\n demo: runDemo,\n upgrade: runUpgrade,\n mcp: runMcp,\n};\n\nconst handler = commands[args[0] ?? \"\"] ?? main;\nhandler().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["PATH_DELIMITER"],"sources":["../src/state/schema.ts","../src/cli.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nexport const KV = {\n sessions: \"mem:sessions\",\n observations: (sessionId: string) => `mem:obs:${sessionId}`,\n memories: \"mem:memories\",\n summaries: \"mem:summaries\",\n config: \"mem:config\",\n metrics: \"mem:metrics\",\n health: \"mem:health\",\n embeddings: (obsId: string) => `mem:emb:${obsId}`,\n bm25Index: \"mem:index:bm25\",\n relations: \"mem:relations\",\n profiles: \"mem:profiles\",\n claudeBridge: \"mem:claude-bridge\",\n graphNodes: \"mem:graph:nodes\",\n graphEdges: \"mem:graph:edges\",\n semantic: \"mem:semantic\",\n procedural: \"mem:procedural\",\n teamShared: (teamId: string) => `mem:team:${teamId}:shared`,\n teamUsers: (teamId: string, userId: string) =>\n `mem:team:${teamId}:users:${userId}`,\n teamProfile: (teamId: string) => `mem:team:${teamId}:profile`,\n audit: \"mem:audit\",\n actions: \"mem:actions\",\n actionEdges: \"mem:action-edges\",\n leases: \"mem:leases\",\n routines: \"mem:routines\",\n routineRuns: \"mem:routine-runs\",\n signals: \"mem:signals\",\n checkpoints: \"mem:checkpoints\",\n mesh: \"mem:mesh\",\n sketches: \"mem:sketches\",\n facets: \"mem:facets\",\n sentinels: \"mem:sentinels\",\n crystals: \"mem:crystals\",\n lessons: \"mem:lessons\",\n insights: \"mem:insights\",\n graphEdgeHistory: \"mem:graph:edge-history\",\n enrichedChunks: (sessionId: string) => `mem:enriched:${sessionId}`,\n latentEmbeddings: (obsId: string) => `mem:latent:${obsId}`,\n retentionScores: \"mem:retention\",\n accessLog: \"mem:access\",\n} as const;\n\nexport const STREAM = {\n name: \"mem-live\",\n group: (sessionId: string) => sessionId,\n viewerGroup: \"viewer\",\n} as const;\n\nexport function generateId(prefix: string): string {\n const ts = Date.now().toString(36);\n const rand = crypto.randomUUID().replace(/-/g, \"\").slice(0, 12);\n return `${prefix}_${ts}_${rand}`;\n}\n\nexport function fingerprintId(prefix: string, content: string): string {\n const hash = createHash(\"sha256\").update(content).digest(\"hex\");\n return `${prefix}_${hash.slice(0, 16)}`;\n}\n\nexport function jaccardSimilarity(a: string, b: string): number {\n const setA = new Set(a.split(/\\s+/).filter((t) => t.length > 2));\n const setB = new Set(b.split(/\\s+/).filter((t) => t.length > 2));\n if (setA.size === 0 && setB.size === 0) return 1;\n if (setA.size === 0 || setB.size === 0) return 0;\n let intersection = 0;\n for (const word of setA) {\n if (setB.has(word)) intersection++;\n }\n return intersection / (setA.size + setB.size - intersection);\n}\n","#!/usr/bin/env node\n\nimport {\n spawn,\n execFileSync,\n spawnSync,\n type ChildProcess,\n} from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname, delimiter as PATH_DELIMITER } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { platform } from \"node:os\";\nimport * as p from \"@clack/prompts\";\nimport { generateId } from \"./state/schema.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\nconst IS_WINDOWS = platform() === \"win32\";\nconst IS_VERBOSE = args.includes(\"--verbose\") || args.includes(\"-v\");\n\nfunction vlog(msg: string): void {\n if (IS_VERBOSE) p.log.info(`[verbose] ${msg}`);\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [command] [options]\n\nCommands:\n (default) Start agentmemory worker\n status Show connection status, memory count, and health\n demo Seed sample sessions and show recall in action\n upgrade Upgrade local deps + iii runtime (best effort)\n mcp Start standalone MCP server (no engine required)\n import-jsonl [p] Import Claude Code JSONL transcripts (default: ~/.claude/projects)\n\nOptions:\n --help, -h Show this help\n --verbose, -v Show engine stderr and diagnostic info on startup\n --tools all|core Tool visibility (default: core = 7 tools)\n --no-engine Skip auto-starting iii-engine\n --port <N> Override REST port (default: 3111)\n\nQuick start:\n npx @agentmemory/agentmemory # start with local iii-engine or Docker\n npx @agentmemory/agentmemory status # check health\n npx @agentmemory/agentmemory demo # try it in 30 seconds (needs server running)\n npx @agentmemory/agentmemory upgrade # upgrade agentmemory + iii runtime\n npx @agentmemory/agentmemory mcp # standalone MCP server (no engine)\n npx @agentmemory/mcp # same as above (shim package)\n`);\n process.exit(0);\n}\n\nconst toolsIdx = args.indexOf(\"--tools\");\nif (toolsIdx !== -1 && args[toolsIdx + 1]) {\n process.env[\"AGENTMEMORY_TOOLS\"] = args[toolsIdx + 1];\n}\n\nconst portIdx = args.indexOf(\"--port\");\nif (portIdx !== -1 && args[portIdx + 1]) {\n process.env[\"III_REST_PORT\"] = args[portIdx + 1];\n}\n\nconst skipEngine = args.includes(\"--no-engine\");\n\nfunction getRestPort(): number {\n return parseInt(process.env[\"III_REST_PORT\"] || \"3111\", 10) || 3111;\n}\n\nasync function isEngineRunning(): Promise<boolean> {\n try {\n await fetch(`http://localhost:${getRestPort()}/`, {\n signal: AbortSignal.timeout(2000),\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction findIiiConfig(): string {\n const candidates = [\n join(__dirname, \"iii-config.yaml\"),\n join(__dirname, \"..\", \"iii-config.yaml\"),\n join(process.cwd(), \"iii-config.yaml\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return \"\";\n}\n\nfunction whichBinary(name: string): string | null {\n const cmd = IS_WINDOWS ? \"where\" : \"which\";\n try {\n const out = execFileSync(cmd, [name], { encoding: \"utf-8\" });\n const first = out\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n return first ?? null;\n } catch {\n return null;\n }\n}\n\nfunction fallbackIiiPaths(): string[] {\n if (IS_WINDOWS) {\n const userProfile = process.env[\"USERPROFILE\"];\n if (!userProfile) return [];\n return [\n join(userProfile, \".local\", \"bin\", \"iii.exe\"),\n join(userProfile, \"bin\", \"iii.exe\"),\n ];\n }\n const home = process.env[\"HOME\"];\n if (!home) return [\"/usr/local/bin/iii\"];\n return [join(home, \".local\", \"bin\", \"iii\"), \"/usr/local/bin/iii\"];\n}\n\ntype StartupFailure = {\n kind: \"no-engine\" | \"no-docker-compose\" | \"engine-crashed\" | \"docker-crashed\";\n stderr?: string;\n binary?: string;\n};\n\nlet startupFailure: StartupFailure | null = null;\n\n// Spawn a background engine and collect any startup stderr for a short\n// window. The process is unref'd so the CLI parent can exit cleanly; we\n// only care about stderr that shows up BEFORE the health check succeeds,\n// which is what surfaces early crash/config-parse errors on all platforms.\nfunction spawnEngineBackground(\n bin: string,\n spawnArgs: string[],\n label: string,\n): ChildProcess {\n vlog(`spawn: ${bin} ${spawnArgs.join(\" \")}`);\n const child = spawn(bin, spawnArgs, {\n detached: true,\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n windowsHide: true,\n });\n const stderrChunks: Buffer[] = [];\n let stderrBytes = 0;\n const MAX_STDERR_CAPTURE = 16 * 1024;\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n if (stderrBytes >= MAX_STDERR_CAPTURE) return;\n const slice = chunk.subarray(0, MAX_STDERR_CAPTURE - stderrBytes);\n stderrChunks.push(slice);\n stderrBytes += slice.length;\n });\n child.on(\"exit\", (code, signal) => {\n const abnormal =\n (code !== null && code !== 0) || (code === null && signal !== null);\n if (abnormal) {\n const stderr = Buffer.concat(stderrChunks).toString(\"utf-8\");\n startupFailure = {\n kind: label.includes(\"Docker\") ? \"docker-crashed\" : \"engine-crashed\",\n stderr:\n stderr.trim() ||\n (signal\n ? `process killed by signal ${signal}`\n : `process exited with code ${code}`),\n binary: bin,\n };\n vlog(`engine exited early: code=${code} signal=${signal}`);\n if (IS_VERBOSE && stderr.trim()) {\n p.log.error(`engine stderr:\\n${stderr}`);\n }\n }\n });\n child.unref();\n return child;\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n let iiiBin = whichBinary(\"iii\");\n vlog(`iii binary: ${iiiBin ?? \"(not on PATH)\"}, config: ${configPath || \"(not found)\"}`);\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n const dockerBin = whichBinary(\"docker\");\n vlog(`docker binary: ${dockerBin ?? \"(not on PATH)\"}`);\n const dockerComposeCandidates = [\n join(__dirname, \"..\", \"docker-compose.yml\"),\n join(__dirname, \"docker-compose.yml\"),\n join(process.cwd(), \"docker-compose.yml\"),\n ];\n const composeFile = dockerComposeCandidates.find((c) => existsSync(c));\n vlog(`docker-compose.yml: ${composeFile ?? \"(not found)\"}`);\n\n if (dockerBin && composeFile) {\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\n spawnEngineBackground(\n dockerBin,\n [\"compose\", \"-f\", composeFile, \"up\", \"-d\"],\n \"iii-engine via Docker\",\n );\n s.stop(\"Docker compose started\");\n return true;\n }\n\n for (const iiiPath of fallbackIiiPaths()) {\n if (existsSync(iiiPath)) {\n p.log.info(`Found iii at: ${iiiPath}`);\n process.env[\"PATH\"] = `${dirname(iiiPath)}${PATH_DELIMITER}${process.env[\"PATH\"] ?? \"\"}`;\n iiiBin = iiiPath;\n break;\n }\n }\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n spawnEngineBackground(iiiBin, [\"--config\", configPath], \"iii-engine\");\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n if (!iiiBin && (!dockerBin || !composeFile)) {\n startupFailure = { kind: \"no-engine\" };\n } else if (!composeFile && dockerBin) {\n startupFailure = { kind: \"no-docker-compose\" };\n }\n return false;\n}\n\nasync function waitForEngine(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (await isEngineRunning()) return true;\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\nfunction installInstructions(): string[] {\n if (IS_WINDOWS) {\n return [\n \"agentmemory requires the `iii-engine` runtime. Pick one:\",\n \"\",\n \" A) Download the prebuilt Windows binary:\",\n \" 1. Open https://github.com/iii-hq/iii/releases/latest\",\n \" 2. Download iii-x86_64-pc-windows-msvc.zip\",\n \" (or iii-aarch64-pc-windows-msvc.zip on ARM)\",\n \" 3. Extract iii.exe and either add its folder to PATH\",\n \" or move it to %USERPROFILE%\\\\.local\\\\bin\\\\iii.exe\",\n \" 4. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \" B) Docker Desktop:\",\n \" 1. Install Docker Desktop for Windows\",\n \" 2. Start Docker Desktop (engine must be running)\",\n \" 3. Re-run: npx @agentmemory/agentmemory\",\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n ];\n }\n return [\n \"agentmemory requires the `iii-engine` runtime. Pick one:\",\n \"\",\n \" A) curl -fsSL https://install.iii.dev/iii/main/install.sh | sh\",\n \" (installs the prebuilt iii binary into ~/.local/bin/iii)\",\n \"\",\n \" B) Docker: install Docker Desktop or docker-ce, then re-run\",\n \"\",\n \"Or skip the engine entirely for standalone MCP:\",\n \" npx @agentmemory/agentmemory mcp\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n ];\n}\n\nfunction portInUseDiagnostic(port: number): string {\n return IS_WINDOWS\n ? ` netstat -ano | findstr :${port}`\n : ` lsof -i :${port} # or: ss -tlnp | grep :${port}`;\n}\n\nasync function main() {\n p.intro(\"agentmemory\");\n\n if (skipEngine) {\n p.log.info(\"Skipping engine check (--no-engine)\");\n await import(\"./index.js\");\n return;\n }\n\n if (await isEngineRunning()) {\n p.log.success(\"iii-engine is running\");\n await import(\"./index.js\");\n return;\n }\n\n const started = await startEngine();\n if (!started) {\n p.log.error(\"Could not start iii-engine.\");\n const lines = installInstructions();\n if (startupFailure?.kind === \"no-docker-compose\") {\n lines.unshift(\n \"Docker is installed but docker-compose.yml is missing from this\",\n \"install. Re-install with: npm install -g @agentmemory/agentmemory\",\n \"\",\n );\n }\n p.note(lines.join(\"\\n\"), \"Setup required\");\n process.exit(1);\n }\n\n const s = p.spinner();\n s.start(\"Waiting for iii-engine to be ready...\");\n\n const ready = await waitForEngine(15000);\n if (!ready) {\n const port = getRestPort();\n s.stop(\"iii-engine did not become ready within 15s\");\n\n if (startupFailure?.kind === \"engine-crashed\" || startupFailure?.kind === \"docker-crashed\") {\n p.log.error(\"The iii-engine process crashed on startup.\");\n if (startupFailure.binary) {\n p.log.info(`Binary: ${startupFailure.binary}`);\n }\n if (startupFailure.stderr) {\n p.note(startupFailure.stderr, \"engine stderr\");\n } else {\n p.log.info(\"No stderr was captured. Re-run with --verbose for more detail.\");\n }\n p.note(\n [\n \"Common causes:\",\n \" - iii-engine version mismatch — reinstall the latest binary\",\n \" (sh script on macOS/Linux, GitHub release zip on Windows)\",\n \" - Docker Desktop not running (if you're using the Docker path)\",\n \" - Port already in use (see below)\",\n \"\",\n \"See https://iii.dev/docs for current install instructions.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n } else {\n p.log.error(\"The engine process started but the REST API never responded.\");\n p.note(\n [\n `Check whether port ${port} is already bound by another process:`,\n portInUseDiagnostic(port),\n \"\",\n \"If it is, free the port or override: agentmemory --port <N>\",\n \"\",\n \"If it isn't, a firewall may be blocking 127.0.0.1:\" + port + \".\",\n \"Re-run with --verbose to see engine stderr.\",\n ].join(\"\\n\"),\n \"Troubleshooting\",\n );\n }\n process.exit(1);\n }\n\n s.stop(\"iii-engine is ready\");\n await import(\"./index.js\");\n}\n\nasync function runStatus() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory status\");\n\n const up = await isEngineRunning();\n if (!up) {\n p.log.error(`Not running — no response on port ${port}`);\n p.log.info(\"Start with: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n try {\n const [healthRes, sessionsRes, graphRes, memoriesRes] = await Promise.all([\n fetch(`${base}/agentmemory/health`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/sessions`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/graph/stats`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n fetch(`${base}/agentmemory/export`, { signal: AbortSignal.timeout(5000) }).then((r) => r.json()).catch(() => null),\n ]);\n\n const h = healthRes?.health;\n const status = healthRes?.status || \"unknown\";\n const version = healthRes?.version || \"?\";\n const sessions = Array.isArray(sessionsRes?.sessions) ? sessionsRes.sessions.length : 0;\n const nodes = graphRes?.nodes || 0;\n const edges = graphRes?.edges || 0;\n const cb = healthRes?.circuitBreaker?.state || \"closed\";\n const heapMB = h?.memory ? Math.round(h.memory.heapUsed / 1048576) : 0;\n const uptime = h?.uptimeSeconds ? Math.round(h.uptimeSeconds) : 0;\n\n const obsCount = memoriesRes?.observations?.length || 0;\n const memCount = memoriesRes?.memories?.length || 0;\n const estFullTokens = obsCount * 80;\n const estInjectedTokens = Math.min(obsCount, 50) * 38;\n const tokensSaved = estFullTokens - estInjectedTokens;\n const pctSaved = estFullTokens > 0 ? Math.round((tokensSaved / estFullTokens) * 100) : 0;\n\n p.log.success(`Connected — v${version} on port ${port}`);\n\n const lines = [\n `Health: ${status === \"healthy\" ? \"✓ healthy\" : status}`,\n `Sessions: ${sessions}`,\n `Observations: ${obsCount}`,\n `Memories: ${memCount}`,\n `Graph: ${nodes} nodes, ${edges} edges`,\n `Circuit: ${cb}`,\n `Heap: ${heapMB} MB`,\n `Uptime: ${uptime}s`,\n `Viewer: http://localhost:${port + 2}`,\n ];\n\n if (obsCount > 0) {\n lines.push(\"\");\n lines.push(`Token savings: ~${tokensSaved.toLocaleString()} tokens saved (${pctSaved}% reduction)`);\n lines.push(` Full context: ~${estFullTokens.toLocaleString()} tokens`);\n lines.push(` Injected: ~${estInjectedTokens.toLocaleString()} tokens`);\n }\n\n p.note(lines.join(\"\\n\"), \"agentmemory\");\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n}\n\ntype DemoObservation = {\n toolName: string;\n toolInput: Record<string, string>;\n toolOutput: string;\n};\n\ntype DemoSession = {\n id: string;\n title: string;\n observations: DemoObservation[];\n};\n\ntype SearchResult = { query: string; hits: number; topTitle: string };\n\nfunction buildDemoSessions(): DemoSession[] {\n return [\n {\n id: generateId(\"demo\"),\n title: \"Session 1: JWT auth setup\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/auth.ts\" },\n toolOutput:\n \"Created JWT middleware using jose library. Tokens expire after 30 days. Chose jose over jsonwebtoken for Edge compatibility.\",\n },\n {\n toolName: \"Write\",\n toolInput: { file_path: \"test/auth.test.ts\" },\n toolOutput:\n \"Added token validation tests covering expired, malformed, and valid cases.\",\n },\n {\n toolName: \"Bash\",\n toolInput: { command: \"npm test\" },\n toolOutput: \"All 12 auth tests passing.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 2: Database migration debugging\",\n observations: [\n {\n toolName: \"Read\",\n toolInput: { file_path: \"prisma/schema.prisma\" },\n toolOutput:\n \"Found N+1 query issue in user relations. Need to add include on posts query.\",\n },\n {\n toolName: \"Edit\",\n toolInput: { file_path: \"src/api/users.ts\" },\n toolOutput:\n \"Fixed N+1 by adding Prisma include. Query time dropped from 450ms to 28ms.\",\n },\n ],\n },\n {\n id: generateId(\"demo\"),\n title: \"Session 3: Rate limiting\",\n observations: [\n {\n toolName: \"Write\",\n toolInput: { file_path: \"src/middleware/ratelimit.ts\" },\n toolOutput:\n \"Added rate limiting middleware with 100 req/min default. Uses in-memory store for dev, Redis for prod.\",\n },\n ],\n },\n ];\n}\n\nasync function postJson<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return null;\n return (await res.json().catch(() => null)) as T | null;\n } catch {\n return null;\n }\n}\n\nasync function postJsonStrict<T = unknown>(\n url: string,\n body: unknown,\n timeoutMs = 5000,\n): Promise<T | null> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n const suffix = errBody ? ` — ${errBody.slice(0, 200)}` : \"\";\n throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${suffix}`);\n }\n return (await res.json().catch(() => null)) as T | null;\n}\n\nasync function seedDemoSession(\n base: string,\n project: string,\n session: DemoSession,\n): Promise<number> {\n await postJsonStrict(`${base}/agentmemory/session/start`, {\n sessionId: session.id,\n project,\n cwd: project,\n });\n\n let stored = 0;\n for (const obs of session.observations) {\n const url = `${base}/agentmemory/observe`;\n const payload = {\n hookType: \"post_tool_use\",\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n data: {\n tool_name: obs.toolName,\n tool_input: obs.toolInput,\n tool_output: obs.toolOutput,\n },\n };\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(5000),\n });\n if (res.ok) {\n stored++;\n } else {\n const body = await res.text().catch(() => \"\");\n p.log.warn(\n `observe failed for ${obs.toolName}: ${res.status} ${res.statusText}${body ? ` — ${body.slice(0, 160)}` : \"\"}`,\n );\n }\n } catch (err) {\n p.log.warn(\n `observe request failed for ${obs.toolName}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n await postJsonStrict(`${base}/agentmemory/session/end`, { sessionId: session.id });\n return stored;\n}\n\nasync function runDemoSearch(base: string, query: string): Promise<SearchResult> {\n const data = await postJson<{ results?: Array<{ title?: string }> }>(\n `${base}/agentmemory/smart-search`,\n { query, limit: 5 },\n 10000,\n );\n const items = data?.results ?? [];\n return {\n query,\n hits: items.length,\n topTitle: items[0]?.title ?? \"(no results)\",\n };\n}\n\nasync function runDemo() {\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n p.intro(\"agentmemory demo\");\n\n if (!(await isEngineRunning())) {\n p.log.error(`Not running — no response on port ${port}`);\n p.log.info(\"Start the server first: npx @agentmemory/agentmemory\");\n process.exit(1);\n }\n\n const demoProject = \"/tmp/agentmemory-demo\";\n const sessions = buildDemoSessions();\n\n const sSeed = p.spinner();\n sSeed.start(\"Seeding 3 demo sessions with realistic observations...\");\n\n let totalObs = 0;\n for (const session of sessions) {\n totalObs += await seedDemoSession(base, demoProject, session);\n }\n\n sSeed.stop(`Seeded ${totalObs} observations across ${sessions.length} sessions`);\n\n const queries = [\n \"jwt auth middleware\",\n \"database performance optimization\",\n \"rate limiting\",\n ];\n\n const sQuery = p.spinner();\n sQuery.start(`Running ${queries.length} smart-search queries...`);\n\n const results: SearchResult[] = [];\n for (const query of queries) {\n results.push(await runDemoSearch(base, query));\n }\n\n sQuery.stop(\"Search complete\");\n\n const lines = [\n `Project: ${demoProject}`,\n `Sessions: ${sessions.length} seeded (${totalObs} observations)`,\n \"\",\n \"Search results:\",\n ...results.flatMap((r) => [\n ` \"${r.query}\"`,\n ` → ${r.hits} hit(s), top: ${r.topTitle.slice(0, 60)}`,\n ]),\n \"\",\n `Notice: searching \"database performance optimization\"`,\n `found the N+1 query fix — keyword matching can't do that.`,\n \"\",\n `Viewer: http://localhost:${port + 2}`,\n `Clean up with: curl -X DELETE \"${base}/agentmemory/sessions?project=${demoProject}\"`,\n ];\n\n p.note(lines.join(\"\\n\"), \"demo complete\");\n p.log.success(\"agentmemory is working. Point your agent at it and get back to coding.\");\n}\n\nfunction runCommand(\n command: string,\n commandArgs: string[],\n options: { cwd?: string; label: string; optional?: boolean } = { label: \"command\" },\n): boolean {\n const spinner = p.spinner();\n spinner.start(options.label);\n const result = spawnSync(command, commandArgs, {\n cwd: options.cwd || process.cwd(),\n stdio: \"pipe\",\n encoding: \"utf-8\",\n });\n\n if (result.status === 0) {\n spinner.stop(`${options.label} ✓`);\n return true;\n }\n\n const stderr = (result.stderr || \"\").toString().trim();\n const stdout = (result.stdout || \"\").toString().trim();\n const msg = stderr || stdout || \"unknown error\";\n\n if (options.optional) {\n spinner.stop(`${options.label} (skipped)`);\n p.log.warn(msg.slice(0, 300));\n return false;\n }\n\n spinner.stop(`${options.label} ✗`);\n p.log.error(msg.slice(0, 300));\n return false;\n}\n\nasync function runUpgrade() {\n p.intro(\"agentmemory upgrade\");\n\n const cwd = process.cwd();\n const hasPackageJson = existsSync(join(cwd, \"package.json\"));\n const hasPnpmLock = existsSync(join(cwd, \"pnpm-lock.yaml\"));\n\n const pnpmBin = whichBinary(\"pnpm\");\n const npmBin = whichBinary(\"npm\");\n const cargoBin = whichBinary(\"cargo\");\n const dockerBin = whichBinary(\"docker\");\n\n p.log.info(`Working directory: ${cwd}`);\n const requireSuccess = (ok: boolean, label: string): void => {\n if (!ok) {\n p.log.error(`Upgrade aborted: ${label} failed.`);\n process.exit(1);\n }\n };\n\n if (hasPackageJson) {\n const usePnpm = !!pnpmBin && hasPnpmLock;\n if (usePnpm && pnpmBin) {\n const installOk = runCommand(pnpmBin, [\"install\"], {\n label: \"Refreshing dependencies (pnpm install)\",\n });\n requireSuccess(installOk, \"pnpm install\");\n runCommand(pnpmBin, [\"up\", \"iii-sdk@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\n optional: true,\n });\n } else if (npmBin) {\n const installOk = runCommand(npmBin, [\"install\"], {\n label: \"Refreshing dependencies (npm install)\",\n });\n requireSuccess(installOk, \"npm install\");\n runCommand(npmBin, [\"install\", \"iii-sdk@latest\"], {\n label: \"Upgrading iii-sdk to latest\",\n optional: true,\n });\n } else {\n p.log.warn(\"No package manager found (pnpm/npm). Skipping JS dependency upgrade.\");\n }\n } else {\n p.log.warn(\"No package.json in current directory. Skipping JS dependency upgrade.\");\n }\n\n if (cargoBin) {\n const upgradeEngine = await p.confirm({\n message: \"Upgrade iii-engine via cargo install --force?\",\n initialValue: true,\n });\n if (p.isCancel(upgradeEngine)) {\n p.cancel(\"Cancelled.\");\n return process.exit(0);\n }\n if (upgradeEngine === true) {\n const cargoOk = runCommand(cargoBin, [\"install\", \"iii-engine\", \"--force\"], {\n label: \"Upgrading iii-engine (cargo)\",\n });\n requireSuccess(cargoOk, \"cargo install iii-engine --force\");\n } else {\n p.log.info(\"Skipped cargo-based iii-engine upgrade.\");\n }\n } else {\n p.log.warn(\"Cargo not found. Skipping iii-engine binary upgrade.\");\n }\n\n if (dockerBin) {\n runCommand(dockerBin, [\"pull\", \"iiidev/iii:latest\"], {\n label: \"Pulling latest iii Docker image\",\n optional: true,\n });\n } else {\n p.log.info(\"Docker not found. Skipping Docker image refresh.\");\n }\n\n p.note(\n [\n \"Upgrade flow completed.\",\n \"\",\n \"Recommended next steps:\",\n \" 1) agentmemory status\",\n \" 2) npm/pnpm test\",\n \" 3) restart agentmemory process\",\n ].join(\"\\n\"),\n \"agentmemory upgrade\",\n );\n}\n\nasync function runMcp(): Promise<void> {\n await import(\"./mcp/standalone.js\");\n}\n\nasync function runImportJsonl(): Promise<void> {\n const nonFlagArgs = args.slice(1).filter((a) => !a.startsWith(\"-\"));\n const pathArg = nonFlagArgs[0];\n const port = getRestPort();\n const base = `http://localhost:${port}`;\n\n try {\n await fetch(`${base}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n } catch {\n p.log.error(`agentmemory is not running on port ${port}. Start it first.`);\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (pathArg) body[\"path\"] = pathArg;\n\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n const secret = process.env[\"AGENTMEMORY_SECRET\"];\n if (secret) headers[\"authorization\"] = `Bearer ${secret}`;\n\n p.log.info(`Importing JSONL from ${pathArg || \"~/.claude/projects\"}…`);\n const spinner = p.spinner();\n spinner.start(\"scanning files\");\n\n try {\n const res = await fetch(`${base}/agentmemory/replay/import-jsonl`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(120_000),\n });\n const json = (await res.json()) as {\n success?: boolean;\n error?: string;\n imported?: number;\n sessionIds?: string[];\n observations?: number;\n };\n if (!res.ok || json.success === false) {\n spinner.stop(\"failed\");\n p.log.error(json.error || `HTTP ${res.status}`);\n process.exit(1);\n }\n spinner.stop(\n `imported ${json.imported} file(s), ${json.observations} observation(s) across ${json.sessionIds?.length || 0} session(s)`,\n );\n if (json.sessionIds && json.sessionIds.length > 0) {\n p.log.info(`View at http://localhost:${port + 2} → Replay tab`);\n }\n } catch (err) {\n spinner.stop(\"failed\");\n if (err instanceof Error && err.name === \"TimeoutError\") {\n p.log.error(\"import timed out after 2 minutes\");\n } else {\n p.log.error(err instanceof Error ? err.message : String(err));\n }\n process.exit(1);\n }\n}\n\nconst commands: Record<string, () => Promise<void>> = {\n status: runStatus,\n demo: runDemo,\n upgrade: runUpgrade,\n mcp: runMcp,\n \"import-jsonl\": runImportJsonl,\n};\n\nconst handler = commands[args[0] ?? \"\"] ?? main;\nhandler().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
|