@hilbras/remembra 0.2.0 → 0.4.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 +41 -0
- package/README.md +9 -3
- package/dist/embeddings.d.ts +12 -0
- package/dist/embeddings.js +65 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/http.js +18 -0
- package/dist/http.js.map +1 -1
- package/dist/index.js +42 -2
- package/dist/index.js.map +1 -1
- package/dist/llm.d.ts +33 -0
- package/dist/llm.js +168 -0
- package/dist/llm.js.map +1 -0
- package/dist/retrieval.d.ts +11 -6
- package/dist/retrieval.js +57 -25
- package/dist/retrieval.js.map +1 -1
- package/dist/service.d.ts +76 -5
- package/dist/service.js +225 -5
- package/dist/service.js.map +1 -1
- package/dist/store.d.ts +18 -8
- package/dist/store.js +83 -17
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js.map +1 -1
- package/docs/chatgpt.md +11 -0
- package/docs/clients.md +6 -0
- package/docs/lifecycle.md +94 -0
- package/docs/providers.md +107 -0
- package/docs/tools.md +27 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,47 @@
|
|
|
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.4.0] — 2026-09-23
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- **Memory lifecycle**: active → downrank → archived (unused 90d, `REMEMBRA_ARCHIVE_AFTER_DAYS`)
|
|
10
|
+
→ deleted (365d after archive, `REMEMBRA_ARCHIVE_TTL_DAYS`). Only archived memories are
|
|
11
|
+
ever auto-deleted; roles never decay.
|
|
12
|
+
- **Decay piggybacks on search** (debounced 1/hour) — free file math; search hits refresh a
|
|
13
|
+
memory's `lastSeen` clock, so used memories stay alive.
|
|
14
|
+
- **Contradiction merge**: digest LLM decisions are now `store | skip | merge` — evolved facts
|
|
15
|
+
update the stored memory in place, preserving the old value as a
|
|
16
|
+
`> superseded (date): ...` note. Fail-open: LLM failure stores fresh.
|
|
17
|
+
- **Revival**: digesting an exact duplicate of an archived memory revives it.
|
|
18
|
+
- **`memory_maintain` tool** + **`POST /maintain`** + **`remembra maintain` CLI** — explicit
|
|
19
|
+
decay sweep + embedding vector backfill.
|
|
20
|
+
- `memory_list` gained `includeArchived`; archived memories show a `[archived]` flag.
|
|
21
|
+
- Store ops: `archive()`, `revive()`, `update()`, `touch()`; `archived/` storage tree.
|
|
22
|
+
- `docs/lifecycle.md` — full lifecycle + merge documentation.
|
|
23
|
+
- 11 new tests (decay, TTL delete, revival, merge decisions, backfill).
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Storage stays file-based (decision: no SQLite — files remain source of truth).
|
|
27
|
+
|
|
28
|
+
## [0.3.0] — 2026-09-23
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- **Session digest**: `memory_digest` tool + `POST /memories/digest` — LLM extracts
|
|
32
|
+
facts/decisions/roles/history from a transcript and stores them.
|
|
33
|
+
- **Pluggable LLM provider**: `REMEMBRA_LLM=openai|anthropic|ollama` (+ `REMEMBRA_LLM_MODEL`).
|
|
34
|
+
- **Pluggable embeddings**: `REMEMBRA_EMBEDDINGS=openai|ollama|none` (default `none`).
|
|
35
|
+
- **Semantic search**: cosine similarity becomes the primary ranking signal when enabled;
|
|
36
|
+
vectors cached in memory frontmatter (computed once on write).
|
|
37
|
+
- Scope and role rules remain hard gates in both ranking modes.
|
|
38
|
+
- Keyword fallback: memories without vectors, and any embedding API failure, degrade
|
|
39
|
+
gracefully to keyword scoring (writes never blocked by embedding errors).
|
|
40
|
+
- Exact-match dedup in digest (type + scope + normalized content) — digests are idempotent.
|
|
41
|
+
- `docs/providers.md` — configuration guide for digest + embeddings.
|
|
42
|
+
- 18 new tests (digest, embeddings, retrieval modes, LLM output parsing).
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- `MemoryService` now accepts optional injected deps (embed/extract) for testing.
|
|
46
|
+
|
|
6
47
|
## [0.2.0] — 2026-09-23
|
|
7
48
|
|
|
8
49
|
### Added
|
package/README.md
CHANGED
|
@@ -89,6 +89,8 @@ 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 |
|
|
93
|
+
| POST | `/maintain` | Decay sweep + vector backfill |
|
|
92
94
|
| DELETE | `/memories/:id` | Forget |
|
|
93
95
|
|
|
94
96
|
All routes except `/health` require `x-api-key` (or `Authorization: Bearer`) when
|
|
@@ -99,8 +101,10 @@ All routes except `/health` require `x-api-key` (or `Authorization: Bearer`) whe
|
|
|
99
101
|
| Tool | Purpose |
|
|
100
102
|
|------|---------|
|
|
101
103
|
| `memory_store` | Save a fact / decision / role / history |
|
|
104
|
+
| `memory_digest` | Extract + store memories from a transcript (LLM) |
|
|
102
105
|
| `memory_search` | Retrieve relevant memories (pass `scope` = current project) |
|
|
103
106
|
| `memory_list` | Browse stored memories |
|
|
107
|
+
| `memory_maintain` | Archive decayed / delete expired / backfill vectors |
|
|
104
108
|
| `memory_forget` | Delete by id |
|
|
105
109
|
|
|
106
110
|
Full reference: **[docs/tools.md](docs/tools.md)**
|
|
@@ -113,6 +117,8 @@ Full reference: **[docs/tools.md](docs/tools.md)**
|
|
|
113
117
|
| [Tool reference](docs/tools.md) | Every MCP tool with arguments |
|
|
114
118
|
| [Client setup](docs/clients.md) | Config for each supported tool |
|
|
115
119
|
| [ChatGPT setup](docs/chatgpt.md) | HTTP API + Custom GPT walkthrough |
|
|
120
|
+
| [AI providers](docs/providers.md) | Digest LLM + embeddings configuration |
|
|
121
|
+
| [Lifecycle](docs/lifecycle.md) | Decay, archiving, auto-delete, contradiction merging |
|
|
116
122
|
| [Contributing](CONTRIBUTING.md) | Dev workflow and guidelines |
|
|
117
123
|
| [Changelog](CHANGELOG.md) | Release history |
|
|
118
124
|
|
|
@@ -142,9 +148,9 @@ npm test # run tests
|
|
|
142
148
|
## Roadmap
|
|
143
149
|
|
|
144
150
|
- **v1** — MCP server for coding tools, file storage, layered retrieval ✅
|
|
145
|
-
- **v1.5**
|
|
146
|
-
- **v2** — automatic session-digest extraction, embeddings behind `memory_search`
|
|
147
|
-
- **v3** —
|
|
151
|
+
- **v1.5** — HTTP API + ChatGPT Custom GPT action ✅
|
|
152
|
+
- **v2** — automatic session-digest extraction, embeddings behind `memory_search` ✅
|
|
153
|
+
- **v3** *(current)* — memory lifecycle (archive/decay), contradiction merging, maintenance CLI ✅
|
|
148
154
|
|
|
149
155
|
## License
|
|
150
156
|
|
|
@@ -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,24 @@ 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 /maintain — decay sweep + vector backfill
|
|
24
|
+
if (req.method === "POST" && path === "/maintain") {
|
|
25
|
+
const result = await service.maintain();
|
|
26
|
+
return send(res, 200, result);
|
|
27
|
+
}
|
|
28
|
+
// POST /memories/digest — must be checked before /memories/:id DELETE patterns
|
|
29
|
+
if (req.method === "POST" && path === "/memories/digest") {
|
|
30
|
+
const body = await readBody(req);
|
|
31
|
+
if (typeof body.transcript !== "string" || !body.transcript.trim()) {
|
|
32
|
+
return send(res, 400, { error: "Body must include a non-empty `transcript` string" });
|
|
33
|
+
}
|
|
34
|
+
const result = await service.digest({
|
|
35
|
+
transcript: body.transcript,
|
|
36
|
+
scope: body.scope,
|
|
37
|
+
source: body.source,
|
|
38
|
+
});
|
|
39
|
+
return send(res, 200, result);
|
|
40
|
+
}
|
|
23
41
|
// POST /memories
|
|
24
42
|
if (req.method === "POST" && path === "/memories") {
|
|
25
43
|
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
|
@@ -8,9 +8,16 @@ import { createHttpServer } from "./http.js";
|
|
|
8
8
|
const store = new MemoryStore(MemoryStore.defaultRoot());
|
|
9
9
|
const service = new MemoryService(store);
|
|
10
10
|
const httpFlag = process.argv.includes("--http");
|
|
11
|
+
const maintainFlag = process.argv.includes("maintain");
|
|
11
12
|
const portArg = process.argv.indexOf("--port");
|
|
12
13
|
const port = portArg !== -1 ? Number(process.argv[portArg + 1]) : undefined;
|
|
13
|
-
if (
|
|
14
|
+
if (maintainFlag) {
|
|
15
|
+
// CLI maintenance: `remembra maintain` — one-shot, prints JSON, exits.
|
|
16
|
+
const result = await service.maintain();
|
|
17
|
+
console.log(JSON.stringify(result, null, 2));
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
else if (httpFlag) {
|
|
14
21
|
// HTTP mode: long-running API for non-MCP clients (ChatGPT, scripts, ...).
|
|
15
22
|
createHttpServer(service, {
|
|
16
23
|
port,
|
|
@@ -22,7 +29,7 @@ else {
|
|
|
22
29
|
await startMcp();
|
|
23
30
|
}
|
|
24
31
|
async function startMcp() {
|
|
25
|
-
const server = new McpServer({ name: "remembra", version: "0.
|
|
32
|
+
const server = new McpServer({ name: "remembra", version: "0.4.0" });
|
|
26
33
|
server.registerTool("memory_store", {
|
|
27
34
|
title: "Store a memory",
|
|
28
35
|
description: "Persist a fact, decision, role or history entry so it survives context window resets. " +
|
|
@@ -43,6 +50,39 @@ async function startMcp() {
|
|
|
43
50
|
const result = await service.store(args);
|
|
44
51
|
return { content: [{ type: "text", text: result.message }] };
|
|
45
52
|
});
|
|
53
|
+
server.registerTool("memory_digest", {
|
|
54
|
+
title: "Digest a session",
|
|
55
|
+
description: "Extract facts, decisions, roles and history from a conversation transcript and store " +
|
|
56
|
+
"them automatically (exact duplicates are skipped). Call at the end of a session with " +
|
|
57
|
+
"the transcript or a detailed summary of it. Requires REMEMBRA_LLM + an API key.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
transcript: z
|
|
60
|
+
.string()
|
|
61
|
+
.describe("Conversation transcript or a detailed summary of the session"),
|
|
62
|
+
scope: z.string().optional().describe("Scope for extracted memories (default: global)"),
|
|
63
|
+
source: z.string().optional().describe("Originating session/client"),
|
|
64
|
+
},
|
|
65
|
+
}, async ({ transcript, scope, source }) => {
|
|
66
|
+
const result = await service.digest({ transcript, scope, source });
|
|
67
|
+
const text = `Digest complete: ${result.extracted} extracted, ${result.stored.length} stored, ` +
|
|
68
|
+
`${result.merged} merged/revived, ${result.skippedDuplicates} duplicates skipped.` +
|
|
69
|
+
(result.ids.length ? `\nStored ids: ${result.ids.join(", ")}` : "");
|
|
70
|
+
return { content: [{ type: "text", text }] };
|
|
71
|
+
});
|
|
72
|
+
server.registerTool("memory_maintain", {
|
|
73
|
+
title: "Run maintenance",
|
|
74
|
+
description: "Run maintenance: archive memories unused past REMEMBRA_ARCHIVE_AFTER_DAYS (default 90), " +
|
|
75
|
+
"auto-delete archived memories past REMEMBRA_ARCHIVE_TTL_DAYS (default 365), and backfill " +
|
|
76
|
+
"missing embedding vectors. Roles never decay. Safe to call anytime.",
|
|
77
|
+
inputSchema: {},
|
|
78
|
+
}, async () => {
|
|
79
|
+
const result = await service.maintain();
|
|
80
|
+
const text = `Maintenance complete: ${result.archived.length} archived, ` +
|
|
81
|
+
`${result.deleted.length} deleted, ${result.embedded} vectors backfilled.` +
|
|
82
|
+
(result.archived.length ? `\nArchived: ${result.archived.join(", ")}` : "") +
|
|
83
|
+
(result.deleted.length ? `\nDeleted: ${result.deleted.join(", ")}` : "");
|
|
84
|
+
return { content: [{ type: "text", text }] };
|
|
85
|
+
});
|
|
46
86
|
server.registerTool("memory_search", {
|
|
47
87
|
title: "Search memories",
|
|
48
88
|
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":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;AACzD,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;AAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC/C,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAE5E,IAAI,QAAQ,EAAE,CAAC;
|
|
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,33 @@
|
|
|
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
|
+
export type MergeDecision = {
|
|
21
|
+
action: "store";
|
|
22
|
+
} | {
|
|
23
|
+
action: "skip";
|
|
24
|
+
} | {
|
|
25
|
+
action: "merge";
|
|
26
|
+
content: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function resolveMerge(newContent: string, existing: {
|
|
29
|
+
type: string;
|
|
30
|
+
content: string;
|
|
31
|
+
}, provider?: LlmProvider): Promise<MergeDecision>;
|
|
32
|
+
/** Parse the model's reply into extracted memories, tolerating code fences. */
|
|
33
|
+
export declare function parseExtraction(raw: string): ExtractedMemory[];
|
package/dist/llm.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
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
|
+
const MERGE_PROMPT = `You compare a NEW memory with an EXISTING stored memory and decide what to do.
|
|
96
|
+
Return ONLY JSON: {"action":"store"|"skip"|"merge","content":"<merged text>"}
|
|
97
|
+
|
|
98
|
+
- "skip": they say the same thing (paraphrase is fine) — the existing memory already covers it.
|
|
99
|
+
- "merge": the new one is a newer version of the same fact (a changed value, evolved decision,
|
|
100
|
+
refined wording). "content" = the updated statement ONLY (state the current truth, no history).
|
|
101
|
+
- "store": unrelated or complementary — store it separately.
|
|
102
|
+
Omit "content" unless action is "merge".`;
|
|
103
|
+
export async function resolveMerge(newContent, existing, provider = resolveLlmProvider()) {
|
|
104
|
+
const user = `EXISTING (${existing.type}): ${existing.content}\nNEW: ${newContent}`;
|
|
105
|
+
const raw = await chat(provider, MERGE_PROMPT, user);
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
|
|
109
|
+
parsed = JSON.parse(text);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return { action: "store" }; // fail open: never lose an item because parsing broke
|
|
113
|
+
}
|
|
114
|
+
if (parsed.action === "skip")
|
|
115
|
+
return { action: "skip" };
|
|
116
|
+
if (parsed.action === "merge" && typeof parsed.content === "string" && parsed.content.trim()) {
|
|
117
|
+
return { action: "merge", content: parsed.content.trim() };
|
|
118
|
+
}
|
|
119
|
+
return { action: "store" };
|
|
120
|
+
}
|
|
121
|
+
/** Parse the model's reply into extracted memories, tolerating code fences. */
|
|
122
|
+
export function parseExtraction(raw) {
|
|
123
|
+
let text = raw.trim();
|
|
124
|
+
text = text.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
|
|
125
|
+
const start = text.indexOf("[");
|
|
126
|
+
const end = text.lastIndexOf("]");
|
|
127
|
+
if (start !== -1 && end > start)
|
|
128
|
+
text = text.slice(start, end + 1);
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(text);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Some models wrap it as {"memories":[...]} — try once more.
|
|
135
|
+
try {
|
|
136
|
+
const obj = JSON.parse(raw.trim());
|
|
137
|
+
parsed = Array.isArray(obj) ? obj : (obj.memories ?? obj.items ?? []);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
throw new Error(`Could not parse extraction output: ${raw.slice(0, 200)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!Array.isArray(parsed))
|
|
144
|
+
return [];
|
|
145
|
+
const out = [];
|
|
146
|
+
for (const item of parsed) {
|
|
147
|
+
if (!item || typeof item !== "object")
|
|
148
|
+
continue;
|
|
149
|
+
const type = item.type;
|
|
150
|
+
const content = item.content;
|
|
151
|
+
if (typeof content !== "string" || !content.trim())
|
|
152
|
+
continue;
|
|
153
|
+
if (type !== "fact" && type !== "decision" && type !== "role" && type !== "history")
|
|
154
|
+
continue;
|
|
155
|
+
const tags = item.tags;
|
|
156
|
+
const importance = Number(item.importance);
|
|
157
|
+
const scope = item.scope;
|
|
158
|
+
out.push({
|
|
159
|
+
type,
|
|
160
|
+
content: content.trim(),
|
|
161
|
+
tags: Array.isArray(tags) ? tags.filter((t) => typeof t === "string") : [],
|
|
162
|
+
importance: Number.isFinite(importance) ? Math.min(5, Math.max(1, Math.round(importance))) : 3,
|
|
163
|
+
scope: typeof scope === "string" && scope.trim() ? scope.trim() : undefined,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=llm.js.map
|
package/dist/llm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"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"}
|
package/dist/retrieval.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { Memory, SearchQuery } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Layered retrieval (
|
|
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
|
-
*
|
|
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[];
|