cortex-engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -0
  3. package/dist/bin/cli.d.ts +13 -0
  4. package/dist/bin/cli.d.ts.map +1 -0
  5. package/dist/bin/cli.js +92 -0
  6. package/dist/bin/cli.js.map +1 -0
  7. package/dist/bin/config-cmd.d.ts +12 -0
  8. package/dist/bin/config-cmd.d.ts.map +1 -0
  9. package/dist/bin/config-cmd.js +184 -0
  10. package/dist/bin/config-cmd.js.map +1 -0
  11. package/dist/bin/config-loader.d.ts +12 -0
  12. package/dist/bin/config-loader.d.ts.map +1 -0
  13. package/dist/bin/config-loader.js +42 -0
  14. package/dist/bin/config-loader.js.map +1 -0
  15. package/dist/bin/digest-cmd.d.ts +13 -0
  16. package/dist/bin/digest-cmd.d.ts.map +1 -0
  17. package/dist/bin/digest-cmd.js +286 -0
  18. package/dist/bin/digest-cmd.js.map +1 -0
  19. package/dist/bin/init.d.ts +33 -0
  20. package/dist/bin/init.d.ts.map +1 -0
  21. package/dist/bin/init.js +355 -0
  22. package/dist/bin/init.js.map +1 -0
  23. package/dist/bin/serve.d.ts +15 -0
  24. package/dist/bin/serve.d.ts.map +1 -0
  25. package/dist/bin/serve.js +21 -0
  26. package/dist/bin/serve.js.map +1 -0
  27. package/dist/bridges/bridge.d.ts +46 -0
  28. package/dist/bridges/bridge.d.ts.map +1 -0
  29. package/dist/bridges/bridge.js +128 -0
  30. package/dist/bridges/bridge.js.map +1 -0
  31. package/dist/bridges/registry.d.ts +19 -0
  32. package/dist/bridges/registry.d.ts.map +1 -0
  33. package/dist/bridges/registry.js +36 -0
  34. package/dist/bridges/registry.js.map +1 -0
  35. package/dist/core/config.d.ts +108 -0
  36. package/dist/core/config.d.ts.map +1 -0
  37. package/dist/core/config.js +29 -0
  38. package/dist/core/config.js.map +1 -0
  39. package/dist/core/embed.d.ts +16 -0
  40. package/dist/core/embed.d.ts.map +1 -0
  41. package/dist/core/embed.js +7 -0
  42. package/dist/core/embed.js.map +1 -0
  43. package/dist/core/llm.d.ts +31 -0
  44. package/dist/core/llm.d.ts.map +1 -0
  45. package/dist/core/llm.js +13 -0
  46. package/dist/core/llm.js.map +1 -0
  47. package/dist/core/nli.d.ts +26 -0
  48. package/dist/core/nli.d.ts.map +1 -0
  49. package/dist/core/nli.js +11 -0
  50. package/dist/core/nli.js.map +1 -0
  51. package/dist/core/session.d.ts +26 -0
  52. package/dist/core/session.d.ts.map +1 -0
  53. package/dist/core/session.js +71 -0
  54. package/dist/core/session.js.map +1 -0
  55. package/dist/core/store.d.ts +58 -0
  56. package/dist/core/store.d.ts.map +1 -0
  57. package/dist/core/store.js +8 -0
  58. package/dist/core/store.js.map +1 -0
  59. package/dist/core/types.d.ts +148 -0
  60. package/dist/core/types.d.ts.map +1 -0
  61. package/dist/core/types.js +8 -0
  62. package/dist/core/types.js.map +1 -0
  63. package/dist/engines/cognition.d.ts +76 -0
  64. package/dist/engines/cognition.d.ts.map +1 -0
  65. package/dist/engines/cognition.js +441 -0
  66. package/dist/engines/cognition.js.map +1 -0
  67. package/dist/engines/digest.d.ts +52 -0
  68. package/dist/engines/digest.d.ts.map +1 -0
  69. package/dist/engines/digest.js +351 -0
  70. package/dist/engines/digest.js.map +1 -0
  71. package/dist/engines/fsrs.d.ts +44 -0
  72. package/dist/engines/fsrs.d.ts.map +1 -0
  73. package/dist/engines/fsrs.js +122 -0
  74. package/dist/engines/fsrs.js.map +1 -0
  75. package/dist/engines/keywords.d.ts +12 -0
  76. package/dist/engines/keywords.d.ts.map +1 -0
  77. package/dist/engines/keywords.js +45 -0
  78. package/dist/engines/keywords.js.map +1 -0
  79. package/dist/engines/memory.d.ts +55 -0
  80. package/dist/engines/memory.d.ts.map +1 -0
  81. package/dist/engines/memory.js +147 -0
  82. package/dist/engines/memory.js.map +1 -0
  83. package/dist/index.d.ts +42 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +38 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/mcp/server.d.ts +12 -0
  88. package/dist/mcp/server.d.ts.map +1 -0
  89. package/dist/mcp/server.js +173 -0
  90. package/dist/mcp/server.js.map +1 -0
  91. package/dist/mcp/tools.d.ts +45 -0
  92. package/dist/mcp/tools.d.ts.map +1 -0
  93. package/dist/mcp/tools.js +814 -0
  94. package/dist/mcp/tools.js.map +1 -0
  95. package/dist/namespace/manager.d.ts +28 -0
  96. package/dist/namespace/manager.d.ts.map +1 -0
  97. package/dist/namespace/manager.js +73 -0
  98. package/dist/namespace/manager.js.map +1 -0
  99. package/dist/namespace/scoped-store.d.ts +43 -0
  100. package/dist/namespace/scoped-store.d.ts.map +1 -0
  101. package/dist/namespace/scoped-store.js +91 -0
  102. package/dist/namespace/scoped-store.js.map +1 -0
  103. package/dist/plugins/loader.d.ts +18 -0
  104. package/dist/plugins/loader.d.ts.map +1 -0
  105. package/dist/plugins/loader.js +71 -0
  106. package/dist/plugins/loader.js.map +1 -0
  107. package/dist/providers/nli-http.d.ts +34 -0
  108. package/dist/providers/nli-http.d.ts.map +1 -0
  109. package/dist/providers/nli-http.js +83 -0
  110. package/dist/providers/nli-http.js.map +1 -0
  111. package/dist/providers/ollama.d.ts +37 -0
  112. package/dist/providers/ollama.d.ts.map +1 -0
  113. package/dist/providers/ollama.js +103 -0
  114. package/dist/providers/ollama.js.map +1 -0
  115. package/dist/providers/vertex-embed.d.ts +38 -0
  116. package/dist/providers/vertex-embed.d.ts.map +1 -0
  117. package/dist/providers/vertex-embed.js +69 -0
  118. package/dist/providers/vertex-embed.js.map +1 -0
  119. package/dist/providers/vertex-llm.d.ts +25 -0
  120. package/dist/providers/vertex-llm.d.ts.map +1 -0
  121. package/dist/providers/vertex-llm.js +75 -0
  122. package/dist/providers/vertex-llm.js.map +1 -0
  123. package/dist/stores/firestore.d.ts +59 -0
  124. package/dist/stores/firestore.d.ts.map +1 -0
  125. package/dist/stores/firestore.js +530 -0
  126. package/dist/stores/firestore.js.map +1 -0
  127. package/dist/stores/sqlite.d.ts +43 -0
  128. package/dist/stores/sqlite.d.ts.map +1 -0
  129. package/dist/stores/sqlite.js +593 -0
  130. package/dist/stores/sqlite.js.map +1 -0
  131. package/dist/triggers/pipeline.d.ts +21 -0
  132. package/dist/triggers/pipeline.d.ts.map +1 -0
  133. package/dist/triggers/pipeline.js +30 -0
  134. package/dist/triggers/pipeline.js.map +1 -0
  135. package/dist/triggers/registry.d.ts +17 -0
  136. package/dist/triggers/registry.d.ts.map +1 -0
  137. package/dist/triggers/registry.js +32 -0
  138. package/dist/triggers/registry.js.map +1 -0
  139. package/package.json +94 -0
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Digest engine — document ingestion pipeline for cortex.
3
+ *
4
+ * Takes raw document content (markdown with optional YAML frontmatter) and
5
+ * runs it through a configurable pipeline of cognitive steps. Each step is
6
+ * isolated in a try/catch so a single failure does not abort the pipeline.
7
+ *
8
+ * Pipeline steps:
9
+ * observe — embed and store content as observations (with prediction error gating)
10
+ * reflect — generate LLM insights connecting content to existing memories
11
+ * predict — extract forward-looking claims and store as prediction observations
12
+ */
13
+ import { parse as parseYaml } from 'yaml';
14
+ import { predictionErrorGate } from './memory.js';
15
+ import { extractKeywords } from './keywords.js';
16
+ /**
17
+ * Split YAML frontmatter from markdown body.
18
+ * Returns empty frontmatter and the full string if no frontmatter is found.
19
+ */
20
+ function parseDocument(content) {
21
+ const trimmed = content.trimStart();
22
+ if (!trimmed.startsWith('---')) {
23
+ return { frontmatter: {}, body: content };
24
+ }
25
+ const endMarker = trimmed.indexOf('\n---', 3);
26
+ if (endMarker === -1) {
27
+ return { frontmatter: {}, body: content };
28
+ }
29
+ const yamlBlock = trimmed.slice(3, endMarker).trim();
30
+ const body = trimmed.slice(endMarker + 4).trimStart();
31
+ let frontmatter = {};
32
+ try {
33
+ const parsed = parseYaml(yamlBlock);
34
+ if (parsed && typeof parsed === 'object') {
35
+ frontmatter = parsed;
36
+ }
37
+ }
38
+ catch {
39
+ // Malformed frontmatter — continue without it.
40
+ }
41
+ return { frontmatter, body };
42
+ }
43
+ // ─── Salience Detection ───────────────────────────────────────────────────────
44
+ /**
45
+ * Estimate salience from document structure and metadata.
46
+ * Returns a value on the 1–10 scale used by observe.
47
+ */
48
+ function detectSalience(frontmatter, body) {
49
+ // Frontmatter can override directly.
50
+ if (typeof frontmatter['salience'] === 'number') {
51
+ return Math.min(10, Math.max(1, frontmatter['salience']));
52
+ }
53
+ // Status hints.
54
+ const status = typeof frontmatter['status'] === 'string'
55
+ ? frontmatter['status'].toLowerCase()
56
+ : '';
57
+ if (status === 'active')
58
+ return 7;
59
+ if (status === 'archived')
60
+ return 3;
61
+ // Type hints.
62
+ const type = typeof frontmatter['type'] === 'string'
63
+ ? frontmatter['type'].toLowerCase()
64
+ : '';
65
+ if (type === 'mind' || type === 'journal')
66
+ return 7;
67
+ if (type === 'knowledge')
68
+ return 6;
69
+ // Fall back to content length heuristic.
70
+ if (body.length > 3000)
71
+ return 7;
72
+ if (body.length > 1000)
73
+ return 6;
74
+ return 5;
75
+ }
76
+ async function runObserveStep(body, frontmatter, store, embed, sourceFile, salience) {
77
+ const observation_ids = [];
78
+ const memories_linked = [];
79
+ const title = typeof frontmatter['title'] === 'string'
80
+ ? frontmatter['title']
81
+ : '';
82
+ if (body.length > 2000) {
83
+ // Long document: summarise first, then observe chunks.
84
+ // Summary chunk at full salience.
85
+ await (async () => {
86
+ try {
87
+ const summaryText = title ? `${title}\n\n${body.slice(0, 2000)}` : body.slice(0, 2000);
88
+ const embedding = await embed.embed(summaryText);
89
+ const gate = await predictionErrorGate(store, embedding);
90
+ const keywords = extractKeywords(summaryText);
91
+ const id = await store.putObservation({
92
+ content: summaryText,
93
+ source_file: sourceFile,
94
+ source_section: 'summary',
95
+ salience,
96
+ processed: false,
97
+ prediction_error: gate.max_similarity > 0 ? 1 - gate.max_similarity : null,
98
+ created_at: new Date(),
99
+ updated_at: new Date(),
100
+ embedding,
101
+ keywords,
102
+ });
103
+ observation_ids.push(id);
104
+ if (gate.decision === 'link' && gate.nearest_id) {
105
+ memories_linked.push(gate.nearest_id);
106
+ }
107
+ }
108
+ catch {
109
+ // Single chunk failure — continue.
110
+ }
111
+ })();
112
+ // Remaining body in ~500 char chunks at reduced salience.
113
+ const chunkSalience = Math.max(1, salience - 2);
114
+ const chunks = [];
115
+ for (let i = 2000; i < body.length; i += 500) {
116
+ chunks.push(body.slice(i, i + 500));
117
+ }
118
+ for (const chunk of chunks) {
119
+ try {
120
+ const embedding = await embed.embed(chunk);
121
+ const gate = await predictionErrorGate(store, embedding);
122
+ const keywords = extractKeywords(chunk);
123
+ const id = await store.putObservation({
124
+ content: chunk,
125
+ source_file: sourceFile,
126
+ source_section: 'chunk',
127
+ salience: chunkSalience,
128
+ processed: false,
129
+ prediction_error: gate.max_similarity > 0 ? 1 - gate.max_similarity : null,
130
+ created_at: new Date(),
131
+ updated_at: new Date(),
132
+ embedding,
133
+ keywords,
134
+ });
135
+ observation_ids.push(id);
136
+ if (gate.decision === 'link' && gate.nearest_id) {
137
+ memories_linked.push(gate.nearest_id);
138
+ }
139
+ }
140
+ catch {
141
+ // Single chunk failure — continue.
142
+ }
143
+ }
144
+ }
145
+ else {
146
+ // Short document: observe whole body.
147
+ try {
148
+ const observeText = title ? `${title}\n\n${body}` : body;
149
+ const embedding = await embed.embed(observeText);
150
+ const gate = await predictionErrorGate(store, embedding);
151
+ const keywords = extractKeywords(observeText);
152
+ const id = await store.putObservation({
153
+ content: observeText,
154
+ source_file: sourceFile,
155
+ source_section: '',
156
+ salience,
157
+ processed: false,
158
+ prediction_error: gate.max_similarity > 0 ? 1 - gate.max_similarity : null,
159
+ created_at: new Date(),
160
+ updated_at: new Date(),
161
+ embedding,
162
+ keywords,
163
+ });
164
+ observation_ids.push(id);
165
+ if (gate.decision === 'link' && gate.nearest_id) {
166
+ memories_linked.push(gate.nearest_id);
167
+ }
168
+ }
169
+ catch {
170
+ // Observe step failed — return empty.
171
+ }
172
+ }
173
+ return { observation_ids, memories_linked };
174
+ }
175
+ // ─── Reflect Step ─────────────────────────────────────────────────────────────
176
+ async function runReflectStep(body, store, embed, llm, sourceFile, salience) {
177
+ const insights = [];
178
+ try {
179
+ // Find memories related to this content.
180
+ const contentEmbedding = await embed.embed(body.slice(0, 1000));
181
+ const related = await store.findNearest(contentEmbedding, 5);
182
+ const memoryContext = related
183
+ .map(r => `- ${r.memory.name}: ${r.memory.definition}`)
184
+ .join('\n');
185
+ const snippet = body.length > 800 ? body.slice(0, 800) + '...' : body;
186
+ const prompt = `You are reflecting on new document content and connecting it to existing knowledge.\n\n` +
187
+ `Document content:\n${snippet}\n\n` +
188
+ `Related memories:\n${memoryContext || '(no related memories found)'}\n\n` +
189
+ `Generate 2-3 concise insights that connect this content to the existing memories, ` +
190
+ `or identify novel patterns and implications. Each insight on its own line. ` +
191
+ `No preamble, no numbering — just the insights.`;
192
+ const reflectionText = await llm.generate(prompt, {
193
+ temperature: 0.6,
194
+ maxTokens: 400,
195
+ });
196
+ const insightLines = reflectionText
197
+ .split('\n')
198
+ .map(l => l.trim())
199
+ .filter(l => l.length > 20);
200
+ for (const insight of insightLines) {
201
+ try {
202
+ const embedding = await embed.embed(insight);
203
+ const keywords = extractKeywords(`digest reflect ${insight}`);
204
+ await store.putObservation({
205
+ content: insight,
206
+ source_file: sourceFile,
207
+ source_section: 'digest:reflect',
208
+ salience: Math.max(1, salience - 1),
209
+ processed: false,
210
+ prediction_error: null,
211
+ created_at: new Date(),
212
+ updated_at: new Date(),
213
+ embedding,
214
+ keywords,
215
+ });
216
+ insights.push(insight);
217
+ }
218
+ catch {
219
+ // One insight failing to store should not stop the rest.
220
+ }
221
+ }
222
+ }
223
+ catch {
224
+ // Reflect step failed — return whatever insights accumulated.
225
+ }
226
+ return insights;
227
+ }
228
+ // ─── Predict Step ─────────────────────────────────────────────────────────────
229
+ async function runPredictStep(body, store, embed, llm, sourceFile, salience) {
230
+ const extractedPredictions = [];
231
+ try {
232
+ const snippet = body.length > 1000 ? body.slice(0, 1000) + '...' : body;
233
+ const prompt = `Extract forward-looking claims or predictions from this text. ` +
234
+ `Only include explicit predictions, goals, plans, or hypotheses about future events. ` +
235
+ `If there are no forward-looking claims, respond with: NO_PREDICTIONS\n\n` +
236
+ `Text:\n${snippet}\n\n` +
237
+ `List each prediction on its own line. No preamble, no numbering.`;
238
+ const result = await llm.generate(prompt, {
239
+ temperature: 0.1,
240
+ maxTokens: 300,
241
+ });
242
+ const trimmed = result.trim();
243
+ if (trimmed === 'NO_PREDICTIONS' || !trimmed) {
244
+ return extractedPredictions;
245
+ }
246
+ const predictions = trimmed
247
+ .split('\n')
248
+ .map(l => l.trim())
249
+ .filter(l => l.length > 15 && l !== 'NO_PREDICTIONS');
250
+ for (const prediction of predictions) {
251
+ try {
252
+ const embedding = await embed.embed(prediction);
253
+ const keywords = extractKeywords(`prediction ${prediction}`);
254
+ await store.putObservation({
255
+ content: prediction,
256
+ source_file: sourceFile,
257
+ source_section: 'digest:predict',
258
+ salience: Math.max(1, salience - 1),
259
+ processed: false,
260
+ prediction_error: null,
261
+ created_at: new Date(),
262
+ updated_at: new Date(),
263
+ embedding,
264
+ keywords,
265
+ });
266
+ extractedPredictions.push(prediction);
267
+ }
268
+ catch {
269
+ // One prediction failing should not stop the rest.
270
+ }
271
+ }
272
+ }
273
+ catch {
274
+ // Predict step failed — return whatever accumulated.
275
+ }
276
+ return extractedPredictions;
277
+ }
278
+ // ─── Main: digestDocument ─────────────────────────────────────────────────────
279
+ /**
280
+ * Process a document through the cortex ingestion pipeline.
281
+ *
282
+ * Parses frontmatter, detects salience, then runs each requested pipeline step
283
+ * in sequence. Steps are isolated — a single step failure does not abort the
284
+ * pipeline; it is logged as skipped.
285
+ *
286
+ * Supported steps: 'observe', 'reflect', 'predict'
287
+ * Unknown steps are silently skipped and recorded in pipeline_executed as
288
+ * 'skipped:<name>'.
289
+ */
290
+ export async function digestDocument(content, store, embed, llm, options) {
291
+ const start = Date.now();
292
+ const pipeline = options?.pipeline ?? ['observe', 'reflect'];
293
+ const sourceFile = options?.source_file ?? '';
294
+ const { frontmatter, body } = parseDocument(content);
295
+ const salience = options?.salience ?? detectSalience(frontmatter, body);
296
+ const observation_ids = [];
297
+ const memories_linked = [];
298
+ const insights = [];
299
+ const pipeline_executed = [];
300
+ for (const step of pipeline) {
301
+ switch (step) {
302
+ case 'observe': {
303
+ try {
304
+ const result = await runObserveStep(body, frontmatter, store, embed, sourceFile, salience);
305
+ observation_ids.push(...result.observation_ids);
306
+ memories_linked.push(...result.memories_linked);
307
+ pipeline_executed.push('observe');
308
+ }
309
+ catch {
310
+ pipeline_executed.push('observe:failed');
311
+ }
312
+ break;
313
+ }
314
+ case 'reflect': {
315
+ try {
316
+ const stepInsights = await runReflectStep(body, store, embed, llm, sourceFile, salience);
317
+ insights.push(...stepInsights);
318
+ pipeline_executed.push('reflect');
319
+ }
320
+ catch {
321
+ pipeline_executed.push('reflect:failed');
322
+ }
323
+ break;
324
+ }
325
+ case 'predict': {
326
+ try {
327
+ const predictions = await runPredictStep(body, store, embed, llm, sourceFile, salience);
328
+ insights.push(...predictions);
329
+ pipeline_executed.push('predict');
330
+ }
331
+ catch {
332
+ pipeline_executed.push('predict:failed');
333
+ }
334
+ break;
335
+ }
336
+ default: {
337
+ pipeline_executed.push(`skipped:${step}`);
338
+ break;
339
+ }
340
+ }
341
+ }
342
+ return {
343
+ observation_ids,
344
+ memories_linked: [...new Set(memories_linked)],
345
+ insights,
346
+ pipeline_executed,
347
+ processed_at: new Date(),
348
+ duration_ms: Date.now() - start,
349
+ };
350
+ }
351
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../../src/engines/digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * FSRS-6 — Free Spaced Repetition Scheduler.
3
+ *
4
+ * Pure math, zero dependencies. Extracted from idapixl-cortex/src/engines/memory.ts.
5
+ *
6
+ * FSRS-6 uses a power-law decay model to predict recall probability
7
+ * and schedule optimal review intervals. Each memory has:
8
+ * - stability: expected days until recall probability drops to 90%
9
+ * - difficulty: 1-10 scale of how hard the memory is to retain
10
+ * - state: new → learning → review → relearning lifecycle
11
+ *
12
+ * Rating scale: 1=Again, 2=Hard, 3=Good, 4=Easy
13
+ */
14
+ import type { FSRSData, ScheduleResult } from '../core/types.js';
15
+ /** Default FSRS-6 weights (w[0]..w[20]) from the open-source paper. */
16
+ export declare const FSRS_WEIGHTS: readonly number[];
17
+ export declare const DESIRED_RETENTION = 0.9;
18
+ /**
19
+ * Probability of recall after `elapsed_days` with given `stability`.
20
+ * Decays from 1.0 toward 0 following a power curve.
21
+ */
22
+ export declare function retrievability(stability: number, elapsed_days: number): number;
23
+ /**
24
+ * Initial stability for a new card rated 1-4 on first review.
25
+ */
26
+ export declare function initialStability(rating: 1 | 2 | 3 | 4): number;
27
+ /**
28
+ * Schedule the next review for a memory given a rating.
29
+ * Returns updated FSRS fields and the next interval in days.
30
+ *
31
+ * @param fsrs - Current FSRS state of the memory
32
+ * @param rating - Review quality: 1=Again, 2=Hard, 3=Good, 4=Easy
33
+ * @param elapsed_days - Days since last review (0 for new memories)
34
+ */
35
+ export declare function scheduleNext(fsrs: FSRSData, rating: 1 | 2 | 3 | 4, elapsed_days?: number): ScheduleResult;
36
+ /**
37
+ * Calculate elapsed days between a date and now.
38
+ */
39
+ export declare function elapsedDaysSince(date: Date | null): number;
40
+ /**
41
+ * Create fresh FSRS state for a new memory.
42
+ */
43
+ export declare function newFSRSState(): FSRSData;
44
+ //# sourceMappingURL=fsrs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsrs.d.ts","sourceRoot":"","sources":["../../src/engines/fsrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAa,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAI5E,uEAAuE;AACvE,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAKzC,CAAC;AAEF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAOrC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE9E;AAsCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EACrB,YAAY,GAAE,MAAU,GACvB,cAAc,CA4BhB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAI1D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CASvC"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * FSRS-6 — Free Spaced Repetition Scheduler.
3
+ *
4
+ * Pure math, zero dependencies. Extracted from idapixl-cortex/src/engines/memory.ts.
5
+ *
6
+ * FSRS-6 uses a power-law decay model to predict recall probability
7
+ * and schedule optimal review intervals. Each memory has:
8
+ * - stability: expected days until recall probability drops to 90%
9
+ * - difficulty: 1-10 scale of how hard the memory is to retain
10
+ * - state: new → learning → review → relearning lifecycle
11
+ *
12
+ * Rating scale: 1=Again, 2=Hard, 3=Good, 4=Easy
13
+ */
14
+ // ─── FSRS-6 Constants ─────────────────────────────────────────────────────────
15
+ /** Default FSRS-6 weights (w[0]..w[20]) from the open-source paper. */
16
+ export const FSRS_WEIGHTS = [
17
+ 0.4072, 1.1829, 3.1262, 15.4722,
18
+ 7.2102, 0.5316, 1.0651, 0.0589,
19
+ 1.506, 0.14, 1.0036, 1.9395,
20
+ 0.11, 0.2918, 0.5, 1.0, 2.0, 0.0, 0.0, 0.0, 0.0,
21
+ ];
22
+ export const DESIRED_RETENTION = 0.9;
23
+ const DECAY = -0.5;
24
+ const FACTOR = Math.pow(0.9, 1 / DECAY) - 1;
25
+ // ─── Core Functions ───────────────────────────────────────────────────────────
26
+ /**
27
+ * Probability of recall after `elapsed_days` with given `stability`.
28
+ * Decays from 1.0 toward 0 following a power curve.
29
+ */
30
+ export function retrievability(stability, elapsed_days) {
31
+ return Math.pow(1 + FACTOR * elapsed_days / stability, DECAY);
32
+ }
33
+ /**
34
+ * New difficulty after a review with a given rating.
35
+ */
36
+ function updateDifficulty(d, rating) {
37
+ const delta = -FSRS_WEIGHTS[6] * (rating - 3);
38
+ const mean_reversion = FSRS_WEIGHTS[7] * (FSRS_WEIGHTS[4] - d);
39
+ return Math.min(10, Math.max(1, d + delta + mean_reversion));
40
+ }
41
+ /**
42
+ * Stability after a successful recall (short-term memory strengthening).
43
+ */
44
+ function stabilityAfterRecall(d, s, r, rating) {
45
+ const hard_penalty = rating === 2 ? FSRS_WEIGHTS[15] : 1;
46
+ const easy_bonus = rating === 4 ? FSRS_WEIGHTS[16] : 1;
47
+ return s * (Math.exp(FSRS_WEIGHTS[8]) *
48
+ (11 - d) *
49
+ Math.pow(s, -FSRS_WEIGHTS[9]) *
50
+ (Math.exp((1 - r) * FSRS_WEIGHTS[10]) - 1) *
51
+ hard_penalty * easy_bonus) + s;
52
+ }
53
+ /**
54
+ * Stability after forgetting (relearning curve).
55
+ */
56
+ function stabilityAfterForgetting(d, s, r) {
57
+ return FSRS_WEIGHTS[11] *
58
+ Math.pow(d, -FSRS_WEIGHTS[12]) *
59
+ (Math.pow(s + 1, FSRS_WEIGHTS[13]) - 1) *
60
+ Math.exp((1 - r) * FSRS_WEIGHTS[14]);
61
+ }
62
+ /**
63
+ * Initial stability for a new card rated 1-4 on first review.
64
+ */
65
+ export function initialStability(rating) {
66
+ return Math.max(FSRS_WEIGHTS[rating - 1], 0.1);
67
+ }
68
+ /**
69
+ * Schedule the next review for a memory given a rating.
70
+ * Returns updated FSRS fields and the next interval in days.
71
+ *
72
+ * @param fsrs - Current FSRS state of the memory
73
+ * @param rating - Review quality: 1=Again, 2=Hard, 3=Good, 4=Easy
74
+ * @param elapsed_days - Days since last review (0 for new memories)
75
+ */
76
+ export function scheduleNext(fsrs, rating, elapsed_days = 0) {
77
+ let stability;
78
+ let difficulty;
79
+ let state;
80
+ if (fsrs.state === 'new') {
81
+ stability = initialStability(rating);
82
+ difficulty = FSRS_WEIGHTS[4] - FSRS_WEIGHTS[5] * (rating - 3);
83
+ state = rating === 1 ? 'relearning' : 'learning';
84
+ }
85
+ else {
86
+ const r = retrievability(fsrs.stability, elapsed_days);
87
+ difficulty = updateDifficulty(fsrs.difficulty, rating);
88
+ if (rating === 1) {
89
+ stability = stabilityAfterForgetting(difficulty, fsrs.stability, r);
90
+ state = 'relearning';
91
+ }
92
+ else {
93
+ stability = stabilityAfterRecall(difficulty, fsrs.stability, r, rating);
94
+ state = 'review';
95
+ }
96
+ }
97
+ const interval_days = Math.max(1, Math.round(stability * Math.log(DESIRED_RETENTION) / Math.log(0.9)));
98
+ return { stability, difficulty, interval_days, state };
99
+ }
100
+ /**
101
+ * Calculate elapsed days between a date and now.
102
+ */
103
+ export function elapsedDaysSince(date) {
104
+ if (!date)
105
+ return 0;
106
+ const ms = Date.now() - date.getTime();
107
+ return ms / (1000 * 60 * 60 * 24);
108
+ }
109
+ /**
110
+ * Create fresh FSRS state for a new memory.
111
+ */
112
+ export function newFSRSState() {
113
+ return {
114
+ stability: FSRS_WEIGHTS[2],
115
+ difficulty: FSRS_WEIGHTS[4],
116
+ reps: 0,
117
+ lapses: 0,
118
+ state: 'new',
119
+ last_review: null,
120
+ };
121
+ }
122
+ //# sourceMappingURL=fsrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsrs.js","sourceRoot":"","sources":["../../src/engines/fsrs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Keyword extraction — no LLM, no latency, no cost.
3
+ *
4
+ * Strips stop words, extracts significant terms, deduplicates.
5
+ * Extracted from idapixl-cortex/src/engines/keywords.ts.
6
+ */
7
+ /**
8
+ * Extract up to `max` meaningful keywords from text.
9
+ * Returns lowercase, deduplicated terms of 3+ characters.
10
+ */
11
+ export declare function extractKeywords(text: string, max?: number): string[];
12
+ //# sourceMappingURL=keywords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keywords.d.ts","sourceRoot":"","sources":["../../src/engines/keywords.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAW,GAAG,MAAM,EAAE,CAWxE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Keyword extraction — no LLM, no latency, no cost.
3
+ *
4
+ * Strips stop words, extracts significant terms, deduplicates.
5
+ * Extracted from idapixl-cortex/src/engines/keywords.ts.
6
+ */
7
+ const STOP_WORDS = new Set([
8
+ 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
9
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
10
+ 'may', 'might', 'shall', 'can', 'need', 'ought', 'used', 'to', 'of', 'in', 'on',
11
+ 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through',
12
+ 'during', 'before', 'after', 'above', 'below', 'from', 'up', 'down', 'and',
13
+ 'but', 'or', 'nor', 'so', 'yet', 'both', 'either', 'neither', 'not', 'only',
14
+ 'same', 'than', 'too', 'very', 'just', 'because', 'as', 'until', 'while',
15
+ 'although', 'though', 'that', 'this', 'these', 'those', 'it', 'its', 'i', 'me',
16
+ 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your', 'yours', 'he',
17
+ 'him', 'his', 'she', 'her', 'hers', 'they', 'them', 'their', 'theirs', 'what',
18
+ 'which', 'who', 'when', 'where', 'why', 'how', 'all', 'each', 'every', 'no',
19
+ 'more', 'most', 'other', 'some', 'such', 'then', 'its', 'also', 'been', 'if',
20
+ 'now', 'like', 'well', 'even', 'back', 'any', 'there', 'think', 'see', 'know',
21
+ 'get', 'one', 'two', 'three', 'new', 'good', 'first', 'last', 'long', 'great',
22
+ 'little', 'own', 'right', 'big', 'high', 'different', 'small', 'large', 'next',
23
+ 'early', 'young', 'old', 'public', 'private', 'real', 'best', 'free', 'much',
24
+ 'want', 'make', 'time', 'year', 'day', 'way', 'man', 'much', 'many', 'look',
25
+ 'come', 'still', 'here', 'take', 'give', 'use', 'find', 'tell', 'ask', 'seem',
26
+ 'feel', 'leave', 'call', 'keep', 'let', 'begin', 'show', 'hear', 'play', 'run',
27
+ 'move', 'live', 'believe', 'hold', 'bring', 'happen', 'write', 'provide', 'sit',
28
+ 'stand', 'lose', 'pay', 'meet', 'include', 'continue', 'set', 'learn', 'change',
29
+ 'lead', 'understand', 'watch', 'follow', 'stop', 'create', 'speak', 'read', 'spend',
30
+ ]);
31
+ /**
32
+ * Extract up to `max` meaningful keywords from text.
33
+ * Returns lowercase, deduplicated terms of 3+ characters.
34
+ */
35
+ export function extractKeywords(text, max = 20) {
36
+ return [
37
+ ...new Set(text
38
+ .toLowerCase()
39
+ .replace(/[^a-z0-9\s'-]/g, ' ')
40
+ .split(/\s+/)
41
+ .map(w => w.replace(/^['-]+|['-]+$/g, ''))
42
+ .filter(w => w.length >= 3 && !STOP_WORDS.has(w) && !/^\d+$/.test(w))),
43
+ ].slice(0, max);
44
+ }
45
+ //# sourceMappingURL=keywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keywords.js","sourceRoot":"","sources":["../../src/engines/keywords.ts"],"names":[],"mappings":"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"}