@agentmemory/agentmemory 0.7.8 → 0.8.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.
@@ -39,10 +39,16 @@ function loadEnvFile() {
39
39
  }
40
40
  function detectProvider(env) {
41
41
  const maxTokens = parseInt(env["MAX_TOKENS"] || "4096", 10);
42
+ if (env["MINIMAX_API_KEY"]) return {
43
+ provider: "minimax",
44
+ model: env["MINIMAX_MODEL"] || "MiniMax-M2.7",
45
+ maxTokens
46
+ };
42
47
  if (env["ANTHROPIC_API_KEY"]) return {
43
48
  provider: "anthropic",
44
49
  model: env["ANTHROPIC_MODEL"] || "claude-sonnet-4-20250514",
45
- maxTokens
50
+ maxTokens,
51
+ baseURL: env["ANTHROPIC_BASE_URL"]
46
52
  };
47
53
  if (env["GEMINI_API_KEY"]) return {
48
54
  provider: "gemini",
@@ -156,7 +162,8 @@ const VALID_PROVIDERS = new Set([
156
162
  "anthropic",
157
163
  "gemini",
158
164
  "openrouter",
159
- "agent-sdk"
165
+ "agent-sdk",
166
+ "minimax"
160
167
  ]);
161
168
  function loadFallbackConfig() {
162
169
  return { providers: (getMergedEnv()["FALLBACK_PROVIDERS"] || "").split(",").map((p) => p.trim()).filter((p) => Boolean(p) && VALID_PROVIDERS.has(p)) };
@@ -195,8 +202,11 @@ var AnthropicProvider = class {
195
202
  client;
196
203
  model;
197
204
  maxTokens;
198
- constructor(apiKey, model, maxTokens) {
199
- this.client = new Anthropic({ apiKey });
205
+ constructor(apiKey, model, maxTokens, baseURL) {
206
+ this.client = new Anthropic({
207
+ apiKey,
208
+ ...baseURL ? { baseURL } : {}
209
+ });
200
210
  this.model = model;
201
211
  this.maxTokens = maxTokens;
202
212
  }
@@ -219,6 +229,67 @@ var AnthropicProvider = class {
219
229
  }
220
230
  };
221
231
 
232
+ //#endregion
233
+ //#region src/providers/minimax.ts
234
+ /**
235
+ * MiniMax provider using raw fetch to call MiniMax's Anthropic-compatible API.
236
+ *
237
+ * The Anthropic SDK automatically injects `x-stainless-*` headers that MiniMax
238
+ * rejects with 403. This provider bypasses the SDK and calls the API directly.
239
+ *
240
+ * Required env vars:
241
+ * MINIMAX_API_KEY — your MiniMax API key
242
+ * MINIMAX_MODEL — model name (default: MiniMax-M2.7)
243
+ * MAX_TOKENS — max output tokens (default: 800; MiniMax-M2.7 needs ≤800)
244
+ *
245
+ * Optional:
246
+ * MINIMAX_BASE_URL — base URL without path (default: https://api.minimaxi.com/anthropic)
247
+ */
248
+ var MinimaxProvider = class {
249
+ name = "minimax";
250
+ apiKey;
251
+ model;
252
+ maxTokens;
253
+ baseUrl;
254
+ constructor(apiKey, model, maxTokens) {
255
+ this.apiKey = apiKey;
256
+ this.model = model;
257
+ this.maxTokens = maxTokens;
258
+ this.baseUrl = process.env["MINIMAX_BASE_URL"] || "https://api.minimaxi.com/anthropic";
259
+ }
260
+ async compress(systemPrompt, userPrompt) {
261
+ return this.call(systemPrompt, userPrompt);
262
+ }
263
+ async summarize(systemPrompt, userPrompt) {
264
+ return this.call(systemPrompt, userPrompt);
265
+ }
266
+ async call(systemPrompt, userPrompt) {
267
+ const url = `${this.baseUrl}/v1/messages`;
268
+ const response = await fetch(url, {
269
+ method: "POST",
270
+ headers: {
271
+ "Content-Type": "application/json",
272
+ "x-api-key": this.apiKey,
273
+ "anthropic-version": "2023-06-01"
274
+ },
275
+ body: JSON.stringify({
276
+ model: this.model,
277
+ max_tokens: this.maxTokens,
278
+ system: systemPrompt,
279
+ messages: [{
280
+ role: "user",
281
+ content: userPrompt
282
+ }]
283
+ })
284
+ });
285
+ if (!response.ok) {
286
+ const text = await response.text();
287
+ throw new Error(`MiniMax API error ${response.status}: ${text}`);
288
+ }
289
+ return ((await response.json()).content?.find((b) => b.type === "text"))?.text ?? "";
290
+ }
291
+ };
292
+
222
293
  //#endregion
223
294
  //#region src/providers/openrouter.ts
224
295
  var OpenRouterProvider = class {
@@ -646,7 +717,8 @@ function createFallbackProvider(config, fallbackConfig) {
646
717
  }
647
718
  function createBaseProvider(config) {
648
719
  switch (config.provider) {
649
- case "anthropic": return new AnthropicProvider(requireEnvVar("ANTHROPIC_API_KEY"), config.model, config.maxTokens);
720
+ case "minimax": return new MinimaxProvider(requireEnvVar("MINIMAX_API_KEY"), config.model, config.maxTokens);
721
+ case "anthropic": return new AnthropicProvider(requireEnvVar("ANTHROPIC_API_KEY"), config.model, config.maxTokens, config.baseURL);
650
722
  case "gemini": return new OpenRouterProvider(requireEnvVar("GEMINI_API_KEY"), config.model, config.maxTokens, "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions");
651
723
  case "openrouter": return new OpenRouterProvider(requireEnvVar("OPENROUTER_API_KEY"), config.model, config.maxTokens, "https://openrouter.ai/api/v1/chat/completions");
652
724
  default: return new AgentSDKProvider();
@@ -2122,23 +2194,56 @@ function registerSearchFunction(sdk, kv) {
2122
2194
  }, async (data) => {
2123
2195
  const ctx = getContext();
2124
2196
  const idx = getSearchIndex();
2197
+ if (typeof data?.query !== "string" || !data.query.trim()) throw new Error("mem::search: query must be a non-empty string");
2198
+ const query = data.query.trim();
2199
+ const MAX_LIMIT = 100;
2200
+ let effectiveLimit = 20;
2201
+ if (data.limit !== void 0) {
2202
+ if (!Number.isInteger(data.limit) || data.limit < 1) throw new Error("mem::search: limit must be a positive integer");
2203
+ effectiveLimit = Math.min(data.limit, MAX_LIMIT);
2204
+ }
2205
+ const projectFilter = typeof data.project === "string" && data.project.length > 0 ? data.project : void 0;
2206
+ const cwdFilter = typeof data.cwd === "string" && data.cwd.length > 0 ? data.cwd : void 0;
2125
2207
  if (idx.size === 0) {
2126
2208
  const count = await rebuildIndex(kv);
2127
2209
  ctx.logger.info("Search index rebuilt", { entries: count });
2128
2210
  }
2129
- const results = idx.search(data.query, data.limit || 20);
2130
- const enriched = [];
2211
+ const filtering = !!(projectFilter || cwdFilter);
2212
+ const fetchLimit = filtering ? Math.max(effectiveLimit * 10, 100) : effectiveLimit;
2213
+ const results = idx.search(query, fetchLimit);
2214
+ const sessionCache = /* @__PURE__ */ new Map();
2215
+ const loadSession = async (sessionId) => {
2216
+ if (sessionCache.has(sessionId)) return sessionCache.get(sessionId);
2217
+ const s = await kv.get(KV.sessions, sessionId);
2218
+ sessionCache.set(sessionId, s ?? null);
2219
+ return s ?? null;
2220
+ };
2221
+ const candidates = [];
2131
2222
  for (const r of results) {
2132
- const obs = await kv.get(KV.observations(r.sessionId), r.obsId);
2223
+ if (candidates.length >= effectiveLimit) break;
2224
+ if (filtering) {
2225
+ const s = await loadSession(r.sessionId);
2226
+ if (!s) continue;
2227
+ if (projectFilter && s.project !== projectFilter) continue;
2228
+ if (cwdFilter && s.cwd !== cwdFilter) continue;
2229
+ }
2230
+ candidates.push(r);
2231
+ }
2232
+ const obsResults = await Promise.all(candidates.map((r) => kv.get(KV.observations(r.sessionId), r.obsId)));
2233
+ const enriched = [];
2234
+ for (let i = 0; i < candidates.length; i++) {
2235
+ const obs = obsResults[i];
2133
2236
  if (obs) enriched.push({
2134
2237
  observation: obs,
2135
- score: r.score,
2136
- sessionId: r.sessionId
2238
+ score: candidates[i].score,
2239
+ sessionId: candidates[i].sessionId
2137
2240
  });
2138
2241
  }
2139
2242
  ctx.logger.info("Search completed", {
2140
- query: data.query,
2141
- results: enriched.length
2243
+ query,
2244
+ results: enriched.length,
2245
+ hasProjectFilter: !!projectFilter,
2246
+ hasCwdFilter: !!cwdFilter
2142
2247
  });
2143
2248
  return { results: enriched };
2144
2249
  });
@@ -3804,7 +3909,7 @@ function registerAutoForgetFunction(sdk, kv) {
3804
3909
 
3805
3910
  //#endregion
3806
3911
  //#region src/version.ts
3807
- const VERSION = "0.7.8";
3912
+ const VERSION = "0.8.0";
3808
3913
 
3809
3914
  //#endregion
3810
3915
  //#region src/functions/export-import.ts
@@ -3909,7 +4014,8 @@ function registerExportImportFunction(sdk, kv) {
3909
4014
  "0.7.5",
3910
4015
  "0.7.6",
3911
4016
  "0.7.7",
3912
- "0.7.8"
4017
+ "0.7.9",
4018
+ "0.8.0"
3913
4019
  ]).has(importData.version)) return {
3914
4020
  success: false,
3915
4021
  error: `Unsupported export version: ${importData.version}`
@@ -10032,9 +10138,32 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10032
10138
  sdk.registerFunction({ id: "api::search" }, async (req) => {
10033
10139
  const authErr = checkAuth$1(req, secret);
10034
10140
  if (authErr) return authErr;
10141
+ const body = req.body ?? {};
10142
+ if (typeof body.query !== "string" || !body.query.trim()) return {
10143
+ status_code: 400,
10144
+ body: { error: "query is required and must be a non-empty string" }
10145
+ };
10146
+ if (body.limit !== void 0 && (!Number.isInteger(body.limit) || body.limit < 1)) return {
10147
+ status_code: 400,
10148
+ body: { error: "limit must be a positive integer" }
10149
+ };
10150
+ if (body.project !== void 0 && typeof body.project !== "string") return {
10151
+ status_code: 400,
10152
+ body: { error: "project must be a string" }
10153
+ };
10154
+ if (body.cwd !== void 0 && typeof body.cwd !== "string") return {
10155
+ status_code: 400,
10156
+ body: { error: "cwd must be a string" }
10157
+ };
10158
+ const payload = {
10159
+ query: body.query.trim(),
10160
+ limit: body.limit,
10161
+ project: body.project,
10162
+ cwd: body.cwd
10163
+ };
10035
10164
  return {
10036
10165
  status_code: 200,
10037
- body: await sdk.trigger("mem::search", req.body)
10166
+ body: await sdk.trigger("mem::search", payload)
10038
10167
  };
10039
10168
  });
10040
10169
  sdk.registerTrigger({
@@ -14727,4 +14856,4 @@ main().catch((err) => {
14727
14856
 
14728
14857
  //#endregion
14729
14858
  export { };
14730
- //# sourceMappingURL=src-Ct05bSXw.mjs.map
14859
+ //# sourceMappingURL=src-qOdKVNQz.mjs.map