ziiagentmemory 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/.env.example +175 -0
  2. package/AGENTS.md +124 -0
  3. package/LICENSE +190 -0
  4. package/README.md +1546 -0
  5. package/dist/cli.d.mts +5 -0
  6. package/dist/cli.d.mts.map +1 -0
  7. package/dist/cli.mjs +2859 -0
  8. package/dist/cli.mjs.map +1 -0
  9. package/dist/config-ChC9EtgV.mjs +259 -0
  10. package/dist/config-ChC9EtgV.mjs.map +1 -0
  11. package/dist/connect-JnsJXc68.mjs +1075 -0
  12. package/dist/connect-JnsJXc68.mjs.map +1 -0
  13. package/dist/hooks/notification.d.mts +1 -0
  14. package/dist/hooks/notification.mjs +74 -0
  15. package/dist/hooks/notification.mjs.map +1 -0
  16. package/dist/hooks/post-commit.d.mts +1 -0
  17. package/dist/hooks/post-commit.mjs +101 -0
  18. package/dist/hooks/post-commit.mjs.map +1 -0
  19. package/dist/hooks/post-tool-failure.d.mts +1 -0
  20. package/dist/hooks/post-tool-failure.mjs +75 -0
  21. package/dist/hooks/post-tool-failure.mjs.map +1 -0
  22. package/dist/hooks/post-tool-use.d.mts +1 -0
  23. package/dist/hooks/post-tool-use.mjs +120 -0
  24. package/dist/hooks/post-tool-use.mjs.map +1 -0
  25. package/dist/hooks/pre-compact.d.mts +1 -0
  26. package/dist/hooks/pre-compact.mjs +78 -0
  27. package/dist/hooks/pre-compact.mjs.map +1 -0
  28. package/dist/hooks/pre-tool-use.d.mts +1 -0
  29. package/dist/hooks/pre-tool-use.mjs +84 -0
  30. package/dist/hooks/pre-tool-use.mjs.map +1 -0
  31. package/dist/hooks/prompt-submit.d.mts +1 -0
  32. package/dist/hooks/prompt-submit.mjs +67 -0
  33. package/dist/hooks/prompt-submit.mjs.map +1 -0
  34. package/dist/hooks/session-end.d.mts +1 -0
  35. package/dist/hooks/session-end.mjs +60 -0
  36. package/dist/hooks/session-end.mjs.map +1 -0
  37. package/dist/hooks/session-start.d.mts +1 -0
  38. package/dist/hooks/session-start.mjs +85 -0
  39. package/dist/hooks/session-start.mjs.map +1 -0
  40. package/dist/hooks/stop.d.mts +1 -0
  41. package/dist/hooks/stop.mjs +44 -0
  42. package/dist/hooks/stop.mjs.map +1 -0
  43. package/dist/hooks/subagent-start.d.mts +1 -0
  44. package/dist/hooks/subagent-start.mjs +73 -0
  45. package/dist/hooks/subagent-start.mjs.map +1 -0
  46. package/dist/hooks/subagent-stop.d.mts +1 -0
  47. package/dist/hooks/subagent-stop.mjs +74 -0
  48. package/dist/hooks/subagent-stop.mjs.map +1 -0
  49. package/dist/hooks/task-completed.d.mts +1 -0
  50. package/dist/hooks/task-completed.mjs +73 -0
  51. package/dist/hooks/task-completed.mjs.map +1 -0
  52. package/dist/image-refs-BKLmp_sD.mjs +34 -0
  53. package/dist/image-refs-BKLmp_sD.mjs.map +1 -0
  54. package/dist/image-refs-C2YU7BIm.mjs +34 -0
  55. package/dist/image-refs-C2YU7BIm.mjs.map +1 -0
  56. package/dist/index.d.mts +2 -0
  57. package/dist/index.mjs +22324 -0
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/keyed-mutex-DTHtcZrt.mjs +88 -0
  60. package/dist/keyed-mutex-DTHtcZrt.mjs.map +1 -0
  61. package/dist/logger-BEB7pCI9.mjs +43 -0
  62. package/dist/logger-BEB7pCI9.mjs.map +1 -0
  63. package/dist/schema-CNiCWzV9.mjs +78 -0
  64. package/dist/schema-CNiCWzV9.mjs.map +1 -0
  65. package/dist/src-Cr3pH_uH.mjs +20745 -0
  66. package/dist/src-Cr3pH_uH.mjs.map +1 -0
  67. package/dist/standalone-C6KzNkt5.mjs +700 -0
  68. package/dist/standalone-C6KzNkt5.mjs.map +1 -0
  69. package/dist/standalone.d.mts +25 -0
  70. package/dist/standalone.d.mts.map +1 -0
  71. package/dist/standalone.mjs +1867 -0
  72. package/dist/standalone.mjs.map +1 -0
  73. package/dist/tools-registry-DCt2KAWA.mjs +1145 -0
  74. package/dist/tools-registry-DCt2KAWA.mjs.map +1 -0
  75. package/docker-compose.yml +47 -0
  76. package/iii-config.docker.yaml +53 -0
  77. package/iii-config.yaml +61 -0
  78. package/package.json +99 -0
  79. package/plugin/.claude-plugin/plugin.json +13 -0
  80. package/plugin/.codex-plugin/plugin.json +15 -0
  81. package/plugin/.mcp.copilot.json +15 -0
  82. package/plugin/.mcp.json +13 -0
  83. package/plugin/hooks/hooks.codex.json +67 -0
  84. package/plugin/hooks/hooks.copilot.json +72 -0
  85. package/plugin/hooks/hooks.json +125 -0
  86. package/plugin/opencode/README.md +229 -0
  87. package/plugin/opencode/agentmemory-capture.ts +687 -0
  88. package/plugin/opencode/commands/recall.md +19 -0
  89. package/plugin/opencode/commands/remember.md +19 -0
  90. package/plugin/opencode/plugin.json +12 -0
  91. package/plugin/plugin.json +15 -0
  92. package/plugin/scripts/diagnostics.mjs +551 -0
  93. package/plugin/scripts/notification.d.mts +1 -0
  94. package/plugin/scripts/notification.mjs +74 -0
  95. package/plugin/scripts/notification.mjs.map +1 -0
  96. package/plugin/scripts/post-commit.d.mts +1 -0
  97. package/plugin/scripts/post-commit.mjs +101 -0
  98. package/plugin/scripts/post-commit.mjs.map +1 -0
  99. package/plugin/scripts/post-tool-failure.d.mts +1 -0
  100. package/plugin/scripts/post-tool-failure.mjs +75 -0
  101. package/plugin/scripts/post-tool-failure.mjs.map +1 -0
  102. package/plugin/scripts/post-tool-use.d.mts +1 -0
  103. package/plugin/scripts/post-tool-use.mjs +120 -0
  104. package/plugin/scripts/post-tool-use.mjs.map +1 -0
  105. package/plugin/scripts/pre-compact.d.mts +1 -0
  106. package/plugin/scripts/pre-compact.mjs +78 -0
  107. package/plugin/scripts/pre-compact.mjs.map +1 -0
  108. package/plugin/scripts/pre-tool-use.d.mts +1 -0
  109. package/plugin/scripts/pre-tool-use.mjs +84 -0
  110. package/plugin/scripts/pre-tool-use.mjs.map +1 -0
  111. package/plugin/scripts/prompt-submit.d.mts +1 -0
  112. package/plugin/scripts/prompt-submit.mjs +67 -0
  113. package/plugin/scripts/prompt-submit.mjs.map +1 -0
  114. package/plugin/scripts/session-end.d.mts +1 -0
  115. package/plugin/scripts/session-end.mjs +60 -0
  116. package/plugin/scripts/session-end.mjs.map +1 -0
  117. package/plugin/scripts/session-start.d.mts +1 -0
  118. package/plugin/scripts/session-start.mjs +85 -0
  119. package/plugin/scripts/session-start.mjs.map +1 -0
  120. package/plugin/scripts/stop.d.mts +1 -0
  121. package/plugin/scripts/stop.mjs +44 -0
  122. package/plugin/scripts/stop.mjs.map +1 -0
  123. package/plugin/scripts/subagent-start.d.mts +1 -0
  124. package/plugin/scripts/subagent-start.mjs +73 -0
  125. package/plugin/scripts/subagent-start.mjs.map +1 -0
  126. package/plugin/scripts/subagent-stop.d.mts +1 -0
  127. package/plugin/scripts/subagent-stop.mjs +74 -0
  128. package/plugin/scripts/subagent-stop.mjs.map +1 -0
  129. package/plugin/scripts/task-completed.d.mts +1 -0
  130. package/plugin/scripts/task-completed.mjs +73 -0
  131. package/plugin/scripts/task-completed.mjs.map +1 -0
  132. package/plugin/skills/_shared/TROUBLESHOOTING.md +38 -0
  133. package/plugin/skills/agentmemory-agents/REFERENCE.md +28 -0
  134. package/plugin/skills/agentmemory-agents/SKILL.md +34 -0
  135. package/plugin/skills/agentmemory-architecture/SKILL.md +33 -0
  136. package/plugin/skills/agentmemory-config/REFERENCE.md +42 -0
  137. package/plugin/skills/agentmemory-config/SKILL.md +37 -0
  138. package/plugin/skills/agentmemory-hooks/REFERENCE.md +20 -0
  139. package/plugin/skills/agentmemory-hooks/SKILL.md +39 -0
  140. package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +65 -0
  141. package/plugin/skills/agentmemory-mcp-tools/SKILL.md +39 -0
  142. package/plugin/skills/agentmemory-rest-api/REFERENCE.md +129 -0
  143. package/plugin/skills/agentmemory-rest-api/SKILL.md +43 -0
  144. package/plugin/skills/commit-context/EXAMPLES.md +71 -0
  145. package/plugin/skills/commit-context/SKILL.md +64 -0
  146. package/plugin/skills/commit-history/EXAMPLES.md +71 -0
  147. package/plugin/skills/commit-history/SKILL.md +62 -0
  148. package/plugin/skills/forget/EXAMPLES.md +75 -0
  149. package/plugin/skills/forget/SKILL.md +66 -0
  150. package/plugin/skills/handoff/EXAMPLES.md +56 -0
  151. package/plugin/skills/handoff/SKILL.md +68 -0
  152. package/plugin/skills/recall/EXAMPLES.md +74 -0
  153. package/plugin/skills/recall/SKILL.md +60 -0
  154. package/plugin/skills/recap/EXAMPLES.md +60 -0
  155. package/plugin/skills/recap/SKILL.md +63 -0
  156. package/plugin/skills/remember/EXAMPLES.md +67 -0
  157. package/plugin/skills/remember/SKILL.md +61 -0
  158. package/plugin/skills/session-history/EXAMPLES.md +59 -0
  159. package/plugin/skills/session-history/SKILL.md +61 -0
  160. package/plugin/skills/write-agentmemory-skill/SKILL.md +40 -0
@@ -0,0 +1,259 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import pc from "picocolors";
5
+ //#region src/config.ts
6
+ function safeParseInt(value, fallback) {
7
+ if (!value) return fallback;
8
+ const parsed = parseInt(value, 10);
9
+ return Number.isNaN(parsed) ? fallback : parsed;
10
+ }
11
+ const DATA_DIR = join(homedir(), ".agentmemory");
12
+ const ENV_FILE = join(DATA_DIR, ".env");
13
+ let warnPremiumModelShown = false;
14
+ function loadEnvFile() {
15
+ if (!existsSync(ENV_FILE)) return {};
16
+ const content = readFileSync(ENV_FILE, "utf-8");
17
+ const vars = {};
18
+ for (const line of content.split("\n")) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed || trimmed.startsWith("#")) continue;
21
+ const eqIdx = trimmed.indexOf("=");
22
+ if (eqIdx === -1) continue;
23
+ const key = trimmed.slice(0, eqIdx).trim();
24
+ let val = trimmed.slice(eqIdx + 1).trim();
25
+ const quoteChar = val[0] === "\"" || val[0] === "'" ? val[0] : "";
26
+ if (quoteChar) {
27
+ const closeIdx = val.indexOf(quoteChar, 1);
28
+ if (closeIdx !== -1) val = val.slice(1, closeIdx);
29
+ } else {
30
+ const hashIdx = val.indexOf(" #");
31
+ if (hashIdx !== -1) val = val.slice(0, hashIdx).trim();
32
+ }
33
+ vars[key] = val;
34
+ }
35
+ return vars;
36
+ }
37
+ function hasRealValue(v) {
38
+ return typeof v === "string" && v.trim().length > 0;
39
+ }
40
+ function detectProvider(env) {
41
+ const maxTokens = parseInt(env["MAX_TOKENS"] || "4096", 10);
42
+ if (hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false") return {
43
+ provider: "openai",
44
+ model: env["OPENAI_MODEL"] || "gpt-4o-mini",
45
+ maxTokens,
46
+ baseURL: env["OPENAI_BASE_URL"]
47
+ };
48
+ if (hasRealValue(env["MINIMAX_API_KEY"])) return {
49
+ provider: "minimax",
50
+ model: env["MINIMAX_MODEL"] || "MiniMax-M2.7",
51
+ maxTokens
52
+ };
53
+ if (hasRealValue(env["ANTHROPIC_API_KEY"])) return {
54
+ provider: "anthropic",
55
+ model: env["ANTHROPIC_MODEL"] || "claude-sonnet-4-20250514",
56
+ maxTokens,
57
+ baseURL: env["ANTHROPIC_BASE_URL"]
58
+ };
59
+ if (hasRealValue(env["GEMINI_API_KEY"]) || hasRealValue(env["GOOGLE_API_KEY"])) {
60
+ if (!hasRealValue(env["GEMINI_API_KEY"]) && hasRealValue(env["GOOGLE_API_KEY"])) process.stderr.write("[agentmemory] GOOGLE_API_KEY detected — treating as GEMINI_API_KEY. Set GEMINI_API_KEY in ~/.agentmemory/.env to silence this warning.\n");
61
+ return {
62
+ provider: "gemini",
63
+ model: env["GEMINI_MODEL"] || "gemini-2.5-flash",
64
+ maxTokens
65
+ };
66
+ }
67
+ if (hasRealValue(env["OPENROUTER_API_KEY"])) {
68
+ const model = env["OPENROUTER_MODEL"] || "anthropic/claude-sonnet-4-20250514";
69
+ if (!warnPremiumModelShown && /sonnet|opus|gpt-4o(?!.*mini)|gpt-4-turbo/i.test(model) && env["AGENTMEMORY_SUPPRESS_COST_WARNING"] !== "1" && env["AGENTMEMORY_SUPPRESS_COST_WARNING"] !== "true") {
70
+ warnPremiumModelShown = true;
71
+ process.stderr.write(`[agentmemory] OPENROUTER_MODEL=${model} is in the premium tier. Background compression on this model can cost $5+/day under active use. Cheaper alternatives with comparable quality for memory compression: deepseek/deepseek-v4-pro, deepseek/deepseek-chat, qwen/qwen3-coder. See README "Cost-aware model selection" for the full table. Set AGENTMEMORY_SUPPRESS_COST_WARNING=1 to silence.\n`);
72
+ }
73
+ return {
74
+ provider: "openrouter",
75
+ model,
76
+ maxTokens
77
+ };
78
+ }
79
+ if (!(env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true")) {
80
+ process.stderr.write(pc.dim("[agentmemory] No LLM provider key set — running zero-LLM (BM25 + on-device embeddings). Set ANTHROPIC_API_KEY (or GEMINI/OPENAI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env for LLM compression and summaries. Agent-SDK fallback stays off by default to avoid a Stop-hook recursion loop; opt in with AGENTMEMORY_AUTO_COMPRESS=true + AGENTMEMORY_ALLOW_AGENT_SDK=true.\n"));
81
+ return {
82
+ provider: "noop",
83
+ model: "noop",
84
+ maxTokens
85
+ };
86
+ }
87
+ process.stderr.write("[agentmemory] WARNING: agent-sdk fallback enabled via AGENTMEMORY_ALLOW_AGENT_SDK=true. This spawns @anthropic-ai/claude-agent-sdk child sessions that can trigger the Stop-hook recursion loop. A SDK-child env marker is set to block re-entry, but prefer setting a real API key in ~/.agentmemory/.env instead.\n");
88
+ return {
89
+ provider: "agent-sdk",
90
+ model: "claude-sonnet-4-20250514",
91
+ maxTokens
92
+ };
93
+ }
94
+ function loadConfig() {
95
+ const env = getMergedEnv();
96
+ const provider = detectProvider(env);
97
+ const restPort = parseInt(env["III_REST_PORT"] || "3111", 10) || 3111;
98
+ const streamsPort = parseInt(env["III_STREAM_PORT"] || env["III_STREAMS_PORT"] || "", 10) || restPort + 1;
99
+ return {
100
+ engineUrl: env["III_ENGINE_URL"] || `ws://localhost:${parseInt(env["III_ENGINE_PORT"] || "", 10) || restPort + 46023}`,
101
+ restPort,
102
+ streamsPort,
103
+ provider,
104
+ tokenBudget: safeParseInt(env["TOKEN_BUDGET"], 2e3),
105
+ maxObservationsPerSession: safeParseInt(env["MAX_OBS_PER_SESSION"], 500),
106
+ compressionModel: provider.model,
107
+ dataDir: DATA_DIR
108
+ };
109
+ }
110
+ function getMergedEnv(overrides) {
111
+ return {
112
+ ...loadEnvFile(),
113
+ ...process.env,
114
+ ...overrides
115
+ };
116
+ }
117
+ function getEnvVar(key) {
118
+ return getMergedEnv()[key];
119
+ }
120
+ function isDropStaleIndexEnabled() {
121
+ return getMergedEnv()["AGENTMEMORY_DROP_STALE_INDEX"] === "true";
122
+ }
123
+ function detectLlmProviderKind() {
124
+ const env = getMergedEnv();
125
+ if (hasRealValue(env["ANTHROPIC_API_KEY"]) || hasRealValue(env["GEMINI_API_KEY"]) || hasRealValue(env["GOOGLE_API_KEY"]) || hasRealValue(env["OPENROUTER_API_KEY"]) || hasRealValue(env["MINIMAX_API_KEY"]) || hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false") return "llm";
126
+ return "noop";
127
+ }
128
+ function loadEmbeddingConfig() {
129
+ const env = getMergedEnv();
130
+ let bm25Weight = parseFloat(env["BM25_WEIGHT"] || "0.4");
131
+ let vectorWeight = parseFloat(env["VECTOR_WEIGHT"] || "0.6");
132
+ bm25Weight = isNaN(bm25Weight) || bm25Weight < 0 ? .4 : Math.min(bm25Weight, 1);
133
+ vectorWeight = isNaN(vectorWeight) || vectorWeight < 0 ? .6 : Math.min(vectorWeight, 1);
134
+ return {
135
+ provider: env["EMBEDDING_PROVIDER"] || void 0,
136
+ bm25Weight,
137
+ vectorWeight
138
+ };
139
+ }
140
+ function detectEmbeddingProvider(env) {
141
+ const source = env ?? getMergedEnv();
142
+ const forced = source["EMBEDDING_PROVIDER"];
143
+ if (forced) return forced;
144
+ if (source["GEMINI_API_KEY"]) return "gemini";
145
+ if (source["OPENAI_API_KEY"]) return "openai";
146
+ if (source["VOYAGE_API_KEY"]) return "voyage";
147
+ if (source["COHERE_API_KEY"]) return "cohere";
148
+ if (source["OPENROUTER_API_KEY"]) return "openrouter";
149
+ return null;
150
+ }
151
+ function loadClaudeBridgeConfig() {
152
+ const env = getMergedEnv();
153
+ const enabled = env["CLAUDE_MEMORY_BRIDGE"] === "true";
154
+ const projectPath = env["CLAUDE_PROJECT_PATH"] || "";
155
+ const lineBudget = safeParseInt(env["CLAUDE_MEMORY_LINE_BUDGET"], 200);
156
+ let memoryFilePath = "";
157
+ if (enabled && projectPath) {
158
+ const safePath = projectPath.replace(/[/\\]/g, "-");
159
+ memoryFilePath = join(homedir(), ".claude", "projects", safePath, "MEMORY.md");
160
+ }
161
+ return {
162
+ enabled,
163
+ projectPath,
164
+ memoryFilePath,
165
+ lineBudget
166
+ };
167
+ }
168
+ function loadTeamConfig() {
169
+ const env = getMergedEnv();
170
+ const teamId = env["TEAM_ID"];
171
+ const userId = env["USER_ID"];
172
+ if (!teamId || !userId) return null;
173
+ return {
174
+ teamId,
175
+ userId,
176
+ mode: env["TEAM_MODE"] === "shared" ? "shared" : "private"
177
+ };
178
+ }
179
+ function loadAgentScope() {
180
+ const env = getMergedEnv();
181
+ const raw = env["AGENT_ID"];
182
+ if (!raw) return null;
183
+ const agentId = raw.trim().slice(0, 128);
184
+ if (!agentId) return null;
185
+ return {
186
+ agentId,
187
+ mode: env["AGENTMEMORY_AGENT_SCOPE"] === "isolated" ? "isolated" : "shared"
188
+ };
189
+ }
190
+ function getAgentId() {
191
+ return loadAgentScope()?.agentId;
192
+ }
193
+ function isAgentScopeIsolated() {
194
+ return loadAgentScope()?.mode === "isolated";
195
+ }
196
+ function loadSnapshotConfig() {
197
+ const env = getMergedEnv();
198
+ return {
199
+ enabled: env["SNAPSHOT_ENABLED"] === "true",
200
+ interval: safeParseInt(env["SNAPSHOT_INTERVAL"], 3600),
201
+ dir: env["SNAPSHOT_DIR"] || join(homedir(), ".agentmemory", "snapshots")
202
+ };
203
+ }
204
+ function isGraphExtractionEnabled() {
205
+ return getMergedEnv()["GRAPH_EXTRACTION_ENABLED"] === "true";
206
+ }
207
+ const FOLLOWUP_WINDOW_DEFAULT_SECONDS = 30;
208
+ function getFollowupWindowSeconds() {
209
+ return safeParseInt(getMergedEnv()["AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS"], FOLLOWUP_WINDOW_DEFAULT_SECONDS);
210
+ }
211
+ function isConsolidationEnabled() {
212
+ const env = getMergedEnv();
213
+ const explicit = env["CONSOLIDATION_ENABLED"];
214
+ if (explicit === "false" || explicit === "0") return false;
215
+ if (explicit === "true" || explicit === "1") return true;
216
+ return hasLLMProviderConfigured(env);
217
+ }
218
+ function hasLLMProviderConfigured(env) {
219
+ const provider = (env["AGENTMEMORY_PROVIDER"] || "").toLowerCase();
220
+ if (provider === "noop") return false;
221
+ const openaiKeyForLlm = env["OPENAI_API_KEY"] && (env["OPENAI_API_KEY_FOR_LLM"] || "").toLowerCase() !== "false";
222
+ return Boolean(env["ANTHROPIC_API_KEY"] || openaiKeyForLlm || env["OPENROUTER_API_KEY"] || env["GEMINI_API_KEY"] || env["GOOGLE_API_KEY"] || env["MINIMAX_API_KEY"] || env["OPENAI_BASE_URL"] || provider === "agent-sdk");
223
+ }
224
+ function isAutoCompressEnabled() {
225
+ return getMergedEnv()["AGENTMEMORY_AUTO_COMPRESS"] === "true";
226
+ }
227
+ function isContextInjectionEnabled() {
228
+ return getMergedEnv()["AGENTMEMORY_INJECT_CONTEXT"] === "true";
229
+ }
230
+ function getConsolidationDecayDays() {
231
+ return safeParseInt(getMergedEnv()["CONSOLIDATION_DECAY_DAYS"], 30);
232
+ }
233
+ function getStandalonePersistPath() {
234
+ return getMergedEnv()["STANDALONE_PERSIST_PATH"] || join(homedir(), ".agentmemory", "standalone.json");
235
+ }
236
+ const VALID_PROVIDERS = new Set([
237
+ "anthropic",
238
+ "gemini",
239
+ "openrouter",
240
+ "agent-sdk",
241
+ "minimax",
242
+ "openai"
243
+ ]);
244
+ function loadFallbackConfig() {
245
+ const env = getMergedEnv();
246
+ const raw = env["FALLBACK_PROVIDERS"] || "";
247
+ const allowAgentSdk = env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true";
248
+ return { providers: raw.split(",").map((p) => p.trim()).filter((p) => Boolean(p) && VALID_PROVIDERS.has(p)).filter((p) => {
249
+ if (p === "agent-sdk" && !allowAgentSdk) {
250
+ process.stderr.write("[agentmemory] Ignoring FALLBACK_PROVIDERS entry 'agent-sdk' (AGENTMEMORY_ALLOW_AGENT_SDK is not 'true'). The agent-sdk fallback can spawn Claude Agent SDK child sessions that trigger the Stop-hook recursion loop. Opt in explicitly with AGENTMEMORY_ALLOW_AGENT_SDK=true if this is intentional.\n");
251
+ return false;
252
+ }
253
+ return true;
254
+ }) };
255
+ }
256
+ //#endregion
257
+ export { loadFallbackConfig as _, getEnvVar as a, isAgentScopeIsolated as c, isContextInjectionEnabled as d, isDropStaleIndexEnabled as f, loadEmbeddingConfig as g, loadConfig as h, getConsolidationDecayDays as i, isAutoCompressEnabled as l, loadClaudeBridgeConfig as m, detectLlmProviderKind as n, getFollowupWindowSeconds as o, isGraphExtractionEnabled as p, getAgentId as r, getStandalonePersistPath as s, detectEmbeddingProvider as t, isConsolidationEnabled as u, loadSnapshotConfig as v, loadTeamConfig as y };
258
+
259
+ //# sourceMappingURL=config-ChC9EtgV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-ChC9EtgV.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\nimport { homedir } from \"node:os\";\r\nimport pc from \"picocolors\";\r\nimport type {\r\n AgentMemoryConfig,\r\n ProviderConfig,\r\n EmbeddingConfig,\r\n FallbackConfig,\r\n ClaudeBridgeConfig,\r\n TeamConfig,\r\n} from \"./types.js\";\r\n\r\nfunction safeParseInt(value: string | undefined, fallback: number): number {\r\n if (!value) return fallback;\r\n const parsed = parseInt(value, 10);\r\n return Number.isNaN(parsed) ? fallback : parsed;\r\n}\r\n\r\nconst DATA_DIR = join(homedir(), \".agentmemory\");\r\nconst ENV_FILE = join(DATA_DIR, \".env\");\r\n\r\nlet warnPremiumModelShown = false;\r\n\r\nfunction loadEnvFile(): Record<string, string> {\r\n if (!existsSync(ENV_FILE)) return {};\r\n const content = readFileSync(ENV_FILE, \"utf-8\");\r\n const vars: Record<string, string> = {};\r\n for (const line of content.split(\"\\n\")) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\r\n const eqIdx = trimmed.indexOf(\"=\");\r\n if (eqIdx === -1) continue;\r\n const key = trimmed.slice(0, eqIdx).trim();\r\n let val = trimmed.slice(eqIdx + 1).trim();\r\n const quoteChar = val[0] === '\"' || val[0] === \"'\" ? val[0] : \"\";\r\n if (quoteChar) {\r\n const closeIdx = val.indexOf(quoteChar, 1);\r\n if (closeIdx !== -1) val = val.slice(1, closeIdx);\r\n } else {\r\n const hashIdx = val.indexOf(\" #\");\r\n if (hashIdx !== -1) val = val.slice(0, hashIdx).trim();\r\n }\r\n vars[key] = val;\r\n }\r\n return vars;\r\n}\r\n\r\nfunction hasRealValue(v: string | undefined): v is string {\r\n return typeof v === \"string\" && v.trim().length > 0;\r\n}\r\n\r\nfunction detectProvider(env: Record<string, string>): ProviderConfig {\r\n const maxTokens = parseInt(env[\"MAX_TOKENS\"] || \"4096\", 10);\r\n\r\n // OpenAI-compatible: supports OpenAI, DeepSeek, SiliconFlow, Azure, vLLM, LM Studio\r\n if (hasRealValue(env[\"OPENAI_API_KEY\"]) && env[\"OPENAI_API_KEY_FOR_LLM\"] !== \"false\") {\r\n return {\r\n provider: \"openai\",\r\n model: env[\"OPENAI_MODEL\"] || \"gpt-4o-mini\",\r\n maxTokens,\r\n baseURL: env[\"OPENAI_BASE_URL\"],\r\n };\r\n }\r\n\r\n // MiniMax: Anthropic-compatible API, requires raw fetch to avoid SDK stainless headers\r\n if (hasRealValue(env[\"MINIMAX_API_KEY\"])) {\r\n return {\r\n provider: \"minimax\",\r\n model: env[\"MINIMAX_MODEL\"] || \"MiniMax-M2.7\",\r\n maxTokens,\r\n };\r\n }\r\n\r\n if (hasRealValue(env[\"ANTHROPIC_API_KEY\"])) {\r\n return {\r\n provider: \"anthropic\",\r\n model: env[\"ANTHROPIC_MODEL\"] || \"claude-sonnet-4-20250514\",\r\n maxTokens,\r\n baseURL: env[\"ANTHROPIC_BASE_URL\"],\r\n };\r\n }\r\n if (hasRealValue(env[\"GEMINI_API_KEY\"]) || hasRealValue(env[\"GOOGLE_API_KEY\"])) {\r\n if (!hasRealValue(env[\"GEMINI_API_KEY\"]) && hasRealValue(env[\"GOOGLE_API_KEY\"])) {\r\n process.stderr.write(\r\n \"[agentmemory] GOOGLE_API_KEY detected — treating as GEMINI_API_KEY. \" +\r\n \"Set GEMINI_API_KEY in ~/.agentmemory/.env to silence this warning.\\n\",\r\n );\r\n }\r\n return {\r\n provider: \"gemini\",\r\n model: env[\"GEMINI_MODEL\"] || \"gemini-2.5-flash\",\r\n maxTokens,\r\n };\r\n }\r\n if (hasRealValue(env[\"OPENROUTER_API_KEY\"])) {\r\n const model =\r\n env[\"OPENROUTER_MODEL\"] || \"anthropic/claude-sonnet-4-20250514\";\r\n // warn when the configured OpenRouter model is in the\r\n // premium tier and likely to burn money on background compression.\r\n // Captured workload data shows ~$5/35h on claude-sonnet-4 vs\r\n // ~$0.46/35h on deepseek-v4-pro for the same compression mix.\r\n // Heuristic match avoids hard-coding a pricing table.\r\n if (\r\n !warnPremiumModelShown &&\r\n /sonnet|opus|gpt-4o(?!.*mini)|gpt-4-turbo/i.test(model) &&\r\n env[\"AGENTMEMORY_SUPPRESS_COST_WARNING\"] !== \"1\" &&\r\n env[\"AGENTMEMORY_SUPPRESS_COST_WARNING\"] !== \"true\"\r\n ) {\r\n warnPremiumModelShown = true;\r\n process.stderr.write(\r\n `[agentmemory] OPENROUTER_MODEL=${model} is in the premium tier. ` +\r\n `Background compression on this model can cost $5+/day under active use. ` +\r\n `Cheaper alternatives with comparable quality for memory compression: ` +\r\n `deepseek/deepseek-v4-pro, deepseek/deepseek-chat, qwen/qwen3-coder. ` +\r\n `See README \"Cost-aware model selection\" for the full table. ` +\r\n `Set AGENTMEMORY_SUPPRESS_COST_WARNING=1 to silence.\\n`,\r\n );\r\n }\r\n return {\r\n provider: \"openrouter\",\r\n model,\r\n maxTokens,\r\n };\r\n }\r\n\r\n const allowAgentSdk = env[\"AGENTMEMORY_ALLOW_AGENT_SDK\"] === \"true\";\r\n if (!allowAgentSdk) {\r\n process.stderr.write(\r\n pc.dim(\r\n \"[agentmemory] No LLM provider key set — running zero-LLM (BM25 + on-device embeddings). \" +\r\n \"Set ANTHROPIC_API_KEY (or GEMINI/OPENAI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env for LLM compression and summaries. \" +\r\n \"Agent-SDK fallback stays off by default to avoid a Stop-hook recursion loop; opt in with AGENTMEMORY_AUTO_COMPRESS=true + AGENTMEMORY_ALLOW_AGENT_SDK=true.\\n\",\r\n ),\r\n );\r\n return {\r\n provider: \"noop\",\r\n model: \"noop\",\r\n maxTokens,\r\n };\r\n }\r\n\r\n process.stderr.write(\r\n \"[agentmemory] WARNING: agent-sdk fallback enabled via AGENTMEMORY_ALLOW_AGENT_SDK=true. \" +\r\n \"This spawns @anthropic-ai/claude-agent-sdk child sessions that can trigger the Stop-hook \" +\r\n \"recursion loop. A SDK-child env marker is set to block re-entry, \" +\r\n \"but prefer setting a real API key in ~/.agentmemory/.env instead.\\n\",\r\n );\r\n return {\r\n provider: \"agent-sdk\",\r\n model: \"claude-sonnet-4-20250514\",\r\n maxTokens,\r\n };\r\n}\r\n\r\nexport function loadConfig(): AgentMemoryConfig {\r\n const env = getMergedEnv();\r\n\r\n const provider = detectProvider(env);\r\n\r\n // Port quartet: REST is the anchor; streams/engine derive from it\r\n // unless individually overridden. Default anchor 3111 yields the\r\n // canonical 3112 streams / 49134 engine pair, but `III_REST_PORT=3211`\r\n // auto-picks 3212 + 49234 so a second instance doesn't collide.\r\n const restPort = parseInt(env[\"III_REST_PORT\"] || \"3111\", 10) || 3111;\r\n const streamsPort =\r\n parseInt(env[\"III_STREAM_PORT\"] || env[\"III_STREAMS_PORT\"] || \"\", 10) ||\r\n restPort + 1;\r\n const engineUrl =\r\n env[\"III_ENGINE_URL\"] ||\r\n `ws://localhost:${\r\n parseInt(env[\"III_ENGINE_PORT\"] || \"\", 10) || restPort + 46023\r\n }`;\r\n\r\n return {\r\n engineUrl,\r\n restPort,\r\n streamsPort,\r\n provider,\r\n tokenBudget: safeParseInt(env[\"TOKEN_BUDGET\"], 2000),\r\n maxObservationsPerSession: safeParseInt(env[\"MAX_OBS_PER_SESSION\"], 500),\r\n compressionModel: provider.model,\r\n dataDir: DATA_DIR,\r\n };\r\n}\r\n\r\nfunction getMergedEnv(\r\n overrides?: Record<string, string>,\r\n): Record<string, string> {\r\n const fileEnv = loadEnvFile();\r\n return { ...fileEnv, ...process.env, ...overrides } as Record<string, string>;\r\n}\r\n\r\nexport function getEnvVar(key: string): string | undefined {\r\n return getMergedEnv()[key];\r\n}\r\n\r\nexport function isDropStaleIndexEnabled(): boolean {\r\n return getMergedEnv()[\"AGENTMEMORY_DROP_STALE_INDEX\"] === \"true\";\r\n}\r\n\r\nexport function detectLlmProviderKind(): \"llm\" | \"noop\" {\r\n const env = getMergedEnv();\r\n if (\r\n hasRealValue(env[\"ANTHROPIC_API_KEY\"]) ||\r\n hasRealValue(env[\"GEMINI_API_KEY\"]) ||\r\n hasRealValue(env[\"GOOGLE_API_KEY\"]) ||\r\n hasRealValue(env[\"OPENROUTER_API_KEY\"]) ||\r\n hasRealValue(env[\"MINIMAX_API_KEY\"]) ||\r\n (hasRealValue(env[\"OPENAI_API_KEY\"]) &&\r\n env[\"OPENAI_API_KEY_FOR_LLM\"] !== \"false\")\r\n ) {\r\n return \"llm\";\r\n }\r\n return \"noop\";\r\n}\r\n\r\nexport function loadEmbeddingConfig(): EmbeddingConfig {\r\n const env = getMergedEnv();\r\n let bm25Weight = parseFloat(env[\"BM25_WEIGHT\"] || \"0.4\");\r\n let vectorWeight = parseFloat(env[\"VECTOR_WEIGHT\"] || \"0.6\");\r\n bm25Weight =\r\n isNaN(bm25Weight) || bm25Weight < 0 ? 0.4 : Math.min(bm25Weight, 1);\r\n vectorWeight =\r\n isNaN(vectorWeight) || vectorWeight < 0 ? 0.6 : Math.min(vectorWeight, 1);\r\n return {\r\n provider: env[\"EMBEDDING_PROVIDER\"] || undefined,\r\n bm25Weight,\r\n vectorWeight,\r\n };\r\n}\r\n\r\nexport function detectEmbeddingProvider(\r\n env?: Record<string, string>,\r\n): string | null {\r\n const source = env ?? getMergedEnv();\r\n const forced = source[\"EMBEDDING_PROVIDER\"];\r\n if (forced) return forced;\r\n\r\n if (source[\"GEMINI_API_KEY\"]) return \"gemini\";\r\n if (source[\"OPENAI_API_KEY\"]) return \"openai\";\r\n if (source[\"VOYAGE_API_KEY\"]) return \"voyage\";\r\n if (source[\"COHERE_API_KEY\"]) return \"cohere\";\r\n if (source[\"OPENROUTER_API_KEY\"]) return \"openrouter\";\r\n return null;\r\n}\r\n\r\nexport function loadClaudeBridgeConfig(): ClaudeBridgeConfig {\r\n const env = getMergedEnv();\r\n const enabled = env[\"CLAUDE_MEMORY_BRIDGE\"] === \"true\";\r\n const projectPath = env[\"CLAUDE_PROJECT_PATH\"] || \"\";\r\n const lineBudget = safeParseInt(env[\"CLAUDE_MEMORY_LINE_BUDGET\"], 200);\r\n let memoryFilePath = \"\";\r\n if (enabled && projectPath) {\r\n // Claude Code stores MEMORY.md at\r\n // ~/.claude/projects/<slug>/MEMORY.md\r\n // where <slug> is the project path with `/` and `\\` swapped for `-`.\r\n // The leading `-` from an absolute POSIX path is preserved (Claude\r\n // Code keeps it; stripping it produced a slug Claude never reads).\r\n // There's also no `memory/` subdirectory — the file sits directly\r\n // under the slug dir.\r\n const safePath = projectPath.replace(/[/\\\\]/g, \"-\");\r\n memoryFilePath = join(\r\n homedir(),\r\n \".claude\",\r\n \"projects\",\r\n safePath,\r\n \"MEMORY.md\",\r\n );\r\n }\r\n return { enabled, projectPath, memoryFilePath, lineBudget };\r\n}\r\n\r\nexport function loadTeamConfig(): TeamConfig | null {\r\n const env = getMergedEnv();\r\n const teamId = env[\"TEAM_ID\"];\r\n const userId = env[\"USER_ID\"];\r\n if (!teamId || !userId) return null;\r\n const mode = env[\"TEAM_MODE\"] === \"shared\" ? \"shared\" : \"private\";\r\n return { teamId, userId, mode };\r\n}\r\n\r\n// optional AGENT_ID env for multi-agent memory isolation.\r\n// Returns null when unset so memory stays unscoped (legacy behavior).\r\n// Trimmed + length-capped to keep KV writes well-formed.\r\n//\r\n// Filtering is gated by AGENTMEMORY_AGENT_SCOPE:\r\n// \"shared\" (default) — tag everything, do not filter recall paths\r\n// \"isolated\" — tag everything AND filter recall paths\r\nexport function loadAgentScope(): {\r\n agentId: string;\r\n mode: \"shared\" | \"isolated\";\r\n} | null {\r\n const env = getMergedEnv();\r\n const raw = env[\"AGENT_ID\"];\r\n if (!raw) return null;\r\n const agentId = raw.trim().slice(0, 128);\r\n if (!agentId) return null;\r\n const mode = env[\"AGENTMEMORY_AGENT_SCOPE\"] === \"isolated\"\r\n ? \"isolated\"\r\n : \"shared\";\r\n return { agentId, mode };\r\n}\r\n\r\nexport function getAgentId(): string | undefined {\r\n return loadAgentScope()?.agentId;\r\n}\r\n\r\n// True only when AGENT_ID is set AND scope=isolated. Recall paths\r\n// consult this to decide whether to filter.\r\nexport function isAgentScopeIsolated(): boolean {\r\n return loadAgentScope()?.mode === \"isolated\";\r\n}\r\n\r\nexport function loadSnapshotConfig(): {\r\n enabled: boolean;\r\n interval: number;\r\n dir: string;\r\n} {\r\n const env = getMergedEnv();\r\n return {\r\n enabled: env[\"SNAPSHOT_ENABLED\"] === \"true\",\r\n interval: safeParseInt(env[\"SNAPSHOT_INTERVAL\"], 3600),\r\n dir: env[\"SNAPSHOT_DIR\"] || join(homedir(), \".agentmemory\", \"snapshots\"),\r\n };\r\n}\r\n\r\nexport function isGraphExtractionEnabled(): boolean {\r\n return getMergedEnv()[\"GRAPH_EXTRACTION_ENABLED\"] === \"true\";\r\n}\r\n\r\nexport function getGraphBatchSize(): number {\r\n return safeParseInt(getMergedEnv()[\"GRAPH_EXTRACTION_BATCH_SIZE\"], 10);\r\n}\r\n\r\n// window for the smart-search followup-rate diagnostic. A second\r\n// search arriving within this many seconds (with disjoint results)\r\n// counts as a \"follow-up\" — a directional signal that the first result\r\n// set didn't satisfy. Long values overcount (legitimate refinement\r\n// looks like a follow-up); short values undercount.\r\nconst FOLLOWUP_WINDOW_DEFAULT_SECONDS = 30;\r\n\r\nexport function getFollowupWindowSeconds(): number {\r\n return safeParseInt(\r\n getMergedEnv()[\"AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS\"],\r\n FOLLOWUP_WINDOW_DEFAULT_SECONDS,\r\n );\r\n}\r\n\r\nexport function isConsolidationEnabled(): boolean {\r\n const env = getMergedEnv();\r\n const explicit = env[\"CONSOLIDATION_ENABLED\"];\r\n if (explicit === \"false\" || explicit === \"0\") return false;\r\n if (explicit === \"true\" || explicit === \"1\") return true;\r\n return hasLLMProviderConfigured(env);\r\n}\r\n\r\nfunction hasLLMProviderConfigured(env: Record<string, string | undefined>): boolean {\r\n const provider = (env[\"AGENTMEMORY_PROVIDER\"] || \"\").toLowerCase();\r\n if (provider === \"noop\") return false;\r\n const openaiKeyForLlm =\r\n env[\"OPENAI_API_KEY\"] &&\r\n (env[\"OPENAI_API_KEY_FOR_LLM\"] || \"\").toLowerCase() !== \"false\";\r\n return Boolean(\r\n env[\"ANTHROPIC_API_KEY\"] ||\r\n openaiKeyForLlm ||\r\n env[\"OPENROUTER_API_KEY\"] ||\r\n env[\"GEMINI_API_KEY\"] ||\r\n env[\"GOOGLE_API_KEY\"] ||\r\n env[\"MINIMAX_API_KEY\"] ||\r\n env[\"OPENAI_BASE_URL\"] ||\r\n provider === \"agent-sdk\",\r\n );\r\n}\r\n\r\n// Per-observation LLM compression is OFF by default as of 0.8.8.\r\n// When disabled, observations are captured and indexed via a synthetic\r\n// (zero-LLM) compression path so recall/search still works. Users who want\r\n// richer LLM-generated summaries can set AGENTMEMORY_AUTO_COMPRESS=true in\r\n// ~/.agentmemory/.env — but should expect their Claude API token usage to\r\n// climb proportionally with session tool-use frequency.\r\nexport function isAutoCompressEnabled(): boolean {\r\n return getMergedEnv()[\"AGENTMEMORY_AUTO_COMPRESS\"] === \"true\";\r\n}\r\n\r\n// Hook-level context injection into Claude Code's conversation is OFF by\r\n// default as of 0.8.10. When disabled, pre-tool-use and\r\n// session-start hooks still POST observations for background capture, but\r\n// never write context to stdout — so Claude Code doesn't inject an extra\r\n// ~4000-char blob into every tool turn. 0.8.8 stopped the agentmemory-side\r\n// Claude calls (via ANTHROPIC_API_KEY); this stops the Claude Code-side\r\n// token burn where every tool call silently grew the model input window.\r\n// Users who want the in-conversation context injection explicitly opt in\r\n// with AGENTMEMORY_INJECT_CONTEXT=true and get a loud startup warning.\r\nexport function isContextInjectionEnabled(): boolean {\r\n return getMergedEnv()[\"AGENTMEMORY_INJECT_CONTEXT\"] === \"true\";\r\n}\r\n\r\nexport function getConsolidationDecayDays(): number {\r\n return safeParseInt(getMergedEnv()[\"CONSOLIDATION_DECAY_DAYS\"], 30);\r\n}\r\n\r\nexport function isStandaloneMcp(): boolean {\r\n return getMergedEnv()[\"STANDALONE_MCP\"] === \"true\";\r\n}\r\n\r\nexport function getStandalonePersistPath(): string {\r\n const env = getMergedEnv();\r\n return (\r\n env[\"STANDALONE_PERSIST_PATH\"] ||\r\n join(homedir(), \".agentmemory\", \"standalone.json\")\r\n );\r\n}\r\n\r\nconst VALID_PROVIDERS = new Set([\r\n \"anthropic\",\r\n \"gemini\",\r\n \"openrouter\",\r\n \"agent-sdk\",\r\n \"minimax\",\r\n \"openai\",\r\n]);\r\n\r\nexport function loadFallbackConfig(): FallbackConfig {\r\n const env = getMergedEnv();\r\n const raw = env[\"FALLBACK_PROVIDERS\"] || \"\";\r\n const allowAgentSdk = env[\"AGENTMEMORY_ALLOW_AGENT_SDK\"] === \"true\";\r\n const providers = raw\r\n .split(\",\")\r\n .map((p) => p.trim())\r\n .filter(\r\n (p): p is FallbackConfig[\"providers\"][number] =>\r\n Boolean(p) && VALID_PROVIDERS.has(p),\r\n )\r\n .filter((p) => {\r\n // Honor the same safety gate as detectProvider: agent-sdk is only\r\n // permitted as a fallback target when the user has explicitly opted\r\n // in. Without this filter, a user could set FALLBACK_PROVIDERS=agent-sdk\r\n // and re-introduce the Stop-hook recursion loop even though\r\n // detectProvider() returned the noop provider.\r\n if (p === \"agent-sdk\" && !allowAgentSdk) {\r\n process.stderr.write(\r\n \"[agentmemory] Ignoring FALLBACK_PROVIDERS entry 'agent-sdk' \" +\r\n \"(AGENTMEMORY_ALLOW_AGENT_SDK is not 'true'). The agent-sdk \" +\r\n \"fallback can spawn Claude Agent SDK child sessions that trigger \" +\r\n \"the Stop-hook recursion loop. Opt in explicitly \" +\r\n \"with AGENTMEMORY_ALLOW_AGENT_SDK=true if this is intentional.\\n\",\r\n );\r\n return false;\r\n }\r\n return true;\r\n });\r\n return { providers };\r\n}\r\n"],"mappings":"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"}