@mono-agent/memory 0.4.1

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 (150) hide show
  1. package/README.md +61 -0
  2. package/dist/bujo/capture.d.ts +20 -0
  3. package/dist/bujo/capture.d.ts.map +1 -0
  4. package/dist/bujo/capture.js +77 -0
  5. package/dist/bujo/capture.js.map +1 -0
  6. package/dist/bujo/cli-env.d.ts +11 -0
  7. package/dist/bujo/cli-env.d.ts.map +1 -0
  8. package/dist/bujo/cli-env.js +30 -0
  9. package/dist/bujo/cli-env.js.map +1 -0
  10. package/dist/bujo/cli.d.ts +3 -0
  11. package/dist/bujo/cli.d.ts.map +1 -0
  12. package/dist/bujo/cli.js +98 -0
  13. package/dist/bujo/cli.js.map +1 -0
  14. package/dist/bujo/consolidate.d.ts +15 -0
  15. package/dist/bujo/consolidate.d.ts.map +1 -0
  16. package/dist/bujo/consolidate.js +61 -0
  17. package/dist/bujo/consolidate.js.map +1 -0
  18. package/dist/bujo/daily.d.ts +17 -0
  19. package/dist/bujo/daily.d.ts.map +1 -0
  20. package/dist/bujo/daily.js +47 -0
  21. package/dist/bujo/daily.js.map +1 -0
  22. package/dist/bujo/distill.d.ts +10 -0
  23. package/dist/bujo/distill.d.ts.map +1 -0
  24. package/dist/bujo/distill.js +50 -0
  25. package/dist/bujo/distill.js.map +1 -0
  26. package/dist/bujo/entities.d.ts +24 -0
  27. package/dist/bujo/entities.d.ts.map +1 -0
  28. package/dist/bujo/entities.js +80 -0
  29. package/dist/bujo/entities.js.map +1 -0
  30. package/dist/bujo/grammar.d.ts +18 -0
  31. package/dist/bujo/grammar.d.ts.map +1 -0
  32. package/dist/bujo/grammar.js +147 -0
  33. package/dist/bujo/grammar.js.map +1 -0
  34. package/dist/bujo/graph.d.ts +17 -0
  35. package/dist/bujo/graph.d.ts.map +1 -0
  36. package/dist/bujo/graph.js +96 -0
  37. package/dist/bujo/graph.js.map +1 -0
  38. package/dist/bujo/ids.d.ts +9 -0
  39. package/dist/bujo/ids.d.ts.map +1 -0
  40. package/dist/bujo/ids.js +23 -0
  41. package/dist/bujo/ids.js.map +1 -0
  42. package/dist/bujo/index.d.ts +26 -0
  43. package/dist/bujo/index.d.ts.map +1 -0
  44. package/dist/bujo/index.js +20 -0
  45. package/dist/bujo/index.js.map +1 -0
  46. package/dist/bujo/json.d.ts +3 -0
  47. package/dist/bujo/json.d.ts.map +1 -0
  48. package/dist/bujo/json.js +58 -0
  49. package/dist/bujo/json.js.map +1 -0
  50. package/dist/bujo/llm.d.ts +14 -0
  51. package/dist/bujo/llm.d.ts.map +1 -0
  52. package/dist/bujo/llm.js +2 -0
  53. package/dist/bujo/llm.js.map +1 -0
  54. package/dist/bujo/migrate.d.ts +12 -0
  55. package/dist/bujo/migrate.d.ts.map +1 -0
  56. package/dist/bujo/migrate.js +136 -0
  57. package/dist/bujo/migrate.js.map +1 -0
  58. package/dist/bujo/model-error.d.ts +16 -0
  59. package/dist/bujo/model-error.d.ts.map +1 -0
  60. package/dist/bujo/model-error.js +20 -0
  61. package/dist/bujo/model-error.js.map +1 -0
  62. package/dist/bujo/ollama-llm.d.ts +7 -0
  63. package/dist/bujo/ollama-llm.d.ts.map +1 -0
  64. package/dist/bujo/ollama-llm.js +43 -0
  65. package/dist/bujo/ollama-llm.js.map +1 -0
  66. package/dist/bujo/projections.d.ts +8 -0
  67. package/dist/bujo/projections.d.ts.map +1 -0
  68. package/dist/bujo/projections.js +53 -0
  69. package/dist/bujo/projections.js.map +1 -0
  70. package/dist/bujo/rebuild.d.ts +12 -0
  71. package/dist/bujo/rebuild.d.ts.map +1 -0
  72. package/dist/bujo/rebuild.js +73 -0
  73. package/dist/bujo/rebuild.js.map +1 -0
  74. package/dist/bujo/recall.d.ts +7 -0
  75. package/dist/bujo/recall.d.ts.map +1 -0
  76. package/dist/bujo/recall.js +33 -0
  77. package/dist/bujo/recall.js.map +1 -0
  78. package/dist/bujo/reconcile.d.ts +37 -0
  79. package/dist/bujo/reconcile.d.ts.map +1 -0
  80. package/dist/bujo/reconcile.js +190 -0
  81. package/dist/bujo/reconcile.js.map +1 -0
  82. package/dist/bujo/reflect.d.ts +30 -0
  83. package/dist/bujo/reflect.d.ts.map +1 -0
  84. package/dist/bujo/reflect.js +100 -0
  85. package/dist/bujo/reflect.js.map +1 -0
  86. package/dist/bujo/store.d.ts +77 -0
  87. package/dist/bujo/store.d.ts.map +1 -0
  88. package/dist/bujo/store.js +222 -0
  89. package/dist/bujo/store.js.map +1 -0
  90. package/dist/bujo/types.d.ts +39 -0
  91. package/dist/bujo/types.d.ts.map +1 -0
  92. package/dist/bujo/types.js +2 -0
  93. package/dist/bujo/types.js.map +1 -0
  94. package/dist/search/chunks.d.ts +14 -0
  95. package/dist/search/chunks.d.ts.map +1 -0
  96. package/dist/search/chunks.js +75 -0
  97. package/dist/search/chunks.js.map +1 -0
  98. package/dist/search/circuit-breaker.d.ts +34 -0
  99. package/dist/search/circuit-breaker.d.ts.map +1 -0
  100. package/dist/search/circuit-breaker.js +89 -0
  101. package/dist/search/circuit-breaker.js.map +1 -0
  102. package/dist/search/embeddings.d.ts +44 -0
  103. package/dist/search/embeddings.d.ts.map +1 -0
  104. package/dist/search/embeddings.js +141 -0
  105. package/dist/search/embeddings.js.map +1 -0
  106. package/dist/search/index.d.ts +8 -0
  107. package/dist/search/index.d.ts.map +1 -0
  108. package/dist/search/index.js +5 -0
  109. package/dist/search/index.js.map +1 -0
  110. package/dist/search/types.d.ts +41 -0
  111. package/dist/search/types.d.ts.map +1 -0
  112. package/dist/search/types.js +2 -0
  113. package/dist/search/types.js.map +1 -0
  114. package/dist/search/vector-index.d.ts +28 -0
  115. package/dist/search/vector-index.d.ts.map +1 -0
  116. package/dist/search/vector-index.js +214 -0
  117. package/dist/search/vector-index.js.map +1 -0
  118. package/dist/store/contract.d.ts +2 -0
  119. package/dist/store/contract.d.ts.map +1 -0
  120. package/dist/store/contract.js +2 -0
  121. package/dist/store/contract.js.map +1 -0
  122. package/dist/store/db.d.ts +84 -0
  123. package/dist/store/db.d.ts.map +1 -0
  124. package/dist/store/db.js +471 -0
  125. package/dist/store/db.js.map +1 -0
  126. package/dist/store/fts.d.ts +3 -0
  127. package/dist/store/fts.d.ts.map +1 -0
  128. package/dist/store/fts.js +6 -0
  129. package/dist/store/fts.js.map +1 -0
  130. package/dist/store/index.d.ts +5 -0
  131. package/dist/store/index.d.ts.map +1 -0
  132. package/dist/store/index.js +3 -0
  133. package/dist/store/index.js.map +1 -0
  134. package/dist/store/ranking.d.ts +16 -0
  135. package/dist/store/ranking.d.ts.map +1 -0
  136. package/dist/store/ranking.js +32 -0
  137. package/dist/store/ranking.js.map +1 -0
  138. package/dist/store/schema.d.ts +3 -0
  139. package/dist/store/schema.d.ts.map +1 -0
  140. package/dist/store/schema.js +61 -0
  141. package/dist/store/schema.js.map +1 -0
  142. package/dist/store/types.d.ts +102 -0
  143. package/dist/store/types.d.ts.map +1 -0
  144. package/dist/store/types.js +25 -0
  145. package/dist/store/types.js.map +1 -0
  146. package/dist/store/vec.d.ts +12 -0
  147. package/dist/store/vec.d.ts.map +1 -0
  148. package/dist/store/vec.js +20 -0
  149. package/dist/store/vec.js.map +1 -0
  150. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # @mono-agent/memory
2
+
3
+ ## Category
4
+
5
+ Category: `context`
6
+
7
+ ## Responsibility
8
+
9
+ Local memory building blocks published as one package with explicit subpaths. `@mono-agent/memory/store` owns the SQLite substrate, schema, FTS5/sqlite-vec hybrid recall, and rebuildable record database. `@mono-agent/memory/search` owns embedding providers, circuit-breaking, chunk gathering, and the in-memory cosine vector index. `@mono-agent/memory/bujo` owns the Bullet-Journal memory engine: markdown grammar, canonical daily files, tier-aware capture/recall, entity graph projection, reflection, migration, and the `memory-bujo` maintenance CLI.
10
+
11
+ The shared `MemoryBlock`, `MemoryStore`, and `MemoryWriteResult` contracts live in `@mono-agent/agent-contracts`. The store subpath re-exports them for local-store consumers, but `@mono-agent/agent-contracts` is the source of truth.
12
+
13
+ ## Install / Usage
14
+
15
+ ```bash
16
+ pnpm --filter @mono-agent/memory run build
17
+ ```
18
+
19
+ ```ts
20
+ import { createBujoMemoryStore } from "@mono-agent/memory/bujo";
21
+ import { createEmbeddingProvider } from "@mono-agent/memory/search";
22
+ import { openMemoryDb } from "@mono-agent/memory/store";
23
+ import type { MemoryStore } from "@mono-agent/agent-contracts";
24
+
25
+ const embeddings = createEmbeddingProvider({ provider: "ollama", model: "nomic-embed-text:v1.5" });
26
+ const store: MemoryStore = createBujoMemoryStore({
27
+ root: "./memory",
28
+ embeddings,
29
+ dim: 768,
30
+ });
31
+
32
+ await store.appendHostSummary("conv-1", "User prefers concise answers.");
33
+ ```
34
+
35
+ ```bash
36
+ memory-bujo rebuild ./memory
37
+ memory-bujo recall ./memory "what did we decide about releases?"
38
+ ```
39
+
40
+ ## Public API
41
+
42
+ - `@mono-agent/memory/store`: `openMemoryDb`, `MemoryDb`, `DEFAULT_VEC_DIM`, `MEMORY_TYPES`, `MEMORY_STATUSES`, local record/entity/recall/stats types, and re-exported `MemoryBlock`, `MemoryStore`, `MemoryWriteResult`
43
+ - `@mono-agent/memory/search`: `createEmbeddingProvider`, `createCircuitBreakerEmbeddingProvider`, `createVectorMemoryIndex`, `gatherMemoryChunks`, embedding/search provider classes and types
44
+ - `@mono-agent/memory/bujo`: `createBujoMemoryStore`, `BujoMemoryStore`, `composeRecallBlock`, markdown grammar helpers, daily-file helpers, capture/reconcile/reflection/migration helpers, `createOllamaLlm`, and related BuJo/LLM types
45
+ - CLI: `memory-bujo`
46
+
47
+ ## Dependency Boundary
48
+
49
+ This package may depend on core contracts and local persistence/search dependencies (`better-sqlite3`, `sqlite-vec`). It does not depend on hosts, harnesses, communication adapters, observability, provider runtimes, or external memory services. Internal subpaths use relative imports so the package has no package-to-self workspace dependency.
50
+
51
+ ## What This Package Does Not Own
52
+
53
+ It does not own host configuration, backend selection, automatic `memory_recall` MCP wiring, external Supermemory storage, model runtime execution, communication channels, or run artifact persistence. `@mono-agent/agent-app` chooses which memory backend to build and wires the recall tool, while `@mono-agent/memory-supermemory` owns the external Supermemory backend.
54
+
55
+ ## Verification
56
+
57
+ ```bash
58
+ pnpm --filter @mono-agent/memory run build
59
+ pnpm --filter @mono-agent/memory run typecheck
60
+ pnpm --filter @mono-agent/memory run test
61
+ ```
@@ -0,0 +1,20 @@
1
+ import { type ReconcileAction, type ReconcileDeps } from "./reconcile.js";
2
+ export interface CaptureTurnResult {
3
+ readonly actions: ReconcileAction[];
4
+ readonly entities: number;
5
+ readonly relations: number;
6
+ }
7
+ /**
8
+ * Full capture pipeline for a single conversation turn:
9
+ * 1. distill(text) → candidate memories
10
+ * 2. reconcile(candidates) → ADD / UPDATE / SUPERSEDE / NOOP actions (writes markdown + index)
11
+ * 3. extractEntities(text) → typed entities + relations
12
+ * 4. Persist each entity canonical-first: graph.jsonl, THEN mirror to the db index
13
+ * 5. Persist each relation canonical-first: graph.jsonl, THEN mirror to the db index
14
+ * 6. Link this turn's ADDed memories to extracted entities via `about` edges (coarse co-occurrence)
15
+ *
16
+ * Never throws on a single bad entity/relation item — each write is wrapped defensively.
17
+ * Returns a summary: actions list, entity count, relation count.
18
+ */
19
+ export declare function captureTurn(text: string, deps: ReconcileDeps): Promise<CaptureTurnResult>;
20
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/bujo/capture.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAErF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8D/F"}
@@ -0,0 +1,77 @@
1
+ import { distill } from "./distill.js";
2
+ import { extractEntities } from "./entities.js";
3
+ import { appendEntity, appendRelation } from "./graph.js";
4
+ import { reconcile } from "./reconcile.js";
5
+ /**
6
+ * Full capture pipeline for a single conversation turn:
7
+ * 1. distill(text) → candidate memories
8
+ * 2. reconcile(candidates) → ADD / UPDATE / SUPERSEDE / NOOP actions (writes markdown + index)
9
+ * 3. extractEntities(text) → typed entities + relations
10
+ * 4. Persist each entity canonical-first: graph.jsonl, THEN mirror to the db index
11
+ * 5. Persist each relation canonical-first: graph.jsonl, THEN mirror to the db index
12
+ * 6. Link this turn's ADDed memories to extracted entities via `about` edges (coarse co-occurrence)
13
+ *
14
+ * Never throws on a single bad entity/relation item — each write is wrapped defensively.
15
+ * Returns a summary: actions list, entity count, relation count.
16
+ */
17
+ export async function captureTurn(text, deps) {
18
+ // Step 1+2: distill candidates and reconcile against existing index
19
+ const candidates = await distill(text, deps.llm);
20
+ const actions = await reconcile(candidates, deps);
21
+ // Step 3: extract entities and relations from the turn text
22
+ const extraction = await extractEntities(text, deps.llm);
23
+ const now = deps.now();
24
+ const createdAt = now.toISOString();
25
+ // Step 4: persist each entity canonical-first (graph.jsonl), then mirror to the rebuildable db
26
+ // index. graph.jsonl is the canonical source rebuildFromMarkdown reads; writing it first means a
27
+ // crash between the two writes still recovers the entity on the next rebuild.
28
+ for (const entity of extraction.entities) {
29
+ try {
30
+ const record = {
31
+ id: entity.id,
32
+ name: entity.name,
33
+ ...(entity.type !== undefined ? { type: entity.type } : {}),
34
+ createdAt,
35
+ };
36
+ appendEntity(deps.root, record);
37
+ deps.db.upsertEntity(record);
38
+ }
39
+ catch {
40
+ // Per-item isolation: a single bad entity must not abort the turn
41
+ }
42
+ }
43
+ // Step 5: persist each relation canonical-first (graph.jsonl), then mirror to the db index.
44
+ for (const relation of extraction.relations) {
45
+ try {
46
+ appendRelation(deps.root, {
47
+ src: relation.src,
48
+ dst: relation.dst,
49
+ relation: relation.relation,
50
+ createdAt,
51
+ });
52
+ deps.db.addEntityRelation(relation.src, relation.dst, relation.relation);
53
+ }
54
+ catch {
55
+ // Per-item isolation: a single bad relation must not abort the turn
56
+ }
57
+ }
58
+ // Step 6: link ADDed memories to extracted entities via `about` edges
59
+ const addedIds = actions.flatMap((a) => (a.kind === "add" ? [a.id] : []));
60
+ const entityIds = extraction.entities.map((e) => e.id);
61
+ for (const memoryId of addedIds) {
62
+ for (const entityId of entityIds) {
63
+ try {
64
+ deps.db.addEdge(memoryId, entityId, "about");
65
+ }
66
+ catch {
67
+ // Per-item isolation
68
+ }
69
+ }
70
+ }
71
+ return {
72
+ actions,
73
+ entities: extraction.entities.length,
74
+ relations: extraction.relations.length,
75
+ };
76
+ }
77
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/bujo/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { EmbeddingProvider } from "../search/index.js";
2
+ /**
3
+ * Resolve the embeddings provider from the same `MONO_AGENT_MEMORY_EMBEDDINGS_*` env vars the agent
4
+ * and the MCP server use. Returns undefined when no provider is configured — embeddings are opt-in,
5
+ * so lite-tier (FTS-only) recall/rebuild works without any embedding service (e.g. no Ollama running).
6
+ */
7
+ export declare function readEmbeddings(env?: NodeJS.ProcessEnv): {
8
+ provider: EmbeddingProvider;
9
+ dim: number;
10
+ } | undefined;
11
+ //# sourceMappingURL=cli-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-env.d.ts","sourceRoot":"","sources":["../../src/bujo/cli-env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,QAAQ,EAAE,iBAAiB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAqB1D"}
@@ -0,0 +1,30 @@
1
+ import { createEmbeddingProvider } from "../search/index.js";
2
+ /**
3
+ * Resolve the embeddings provider from the same `MONO_AGENT_MEMORY_EMBEDDINGS_*` env vars the agent
4
+ * and the MCP server use. Returns undefined when no provider is configured — embeddings are opt-in,
5
+ * so lite-tier (FTS-only) recall/rebuild works without any embedding service (e.g. no Ollama running).
6
+ */
7
+ export function readEmbeddings(env = process.env) {
8
+ const providerKind = env.MONO_AGENT_MEMORY_EMBEDDINGS_PROVIDER?.trim();
9
+ if (!providerKind)
10
+ return undefined;
11
+ if (providerKind !== "ollama" && providerKind !== "openai") {
12
+ throw new Error(`unsupported MONO_AGENT_MEMORY_EMBEDDINGS_PROVIDER "${providerKind}" (expected "ollama" or "openai")`);
13
+ }
14
+ const model = env.MONO_AGENT_MEMORY_EMBEDDINGS_MODEL?.trim() || "nomic-embed-text:v1.5";
15
+ const endpoint = env.MONO_AGENT_MEMORY_EMBEDDINGS_ENDPOINT?.trim();
16
+ const apiKey = env.MONO_AGENT_MEMORY_EMBEDDINGS_API_KEY?.trim();
17
+ const dimStr = env.MONO_AGENT_MEMORY_EMBEDDINGS_DIM?.trim();
18
+ const dim = dimStr ? Number(dimStr) : 768;
19
+ if (!Number.isInteger(dim) || dim <= 0) {
20
+ throw new Error(`invalid MONO_AGENT_MEMORY_EMBEDDINGS_DIM "${dimStr ?? ""}" (expected a positive integer)`);
21
+ }
22
+ const provider = createEmbeddingProvider({
23
+ provider: providerKind,
24
+ model,
25
+ ...(endpoint ? { endpoint } : {}),
26
+ ...(apiKey ? { apiKey } : {}),
27
+ });
28
+ return { provider, dim };
29
+ }
30
+ //# sourceMappingURL=cli-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-env.js","sourceRoot":"","sources":["../../src/bujo/cli-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG7D;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,YAAY,GAAG,GAAG,CAAC,qCAAqC,EAAE,IAAI,EAAE,CAAC;IACvE,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IACpC,IAAI,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,sDAAsD,YAAY,mCAAmC,CAAC,CAAC;IACzH,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,kCAAkC,EAAE,IAAI,EAAE,IAAI,uBAAuB,CAAC;IACxF,MAAM,QAAQ,GAAG,GAAG,CAAC,qCAAqC,EAAE,IAAI,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,GAAG,CAAC,oCAAoC,EAAE,IAAI,EAAE,CAAC;IAChE,MAAM,MAAM,GAAG,GAAG,CAAC,gCAAgC,EAAE,IAAI,EAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,IAAI,EAAE,iCAAiC,CAAC,CAAC;IAC9G,CAAC;IACD,MAAM,QAAQ,GAAG,uBAAuB,CAAC;QACvC,QAAQ,EAAE,YAAY;QACtB,KAAK;QACL,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC,CAAC;IACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bujo/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ import { join } from "node:path";
3
+ import { openMemoryDb } from "../store/index.js";
4
+ import { readEmbeddings } from "./cli-env.js";
5
+ import { createIdFactory } from "./ids.js";
6
+ import { migrate } from "./migrate.js";
7
+ import { createOllamaLlm } from "./ollama-llm.js";
8
+ import { writeFutureLog, writeIndex } from "./projections.js";
9
+ import { rebuildFromMarkdown } from "./rebuild.js";
10
+ import { reflect } from "./reflect.js";
11
+ /** Optional per-call LLM timeout override (ms). Invalid values fall back to the client default. */
12
+ function llmTimeoutMsFromEnv() {
13
+ const raw = process.env.MONO_AGENT_MEMORY_LLM_TIMEOUT_MS?.trim();
14
+ if (!raw)
15
+ return undefined;
16
+ const parsed = Number(raw);
17
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
18
+ }
19
+ async function main() {
20
+ const [command, root, ...rest] = process.argv.slice(2);
21
+ if (command !== "rebuild" && command !== "recall" && command !== "index" && command !== "reflect" && command !== "migrate") {
22
+ process.stderr.write("usage: memory-bujo <rebuild|recall|index|reflect|migrate> <root> [query]\n");
23
+ process.exit(2);
24
+ }
25
+ if (root === undefined) {
26
+ process.stderr.write("error: <root> is required\n");
27
+ process.exit(2);
28
+ }
29
+ const query = rest.join(" ").trim();
30
+ if (command === "recall" && query.length === 0) {
31
+ process.stderr.write("error: recall requires a non-empty <query>\n");
32
+ process.exit(2);
33
+ }
34
+ if (command === "reflect" || command === "migrate") {
35
+ const chatModel = process.env.MONO_AGENT_MEMORY_LLM_MODEL;
36
+ if (chatModel === undefined) {
37
+ process.stderr.write("error: set MONO_AGENT_MEMORY_LLM_MODEL to a local Ollama chat model (e.g. qwen3.6:latest)\n");
38
+ process.exit(2);
39
+ }
40
+ }
41
+ // Embeddings are opt-in (matching the agent/MCP): only enabled when an embeddings provider is
42
+ // configured. A lite-tier (FTS-only) recall/rebuild then needs no embedding service running.
43
+ const embeddingsConfig = readEmbeddings();
44
+ const db = openMemoryDb({
45
+ path: join(root, "memory.db"),
46
+ ...(embeddingsConfig !== undefined ? { embeddings: embeddingsConfig.provider, dim: embeddingsConfig.dim } : {}),
47
+ });
48
+ try {
49
+ if (command === "rebuild") {
50
+ const result = await rebuildFromMarkdown(root, db);
51
+ process.stdout.write(`rebuilt: indexed ${result.indexed} memories into ${join(root, "memory.db")}\n`);
52
+ }
53
+ else if (command === "index") {
54
+ writeIndex(root, db, new Date());
55
+ process.stdout.write(`wrote ${join(root, "index.md")}\n`);
56
+ }
57
+ else if (command === "reflect") {
58
+ // MONO_AGENT_MEMORY_LLM_MODEL is guaranteed non-undefined here (guard above)
59
+ const chatModel = process.env.MONO_AGENT_MEMORY_LLM_MODEL;
60
+ const timeoutMs = llmTimeoutMsFromEnv();
61
+ const llm = createOllamaLlm({
62
+ model: chatModel,
63
+ ...(process.env.MONO_AGENT_MEMORY_LLM_ENDPOINT ? { endpoint: process.env.MONO_AGENT_MEMORY_LLM_ENDPOINT } : {}),
64
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
65
+ });
66
+ const r = await reflect({ db, root, llm, nextId: createIdFactory(), now: () => new Date() });
67
+ writeFutureLog(root, db, new Date());
68
+ writeIndex(root, db, new Date());
69
+ process.stdout.write(`reflected: decayed ${r.decayed}, insights ${r.insights}, due ${r.due}\n`);
70
+ }
71
+ else if (command === "migrate") {
72
+ // MONO_AGENT_MEMORY_LLM_MODEL is guaranteed non-undefined here (guard above)
73
+ const chatModel = process.env.MONO_AGENT_MEMORY_LLM_MODEL;
74
+ const timeoutMs = llmTimeoutMsFromEnv();
75
+ const llm = createOllamaLlm({
76
+ model: chatModel,
77
+ ...(process.env.MONO_AGENT_MEMORY_LLM_ENDPOINT ? { endpoint: process.env.MONO_AGENT_MEMORY_LLM_ENDPOINT } : {}),
78
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
79
+ });
80
+ const m = await migrate({ db, root, llm, nextId: createIdFactory(), now: () => new Date() });
81
+ writeFutureLog(root, db, new Date());
82
+ process.stdout.write(`migrated: promoted ${m.promoted}, rescheduled ${m.rescheduled}, clustered ${m.clustered}, forgotten ${m.forgotten}, reviewed ${m.reviewed}\n`);
83
+ }
84
+ else {
85
+ const hits = await db.recall(query, { topK: 8 });
86
+ for (const hit of hits)
87
+ process.stdout.write(`${hit.score.toFixed(3)} ${hit.record.text}\n`);
88
+ }
89
+ }
90
+ finally {
91
+ db.close();
92
+ }
93
+ }
94
+ main().catch((error) => {
95
+ process.stderr.write(`memory-bujo failed: ${error instanceof Error ? error.message : String(error)}\n`);
96
+ process.exit(1);
97
+ });
98
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bujo/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { MemoryDb } from "../store/index.js";
2
+ export interface ConsolidateDeps {
3
+ readonly root: string;
4
+ readonly db: MemoryDb;
5
+ readonly now: Date;
6
+ }
7
+ export interface ConsolidateResult {
8
+ readonly decayed: number;
9
+ readonly duplicateGroups: number;
10
+ readonly superseded: number;
11
+ readonly markdownInvalidated: number;
12
+ }
13
+ /** Deterministic, no-LLM maintenance: decay, exact-normalized duplicate folding, projections. */
14
+ export declare function consolidateBujoMemory(deps: ConsolidateDeps): Promise<ConsolidateResult>;
15
+ //# sourceMappingURL=consolidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../src/bujo/consolidate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,mBAAmB,CAAC;AAKhE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED,iGAAiG;AACjG,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0B7F"}
@@ -0,0 +1,61 @@
1
+ import { rewriteBullet } from "./daily.js";
2
+ import { writeEmptyFutureLog, writeIndex } from "./projections.js";
3
+ /** Deterministic, no-LLM maintenance: decay, exact-normalized duplicate folding, projections. */
4
+ export async function consolidateBujoMemory(deps) {
5
+ const { decayed } = deps.db.applyDecay(deps.now);
6
+ const liveRecords = deps.db.topSalient(Math.max(deps.db.count(), 1));
7
+ const groups = groupByNormalizedText(liveRecords);
8
+ let duplicateGroups = 0;
9
+ let superseded = 0;
10
+ let markdownInvalidated = 0;
11
+ for (const group of groups.values()) {
12
+ if (group.length < 2)
13
+ continue;
14
+ duplicateGroups += 1;
15
+ const [keeper, ...duplicates] = [...group].sort(compareNewestFirst);
16
+ if (keeper === undefined)
17
+ continue;
18
+ for (const duplicate of duplicates) {
19
+ deps.db.markSuperseded(duplicate.id, keeper.id, deps.now.toISOString());
20
+ superseded += 1;
21
+ if (duplicate.source.file !== undefined) {
22
+ const rewritten = rewriteBullet(deps.root, duplicate.source.file, duplicate.id, { status: "invalidated" });
23
+ if (rewritten)
24
+ markdownInvalidated += 1;
25
+ }
26
+ }
27
+ }
28
+ writeIndex(deps.root, deps.db, deps.now);
29
+ writeEmptyFutureLog(deps.root);
30
+ return { decayed, duplicateGroups, superseded, markdownInvalidated };
31
+ }
32
+ function groupByNormalizedText(records) {
33
+ const groups = new Map();
34
+ for (const record of records) {
35
+ const key = normalizeFactText(record.text);
36
+ if (key.length === 0)
37
+ continue;
38
+ const existing = groups.get(key);
39
+ if (existing === undefined) {
40
+ groups.set(key, [record]);
41
+ }
42
+ else {
43
+ existing.push(record);
44
+ }
45
+ }
46
+ return groups;
47
+ }
48
+ function normalizeFactText(text) {
49
+ return text
50
+ .normalize("NFKC")
51
+ .toLocaleLowerCase("en-US")
52
+ .replace(/[^\p{Letter}\p{Number}]+/gu, " ")
53
+ .trim();
54
+ }
55
+ function compareNewestFirst(a, b) {
56
+ const byCreated = Date.parse(b.createdAt) - Date.parse(a.createdAt);
57
+ if (byCreated !== 0)
58
+ return byCreated;
59
+ return b.id.localeCompare(a.id);
60
+ }
61
+ //# sourceMappingURL=consolidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../../src/bujo/consolidate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Bullet } from "./types.js";
2
+ export declare function dailyFilePath(root: string, when: Date): string;
3
+ /** Append a bullet to today's daily file (creating it with a heading if absent). Returns the bullet. */
4
+ export declare function appendBullet(root: string, bullet: Bullet, when: Date): Bullet;
5
+ /**
6
+ * Rewrite a single bullet inside an existing daily file.
7
+ *
8
+ * Reads `<root>/<file>`, parses it, finds the line whose `bullet.id === id`,
9
+ * applies `patch` onto that Bullet (object spread), serializes and writes back.
10
+ *
11
+ * Returns `true` if the bullet was found and the file was rewritten, `false` if
12
+ * no bullet with `id` was found (file is not modified in that case).
13
+ *
14
+ * Non-bullet lines (prose, headings, blank lines) are preserved verbatim.
15
+ */
16
+ export declare function rewriteBullet(root: string, file: string, id: string, patch: Partial<Pick<Bullet, "text" | "status" | "salience" | "isInsight" | "dueAt" | "refs">>): boolean;
17
+ //# sourceMappingURL=daily.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily.d.ts","sourceRoot":"","sources":["../../src/bujo/daily.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAG9D;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAO7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,GAC5F,OAAO,CAmBT"}
@@ -0,0 +1,47 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { parseDailyFile, serializeBullet, serializeDailyFile } from "./grammar.js";
4
+ export function dailyFilePath(root, when) {
5
+ const day = when.toISOString().slice(0, 10);
6
+ return join(root, "daily", `${day}.md`);
7
+ }
8
+ /** Append a bullet to today's daily file (creating it with a heading if absent). Returns the bullet. */
9
+ export function appendBullet(root, bullet, when) {
10
+ const path = dailyFilePath(root, when);
11
+ mkdirSync(dirname(path), { recursive: true });
12
+ // existsSync (not read-and-catch) so a permission/IO error surfaces instead of being mistaken for a new file.
13
+ const header = existsSync(path) ? "" : `# ${when.toISOString().slice(0, 10)}\n\n`;
14
+ appendFileSync(path, `${header}${serializeBullet(bullet)}\n`, "utf8");
15
+ return bullet;
16
+ }
17
+ /**
18
+ * Rewrite a single bullet inside an existing daily file.
19
+ *
20
+ * Reads `<root>/<file>`, parses it, finds the line whose `bullet.id === id`,
21
+ * applies `patch` onto that Bullet (object spread), serializes and writes back.
22
+ *
23
+ * Returns `true` if the bullet was found and the file was rewritten, `false` if
24
+ * no bullet with `id` was found (file is not modified in that case).
25
+ *
26
+ * Non-bullet lines (prose, headings, blank lines) are preserved verbatim.
27
+ */
28
+ export function rewriteBullet(root, file, id, patch) {
29
+ const path = join(root, file);
30
+ const content = readFileSync(path, "utf8");
31
+ const parsed = parseDailyFile(content);
32
+ let found = false;
33
+ const newLines = parsed.lines.map((line) => {
34
+ if (line.bullet === undefined || line.bullet.id !== id)
35
+ return line;
36
+ found = true;
37
+ // Build the merged bullet by applying only the defined patch keys so that
38
+ // exactOptionalPropertyTypes is satisfied (no undefined values injected).
39
+ const merged = { ...line.bullet, ...patch };
40
+ return { raw: line.raw, lineNumber: line.lineNumber, bullet: merged };
41
+ });
42
+ if (!found)
43
+ return false;
44
+ writeFileSync(path, serializeDailyFile({ lines: newLines }), "utf8");
45
+ return true;
46
+ }
47
+ //# sourceMappingURL=daily.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily.js","sourceRoot":"","sources":["../../src/bujo/daily.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGnF,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAAU;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,MAAc,EAAE,IAAU;IACnE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,8GAA8G;IAC9G,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;IAClF,cAAc,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,IAAY,EACZ,EAAU,EACV,KAA6F;IAE7F,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAEvC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QACpE,KAAK,GAAG,IAAI,CAAC;QACb,0EAA0E;QAC1E,0EAA0E;QAC1E,MAAM,MAAM,GAAW,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACpD,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,aAAa,CAAC,IAAI,EAAE,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { MemoryType } from "../store/index.js";
2
+ import type { LlmComplete } from "./llm.js";
3
+ export interface CandidateMemory {
4
+ readonly type: MemoryType;
5
+ readonly text: string;
6
+ readonly salience: number;
7
+ readonly isInsight: boolean;
8
+ }
9
+ export declare function distill(text: string, llm: LlmComplete): Promise<CandidateMemory[]>;
10
+ //# sourceMappingURL=distill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../../src/bujo/distill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAI5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AASD,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAaxF"}
@@ -0,0 +1,50 @@
1
+ import { parseJsonLoose } from "./json.js";
2
+ import { MemoryModelError } from "./model-error.js";
3
+ const PROMPT = (text) => `Extract durable memories from the text below as a JSON array.
4
+ Each item: {"type":"task|event|note","text":"<one atomic sentence>","salience":0..1,"isInsight":true|false}.
5
+ Rules: one fact per item; <=160 chars; omit chit-chat; salience reflects long-term importance; isInsight=true only for synthesized higher-level conclusions. Return ONLY the JSON array.
6
+
7
+ TEXT:
8
+ ${text}`;
9
+ export async function distill(text, llm) {
10
+ if (text.trim().length === 0)
11
+ return [];
12
+ let raw;
13
+ try {
14
+ raw = await llm.complete(PROMPT(text), { label: "capture:distill" });
15
+ }
16
+ catch (cause) {
17
+ // Surface model outages (Ollama down, timeout, 5xx) instead of returning [] — an empty result is
18
+ // indistinguishable from "nothing worth remembering", which is exactly how a dead model hides.
19
+ throw new MemoryModelError("llm", "distill", cause);
20
+ }
21
+ const parsed = parseJsonLoose(raw);
22
+ if (!Array.isArray(parsed))
23
+ return [];
24
+ return parsed.flatMap((it) => normalizeCandidate(it));
25
+ }
26
+ const VALID_TYPES = new Set(["task", "event", "note"]);
27
+ function normalizeCandidate(it) {
28
+ if (it === null || typeof it !== "object")
29
+ return [];
30
+ const obj = it;
31
+ // Require non-empty text, then normalize to a bullet-safe single line so it round-trips through
32
+ // serializeBullet (which rejects newlines and the `<!--mem` delimiter) instead of being silently
33
+ // dropped by reconcile's per-candidate isolation. Collapse whitespace, strip the delimiter, cap ~280.
34
+ const rawText = typeof obj["text"] === "string" ? obj["text"] : "";
35
+ const text = rawText.replace(/\s+/gu, " ").replace(/<!--mem/gu, "").trim().slice(0, 280);
36
+ if (text.length === 0)
37
+ return [];
38
+ // Coerce type to one of task/event/note (default "note")
39
+ const rawType = typeof obj["type"] === "string" ? obj["type"] : "";
40
+ const type = VALID_TYPES.has(rawType) ? rawType : "note";
41
+ // Clamp salience to [0,1] (default 0.5 when missing/non-finite)
42
+ const rawSalience = typeof obj["salience"] === "number" ? obj["salience"] : NaN;
43
+ const salience = Number.isFinite(rawSalience)
44
+ ? Math.min(1, Math.max(0, rawSalience))
45
+ : 0.5;
46
+ // Coerce isInsight to boolean (default false)
47
+ const isInsight = typeof obj["isInsight"] === "boolean" ? obj["isInsight"] : false;
48
+ return [{ type, text, salience, isInsight }];
49
+ }
50
+ //# sourceMappingURL=distill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distill.js","sourceRoot":"","sources":["../../src/bujo/distill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { LlmComplete } from "./llm.js";
2
+ export interface ExtractedEntity {
3
+ readonly id: string;
4
+ readonly name: string;
5
+ readonly type?: string;
6
+ }
7
+ export interface ExtractedRelation {
8
+ readonly src: string;
9
+ readonly dst: string;
10
+ readonly relation: string;
11
+ }
12
+ export interface Extraction {
13
+ readonly entities: ExtractedEntity[];
14
+ readonly relations: ExtractedRelation[];
15
+ }
16
+ /**
17
+ * Use the LLM to extract named entities and their relations from `text`.
18
+ * Empty/whitespace text → `{entities:[], relations:[]}`.
19
+ * Malformed LLM *output* is handled defensively (→ EMPTY), but a model *failure* (Ollama down,
20
+ * timeout, 5xx) is rethrown as a {@link MemoryModelError} so it surfaces rather than looking like
21
+ * "no entities found".
22
+ */
23
+ export declare function extractEntities(text: string, llm: LlmComplete): Promise<Extraction>;
24
+ //# sourceMappingURL=entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/bujo/entities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAI5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAC;CACzC;AA2DD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BzF"}