@agentmemory/agentmemory 0.9.16 → 0.9.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -5
- package/README.md +27 -6
- package/dist/cli.mjs +5 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +155 -6
- package/dist/index.mjs.map +1 -1
- package/dist/{src-3Oy_OOlF.mjs → src-TiNuQ3Ub.mjs} +146 -4
- package/dist/src-TiNuQ3Ub.mjs.map +1 -0
- package/dist/{standalone-BQOaGF4z.mjs → standalone-BIXq6S80.mjs} +3 -3
- package/dist/standalone-BIXq6S80.mjs.map +1 -0
- package/dist/standalone.mjs +2 -2
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-BF0pgZmI.mjs → tools-registry-BFKFKmYh.mjs} +11 -4
- package/dist/tools-registry-BFKFKmYh.mjs.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/dist/src-3Oy_OOlF.mjs.map +0 -1
- package/dist/standalone-BQOaGF4z.mjs.map +0 -1
- package/dist/tools-registry-BF0pgZmI.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -68,6 +68,12 @@ function hasRealValue(v) {
|
|
|
68
68
|
}
|
|
69
69
|
function detectProvider(env) {
|
|
70
70
|
const maxTokens = parseInt(env["MAX_TOKENS"] || "4096", 10);
|
|
71
|
+
if (hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false") return {
|
|
72
|
+
provider: "openai",
|
|
73
|
+
model: env["OPENAI_MODEL"] || "gpt-4o-mini",
|
|
74
|
+
maxTokens,
|
|
75
|
+
baseURL: env["OPENAI_BASE_URL"]
|
|
76
|
+
};
|
|
71
77
|
if (hasRealValue(env["MINIMAX_API_KEY"])) return {
|
|
72
78
|
provider: "minimax",
|
|
73
79
|
model: env["MINIMAX_MODEL"] || "MiniMax-M2.7",
|
|
@@ -93,7 +99,7 @@ function detectProvider(env) {
|
|
|
93
99
|
maxTokens
|
|
94
100
|
};
|
|
95
101
|
if (!(env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true")) {
|
|
96
|
-
process.stderr.write("[agentmemory] No LLM provider key found (ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY, MINIMAX_API_KEY). LLM-backed compression and summarization are DISABLED — using no-op provider. This is the safe default: the agent-sdk fallback used to spawn Claude Agent SDK child sessions which inherit Claude Code's plugin hooks and cause infinite Stop-hook recursion (#149 follow-up). To opt in to the agent-sdk fallback anyway, set both AGENTMEMORY_AUTO_COMPRESS=true AND AGENTMEMORY_ALLOW_AGENT_SDK=true — but be aware it will burn your Claude Pro allocation and may still recurse if you use it from inside Claude Code itself.\n");
|
|
102
|
+
process.stderr.write("[agentmemory] No LLM provider key found (ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY, MINIMAX_API_KEY, OPENAI_API_KEY). LLM-backed compression and summarization are DISABLED — using no-op provider. This is the safe default: the agent-sdk fallback used to spawn Claude Agent SDK child sessions which inherit Claude Code's plugin hooks and cause infinite Stop-hook recursion (#149 follow-up). To opt in to the agent-sdk fallback anyway, set both AGENTMEMORY_AUTO_COMPRESS=true AND AGENTMEMORY_ALLOW_AGENT_SDK=true — but be aware it will burn your Claude Pro allocation and may still recurse if you use it from inside Claude Code itself.\n");
|
|
97
103
|
return {
|
|
98
104
|
provider: "noop",
|
|
99
105
|
model: "noop",
|
|
@@ -133,7 +139,7 @@ function getEnvVar(key) {
|
|
|
133
139
|
}
|
|
134
140
|
function detectLlmProviderKind() {
|
|
135
141
|
const env = getMergedEnv();
|
|
136
|
-
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"])) return "llm";
|
|
142
|
+
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";
|
|
137
143
|
return "noop";
|
|
138
144
|
}
|
|
139
145
|
function loadEmbeddingConfig() {
|
|
@@ -215,7 +221,8 @@ const VALID_PROVIDERS = new Set([
|
|
|
215
221
|
"gemini",
|
|
216
222
|
"openrouter",
|
|
217
223
|
"agent-sdk",
|
|
218
|
-
"minimax"
|
|
224
|
+
"minimax",
|
|
225
|
+
"openai"
|
|
219
226
|
]);
|
|
220
227
|
function loadFallbackConfig() {
|
|
221
228
|
const env = getMergedEnv();
|
|
@@ -398,6 +405,137 @@ var NoopProvider = class {
|
|
|
398
405
|
}
|
|
399
406
|
};
|
|
400
407
|
|
|
408
|
+
//#endregion
|
|
409
|
+
//#region src/providers/openai.ts
|
|
410
|
+
const DEFAULT_BASE_URL$1 = "https://api.openai.com";
|
|
411
|
+
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
412
|
+
const DEFAULT_AZURE_API_VERSION = "2024-08-01-preview";
|
|
413
|
+
/**
|
|
414
|
+
* OpenAI-compatible LLM provider.
|
|
415
|
+
*
|
|
416
|
+
* Uses raw fetch (no SDK) to support any OpenAI-compatible endpoint:
|
|
417
|
+
* - OpenAI official
|
|
418
|
+
* - Azure OpenAI (auto-detected from .openai.azure.com host)
|
|
419
|
+
* - DeepSeek
|
|
420
|
+
* - 硅基流动 (SiliconFlow)
|
|
421
|
+
* - vLLM / LM Studio / Ollama (with OpenAI compatibility layer)
|
|
422
|
+
* - Any other proxy implementing /v1/chat/completions
|
|
423
|
+
*
|
|
424
|
+
* Required env vars:
|
|
425
|
+
* OPENAI_API_KEY — API key
|
|
426
|
+
*
|
|
427
|
+
* Optional:
|
|
428
|
+
* OPENAI_BASE_URL — base URL without path (default: https://api.openai.com).
|
|
429
|
+
* Azure: https://<resource>.openai.azure.com/openai/deployments/<deployment>
|
|
430
|
+
* OPENAI_MODEL — model name (default: gpt-4o-mini)
|
|
431
|
+
* OPENAI_API_VERSION — Azure api-version query param (default: 2024-08-01-preview)
|
|
432
|
+
* OPENAI_TIMEOUT_MS — outbound fetch timeout in ms (default: 60000)
|
|
433
|
+
* MAX_TOKENS — max output tokens (default: from config or 4096)
|
|
434
|
+
* OPENAI_REASONING_EFFORT — "low" | "medium" | "high" | "none"
|
|
435
|
+
* Passthrough for reasoning models (e.g. Ollama Cloud
|
|
436
|
+
* thinking models). Set to "none" to ensure
|
|
437
|
+
* message.content is populated instead of only
|
|
438
|
+
* message.reasoning.
|
|
439
|
+
*/
|
|
440
|
+
var OpenAIProvider = class {
|
|
441
|
+
name = "openai";
|
|
442
|
+
apiKey;
|
|
443
|
+
model;
|
|
444
|
+
maxTokens;
|
|
445
|
+
baseUrl;
|
|
446
|
+
reasoningEffort;
|
|
447
|
+
timeoutMs;
|
|
448
|
+
isAzure;
|
|
449
|
+
azureApiVersion;
|
|
450
|
+
constructor(apiKey, model, maxTokens, baseURL) {
|
|
451
|
+
this.apiKey = apiKey;
|
|
452
|
+
this.model = model;
|
|
453
|
+
this.maxTokens = maxTokens;
|
|
454
|
+
this.baseUrl = (baseURL || getEnvVar("OPENAI_BASE_URL") || DEFAULT_BASE_URL$1).replace(/\/+$/, "");
|
|
455
|
+
this.reasoningEffort = getEnvVar("OPENAI_REASONING_EFFORT") || void 0;
|
|
456
|
+
this.timeoutMs = parseTimeout(getEnvVar("OPENAI_TIMEOUT_MS"));
|
|
457
|
+
this.azureApiVersion = getEnvVar("OPENAI_API_VERSION") || DEFAULT_AZURE_API_VERSION;
|
|
458
|
+
this.isAzure = detectAzure(this.baseUrl);
|
|
459
|
+
}
|
|
460
|
+
async compress(systemPrompt, userPrompt) {
|
|
461
|
+
return this.call(systemPrompt, userPrompt);
|
|
462
|
+
}
|
|
463
|
+
async summarize(systemPrompt, userPrompt) {
|
|
464
|
+
return this.call(systemPrompt, userPrompt);
|
|
465
|
+
}
|
|
466
|
+
buildUrl() {
|
|
467
|
+
if (this.isAzure) {
|
|
468
|
+
const sep = this.baseUrl.includes("?") ? "&" : "?";
|
|
469
|
+
return `${this.baseUrl}/chat/completions${sep}api-version=${encodeURIComponent(this.azureApiVersion)}`;
|
|
470
|
+
}
|
|
471
|
+
return `${this.baseUrl}/v1/chat/completions`;
|
|
472
|
+
}
|
|
473
|
+
buildHeaders() {
|
|
474
|
+
if (this.isAzure) return {
|
|
475
|
+
"Content-Type": "application/json",
|
|
476
|
+
"api-key": this.apiKey
|
|
477
|
+
};
|
|
478
|
+
return {
|
|
479
|
+
"Content-Type": "application/json",
|
|
480
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
async call(systemPrompt, userPrompt) {
|
|
484
|
+
const url = this.buildUrl();
|
|
485
|
+
const body = {
|
|
486
|
+
model: this.model,
|
|
487
|
+
max_tokens: this.maxTokens,
|
|
488
|
+
messages: [{
|
|
489
|
+
role: "system",
|
|
490
|
+
content: systemPrompt
|
|
491
|
+
}, {
|
|
492
|
+
role: "user",
|
|
493
|
+
content: userPrompt
|
|
494
|
+
}]
|
|
495
|
+
};
|
|
496
|
+
if (this.reasoningEffort) body.reasoning_effort = this.reasoningEffort;
|
|
497
|
+
const ac = new AbortController();
|
|
498
|
+
const t = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
499
|
+
let response;
|
|
500
|
+
try {
|
|
501
|
+
response = await fetch(url, {
|
|
502
|
+
method: "POST",
|
|
503
|
+
headers: this.buildHeaders(),
|
|
504
|
+
body: JSON.stringify(body),
|
|
505
|
+
signal: ac.signal
|
|
506
|
+
});
|
|
507
|
+
} catch (err) {
|
|
508
|
+
if (ac.signal.aborted || err instanceof Error && err.name === "AbortError") throw new Error(`OpenAI API request timed out after ${this.timeoutMs}ms — set OPENAI_TIMEOUT_MS to raise the bound or check the provider status.`);
|
|
509
|
+
throw err;
|
|
510
|
+
} finally {
|
|
511
|
+
clearTimeout(t);
|
|
512
|
+
}
|
|
513
|
+
if (!response.ok) {
|
|
514
|
+
const text = await response.text();
|
|
515
|
+
throw new Error(`OpenAI API error (${response.status}): ${text}`);
|
|
516
|
+
}
|
|
517
|
+
const data = await response.json();
|
|
518
|
+
const message = data.choices?.[0]?.message;
|
|
519
|
+
const content = message?.content;
|
|
520
|
+
if (content) return content;
|
|
521
|
+
const reasoning = message?.reasoning;
|
|
522
|
+
if (reasoning) return reasoning;
|
|
523
|
+
throw new Error(`OpenAI returned unexpected response: ${JSON.stringify(data).slice(0, 200)}`);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
function parseTimeout(raw) {
|
|
527
|
+
if (!raw) return DEFAULT_TIMEOUT_MS;
|
|
528
|
+
const n = parseInt(raw, 10);
|
|
529
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_TIMEOUT_MS;
|
|
530
|
+
}
|
|
531
|
+
function detectAzure(baseUrl) {
|
|
532
|
+
try {
|
|
533
|
+
return new URL(baseUrl).hostname.endsWith(".openai.azure.com");
|
|
534
|
+
} catch {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
401
539
|
//#endregion
|
|
402
540
|
//#region src/providers/openrouter.ts
|
|
403
541
|
var OpenRouterProvider = class {
|
|
@@ -983,6 +1121,11 @@ function createBaseProvider(config) {
|
|
|
983
1121
|
return new OpenRouterProvider(geminiKey, config.model, config.maxTokens, "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions");
|
|
984
1122
|
}
|
|
985
1123
|
case "openrouter": return new OpenRouterProvider(requireEnvVar("OPENROUTER_API_KEY"), config.model, config.maxTokens, "https://openrouter.ai/api/v1/chat/completions");
|
|
1124
|
+
case "openai": {
|
|
1125
|
+
const openaiKey = getEnvVar("OPENAI_API_KEY");
|
|
1126
|
+
if (!openaiKey) throw new Error("OPENAI_API_KEY is required for the openai provider");
|
|
1127
|
+
return new OpenAIProvider(openaiKey, config.model, config.maxTokens, config.baseURL);
|
|
1128
|
+
}
|
|
986
1129
|
case "noop": return new NoopProvider();
|
|
987
1130
|
default: return new AgentSDKProvider();
|
|
988
1131
|
}
|
|
@@ -5967,7 +6110,7 @@ function registerAutoForgetFunction(sdk, kv) {
|
|
|
5967
6110
|
|
|
5968
6111
|
//#endregion
|
|
5969
6112
|
//#region src/version.ts
|
|
5970
|
-
const VERSION = "0.9.
|
|
6113
|
+
const VERSION = "0.9.17";
|
|
5971
6114
|
|
|
5972
6115
|
//#endregion
|
|
5973
6116
|
//#region src/functions/export-import.ts
|
|
@@ -6101,7 +6244,8 @@ function registerExportImportFunction(sdk, kv) {
|
|
|
6101
6244
|
"0.9.13",
|
|
6102
6245
|
"0.9.14",
|
|
6103
6246
|
"0.9.15",
|
|
6104
|
-
"0.9.16"
|
|
6247
|
+
"0.9.16",
|
|
6248
|
+
"0.9.17"
|
|
6105
6249
|
]).has(importData.version)) return {
|
|
6106
6250
|
success: false,
|
|
6107
6251
|
error: `Unsupported export version: ${importData.version}`
|
|
@@ -19676,6 +19820,11 @@ async function main() {
|
|
|
19676
19820
|
serviceName: OTEL_CONFIG.serviceName,
|
|
19677
19821
|
serviceVersion: OTEL_CONFIG.serviceVersion,
|
|
19678
19822
|
metricsExportIntervalMs: OTEL_CONFIG.metricsExportIntervalMs
|
|
19823
|
+
},
|
|
19824
|
+
telemetry: {
|
|
19825
|
+
project_name: "agentmemory",
|
|
19826
|
+
language: "node",
|
|
19827
|
+
framework: "iii-sdk"
|
|
19679
19828
|
}
|
|
19680
19829
|
});
|
|
19681
19830
|
const kv = new StateKV(sdk);
|
|
@@ -19835,7 +19984,7 @@ async function main() {
|
|
|
19835
19984
|
console.warn(`[agentmemory] Failed to backfill memories into BM25:`, err);
|
|
19836
19985
|
}
|
|
19837
19986
|
bootLog(`Ready. ${embeddingProvider ? "Triple-stream (BM25+Vector+Graph)" : "BM25+Graph"} search active.`);
|
|
19838
|
-
bootLog(`REST API:
|
|
19987
|
+
bootLog(`REST API: 121 endpoints at http://localhost:${config.restPort}/agentmemory/*`);
|
|
19839
19988
|
bootLog(`MCP surface (opt-in via \`npx @agentmemory/mcp\`): ${getAllTools().length} tools · 6 resources · 3 prompts`);
|
|
19840
19989
|
const viewerServer = startViewerServer(config.restPort + 2, kv, sdk, secret, config.restPort);
|
|
19841
19990
|
const autoForgetIntervalMs = parseInt(process.env.AUTO_FORGET_INTERVAL_MS || "3600000", 10);
|