@agentmemory/agentmemory 0.7.0 → 0.7.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/AGENTS.md CHANGED
@@ -110,4 +110,4 @@ Hook scripts in `src/hooks/` are standalone Node.js scripts (no iii-sdk import).
110
110
  - 6 MCP resources, 3 MCP prompts
111
111
  - 12 hooks, 4 skills
112
112
  - 50+ iii functions
113
- - 573 tests
113
+ - 581 tests
package/README.md CHANGED
@@ -26,14 +26,12 @@
26
26
 
27
27
  ---
28
28
 
29
- Every AI coding agent has the same blind spot. Session ends, memory vanishes. You re-explain architecture. You re-discover bugs. You re-teach preferences. Built-in memory files like CLAUDE.md and .cursorrules are 200-line sticky notes that overflow and go stale. agentmemory replaces that with a searchable, versioned, cross-agent database — 41 MCP tools, triple-stream retrieval (BM25 + vector + knowledge graph), 4-tier memory consolidation, provenance-tracked citations, and cascading staleness so retired facts never pollute your context again. One instance serves Claude Code, Cursor, Codex, Windsurf, and any MCP client simultaneously. 573 tests. Zero external DB dependencies.
29
+ Every AI coding agent has the same blind spot. Session ends, memory vanishes. You re-explain architecture. You re-discover bugs. You re-teach preferences. Built-in memory files like CLAUDE.md and .cursorrules are 200-line sticky notes that overflow and go stale. agentmemory replaces that with a searchable, versioned, cross-agent database — 41 MCP tools, triple-stream retrieval (BM25 + vector + knowledge graph), 4-tier memory consolidation, provenance-tracked citations, and cascading staleness so retired facts never pollute your context again. One instance serves Claude Code, Cursor, Codex, Windsurf, and any MCP client simultaneously. 581 tests. Zero external DB dependencies.
30
30
 
31
31
  The result is measurable. On 240 real observations across 30 sessions, agentmemory hits 64% Recall@10 and perfect MRR while using 92% fewer tokens than dumping everything into context. When an agent searches "database performance optimization," it finds the N+1 fix you made three weeks ago — something keyword grep literally cannot do. Memories version automatically, supersede each other, propagate staleness to related graph nodes, and sync across agent instances via P2P mesh. Your agents stop repeating mistakes. Your context stays clean. Your sessions start fast.
32
32
 
33
33
  ```bash
34
- git clone https://github.com/rohitg00/agentmemory.git && cd agentmemory
35
- docker compose up -d && npm install && npm run build && npm start
36
- curl http://localhost:3111/agentmemory/health
34
+ npx @agentmemory/agentmemory # installs iii-engine if missing, starts everything
37
35
  ```
38
36
 
39
37
  ---
@@ -162,8 +160,8 @@ GET /agentmemory/profile # Get project intelligence
162
160
  |---|---|
163
161
  | Claude Code user | Plugin install (hooks + MCP + skills) |
164
162
  | Building a custom agent with Claude SDK | AgentSDKProvider (zero config) |
165
- | Using Cursor, Windsurf, or any MCP client | MCP server (38 tools + 6 resources + 3 prompts) |
166
- | Building your own agent framework | REST API (93 endpoints) |
163
+ | Using Cursor, Windsurf, or any MCP client | MCP server (41 tools + 6 resources + 3 prompts) |
164
+ | Building your own agent framework | REST API (100 endpoints) |
167
165
  | Sharing memory across multiple agents | All agents point to the same iii-engine instance |
168
166
 
169
167
  ## Quick Start
@@ -177,17 +175,22 @@ GET /agentmemory/profile # Get project intelligence
177
175
 
178
176
  All 12 hooks, 4 skills, and MCP server are registered automatically.
179
177
 
180
- ### 2. Start the Worker
178
+ ### 2. Start agentmemory
181
179
 
182
180
  ```bash
183
- git clone https://github.com/rohitg00/agentmemory.git
184
- cd agentmemory
181
+ npx @agentmemory/agentmemory
182
+ ```
183
+
184
+ This auto-installs iii-engine if missing, starts it, and runs the worker. One command.
185
+
186
+ Or from source:
185
187
 
186
- docker compose up -d # Start iii-engine
188
+ ```bash
189
+ git clone https://github.com/rohitg00/agentmemory.git && cd agentmemory
187
190
  npm install && npm run build && npm start
188
191
  ```
189
192
 
190
- ### 3. Verify
193
+ ### 4. Verify
191
194
 
192
195
  ```bash
193
196
  curl http://localhost:3111/agentmemory/health
@@ -200,7 +203,7 @@ open http://localhost:3113
200
203
  {
201
204
  "status": "healthy",
202
205
  "service": "agentmemory",
203
- "version": "0.6.1",
206
+ "version": "0.7.1",
204
207
  "health": {
205
208
  "memory": { "heapUsed": 42000000, "heapTotal": 67000000 },
206
209
  "cpu": { "percent": 2.1 },
@@ -604,9 +607,18 @@ ANTHROPIC_API_KEY=sk-ant-...
604
607
  # GRAPH_EXTRACTION_BATCH_SIZE=10
605
608
 
606
609
  # Consolidation Pipeline (v0.5.0)
607
- # CONSOLIDATION_ENABLED=false
610
+ # CONSOLIDATION_ENABLED=true
608
611
  # CONSOLIDATION_DECAY_DAYS=30
609
612
 
613
+ # Lesson Decay (v0.7.0)
614
+ # LESSON_DECAY_ENABLED=true
615
+
616
+ # Obsidian Export (v0.7.0)
617
+ # OBSIDIAN_AUTO_EXPORT=false
618
+
619
+ # MCP Tool Visibility (v0.7.0) — "core" (7 tools) or "all" (41 tools)
620
+ # AGENTMEMORY_TOOLS=core
621
+
610
622
  # Team Memory (v0.5.0)
611
623
  # TEAM_ID=
612
624
  # USER_ID=
@@ -667,6 +679,11 @@ ANTHROPIC_API_KEY=sk-ant-...
667
679
  | `GET` | `/agentmemory/snapshots` | List git snapshots |
668
680
  | `POST` | `/agentmemory/snapshot/create` | Create git-versioned snapshot |
669
681
  | `POST` | `/agentmemory/snapshot/restore` | Restore from snapshot commit |
682
+ | `POST` | `/agentmemory/lessons` | Save a lesson (returns 201 if created, 200 if strengthened) |
683
+ | `GET` | `/agentmemory/lessons` | List lessons (`?project=X&minConfidence=0.5`) |
684
+ | `POST` | `/agentmemory/lessons/search` | Search lessons by query |
685
+ | `POST` | `/agentmemory/lessons/strengthen` | Reinforce a lesson's confidence |
686
+ | `POST` | `/agentmemory/obsidian/export` | Export vault as Obsidian Markdown |
670
687
  | `GET` | `/agentmemory/mcp/tools` | List MCP tools |
671
688
  | `POST` | `/agentmemory/mcp/call` | Execute MCP tool |
672
689
  | `GET` | `/agentmemory/mcp/resources` | List MCP resources |
@@ -707,9 +724,9 @@ agentmemory is built on iii-engine's three primitives:
707
724
  | Prometheus / Grafana | iii OTEL + built-in health monitor |
708
725
  | Redis (circuit breaker) | In-process circuit breaker + fallback chain |
709
726
 
710
- **105+ source files. ~16,000 LOC. 573 tests. Zero external DB dependencies.**
727
+ **113 source files. ~20,000 LOC. 581 tests. Zero external DB dependencies.**
711
728
 
712
- ### Functions (52)
729
+ ### Functions (57)
713
730
 
714
731
  | Function | Purpose |
715
732
  |----------|---------|
@@ -734,7 +751,7 @@ agentmemory is built on iii-engine's three primitives:
734
751
  | `mem::profile` | Aggregate project profile |
735
752
  | `mem::auto-forget` | TTL expiry + contradiction detection |
736
753
  | `mem::enrich` | Unified enrichment (file context + observations + bug memories) |
737
- | `mem::export` / `mem::import` | Full JSON round-trip (v0.3.0 + v0.4.0 + v0.5.0 formats) |
754
+ | `mem::export` / `mem::import` | Full JSON round-trip (v0.3.0 v0.7.0 formats, includes lessons) |
738
755
  | `mem::claude-bridge-read` | Read Claude Code native MEMORY.md |
739
756
  | `mem::claude-bridge-sync` | Sync top memories back to MEMORY.md |
740
757
  | `mem::graph-extract` | LLM-powered entity extraction from observations |
@@ -770,8 +787,11 @@ agentmemory is built on iii-engine's three primitives:
770
787
  | `mem::graph-retrieval` | Entity search + chunk expansion + temporal queries via knowledge graph |
771
788
  | `mem::verify` | JIT verification — trace memory provenance back to source observations |
772
789
  | `mem::cascade-update` | Propagate staleness to graph nodes, edges, and sibling memories |
790
+ | `mem::lesson-save` / `recall` / `list` | Confidence-scored lessons with dedup, reinforcement, and decay |
791
+ | `mem::lesson-strengthen` / `decay-sweep` | Reinforce lessons on reuse, sweep for time-based decay |
792
+ | `mem::obsidian-export` | Export vault as Obsidian-compatible Markdown with YAML frontmatter + wikilinks |
773
793
 
774
- ### Data Model (33 KV scopes)
794
+ ### Data Model (34 KV scopes)
775
795
 
776
796
  | Scope | Stores |
777
797
  |-------|--------|
@@ -808,20 +828,21 @@ agentmemory is built on iii-engine's three primitives:
808
828
  | `mem:sketches` | Ephemeral action graphs |
809
829
  | `mem:crystals` | Compacted action chain digests |
810
830
  | `mem:facets` | Multi-dimensional tags |
831
+ | `mem:lessons` | Confidence-scored lessons with decay |
811
832
 
812
833
  ## Development
813
834
 
814
835
  ```bash
815
836
  npm run dev # Hot reload
816
- npm run build # Production build (365KB)
817
- npm test # Unit tests (573 tests, ~1.5s)
837
+ npm run build # Production build (~425KB)
838
+ npm test # Unit tests (581 tests, ~1.5s)
818
839
  npm run test:integration # API tests (requires running services)
819
840
  ```
820
841
 
821
842
  ### Prerequisites
822
843
 
823
- - Node.js >= 18
824
- - Docker
844
+ - Node.js >= 20
845
+ - [iii-engine](https://iii.dev/docs) (`curl -fsSL https://install.iii.dev/iii/main/install.sh | sh`)
825
846
 
826
847
  ## License
827
848
 
package/dist/cli.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { execFileSync, spawn } from "node:child_process";
2
+ import { execFileSync, execSync, spawn } from "node:child_process";
3
3
  import { existsSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ import * as p from "@clack/prompts";
6
7
 
7
8
  //#region src/cli.ts
8
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -20,14 +21,14 @@ Options:
20
21
  --port <N> Override REST port (default: 3111)
21
22
 
22
23
  Environment:
23
- AGENTMEMORY_TOOLS=all Expose all 41 MCP tools
24
- AGENTMEMORY_SECRET=xxx Auth secret for REST/MCP
24
+ AGENTMEMORY_TOOLS=all Expose all 41 MCP tools
25
+ AGENTMEMORY_SECRET=xxx Auth secret for REST/MCP
25
26
  CONSOLIDATION_ENABLED=true Enable auto-consolidation (off by default)
26
27
  OBSIDIAN_AUTO_EXPORT=true Auto-export on consolidation
27
28
 
28
29
  Quick start:
29
- npx agentmemory # auto-starts iii-engine, runs worker
30
- npx agentmemory-mcp # standalone MCP server (no engine needed)
30
+ npx @agentmemory/agentmemory # installs iii if missing, starts everything
31
+ npx agentmemory-mcp # standalone MCP server (no engine needed)
31
32
  `);
32
33
  process.exit(0);
33
34
  }
@@ -63,23 +64,74 @@ function whichBinary(name) {
63
64
  return null;
64
65
  }
65
66
  }
67
+ async function installIii() {
68
+ if (process.platform === "win32") {
69
+ p.log.warn("Automatic iii-engine install is not supported on Windows.");
70
+ p.log.info("Install manually: https://iii.dev/docs");
71
+ return false;
72
+ }
73
+ if (!whichBinary("curl")) {
74
+ p.log.warn("curl not found — cannot auto-install iii-engine.");
75
+ return false;
76
+ }
77
+ const shouldInstall = await p.confirm({
78
+ message: "iii-engine is not installed. Install it now?",
79
+ initialValue: true
80
+ });
81
+ if (p.isCancel(shouldInstall) || !shouldInstall) return false;
82
+ const s = p.spinner();
83
+ s.start("Installing iii-engine...");
84
+ try {
85
+ execSync("curl -fsSL https://install.iii.dev/iii/main/install.sh | sh", {
86
+ stdio: [
87
+ "pipe",
88
+ "pipe",
89
+ "pipe"
90
+ ],
91
+ timeout: 12e4
92
+ });
93
+ if (whichBinary("iii")) {
94
+ s.stop("iii-engine installed successfully");
95
+ return true;
96
+ }
97
+ s.stop("Installation completed but iii not found in PATH");
98
+ p.log.warn("You may need to restart your shell or add iii to your PATH.");
99
+ const iiiPaths = [join(process.env["HOME"] || "", ".local", "bin", "iii"), "/usr/local/bin/iii"];
100
+ for (const iiiPath of iiiPaths) if (existsSync(iiiPath)) {
101
+ p.log.info(`Found iii at: ${iiiPath}`);
102
+ process.env["PATH"] = `${dirname(iiiPath)}:${process.env["PATH"]}`;
103
+ return true;
104
+ }
105
+ return false;
106
+ } catch (err) {
107
+ s.stop("Failed to install iii-engine");
108
+ p.log.error(err instanceof Error ? err.message : String(err));
109
+ return false;
110
+ }
111
+ }
66
112
  async function startEngine() {
67
113
  const configPath = findIiiConfig();
68
- const iiiBin = whichBinary("iii");
114
+ let iiiBin = whichBinary("iii");
115
+ if (!iiiBin) {
116
+ if (await installIii()) iiiBin = whichBinary("iii");
117
+ }
69
118
  if (iiiBin && configPath) {
70
- console.log(`[agentmemory] Starting iii-engine: ${iiiBin} --config ${configPath}`);
119
+ const s = p.spinner();
120
+ s.start(`Starting iii-engine: ${iiiBin}`);
71
121
  spawn(iiiBin, ["--config", configPath], {
72
122
  detached: true,
73
123
  stdio: "ignore"
74
124
  }).unref();
125
+ s.stop("iii-engine process started");
75
126
  return true;
76
127
  }
128
+ const dockerBin = whichBinary("docker");
77
129
  const dockerCompose = join(__dirname, "..", "docker-compose.yml");
78
130
  const dcExists = existsSync(dockerCompose) || existsSync(join(process.cwd(), "docker-compose.yml"));
79
- const dockerBin = whichBinary("docker");
80
131
  if (dockerBin && dcExists) {
81
132
  const composeFile = existsSync(dockerCompose) ? dockerCompose : join(process.cwd(), "docker-compose.yml");
82
- console.log(`[agentmemory] Starting iii-engine via Docker...`);
133
+ const s = p.spinner();
134
+ s.start("Starting iii-engine via Docker...");
83
135
  spawn(dockerBin, [
84
136
  "compose",
85
137
  "-f",
@@ -90,6 +142,7 @@ async function startEngine() {
90
142
  detached: true,
91
143
  stdio: "ignore"
92
144
  }).unref();
145
+ s.stop("Docker compose started");
93
146
  return true;
94
147
  }
95
148
  return false;
@@ -103,32 +156,46 @@ async function waitForEngine(timeoutMs) {
103
156
  return false;
104
157
  }
105
158
  async function main() {
106
- if (!skipEngine && !await isEngineRunning()) {
107
- if (!await startEngine()) {
108
- console.error(`
109
- [agentmemory] iii-engine is not running and could not be auto-started.
110
-
111
- Install one of:
112
- 1. iii CLI: npm install -g iii-engine
113
- 2. Docker: docker compose up -d (with docker-compose.yml)
114
-
115
- Or run with --no-engine to connect to a remote engine.
116
- `);
117
- process.exit(1);
118
- }
119
- console.log(`[agentmemory] Waiting for iii-engine to start...`);
120
- if (!await waitForEngine(15e3)) {
121
- const port = getRestPort();
122
- console.error(`[agentmemory] iii-engine did not become ready within 15s.`);
123
- console.error(`[agentmemory] Check that ports ${port}, ${port + 1}, 49134 are available.`);
124
- process.exit(1);
125
- }
126
- console.log(`[agentmemory] iii-engine is ready.`);
159
+ p.intro("agentmemory");
160
+ if (skipEngine) {
161
+ p.log.info("Skipping engine check (--no-engine)");
162
+ await import("./src-1fTKFEtN.mjs");
163
+ return;
164
+ }
165
+ if (await isEngineRunning()) {
166
+ p.log.success("iii-engine is running");
167
+ await import("./src-1fTKFEtN.mjs");
168
+ return;
169
+ }
170
+ if (!await startEngine()) {
171
+ p.log.error("Could not start iii-engine.");
172
+ p.note([
173
+ "Install iii-engine (pick one):",
174
+ " curl -fsSL https://install.iii.dev/iii/main/install.sh | sh",
175
+ " cargo install iii-engine",
176
+ "",
177
+ "Or use Docker:",
178
+ " docker pull iiidev/iii:latest",
179
+ "",
180
+ "Docs: https://iii.dev/docs",
181
+ "",
182
+ "Or skip with: agentmemory --no-engine"
183
+ ].join("\n"), "Setup required");
184
+ process.exit(1);
185
+ }
186
+ const s = p.spinner();
187
+ s.start("Waiting for iii-engine to be ready...");
188
+ if (!await waitForEngine(15e3)) {
189
+ const port = getRestPort();
190
+ s.stop("iii-engine did not become ready within 15s");
191
+ p.log.error(`Check that ports ${port}, ${port + 1}, 49134 are available.`);
192
+ process.exit(1);
127
193
  }
128
- await import("./src-QxitMPfJ.mjs");
194
+ s.stop("iii-engine is ready");
195
+ await import("./src-1fTKFEtN.mjs");
129
196
  }
130
197
  main().catch((err) => {
131
- console.error(`[agentmemory] Fatal:`, err);
198
+ p.log.error(err instanceof Error ? err.message : String(err));
132
199
  process.exit(1);
133
200
  });
134
201
 
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst args = process.argv.slice(2);\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [options]\n\nOptions:\n --help, -h Show this help\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\nEnvironment:\n AGENTMEMORY_TOOLS=all Expose all 41 MCP tools\n AGENTMEMORY_SECRET=xxx Auth secret for REST/MCP\n CONSOLIDATION_ENABLED=true Enable auto-consolidation (off by default)\n OBSIDIAN_AUTO_EXPORT=true Auto-export on consolidation\n\nQuick start:\n npx agentmemory # auto-starts iii-engine, runs worker\n npx agentmemory-mcp # standalone MCP server (no engine needed)\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 const res = await fetch(`http://localhost:${getRestPort()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n return res.ok;\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 = process.platform === \"win32\" ? \"where\" : \"which\";\n try {\n return execFileSync(cmd, [name], { encoding: \"utf-8\" }).trim().split(\"\\n\")[0];\n } catch {\n return null;\n }\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n\n const iiiBin = whichBinary(\"iii\");\n if (iiiBin && configPath) {\n console.log(`[agentmemory] Starting iii-engine: ${iiiBin} --config ${configPath}`);\n const child = spawn(iiiBin, [\"--config\", configPath], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n return true;\n }\n\n const dockerCompose = join(__dirname, \"..\", \"docker-compose.yml\");\n const dcExists = existsSync(dockerCompose) || existsSync(join(process.cwd(), \"docker-compose.yml\"));\n const dockerBin = whichBinary(\"docker\");\n\n if (dockerBin && dcExists) {\n const composeFile = existsSync(dockerCompose) ? dockerCompose : join(process.cwd(), \"docker-compose.yml\");\n console.log(`[agentmemory] Starting iii-engine via Docker...`);\n const child = spawn(dockerBin, [\"compose\", \"-f\", composeFile, \"up\", \"-d\"], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n return true;\n }\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\nasync function main() {\n if (!skipEngine && !(await isEngineRunning())) {\n const started = await startEngine();\n if (!started) {\n console.error(`\n[agentmemory] iii-engine is not running and could not be auto-started.\n\nInstall one of:\n 1. iii CLI: npm install -g iii-engine\n 2. Docker: docker compose up -d (with docker-compose.yml)\n\nOr run with --no-engine to connect to a remote engine.\n`);\n process.exit(1);\n }\n\n console.log(`[agentmemory] Waiting for iii-engine to start...`);\n const ready = await waitForEngine(15000);\n if (!ready) {\n const port = getRestPort();\n console.error(`[agentmemory] iii-engine did not become ready within 15s.`);\n console.error(`[agentmemory] Check that ports ${port}, ${port + 1}, 49134 are available.`);\n process.exit(1);\n }\n console.log(`[agentmemory] iii-engine is ready.`);\n }\n\n await import(\"./index.js\");\n}\n\nmain().catch((err) => {\n console.error(`[agentmemory] Fatal:`, err);\n process.exit(1);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, execFileSync, execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as p from \"@clack/prompts\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst args = process.argv.slice(2);\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nagentmemory — persistent memory for AI coding agents\n\nUsage: agentmemory [options]\n\nOptions:\n --help, -h Show this help\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\nEnvironment:\n AGENTMEMORY_TOOLS=all Expose all 41 MCP tools\n AGENTMEMORY_SECRET=xxx Auth secret for REST/MCP\n CONSOLIDATION_ENABLED=true Enable auto-consolidation (off by default)\n OBSIDIAN_AUTO_EXPORT=true Auto-export on consolidation\n\nQuick start:\n npx @agentmemory/agentmemory # installs iii if missing, starts everything\n npx agentmemory-mcp # standalone MCP server (no engine needed)\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 const res = await fetch(`http://localhost:${getRestPort()}/agentmemory/livez`, {\n signal: AbortSignal.timeout(2000),\n });\n return res.ok;\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 = process.platform === \"win32\" ? \"where\" : \"which\";\n try {\n return execFileSync(cmd, [name], { encoding: \"utf-8\" }).trim().split(\"\\n\")[0];\n } catch {\n return null;\n }\n}\n\nasync function installIii(): Promise<boolean> {\n if (process.platform === \"win32\") {\n p.log.warn(\"Automatic iii-engine install is not supported on Windows.\");\n p.log.info(\"Install manually: https://iii.dev/docs\");\n return false;\n }\n\n const curlBin = whichBinary(\"curl\");\n if (!curlBin) {\n p.log.warn(\"curl not found — cannot auto-install iii-engine.\");\n return false;\n }\n\n const shouldInstall = await p.confirm({\n message: \"iii-engine is not installed. Install it now?\",\n initialValue: true,\n });\n\n if (p.isCancel(shouldInstall) || !shouldInstall) {\n return false;\n }\n\n const s = p.spinner();\n s.start(\"Installing iii-engine...\");\n\n try {\n execSync(\"curl -fsSL https://install.iii.dev/iii/main/install.sh | sh\", {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n timeout: 120000,\n });\n\n const installed = whichBinary(\"iii\");\n if (installed) {\n s.stop(\"iii-engine installed successfully\");\n return true;\n }\n\n s.stop(\"Installation completed but iii not found in PATH\");\n p.log.warn(\"You may need to restart your shell or add iii to your PATH.\");\n\n const iiiPaths = [\n join(process.env[\"HOME\"] || \"\", \".local\", \"bin\", \"iii\"),\n \"/usr/local/bin/iii\",\n ];\n for (const iiiPath of iiiPaths) {\n if (existsSync(iiiPath)) {\n p.log.info(`Found iii at: ${iiiPath}`);\n process.env[\"PATH\"] = `${dirname(iiiPath)}:${process.env[\"PATH\"]}`;\n return true;\n }\n }\n\n return false;\n } catch (err) {\n s.stop(\"Failed to install iii-engine\");\n p.log.error(err instanceof Error ? err.message : String(err));\n return false;\n }\n}\n\nasync function startEngine(): Promise<boolean> {\n const configPath = findIiiConfig();\n let iiiBin = whichBinary(\"iii\");\n\n if (!iiiBin) {\n const installed = await installIii();\n if (installed) {\n iiiBin = whichBinary(\"iii\");\n }\n }\n\n if (iiiBin && configPath) {\n const s = p.spinner();\n s.start(`Starting iii-engine: ${iiiBin}`);\n const child = spawn(iiiBin, [\"--config\", configPath], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n s.stop(\"iii-engine process started\");\n return true;\n }\n\n const dockerBin = whichBinary(\"docker\");\n const dockerCompose = join(__dirname, \"..\", \"docker-compose.yml\");\n const dcExists = existsSync(dockerCompose) || existsSync(join(process.cwd(), \"docker-compose.yml\"));\n\n if (dockerBin && dcExists) {\n const composeFile = existsSync(dockerCompose) ? dockerCompose : join(process.cwd(), \"docker-compose.yml\");\n const s = p.spinner();\n s.start(\"Starting iii-engine via Docker...\");\n const child = spawn(dockerBin, [\"compose\", \"-f\", composeFile, \"up\", \"-d\"], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n s.stop(\"Docker compose started\");\n return true;\n }\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\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 p.note(\n [\n \"Install iii-engine (pick one):\",\n \" curl -fsSL https://install.iii.dev/iii/main/install.sh | sh\",\n \" cargo install iii-engine\",\n \"\",\n \"Or use Docker:\",\n \" docker pull iiidev/iii:latest\",\n \"\",\n \"Docs: https://iii.dev/docs\",\n \"\",\n \"Or skip with: agentmemory --no-engine\",\n ].join(\"\\n\"),\n \"Setup required\",\n );\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 p.log.error(`Check that ports ${port}, ${port + 1}, 49134 are available.`);\n process.exit(1);\n }\n\n s.stop(\"iii-engine is ready\");\n await import(\"./index.js\");\n}\n\nmain().catch((err) => {\n p.log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -3739,7 +3739,7 @@ function registerAutoForgetFunction(sdk, kv) {
3739
3739
 
3740
3740
  //#endregion
3741
3741
  //#region src/version.ts
3742
- const VERSION = "0.7.0";
3742
+ const VERSION = "0.7.2";
3743
3743
 
3744
3744
  //#endregion
3745
3745
  //#region src/functions/export-import.ts
@@ -3835,7 +3835,8 @@ function registerExportImportFunction(sdk, kv) {
3835
3835
  "0.5.0",
3836
3836
  "0.6.0",
3837
3837
  "0.6.1",
3838
- "0.7.0"
3838
+ "0.7.0",
3839
+ "0.7.2"
3839
3840
  ]).has(importData.version)) return {
3840
3841
  success: false,
3841
3842
  error: `Unsupported export version: ${importData.version}`