@hope666/melu 1.0.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 (87) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +57 -0
  3. package/dist/cli.d.ts +8 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +630 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +45 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +135 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/embedder-client.d.ts +24 -0
  12. package/dist/embedder-client.d.ts.map +1 -0
  13. package/dist/embedder-client.js +164 -0
  14. package/dist/embedder-client.js.map +1 -0
  15. package/dist/embedder-daemon-client.d.ts +10 -0
  16. package/dist/embedder-daemon-client.d.ts.map +1 -0
  17. package/dist/embedder-daemon-client.js +185 -0
  18. package/dist/embedder-daemon-client.js.map +1 -0
  19. package/dist/embedder-daemon.d.ts +11 -0
  20. package/dist/embedder-daemon.d.ts.map +1 -0
  21. package/dist/embedder-daemon.js +284 -0
  22. package/dist/embedder-daemon.js.map +1 -0
  23. package/dist/embedder-ipc.d.ts +27 -0
  24. package/dist/embedder-ipc.d.ts.map +1 -0
  25. package/dist/embedder-ipc.js +60 -0
  26. package/dist/embedder-ipc.js.map +1 -0
  27. package/dist/embedder-main.d.ts +2 -0
  28. package/dist/embedder-main.d.ts.map +1 -0
  29. package/dist/embedder-main.js +6 -0
  30. package/dist/embedder-main.js.map +1 -0
  31. package/dist/embedder.d.ts +41 -0
  32. package/dist/embedder.d.ts.map +1 -0
  33. package/dist/embedder.js +231 -0
  34. package/dist/embedder.js.map +1 -0
  35. package/dist/extraction-queue.d.ts +53 -0
  36. package/dist/extraction-queue.d.ts.map +1 -0
  37. package/dist/extraction-queue.js +418 -0
  38. package/dist/extraction-queue.js.map +1 -0
  39. package/dist/extraction-stats.d.ts +15 -0
  40. package/dist/extraction-stats.d.ts.map +1 -0
  41. package/dist/extraction-stats.js +89 -0
  42. package/dist/extraction-stats.js.map +1 -0
  43. package/dist/extractor-worker-main.d.ts +2 -0
  44. package/dist/extractor-worker-main.d.ts.map +1 -0
  45. package/dist/extractor-worker-main.js +70 -0
  46. package/dist/extractor-worker-main.js.map +1 -0
  47. package/dist/extractor-worker.d.ts +17 -0
  48. package/dist/extractor-worker.d.ts.map +1 -0
  49. package/dist/extractor-worker.js +164 -0
  50. package/dist/extractor-worker.js.map +1 -0
  51. package/dist/extractor.d.ts +36 -0
  52. package/dist/extractor.d.ts.map +1 -0
  53. package/dist/extractor.js +244 -0
  54. package/dist/extractor.js.map +1 -0
  55. package/dist/i18n.d.ts +995 -0
  56. package/dist/i18n.d.ts.map +1 -0
  57. package/dist/i18n.js +1024 -0
  58. package/dist/i18n.js.map +1 -0
  59. package/dist/memory.d.ts +62 -0
  60. package/dist/memory.d.ts.map +1 -0
  61. package/dist/memory.js +293 -0
  62. package/dist/memory.js.map +1 -0
  63. package/dist/model-bootstrap.d.ts +29 -0
  64. package/dist/model-bootstrap.d.ts.map +1 -0
  65. package/dist/model-bootstrap.js +235 -0
  66. package/dist/model-bootstrap.js.map +1 -0
  67. package/dist/proxy-main.d.ts +5 -0
  68. package/dist/proxy-main.d.ts.map +1 -0
  69. package/dist/proxy-main.js +10 -0
  70. package/dist/proxy-main.js.map +1 -0
  71. package/dist/proxy.d.ts +9 -0
  72. package/dist/proxy.d.ts.map +1 -0
  73. package/dist/proxy.js +309 -0
  74. package/dist/proxy.js.map +1 -0
  75. package/dist/run-runtime.d.ts +34 -0
  76. package/dist/run-runtime.d.ts.map +1 -0
  77. package/dist/run-runtime.js +170 -0
  78. package/dist/run-runtime.js.map +1 -0
  79. package/dist/runtime-context.d.ts +12 -0
  80. package/dist/runtime-context.d.ts.map +1 -0
  81. package/dist/runtime-context.js +39 -0
  82. package/dist/runtime-context.js.map +1 -0
  83. package/dist/text-chunking.d.ts +7 -0
  84. package/dist/text-chunking.d.ts.map +1 -0
  85. package/dist/text-chunking.js +50 -0
  86. package/dist/text-chunking.js.map +1 -0
  87. package/package.json +46 -0
@@ -0,0 +1,164 @@
1
+ import { buildEmbedderSocketPath } from "./runtime-context.js";
2
+ import { embedTextsViaDaemon } from "./embedder-daemon-client.js";
3
+ import { MemoryStore } from "./memory.js";
4
+ import { claimNextPendingExtractionJobForRun, completeClaimedPendingExtractionJob, getExtractionQueueSnapshotForRun, preparePendingExtractionQueueForRun, requeueClaimedPendingExtractionJob, resolveExtractionRunId, } from "./extraction-queue.js";
5
+ import { createInitialExtractionRunStats, updateExtractionRunStats, } from "./extraction-stats.js";
6
+ import { extractMemoriesFromUserMessage, processAndStoreMemories, } from "./extractor.js";
7
+ const DEFAULT_POLL_INTERVAL_MS = 2_000;
8
+ function formatError(error) {
9
+ return error instanceof Error ? error.message : String(error);
10
+ }
11
+ function isProcessAlive(pid) {
12
+ if (!Number.isInteger(pid) || (pid ?? 0) <= 0) {
13
+ return false;
14
+ }
15
+ try {
16
+ process.kill(pid, 0);
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ function sleep(ms, abortSignal) {
24
+ if (ms <= 0)
25
+ return Promise.resolve();
26
+ return new Promise((resolve) => {
27
+ const timer = setTimeout(() => {
28
+ cleanup();
29
+ resolve();
30
+ }, ms);
31
+ const onAbort = () => {
32
+ cleanup();
33
+ resolve();
34
+ };
35
+ const cleanup = () => {
36
+ clearTimeout(timer);
37
+ if (abortSignal) {
38
+ abortSignal.removeEventListener("abort", onAbort);
39
+ }
40
+ };
41
+ if (abortSignal) {
42
+ if (abortSignal.aborted) {
43
+ cleanup();
44
+ resolve();
45
+ return;
46
+ }
47
+ abortSignal.addEventListener("abort", onAbort, { once: true });
48
+ }
49
+ });
50
+ }
51
+ async function storeMemoriesForJob(job, runId, options) {
52
+ const memoryPath = job.memoryPath ?? options.defaultMemoryPath;
53
+ if (!memoryPath) {
54
+ throw new Error("Missing memory path for extraction job");
55
+ }
56
+ const rawMemories = await extractMemoriesFromUserMessage(job.text, {
57
+ url: "",
58
+ headers: {},
59
+ bodyTemplate: {},
60
+ quiet: options.quiet ?? true,
61
+ });
62
+ if (rawMemories.length === 0) {
63
+ return 0;
64
+ }
65
+ const store = new MemoryStore(memoryPath);
66
+ store.open();
67
+ try {
68
+ return await processAndStoreMemories(rawMemories, store, options.embeddingModel, memoryPath, {
69
+ quiet: options.quiet ?? true,
70
+ failOnEmbeddingError: true,
71
+ embedText: async (summary, embeddingModel) => {
72
+ const vectors = await embedTextsViaDaemon([summary], embeddingModel, {
73
+ runId,
74
+ socketPath: options.embedderSocketPath ?? buildEmbedderSocketPath(runId),
75
+ type: "memory",
76
+ });
77
+ if (!vectors || vectors.length === 0) {
78
+ throw new Error("Embedder daemon returned no vectors");
79
+ }
80
+ return vectors[0];
81
+ },
82
+ });
83
+ }
84
+ finally {
85
+ store.close();
86
+ }
87
+ }
88
+ function persistStats(runId, counters) {
89
+ const snapshot = getExtractionQueueSnapshotForRun(runId);
90
+ const stats = updateExtractionRunStats(runId, () => ({
91
+ ...createInitialExtractionRunStats(runId, snapshot.remaining),
92
+ processed: counters.processed,
93
+ effectiveNewMemories: counters.effectiveNewMemories,
94
+ failed: counters.failed,
95
+ remainingQueue: snapshot.remaining,
96
+ updatedAt: new Date().toISOString(),
97
+ }));
98
+ return {
99
+ stats,
100
+ remainingQueue: snapshot.remaining,
101
+ nextRetryAt: snapshot.nextRetryAt,
102
+ };
103
+ }
104
+ export async function runExtractorWorker(options) {
105
+ const runId = resolveExtractionRunId(options.runId);
106
+ const quiet = options.quiet ?? true;
107
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
108
+ preparePendingExtractionQueueForRun(runId);
109
+ const counters = {
110
+ processed: 0,
111
+ effectiveNewMemories: 0,
112
+ failed: 0,
113
+ };
114
+ let { stats } = persistStats(runId, counters);
115
+ while (true) {
116
+ if (options.abortSignal?.aborted) {
117
+ break;
118
+ }
119
+ const claimed = claimNextPendingExtractionJobForRun(runId);
120
+ if (!claimed) {
121
+ const snapshot = persistStats(runId, counters);
122
+ stats = snapshot.stats;
123
+ const ownerAlive = isProcessAlive(options.ownerPid);
124
+ if (snapshot.remainingQueue === 0 && !ownerAlive) {
125
+ break;
126
+ }
127
+ const now = Date.now();
128
+ const waitMs = snapshot.remainingQueue === 0
129
+ ? pollIntervalMs
130
+ : snapshot.nextRetryAt !== null && snapshot.nextRetryAt > now
131
+ ? Math.max(250, snapshot.nextRetryAt - now)
132
+ : pollIntervalMs;
133
+ await sleep(waitMs, options.abortSignal);
134
+ continue;
135
+ }
136
+ let addedMemories = 0;
137
+ let terminalFailure = false;
138
+ try {
139
+ addedMemories = await storeMemoriesForJob(claimed, runId, { ...options, quiet });
140
+ completeClaimedPendingExtractionJob(claimed);
141
+ }
142
+ catch (error) {
143
+ const result = requeueClaimedPendingExtractionJob(claimed, { lastError: formatError(error) }, {
144
+ maxAttempts: options.maxAttempts,
145
+ baseDelayMs: options.retryBaseDelayMs,
146
+ maxDelayMs: options.retryMaxDelayMs,
147
+ });
148
+ terminalFailure = result.terminal;
149
+ }
150
+ finally {
151
+ counters.processed += 1;
152
+ counters.effectiveNewMemories += addedMemories;
153
+ if (terminalFailure) {
154
+ counters.failed += 1;
155
+ }
156
+ stats = persistStats(runId, counters).stats;
157
+ }
158
+ }
159
+ return stats;
160
+ }
161
+ export function createExtractorWorkerAbortController() {
162
+ return new AbortController();
163
+ }
164
+ //# sourceMappingURL=extractor-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor-worker.js","sourceRoot":"","sources":["../src/extractor-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Melu 记忆提取器。
3
+ *
4
+ * 只从 user 消息中提取长期记忆。
5
+ * 每条 user 消息完整传给 claude -p,最多提取 1 条记忆。
6
+ * 不做切块——用户输入剥离系统标签后通常很短,LLM 处理无压力。
7
+ */
8
+ import type { MemoryStore } from "./memory.js";
9
+ interface RawMemory {
10
+ content: string;
11
+ summary: string;
12
+ category: string;
13
+ subject: string;
14
+ }
15
+ /**
16
+ * 调用上游 Anthropic API 提取用户长期记忆。
17
+ */
18
+ export interface ExtractionRequestContext {
19
+ url: string;
20
+ headers: Record<string, string>;
21
+ bodyTemplate: Record<string, unknown>;
22
+ quiet?: boolean;
23
+ strict?: boolean;
24
+ }
25
+ export interface ProcessAndStoreMemoriesOptions {
26
+ embedText?: (summary: string, embeddingModel: string) => Promise<Float32Array>;
27
+ failOnEmbeddingError?: boolean;
28
+ quiet?: boolean;
29
+ }
30
+ export declare function extractMemoriesFromUserMessage(userMessage: string, ctx: ExtractionRequestContext): Promise<RawMemory[]>;
31
+ /**
32
+ * 处理提取到的记忆:embedding → 去重 → 存储。返回新增条数。
33
+ */
34
+ export declare function processAndStoreMemories(rawMemories: RawMemory[], store: MemoryStore, embeddingModel: string, sourceConversation?: string, options?: ProcessAndStoreMemoriesOptions): Promise<number>;
35
+ export {};
36
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA+C/C,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,8BAA8B,CAClD,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,wBAAwB,GAC5B,OAAO,CAAC,SAAS,EAAE,CAAC,CAYtB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,SAAS,EAAE,EACxB,KAAK,EAAE,WAAW,EAClB,cAAc,EAAE,MAAM,EACtB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC,MAAM,CAAC,CAuEjB"}
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Melu 记忆提取器。
3
+ *
4
+ * 只从 user 消息中提取长期记忆。
5
+ * 每条 user 消息完整传给 claude -p,最多提取 1 条记忆。
6
+ * 不做切块——用户输入剥离系统标签后通常很短,LLM 处理无压力。
7
+ */
8
+ import { embed } from "./embedder.js";
9
+ import { loadConfig } from "./config.js";
10
+ import { createI18n } from "./i18n.js";
11
+ import { normalizeWhitespace, truncateCharacters, } from "./text-chunking.js";
12
+ const MAX_SUMMARY_CHARS = 50;
13
+ const MAX_CONTENT_CHARS = 500;
14
+ const MAX_SUBJECT_CHARS = 80;
15
+ const MEMORY_CATEGORIES = new Set([
16
+ "profile",
17
+ "project",
18
+ "event",
19
+ "preference",
20
+ "correction",
21
+ ]);
22
+ const EXTRACTION_PROMPT = `You are a strict long-term memory extractor.
23
+ Based only on the user message below, determine whether there is exactly one stable memory worth keeping for future conversations.
24
+
25
+ Extraction rules:
26
+ - Look only at the user message. Do not use any imagined assistant reply.
27
+ - Extract at most one memory.
28
+ - Keep only information that is stable, durable, and likely to remain useful later.
29
+ - Do not extract one-off requests, casual chit-chat, temporary tasks, or noisy situational context.
30
+
31
+ Language rule:
32
+ - Use the same language as the user's message when writing the memory.
33
+
34
+ Field requirements:
35
+ - content: up to 60 words, include enough context and detail to be useful on its own
36
+ - summary: one short summary sentence, ideally no more than 30 Chinese characters or 20 English words, with a hard limit of 50 characters
37
+ - category: must be one of profile / project / event / preference / correction
38
+ - subject: a short topic tag such as user.name / user.preference.answer_style / project.melu
39
+
40
+ Output requirements:
41
+ - If a memory should be kept, output exactly one JSON object:
42
+ {"content":"...","summary":"...","category":"...","subject":"..."}
43
+ - If nothing should be kept, output null
44
+ - Do not output Markdown
45
+ - Do not output explanations
46
+
47
+ User message:
48
+ {user_message}`;
49
+ export async function extractMemoriesFromUserMessage(userMessage, ctx) {
50
+ const trimmed = normalizeWhitespace(userMessage);
51
+ if (trimmed.length === 0)
52
+ return [];
53
+ // 不切块,完整的 userMessage 直接传给 claude -p 提取,最多返回 1 条记忆。
54
+ // 用户单条消息剥离系统标签后一般几十到几百字,远在 LLM context 舒适区内。
55
+ // 切块反而会丢失上下文关联,且每个 chunk 各调一次 claude -p 浪费配额。
56
+ const candidate = await extractSingleMemoryFromChunk(trimmed, ctx);
57
+ if (candidate) {
58
+ return [candidate];
59
+ }
60
+ return [];
61
+ }
62
+ /**
63
+ * 处理提取到的记忆:embedding → 去重 → 存储。返回新增条数。
64
+ */
65
+ export async function processAndStoreMemories(rawMemories, store, embeddingModel, sourceConversation, options) {
66
+ const ui = createI18n(loadConfig().uiLanguage);
67
+ let added = 0;
68
+ for (const rawMemory of rawMemories) {
69
+ const memory = normalizeExtractedMemory(rawMemory);
70
+ if (!memory)
71
+ continue;
72
+ const { content, summary, category, subject } = memory;
73
+ let vector;
74
+ try {
75
+ vector = options?.embedText
76
+ ? await options.embedText(summary, embeddingModel)
77
+ : await embed(summary, embeddingModel, { purpose: "memory" });
78
+ }
79
+ catch (e) {
80
+ if (!options?.quiet) {
81
+ console.warn(ui.t("embeddingFailed"), e);
82
+ }
83
+ if (options?.failOnEmbeddingError === false) {
84
+ continue;
85
+ }
86
+ throw e;
87
+ }
88
+ const similar = store.findSimilar(vector, 0.7);
89
+ if (similar.length > 0) {
90
+ const { memory: bestMatch, similarity: bestSim } = similar[0];
91
+ if (bestSim > 0.9) {
92
+ store.add({
93
+ content,
94
+ summary,
95
+ category,
96
+ subject,
97
+ vector,
98
+ supersedes: bestMatch.id,
99
+ sourceConversation,
100
+ });
101
+ added++;
102
+ if (!options?.quiet) {
103
+ console.log(ui.t("memoryUpdated", { summary, previous: bestMatch.summary }));
104
+ }
105
+ continue;
106
+ }
107
+ if (bestSim > 0.7) {
108
+ store.conn.prepare("UPDATE memories SET confidence = confidence * 0.8 WHERE id=?").run(bestMatch.id);
109
+ }
110
+ }
111
+ store.add({
112
+ content,
113
+ summary,
114
+ category,
115
+ subject,
116
+ vector,
117
+ sourceConversation,
118
+ });
119
+ added++;
120
+ if (!options?.quiet) {
121
+ console.log(ui.t("memoryNew", { category, summary }));
122
+ }
123
+ }
124
+ return added;
125
+ }
126
+ async function extractSingleMemoryFromChunk(userChunk, ctx) {
127
+ const prompt = EXTRACTION_PROMPT.replace("{user_message}", userChunk);
128
+ const text = await callExtractionModel(prompt, ctx, 256);
129
+ if (!text)
130
+ return null;
131
+ const parsed = parseJsonPayload(text);
132
+ if (parsed == null)
133
+ return null;
134
+ if (Array.isArray(parsed)) {
135
+ for (const item of parsed) {
136
+ const memory = normalizeExtractedMemory(item);
137
+ if (memory)
138
+ return memory;
139
+ }
140
+ return null;
141
+ }
142
+ return normalizeExtractedMemory(parsed);
143
+ }
144
+ async function callExtractionModel(prompt, ctx, _maxTokens) {
145
+ const { spawn } = await import("node:child_process");
146
+ const ui = createI18n(loadConfig().uiLanguage);
147
+ const quiet = Boolean(ctx.quiet);
148
+ if (!quiet) {
149
+ console.log(ui.t("claudePExtracting"));
150
+ }
151
+ return new Promise((resolve, reject) => {
152
+ // 构造一个干净的环境:只保留系统必需的变量,删掉所有代理相关的
153
+ const cleanEnv = {};
154
+ const KEEP_KEYS = ["PATH", "HOME", "USER", "SHELL", "LANG", "TERM", "TMPDIR", "XDG_CONFIG_HOME", "XDG_DATA_HOME"];
155
+ for (const key of KEEP_KEYS) {
156
+ if (process.env[key])
157
+ cleanEnv[key] = process.env[key];
158
+ }
159
+ const child = spawn("claude", ["-p", prompt], {
160
+ env: cleanEnv,
161
+ stdio: ["ignore", "pipe", "pipe"],
162
+ timeout: 60000,
163
+ });
164
+ const chunks = [];
165
+ child.stdout.on("data", (chunk) => chunks.push(chunk));
166
+ const errChunks = [];
167
+ child.stderr.on("data", (chunk) => errChunks.push(chunk));
168
+ child.on("close", (code) => {
169
+ const stdout = Buffer.concat(chunks).toString("utf-8").trim();
170
+ if (code !== 0 || !stdout) {
171
+ const stderr = Buffer.concat(errChunks).toString("utf-8").slice(0, 200);
172
+ if (!quiet) {
173
+ console.warn(ui.t("claudePExitCode", { code: code ?? "null", stderr }));
174
+ }
175
+ reject(new Error(ui.t("claudePExitCode", { code: code ?? "null", stderr })));
176
+ return;
177
+ }
178
+ if (!quiet) {
179
+ console.log(`[Melu:DEBUG] claude -p 返回: ${truncateCharacters(stdout, 200)}`);
180
+ }
181
+ resolve(stripMarkdownFences(stdout));
182
+ });
183
+ child.on("error", (err) => {
184
+ if (!quiet) {
185
+ console.warn(ui.t("claudePStartFailed", { message: err.message }));
186
+ }
187
+ reject(err);
188
+ });
189
+ });
190
+ }
191
+ function stripMarkdownFences(text) {
192
+ const trimmed = text.trim();
193
+ if (!trimmed.startsWith("```")) {
194
+ return trimmed;
195
+ }
196
+ const lines = trimmed.split("\n");
197
+ return lines
198
+ .slice(1, lines[lines.length - 1].trim() === "```" ? -1 : undefined)
199
+ .join("\n")
200
+ .trim();
201
+ }
202
+ function parseJsonPayload(text) {
203
+ const normalized = text.trim();
204
+ if (normalized === "" || normalized === "null") {
205
+ return null;
206
+ }
207
+ try {
208
+ return JSON.parse(normalized);
209
+ }
210
+ catch {
211
+ return null;
212
+ }
213
+ }
214
+ function normalizeExtractedMemory(value) {
215
+ if (!value || typeof value !== "object")
216
+ return null;
217
+ const obj = value;
218
+ const rawSummary = normalizeWhitespace(String(obj.summary ?? ""));
219
+ const rawContent = normalizeWhitespace(String(obj.content ?? rawSummary));
220
+ if (rawSummary === "" && rawContent === "") {
221
+ return null;
222
+ }
223
+ const summary = truncateCharacters(rawSummary || rawContent, MAX_SUMMARY_CHARS);
224
+ const content = truncateCharacters(rawContent || summary, MAX_CONTENT_CHARS);
225
+ const category = normalizeCategory(obj.category);
226
+ const subject = truncateCharacters(normalizeWhitespace(String(obj.subject ?? "")), MAX_SUBJECT_CHARS, "");
227
+ if (summary === "" || content === "") {
228
+ return null;
229
+ }
230
+ return {
231
+ content,
232
+ summary,
233
+ category,
234
+ subject,
235
+ };
236
+ }
237
+ function normalizeCategory(value) {
238
+ const category = normalizeWhitespace(String(value ?? "")).toLowerCase();
239
+ if (MEMORY_CATEGORIES.has(category)) {
240
+ return category;
241
+ }
242
+ return "event";
243
+ }
244
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"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"}