@hilbras/remembra 0.2.0 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to Remembra will be documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/).
5
5
 
6
+ ## [0.3.0] — 2026-09-23
7
+
8
+ ### Added
9
+ - **Session digest**: `memory_digest` tool + `POST /memories/digest` — LLM extracts
10
+ facts/decisions/roles/history from a transcript and stores them.
11
+ - **Pluggable LLM provider**: `REMEMBRA_LLM=openai|anthropic|ollama` (+ `REMEMBRA_LLM_MODEL`).
12
+ - **Pluggable embeddings**: `REMEMBRA_EMBEDDINGS=openai|ollama|none` (default `none`).
13
+ - **Semantic search**: cosine similarity becomes the primary ranking signal when enabled;
14
+ vectors cached in memory frontmatter (computed once on write).
15
+ - Scope and role rules remain hard gates in both ranking modes.
16
+ - Keyword fallback: memories without vectors, and any embedding API failure, degrade
17
+ gracefully to keyword scoring (writes never blocked by embedding errors).
18
+ - Exact-match dedup in digest (type + scope + normalized content) — digests are idempotent.
19
+ - `docs/providers.md` — configuration guide for digest + embeddings.
20
+ - 18 new tests (digest, embeddings, retrieval modes, LLM output parsing).
21
+
22
+ ### Changed
23
+ - `MemoryService` now accepts optional injected deps (embed/extract) for testing.
24
+
6
25
  ## [0.2.0] — 2026-09-23
7
26
 
8
27
  ### Added
package/README.md CHANGED
@@ -89,6 +89,7 @@ Then wire a Custom GPT to the API — full walkthrough in **[docs/chatgpt.md](do
89
89
  | POST | `/memories` | Store a memory |
90
90
  | GET | `/memories/search?query=&scope=` | Search |
91
91
  | GET | `/memories?scope=&type=` | List |
92
+ | POST | `/memories/digest` | LLM extract + store from a transcript |
92
93
  | DELETE | `/memories/:id` | Forget |
93
94
 
94
95
  All routes except `/health` require `x-api-key` (or `Authorization: Bearer`) when
@@ -99,6 +100,7 @@ All routes except `/health` require `x-api-key` (or `Authorization: Bearer`) whe
99
100
  | Tool | Purpose |
100
101
  |------|---------|
101
102
  | `memory_store` | Save a fact / decision / role / history |
103
+ | `memory_digest` | Extract + store memories from a transcript (LLM) |
102
104
  | `memory_search` | Retrieve relevant memories (pass `scope` = current project) |
103
105
  | `memory_list` | Browse stored memories |
104
106
  | `memory_forget` | Delete by id |
@@ -113,6 +115,7 @@ Full reference: **[docs/tools.md](docs/tools.md)**
113
115
  | [Tool reference](docs/tools.md) | Every MCP tool with arguments |
114
116
  | [Client setup](docs/clients.md) | Config for each supported tool |
115
117
  | [ChatGPT setup](docs/chatgpt.md) | HTTP API + Custom GPT walkthrough |
118
+ | [AI providers](docs/providers.md) | Digest LLM + embeddings configuration |
116
119
  | [Contributing](CONTRIBUTING.md) | Dev workflow and guidelines |
117
120
  | [Changelog](CHANGELOG.md) | Release history |
118
121
 
@@ -142,8 +145,8 @@ npm test # run tests
142
145
  ## Roadmap
143
146
 
144
147
  - **v1** — MCP server for coding tools, file storage, layered retrieval ✅
145
- - **v1.5** *(current)* — HTTP API + ChatGPT Custom GPT action ✅
146
- - **v2** — automatic session-digest extraction, embeddings behind `memory_search`
148
+ - **v1.5** — HTTP API + ChatGPT Custom GPT action ✅
149
+ - **v2** *(current)* — automatic session-digest extraction, embeddings behind `memory_search`
147
150
  - **v3** — SQLite for scale, duplicate merging, memory decay
148
151
 
149
152
  ## License
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Pluggable embedding provider (v2).
3
+ *
4
+ * Config: REMEMBRA_EMBEDDINGS=openai|ollama|none (default: none → keyword-only, v1 behavior)
5
+ * Keys: OPENAI_API_KEY / OLLAMA_HOST (default localhost:11434)
6
+ *
7
+ * Vectors are computed once on write and cached in the memory file's frontmatter.
8
+ */
9
+ export type EmbeddingProvider = "openai" | "ollama" | "none";
10
+ export declare function resolveEmbeddingProvider(): EmbeddingProvider;
11
+ export declare function embedText(text: string, provider?: EmbeddingProvider): Promise<number[]>;
12
+ export declare function cosine(a: number[], b: number[]): number;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Pluggable embedding provider (v2).
3
+ *
4
+ * Config: REMEMBRA_EMBEDDINGS=openai|ollama|none (default: none → keyword-only, v1 behavior)
5
+ * Keys: OPENAI_API_KEY / OLLAMA_HOST (default localhost:11434)
6
+ *
7
+ * Vectors are computed once on write and cached in the memory file's frontmatter.
8
+ */
9
+ export function resolveEmbeddingProvider() {
10
+ const v = (process.env.REMEMBRA_EMBEDDINGS ?? "none").toLowerCase();
11
+ if (v === "openai" || v === "ollama" || v === "none")
12
+ return v;
13
+ throw new Error(`Invalid REMEMBRA_EMBEDDINGS "${v}" — expected openai|ollama|none`);
14
+ }
15
+ export async function embedText(text, provider = resolveEmbeddingProvider()) {
16
+ if (provider === "none")
17
+ throw new Error("embeddings disabled (REMEMBRA_EMBEDDINGS=none)");
18
+ if (provider === "openai") {
19
+ const key = process.env.OPENAI_API_KEY;
20
+ if (!key)
21
+ throw new Error("REMEMBRA_EMBEDDINGS=openai requires OPENAI_API_KEY");
22
+ const res = await fetch("https://api.openai.com/v1/embeddings", {
23
+ method: "POST",
24
+ headers: { authorization: `Bearer ${key}`, "content-type": "application/json" },
25
+ body: JSON.stringify({
26
+ model: process.env.REMEMBRA_EMBEDDING_MODEL ?? "text-embedding-3-small",
27
+ input: text,
28
+ }),
29
+ });
30
+ if (!res.ok)
31
+ throw new Error(`OpenAI embeddings failed: ${res.status}`);
32
+ const data = (await res.json());
33
+ return data.data[0].embedding;
34
+ }
35
+ // ollama
36
+ const host = process.env.OLLAMA_HOST ?? "http://localhost:11434";
37
+ const res = await fetch(`${host}/api/embeddings`, {
38
+ method: "POST",
39
+ headers: { "content-type": "application/json" },
40
+ body: JSON.stringify({
41
+ model: process.env.REMEMBRA_EMBEDDING_MODEL ?? "nomic-embed-text",
42
+ prompt: text,
43
+ }),
44
+ });
45
+ if (!res.ok)
46
+ throw new Error(`Ollama embeddings failed: ${res.status}`);
47
+ const data = (await res.json());
48
+ return data.embedding;
49
+ }
50
+ export function cosine(a, b) {
51
+ if (a.length === 0 || a.length !== b.length)
52
+ return 0;
53
+ let dot = 0;
54
+ let na = 0;
55
+ let nb = 0;
56
+ for (let i = 0; i < a.length; i++) {
57
+ dot += a[i] * b[i];
58
+ na += a[i] * a[i];
59
+ nb += b[i] * b[i];
60
+ }
61
+ if (na === 0 || nb === 0)
62
+ return 0;
63
+ return dot / (Math.sqrt(na) * Math.sqrt(nb));
64
+ }
65
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
package/dist/http.js CHANGED
@@ -20,6 +20,19 @@ export function createHttpServer(service, opts = {}) {
20
20
  if (opts.apiKey && !authorized(req, opts.apiKey)) {
21
21
  return send(res, 401, { error: "Unauthorized: missing or invalid API key" });
22
22
  }
23
+ // POST /memories/digest — must be checked before /memories/:id DELETE patterns
24
+ if (req.method === "POST" && path === "/memories/digest") {
25
+ const body = await readBody(req);
26
+ if (typeof body.transcript !== "string" || !body.transcript.trim()) {
27
+ return send(res, 400, { error: "Body must include a non-empty `transcript` string" });
28
+ }
29
+ const result = await service.digest({
30
+ transcript: body.transcript,
31
+ scope: body.scope,
32
+ source: body.source,
33
+ });
34
+ return send(res, 200, result);
35
+ }
23
36
  // POST /memories
24
37
  if (req.method === "POST" && path === "/memories") {
25
38
  const body = await readBody(req);
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ else {
22
22
  await startMcp();
23
23
  }
24
24
  async function startMcp() {
25
- const server = new McpServer({ name: "remembra", version: "0.2.0" });
25
+ const server = new McpServer({ name: "remembra", version: "0.3.0" });
26
26
  server.registerTool("memory_store", {
27
27
  title: "Store a memory",
28
28
  description: "Persist a fact, decision, role or history entry so it survives context window resets. " +
@@ -43,6 +43,25 @@ async function startMcp() {
43
43
  const result = await service.store(args);
44
44
  return { content: [{ type: "text", text: result.message }] };
45
45
  });
46
+ server.registerTool("memory_digest", {
47
+ title: "Digest a session",
48
+ description: "Extract facts, decisions, roles and history from a conversation transcript and store " +
49
+ "them automatically (exact duplicates are skipped). Call at the end of a session with " +
50
+ "the transcript or a detailed summary of it. Requires REMEMBRA_LLM + an API key.",
51
+ inputSchema: {
52
+ transcript: z
53
+ .string()
54
+ .describe("Conversation transcript or a detailed summary of the session"),
55
+ scope: z.string().optional().describe("Scope for extracted memories (default: global)"),
56
+ source: z.string().optional().describe("Originating session/client"),
57
+ },
58
+ }, async ({ transcript, scope, source }) => {
59
+ const result = await service.digest({ transcript, scope, source });
60
+ const text = `Digest complete: ${result.extracted} extracted, ${result.stored.length} stored, ` +
61
+ `${result.skippedDuplicates} duplicates skipped.` +
62
+ (result.ids.length ? `\nStored ids: ${result.ids.join(", ")}` : "");
63
+ return { content: [{ type: "text", text }] };
64
+ });
46
65
  server.registerTool("memory_search", {
47
66
  title: "Search memories",
48
67
  description: "Retrieve relevant memories from external storage. Call this at the start of a session " +
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/llm.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Pluggable LLM provider for session-digest extraction (v2).
3
+ *
4
+ * Config: REMEMBRA_LLM=openai|anthropic|ollama (default: openai)
5
+ * Keys: OPENAI_API_KEY / ANTHROPIC_API_KEY / OLLAMA_HOST (default localhost:11434)
6
+ *
7
+ * No SDK dependencies — plain fetch against each provider's HTTP API.
8
+ */
9
+ export type LlmProvider = "openai" | "anthropic" | "ollama";
10
+ export interface ExtractedMemory {
11
+ type: "fact" | "decision" | "role" | "history";
12
+ content: string;
13
+ tags: string[];
14
+ importance: number;
15
+ /** Optional scope override; falls back to the digest call's scope. */
16
+ scope?: string;
17
+ }
18
+ export declare function resolveLlmProvider(): LlmProvider;
19
+ export declare function extractMemories(transcript: string, provider?: LlmProvider): Promise<ExtractedMemory[]>;
20
+ /** Parse the model's reply into extracted memories, tolerating code fences. */
21
+ export declare function parseExtraction(raw: string): ExtractedMemory[];
package/dist/llm.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Pluggable LLM provider for session-digest extraction (v2).
3
+ *
4
+ * Config: REMEMBRA_LLM=openai|anthropic|ollama (default: openai)
5
+ * Keys: OPENAI_API_KEY / ANTHROPIC_API_KEY / OLLAMA_HOST (default localhost:11434)
6
+ *
7
+ * No SDK dependencies — plain fetch against each provider's HTTP API.
8
+ */
9
+ export function resolveLlmProvider() {
10
+ const v = (process.env.REMEMBRA_LLM ?? "openai").toLowerCase();
11
+ if (v === "openai" || v === "anthropic" || v === "ollama")
12
+ return v;
13
+ throw new Error(`Invalid REMEMBRA_LLM "${v}" — expected openai|anthropic|ollama`);
14
+ }
15
+ const SYSTEM_PROMPT = `You extract long-term memories from a conversation transcript.
16
+ Return ONLY a JSON array (no prose, no markdown fence). Each element:
17
+ {"type":"fact"|"decision"|"role"|"history","content":"<standalone statement>","tags":["..."],"importance":1-5}
18
+
19
+ Rules:
20
+ - "fact": stable knowledge worth keeping. "decision": a choice already made.
21
+ - "role": standing instruction/preference about how to behave. "history": condensed chronology of past work.
22
+ - Write each content as a self-contained statement (no "we discussed" or "earlier").
23
+ - Skip small talk, pleasantries, and anything already obvious from the transcript's task.
24
+ - importance: 5 = critical, 1 = trivia. Default 3.
25
+ - If nothing is worth keeping, return [].
26
+ - Output must be valid JSON parseable directly.`;
27
+ export async function extractMemories(transcript, provider = resolveLlmProvider()) {
28
+ const text = await chat(provider, SYSTEM_PROMPT, transcript);
29
+ return parseExtraction(text);
30
+ }
31
+ async function chat(provider, system, user) {
32
+ switch (provider) {
33
+ case "openai": {
34
+ const key = process.env.OPENAI_API_KEY;
35
+ if (!key)
36
+ throw new Error("REMEMBRA_LLM=openai requires OPENAI_API_KEY");
37
+ return postJson("https://api.openai.com/v1/chat/completions", {
38
+ headers: { authorization: `Bearer ${key}` },
39
+ body: {
40
+ model: process.env.REMEMBRA_LLM_MODEL ?? "gpt-4o-mini",
41
+ temperature: 0,
42
+ response_format: { type: "json_object" },
43
+ messages: [
44
+ { role: "system", content: system },
45
+ { role: "user", content: user },
46
+ ],
47
+ },
48
+ }).then((r) => r.choices[0].message.content);
49
+ }
50
+ case "anthropic": {
51
+ const key = process.env.ANTHROPIC_API_KEY;
52
+ if (!key)
53
+ throw new Error("REMEMBRA_LLM=anthropic requires ANTHROPIC_API_KEY");
54
+ return postJson("https://api.anthropic.com/v1/messages", {
55
+ headers: {
56
+ "x-api-key": key,
57
+ "anthropic-version": "2023-06-01",
58
+ },
59
+ body: {
60
+ model: process.env.REMEMBRA_LLM_MODEL ?? "claude-haiku-4-5",
61
+ max_tokens: 4096,
62
+ system,
63
+ messages: [{ role: "user", content: user }],
64
+ },
65
+ }).then((r) => r.content[0].text);
66
+ }
67
+ case "ollama": {
68
+ const host = process.env.OLLAMA_HOST ?? "http://localhost:11434";
69
+ return postJson(`${host}/api/chat`, {
70
+ body: {
71
+ model: process.env.REMEMBRA_LLM_MODEL ?? "llama3.2",
72
+ format: "json",
73
+ stream: false,
74
+ messages: [
75
+ { role: "system", content: system },
76
+ { role: "user", content: user },
77
+ ],
78
+ },
79
+ }).then((r) => r.message.content);
80
+ }
81
+ }
82
+ }
83
+ async function postJson(url, opts) {
84
+ const res = await fetch(url, {
85
+ method: "POST",
86
+ headers: { "content-type": "application/json", ...opts.headers },
87
+ body: JSON.stringify(opts.body),
88
+ });
89
+ if (!res.ok) {
90
+ const detail = await res.text().catch(() => "");
91
+ throw new Error(`LLM request failed (${res.status} ${url}): ${detail.slice(0, 300)}`);
92
+ }
93
+ return res.json();
94
+ }
95
+ /** Parse the model's reply into extracted memories, tolerating code fences. */
96
+ export function parseExtraction(raw) {
97
+ let text = raw.trim();
98
+ text = text.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
99
+ const start = text.indexOf("[");
100
+ const end = text.lastIndexOf("]");
101
+ if (start !== -1 && end > start)
102
+ text = text.slice(start, end + 1);
103
+ let parsed;
104
+ try {
105
+ parsed = JSON.parse(text);
106
+ }
107
+ catch {
108
+ // Some models wrap it as {"memories":[...]} — try once more.
109
+ try {
110
+ const obj = JSON.parse(raw.trim());
111
+ parsed = Array.isArray(obj) ? obj : (obj.memories ?? obj.items ?? []);
112
+ }
113
+ catch {
114
+ throw new Error(`Could not parse extraction output: ${raw.slice(0, 200)}`);
115
+ }
116
+ }
117
+ if (!Array.isArray(parsed))
118
+ return [];
119
+ const out = [];
120
+ for (const item of parsed) {
121
+ if (!item || typeof item !== "object")
122
+ continue;
123
+ const type = item.type;
124
+ const content = item.content;
125
+ if (typeof content !== "string" || !content.trim())
126
+ continue;
127
+ if (type !== "fact" && type !== "decision" && type !== "role" && type !== "history")
128
+ continue;
129
+ const tags = item.tags;
130
+ const importance = Number(item.importance);
131
+ const scope = item.scope;
132
+ out.push({
133
+ type,
134
+ content: content.trim(),
135
+ tags: Array.isArray(tags) ? tags.filter((t) => typeof t === "string") : [],
136
+ importance: Number.isFinite(importance) ? Math.min(5, Math.max(1, Math.round(importance))) : 3,
137
+ scope: typeof scope === "string" && scope.trim() ? scope.trim() : undefined,
138
+ });
139
+ }
140
+ return out;
141
+ }
142
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,sCAAsC,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,aAAa,GAAG;;;;;;;;;;;gDAW0B,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,WAAwB,kBAAkB,EAAE;IAE5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;IAC7D,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,QAAqB,EAAE,MAAc,EAAE,IAAY;IACrE,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YACvC,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACzE,OAAO,QAAQ,CAAC,4CAA4C,EAAE;gBAC5D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,GAAG,EAAE,EAAE;gBAC3C,IAAI,EAAE;oBACJ,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,aAAa;oBACtD,WAAW,EAAE,CAAC;oBACd,eAAe,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;oBACxC,QAAQ,EAAE;wBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;wBACnC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;qBAChC;iBACF;aACF,CAAC,CAAC,IAAI,CAAC,CAAC,CAAkD,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChG,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAC1C,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YAC/E,OAAO,QAAQ,CAAC,uCAAuC,EAAE;gBACvD,OAAO,EAAE;oBACP,WAAW,EAAE,GAAG;oBAChB,mBAAmB,EAAE,YAAY;iBAClC;gBACD,IAAI,EAAE;oBACJ,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,kBAAkB;oBAC3D,UAAU,EAAE,IAAI;oBAChB,MAAM;oBACN,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iBAC5C;aACF,CAAC,CAAC,IAAI,CAAC,CAAC,CAAkC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,wBAAwB,CAAC;YACjE,OAAO,QAAQ,CAAC,GAAG,IAAI,WAAW,EAAE;gBAClC,IAAI,EAAE;oBACJ,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,UAAU;oBACnD,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,KAAK;oBACb,QAAQ,EAAE;wBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;wBACnC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;qBAChC;iBACF;aACF,CAAC,CAAC,IAAI,CAAC,CAAC,CAAmC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,GAAW,EACX,IAAyD;IAEzD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;QAChE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK;QAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IAEnE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,SAAS;QAChD,MAAM,IAAI,GAAI,IAAgC,CAAC,IAAI,CAAC;QACpD,MAAM,OAAO,GAAI,IAAgC,CAAC,OAAO,CAAC;QAC1D,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,SAAS;QAC7D,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QAC9F,MAAM,IAAI,GAAI,IAAgC,CAAC,IAAI,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,CAAE,IAAgC,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,KAAK,GAAI,IAAgC,CAAC,KAAK,CAAC;QACtD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI;YACJ,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;YACvB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACvF,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9F,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;SAC5E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,10 +1,15 @@
1
1
  import { Memory, SearchQuery } from "./types.js";
2
2
  /**
3
- * Layered retrieval (decision from Q4):
4
- * 1. Roles always pass (they are instructions).
5
- * 2. Scope match (global + current scope beat other scopes).
6
- * 3. Importance, recency, and keyword overlap contribute to the score.
3
+ * Layered retrieval (decisions Q4 + v2-Q3):
7
4
  *
8
- * Embeddings can replace the keyword part later without changing callers.
5
+ * Hard gates (never bypassed by scores):
6
+ * - roles always pass (+1000)
7
+ * - other scopes' memories are excluded entirely
8
+ *
9
+ * Ranking:
10
+ * - embeddings ON (queryVec provided): semantic similarity is the primary
11
+ * signal; importance + recency act as modifiers; keywords still help as
12
+ * a tie-breaker for memories missing vectors.
13
+ * - embeddings OFF: keyword overlap is the primary signal (v1 behavior).
9
14
  */
10
- export declare function search(memories: Memory[], q: SearchQuery): Memory[];
15
+ export declare function search(memories: Memory[], q: SearchQuery, queryVec?: number[] | null): Memory[];
package/dist/retrieval.js CHANGED
@@ -1,12 +1,18 @@
1
+ import { cosine } from "./embeddings.js";
1
2
  /**
2
- * Layered retrieval (decision from Q4):
3
- * 1. Roles always pass (they are instructions).
4
- * 2. Scope match (global + current scope beat other scopes).
5
- * 3. Importance, recency, and keyword overlap contribute to the score.
3
+ * Layered retrieval (decisions Q4 + v2-Q3):
6
4
  *
7
- * Embeddings can replace the keyword part later without changing callers.
5
+ * Hard gates (never bypassed by scores):
6
+ * - roles always pass (+1000)
7
+ * - other scopes' memories are excluded entirely
8
+ *
9
+ * Ranking:
10
+ * - embeddings ON (queryVec provided): semantic similarity is the primary
11
+ * signal; importance + recency act as modifiers; keywords still help as
12
+ * a tie-breaker for memories missing vectors.
13
+ * - embeddings OFF: keyword overlap is the primary signal (v1 behavior).
8
14
  */
9
- export function search(memories, q) {
15
+ export function search(memories, q, queryVec) {
10
16
  const now = Date.now();
11
17
  const terms = (q.query ?? "")
12
18
  .toLowerCase()
@@ -14,38 +20,64 @@ export function search(memories, q) {
14
20
  .filter((t) => t.length > 1);
15
21
  const scored = memories
16
22
  .filter((m) => (q.type ? m.type === q.type : true))
17
- .map((m) => ({ m, score: score(m, terms, q.scope, now) }))
23
+ .map((m) => ({ m, score: score(m, terms, q.scope, now, queryVec) }))
18
24
  .filter(({ m, score }) => m.type === "role" || score > 0)
19
25
  .sort((a, b) => b.score - a.score || b.m.updatedAt.localeCompare(a.m.updatedAt));
20
26
  return scored.slice(0, q.limit ?? 10).map(({ m }) => m);
21
27
  }
22
- function score(m, terms, scope, now) {
28
+ function score(m, terms, scope, now, queryVec) {
23
29
  let s = 0;
30
+ // --- hard gates ---
24
31
  if (m.type === "role")
25
32
  s += 1000;
33
+ if (scope && m.scope !== scope && m.scope !== "global")
34
+ return 0; // no cross-project leaks
26
35
  if (m.scope === "global")
27
36
  s += 100;
28
37
  if (scope && m.scope === scope)
29
38
  s += 150;
30
- if (scope && m.scope !== scope && m.scope !== "global")
31
- return 0; // other projects' memories don't leak in
32
- s += m.importance * 10;
33
- // Recency: half-life of ~30 days.
34
- const ageDays = (now - Date.parse(m.updatedAt)) / 86_400_000;
35
- if (!Number.isNaN(ageDays))
36
- s += Math.max(0, 20 - ageDays / 3);
37
- // Keyword overlap over content + tags.
38
- if (terms.length > 0) {
39
- const hay = (m.content + " " + m.tags.join(" ")).toLowerCase();
40
- let hits = 0;
41
- for (const t of terms)
42
- if (hay.includes(t))
43
- hits++;
44
- s += (hits / terms.length) * 60;
39
+ // --- semantic mode (embeddings on) ---
40
+ if (queryVec && queryVec.length > 0) {
41
+ if (m.embedding && m.embedding.length > 0) {
42
+ // Primary signal: cosine similarity (0..1 → up to +100).
43
+ const sim = Math.max(0, cosine(queryVec, m.embedding));
44
+ s += sim * 100;
45
+ // Similarity gate: near-zero matches only survive on role/scope strength.
46
+ if (sim < 0.05 && m.type !== "role" && m.scope !== "global" && scope !== m.scope)
47
+ return 0;
48
+ }
49
+ else {
50
+ // Memory without a vector: fall back to keyword scoring for it.
51
+ s += keywordScore(m, terms);
52
+ }
53
+ // Modifiers (smaller weight than keywords-only mode).
54
+ s += m.importance * 4;
55
+ s += recencyScore(m, now) * 0.5;
56
+ return s;
45
57
  }
46
- else {
58
+ // --- keyword mode (embeddings off — v1 behavior) ---
59
+ s += m.importance * 10;
60
+ s += recencyScore(m, now);
61
+ if (terms.length > 0)
62
+ s += keywordScore(m, terms);
63
+ else
47
64
  s += 10; // no query: everything eligible scores a little
48
- }
49
65
  return s;
50
66
  }
67
+ function recencyScore(m, now) {
68
+ const ageDays = (now - Date.parse(m.updatedAt)) / 86_400_000;
69
+ if (Number.isNaN(ageDays))
70
+ return 0;
71
+ return Math.max(0, 20 - ageDays / 3);
72
+ }
73
+ function keywordScore(m, terms) {
74
+ if (terms.length === 0)
75
+ return 0;
76
+ const hay = (m.content + " " + m.tags.join(" ")).toLowerCase();
77
+ let hits = 0;
78
+ for (const t of terms)
79
+ if (hay.includes(t))
80
+ hits++;
81
+ return (hits / terms.length) * 60;
82
+ }
51
83
  //# sourceMappingURL=retrieval.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"retrieval.js","sourceRoot":"","sources":["../src/retrieval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"retrieval.js","sourceRoot":"","sources":["../src/retrieval.ts"],"names":[],"mappings":"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"}
package/dist/service.d.ts CHANGED
@@ -1,16 +1,35 @@
1
1
  import { MemoryStore } from "./store.js";
2
- import { MemoryType } from "./types.js";
2
+ import { MemoryType, Memory } from "./types.js";
3
+ import { EmbeddingProvider } from "./embeddings.js";
4
+ import { LlmProvider, ExtractedMemory } from "./llm.js";
5
+ export interface DigestResult {
6
+ extracted: number;
7
+ stored: Memory[];
8
+ skippedDuplicates: number;
9
+ ids: string[];
10
+ }
11
+ interface ServiceDeps {
12
+ embeddingProvider?: EmbeddingProvider;
13
+ llmProvider?: LlmProvider;
14
+ /** Injection points for tests. */
15
+ embedFn?: (text: string) => Promise<number[]>;
16
+ extractFn?: (transcript: string) => Promise<ExtractedMemory[]>;
17
+ }
3
18
  /**
4
19
  * Transport-agnostic handlers. Both the MCP tools and the HTTP API
5
20
  * call into this module, so behavior is guaranteed to match.
6
21
  */
7
22
  export declare class MemoryService {
8
23
  readonly db: MemoryStore;
9
- constructor(db: MemoryStore);
24
+ private readonly embedFn?;
25
+ private readonly extractFn?;
26
+ constructor(db: MemoryStore, deps?: ServiceDeps);
27
+ get embeddingsEnabled(): boolean;
28
+ private maybeEmbed;
10
29
  store(input: unknown): Promise<{
11
30
  id: string;
12
31
  message: string;
13
- memory: import("./types.js").Memory;
32
+ memory: Memory;
14
33
  }>;
15
34
  search(q: {
16
35
  query?: string;
@@ -19,17 +38,27 @@ export declare class MemoryService {
19
38
  limit?: number;
20
39
  }): Promise<{
21
40
  text: string;
22
- results: import("./types.js").Memory[];
41
+ results: Memory[];
23
42
  }>;
24
43
  list(q: {
25
44
  scope?: string;
26
45
  type?: MemoryType;
27
46
  }): Promise<{
28
47
  text: string;
29
- memories: import("./types.js").Memory[];
48
+ memories: Memory[];
30
49
  }>;
31
50
  forget(id: string): Promise<{
32
51
  ok: boolean;
33
52
  text: string;
34
53
  }>;
54
+ /**
55
+ * Session digest (v2): extract worth-keeping memories from a transcript
56
+ * and store them, skipping exact duplicates already present.
57
+ */
58
+ digest(opts: {
59
+ transcript: string;
60
+ scope?: string;
61
+ source?: string;
62
+ }): Promise<DigestResult>;
35
63
  }
64
+ export {};
package/dist/service.js CHANGED
@@ -1,16 +1,49 @@
1
1
  import { search } from "./retrieval.js";
2
2
  import { StoreInput } from "./types.js";
3
+ import { resolveEmbeddingProvider, embedText } from "./embeddings.js";
4
+ import { resolveLlmProvider, extractMemories } from "./llm.js";
3
5
  /**
4
6
  * Transport-agnostic handlers. Both the MCP tools and the HTTP API
5
7
  * call into this module, so behavior is guaranteed to match.
6
8
  */
7
9
  export class MemoryService {
8
10
  db;
9
- constructor(db) {
11
+ embedFn;
12
+ extractFn;
13
+ constructor(db, deps = {}) {
10
14
  this.db = db;
15
+ const emb = deps.embeddingProvider ?? resolveEmbeddingProvider();
16
+ const llm = deps.llmProvider ?? resolveLlmProvider();
17
+ this.embedFn =
18
+ deps.embedFn ??
19
+ (emb === "none"
20
+ ? undefined
21
+ : async (text) => embedText(text, emb));
22
+ // Extraction is resolved lazily inside the call so search/store work
23
+ // even when no LLM key is configured.
24
+ this.extractFn =
25
+ deps.extractFn ??
26
+ (async (transcript) => extractMemories(transcript, llm));
27
+ }
28
+ get embeddingsEnabled() {
29
+ return this.embedFn !== undefined;
30
+ }
31
+ async maybeEmbed(text) {
32
+ if (!this.embedFn)
33
+ return undefined;
34
+ try {
35
+ return await this.embedFn(text);
36
+ }
37
+ catch (err) {
38
+ // Degrade to keyword mode rather than failing the write.
39
+ console.error(`Remembra: embedding failed (${err instanceof Error ? err.message : err}); continuing without`);
40
+ return undefined;
41
+ }
11
42
  }
12
43
  async store(input) {
13
- const memory = await this.db.store(StoreInput.parse(input));
44
+ const parsed = StoreInput.parse(input);
45
+ const embedding = await this.maybeEmbed(parsed.content);
46
+ const memory = await this.db.store(parsed, embedding);
14
47
  return {
15
48
  id: memory.id,
16
49
  message: `Stored ${memory.type} memory ${memory.id} (scope: ${memory.scope})`,
@@ -18,7 +51,10 @@ export class MemoryService {
18
51
  };
19
52
  }
20
53
  async search(q) {
21
- const results = search(await this.db.all(), q);
54
+ let queryVec = null;
55
+ if (q.query && this.embedFn)
56
+ queryVec = (await this.maybeEmbed(q.query)) ?? null;
57
+ const results = search(await this.db.all(), q, queryVec);
22
58
  const text = results.length === 0
23
59
  ? "No matching memories."
24
60
  : results
@@ -42,5 +78,44 @@ export class MemoryService {
42
78
  const ok = await this.db.forget(id);
43
79
  return { ok, text: ok ? `Deleted memory ${id}.` : `No memory with id ${id}.` };
44
80
  }
81
+ /**
82
+ * Session digest (v2): extract worth-keeping memories from a transcript
83
+ * and store them, skipping exact duplicates already present.
84
+ */
85
+ async digest(opts) {
86
+ const extracted = await this.extractFn(opts.transcript);
87
+ const existing = await this.db.all();
88
+ const seen = new Set(existing.map((m) => dedupKey(m.type, m.content, m.scope)));
89
+ const stored = [];
90
+ let skippedDuplicates = 0;
91
+ for (const item of extracted) {
92
+ const scope = item.scope ?? opts.scope ?? "global";
93
+ const key = dedupKey(item.type, item.content, scope);
94
+ if (seen.has(key)) {
95
+ skippedDuplicates++;
96
+ continue;
97
+ }
98
+ seen.add(key);
99
+ const { memory } = await this.store({
100
+ type: item.type,
101
+ content: item.content,
102
+ scope,
103
+ tags: item.tags,
104
+ importance: item.importance,
105
+ source: opts.source,
106
+ });
107
+ stored.push(memory);
108
+ }
109
+ return {
110
+ extracted: extracted.length,
111
+ stored,
112
+ skippedDuplicates,
113
+ ids: stored.map((m) => m.id),
114
+ };
115
+ }
116
+ }
117
+ /** Normalized identity for exact-match dedup (v2; LLM merge comes in v3). */
118
+ function dedupKey(type, content, scope) {
119
+ return `${type}|${scope}|${content.toLowerCase().replace(/\s+/g, " ").trim()}`;
45
120
  }
46
121
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/dist/store.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare class MemoryStore {
14
14
  constructor(root: string);
15
15
  static defaultRoot(): string;
16
16
  private fileFor;
17
- store(input: StoreInput): Promise<Memory>;
17
+ store(input: StoreInput, embedding?: number[]): Promise<Memory>;
18
18
  forget(id: string): Promise<boolean>;
19
19
  /** Load every memory across all scopes (global + scoped). */
20
20
  all(): Promise<Memory[]>;
package/dist/store.js CHANGED
@@ -27,7 +27,7 @@ export class MemoryStore {
27
27
  const safeScope = m.scope.replace(/[^a-zA-Z0-9._/-]/g, "_");
28
28
  return path.join(this.root, "scopes", safeScope, `${m.id}.md`);
29
29
  }
30
- async store(input) {
30
+ async store(input, embedding) {
31
31
  const now = new Date().toISOString();
32
32
  const memory = {
33
33
  id: randomUUID().slice(0, 8),
@@ -39,6 +39,7 @@ export class MemoryStore {
39
39
  createdAt: now,
40
40
  updatedAt: now,
41
41
  source: input.source,
42
+ embedding,
42
43
  };
43
44
  const file = this.fileFor(memory);
44
45
  await fs.mkdir(path.dirname(file), { recursive: true });
@@ -103,6 +104,7 @@ function render(m) {
103
104
  `created: ${m.createdAt}`,
104
105
  `updated: ${m.updatedAt}`,
105
106
  m.source ? `source: ${m.source}` : undefined,
107
+ m.embedding && m.embedding.length > 0 ? `embedding: [${m.embedding.join(",")}]` : undefined,
106
108
  "---",
107
109
  "",
108
110
  m.content,
@@ -124,6 +126,12 @@ async function parse(file) {
124
126
  meta[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
125
127
  }
126
128
  const tagsRaw = (meta.tags ?? "[]").replace(/^\[|\]$/g, "");
129
+ let embedding;
130
+ if (meta.embedding) {
131
+ const nums = meta.embedding.replace(/^\[|\]$/g, "").split(",").map(Number);
132
+ if (nums.length > 0 && nums.every((n) => Number.isFinite(n)))
133
+ embedding = nums;
134
+ }
127
135
  return {
128
136
  id: meta.id ?? path.basename(file, ".md"),
129
137
  type: (meta.type ?? "fact"),
@@ -134,6 +142,7 @@ async function parse(file) {
134
142
  createdAt: meta.created ?? new Date(0).toISOString(),
135
143
  updatedAt: meta.updated ?? meta.created ?? new Date(0).toISOString(),
136
144
  source: meta.source,
145
+ embedding,
137
146
  };
138
147
  }
139
148
  catch {
package/dist/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;;;;;;GASG;AACH,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAE7C,MAAM,CAAC,WAAW;QAChB,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;IAC3E,CAAC;IAEO,OAAO,CAAC,CAAS;QACvB,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAiB;QAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAW;YACrB,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;YACd,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,GAAG;QACP,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YACnF,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzF,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IACnE,CAAC;CACF;AAED,KAAK,UAAU,IAAI,CAAC,GAAG,IAAc;IACnC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;iBAChD,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,MAAM,KAAK,GAAG;QACZ,KAAK;QACL,OAAO,CAAC,CAAC,EAAE,EAAE;QACb,SAAS,CAAC,CAAC,IAAI,EAAE;QACjB,UAAU,CAAC,CAAC,KAAK,EAAE;QACnB,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC9B,eAAe,CAAC,CAAC,UAAU,EAAE;QAC7B,YAAY,CAAC,CAAC,SAAS,EAAE;QACzB,YAAY,CAAC,CAAC,SAAS,EAAE;QACzB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;QAC5C,KAAK;QACL,EAAE;QACF,CAAC,CAAC,OAAO;QACT,EAAE;KACH,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAChE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,IAAI,GAA2B,EAAE,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,SAAS;YACzB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;YACzC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,MAAM,CAAmB;YAC7C,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,QAAQ;YAC7B,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;YAC5D,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;YACxC,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YACpD,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YACpE,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -18,6 +18,8 @@ export interface Memory {
18
18
  createdAt: string;
19
19
  updatedAt: string;
20
20
  source?: string;
21
+ /** Cached embedding vector (REMEMBRA_EMBEDDINGS≠none); serialized in frontmatter. */
22
+ embedding?: number[];
21
23
  }
22
24
  export declare const StoreInput: z.ZodObject<{
23
25
  type: z.ZodEnum<["fact", "decision", "role", "history"]>;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,6CAA6C;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AAsB1E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,6CAA6C;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AAwB1E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC"}
package/docs/chatgpt.md CHANGED
@@ -70,6 +70,17 @@ curl -X DELETE http://localhost:8787/memories/<id> \
70
70
  -H "x-api-key: $REMEMBRA_API_KEY"
71
71
  ```
72
72
 
73
+ ### Digest a session (LLM extraction)
74
+
75
+ ```bash
76
+ curl -X POST http://localhost:8787/memories/digest \
77
+ -H "content-type: application/json" \
78
+ -H "x-api-key: $REMEMBRA_API_KEY" \
79
+ -d '{"transcript":"<conversation text>","scope":"chatgpt"}'
80
+ ```
81
+
82
+ Requires `REMEMBRA_LLM` + key — see [providers.md](providers.md).
83
+
73
84
  ## 3. Create the Custom GPT
74
85
 
75
86
  1. Go to **chatgpt.com → Explore GPTs → Create a GPT**.
package/docs/clients.md CHANGED
@@ -86,6 +86,10 @@ REMEMBRA_API_KEY="your-secret" remembra --http
86
86
  | `REMEMBRA_HOME` | `~/.remembra` | Where memory files live |
87
87
  | `REMEMBRA_API_KEY` | *(unset)* | Enables auth on the HTTP API |
88
88
  | `REMEMBRA_PORT` | `8787` | HTTP API port (`--port` overrides) |
89
+ | `REMEMBRA_LLM` | `openai` | Digest LLM: `openai` \| `anthropic` \| `ollama` |
90
+ | `REMEMBRA_EMBEDDINGS` | `none` | Semantic search: `openai` \| `ollama` \| `none` |
91
+
92
+ LLM/embedding key setup: see **[providers.md](providers.md)**.
89
93
 
90
94
  ## Tips
91
95
 
@@ -0,0 +1,107 @@
1
+ # AI Providers & Session Digest (v2)
2
+
3
+ Remembra can call an LLM to extract memories automatically (**session digest**)
4
+ and use embeddings for semantic search. Both are pluggable and off-by-default
5
+ where possible, so a plain keyword install still works with zero API keys.
6
+
7
+ ## Configuration
8
+
9
+ | Variable | Values | Default | Purpose |
10
+ |----------|--------|---------|---------|
11
+ | `REMEMBRA_LLM` | `openai` \| `anthropic` \| `ollama` | `openai` | Which LLM does digest extraction |
12
+ | `REMEMBRA_LLM_MODEL` | provider model id | provider default | Override the extraction model |
13
+ | `REMEMBRA_EMBEDDINGS` | `openai` \| `ollama` \| `none` | `none` | Semantic search provider |
14
+ | `REMEMBRA_EMBEDDING_MODEL` | provider model id | provider default | Override the embedding model |
15
+ | `OPENAI_API_KEY` | — | — | Required when provider = openai |
16
+ | `ANTHROPIC_API_KEY` | — | — | Required when provider = anthropic |
17
+ | `OLLAMA_HOST` | URL | `http://localhost:11434` | Ollama endpoint (LLM and/or embeddings) |
18
+
19
+ ### Examples
20
+
21
+ ```bash
22
+ # OpenAI for both (simplest hosted setup)
23
+ export OPENAI_API_KEY=sk-...
24
+ export REMEMBRA_LLM=openai
25
+ export REMEMBRA_EMBEDDINGS=openai
26
+
27
+ # Fully local with Ollama — no API keys
28
+ export REMEMBRA_LLM=ollama
29
+ export REMEMBRA_LLM_MODEL=llama3.2
30
+ export REMEMBRA_EMBEDDINGS=ollama
31
+ export REMEMBRA_EMBEDDING_MODEL=nomic-embed-text
32
+
33
+ # Anthropic for extraction, semantic search off (keyword mode)
34
+ export ANTHROPIC_API_KEY=sk-ant-...
35
+ export REMEMBRA_LLM=anthropic
36
+ ```
37
+
38
+ ## Session digest
39
+
40
+ Instead of the model remembering to call `memory_store` for every little thing,
41
+ hand the whole conversation to one tool at the end of a session:
42
+
43
+ ```
44
+ memory_digest {
45
+ transcript: "<full transcript or a detailed summary>",
46
+ scope: "/path/to/project", // optional, default global
47
+ source: "opencode" // optional
48
+ }
49
+ ```
50
+
51
+ Remembra asks the configured LLM to extract **facts, decisions, roles, and
52
+ history**, then stores each one — **skipping exact duplicates** that are
53
+ already present (normalized by type + scope + content). Running a digest twice
54
+ over the same conversation is a no-op.
55
+
56
+ HTTP equivalent:
57
+
58
+ ```bash
59
+ curl -X POST http://localhost:8787/memories/digest \
60
+ -H "content-type: application/json" \
61
+ -H "x-api-key: $REMEMBRA_API_KEY" \
62
+ -d '{"transcript":"...","scope":"chatgpt","source":"chatgpt"}'
63
+ ```
64
+
65
+ Response:
66
+
67
+ ```json
68
+ {
69
+ "extracted": 4,
70
+ "stored": [ ... ],
71
+ "skippedDuplicates": 2,
72
+ "ids": ["a1b2c3d4", "..."]
73
+ }
74
+ ```
75
+
76
+ > **Note:** the digest LLM key is only needed when you actually call
77
+ > `memory_digest` — storage and search work without it.
78
+
79
+ ## Semantic search
80
+
81
+ With `REMEMBRA_EMBEDDINGS=openai|ollama`:
82
+
83
+ - **On write**: every stored memory gets an embedding, cached in its
84
+ frontmatter (`embedding: [...]`) — computed once, never re-embedded.
85
+ - **On search**: the query is embedded and **cosine similarity becomes the
86
+ primary ranking signal**. Importance and recency remain small modifiers.
87
+ - **Gates stay absolute**: `role` memories always surface, and memories from
88
+ other scopes are never returned, no matter how similar.
89
+ - **Memories without vectors** (stored while embeddings were off) fall back
90
+ to keyword matching.
91
+
92
+ With `REMEMBRA_EMBEDDINGS=none` (default): pure keyword scoring — exactly
93
+ the v1 behavior.
94
+
95
+ ### Backfilling vectors
96
+
97
+ Memories stored before you enabled embeddings have no vectors. They still
98
+ work (keyword fallback), but to bring them into semantic search, re-store
99
+ them or wait for v3's maintenance commands.
100
+
101
+ ## Failure behavior
102
+
103
+ - **Embedding API fails** → warning logged, write continues without a vector,
104
+ search degrades to keywords. Never blocks storing.
105
+ - **LLM call fails** → `memory_digest` returns the error; nothing is stored.
106
+ - **No keys configured** → MCP/HTTP servers run normally; only `memory_digest`
107
+ errors if invoked.
package/docs/tools.md CHANGED
@@ -64,12 +64,26 @@ Permanently delete a memory.
64
64
 
65
65
  Returns an error result if no memory matches the id.
66
66
 
67
+ ## `memory_digest`
68
+
69
+ Extract memories from a conversation transcript using the configured LLM and
70
+ store them, skipping exact duplicates. See [providers.md](providers.md).
71
+
72
+ | Argument | Type | Required | Description |
73
+ |----------|------|----------|-------------|
74
+ | `transcript` | string | ✅ | Full transcript or a detailed session summary |
75
+ | `scope` | string | no | Scope for extracted memories (default `global`) |
76
+ | `source` | string | no | Originating session/client |
77
+
78
+ Requires `REMEMBRA_LLM` + its API key (or Ollama). Returns counts:
79
+ extracted / stored / duplicates skipped, plus stored ids.
80
+
67
81
  ---
68
82
 
69
83
  ## Suggested session flow
70
84
 
71
85
  ```
72
- 1. memory_search { scope: <current project> } → recover roles, facts, decisions
86
+ 1. memory_search { scope: <current project> } → recover roles, facts, decisions
73
87
  2. ... work happens; model calls memory_store when something worth keeping emerges ...
74
- 3. (v2) automatic session digest sweeps anything missed
88
+ 3. memory_digest { transcript, scope } → end-of-session sweep (v2, LLM extracts)
75
89
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hilbras/remembra",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "External memory for AI assistants — remember facts, decisions, roles and history across sessions. MCP server for OpenCode, Claude Code, Cline, Kimi Code and more.",
5
5
  "type": "module",
6
6
  "bin": {