@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
@@ -0,0 +1,136 @@
1
+ import { appendFileSync, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { parseJsonLoose } from "./json.js";
4
+ import { MemoryModelError } from "./model-error.js";
5
+ import { rewriteBullet } from "./daily.js";
6
+ const VALID_ACTIONS = new Set(["promote", "reschedule", "cluster", "forget"]);
7
+ function buildMigratePrompt(id, text) {
8
+ return `You are a BuJo (Bullet Journal) migration assistant. This memory has been open for over 30 days with low salience.
9
+
10
+ MEMORY:
11
+ id=${id}
12
+ text="${text}"
13
+
14
+ Decide what to do with it. Return ONLY a JSON object (no prose, no code fences):
15
+ {"action":"promote|reschedule|cluster|forget","dueAt":"<ISO 8601, only for reschedule>","collection":"<slug, only for cluster>"}
16
+
17
+ - promote: worth keeping + elevating salience
18
+ - reschedule: has a future due date, schedule it
19
+ - cluster: belongs to a named collection/theme (provide slug)
20
+ - forget: no longer relevant, drop it`;
21
+ }
22
+ /** Monthly BuJo migration ritual: review aging open memories and apply LLM decisions. */
23
+ export async function migrate(deps) {
24
+ const now = deps.now();
25
+ // Re-run safety: every action moves the item out of agingOpen's pool (promote raises salience above
26
+ // the threshold; reschedule/forget change status away from 'open'), so a repeated run won't re-process it.
27
+ const aging = deps.db.agingOpen(now, { olderThanDays: 30, maxSalience: 0.4, limit: 50 });
28
+ let promoted = 0;
29
+ let rescheduled = 0;
30
+ let clustered = 0;
31
+ let forgotten = 0;
32
+ const decisions = [];
33
+ for (const item of aging) {
34
+ try {
35
+ const prompt = buildMigratePrompt(item.id, item.text);
36
+ let raw;
37
+ try {
38
+ raw = await deps.llm.complete(prompt, { label: "migrate" });
39
+ }
40
+ catch (cause) {
41
+ // A model outage fails every item, so tag it and let the catch below surface it rather than
42
+ // swallowing it as a per-item skip (which would make a dead model look like an empty migration).
43
+ throw new MemoryModelError("llm", "migrate", cause);
44
+ }
45
+ const parsed = parseJsonLoose(raw);
46
+ // Validate: must be a non-null object with a recognized action
47
+ if (parsed === undefined ||
48
+ parsed === null ||
49
+ typeof parsed !== "object" ||
50
+ !VALID_ACTIONS.has(parsed.action)) {
51
+ continue;
52
+ }
53
+ const action = parsed.action;
54
+ const sourceFile = item.source.file;
55
+ if (action === "promote") {
56
+ const newSalience = Math.min(1, item.salience + 0.3);
57
+ if (sourceFile !== undefined) {
58
+ rewriteBullet(deps.root, sourceFile, item.id, { salience: newSalience });
59
+ }
60
+ await deps.db.upsert({ ...item, salience: newSalience });
61
+ promoted += 1;
62
+ decisions.push({ action, id: item.id, text: item.text });
63
+ }
64
+ else if (action === "reschedule") {
65
+ const dueAt = typeof parsed.dueAt === "string" ? parsed.dueAt : undefined;
66
+ const patch = {
67
+ status: "scheduled",
68
+ ...(dueAt !== undefined && { dueAt }),
69
+ };
70
+ if (sourceFile !== undefined) {
71
+ rewriteBullet(deps.root, sourceFile, item.id, patch);
72
+ }
73
+ await deps.db.upsert({
74
+ ...item,
75
+ status: "scheduled",
76
+ ...(dueAt !== undefined && { dueAt }),
77
+ });
78
+ rescheduled += 1;
79
+ decisions.push({ action, id: item.id, text: item.text });
80
+ }
81
+ else if (action === "cluster") {
82
+ const slug = typeof parsed.collection === "string" ? parsed.collection.trim() : "";
83
+ if (slug.length === 0)
84
+ continue; // cluster without a collection slug is malformed — skip, don't mint a catch-all
85
+ await deps.db.upsert({ ...item, collection: slug });
86
+ deps.db.upsertEntity({
87
+ id: `collection:${slug}`,
88
+ name: slug,
89
+ type: "collection",
90
+ createdAt: now.toISOString(),
91
+ });
92
+ deps.db.addEdge(item.id, `collection:${slug}`, "supports");
93
+ clustered += 1;
94
+ decisions.push({ action, id: item.id, text: item.text });
95
+ }
96
+ else if (action === "forget") {
97
+ if (sourceFile !== undefined) {
98
+ rewriteBullet(deps.root, sourceFile, item.id, { status: "dropped" });
99
+ }
100
+ await deps.db.upsert({ ...item, status: "dropped", validTo: now.toISOString() });
101
+ forgotten += 1;
102
+ decisions.push({ action, id: item.id, text: item.text });
103
+ }
104
+ }
105
+ catch (err) {
106
+ // A model outage is systemic — surface it (the ritual scheduler logs it).
107
+ if (err instanceof MemoryModelError)
108
+ throw err;
109
+ // Per-item isolation: a genuine per-item data error (e.g. a missing daily file) is skipped so
110
+ // it doesn't abort the rest of the batch.
111
+ continue;
112
+ }
113
+ }
114
+ // Write monthly/<YYYY-MM>.md — append a dated section with all decisions
115
+ if (decisions.length > 0) {
116
+ const yearMonth = now.toISOString().slice(0, 7); // "YYYY-MM"
117
+ const monthlyDir = join(deps.root, "monthly");
118
+ mkdirSync(monthlyDir, { recursive: true });
119
+ const monthlyPath = join(monthlyDir, `${yearMonth}.md`);
120
+ const dateStr = now.toISOString().slice(0, 10);
121
+ const lines = [
122
+ `\n## ${dateStr}`,
123
+ ...decisions.map((d) => `- ${d.action} ${d.id}: "${d.text}"`),
124
+ "",
125
+ ].join("\n");
126
+ appendFileSync(monthlyPath, lines, "utf8");
127
+ }
128
+ return {
129
+ promoted,
130
+ rescheduled,
131
+ clustered,
132
+ forgotten,
133
+ reviewed: aging.length,
134
+ };
135
+ }
136
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/bujo/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** Which memory AI model failed: the chat LLM (distill/classify/entities) or the embedding provider. */
2
+ export type MemoryModelKind = "llm" | "embedding";
3
+ /**
4
+ * A failure from one of the memory AI models. Distinct from a per-item *data* error (a malformed
5
+ * candidate, a missing daily file): those are tolerated/isolated, whereas a model outage is systemic
6
+ * and must surface so the calling boundary can log it. Thrown from both the per-turn capture pipeline
7
+ * (distill/entities/classify/findSimilar) and the rituals (reflect insights, migrate), so the message
8
+ * is scope-neutral — the `stage` distinguishes the source and the surrounding log prefix (e.g.
9
+ * "bujo capture failed" / 'Memory ritual "reflect" failed') supplies the feature context.
10
+ */
11
+ export declare class MemoryModelError extends Error {
12
+ readonly kind: MemoryModelKind;
13
+ readonly stage: string;
14
+ constructor(kind: MemoryModelKind, stage: string, cause: unknown);
15
+ }
16
+ //# sourceMappingURL=model-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-error.d.ts","sourceRoot":"","sources":["../../src/bujo/model-error.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,WAAW,CAAC;AAElD;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAOjE"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A failure from one of the memory AI models. Distinct from a per-item *data* error (a malformed
3
+ * candidate, a missing daily file): those are tolerated/isolated, whereas a model outage is systemic
4
+ * and must surface so the calling boundary can log it. Thrown from both the per-turn capture pipeline
5
+ * (distill/entities/classify/findSimilar) and the rituals (reflect insights, migrate), so the message
6
+ * is scope-neutral — the `stage` distinguishes the source and the surrounding log prefix (e.g.
7
+ * "bujo capture failed" / 'Memory ritual "reflect" failed') supplies the feature context.
8
+ */
9
+ export class MemoryModelError extends Error {
10
+ kind;
11
+ stage;
12
+ constructor(kind, stage, cause) {
13
+ const detail = cause instanceof Error ? cause.message : String(cause);
14
+ super(`memory ${kind} failure at ${stage}: ${detail}`, { cause });
15
+ this.name = "MemoryModelError";
16
+ this.kind = kind;
17
+ this.stage = stage;
18
+ }
19
+ }
20
+ //# sourceMappingURL=model-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-error.js","sourceRoot":"","sources":["../../src/bujo/model-error.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAkB;IACtB,KAAK,CAAS;IAEvB,YAAY,IAAqB,EAAE,KAAa,EAAE,KAAc;QAC9D,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,KAAK,CAAC,UAAU,IAAI,eAAe,KAAK,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { LlmComplete } from "./llm.js";
2
+ export declare function createOllamaLlm(opts: {
3
+ model: string;
4
+ endpoint?: string;
5
+ timeoutMs?: number;
6
+ }): LlmComplete;
7
+ //# sourceMappingURL=ollama-llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama-llm.d.ts","sourceRoot":"","sources":["../../src/bujo/ollama-llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAgC3G"}
@@ -0,0 +1,43 @@
1
+ // A capture runs several sequential LLM calls (distil → reconcile → extract entities); local Ollama
2
+ // chat models routinely take tens of seconds per call, so the per-call timeout is generous by
3
+ // default (and overridable). Too short a timeout aborts mid-capture, and because distil/reconcile/
4
+ // entities swallow LLM errors (never-throw), that surfaces as a memory that silently stores nothing.
5
+ const DEFAULT_TIMEOUT_MS = 120_000;
6
+ export function createOllamaLlm(opts) {
7
+ const endpoint = (opts.endpoint ?? "http://localhost:11434").replace(/\/$/u, "");
8
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
9
+ return {
10
+ id: `ollama:${opts.model}`,
11
+ async complete(prompt) {
12
+ const ctrl = new AbortController();
13
+ let timedOut = false;
14
+ const timer = setTimeout(() => {
15
+ timedOut = true;
16
+ ctrl.abort();
17
+ }, timeoutMs);
18
+ try {
19
+ const res = await fetch(`${endpoint}/api/generate`, {
20
+ method: "POST",
21
+ headers: { "content-type": "application/json" },
22
+ body: JSON.stringify({ model: opts.model, prompt, stream: false }),
23
+ signal: ctrl.signal,
24
+ });
25
+ if (!res.ok)
26
+ throw new Error(`ollama /api/generate ${res.status}`);
27
+ const data = (await res.json());
28
+ return typeof data.response === "string" ? data.response : "";
29
+ }
30
+ catch (err) {
31
+ // Translate our own abort into an explicit, diagnosable timeout (a generic AbortError that
32
+ // callers swallow would make a slow-model capture look like "nothing to remember").
33
+ if (timedOut)
34
+ throw new Error(`ollama /api/generate timed out after ${timeoutMs}ms`);
35
+ throw err;
36
+ }
37
+ finally {
38
+ clearTimeout(timer);
39
+ }
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=ollama-llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama-llm.js","sourceRoot":"","sources":["../../src/bujo/ollama-llm.ts"],"names":[],"mappings":"AAEA,oGAAoG;AACpG,8FAA8F;AAC9F,mGAAmG;AACnG,qGAAqG;AACrG,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC,MAAM,UAAU,eAAe,CAAC,IAA8D;IAC5F,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;IACvD,OAAO;QACL,EAAE,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;QAC1B,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,QAAQ,GAAG,IAAI,CAAC;gBAChB,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,eAAe,EAAE;oBAClD,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;oBAClE,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;gBACnE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAC;gBAC1D,OAAO,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,2FAA2F;gBAC3F,oFAAoF;gBACpF,IAAI,QAAQ;oBAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,SAAS,IAAI,CAAC,CAAC;gBACrF,MAAM,GAAG,CAAC;YACZ,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { MemoryDb } from "../store/index.js";
2
+ /** Write <root>/future-log.md: the due/scheduled intentions queue, soonest first. Returns count. */
3
+ export declare function writeFutureLog(root: string, db: MemoryDb, now: Date, horizonDays?: number): number;
4
+ /** Write the deterministic consolidation future log. No synthesis or due-item expansion. */
5
+ export declare function writeEmptyFutureLog(root: string): void;
6
+ /** Write <root>/index.md: a living table of contents — counts + top entities + top-salient memories. */
7
+ export declare function writeIndex(root: string, db: MemoryDb, _now: Date): void;
8
+ //# sourceMappingURL=projections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projections.d.ts","sourceRoot":"","sources":["../../src/bujo/projections.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,oGAAoG;AACpG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,SAAM,GAAG,MAAM,CAQ/F;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGtD;AAED,wGAAwG;AACxG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAsCvE"}
@@ -0,0 +1,53 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /** Write <root>/future-log.md: the due/scheduled intentions queue, soonest first. Returns count. */
4
+ export function writeFutureLog(root, db, now, horizonDays = 365) {
5
+ const horizon = new Date(now.getTime() + horizonDays * 86_400_000);
6
+ const items = db.dueItems(horizon, 200);
7
+ const lines = items.map((m) => `- [<] ${m.text} (due ${m.dueAt ?? "?"}) ^${m.id}`);
8
+ const body = ["# Future Log", "", ...lines, ""].join("\n");
9
+ mkdirSync(root, { recursive: true });
10
+ writeFileSync(join(root, "future-log.md"), body, "utf8");
11
+ return items.length;
12
+ }
13
+ /** Write the deterministic consolidation future log. No synthesis or due-item expansion. */
14
+ export function writeEmptyFutureLog(root) {
15
+ mkdirSync(root, { recursive: true });
16
+ writeFileSync(join(root, "future-log.md"), "# Future Log\n", "utf8");
17
+ }
18
+ /** Write <root>/index.md: a living table of contents — counts + top entities + top-salient memories. */
19
+ export function writeIndex(root, db, _now) {
20
+ const memoryCount = db.count();
21
+ const entityCount = db.countEntities();
22
+ const topMemories = db.topSalient(15);
23
+ const entities = db.listEntities(50);
24
+ const overviewLines = [
25
+ "## Overview",
26
+ "",
27
+ `- Memories: ${memoryCount}`,
28
+ `- Entities: ${entityCount}`,
29
+ ];
30
+ const topMemoryLines = [
31
+ "## Top memories",
32
+ "",
33
+ ...topMemories.map((m) => `- ${m.text} ^${m.id}`),
34
+ ];
35
+ const entityLines = [
36
+ "## Entities",
37
+ "",
38
+ ...entities.map((e) => `- ${e.name} (${e.type ?? "unknown"})`),
39
+ ];
40
+ const body = [
41
+ "# Index",
42
+ "",
43
+ ...overviewLines,
44
+ "",
45
+ ...topMemoryLines,
46
+ "",
47
+ ...entityLines,
48
+ "",
49
+ ].join("\n");
50
+ mkdirSync(root, { recursive: true });
51
+ writeFileSync(join(root, "index.md"), body, "utf8");
52
+ }
53
+ //# sourceMappingURL=projections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projections.js","sourceRoot":"","sources":["../../src/bujo/projections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,EAAY,EAAE,GAAS,EAAE,WAAW,GAAG,GAAG;IACrF,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,CAAC,cAAc,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;AACvE,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAY,EAAE,IAAU;IAC/D,MAAM,WAAW,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IACvC,MAAM,WAAW,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAErC,MAAM,aAAa,GAAG;QACpB,aAAa;QACb,EAAE;QACF,eAAe,WAAW,EAAE;QAC5B,eAAe,WAAW,EAAE;KAC7B,CAAC;IAEF,MAAM,cAAc,GAAG;QACrB,iBAAiB;QACjB,EAAE;QACF,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;KACnD,CAAC;IAEF,MAAM,WAAW,GAAG;QAClB,aAAa;QACb,EAAE;QACF,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,SAAS,GAAG,CAAC;KAC/D,CAAC;IAEF,MAAM,IAAI,GAAG;QACX,SAAS;QACT,EAAE;QACF,GAAG,aAAa;QAChB,EAAE;QACF,GAAG,cAAc;QACjB,EAAE;QACF,GAAG,WAAW;QACd,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { MemoryDb } from "../store/index.js";
2
+ /**
3
+ * Rebuild the SQLite index from canonical markdown. No LLM — re-embeds via the db's provider.
4
+ *
5
+ * After indexing memory bullets, reads `graph.jsonl` and mirrors entities/relations into the db.
6
+ * Note: memory↔entity `about` edges are NOT stored in markdown/graph.jsonl (P2 known lossiness)
7
+ * and are intentionally NOT rebuilt here. This is documented and deferred to P3+.
8
+ */
9
+ export declare function rebuildFromMarkdown(root: string, db: MemoryDb): Promise<{
10
+ indexed: number;
11
+ }>;
12
+ //# sourceMappingURL=rebuild.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rebuild.d.ts","sourceRoot":"","sources":["../../src/bujo/rebuild.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,mBAAmB,CAAC;AAMhE;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA2ClG"}
@@ -0,0 +1,73 @@
1
+ import { readFileSync, readdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { parseDailyFile } from "./grammar.js";
4
+ import { readGraph } from "./graph.js";
5
+ /**
6
+ * Rebuild the SQLite index from canonical markdown. No LLM — re-embeds via the db's provider.
7
+ *
8
+ * After indexing memory bullets, reads `graph.jsonl` and mirrors entities/relations into the db.
9
+ * Note: memory↔entity `about` edges are NOT stored in markdown/graph.jsonl (P2 known lossiness)
10
+ * and are intentionally NOT rebuilt here. This is documented and deferred to P3+.
11
+ */
12
+ export async function rebuildFromMarkdown(root, db) {
13
+ const dailyDir = join(root, "daily");
14
+ let files;
15
+ try {
16
+ files = readdirSync(dailyDir).filter((f) => f.endsWith(".md")).sort();
17
+ }
18
+ catch (err) {
19
+ // Only a missing directory means "empty". Re-throw permission/IO errors (EACCES, EIO, …) so a
20
+ // transient fault can't silently produce an empty rebuild — db.rebuild() deletes every row first.
21
+ if (err.code !== "ENOENT")
22
+ throw err;
23
+ files = [];
24
+ }
25
+ const records = [];
26
+ for (const file of files) {
27
+ const parsed = parseDailyFile(readFileSync(join(dailyDir, file), "utf8"));
28
+ // Use the real 1-based file line number (not the bullet ordinal) so source.line points at the
29
+ // actual markdown line for provenance / jump-to-source.
30
+ parsed.lines.forEach((line) => {
31
+ if (line.bullet !== undefined) {
32
+ records.push(toRecord(line.bullet, `daily/${file}`, line.lineNumber));
33
+ }
34
+ });
35
+ }
36
+ const result = await db.rebuild(records);
37
+ // Ingest entity graph — db.rebuild already wiped the entity tables, so start fresh.
38
+ // No LLM: graph.jsonl is the canonical source written by captureTurn.
39
+ const g = readGraph(root);
40
+ for (const entity of g.entities) {
41
+ try {
42
+ db.upsertEntity(entity);
43
+ }
44
+ catch {
45
+ // Per-item isolation: a single corrupt entity must not abort the rebuild
46
+ }
47
+ }
48
+ for (const relation of g.relations) {
49
+ try {
50
+ db.addEntityRelation(relation.src, relation.dst, relation.relation);
51
+ }
52
+ catch {
53
+ // Per-item isolation
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ function toRecord(bullet, file, line) {
59
+ return {
60
+ id: bullet.id,
61
+ type: bullet.type,
62
+ status: bullet.status,
63
+ text: bullet.text,
64
+ salience: bullet.salience,
65
+ isInsight: bullet.isInsight,
66
+ createdAt: bullet.createdAt,
67
+ accessCount: 0,
68
+ ...(bullet.dueAt !== undefined ? { dueAt: bullet.dueAt } : {}),
69
+ tags: [],
70
+ source: { file, line },
71
+ };
72
+ }
73
+ //# sourceMappingURL=rebuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/bujo/rebuild.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { MemoryBlock } from "@mono-agent/agent-contracts";
2
+ import type { MemoryDb } from "../store/index.js";
3
+ export declare function composeRecallBlock(db: MemoryDb, query: string, options?: {
4
+ topK?: number;
5
+ maxBytes?: number;
6
+ }): Promise<MemoryBlock | undefined>;
7
+ //# sourceMappingURL=recall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/bujo/recall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIlD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAuBlC"}
@@ -0,0 +1,33 @@
1
+ import { MARKER_FOR } from "./grammar.js";
2
+ export async function composeRecallBlock(db, query, options = {}) {
3
+ const maxBytes = options.maxBytes ?? 8_000;
4
+ const hits = await db.recall(query, { topK: options.topK ?? 8 });
5
+ // No hits → no block. A header-only block carries no signal and only adds
6
+ // noise/tokens to whatever surface injects it; returning undefined lets
7
+ // callers skip injection via their existing `block === undefined` guard.
8
+ if (hits.length === 0) {
9
+ return undefined;
10
+ }
11
+ const lines = ["## Memory (recalled)", ""];
12
+ for (const hit of hits) {
13
+ const star = hit.record.isInsight ? " *" : "";
14
+ // Marker reflects type *and* status (e.g. a done task renders `- [x]`, not `- [ ]`); recall
15
+ // surfaces done/scheduled/migrated records, so a type-only marker would misrepresent their state.
16
+ lines.push(`- ${MARKER_FOR(hit.record.type, hit.record.status)} ${hit.record.text}${star}`);
17
+ }
18
+ let content = lines.join("\n");
19
+ let truncated = false;
20
+ if (Buffer.byteLength(content, "utf8") > maxBytes) {
21
+ content = clampToBytes(content, maxBytes);
22
+ truncated = true;
23
+ }
24
+ return { kind: "markdown", content, source: "memory-bujo", truncated };
25
+ }
26
+ function clampToBytes(text, maxBytes) {
27
+ const buf = Buffer.from(text, "utf8");
28
+ if (buf.byteLength <= maxBytes)
29
+ return text;
30
+ // Cut on a UTF-8 boundary by decoding a sliced buffer leniently.
31
+ return new TextDecoder("utf-8").decode(buf.subarray(0, maxBytes)).replace(/�+$/u, "");
32
+ }
33
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/bujo/recall.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAY,EACZ,KAAa,EACb,UAAgD,EAAE;IAElD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACjE,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,4FAA4F;QAC5F,kGAAkG;QAClG,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;QAClD,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,QAAgB;IAClD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,GAAG,CAAC,UAAU,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC5C,iEAAiE;IACjE,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACxF,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { MemoryDb } from "../store/index.js";
2
+ import type { LlmComplete } from "./llm.js";
3
+ import type { CandidateMemory } from "./types.js";
4
+ /** The outcome of reconciling a single candidate against the existing index. */
5
+ export type ReconcileAction = {
6
+ readonly kind: "add";
7
+ readonly id: string;
8
+ } | {
9
+ readonly kind: "update";
10
+ readonly id: string;
11
+ } | {
12
+ readonly kind: "supersede";
13
+ readonly oldId: string;
14
+ readonly newId: string;
15
+ } | {
16
+ readonly kind: "noop";
17
+ readonly id: string;
18
+ };
19
+ export interface ReconcileDeps {
20
+ readonly db: MemoryDb;
21
+ readonly root: string;
22
+ readonly llm: LlmComplete;
23
+ readonly nextId: () => string;
24
+ readonly now: () => Date;
25
+ /** Distance below which an ADD also threads a `thread` edge to the neighbour. Default 0.35. */
26
+ readonly threadThreshold?: number;
27
+ /** Distance below which we consult the LLM to classify; above → ADD outright (skip LLM). Default 0.5. */
28
+ readonly dupThreshold?: number;
29
+ }
30
+ /**
31
+ * Reconcile distilled candidates against the existing memory index, writing to BOTH the
32
+ * canonical markdown daily files and the SQLite index. Each candidate is handled independently
33
+ * (an LLM/IO failure on one does not abort the others). The LLM is consulted only for candidates
34
+ * that are close to an existing memory; clearly-novel candidates are added without an LLM call.
35
+ */
36
+ export declare function reconcile(candidates: readonly CandidateMemory[], deps: ReconcileDeps): Promise<ReconcileAction[]>;
37
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/bujo/reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAA4B,MAAM,mBAAmB,CAAC;AAI5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,YAAY,CAAC;AAE1D,gFAAgF;AAChF,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC;IACzB,+FAA+F;IAC/F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,yGAAyG;IACzG,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAUD;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,SAAS,eAAe,EAAE,EACtC,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,EAAE,CAAC,CAmC5B"}