@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
package/dist/cli.mjs CHANGED
@@ -1,101 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
2
+ import { n as resolveAdapter, r as runAdapter } from "./connect-BQQXpyDS.mjs";
3
+ import { i as generateId } from "./schema-BkALl7Z_.mjs";
4
+ import { r as setBootVerbose } from "./logger-xlVlvCWX.mjs";
5
+ import { t as VERSION } from "./version-DvQMNbEH.mjs";
3
6
  import { execFileSync, spawn, spawnSync } from "node:child_process";
4
- import { closeSync, constants, copyFileSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
7
+ import { closeSync, constants, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
5
8
  import { delimiter, dirname, join } from "node:path";
6
9
  import { fileURLToPath } from "node:url";
7
10
  import { homedir, platform } from "node:os";
8
11
  import * as p from "@clack/prompts";
9
- import { createHash } from "node:crypto";
10
12
  import { copyFile, mkdir } from "node:fs/promises";
11
13
 
12
- //#region \0rolldown/runtime.js
13
- var __defProp = Object.defineProperty;
14
- var __exportAll = (all, no_symbols) => {
15
- let target = {};
16
- for (var name in all) {
17
- __defProp(target, name, {
18
- get: all[name],
19
- enumerable: true
20
- });
21
- }
22
- if (!no_symbols) {
23
- __defProp(target, Symbol.toStringTag, { value: "Module" });
24
- }
25
- return target;
26
- };
27
-
28
- //#endregion
29
- //#region src/state/schema.ts
30
- const KV = {
31
- sessions: "mem:sessions",
32
- observations: (sessionId) => `mem:obs:${sessionId}`,
33
- memories: "mem:memories",
34
- summaries: "mem:summaries",
35
- config: "mem:config",
36
- metrics: "mem:metrics",
37
- health: "mem:health",
38
- embeddings: (obsId) => `mem:emb:${obsId}`,
39
- bm25Index: "mem:index:bm25",
40
- relations: "mem:relations",
41
- profiles: "mem:profiles",
42
- claudeBridge: "mem:claude-bridge",
43
- graphNodes: "mem:graph:nodes",
44
- graphEdges: "mem:graph:edges",
45
- semantic: "mem:semantic",
46
- procedural: "mem:procedural",
47
- teamShared: (teamId) => `mem:team:${teamId}:shared`,
48
- teamUsers: (teamId, userId) => `mem:team:${teamId}:users:${userId}`,
49
- teamProfile: (teamId) => `mem:team:${teamId}:profile`,
50
- audit: "mem:audit",
51
- actions: "mem:actions",
52
- actionEdges: "mem:action-edges",
53
- leases: "mem:leases",
54
- routines: "mem:routines",
55
- routineRuns: "mem:routine-runs",
56
- signals: "mem:signals",
57
- checkpoints: "mem:checkpoints",
58
- mesh: "mem:mesh",
59
- sketches: "mem:sketches",
60
- facets: "mem:facets",
61
- sentinels: "mem:sentinels",
62
- crystals: "mem:crystals",
63
- lessons: "mem:lessons",
64
- insights: "mem:insights",
65
- graphEdgeHistory: "mem:graph:edge-history",
66
- enrichedChunks: (sessionId) => `mem:enriched:${sessionId}`,
67
- latentEmbeddings: (obsId) => `mem:latent:${obsId}`,
68
- retentionScores: "mem:retention",
69
- accessLog: "mem:access",
70
- imageRefs: "mem:image-refs",
71
- imageEmbeddings: "mem:image-embeddings",
72
- slots: "mem:slots",
73
- globalSlots: "mem:slots:global",
74
- state: "mem:state",
75
- commits: "mem:commits"
76
- };
77
- const STREAM = {
78
- name: "mem-live",
79
- group: (sessionId) => sessionId,
80
- viewerGroup: "viewer"
81
- };
82
- function generateId(prefix) {
83
- return `${prefix}_${Date.now().toString(36)}_${crypto.randomUUID().replace(/-/g, "").slice(0, 12)}`;
84
- }
85
- function fingerprintId(prefix, content) {
86
- return `${prefix}_${createHash("sha256").update(content).digest("hex").slice(0, 16)}`;
87
- }
88
- function jaccardSimilarity(a, b) {
89
- const setA = new Set(a.split(/\s+/).filter((t) => t.length > 2));
90
- const setB = new Set(b.split(/\s+/).filter((t) => t.length > 2));
91
- if (setA.size === 0 && setB.size === 0) return 1;
92
- if (setA.size === 0 || setB.size === 0) return 0;
93
- let intersection = 0;
94
- for (const word of setA) if (setB.has(word)) intersection++;
95
- return intersection / (setA.size + setB.size - intersection);
96
- }
97
-
98
- //#endregion
99
14
  //#region src/cli/doctor-diagnostics.ts
100
15
  /** Common placeholder values shipped in .env.example. */
101
16
  const PLACEHOLDER_VALUES = new Set([
@@ -323,7 +238,7 @@ function envPath(home) {
323
238
  function preferencesPath(home) {
324
239
  return join(home, ".agentmemory", "preferences.json");
325
240
  }
326
- function backupsDir$1(home) {
241
+ function backupsDir(home) {
327
242
  return join(home, ".agentmemory", "backups");
328
243
  }
329
244
  function dataDir(home) {
@@ -399,9 +314,9 @@ function buildRemovePlan(ctx, options) {
399
314
  plan.push({
400
315
  id: "backups",
401
316
  description: "Delete backups/ directory (connect manifest + backups)",
402
- path: backupsDir$1(home),
317
+ path: backupsDir(home),
403
318
  alwaysAsk: false,
404
- applicable: !options.keepData && pathExists(backupsDir$1(home)),
319
+ applicable: !options.keepData && pathExists(backupsDir(home)),
405
320
  sizeBytes: -1
406
321
  });
407
322
  if (connectManifest?.installed?.length) for (const entry of connectManifest.installed) plan.push({
@@ -564,544 +479,6 @@ function isFirstRun() {
564
479
  return readPrefs().firstRunAt === null;
565
480
  }
566
481
 
567
- //#endregion
568
- //#region src/cli/connect/util.ts
569
- const AGENTMEMORY_MCP_BLOCK = {
570
- command: "npx",
571
- args: ["-y", "@agentmemory/mcp"],
572
- env: {
573
- AGENTMEMORY_URL: "${AGENTMEMORY_URL}",
574
- AGENTMEMORY_SECRET: "${AGENTMEMORY_SECRET}"
575
- }
576
- };
577
- function backupsDir() {
578
- return join(homedir(), ".agentmemory", "backups");
579
- }
580
- function ensureBackupsDir() {
581
- const dir = backupsDir();
582
- mkdirSync(dir, { recursive: true });
583
- return dir;
584
- }
585
- function timestampSlug() {
586
- return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
587
- }
588
- function backupFile(sourcePath, agent, ext = "json") {
589
- ensureBackupsDir();
590
- const stamp = timestampSlug();
591
- const target = join(backupsDir(), `${agent}-${stamp}.${ext}`);
592
- copyFileSync(sourcePath, target);
593
- return target;
594
- }
595
- function readJsonSafe(path) {
596
- if (!existsSync(path)) return null;
597
- try {
598
- return JSON.parse(readFileSync(path, "utf-8"));
599
- } catch {
600
- return null;
601
- }
602
- }
603
- function writeJsonAtomic(path, value) {
604
- mkdirSync(dirname(path), { recursive: true });
605
- const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
606
- writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
607
- renameSync(tmp, path);
608
- }
609
- function logInstalled(label, target) {
610
- p.log.success(`${label} → wired into ${target}`);
611
- }
612
- function logAlreadyWired(label, target) {
613
- p.log.info(`${label} already wired in ${target} (use --force to re-install)`);
614
- }
615
- function logBackup(target) {
616
- p.log.info(`Backup: ${target}`);
617
- }
618
-
619
- //#endregion
620
- //#region src/cli/connect/claude-code.ts
621
- const CLAUDE_DIR = join(homedir(), ".claude");
622
- const CLAUDE_JSON = join(homedir(), ".claude.json");
623
- function entryMatches$1(entry) {
624
- if (!entry || typeof entry !== "object") return false;
625
- const e = entry;
626
- if (e["command"] !== "npx") return false;
627
- return (Array.isArray(e["args"]) ? e["args"] : []).includes("@agentmemory/mcp");
628
- }
629
- const adapter$7 = {
630
- name: "claude-code",
631
- displayName: "Claude Code",
632
- docs: "https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it",
633
- protocolNote: "→ Using MCP. Hooks are also available — see docs/claude-code.md.",
634
- detect() {
635
- return existsSync(CLAUDE_DIR);
636
- },
637
- async install(opts) {
638
- const existing = readJsonSafe(CLAUDE_JSON);
639
- const next = existing ? { ...existing } : {};
640
- const servers = { ...next.mcpServers ?? {} };
641
- const alreadyHas = entryMatches$1(servers["agentmemory"]);
642
- if (alreadyHas && !opts.force) {
643
- logAlreadyWired("Claude Code", CLAUDE_JSON);
644
- return {
645
- kind: "already-wired",
646
- mutatedPath: CLAUDE_JSON
647
- };
648
- }
649
- if (opts.dryRun) {
650
- p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} mcpServers.agentmemory in ${CLAUDE_JSON}`);
651
- return {
652
- kind: "installed",
653
- mutatedPath: CLAUDE_JSON
654
- };
655
- }
656
- let backupPath;
657
- if (existsSync(CLAUDE_JSON)) {
658
- backupPath = backupFile(CLAUDE_JSON, "claude-code");
659
- logBackup(backupPath);
660
- } else {
661
- mkdirSync(CLAUDE_DIR, { recursive: true });
662
- writeFileSync(CLAUDE_JSON, "{}\n", "utf-8");
663
- }
664
- servers["agentmemory"] = AGENTMEMORY_MCP_BLOCK;
665
- next.mcpServers = servers;
666
- writeJsonAtomic(CLAUDE_JSON, next);
667
- if (!entryMatches$1(readJsonSafe(CLAUDE_JSON)?.mcpServers?.["agentmemory"])) {
668
- p.log.error(`Verification failed: ${CLAUDE_JSON} did not contain mcpServers.agentmemory after write.`);
669
- return {
670
- kind: "skipped",
671
- reason: "verification-failed"
672
- };
673
- }
674
- logInstalled("Claude Code", CLAUDE_JSON);
675
- p.log.info("Restart Claude Code (or run `/mcp` inside a session) to pick up the new server.");
676
- return {
677
- kind: "installed",
678
- mutatedPath: CLAUDE_JSON,
679
- backupPath
680
- };
681
- }
682
- };
683
-
684
- //#endregion
685
- //#region src/cli/connect/codex.ts
686
- const CODEX_DIR = join(homedir(), ".codex");
687
- const CODEX_TOML = join(CODEX_DIR, "config.toml");
688
- const TOML_BLOCK = `[mcp_servers.agentmemory]
689
- command = "npx"
690
- args = ["-y", "@agentmemory/mcp"]
691
-
692
- [mcp_servers.agentmemory.env]
693
- AGENTMEMORY_URL = "http://localhost:3111"
694
- `;
695
- const SECTION_HEADER = "[mcp_servers.agentmemory]";
696
- function isWiredText(toml) {
697
- return toml.includes(SECTION_HEADER);
698
- }
699
- function stripExistingBlock(toml) {
700
- const lines = toml.split(/\r?\n/);
701
- const out = [];
702
- let skipping = false;
703
- for (const line of lines) {
704
- const trimmed = line.trim();
705
- if (trimmed === SECTION_HEADER || trimmed === "[mcp_servers.agentmemory.env]") {
706
- skipping = true;
707
- continue;
708
- }
709
- if (skipping && trimmed.startsWith("[") && trimmed !== "[mcp_servers.agentmemory.env]") skipping = false;
710
- if (!skipping) out.push(line);
711
- }
712
- return out.join("\n").replace(/\n{3,}$/, "\n\n").trimEnd() + "\n";
713
- }
714
- const adapter$6 = {
715
- name: "codex",
716
- displayName: "Codex CLI",
717
- docs: "https://github.com/rohitg00/agentmemory#codex-cli-codex-plugin-platform",
718
- protocolNote: "→ Using MCP. Hooks are also available — see docs/codex.md.",
719
- detect() {
720
- return existsSync(CODEX_DIR);
721
- },
722
- async install(opts) {
723
- const exists = existsSync(CODEX_TOML);
724
- const current = exists ? readFileSync(CODEX_TOML, "utf-8") : "";
725
- const wired = isWiredText(current);
726
- if (wired && !opts.force) {
727
- logAlreadyWired("Codex CLI", CODEX_TOML);
728
- return {
729
- kind: "already-wired",
730
- mutatedPath: CODEX_TOML
731
- };
732
- }
733
- if (opts.dryRun) {
734
- p.log.info(`[dry-run] Would ${wired ? "rewrite" : "append"} [mcp_servers.agentmemory] in ${CODEX_TOML}`);
735
- return {
736
- kind: "installed",
737
- mutatedPath: CODEX_TOML
738
- };
739
- }
740
- let backupPath;
741
- if (exists) {
742
- backupPath = backupFile(CODEX_TOML, "codex", "toml");
743
- logBackup(backupPath);
744
- } else mkdirSync(dirname(CODEX_TOML), { recursive: true });
745
- const cleaned = wired ? stripExistingBlock(current) : current;
746
- writeFileSync(CODEX_TOML, `${cleaned}${cleaned.length === 0 || cleaned.endsWith("\n") ? "" : "\n"}${cleaned.length > 0 ? "\n" : ""}${TOML_BLOCK}`, "utf-8");
747
- if (!isWiredText(readFileSync(CODEX_TOML, "utf-8"))) {
748
- p.log.error(`Verification failed: ${CODEX_TOML} did not contain ${SECTION_HEADER} after write.`);
749
- return {
750
- kind: "skipped",
751
- reason: "verification-failed"
752
- };
753
- }
754
- logInstalled("Codex CLI", CODEX_TOML);
755
- 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 install agentmemory");
756
- return {
757
- kind: "installed",
758
- mutatedPath: CODEX_TOML,
759
- ...backupPath !== void 0 && { backupPath }
760
- };
761
- }
762
- };
763
-
764
- //#endregion
765
- //#region src/cli/connect/json-mcp-adapter.ts
766
- function entryMatches(entry) {
767
- if (!entry || typeof entry !== "object") return false;
768
- const e = entry;
769
- if (e["command"] !== "npx") return false;
770
- return (Array.isArray(e["args"]) ? e["args"] : []).includes("@agentmemory/mcp");
771
- }
772
- function createJsonMcpAdapter(config) {
773
- return {
774
- name: config.name,
775
- displayName: config.displayName,
776
- ...config.docs !== void 0 && { docs: config.docs },
777
- ...config.protocolNote !== void 0 && { protocolNote: config.protocolNote },
778
- detect() {
779
- return existsSync(config.detectDir);
780
- },
781
- async install(opts) {
782
- const existing = readJsonSafe(config.configPath);
783
- const next = existing ? { ...existing } : {};
784
- const servers = { ...next.mcpServers ?? {} };
785
- const alreadyHas = entryMatches(servers["agentmemory"]);
786
- if (alreadyHas && !opts.force) {
787
- logAlreadyWired(config.displayName, config.configPath);
788
- return {
789
- kind: "already-wired",
790
- mutatedPath: config.configPath
791
- };
792
- }
793
- if (opts.dryRun) {
794
- p.log.info(`[dry-run] Would ${alreadyHas ? "overwrite" : "add"} mcpServers.agentmemory in ${config.configPath}`);
795
- return {
796
- kind: "installed",
797
- mutatedPath: config.configPath
798
- };
799
- }
800
- let backupPath;
801
- if (existsSync(config.configPath)) {
802
- backupPath = backupFile(config.configPath, config.name);
803
- logBackup(backupPath);
804
- } else mkdirSync(dirname(config.configPath), { recursive: true });
805
- servers["agentmemory"] = AGENTMEMORY_MCP_BLOCK;
806
- next.mcpServers = servers;
807
- writeJsonAtomic(config.configPath, next);
808
- if (!entryMatches(readJsonSafe(config.configPath)?.mcpServers?.["agentmemory"])) {
809
- p.log.error(`Verification failed: ${config.configPath} did not contain mcpServers.agentmemory after write.`);
810
- return {
811
- kind: "skipped",
812
- reason: "verification-failed"
813
- };
814
- }
815
- logInstalled(config.displayName, config.configPath);
816
- return {
817
- kind: "installed",
818
- mutatedPath: config.configPath,
819
- ...backupPath !== void 0 && { backupPath }
820
- };
821
- }
822
- };
823
- }
824
-
825
- //#endregion
826
- //#region src/cli/connect/cursor.ts
827
- const adapter$5 = createJsonMcpAdapter({
828
- name: "cursor",
829
- displayName: "Cursor",
830
- detectDir: join(homedir(), ".cursor"),
831
- configPath: join(homedir(), ".cursor", "mcp.json"),
832
- docs: "https://github.com/rohitg00/agentmemory#other-agents",
833
- protocolNote: "→ Using MCP (the only protocol Cursor speaks). Memory bridge runs at :3111 underneath."
834
- });
835
-
836
- //#endregion
837
- //#region src/cli/connect/gemini-cli.ts
838
- const adapter$4 = createJsonMcpAdapter({
839
- name: "gemini-cli",
840
- displayName: "Gemini CLI",
841
- detectDir: join(homedir(), ".gemini"),
842
- configPath: join(homedir(), ".gemini", "settings.json"),
843
- docs: "https://github.com/rohitg00/agentmemory#other-agents",
844
- protocolNote: "→ Using MCP (the only protocol Gemini CLI speaks). Memory bridge runs at :3111 underneath."
845
- });
846
-
847
- //#endregion
848
- //#region src/cli/connect/hermes.ts
849
- const HERMES_DIR = join(homedir(), ".hermes");
850
- const HERMES_CONFIG = join(HERMES_DIR, "config.yaml");
851
- const DOCS$2 = "https://github.com/rohitg00/agentmemory/tree/main/integrations/hermes";
852
- const adapter$3 = {
853
- name: "hermes",
854
- displayName: "Hermes Agent",
855
- docs: DOCS$2,
856
- protocolNote: "→ Using MCP. Hooks are also available — see docs/hermes.md.",
857
- detect() {
858
- return existsSync(HERMES_DIR);
859
- },
860
- async install(_opts) {
861
- p.log.warn("Hermes uses YAML config. Automated merge isn't implemented yet — manual install required.");
862
- p.note([
863
- `Add to ${HERMES_CONFIG}:`,
864
- "",
865
- " mcp_servers:",
866
- " agentmemory:",
867
- " command: npx",
868
- " args: [\"-y\", \"@agentmemory/mcp\"]",
869
- "",
870
- " memory:",
871
- " provider: agentmemory",
872
- "",
873
- `Full guide: ${DOCS$2}`
874
- ].join("\n"), "Hermes manual install");
875
- return {
876
- kind: "stub",
877
- reason: "yaml-merge-not-implemented"
878
- };
879
- }
880
- };
881
-
882
- //#endregion
883
- //#region src/cli/connect/openclaw.ts
884
- const adapter$2 = createJsonMcpAdapter({
885
- name: "openclaw",
886
- displayName: "OpenClaw",
887
- detectDir: join(homedir(), ".openclaw"),
888
- configPath: join(homedir(), ".openclaw", "openclaw.json"),
889
- docs: "https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw",
890
- protocolNote: "→ Using MCP. Hooks are also available — see docs/openclaw.md."
891
- });
892
-
893
- //#endregion
894
- //#region src/cli/connect/openhuman.ts
895
- const OPENHUMAN_DIR = join(homedir(), ".openhuman");
896
- const DOCS$1 = "https://github.com/tinyhumansai/openhuman";
897
- const adapter$1 = {
898
- name: "openhuman",
899
- displayName: "OpenHuman",
900
- docs: DOCS$1,
901
- protocolNote: "→ Using native hooks (REST API at :3111). MCP not required.",
902
- detect() {
903
- return existsSync(OPENHUMAN_DIR);
904
- },
905
- async install(_opts) {
906
- p.log.warn("OpenHuman integration is not yet automated. No `integrations/openhuman/` folder exists in the agentmemory repo today.");
907
- p.note([
908
- "OpenHuman is a Memory-trait host. The expected wiring is the REST",
909
- "proxy at http://localhost:3111 plus an OpenHuman-side Memory trait",
910
- "impl. Once integrations/openhuman/ lands in agentmemory we'll wire",
911
- "this up automatically.",
912
- "",
913
- `Tracking: ${DOCS$1}`
914
- ].join("\n"), "OpenHuman manual install");
915
- return {
916
- kind: "stub",
917
- reason: "no-integration-folder-yet"
918
- };
919
- }
920
- };
921
-
922
- //#endregion
923
- //#region src/cli/connect/pi.ts
924
- const PI_DIR = join(homedir(), ".pi");
925
- const PI_EXT_DIR = join(PI_DIR, "agent", "extensions", "agentmemory");
926
- const DOCS = "https://github.com/rohitg00/agentmemory/tree/main/integrations/pi";
927
- const adapter = {
928
- name: "pi",
929
- displayName: "pi",
930
- docs: DOCS,
931
- protocolNote: "→ Using native hooks (REST API at :3111). MCP not required.",
932
- detect() {
933
- return existsSync(PI_DIR);
934
- },
935
- async install(_opts) {
936
- p.log.warn("pi uses a TypeScript extension file. Automated copy + register isn't implemented yet — manual install required.");
937
- p.note([
938
- "Run these from the agentmemory repo root:",
939
- "",
940
- ` mkdir -p ${PI_EXT_DIR}`,
941
- ` cp integrations/pi/index.ts ${PI_EXT_DIR}/index.ts`,
942
- ` cp integrations/pi/security.ts ${PI_EXT_DIR}/security.ts`,
943
- "",
944
- "Then add to ~/.pi/agent/settings.json:",
945
- " { \"extensions\": [\"~/.pi/agent/extensions/agentmemory\"] }",
946
- "",
947
- `Full guide: ${DOCS}`
948
- ].join("\n"), "pi manual install");
949
- return {
950
- kind: "stub",
951
- reason: "ts-extension-copy-not-implemented"
952
- };
953
- }
954
- };
955
-
956
- //#endregion
957
- //#region src/cli/connect/index.ts
958
- var connect_exports = /* @__PURE__ */ __exportAll({
959
- ADAPTERS: () => ADAPTERS,
960
- knownAgents: () => knownAgents,
961
- resolveAdapter: () => resolveAdapter,
962
- runAdapter: () => runAdapter,
963
- runConnect: () => runConnect
964
- });
965
- const ADAPTERS = [
966
- adapter$7,
967
- adapter$6,
968
- adapter$5,
969
- adapter$4,
970
- adapter$2,
971
- adapter$3,
972
- adapter,
973
- adapter$1
974
- ];
975
- function resolveAdapter(name) {
976
- const lower = name.toLowerCase();
977
- return ADAPTERS.find((a) => a.name === lower) ?? null;
978
- }
979
- function knownAgents() {
980
- return ADAPTERS.map((a) => a.name);
981
- }
982
- function parseFlags(args) {
983
- const positional = [];
984
- let dryRun = false;
985
- let force = false;
986
- let all = false;
987
- for (const a of args) if (a === "--dry-run") dryRun = true;
988
- else if (a === "--force") force = true;
989
- else if (a === "--all") all = true;
990
- else if (!a.startsWith("-")) positional.push(a);
991
- return {
992
- dryRun,
993
- force,
994
- all,
995
- positional
996
- };
997
- }
998
- async function runAdapter(adapter, opts) {
999
- if (!adapter.detect()) {
1000
- p.log.warn(`${adapter.displayName}: not detected on this machine (skipping).${adapter.docs ? ` Docs: ${adapter.docs}` : ""}`);
1001
- return {
1002
- kind: "skipped",
1003
- reason: "not-detected"
1004
- };
1005
- }
1006
- p.log.step(`Wiring ${adapter.displayName}…`);
1007
- if (adapter.protocolNote) p.log.message(adapter.protocolNote);
1008
- try {
1009
- return await adapter.install(opts);
1010
- } catch (err) {
1011
- p.log.error(`${adapter.displayName}: ${err instanceof Error ? err.message : String(err)}`);
1012
- return {
1013
- kind: "skipped",
1014
- reason: "exception"
1015
- };
1016
- }
1017
- }
1018
- async function runConnect(args) {
1019
- if (platform() === "win32") {
1020
- p.intro("agentmemory connect");
1021
- p.log.warn("Windows: automated `connect` is not supported yet. See https://github.com/rohitg00/agentmemory#other-agents for manual install steps.");
1022
- p.outro("Windows: manual install required — see docs");
1023
- return;
1024
- }
1025
- const { dryRun, force, all, positional } = parseFlags(args);
1026
- const opts = {
1027
- dryRun,
1028
- force
1029
- };
1030
- p.intro("agentmemory connect");
1031
- if (positional.length === 0 && !all) {
1032
- const detected = ADAPTERS.filter((a) => a.detect());
1033
- if (detected.length === 0) {
1034
- p.log.error("No supported agents detected on this machine.");
1035
- p.outro(`Supported: ${knownAgents().join(", ")}`);
1036
- process.exit(1);
1037
- }
1038
- const picked = await p.multiselect({
1039
- message: "Wire agentmemory into which agents?",
1040
- options: detected.map((a) => ({
1041
- value: a.name,
1042
- label: a.displayName
1043
- })),
1044
- required: true
1045
- });
1046
- if (p.isCancel(picked)) {
1047
- p.cancel("Cancelled.");
1048
- return;
1049
- }
1050
- const results = [];
1051
- for (const name of picked) {
1052
- const adapter = resolveAdapter(name);
1053
- if (!adapter) continue;
1054
- results.push({
1055
- name,
1056
- result: await runAdapter(adapter, opts)
1057
- });
1058
- }
1059
- summarize(results);
1060
- return;
1061
- }
1062
- if (all) {
1063
- const detected = ADAPTERS.filter((a) => a.detect());
1064
- if (detected.length === 0) {
1065
- p.log.error("No supported agents detected on this machine.");
1066
- process.exit(1);
1067
- }
1068
- const results = [];
1069
- for (const adapter of detected) results.push({
1070
- name: adapter.name,
1071
- result: await runAdapter(adapter, opts)
1072
- });
1073
- summarize(results);
1074
- return;
1075
- }
1076
- const agentName = positional[0];
1077
- const adapter = resolveAdapter(agentName);
1078
- if (!adapter) {
1079
- p.log.error(`Unknown agent: ${agentName}`);
1080
- p.outro(`Supported: ${knownAgents().join(", ")}`);
1081
- process.exit(1);
1082
- }
1083
- const result = await runAdapter(adapter, opts);
1084
- summarize([{
1085
- name: agentName,
1086
- result
1087
- }]);
1088
- if (result.kind === "skipped" && result.reason !== "not-detected") process.exit(1);
1089
- }
1090
- function summarize(results) {
1091
- const lines = results.map(({ name, result }) => {
1092
- switch (result.kind) {
1093
- case "installed": return ` ✓ ${name}${result.mutatedPath ? ` → ${result.mutatedPath}` : ""}`;
1094
- case "already-wired": return ` ✓ ${name} (already wired)`;
1095
- case "stub": return ` ⚠ ${name} (manual install required: ${result.reason})`;
1096
- case "skipped": return ` ✗ ${name} (skipped: ${result.reason})`;
1097
- }
1098
- });
1099
- p.note(lines.join("\n"), "summary");
1100
- const stubs = results.filter((r) => r.result.kind === "stub");
1101
- if (stubs.length > 0) p.log.info(`${stubs.length} agent(s) require manual install — see docs links above.`);
1102
- p.outro("Restart any wired agent (or open a new session) to pick up agentmemory.");
1103
- }
1104
-
1105
482
  //#endregion
1106
483
  //#region src/cli/onboarding.ts
1107
484
  const __dirname$1 = dirname(fileURLToPath(import.meta.url));
@@ -1412,51 +789,6 @@ async function wireSelectedAgents(agents) {
1412
789
  p.note(summary.join("\n"), "wire summary");
1413
790
  }
1414
791
 
1415
- //#endregion
1416
- //#region src/logger.ts
1417
- function fmt(level, msg, fields) {
1418
- if (!fields || Object.keys(fields).length === 0) return `[agentmemory] ${level} ${msg}`;
1419
- try {
1420
- return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;
1421
- } catch {
1422
- return `[agentmemory] ${level} ${msg}`;
1423
- }
1424
- }
1425
- function emit(level, msg, fields) {
1426
- try {
1427
- process.stderr.write(fmt(level, msg, fields) + "\n");
1428
- } catch {}
1429
- }
1430
- const logger = {
1431
- info(msg, fields) {
1432
- emit("info", msg, fields);
1433
- },
1434
- warn(msg, fields) {
1435
- emit("warn", msg, fields);
1436
- },
1437
- error(msg, fields) {
1438
- emit("error", msg, fields);
1439
- }
1440
- };
1441
- let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
1442
- const bootBuffer = [];
1443
- function setBootVerbose(enabled) {
1444
- bootVerbose = enabled;
1445
- }
1446
- function bootLog(msg) {
1447
- if (bootVerbose) {
1448
- try {
1449
- process.stderr.write(`[agentmemory] ${msg}\n`);
1450
- } catch {}
1451
- return;
1452
- }
1453
- if (bootBuffer.length < 500) bootBuffer.push(msg);
1454
- }
1455
-
1456
- //#endregion
1457
- //#region src/version.ts
1458
- const VERSION = "0.9.21";
1459
-
1460
792
  //#endregion
1461
793
  //#region src/cli.ts
1462
794
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -1521,7 +853,7 @@ Options:
1521
853
  --help, -h Show this help
1522
854
  --verbose, -v Show engine stderr, boot log, and diagnostic info
1523
855
  --reset Wipe ~/.agentmemory/preferences.json and re-run onboarding
1524
- --tools all|core Tool visibility (default: core = 7 tools)
856
+ --tools all|core Tool visibility (default: all = 51 tools; core = 8 essentials)
1525
857
  --no-engine Skip auto-starting iii-engine
1526
858
  --port <N> Override REST port (default: 3111)
1527
859
 
@@ -1561,9 +893,26 @@ function getBaseUrl() {
1561
893
  if (url) return url.replace(/\/+$/, "");
1562
894
  return `http://localhost:${getRestPort()}`;
1563
895
  }
896
+ let discoveredViewerPort = null;
897
+ async function discoverViewerPort() {
898
+ if (discoveredViewerPort !== null) return;
899
+ try {
900
+ const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, { signal: AbortSignal.timeout(1e3) });
901
+ if (res.ok) {
902
+ const data = await res.json();
903
+ if (typeof data.viewerPort === "number") discoveredViewerPort = data.viewerPort;
904
+ }
905
+ } catch {}
906
+ }
1564
907
  function getViewerUrl() {
1565
908
  const envUrl = process.env["AGENTMEMORY_VIEWER_URL"];
1566
909
  if (envUrl) return envUrl.replace(/\/+$/, "");
910
+ if (discoveredViewerPort !== null) try {
911
+ const u = new URL(getBaseUrl());
912
+ return `${u.protocol}//${u.hostname}:${discoveredViewerPort}`;
913
+ } catch {
914
+ return `http://localhost:${discoveredViewerPort}`;
915
+ }
1567
916
  try {
1568
917
  const u = new URL(getBaseUrl());
1569
918
  const vPort = parseInt(process.env["III_VIEWER_PORT"] || "", 10) || (parseInt(u.port || "3111", 10) || 3111) + 2;
@@ -1595,7 +944,19 @@ async function isEngineRunning() {
1595
944
  }
1596
945
  async function isAgentmemoryReady() {
1597
946
  try {
1598
- return (await fetch(`${getBaseUrl()}/agentmemory/livez`, { signal: AbortSignal.timeout(2e3) })).ok;
947
+ const res = await fetch(`${getBaseUrl()}/agentmemory/livez`, { signal: AbortSignal.timeout(2e3) });
948
+ if (!res.ok) return false;
949
+ try {
950
+ const data = await res.json();
951
+ if (typeof data.viewerPort === "number") {
952
+ discoveredViewerPort = data.viewerPort;
953
+ return true;
954
+ }
955
+ if (data.viewerSkipped) return true;
956
+ return false;
957
+ } catch {
958
+ return false;
959
+ }
1599
960
  } catch {
1600
961
  return false;
1601
962
  }
@@ -1689,6 +1050,23 @@ function clearEnginePidfile() {
1689
1050
  unlinkSync(enginePidfilePath());
1690
1051
  } catch {}
1691
1052
  }
1053
+ function workerPidfilePath() {
1054
+ return join(homedir(), ".agentmemory", "worker.pid");
1055
+ }
1056
+ function readWorkerPidfile() {
1057
+ try {
1058
+ const pidStr = readFileSync(workerPidfilePath(), "utf-8").trim();
1059
+ const pid = parseInt(pidStr, 10);
1060
+ return Number.isFinite(pid) && pid > 0 ? pid : null;
1061
+ } catch {
1062
+ return null;
1063
+ }
1064
+ }
1065
+ function clearWorkerPidfile() {
1066
+ try {
1067
+ unlinkSync(workerPidfilePath());
1068
+ } catch {}
1069
+ }
1692
1070
  function writeEngineState(state) {
1693
1071
  try {
1694
1072
  const statePath = engineStatePath();
@@ -2110,7 +1488,7 @@ async function main() {
2110
1488
  if (firstRun || IS_RESET) await runOnboarding();
2111
1489
  if (skipEngine) {
2112
1490
  if (IS_VERBOSE) p.log.info("Skipping engine check (--no-engine)");
2113
- await import("./src-D5arboxc.mjs");
1491
+ await import("./src-gpTAJuBy.mjs");
2114
1492
  if (await waitForAgentmemoryReady(15e3)) {
2115
1493
  const consoleState = await ensureIiiConsole();
2116
1494
  await maybeOfferGlobalInstall();
@@ -2122,7 +1500,7 @@ async function main() {
2122
1500
  if (IS_VERBOSE) p.log.success("iii-engine is running");
2123
1501
  warnIfEngineVersionMismatch(whichBinary("iii") ?? fallbackIiiPaths().find((p) => existsSync(p)) ?? null);
2124
1502
  adoptRunningEngine();
2125
- await import("./src-D5arboxc.mjs");
1503
+ await import("./src-gpTAJuBy.mjs");
2126
1504
  if (await waitForAgentmemoryReady(15e3)) {
2127
1505
  const consoleState = await ensureIiiConsole();
2128
1506
  await maybeOfferGlobalInstall();
@@ -2171,7 +1549,7 @@ async function main() {
2171
1549
  process.exit(1);
2172
1550
  }
2173
1551
  s.stop("iii-engine is ready");
2174
- await import("./src-D5arboxc.mjs");
1552
+ await import("./src-gpTAJuBy.mjs");
2175
1553
  if (await waitForAgentmemoryReady(15e3)) {
2176
1554
  const consoleState = await ensureIiiConsole();
2177
1555
  await maybeOfferGlobalInstall();
@@ -2209,6 +1587,7 @@ async function runStatus() {
2209
1587
  apiFetch(base, "export"),
2210
1588
  apiFetch(base, "config/flags")
2211
1589
  ]);
1590
+ if (typeof healthRes?.viewerPort === "number") discoveredViewerPort = healthRes.viewerPort;
2212
1591
  const h = healthRes?.health;
2213
1592
  const status = healthRes?.status || "unknown";
2214
1593
  const version = healthRes?.version || "?";
@@ -2328,6 +1707,7 @@ function buildDoctorEffects() {
2328
1707
  iiiBinaryVersion: (binPath) => iiiBinVersion(binPath),
2329
1708
  viewerReachable: async (timeoutMs = 2e3) => {
2330
1709
  try {
1710
+ await discoverViewerPort();
2331
1711
  return (await fetch(getViewerUrl(), { signal: AbortSignal.timeout(timeoutMs) })).ok;
2332
1712
  } catch {
2333
1713
  return false;
@@ -2877,14 +2257,14 @@ async function runUpgrade() {
2877
2257
  };
2878
2258
  if (hasPackageJson) if (!!pnpmBin && hasPnpmLock && pnpmBin) {
2879
2259
  requireSuccess(runCommand(pnpmBin, ["install"], { label: "Refreshing dependencies (pnpm install)" }), "pnpm install");
2880
- runCommand(pnpmBin, ["up", "iii-sdk@latest"], {
2881
- label: "Upgrading iii-sdk to latest",
2260
+ runCommand(pnpmBin, ["up", "iii-sdk@0.11.2"], {
2261
+ label: "Pinning iii-sdk@0.11.2",
2882
2262
  optional: true
2883
2263
  });
2884
2264
  } else if (npmBin) {
2885
2265
  requireSuccess(runCommand(npmBin, ["install"], { label: "Refreshing dependencies (npm install)" }), "npm install");
2886
- runCommand(npmBin, ["install", "iii-sdk@latest"], {
2887
- label: "Upgrading iii-sdk to latest",
2266
+ runCommand(npmBin, ["install", "iii-sdk@0.11.2"], {
2267
+ label: "Pinning iii-sdk@0.11.2",
2888
2268
  optional: true
2889
2269
  });
2890
2270
  } else p.log.warn("No package manager found (pnpm/npm). Skipping JS dependency upgrade.");
@@ -2992,6 +2372,7 @@ async function stopDockerEngine(composeFile, port) {
2992
2372
  ], { label: `docker compose -f ${composeFile} down` });
2993
2373
  clearEnginePidfile();
2994
2374
  clearEngineState();
2375
+ clearWorkerPidfile();
2995
2376
  if (!ok) {
2996
2377
  p.log.error(`docker compose down failed. The engine may still be running on :${port}. Inspect with:\n docker compose -f ${composeFile} ps`);
2997
2378
  process.exit(1);
@@ -3009,6 +2390,7 @@ async function runStop() {
3009
2390
  p.log.info(`No engine responding on port ${port}.`);
3010
2391
  clearEnginePidfile();
3011
2392
  clearEngineState();
2393
+ clearWorkerPidfile();
3012
2394
  p.outro("Nothing to stop.");
3013
2395
  return;
3014
2396
  }
@@ -3017,17 +2399,35 @@ async function runStop() {
3017
2399
  }
3018
2400
  const portPids = findEnginePidsByPort(port);
3019
2401
  const pidfilePid = readEnginePidfile();
2402
+ const workerPid = readWorkerPidfile();
3020
2403
  if (!running) {
3021
- if (portPids.length === 0 && pidfilePid === null) {
2404
+ if (portPids.length === 0 && pidfilePid === null && workerPid === null) {
3022
2405
  clearEnginePidfile();
3023
2406
  clearEngineState();
2407
+ clearWorkerPidfile();
3024
2408
  p.outro("Nothing to stop.");
3025
2409
  return;
3026
2410
  }
2411
+ if (workerPid !== null && portPids.length === 0 && pidfilePid === null) {
2412
+ const s = p.spinner();
2413
+ s.start(`Stopping orphaned agentmemory worker (pid ${workerPid})...`);
2414
+ const ok = await signalAndWait(workerPid, "SIGTERM", 3e3);
2415
+ s.stop(ok ? `Stopped worker pid ${workerPid}` : `Failed to stop worker pid ${workerPid}`);
2416
+ clearEnginePidfile();
2417
+ clearEngineState();
2418
+ clearWorkerPidfile();
2419
+ if (!ok) {
2420
+ p.log.error(`Worker pid ${workerPid} survived SIGKILL. Investigate with \`ps\`.`);
2421
+ process.exit(1);
2422
+ }
2423
+ p.outro("Stopped orphaned worker. Memories persisted to disk.");
2424
+ return;
2425
+ }
3027
2426
  const survivors = new Set(portPids);
3028
2427
  if (pidfilePid) survivors.add(pidfilePid);
2428
+ if (workerPid) survivors.add(workerPid);
3029
2429
  p.log.warn(`Engine not responding on :${port}, but ${survivors.size} process(es) still hold the port or pidfile: ${[...survivors].join(", ")}`);
3030
- p.log.info(`Preserving ~/.agentmemory/iii.pid. Investigate before manual cleanup:\n ps -p ${[...survivors].join(",")} -o pid,ppid,comm,etime\n ${IS_WINDOWS ? "netstat -ano | findstr :" + port : "lsof -i :" + port}`);
2430
+ p.log.info(`Preserving ~/.agentmemory/iii.pid + worker.pid. Investigate before manual cleanup:\n ps -p ${[...survivors].join(",")} -o pid,ppid,comm,etime\n ${IS_WINDOWS ? "netstat -ano | findstr :" + port : "lsof -i :" + port}`);
3031
2431
  process.exit(1);
3032
2432
  }
3033
2433
  if (!state) {
@@ -3041,7 +2441,9 @@ async function runStop() {
3041
2441
  const candidates = /* @__PURE__ */ new Set();
3042
2442
  if (pidfilePid) candidates.add(pidfilePid);
3043
2443
  for (const pid of portPids) candidates.add(pid);
3044
- if (candidates.size === 0) {
2444
+ const workerCandidates = /* @__PURE__ */ new Set();
2445
+ if (workerPid) workerCandidates.add(workerPid);
2446
+ if (candidates.size === 0 && workerCandidates.size === 0) {
3045
2447
  p.log.error(`Could not locate engine process. Try:\n ${IS_WINDOWS ? "netstat -ano | findstr :" + port : "lsof -i :" + port + " -t | xargs kill -9"}`);
3046
2448
  process.exit(1);
3047
2449
  }
@@ -3053,19 +2455,28 @@ async function runStop() {
3053
2455
  s.stop(ok ? `Stopped pid ${pid}` : `Failed to stop pid ${pid}`);
3054
2456
  if (!ok) allStopped = false;
3055
2457
  }
2458
+ for (const pid of workerCandidates) {
2459
+ if (candidates.has(pid)) continue;
2460
+ const s = p.spinner();
2461
+ s.start(`Stopping agentmemory worker (pid ${pid})...`);
2462
+ const ok = await signalAndWait(pid, "SIGTERM", 3e3);
2463
+ s.stop(ok ? `Stopped worker pid ${pid}` : `Failed to stop worker pid ${pid}`);
2464
+ if (!ok) allStopped = false;
2465
+ }
3056
2466
  clearEnginePidfile();
3057
2467
  clearEngineState();
2468
+ clearWorkerPidfile();
3058
2469
  if (!allStopped) {
3059
- p.log.error("One or more engine processes survived SIGKILL. Investigate with `ps`.");
2470
+ p.log.error("One or more processes survived SIGKILL. Investigate with `ps`.");
3060
2471
  process.exit(1);
3061
2472
  }
3062
2473
  p.outro("Stopped. Memories persisted to disk; restart anytime with: npx @agentmemory/agentmemory");
3063
2474
  }
3064
2475
  async function runMcp() {
3065
- await import("./standalone-C7BgzzIN.mjs");
2476
+ await import("./standalone-C4i7ktpn.mjs");
3066
2477
  }
3067
2478
  async function runConnectCmd() {
3068
- const { runConnect } = await Promise.resolve().then(() => connect_exports);
2479
+ const { runConnect } = await import("./connect-BQQXpyDS.mjs").then((n) => n.t);
3069
2480
  await runConnect(args.slice(1));
3070
2481
  }
3071
2482
  async function runImportJsonl() {
@@ -3298,5 +2709,5 @@ async function runRemove() {
3298
2709
  });
3299
2710
 
3300
2711
  //#endregion
3301
- export { STREAM as a, jaccardSimilarity as c, KV as i, bootLog as n, fingerprintId as o, logger as r, generateId as s, VERSION as t };
2712
+ export { discoverViewerPort };
3302
2713
  //# sourceMappingURL=cli.mjs.map