@loreai/core 0.11.1 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAyVtC,wBAAgB,EAAE,IAAI,QAAQ,CAkC7B;AAqCD,wBAAgB,KAAK,SAKpB;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAYjE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK1D;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAYxE"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAyVtC,wBAAgB,EAAE,IAAI,QAAQ,CAkC7B;AAmGD,wBAAgB,KAAK,SAKpB;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAYjE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK1D;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAKpC;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAYxE"}
@@ -3,6 +3,32 @@ import { workerSessionIDs } from "./worker";
3
3
  import type { LLMClient } from "./types";
4
4
  export { workerSessionIDs };
5
5
  type TemporalMessage = temporal.TemporalMessage;
6
+ /**
7
+ * Compression health ratio: k / √N.
8
+ *
9
+ * k = distilled token count, N = source token count.
10
+ * Values < 1.0 signal likely lossy compression (below the square-root
11
+ * boundary). Values > 1.0 signal relatively faithful compression.
12
+ *
13
+ * Based on the "LLM Context Square Root Theory" heuristic from
14
+ * D7x7z49/llm-context-idea. The specific threshold is unvalidated —
15
+ * use as a diagnostic signal, not a hard gate.
16
+ */
17
+ export declare function compressionRatio(distilledTokens: number, sourceTokens: number): number;
18
+ /**
19
+ * Segment detection: group related messages into distillation-sized chunks.
20
+ *
21
+ * When the message count exceeds `maxSegment`, prefers splitting at the
22
+ * largest inter-message time gap (if it's ≥ 3× the median gap) to respect
23
+ * natural conversation boundaries. Falls back to count-based splitting at
24
+ * `maxSegment` when timestamps are uniform.
25
+ *
26
+ * Trailing segments with < 3 messages are merged into the previous segment
27
+ * to avoid tiny distillation inputs with too little context.
28
+ *
29
+ * Exported for testing; `run()` is the production caller.
30
+ */
31
+ export declare function detectSegments(messages: TemporalMessage[], maxSegment: number): TemporalMessage[][];
6
32
  /**
7
33
  * Truncate tool outputs within a `TemporalMessage.content` string (produced
8
34
  * by `temporal.partsToText`). Plain text and `[reasoning]` chunks pass
@@ -1 +1 @@
1
- {"version":3,"file":"distillation.d.ts","sourceRoot":"","sources":["../../src/distillation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAWvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,KAAK,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AAmDhD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAwBR;AAgBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,eAAe,EAAE,EAC3B,kBAAkB,CAAC,EAAE,MAAM,GAC1B,MAAM,CAUR;AAED,KAAK,kBAAkB,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAwBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAEpB;AAwBD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpD;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,eAAe,UAAQ,GACtB,YAAY,EAAE,CAqBhB;AA0ID,wBAAsB,GAAG,CAAC,KAAK,EAAE;IAC/B,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA4DjD;AAsDD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE;IACvC,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA+ErC"}
1
+ {"version":3,"file":"distillation.d.ts","sourceRoot":"","sources":["../../src/distillation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAWvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,KAAK,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,GACnB,MAAM,CAGR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,eAAe,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,eAAe,EAAE,EAAE,CAGrB;AAwGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAwBR;AAgBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,eAAe,EAAE,EAC3B,kBAAkB,CAAC,EAAE,MAAM,GAC1B,MAAM,CAUR;AAED,KAAK,kBAAkB,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAwBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAEpB;AAwBD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpD;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,eAAe,UAAQ,GACtB,YAAY,EAAE,CAqBhB;AA0ID,wBAAsB,GAAG,CAAC,KAAK,EAAE;IAC/B,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA4DjD;AAmED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE;IACvC,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA+ErC"}
package/dist/bun/index.js CHANGED
@@ -131,6 +131,7 @@ __export(temporal_exports, {
131
131
  search: () => search2,
132
132
  searchScored: () => searchScored,
133
133
  store: () => store,
134
+ temporalCnorm: () => temporalCnorm,
134
135
  undistilled: () => undistilled,
135
136
  undistilledCount: () => undistilledCount
136
137
  });
@@ -508,16 +509,47 @@ function migrate(database) {
508
509
  "SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'"
509
510
  ).get();
510
511
  const current2 = row ? database.query("SELECT version FROM schema_version").get()?.version ?? 0 : 0;
511
- if (current2 >= MIGRATIONS.length) return;
512
+ if (current2 >= MIGRATIONS.length) {
513
+ recoverMissingObjects(database);
514
+ return;
515
+ }
512
516
  for (let i = current2; i < MIGRATIONS.length; i++) {
513
517
  if (i === VACUUM_MIGRATION_INDEX) {
514
518
  database.exec("PRAGMA auto_vacuum = INCREMENTAL");
515
519
  database.exec("VACUUM");
516
520
  } else {
517
- database.exec(MIGRATIONS[i]);
521
+ try {
522
+ database.exec(MIGRATIONS[i]);
523
+ } catch (e) {
524
+ if (e instanceof Error && /duplicate column name/i.test(e.message)) {
525
+ const stripped = stripAppliedAlters(MIGRATIONS[i], database);
526
+ if (stripped.trim()) database.exec(stripped);
527
+ } else {
528
+ throw e;
529
+ }
530
+ }
518
531
  }
519
532
  }
520
533
  database.exec(`UPDATE schema_version SET version = ${MIGRATIONS.length}`);
534
+ recoverMissingObjects(database);
535
+ }
536
+ function stripAppliedAlters(migration, database) {
537
+ return migration.replace(
538
+ /ALTER\s+TABLE\s+(\w+)\s+ADD\s+COLUMN\s+(\w+)\b[^;]*;/gi,
539
+ (match, table, column) => {
540
+ const cols = database.query(`PRAGMA table_info(${table})`).all();
541
+ if (cols.some((c) => c.name === column)) return "";
542
+ return match;
543
+ }
544
+ );
545
+ }
546
+ function recoverMissingObjects(database) {
547
+ database.exec(`
548
+ CREATE TABLE IF NOT EXISTS kv_meta (
549
+ key TEXT PRIMARY KEY,
550
+ value TEXT NOT NULL
551
+ );
552
+ `);
521
553
  }
522
554
  function close() {
523
555
  if (instance) {
@@ -11423,6 +11455,18 @@ function searchScored(input) {
11423
11455
  return [];
11424
11456
  }
11425
11457
  }
11458
+ function temporalCnorm(timestamps, now = Date.now()) {
11459
+ const n = timestamps.length;
11460
+ if (n < 2) return 0;
11461
+ const durations = timestamps.map((t2) => now - t2);
11462
+ const totalDuration = durations.reduce((a, b) => a + b, 0);
11463
+ if (totalDuration <= 0) return 0;
11464
+ const weights = durations.map((d) => d / totalDuration);
11465
+ const uniform = 1 / n;
11466
+ const variance = weights.reduce((sum, w) => sum + (w - uniform) ** 2, 0) / n;
11467
+ const maxVariance = (n - 1) / (n * n);
11468
+ return maxVariance === 0 ? 0 : variance / maxVariance;
11469
+ }
11426
11470
  function count(projectPath, sessionID) {
11427
11471
  const pid = ensureProject(projectPath);
11428
11472
  const query = sessionID ? "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ? AND session_id = ?" : "SELECT COUNT(*) as count FROM temporal_messages WHERE project_id = ?";
@@ -26740,6 +26784,8 @@ function check2(projectPath) {
26740
26784
  // src/distillation.ts
26741
26785
  var distillation_exports = {};
26742
26786
  __export(distillation_exports, {
26787
+ compressionRatio: () => compressionRatio,
26788
+ detectSegments: () => detectSegments,
26743
26789
  latestMetaObservations: () => latestMetaObservations,
26744
26790
  loadForSession: () => loadForSession,
26745
26791
  messagesToText: () => messagesToText,
@@ -27597,25 +27643,50 @@ function isWorkerSession(sessionID) {
27597
27643
  }
27598
27644
 
27599
27645
  // src/distillation.ts
27646
+ function compressionRatio(distilledTokens, sourceTokens) {
27647
+ if (sourceTokens <= 0) return 0;
27648
+ return distilledTokens / Math.sqrt(sourceTokens);
27649
+ }
27600
27650
  function detectSegments(messages, maxSegment) {
27601
27651
  if (messages.length <= maxSegment) return [messages];
27602
- const segments = [];
27603
- let current2 = [];
27604
- for (const msg of messages) {
27605
- current2.push(msg);
27606
- if (current2.length >= maxSegment) {
27607
- segments.push(current2);
27608
- current2 = [];
27609
- }
27610
- }
27611
- if (current2.length > 0) {
27612
- if (current2.length < 3 && segments.length > 0) {
27613
- segments[segments.length - 1].push(...current2);
27614
- } else {
27615
- segments.push(current2);
27652
+ return splitSegments(messages, maxSegment);
27653
+ }
27654
+ var MIN_SEGMENT = 3;
27655
+ var GAP_THRESHOLD_MULTIPLIER = 3;
27656
+ function splitSegments(messages, maxSegment) {
27657
+ if (messages.length <= maxSegment) return [messages];
27658
+ const splitIdx = findSplitIndex(messages, maxSegment);
27659
+ const left = messages.slice(0, splitIdx);
27660
+ const right = messages.slice(splitIdx);
27661
+ const result = splitSegments(left, maxSegment);
27662
+ if (right.length < MIN_SEGMENT) {
27663
+ result[result.length - 1].push(...right);
27664
+ } else {
27665
+ result.push(...splitSegments(right, maxSegment));
27666
+ }
27667
+ return result;
27668
+ }
27669
+ function findSplitIndex(messages, maxSegment) {
27670
+ const gaps = [];
27671
+ for (let i = 1; i < messages.length; i++) {
27672
+ gaps.push({
27673
+ index: i,
27674
+ gap: messages[i].created_at - messages[i - 1].created_at
27675
+ });
27676
+ }
27677
+ if (gaps.length === 0) return maxSegment;
27678
+ const sortedGaps = gaps.map((g) => g.gap).sort((a, b) => a - b);
27679
+ const medianGap = sortedGaps[Math.floor(sortedGaps.length / 2)];
27680
+ let bestGap = { index: -1, gap: 0 };
27681
+ for (const g of gaps) {
27682
+ if (g.gap > bestGap.gap && g.index >= MIN_SEGMENT && messages.length - g.index >= MIN_SEGMENT) {
27683
+ bestGap = g;
27616
27684
  }
27617
27685
  }
27618
- return segments;
27686
+ if (bestGap.index > 0 && bestGap.gap >= medianGap * GAP_THRESHOLD_MULTIPLIER) {
27687
+ return bestGap.index;
27688
+ }
27689
+ return maxSegment;
27619
27690
  }
27620
27691
  function formatTime(ms) {
27621
27692
  const d = new Date(ms);
@@ -27853,6 +27924,13 @@ async function distillSegment(input) {
27853
27924
  generation: 0
27854
27925
  });
27855
27926
  markDistilled(input.messages.map((m) => m.id));
27927
+ const distilledTokens = Math.ceil(result.observations.length / 3);
27928
+ const sourceTokens = input.messages.reduce((sum, m) => sum + m.tokens, 0);
27929
+ const rComp = compressionRatio(distilledTokens, sourceTokens);
27930
+ const cNorm = temporalCnorm(input.messages.map((m) => m.created_at));
27931
+ info(
27932
+ `distill segment: ${input.messages.length} msgs, ${sourceTokens}\u2192${distilledTokens} tokens, R=${rComp.toFixed(2)}, C_norm=${cNorm.toFixed(3)}`
27933
+ );
27856
27934
  if (isAvailable()) {
27857
27935
  embedDistillation(distillId, result.observations);
27858
27936
  }
@@ -28217,6 +28295,18 @@ async function runRecall(input) {
28217
28295
  key: (r) => `t:${r.item.id}`
28218
28296
  }
28219
28297
  );
28298
+ if (temporalResults.length > 0) {
28299
+ const recencySorted = [...temporalResults].sort(
28300
+ (a, b) => b.created_at - a.created_at
28301
+ );
28302
+ allRrfLists.push({
28303
+ items: recencySorted.map((item) => ({
28304
+ source: "temporal",
28305
+ item
28306
+ })),
28307
+ key: (r) => `t:${r.item.id}`
28308
+ });
28309
+ }
28220
28310
  }
28221
28311
  if (isAvailable() && scope !== "session") {
28222
28312
  try {