@agentmemory/agentmemory 0.9.12 → 0.9.14

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/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { TriggerAction, registerWorker } from "iii-sdk";
3
4
  import { constants, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
5
  import { basename, dirname, extname, join, resolve, sep } from "node:path";
@@ -82,7 +83,7 @@ function detectProvider(env) {
82
83
  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");
83
84
  return {
84
85
  provider: "gemini",
85
- model: env["GEMINI_MODEL"] || "gemini-2.0-flash",
86
+ model: env["GEMINI_MODEL"] || "gemini-2.5-flash",
86
87
  maxTokens
87
88
  };
88
89
  }
@@ -570,7 +571,8 @@ var FallbackChainProvider = class {
570
571
  //#endregion
571
572
  //#region src/providers/embedding/gemini.ts
572
573
  const BATCH_LIMIT = 100;
573
- const API_BASE = "https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:batchEmbedContent";
574
+ const MODEL = "models/gemini-embedding-001";
575
+ const API_BASE = `https://generativelanguage.googleapis.com/v1beta/${MODEL}:batchEmbedContents`;
574
576
  var GeminiEmbeddingProvider = class {
575
577
  name = "gemini";
576
578
  dimensions = 768;
@@ -591,8 +593,9 @@ var GeminiEmbeddingProvider = class {
591
593
  method: "POST",
592
594
  headers: { "Content-Type": "application/json" },
593
595
  body: JSON.stringify({ requests: chunk.map((t) => ({
594
- model: "models/text-embedding-004",
595
- content: { parts: [{ text: t }] }
596
+ model: MODEL,
597
+ content: { parts: [{ text: t }] },
598
+ outputDimensionality: this.dimensions
596
599
  })) })
597
600
  });
598
601
  if (!response.ok) {
@@ -600,11 +603,26 @@ var GeminiEmbeddingProvider = class {
600
603
  throw new Error(`Gemini embedding failed (${response.status}): ${err}`);
601
604
  }
602
605
  const data = await response.json();
603
- for (const emb of data.embeddings) results.push(new Float32Array(emb.values));
606
+ for (const emb of data.embeddings) results.push(l2Normalize(new Float32Array(emb.values)));
604
607
  }
605
608
  return results;
606
609
  }
607
610
  };
611
+ let zeroNormWarned = false;
612
+ function l2Normalize(vec) {
613
+ let sum = 0;
614
+ for (let i = 0; i < vec.length; i++) sum += vec[i] * vec[i];
615
+ const norm = Math.sqrt(sum);
616
+ if (norm === 0) {
617
+ if (!zeroNormWarned) {
618
+ zeroNormWarned = true;
619
+ process.stderr.write(`[agentmemory] warn: gemini-embedding-001 returned a zero-norm embedding (length=${vec.length}); leaving it un-normalized. Subsequent zero-norm vectors will not be reported.\n`);
620
+ }
621
+ return vec;
622
+ }
623
+ for (let i = 0; i < vec.length; i++) vec[i] = vec[i] / norm;
624
+ return vec;
625
+ }
608
626
 
609
627
  //#endregion
610
628
  //#region src/providers/embedding/openai.ts
@@ -2075,6 +2093,110 @@ function getSynonyms(stemmedTerm) {
2075
2093
  return syns ? [...syns] : [];
2076
2094
  }
2077
2095
 
2096
+ //#endregion
2097
+ //#region src/state/cjk-segmenter.ts
2098
+ const cjkRequire = createRequire(import.meta.url);
2099
+ const CJK_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
2100
+ const KANA_RE = /[\p{Script=Hiragana}\p{Script=Katakana}]/u;
2101
+ const HANGUL_RE = /\p{Script=Hangul}/u;
2102
+ const CJK_RUN_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+/gu;
2103
+ const HANGUL_BLOCK_RE = /[가-힯]+/g;
2104
+ const hintShown = /* @__PURE__ */ new Set();
2105
+ function hasCjk(text) {
2106
+ return CJK_RE.test(text);
2107
+ }
2108
+ function showHintOnce(key, message) {
2109
+ if (hintShown.has(key)) return;
2110
+ hintShown.add(key);
2111
+ if (typeof process !== "undefined" && process.stderr?.write) process.stderr.write(`agentmemory: ${message}\n`);
2112
+ }
2113
+ let jiebaInstance = null;
2114
+ let jiebaLoaded = false;
2115
+ function getJieba() {
2116
+ if (jiebaLoaded) return jiebaInstance;
2117
+ jiebaLoaded = true;
2118
+ try {
2119
+ const mod = cjkRequire("@node-rs/jieba");
2120
+ try {
2121
+ const dictMod = cjkRequire("@node-rs/jieba/dict");
2122
+ jiebaInstance = mod.Jieba.withDict(dictMod.dict);
2123
+ } catch {
2124
+ jiebaInstance = new mod.Jieba();
2125
+ }
2126
+ return jiebaInstance;
2127
+ } catch {
2128
+ showHintOnce("jieba", "install @node-rs/jieba to improve Chinese search; falling back to whole-string tokenization");
2129
+ return null;
2130
+ }
2131
+ }
2132
+ let jaSegmenterInstance = null;
2133
+ let jaSegmenterLoaded = false;
2134
+ function getJaSegmenter() {
2135
+ if (jaSegmenterLoaded) return jaSegmenterInstance;
2136
+ jaSegmenterLoaded = true;
2137
+ try {
2138
+ jaSegmenterInstance = new (cjkRequire("tiny-segmenter"))();
2139
+ return jaSegmenterInstance;
2140
+ } catch {
2141
+ showHintOnce("tiny-segmenter", "install tiny-segmenter to improve Japanese search; falling back to whole-string tokenization");
2142
+ return null;
2143
+ }
2144
+ }
2145
+ function cleanTokens(tokens) {
2146
+ const out = [];
2147
+ for (const t of tokens) {
2148
+ const trimmed = t.trim();
2149
+ if (trimmed) out.push(trimmed);
2150
+ }
2151
+ return out;
2152
+ }
2153
+ function segmentHan(text) {
2154
+ const j = getJieba();
2155
+ if (!j) return [text];
2156
+ try {
2157
+ return cleanTokens(j.cut(text, true));
2158
+ } catch {
2159
+ return [text];
2160
+ }
2161
+ }
2162
+ function segmentKana(text) {
2163
+ const s = getJaSegmenter();
2164
+ if (!s) return [text];
2165
+ try {
2166
+ return cleanTokens(s.segment(text));
2167
+ } catch {
2168
+ return [text];
2169
+ }
2170
+ }
2171
+ function segmentHangul(text) {
2172
+ const out = [];
2173
+ for (const m of text.matchAll(HANGUL_BLOCK_RE)) if (m[0]) out.push(m[0]);
2174
+ return out;
2175
+ }
2176
+ function segmentCjk(text) {
2177
+ if (!hasCjk(text)) return [text];
2178
+ const out = [];
2179
+ let cursor = 0;
2180
+ for (const m of text.matchAll(CJK_RUN_RE)) {
2181
+ const start = m.index ?? 0;
2182
+ const run = m[0];
2183
+ const end = start + run.length;
2184
+ if (start > cursor) {
2185
+ const piece = text.slice(cursor, start).trim();
2186
+ if (piece) out.push(piece);
2187
+ }
2188
+ if (HANGUL_RE.test(run)) out.push(...segmentHangul(run));
2189
+ else if (KANA_RE.test(run)) out.push(...segmentKana(run));
2190
+ else out.push(...segmentHan(run));
2191
+ cursor = end;
2192
+ }
2193
+ if (cursor < text.length) {
2194
+ const trailing = text.slice(cursor).trim();
2195
+ if (trailing) out.push(trailing);
2196
+ }
2197
+ return out;
2198
+ }
2199
+
2078
2200
  //#endregion
2079
2201
  //#region src/state/search-index.ts
2080
2202
  var SearchIndex = class SearchIndex {
@@ -2231,7 +2353,15 @@ var SearchIndex = class SearchIndex {
2231
2353
  return this.tokenize(parts.join(" ").toLowerCase());
2232
2354
  }
2233
2355
  tokenize(text) {
2234
- return text.replace(/[^\p{L}\p{N}\s/.\\-_]/gu, " ").split(/\s+/).filter((t) => t.length > 1).map((t) => stem(t));
2356
+ const cleaned = text.replace(/[^\p{L}\p{N}\s/.\\-_]/gu, " ");
2357
+ const out = [];
2358
+ for (const raw of cleaned.split(/\s+/)) {
2359
+ if (raw.length < 2) continue;
2360
+ if (hasCjk(raw)) {
2361
+ for (const seg of segmentCjk(raw)) if (seg.length >= 1) out.push(seg);
2362
+ } else out.push(stem(raw));
2363
+ }
2364
+ return out;
2235
2365
  }
2236
2366
  getSortedTerms() {
2237
2367
  if (!this.sortedTerms) this.sortedTerms = Array.from(this.invertedIndex.keys()).sort();
@@ -5826,7 +5956,7 @@ function registerAutoForgetFunction(sdk, kv) {
5826
5956
 
5827
5957
  //#endregion
5828
5958
  //#region src/version.ts
5829
- const VERSION = "0.9.12";
5959
+ const VERSION = "0.9.14";
5830
5960
 
5831
5961
  //#endregion
5832
5962
  //#region src/functions/export-import.ts
@@ -5956,7 +6086,9 @@ function registerExportImportFunction(sdk, kv) {
5956
6086
  "0.9.9",
5957
6087
  "0.9.10",
5958
6088
  "0.9.11",
5959
- "0.9.12"
6089
+ "0.9.12",
6090
+ "0.9.13",
6091
+ "0.9.14"
5960
6092
  ]).has(importData.version)) return {
5961
6093
  success: false,
5962
6094
  error: `Unsupported export version: ${importData.version}`