@agentmemory/agentmemory 0.9.21 → 0.9.22

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.
Files changed (47) hide show
  1. package/README.md +150 -7
  2. package/dist/cli.d.mts +5 -1
  3. package/dist/cli.d.mts.map +1 -0
  4. package/dist/cli.mjs +103 -692
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/connect-BQQXpyDS.mjs +763 -0
  7. package/dist/connect-BQQXpyDS.mjs.map +1 -0
  8. package/dist/hooks/post-tool-use.mjs +1 -1
  9. package/dist/hooks/post-tool-use.mjs.map +1 -1
  10. package/dist/hooks/stop.mjs +8 -0
  11. package/dist/hooks/stop.mjs.map +1 -1
  12. package/dist/{image-refs-R3tin9MR.mjs → image-refs-CJS5B9Gq.mjs} +2 -2
  13. package/dist/{image-refs-R3tin9MR.mjs.map → image-refs-CJS5B9Gq.mjs.map} +1 -1
  14. package/dist/{image-store-DyrKZKqZ.mjs → image-store-CdE0amb1.mjs} +1 -1
  15. package/dist/index.mjs +450 -242
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/logger-xlVlvCWX.mjs +43 -0
  18. package/dist/logger-xlVlvCWX.mjs.map +1 -0
  19. package/dist/schema-BkALl7Z_.mjs +74 -0
  20. package/dist/schema-BkALl7Z_.mjs.map +1 -0
  21. package/dist/{src-D5arboxc.mjs → src-gpTAJuBy.mjs} +428 -243
  22. package/dist/src-gpTAJuBy.mjs.map +1 -0
  23. package/dist/{standalone-C7BgzzIN.mjs → standalone-C4i7ktpn.mjs} +18 -6
  24. package/dist/standalone-C4i7ktpn.mjs.map +1 -0
  25. package/dist/standalone.d.mts.map +1 -1
  26. package/dist/standalone.mjs +15 -4
  27. package/dist/standalone.mjs.map +1 -1
  28. package/dist/{tools-registry-CRTWUFw9.mjs → tools-registry-B7Y6nJsr.mjs} +36 -11
  29. package/dist/tools-registry-B7Y6nJsr.mjs.map +1 -0
  30. package/dist/version-DvQMNbEH.mjs +6 -0
  31. package/dist/version-DvQMNbEH.mjs.map +1 -0
  32. package/dist/viewer/index.html +77 -9
  33. package/package.json +6 -4
  34. package/plugin/.claude-plugin/plugin.json +1 -1
  35. package/plugin/.codex-plugin/plugin.json +1 -1
  36. package/plugin/.mcp.json +3 -2
  37. package/plugin/opencode/agentmemory-capture.ts +34 -9
  38. package/plugin/scripts/diagnostics.d.mts +17 -0
  39. package/plugin/scripts/diagnostics.d.mts.map +1 -0
  40. package/plugin/scripts/diagnostics.mjs.map +1 -0
  41. package/plugin/scripts/post-tool-use.mjs +1 -1
  42. package/plugin/scripts/post-tool-use.mjs.map +1 -1
  43. package/plugin/scripts/stop.mjs +8 -0
  44. package/plugin/scripts/stop.mjs.map +1 -1
  45. package/dist/src-D5arboxc.mjs.map +0 -1
  46. package/dist/standalone-C7BgzzIN.mjs.map +0 -1
  47. package/dist/tools-registry-CRTWUFw9.mjs.map +0 -1
@@ -0,0 +1,763 @@
1
+ import { createRequire } from "node:module";
2
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { homedir, platform } from "node:os";
6
+ import * as p from "@clack/prompts";
7
+
8
+ //#region \0rolldown/runtime.js
9
+ var __defProp = Object.defineProperty;
10
+ var __exportAll = (all, no_symbols) => {
11
+ let target = {};
12
+ for (var name in all) {
13
+ __defProp(target, name, {
14
+ get: all[name],
15
+ enumerable: true
16
+ });
17
+ }
18
+ if (!no_symbols) {
19
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
20
+ }
21
+ return target;
22
+ };
23
+
24
+ //#endregion
25
+ //#region src/cli/connect/util.ts
26
+ const AGENTMEMORY_MCP_BLOCK = {
27
+ command: "npx",
28
+ args: ["-y", "@agentmemory/mcp"],
29
+ env: {
30
+ AGENTMEMORY_URL: "${AGENTMEMORY_URL:-http://localhost:3111}",
31
+ AGENTMEMORY_SECRET: "${AGENTMEMORY_SECRET:-}",
32
+ AGENTMEMORY_TOOLS: "${AGENTMEMORY_TOOLS:-all}"
33
+ }
34
+ };
35
+ function backupsDir() {
36
+ return join(homedir(), ".agentmemory", "backups");
37
+ }
38
+ function ensureBackupsDir() {
39
+ const dir = backupsDir();
40
+ mkdirSync(dir, { recursive: true });
41
+ return dir;
42
+ }
43
+ function timestampSlug() {
44
+ return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
45
+ }
46
+ function backupFile(sourcePath, agent, ext = "json") {
47
+ ensureBackupsDir();
48
+ const stamp = timestampSlug();
49
+ const target = join(backupsDir(), `${agent}-${stamp}.${ext}`);
50
+ copyFileSync(sourcePath, target);
51
+ return target;
52
+ }
53
+ function readJsonSafe(path) {
54
+ if (!existsSync(path)) return null;
55
+ try {
56
+ return JSON.parse(readFileSync(path, "utf-8"));
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+ function writeJsonAtomic(path, value) {
62
+ mkdirSync(dirname(path), { recursive: true });
63
+ const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
64
+ writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
65
+ renameSync(tmp, path);
66
+ }
67
+ function logInstalled(label, target) {
68
+ p.log.success(`${label} → wired into ${target}`);
69
+ }
70
+ function logAlreadyWired(label, target) {
71
+ p.log.info(`${label} already wired in ${target} (use --force to re-install)`);
72
+ }
73
+ function logBackup(target) {
74
+ p.log.info(`Backup: ${target}`);
75
+ }
76
+
77
+ //#endregion
78
+ //#region src/cli/connect/json-mcp-adapter.ts
79
+ function entryMatches$1(entry) {
80
+ if (!entry || typeof entry !== "object") return false;
81
+ const e = entry;
82
+ if (e["command"] !== "npx") return false;
83
+ return (Array.isArray(e["args"]) ? e["args"] : []).includes("@agentmemory/mcp");
84
+ }
85
+ function createJsonMcpAdapter(config) {
86
+ return {
87
+ name: config.name,
88
+ displayName: config.displayName,
89
+ ...config.docs !== void 0 && { docs: config.docs },
90
+ ...config.protocolNote !== void 0 && { protocolNote: config.protocolNote },
91
+ detect() {
92
+ return existsSync(config.detectDir);
93
+ },
94
+ async install(opts) {
95
+ const existing = readJsonSafe(config.configPath);
96
+ const next = existing ? { ...existing } : {};
97
+ const servers = { ...next.mcpServers ?? {} };
98
+ const alreadyHas = entryMatches$1(servers["agentmemory"]);
99
+ if (alreadyHas && !opts.force) {
100
+ logAlreadyWired(config.displayName, config.configPath);
101
+ return {
102
+ kind: "already-wired",
103
+ mutatedPath: config.configPath
104
+ };
105
+ }
106
+ if (opts.dryRun) {
107
+ p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} mcpServers.agentmemory in ${config.configPath}`);
108
+ return {
109
+ kind: "installed",
110
+ mutatedPath: config.configPath
111
+ };
112
+ }
113
+ let backupPath;
114
+ if (existsSync(config.configPath)) {
115
+ backupPath = backupFile(config.configPath, config.name);
116
+ logBackup(backupPath);
117
+ } else mkdirSync(dirname(config.configPath), { recursive: true });
118
+ servers["agentmemory"] = AGENTMEMORY_MCP_BLOCK;
119
+ next.mcpServers = servers;
120
+ writeJsonAtomic(config.configPath, next);
121
+ if (!entryMatches$1(readJsonSafe(config.configPath)?.mcpServers?.["agentmemory"])) {
122
+ p.log.error(`Verification failed: ${config.configPath} did not contain mcpServers.agentmemory after write.`);
123
+ return {
124
+ kind: "skipped",
125
+ reason: "verification-failed"
126
+ };
127
+ }
128
+ logInstalled(config.displayName, config.configPath);
129
+ return {
130
+ kind: "installed",
131
+ mutatedPath: config.configPath,
132
+ ...backupPath !== void 0 && { backupPath }
133
+ };
134
+ }
135
+ };
136
+ }
137
+
138
+ //#endregion
139
+ //#region src/cli/connect/antigravity.ts
140
+ const ANTIGRAVITY_DIR = platform() === "darwin" ? join(homedir(), "Library", "Application Support", "Antigravity", "User") : join(homedir(), ".config", "Antigravity", "User");
141
+ const adapter$10 = createJsonMcpAdapter({
142
+ name: "antigravity",
143
+ displayName: "Antigravity",
144
+ detectDir: ANTIGRAVITY_DIR,
145
+ configPath: join(ANTIGRAVITY_DIR, "mcp_config.json"),
146
+ docs: "https://github.com/rohitg00/agentmemory#other-agents",
147
+ protocolNote: "→ Using MCP via mcp_config.json. Antigravity replaces Gemini CLI (sunset 2026-06-18)."
148
+ });
149
+
150
+ //#endregion
151
+ //#region src/cli/connect/codex-hooks.ts
152
+ /**
153
+ * Locate the bundled `plugin/` directory at runtime. Walks up from the
154
+ * module's own location looking for `plugin/scripts/` + `plugin/hooks/`,
155
+ * both shipped via the npm `files` field. Works for both `dist/cli.mjs`
156
+ * (bundled) and `src/cli/connect/codex-hooks.ts` (dev) layouts.
157
+ */
158
+ function findPluginRoot(startUrl = import.meta.url) {
159
+ const here = dirname(fileURLToPath(startUrl));
160
+ let dir = here;
161
+ for (let i = 0; i < 12; i++) {
162
+ if (existsSync(join(dir, "plugin", "scripts")) && existsSync(join(dir, "plugin", "hooks"))) return resolve(join(dir, "plugin"));
163
+ const parent = dirname(dir);
164
+ if (parent === dir) break;
165
+ dir = parent;
166
+ }
167
+ throw new Error(`agentmemory: could not locate bundled plugin/ directory (searched up from ${here})`);
168
+ }
169
+ /**
170
+ * Build the merged hooks.json content.
171
+ *
172
+ * 1. Strip any entry from `existing` whose first hook command points
173
+ * under `<pluginRoot>/scripts/`. This lets us re-install idempotently
174
+ * without leaving stale references.
175
+ * 2. Append fresh entries from the bundled Codex manifest with
176
+ * `${CLAUDE_PLUGIN_ROOT}` rewritten to the absolute plugin path.
177
+ * Matcher values from the bundled manifest are preserved so PreToolUse
178
+ * event routing keeps working.
179
+ */
180
+ function buildMergedHooks(existing, pluginRoot, manifestFile = "hooks.codex.json") {
181
+ const bundledManifestPath = join(pluginRoot, "hooks", manifestFile);
182
+ const ours = JSON.parse(readFileSync(bundledManifestPath, "utf-8"));
183
+ const scriptsDir = join(pluginRoot, "scripts");
184
+ const out = { hooks: {} };
185
+ if (existing?.hooks) for (const [event, entries] of Object.entries(existing.hooks)) {
186
+ const kept = entries.filter((entry) => !isAgentmemoryEntry(entry, scriptsDir));
187
+ if (kept.length > 0) out.hooks[event] = kept;
188
+ }
189
+ for (const [event, entries] of Object.entries(ours.hooks)) {
190
+ const resolvedEntries = entries.map((entry) => {
191
+ const next = { hooks: entry.hooks.map((handler) => ({
192
+ type: handler.type,
193
+ command: handler.command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, pluginRoot)
194
+ })) };
195
+ if (entry.matcher !== void 0) next.matcher = entry.matcher;
196
+ return next;
197
+ });
198
+ out.hooks[event] = [...out.hooks[event] ?? [], ...resolvedEntries];
199
+ }
200
+ return out;
201
+ }
202
+ function isAgentmemoryEntry(entry, scriptsDir) {
203
+ return entry.hooks.some((handler) => handler.command.includes(scriptsDir));
204
+ }
205
+
206
+ //#endregion
207
+ //#region src/cli/connect/claude-code.ts
208
+ const CLAUDE_DIR = join(homedir(), ".claude");
209
+ const CLAUDE_JSON = join(homedir(), ".claude.json");
210
+ const CLAUDE_SETTINGS = join(CLAUDE_DIR, "settings.json");
211
+ function entryMatches(entry) {
212
+ if (!entry || typeof entry !== "object") return false;
213
+ const e = entry;
214
+ if (e["command"] !== "npx") return false;
215
+ return (Array.isArray(e["args"]) ? e["args"] : []).includes("@agentmemory/mcp");
216
+ }
217
+ const adapter$9 = {
218
+ name: "claude-code",
219
+ displayName: "Claude Code",
220
+ docs: "https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it",
221
+ protocolNote: "→ Using MCP. Hooks are also available — see docs/claude-code.md.",
222
+ detect() {
223
+ return existsSync(CLAUDE_DIR);
224
+ },
225
+ async install(opts) {
226
+ const existing = readJsonSafe(CLAUDE_JSON);
227
+ const next = existing ? { ...existing } : {};
228
+ const servers = { ...next.mcpServers ?? {} };
229
+ const alreadyHas = entryMatches(servers["agentmemory"]);
230
+ if (alreadyHas && !opts.force) {
231
+ logAlreadyWired("Claude Code", CLAUDE_JSON);
232
+ if (opts.withHooks) {
233
+ const hookResult = installClaudeHooks(opts);
234
+ if (hookResult.kind === "skipped") p.log.warn(`Claude Code hooks fallback skipped: ${hookResult.reason}.`);
235
+ }
236
+ return {
237
+ kind: "already-wired",
238
+ mutatedPath: CLAUDE_JSON
239
+ };
240
+ }
241
+ if (opts.dryRun) {
242
+ p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} mcpServers.agentmemory in ${CLAUDE_JSON}`);
243
+ return {
244
+ kind: "installed",
245
+ mutatedPath: CLAUDE_JSON
246
+ };
247
+ }
248
+ let backupPath;
249
+ if (existsSync(CLAUDE_JSON)) {
250
+ backupPath = backupFile(CLAUDE_JSON, "claude-code");
251
+ logBackup(backupPath);
252
+ } else {
253
+ mkdirSync(CLAUDE_DIR, { recursive: true });
254
+ writeFileSync(CLAUDE_JSON, "{}\n", "utf-8");
255
+ }
256
+ servers["agentmemory"] = AGENTMEMORY_MCP_BLOCK;
257
+ next.mcpServers = servers;
258
+ writeJsonAtomic(CLAUDE_JSON, next);
259
+ if (!entryMatches(readJsonSafe(CLAUDE_JSON)?.mcpServers?.["agentmemory"])) {
260
+ p.log.error(`Verification failed: ${CLAUDE_JSON} did not contain mcpServers.agentmemory after write.`);
261
+ return {
262
+ kind: "skipped",
263
+ reason: "verification-failed"
264
+ };
265
+ }
266
+ logInstalled("Claude Code", CLAUDE_JSON);
267
+ p.log.info("Restart Claude Code (or run `/mcp` inside a session) to pick up the new server.");
268
+ if (opts.withHooks) {
269
+ const hookResult = installClaudeHooks(opts);
270
+ if (hookResult.kind === "skipped") p.log.warn(`Claude Code hooks fallback skipped: ${hookResult.reason}. MCP wiring still applied.`);
271
+ }
272
+ return {
273
+ kind: "installed",
274
+ mutatedPath: CLAUDE_JSON,
275
+ backupPath
276
+ };
277
+ }
278
+ };
279
+ /**
280
+ * Merge the bundled `plugin/hooks/hooks.json` into
281
+ * `~/.claude/settings.json`'s top-level `hooks` field with absolute
282
+ * script paths. Use this when agentmemory is NOT installed through
283
+ * `/plugin marketplace add` (e.g. MCP standalone wiring), so the
284
+ * hook scripts survive version bumps without `${CLAUDE_PLUGIN_ROOT}`
285
+ * expansion (issue #508).
286
+ *
287
+ * Re-install strips entries whose command points under
288
+ * `<pluginRoot>/scripts/`; unrelated user hook entries survive.
289
+ */
290
+ function installClaudeHooks(opts) {
291
+ let pluginRoot;
292
+ try {
293
+ pluginRoot = findPluginRoot();
294
+ } catch (err) {
295
+ return {
296
+ kind: "skipped",
297
+ reason: err instanceof Error ? err.message : String(err)
298
+ };
299
+ }
300
+ const existing = readJsonSafe(CLAUDE_SETTINGS) ?? {};
301
+ const merged = buildMergedHooks(existing.hooks ? { hooks: existing.hooks } : null, pluginRoot, "hooks.json");
302
+ if (opts.dryRun) {
303
+ p.log.info(`[dry-run] Would merge agentmemory hook entries into ${CLAUDE_SETTINGS} (${Object.keys(merged.hooks).length} event(s))`);
304
+ return {
305
+ kind: "installed",
306
+ mutatedPath: CLAUDE_SETTINGS
307
+ };
308
+ }
309
+ let backupPath;
310
+ if (existsSync(CLAUDE_SETTINGS)) {
311
+ backupPath = backupFile(CLAUDE_SETTINGS, "claude-settings", "json");
312
+ logBackup(backupPath);
313
+ } else mkdirSync(CLAUDE_DIR, { recursive: true });
314
+ writeJsonAtomic(CLAUDE_SETTINGS, {
315
+ ...existing,
316
+ hooks: merged.hooks
317
+ });
318
+ logInstalled("Claude Code hooks (workaround for #508)", CLAUDE_SETTINGS);
319
+ p.log.info("User-scope hook entries reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect claude-code --with-hooks` after upgrading agentmemory to refresh them.");
320
+ return {
321
+ kind: "installed",
322
+ mutatedPath: CLAUDE_SETTINGS,
323
+ ...backupPath !== void 0 && { backupPath }
324
+ };
325
+ }
326
+
327
+ //#endregion
328
+ //#region src/cli/connect/codex.ts
329
+ const CODEX_DIR = join(homedir(), ".codex");
330
+ const CODEX_TOML = join(CODEX_DIR, "config.toml");
331
+ const CODEX_HOOKS = join(CODEX_DIR, "hooks.json");
332
+ const TOML_BLOCK = `[mcp_servers.agentmemory]
333
+ command = "npx"
334
+ args = ["-y", "@agentmemory/mcp"]
335
+
336
+ [mcp_servers.agentmemory.env]
337
+ AGENTMEMORY_URL = "http://localhost:3111"
338
+ `;
339
+ const SECTION_HEADER = "[mcp_servers.agentmemory]";
340
+ function isWiredText(toml) {
341
+ return toml.includes(SECTION_HEADER);
342
+ }
343
+ function stripExistingBlock(toml) {
344
+ const lines = toml.split(/\r?\n/);
345
+ const out = [];
346
+ let skipping = false;
347
+ for (const line of lines) {
348
+ const trimmed = line.trim();
349
+ if (trimmed === SECTION_HEADER || trimmed === "[mcp_servers.agentmemory.env]") {
350
+ skipping = true;
351
+ continue;
352
+ }
353
+ if (skipping && trimmed.startsWith("[") && trimmed !== "[mcp_servers.agentmemory.env]") skipping = false;
354
+ if (!skipping) out.push(line);
355
+ }
356
+ return out.join("\n").replace(/\n{3,}$/, "\n\n").trimEnd() + "\n";
357
+ }
358
+ const adapter$8 = {
359
+ name: "codex",
360
+ displayName: "Codex CLI",
361
+ docs: "https://github.com/rohitg00/agentmemory#codex-cli-codex-plugin-platform",
362
+ protocolNote: "→ Using MCP. Hooks ship via the Codex plugin; on Codex Desktop, also pass --with-hooks to install the global hooks.json workaround for openai/codex#16430.",
363
+ detect() {
364
+ return existsSync(CODEX_DIR);
365
+ },
366
+ async install(opts) {
367
+ const exists = existsSync(CODEX_TOML);
368
+ const current = exists ? readFileSync(CODEX_TOML, "utf-8") : "";
369
+ const wired = isWiredText(current);
370
+ if (wired && !opts.force) {
371
+ logAlreadyWired("Codex CLI", CODEX_TOML);
372
+ return {
373
+ kind: "already-wired",
374
+ mutatedPath: CODEX_TOML
375
+ };
376
+ }
377
+ if (opts.dryRun) {
378
+ p.log.info(`[dry-run] Would ${wired ? "rewrite" : "append"} [mcp_servers.agentmemory] in ${CODEX_TOML}`);
379
+ if (opts.withHooks) installCodexHooks(opts);
380
+ return {
381
+ kind: "installed",
382
+ mutatedPath: CODEX_TOML
383
+ };
384
+ }
385
+ let backupPath;
386
+ if (exists) {
387
+ backupPath = backupFile(CODEX_TOML, "codex", "toml");
388
+ logBackup(backupPath);
389
+ } else mkdirSync(dirname(CODEX_TOML), { recursive: true });
390
+ const cleaned = wired ? stripExistingBlock(current) : current;
391
+ writeFileSync(CODEX_TOML, `${cleaned}${cleaned.length === 0 || cleaned.endsWith("\n") ? "" : "\n"}${cleaned.length > 0 ? "\n" : ""}${TOML_BLOCK}`, "utf-8");
392
+ if (!isWiredText(readFileSync(CODEX_TOML, "utf-8"))) {
393
+ p.log.error(`Verification failed: ${CODEX_TOML} did not contain ${SECTION_HEADER} after write.`);
394
+ return {
395
+ kind: "skipped",
396
+ reason: "verification-failed"
397
+ };
398
+ }
399
+ logInstalled("Codex CLI", CODEX_TOML);
400
+ p.log.info("Codex picks up MCP servers on next launch. For the deeper plugin install, run: codex plugin marketplace add rohitg00/agentmemory && codex plugin add agentmemory@agentmemory");
401
+ if (opts.withHooks) {
402
+ const hookResult = installCodexHooks(opts);
403
+ if (hookResult.kind === "skipped") p.log.warn(`Codex hooks fallback skipped: ${hookResult.reason}. MCP wiring still applied.`);
404
+ }
405
+ return {
406
+ kind: "installed",
407
+ mutatedPath: CODEX_TOML,
408
+ ...backupPath !== void 0 && { backupPath }
409
+ };
410
+ }
411
+ };
412
+ /**
413
+ * Install the global `~/.codex/hooks.json` fallback. See
414
+ * `codex-hooks.ts` for context (openai/codex#16430). Returns a result
415
+ * describing the side effect for the caller's summary; failures here do
416
+ * not roll back the MCP wiring.
417
+ */
418
+ function installCodexHooks(opts) {
419
+ let pluginRoot;
420
+ try {
421
+ pluginRoot = findPluginRoot();
422
+ } catch (err) {
423
+ return {
424
+ kind: "skipped",
425
+ reason: err instanceof Error ? err.message : String(err)
426
+ };
427
+ }
428
+ const existing = readJsonSafe(CODEX_HOOKS);
429
+ const merged = buildMergedHooks(existing, pluginRoot);
430
+ if (opts.dryRun) {
431
+ p.log.info(`[dry-run] Would ${existing ? "merge" : "create"} ${CODEX_HOOKS} with ${Object.keys(merged.hooks).length} event(s)`);
432
+ return {
433
+ kind: "installed",
434
+ mutatedPath: CODEX_HOOKS
435
+ };
436
+ }
437
+ let backupPath;
438
+ if (existsSync(CODEX_HOOKS)) {
439
+ backupPath = backupFile(CODEX_HOOKS, "codex-hooks", "json");
440
+ logBackup(backupPath);
441
+ }
442
+ writeJsonAtomic(CODEX_HOOKS, merged);
443
+ logInstalled("Codex hooks (workaround for openai/codex#16430)", CODEX_HOOKS);
444
+ p.log.info("User-scope hooks reference absolute paths under the bundled plugin/ dir. Re-run `agentmemory connect codex --with-hooks` after upgrading agentmemory to refresh them.");
445
+ return {
446
+ kind: "installed",
447
+ mutatedPath: CODEX_HOOKS,
448
+ ...backupPath !== void 0 && { backupPath }
449
+ };
450
+ }
451
+
452
+ //#endregion
453
+ //#region src/cli/connect/cursor.ts
454
+ const adapter$7 = createJsonMcpAdapter({
455
+ name: "cursor",
456
+ displayName: "Cursor",
457
+ detectDir: join(homedir(), ".cursor"),
458
+ configPath: join(homedir(), ".cursor", "mcp.json"),
459
+ docs: "https://github.com/rohitg00/agentmemory#other-agents",
460
+ protocolNote: "→ Using MCP (the only protocol Cursor speaks). Memory bridge runs at :3111 underneath."
461
+ });
462
+
463
+ //#endregion
464
+ //#region src/cli/connect/gemini-cli.ts
465
+ const adapter$6 = createJsonMcpAdapter({
466
+ name: "gemini-cli",
467
+ displayName: "Gemini CLI",
468
+ detectDir: join(homedir(), ".gemini"),
469
+ configPath: join(homedir(), ".gemini", "settings.json"),
470
+ docs: "https://github.com/rohitg00/agentmemory#other-agents",
471
+ protocolNote: "→ Using MCP (the only protocol Gemini CLI speaks). Memory bridge runs at :3111 underneath."
472
+ });
473
+
474
+ //#endregion
475
+ //#region src/cli/connect/hermes.ts
476
+ const HERMES_DIR = join(homedir(), ".hermes");
477
+ const HERMES_CONFIG = join(HERMES_DIR, "config.yaml");
478
+ const DOCS$2 = "https://github.com/rohitg00/agentmemory/tree/main/integrations/hermes";
479
+ const adapter$5 = {
480
+ name: "hermes",
481
+ displayName: "Hermes Agent",
482
+ docs: DOCS$2,
483
+ protocolNote: "→ Using MCP. Hooks are also available — see docs/hermes.md.",
484
+ detect() {
485
+ return existsSync(HERMES_DIR);
486
+ },
487
+ async install(_opts) {
488
+ p.log.warn("Hermes uses YAML config. Automated merge isn't implemented yet — manual install required.");
489
+ p.note([
490
+ `Add to ${HERMES_CONFIG}:`,
491
+ "",
492
+ " mcp_servers:",
493
+ " agentmemory:",
494
+ " command: npx",
495
+ " args: [\"-y\", \"@agentmemory/mcp\"]",
496
+ "",
497
+ " memory:",
498
+ " provider: agentmemory",
499
+ "",
500
+ `Full guide: ${DOCS$2}`
501
+ ].join("\n"), "Hermes manual install");
502
+ return {
503
+ kind: "stub",
504
+ reason: "yaml-merge-not-implemented"
505
+ };
506
+ }
507
+ };
508
+
509
+ //#endregion
510
+ //#region src/cli/connect/kiro.ts
511
+ const adapter$4 = createJsonMcpAdapter({
512
+ name: "kiro",
513
+ displayName: "Kiro",
514
+ detectDir: join(homedir(), ".kiro"),
515
+ configPath: join(homedir(), ".kiro", "settings", "mcp.json"),
516
+ docs: "https://github.com/rohitg00/agentmemory#other-agents",
517
+ protocolNote: "→ Using MCP via ~/.kiro/settings/mcp.json (user-level). Workspace overrides live in .kiro/settings/mcp.json."
518
+ });
519
+
520
+ //#endregion
521
+ //#region src/cli/connect/openclaw.ts
522
+ const adapter$3 = createJsonMcpAdapter({
523
+ name: "openclaw",
524
+ displayName: "OpenClaw",
525
+ detectDir: join(homedir(), ".openclaw"),
526
+ configPath: join(homedir(), ".openclaw", "openclaw.json"),
527
+ docs: "https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw",
528
+ protocolNote: "→ Using MCP. Hooks are also available — see docs/openclaw.md."
529
+ });
530
+
531
+ //#endregion
532
+ //#region src/cli/connect/openhuman.ts
533
+ const OPENHUMAN_DIR = join(homedir(), ".openhuman");
534
+ const DOCS$1 = "https://github.com/tinyhumansai/openhuman";
535
+ const adapter$2 = {
536
+ name: "openhuman",
537
+ displayName: "OpenHuman",
538
+ docs: DOCS$1,
539
+ protocolNote: "→ Using native hooks (REST API at :3111). MCP not required.",
540
+ detect() {
541
+ return existsSync(OPENHUMAN_DIR);
542
+ },
543
+ async install(_opts) {
544
+ p.log.warn("OpenHuman integration is not yet automated. No `integrations/openhuman/` folder exists in the agentmemory repo today.");
545
+ p.note([
546
+ "OpenHuman is a Memory-trait host. The expected wiring is the REST",
547
+ "proxy at http://localhost:3111 plus an OpenHuman-side Memory trait",
548
+ "impl. Once integrations/openhuman/ lands in agentmemory we'll wire",
549
+ "this up automatically.",
550
+ "",
551
+ `Tracking: ${DOCS$1}`
552
+ ].join("\n"), "OpenHuman manual install");
553
+ return {
554
+ kind: "stub",
555
+ reason: "no-integration-folder-yet"
556
+ };
557
+ }
558
+ };
559
+
560
+ //#endregion
561
+ //#region src/cli/connect/pi.ts
562
+ const PI_DIR = join(homedir(), ".pi");
563
+ const PI_EXT_DIR = join(PI_DIR, "agent", "extensions", "agentmemory");
564
+ const DOCS = "https://github.com/rohitg00/agentmemory/tree/main/integrations/pi";
565
+ const adapter$1 = {
566
+ name: "pi",
567
+ displayName: "pi",
568
+ docs: DOCS,
569
+ protocolNote: "→ Using native hooks (REST API at :3111). MCP not required.",
570
+ detect() {
571
+ return existsSync(PI_DIR);
572
+ },
573
+ async install(_opts) {
574
+ p.log.warn("pi uses a TypeScript extension file. Automated copy + register isn't implemented yet — manual install required.");
575
+ p.note([
576
+ "Run these from the agentmemory repo root:",
577
+ "",
578
+ ` mkdir -p ${PI_EXT_DIR}`,
579
+ ` cp integrations/pi/index.ts ${PI_EXT_DIR}/index.ts`,
580
+ ` cp integrations/pi/security.ts ${PI_EXT_DIR}/security.ts`,
581
+ "",
582
+ "Then add to ~/.pi/agent/settings.json:",
583
+ " { \"extensions\": [\"~/.pi/agent/extensions/agentmemory\"] }",
584
+ "",
585
+ `Full guide: ${DOCS}`
586
+ ].join("\n"), "pi manual install");
587
+ return {
588
+ kind: "stub",
589
+ reason: "ts-extension-copy-not-implemented"
590
+ };
591
+ }
592
+ };
593
+
594
+ //#endregion
595
+ //#region src/cli/connect/qwen.ts
596
+ const adapter = createJsonMcpAdapter({
597
+ name: "qwen",
598
+ displayName: "Qwen Code",
599
+ detectDir: join(homedir(), ".qwen"),
600
+ configPath: join(homedir(), ".qwen", "settings.json"),
601
+ docs: "https://github.com/rohitg00/agentmemory#other-agents",
602
+ protocolNote: "→ Using MCP via ~/.qwen/settings.json. Qwen Code's hook system can also be wired separately — see docs."
603
+ });
604
+
605
+ //#endregion
606
+ //#region src/cli/connect/index.ts
607
+ var connect_exports = /* @__PURE__ */ __exportAll({
608
+ ADAPTERS: () => ADAPTERS,
609
+ knownAgents: () => knownAgents,
610
+ resolveAdapter: () => resolveAdapter,
611
+ runAdapter: () => runAdapter,
612
+ runConnect: () => runConnect
613
+ });
614
+ const ADAPTERS = [
615
+ adapter$9,
616
+ adapter$8,
617
+ adapter$7,
618
+ adapter$6,
619
+ adapter,
620
+ adapter$10,
621
+ adapter$4,
622
+ adapter$3,
623
+ adapter$5,
624
+ adapter$1,
625
+ adapter$2
626
+ ];
627
+ function resolveAdapter(name) {
628
+ const lower = name.toLowerCase();
629
+ return ADAPTERS.find((a) => a.name === lower) ?? null;
630
+ }
631
+ function knownAgents() {
632
+ return ADAPTERS.map((a) => a.name);
633
+ }
634
+ function parseFlags(args) {
635
+ const positional = [];
636
+ let dryRun = false;
637
+ let force = false;
638
+ let all = false;
639
+ let withHooks = false;
640
+ for (const a of args) if (a === "--dry-run") dryRun = true;
641
+ else if (a === "--force") force = true;
642
+ else if (a === "--all") all = true;
643
+ else if (a === "--with-hooks") withHooks = true;
644
+ else if (!a.startsWith("-")) positional.push(a);
645
+ return {
646
+ dryRun,
647
+ force,
648
+ all,
649
+ withHooks,
650
+ positional
651
+ };
652
+ }
653
+ async function runAdapter(adapter, opts) {
654
+ if (!adapter.detect()) {
655
+ p.log.warn(`${adapter.displayName}: not detected on this machine (skipping).${adapter.docs ? ` Docs: ${adapter.docs}` : ""}`);
656
+ return {
657
+ kind: "skipped",
658
+ reason: "not-detected"
659
+ };
660
+ }
661
+ p.log.step(`Wiring ${adapter.displayName}…`);
662
+ if (adapter.protocolNote) p.log.message(adapter.protocolNote);
663
+ try {
664
+ return await adapter.install(opts);
665
+ } catch (err) {
666
+ p.log.error(`${adapter.displayName}: ${err instanceof Error ? err.message : String(err)}`);
667
+ return {
668
+ kind: "skipped",
669
+ reason: "exception"
670
+ };
671
+ }
672
+ }
673
+ async function runConnect(args) {
674
+ if (platform() === "win32") {
675
+ p.intro("agentmemory connect");
676
+ p.log.warn("Windows: automated `connect` is not supported yet. See https://github.com/rohitg00/agentmemory#other-agents for manual install steps.");
677
+ p.outro("Windows: manual install required — see docs");
678
+ return;
679
+ }
680
+ const { dryRun, force, all, withHooks, positional } = parseFlags(args);
681
+ const opts = {
682
+ dryRun,
683
+ force,
684
+ withHooks
685
+ };
686
+ p.intro("agentmemory connect");
687
+ if (positional.length === 0 && !all) {
688
+ const detected = ADAPTERS.filter((a) => a.detect());
689
+ if (detected.length === 0) {
690
+ p.log.error("No supported agents detected on this machine.");
691
+ p.outro(`Supported: ${knownAgents().join(", ")}`);
692
+ process.exit(1);
693
+ }
694
+ const picked = await p.multiselect({
695
+ message: "Wire agentmemory into which agents?",
696
+ options: detected.map((a) => ({
697
+ value: a.name,
698
+ label: a.displayName
699
+ })),
700
+ required: true
701
+ });
702
+ if (p.isCancel(picked)) {
703
+ p.cancel("Cancelled.");
704
+ return;
705
+ }
706
+ const results = [];
707
+ for (const name of picked) {
708
+ const adapter = resolveAdapter(name);
709
+ if (!adapter) continue;
710
+ results.push({
711
+ name,
712
+ result: await runAdapter(adapter, opts)
713
+ });
714
+ }
715
+ summarize(results);
716
+ return;
717
+ }
718
+ if (all) {
719
+ const detected = ADAPTERS.filter((a) => a.detect());
720
+ if (detected.length === 0) {
721
+ p.log.error("No supported agents detected on this machine.");
722
+ process.exit(1);
723
+ }
724
+ const results = [];
725
+ for (const adapter of detected) results.push({
726
+ name: adapter.name,
727
+ result: await runAdapter(adapter, opts)
728
+ });
729
+ summarize(results);
730
+ return;
731
+ }
732
+ const agentName = positional[0];
733
+ const adapter = resolveAdapter(agentName);
734
+ if (!adapter) {
735
+ p.log.error(`Unknown agent: ${agentName}`);
736
+ p.outro(`Supported: ${knownAgents().join(", ")}`);
737
+ process.exit(1);
738
+ }
739
+ const result = await runAdapter(adapter, opts);
740
+ summarize([{
741
+ name: agentName,
742
+ result
743
+ }]);
744
+ if (result.kind === "skipped" && result.reason !== "not-detected") process.exit(1);
745
+ }
746
+ function summarize(results) {
747
+ const lines = results.map(({ name, result }) => {
748
+ switch (result.kind) {
749
+ case "installed": return ` ✓ ${name}${result.mutatedPath ? ` → ${result.mutatedPath}` : ""}`;
750
+ case "already-wired": return ` ✓ ${name} (already wired)`;
751
+ case "stub": return ` ⚠ ${name} (manual install required: ${result.reason})`;
752
+ case "skipped": return ` ✗ ${name} (skipped: ${result.reason})`;
753
+ }
754
+ });
755
+ p.note(lines.join("\n"), "summary");
756
+ const stubs = results.filter((r) => r.result.kind === "stub");
757
+ if (stubs.length > 0) p.log.info(`${stubs.length} agent(s) require manual install — see docs links above.`);
758
+ p.outro("Restart any wired agent (or open a new session) to pick up agentmemory.");
759
+ }
760
+
761
+ //#endregion
762
+ export { resolveAdapter as n, runAdapter as r, connect_exports as t };
763
+ //# sourceMappingURL=connect-BQQXpyDS.mjs.map