@loreai/core 0.20.2 → 0.22.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 (59) hide show
  1. package/README.md +1 -1
  2. package/dist/bun/config.d.ts +1 -0
  3. package/dist/bun/config.d.ts.map +1 -1
  4. package/dist/bun/curator.d.ts +2 -0
  5. package/dist/bun/curator.d.ts.map +1 -1
  6. package/dist/bun/db.d.ts +13 -2
  7. package/dist/bun/db.d.ts.map +1 -1
  8. package/dist/bun/distillation.d.ts.map +1 -1
  9. package/dist/bun/gradient.d.ts +7 -4
  10. package/dist/bun/gradient.d.ts.map +1 -1
  11. package/dist/bun/index.d.ts +2 -2
  12. package/dist/bun/index.d.ts.map +1 -1
  13. package/dist/bun/index.js +156 -23
  14. package/dist/bun/index.js.map +3 -3
  15. package/dist/bun/ltm.d.ts +10 -0
  16. package/dist/bun/ltm.d.ts.map +1 -1
  17. package/dist/bun/prompt.d.ts +1 -1
  18. package/dist/bun/prompt.d.ts.map +1 -1
  19. package/dist/node/config.d.ts +1 -0
  20. package/dist/node/config.d.ts.map +1 -1
  21. package/dist/node/curator.d.ts +2 -0
  22. package/dist/node/curator.d.ts.map +1 -1
  23. package/dist/node/db.d.ts +13 -2
  24. package/dist/node/db.d.ts.map +1 -1
  25. package/dist/node/distillation.d.ts.map +1 -1
  26. package/dist/node/gradient.d.ts +7 -4
  27. package/dist/node/gradient.d.ts.map +1 -1
  28. package/dist/node/index.d.ts +2 -2
  29. package/dist/node/index.d.ts.map +1 -1
  30. package/dist/node/index.js +156 -23
  31. package/dist/node/index.js.map +3 -3
  32. package/dist/node/ltm.d.ts +10 -0
  33. package/dist/node/ltm.d.ts.map +1 -1
  34. package/dist/node/prompt.d.ts +1 -1
  35. package/dist/node/prompt.d.ts.map +1 -1
  36. package/dist/types/config.d.ts +1 -0
  37. package/dist/types/config.d.ts.map +1 -1
  38. package/dist/types/curator.d.ts +2 -0
  39. package/dist/types/curator.d.ts.map +1 -1
  40. package/dist/types/db.d.ts +13 -2
  41. package/dist/types/db.d.ts.map +1 -1
  42. package/dist/types/distillation.d.ts.map +1 -1
  43. package/dist/types/gradient.d.ts +7 -4
  44. package/dist/types/gradient.d.ts.map +1 -1
  45. package/dist/types/index.d.ts +2 -2
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/ltm.d.ts +10 -0
  48. package/dist/types/ltm.d.ts.map +1 -1
  49. package/dist/types/prompt.d.ts +1 -1
  50. package/dist/types/prompt.d.ts.map +1 -1
  51. package/package.json +1 -1
  52. package/src/config.ts +4 -2
  53. package/src/curator.ts +3 -0
  54. package/src/db.ts +66 -14
  55. package/src/distillation.ts +5 -0
  56. package/src/gradient.ts +27 -12
  57. package/src/index.ts +2 -0
  58. package/src/ltm.ts +101 -5
  59. package/src/prompt.ts +31 -4
@@ -816,6 +816,17 @@ var MIGRATIONS = [
816
816
  );
817
817
  CREATE INDEX IF NOT EXISTS idx_dedup_feedback_project
818
818
  ON dedup_feedback(project_id);
819
+ `,
820
+ `
821
+ -- Version 26: Persist sub-agent parent\u2013child session relationships.
822
+ -- parent_session_id: Lore internal session ID of the parent session
823
+ -- (resolved from the x-parent-session-id header at detection time).
824
+ -- NULL for root (non-sub-agent) sessions.
825
+ -- is_subagent: boolean flag (1 = sub-agent) so the flag survives
826
+ -- gateway restarts without requiring the header again.
827
+ ALTER TABLE session_state ADD COLUMN parent_session_id TEXT;
828
+ ALTER TABLE session_state ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0;
829
+ CREATE INDEX IF NOT EXISTS idx_session_state_parent ON session_state(parent_session_id);
819
830
  `
820
831
  ];
821
832
  function dbPath() {
@@ -1039,13 +1050,11 @@ function loadForceMinLayer(sessionID) {
1039
1050
  return row?.force_min_layer ?? 0;
1040
1051
  }
1041
1052
  function saveForceMinLayer(sessionID, layer) {
1042
- if (layer === 0) {
1043
- db().query("DELETE FROM session_state WHERE session_id = ?").run(sessionID);
1044
- } else {
1045
- db().query(
1046
- "INSERT OR REPLACE INTO session_state (session_id, force_min_layer, updated_at) VALUES (?, ?, ?)"
1047
- ).run(sessionID, layer, Date.now());
1048
- }
1053
+ const now = Date.now();
1054
+ db().query(
1055
+ "INSERT OR IGNORE INTO session_state (session_id, force_min_layer, updated_at) VALUES (?, 0, ?)"
1056
+ ).run(sessionID, now);
1057
+ db().query("UPDATE session_state SET force_min_layer = ?, updated_at = ? WHERE session_id = ?").run(layer, now, sessionID);
1049
1058
  }
1050
1059
  function saveSessionCosts(sessionID, costs) {
1051
1060
  db().query(
@@ -1226,6 +1235,14 @@ function saveSessionTracking(sessionID, state) {
1226
1235
  sets.push("last_bust_at = ?");
1227
1236
  vals.push(state.lastBustAt);
1228
1237
  }
1238
+ if (state.parentSessionId !== void 0) {
1239
+ sets.push("parent_session_id = ?");
1240
+ vals.push(state.parentSessionId);
1241
+ }
1242
+ if (state.isSubagent !== void 0) {
1243
+ sets.push("is_subagent = ?");
1244
+ vals.push(state.isSubagent ? 1 : 0);
1245
+ }
1229
1246
  db().query(
1230
1247
  "UPDATE session_state SET " + sets.join(", ") + " WHERE session_id = ?"
1231
1248
  ).run(...vals, sessionID);
@@ -1238,7 +1255,8 @@ function loadSessionTracking(sessionID) {
1238
1255
  fingerprint, header_session_id, header_name,
1239
1256
  resolved_conversation_ttl, warmup_state,
1240
1257
  dynamic_context_cap, bust_rate_ema, inter_bust_interval_ema,
1241
- last_layer, last_known_input, last_turn_at, last_bust_at
1258
+ last_layer, last_known_input, last_turn_at, last_bust_at,
1259
+ parent_session_id, is_subagent
1242
1260
  FROM session_state WHERE session_id = ?`
1243
1261
  ).get(sessionID);
1244
1262
  if (!row) return null;
@@ -1262,7 +1280,9 @@ function loadSessionTracking(sessionID) {
1262
1280
  lastLayer: row.last_layer,
1263
1281
  lastKnownInput: row.last_known_input,
1264
1282
  lastTurnAt: row.last_turn_at,
1265
- lastBustAt: row.last_bust_at
1283
+ lastBustAt: row.last_bust_at,
1284
+ parentSessionId: row.parent_session_id,
1285
+ isSubagent: row.is_subagent === 1
1266
1286
  };
1267
1287
  }
1268
1288
  function loadHeaderSessionIndex() {
@@ -1277,6 +1297,18 @@ function loadHeaderSessionIndex() {
1277
1297
  headerName: row.header_name
1278
1298
  }));
1279
1299
  }
1300
+ function loadParentChildMap() {
1301
+ const rows = db().query(
1302
+ `SELECT session_id, parent_session_id
1303
+ FROM session_state
1304
+ WHERE parent_session_id IS NOT NULL`
1305
+ ).all();
1306
+ const map5 = /* @__PURE__ */ new Map();
1307
+ for (const row of rows) {
1308
+ map5.set(row.session_id, row.parent_session_id);
1309
+ }
1310
+ return map5;
1311
+ }
1280
1312
  function getKV(key) {
1281
1313
  const row = db().query("SELECT value FROM kv_meta WHERE key = ?").get(key);
1282
1314
  return row?.value ?? null;
@@ -12245,7 +12277,9 @@ var CURATOR_SYSTEM = `You are a long-term memory curator. Your job is to extract
12245
12277
  Focus ONLY on knowledge that helps a coding agent work effectively on THIS codebase:
12246
12278
  - Architectural decisions and their rationale (why something was built a certain way)
12247
12279
  - Non-obvious implementation patterns and conventions specific to the project
12248
- - Recurring gotchas, constraints, or traps in the codebase
12280
+ - Recurring gotchas, constraints, or traps in the codebase \u2014 always include WHY the
12281
+ wrong approach seems right, not just the trap and fix. Without this, a future session
12282
+ will re-propose the broken approach because it looks like a reasonable improvement.
12249
12283
  - Environment/tooling setup details that affect development
12250
12284
  - Important relationships between components that aren't obvious from reading the code
12251
12285
  - User preferences and working style specific to how they use this project
@@ -12264,10 +12298,19 @@ Do NOT extract:
12264
12298
  - Knowledge about unrelated projects or repositories unless explicitly cross-project
12265
12299
  - Restatements of what the code obviously does (e.g. "the auth module handles authentication")
12266
12300
 
12301
+ INCLUDE THE "WHY" \u2014 decisions and gotchas without rationale get undone:
12302
+ - Every "decision" MUST include the rejected alternative and why it was rejected.
12303
+ Format: "Chose X over Y because Z." Without the rejected option, a future session
12304
+ will re-propose Y because it looks like a reasonable improvement.
12305
+ - Every "gotcha" MUST explain why the wrong approach seems correct, not just the trap
12306
+ and its fix. Format: "Trap: X looks right because [reason]. Fix: Y, because [reason]."
12307
+ - Any standard or rule without its rationale is vulnerable to being optimized away by
12308
+ a session that doesn't know what problem it was solving.
12309
+
12267
12310
  BREVITY IS CRITICAL \u2014 each entry must be concise:
12268
12311
  - content MUST be under 150 words (~600 characters). Capture ONE specific actionable
12269
12312
  insight in 2-3 sentences. Prefer terse technical language.
12270
- - Each "gotcha": one specific trap + its fix in 1-2 sentences
12313
+ - Each "gotcha": one specific trap + WHY it looks right + its fix in 2-3 sentences
12271
12314
  - Each "architecture": one design decision and its key constraint
12272
12315
  - Focus on the actionable insight, not the full story behind it
12273
12316
  - If a pattern requires more detail, split into multiple focused entries (each under 150 words)
@@ -12293,6 +12336,20 @@ crossProject flag:
12293
12336
  - Default is true \u2014 most useful knowledge is worth sharing across projects
12294
12337
  - Set crossProject to false for things that are meaningless outside this specific repo (e.g. a config path, a project-local naming convention that conflicts with your usual style)
12295
12338
 
12339
+ Confidence values (0.0\u20131.0) \u2014 determines injection priority when budget is tight:
12340
+ - 1.0: Unconditional directive \u2014 user used "NEVER", "ALWAYS", "from now on", or similarly
12341
+ absolute language. These must always be respected regardless of context.
12342
+ - 0.9: Strong preference \u2014 explicit user preference ("I prefer", "I want", "make sure to",
12343
+ "don't forget to"). Clear intent but not absolute.
12344
+ - 0.8: Moderate preference \u2014 inferred from repeated user behavior or gentle correction across
12345
+ sessions. Not explicitly stated as a rule.
12346
+ - 0.6: Mild/contextual preference \u2014 may not apply universally. Observed once or context-dependent.
12347
+ - For non-preference categories (gotcha, pattern, architecture, decision), confidence reflects
12348
+ how well-established the knowledge is: 1.0 = verified/confirmed, 0.8 = high confidence,
12349
+ 0.6 = probable but unverified.
12350
+ - Default to 1.0 for preferences with strong directive language, 0.8 for other preferences.
12351
+ - Always set confidence on create ops \u2014 it determines injection priority.
12352
+
12296
12353
  Produce a JSON array of operations:
12297
12354
  [
12298
12355
  {
@@ -12301,7 +12358,8 @@ Produce a JSON array of operations:
12301
12358
  "title": "Short descriptive title",
12302
12359
  "content": "Concise knowledge entry \u2014 under 150 words",
12303
12360
  "scope": "project" | "global",
12304
- "crossProject": true
12361
+ "crossProject": true,
12362
+ "confidence": 1.0
12305
12363
  },
12306
12364
  {
12307
12365
  "op": "update",
@@ -12339,7 +12397,8 @@ IMPORTANT:
12339
12397
  4. Only create a new entry for genuinely distinct knowledge with no existing home.
12340
12398
  5. Keep all entries under 150 words. If an existing entry is too long, use an update op to trim it.
12341
12399
  6. Pay special attention to user instructions ("always do X", "never do Y", "make sure to X").
12342
- These are strong signals for "preference" entries with high confidence.`;
12400
+ These are strong signals for "preference" entries with high confidence (1.0 for absolute
12401
+ directives like "never"/"always", 0.9 for explicit preferences like "I prefer").`;
12343
12402
  }
12344
12403
  var CONSOLIDATION_SYSTEM = `You are a long-term memory curator performing a consolidation pass. The knowledge base has grown too large and needs to be trimmed.
12345
12404
 
@@ -26617,8 +26676,10 @@ var LoreConfig = external_exports.object({
26617
26676
  distilled: external_exports.number().min(0.05).max(0.5).default(0.25),
26618
26677
  raw: external_exports.number().min(0.1).max(0.7).default(0.4),
26619
26678
  output: external_exports.number().min(0.1).max(0.5).default(0.25),
26620
- /** Max fraction of usable context reserved for LTM system-prompt injection. Default: 0.05 (5%). */
26679
+ /** Max fraction of usable context reserved for context-bound LTM system-prompt injection. Default: 0.05 (5%). */
26621
26680
  ltm: external_exports.number().min(0.02).max(0.3).default(0.05),
26681
+ /** Fraction of usable context for stable LTM (preferences). Independent of `ltm`. Default: 0.02 (2%). */
26682
+ preferenceLtm: external_exports.number().min(0.01).max(0.1).default(0.02),
26622
26683
  /** Per-turn cache-read cost target in dollars. Controls when layer 0 (full
26623
26684
  * passthrough) escalates to layer 1 (compressed). The cap is derived as:
26624
26685
  * maxLayer0Tokens = max(target / model.cost.cache.read, 40K).
@@ -26633,7 +26694,7 @@ var LoreConfig = external_exports.object({
26633
26694
  targetBustCost: external_exports.number().min(0).default(1).optional(),
26634
26695
  /** @deprecated Ignored. Tier-based bust-vs-continue replaces static cap. */
26635
26696
  maxContextTokens: external_exports.number().min(0).optional()
26636
- }).default({ distilled: 0.25, raw: 0.4, output: 0.25, ltm: 0.05, targetCacheReadCostPerTurn: 0.1 }),
26697
+ }).default({ distilled: 0.25, raw: 0.4, output: 0.25, ltm: 0.05, preferenceLtm: 0.02, targetCacheReadCostPerTurn: 0.1 }),
26637
26698
  /**
26638
26699
  * Cold-cache idle-resume handling.
26639
26700
  *
@@ -27779,6 +27840,7 @@ __export(ltm_exports, {
27779
27840
  recordDedupFeedback: () => recordDedupFeedback,
27780
27841
  recordDedupResultFeedback: () => recordDedupResultFeedback,
27781
27842
  remove: () => remove,
27843
+ rerankPreferences: () => rerankPreferences,
27782
27844
  resolveRef: () => resolveRef2,
27783
27845
  saveCalibratedThreshold: () => saveCalibratedThreshold,
27784
27846
  search: () => search3,
@@ -28363,28 +28425,33 @@ function create(input) {
28363
28425
  ).get(pid, input.title) : db().query(
28364
28426
  "SELECT id FROM knowledge WHERE project_id IS NULL AND LOWER(title) = LOWER(?) AND confidence > 0 LIMIT 1"
28365
28427
  ).get(input.title);
28428
+ const dedupUpdate = {
28429
+ content: input.content,
28430
+ ...input.confidence != null ? { confidence: input.confidence } : {}
28431
+ };
28366
28432
  if (existing) {
28367
- update(existing.id, { content: input.content });
28433
+ update(existing.id, dedupUpdate);
28368
28434
  return existing.id;
28369
28435
  }
28370
28436
  const crossExisting = db().query(
28371
28437
  "SELECT id FROM knowledge WHERE cross_project = 1 AND LOWER(title) = LOWER(?) AND confidence > 0 LIMIT 1"
28372
28438
  ).get(input.title);
28373
28439
  if (crossExisting) {
28374
- update(crossExisting.id, { content: input.content });
28440
+ update(crossExisting.id, dedupUpdate);
28375
28441
  return crossExisting.id;
28376
28442
  }
28377
28443
  const fuzzyMatch = findFuzzyDuplicate({ title: input.title, projectId: pid });
28378
28444
  if (fuzzyMatch) {
28379
- update(fuzzyMatch.id, { content: input.content });
28445
+ update(fuzzyMatch.id, dedupUpdate);
28380
28446
  return fuzzyMatch.id;
28381
28447
  }
28382
28448
  }
28383
28449
  const id = input.id ?? uuidv72();
28384
28450
  const now = Date.now();
28451
+ const confidence = input.confidence != null ? Math.max(0, Math.min(1, input.confidence)) : 1;
28385
28452
  db().query(
28386
28453
  `INSERT INTO knowledge (id, project_id, category, title, content, source_session, cross_project, confidence, created_at, updated_at)
28387
- VALUES (?, ?, ?, ?, ?, ?, ?, 1.0, ?, ?)`
28454
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
28388
28455
  ).run(
28389
28456
  id,
28390
28457
  pid,
@@ -28393,6 +28460,7 @@ function create(input) {
28393
28460
  input.content,
28394
28461
  input.session ?? null,
28395
28462
  crossProject2 ? 1 : 0,
28463
+ confidence,
28396
28464
  now,
28397
28465
  now
28398
28466
  );
@@ -28543,6 +28611,24 @@ async function forSession(projectPath2, sessionID, maxTokens, options) {
28543
28611
  ORDER BY confidence DESC, updated_at DESC`
28544
28612
  ).all(...categoryParams);
28545
28613
  if (!crossEntries.length && !projectEntries.length) return [];
28614
+ const isPreferenceOnly = categoryFilter?.length === 1 && categoryFilter[0] === "preference";
28615
+ if (isPreferenceOnly) {
28616
+ const allPrefs = [...projectEntries, ...crossEntries];
28617
+ allPrefs.sort(
28618
+ (a, b) => a.confidence !== b.confidence ? b.confidence - a.confidence : b.updated_at - a.updated_at
28619
+ );
28620
+ const HEADER_OVERHEAD_TOKENS2 = 15;
28621
+ let used2 = HEADER_OVERHEAD_TOKENS2;
28622
+ const result2 = [];
28623
+ for (const entry of allPrefs) {
28624
+ if (used2 >= maxTokens) break;
28625
+ const cost = estimateTokens3(entry.title + entry.content) + 10;
28626
+ if (used2 + cost > maxTokens) continue;
28627
+ result2.push(entry);
28628
+ used2 += cost;
28629
+ }
28630
+ return result2;
28631
+ }
28546
28632
  let sessionContext = "";
28547
28633
  if (sessionID) {
28548
28634
  const distRow = db().query(
@@ -28615,10 +28701,24 @@ async function forSession(projectPath2, sessionID, maxTokens, options) {
28615
28701
  const allScored = [...scoredProject, ...scoredCross];
28616
28702
  allScored.sort((a, b) => b.score - a.score);
28617
28703
  const HEADER_OVERHEAD_TOKENS = 15;
28704
+ const ARCH_BUDGET_FRACTION = 0.2;
28618
28705
  let used = HEADER_OVERHEAD_TOKENS;
28619
28706
  const result = [];
28707
+ const packedIds = /* @__PURE__ */ new Set();
28708
+ const archBudget = Math.floor(maxTokens * ARCH_BUDGET_FRACTION);
28709
+ const archEntries = allScored.filter((s) => s.entry.category === "architecture");
28710
+ archEntries.sort((a, b) => b.score - a.score);
28711
+ for (const { entry } of archEntries) {
28712
+ if (used >= archBudget + HEADER_OVERHEAD_TOKENS) break;
28713
+ const cost = estimateTokens3(entry.title + entry.content) + 10;
28714
+ if (used + cost > maxTokens) continue;
28715
+ result.push(entry);
28716
+ packedIds.add(entry.id);
28717
+ used += cost;
28718
+ }
28620
28719
  for (const { entry } of allScored) {
28621
28720
  if (used >= maxTokens) break;
28721
+ if (packedIds.has(entry.id)) continue;
28622
28722
  const cost = estimateTokens3(entry.title + entry.content) + 10;
28623
28723
  if (used + cost > maxTokens) continue;
28624
28724
  result.push(entry);
@@ -28680,6 +28780,28 @@ function crossProject() {
28680
28780
  ORDER BY confidence DESC, updated_at DESC`
28681
28781
  ).all();
28682
28782
  }
28783
+ function rerankPreferences() {
28784
+ const prefs = db().query(`SELECT ${KNOWLEDGE_COLS} FROM knowledge WHERE category = 'preference' AND confidence = 1.0`).all();
28785
+ const STRONG_DIRECTIVE_RE = /\b(never|always|must not|must)\b/i;
28786
+ const EXPLICIT_PREF_RE = /\b(I (?:want|need|prefer|expect)|make sure to|don'?t forget)\b/i;
28787
+ let updated = 0;
28788
+ for (const entry of prefs) {
28789
+ const text4 = entry.title + " " + entry.content;
28790
+ let newConfidence;
28791
+ if (STRONG_DIRECTIVE_RE.test(text4)) {
28792
+ newConfidence = 1;
28793
+ } else if (EXPLICIT_PREF_RE.test(text4)) {
28794
+ newConfidence = 0.9;
28795
+ } else {
28796
+ newConfidence = 0.8;
28797
+ }
28798
+ if (newConfidence !== entry.confidence) {
28799
+ update(entry.id, { confidence: newConfidence });
28800
+ updated++;
28801
+ }
28802
+ }
28803
+ return updated;
28804
+ }
28683
28805
  function searchLike2(input) {
28684
28806
  const terms = input.query.toLowerCase().split(/\s+/).filter((t2) => t2.length > 2);
28685
28807
  if (!terms.length) return [];
@@ -29972,13 +30094,20 @@ function getTier(tokens) {
29972
30094
  function recordCacheUsage(cacheWrite, cacheRead, inputTokens, sessionID) {
29973
30095
  if (!sessionID) return;
29974
30096
  const state = getSessionState(sessionID);
29975
- const total = inputTokens > 0 ? inputTokens : cacheWrite + cacheRead;
30097
+ const total = cacheWrite + cacheRead + inputTokens;
29976
30098
  if (total > 0) {
29977
- if (cacheWrite / total > 0.5) {
30099
+ const bustRatio = cacheWrite / total;
30100
+ const prev = state.consecutiveBusts;
30101
+ if (bustRatio > 0.5) {
29978
30102
  state.consecutiveBusts++;
29979
30103
  } else {
29980
30104
  state.consecutiveBusts = 0;
29981
30105
  }
30106
+ if (state.consecutiveBusts !== prev) {
30107
+ info(
30108
+ `bust-tracker: session=${sessionID.slice(0, 16)} ratio=${bustRatio.toFixed(3)} (write=${cacheWrite} read=${cacheRead} uncached=${inputTokens}) busts=${prev}\u2192${state.consecutiveBusts}`
30109
+ );
30110
+ }
29982
30111
  }
29983
30112
  }
29984
30113
  var FIRST_TURN_OVERHEAD = 15e3;
@@ -30015,7 +30144,6 @@ function getSessionState(sessionID) {
30015
30144
  state.lastLayer = persisted.lastLayer;
30016
30145
  state.lastKnownInput = persisted.lastKnownInput;
30017
30146
  state.lastTurnAt = persisted.lastTurnAt;
30018
- state.consecutiveBusts = persisted.dynamicContextCap;
30019
30147
  }
30020
30148
  sessionStates.set(sessionID, state);
30021
30149
  }
@@ -30074,6 +30202,7 @@ function getLtmBudget(ltmFraction) {
30074
30202
  const usable = Math.max(0, contextLimit - outputReserved - overhead);
30075
30203
  return Math.floor(usable * ltmFraction);
30076
30204
  }
30205
+ var getPreferenceLtmBudget = getLtmBudget;
30077
30206
  function calibrate(actualInput, sessionID, messageCount) {
30078
30207
  const messageEstimate = sessionID ? getSessionState(sessionID).lastTransformEstimate : 0;
30079
30208
  if (messageEstimate > 0 || actualInput === 0) {
@@ -31089,6 +31218,7 @@ function sliceTokens(messages, start, end) {
31089
31218
  function splitSegments(messages, maxTokens) {
31090
31219
  const totalTokens = messages.reduce((s, m) => s + m.tokens, 0);
31091
31220
  if (totalTokens <= maxTokens) return [messages];
31221
+ if (messages.length <= 1) return [messages];
31092
31222
  const splitIdx = findSplitIndex(messages, maxTokens);
31093
31223
  const left = messages.slice(0, splitIdx);
31094
31224
  const right = messages.slice(splitIdx);
@@ -31727,7 +31857,8 @@ function applyOps(ops, input) {
31727
31857
  content: content3,
31728
31858
  session: input.sessionID,
31729
31859
  scope: op.scope,
31730
- crossProject: op.crossProject ?? true
31860
+ crossProject: op.crossProject ?? true,
31861
+ confidence: op.confidence
31731
31862
  });
31732
31863
  idsToSync.push(id);
31733
31864
  created++;
@@ -33968,6 +34099,7 @@ export {
33968
34099
  getLtmBudget,
33969
34100
  getLtmTokens,
33970
34101
  getMeta,
34102
+ getPreferenceLtmBudget,
33971
34103
  getTier,
33972
34104
  h,
33973
34105
  importFromFile,
@@ -33988,6 +34120,7 @@ export {
33988
34120
  loadAllSessionCosts,
33989
34121
  loadForceMinLayer,
33990
34122
  loadHeaderSessionIndex,
34123
+ loadParentChildMap,
33991
34124
  loadSessionCosts,
33992
34125
  loadSessionTracking,
33993
34126
  log_exports as log,