lemura 1.2.0 → 1.4.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 (39) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +12 -11
  3. package/dist/adapters/index.d.mts +1 -1
  4. package/dist/adapters/index.d.ts +1 -1
  5. package/dist/adapters/index.js +10 -2
  6. package/dist/adapters/index.js.map +1 -1
  7. package/dist/adapters/index.mjs +10 -2
  8. package/dist/adapters/index.mjs.map +1 -1
  9. package/dist/{storage-CG3nTa6o.d.mts → adapters-BhTAnrOM.d.mts} +79 -46
  10. package/dist/{storage-DBt_q0wO.d.ts → adapters-CVcfWf85.d.ts} +79 -46
  11. package/dist/{agent-DxRd93wl.d.ts → agent-38El9_yp.d.ts} +35 -4
  12. package/dist/{agent-D6uhF-CZ.d.mts → agent-CJvmcAbT.d.mts} +35 -4
  13. package/dist/context/index.d.mts +71 -7
  14. package/dist/context/index.d.ts +71 -7
  15. package/dist/context/index.js +75 -4
  16. package/dist/context/index.js.map +1 -1
  17. package/dist/context/index.mjs +74 -5
  18. package/dist/context/index.mjs.map +1 -1
  19. package/dist/index.d.mts +339 -63
  20. package/dist/index.d.ts +339 -63
  21. package/dist/index.js +1018 -132
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +1017 -133
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/skills/index.d.mts +92 -3
  26. package/dist/skills/index.d.ts +92 -3
  27. package/dist/skills/index.js +138 -8
  28. package/dist/skills/index.js.map +1 -1
  29. package/dist/skills/index.mjs +138 -8
  30. package/dist/skills/index.mjs.map +1 -1
  31. package/dist/skills-Y6D7zSSw.d.mts +66 -0
  32. package/dist/skills-Y6D7zSSw.d.ts +66 -0
  33. package/dist/tools/index.d.mts +3 -3
  34. package/dist/tools/index.d.ts +3 -3
  35. package/dist/types/index.d.mts +3 -3
  36. package/dist/types/index.d.ts +3 -3
  37. package/package.json +6 -1
  38. package/dist/skills-wc8S-OvC.d.mts +0 -14
  39. package/dist/skills-wc8S-OvC.d.ts +0 -14
@@ -49,6 +49,8 @@ var ContextManager = class {
49
49
  */
50
50
  async prepare(context, safetyMargin = 0.95) {
51
51
  let currentCtx = { ...context, turns: [...context.turns] };
52
+ const systemTokens = currentCtx.systemPrompt ? Math.ceil(currentCtx.systemPrompt.length / 4) : 0;
53
+ currentCtx.tokenCount = currentCtx.turns.reduce((sum, t) => sum + t.tokenCount, 0) + systemTokens;
52
54
  currentCtx.maxTokens * safetyMargin;
53
55
  for (const strategy of this.strategies) {
54
56
  if (strategy.shouldApply(currentCtx)) {
@@ -69,11 +71,13 @@ var SandwichCompressionStrategy = class {
69
71
  constructor(adapter, config) {
70
72
  this.adapter = adapter;
71
73
  this.config = config;
74
+ this.priority = config.priority ?? 20;
72
75
  }
73
76
  name = "sandwich_compression";
74
- priority = 20;
77
+ priority;
75
78
  shouldApply(ctx) {
76
- return ctx.tokenCount >= ctx.maxTokens * this.config.triggerThreshold && ctx.turns.length > this.config.preserveFirst + this.config.preserveLast;
79
+ const threshold = this.config.triggerThreshold ?? 0.8;
80
+ return ctx.tokenCount >= ctx.maxTokens * threshold && ctx.turns.length > this.config.preserveFirst + this.config.preserveLast;
77
81
  }
78
82
  async apply(ctx) {
79
83
  const { preserveFirst, preserveLast } = this.config;
@@ -87,7 +91,8 @@ var SandwichCompressionStrategy = class {
87
91
  role: "user",
88
92
  content: `Summarize the following conversation history briefly:
89
93
  ${middleText}`
90
- }]
94
+ }],
95
+ ...this.config.summaryMaxTokens ? { maxTokens: this.config.summaryMaxTokens } : {}
91
96
  });
92
97
  const summaryStr = summaryResponse.content;
93
98
  const newCompressionSummary = ctx.compressionSummary ? `${ctx.compressionSummary}
@@ -155,9 +160,10 @@ var HistoryCompressionStrategy = class {
155
160
  constructor(adapter, config) {
156
161
  this.adapter = adapter;
157
162
  this.config = config;
163
+ this.priority = config.priority ?? 30;
158
164
  }
159
165
  name = "history_compression";
160
- priority = 30;
166
+ priority;
161
167
  shouldApply(ctx) {
162
168
  const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;
163
169
  const uncompressedTurns = ctx.turns.filter((t) => t.role !== "system" && !t.compressed);
@@ -189,6 +195,52 @@ ${summaryStr}` : summaryStr;
189
195
  };
190
196
  }
191
197
  };
198
+
199
+ // src/context/SummaryInjectionStrategy.ts
200
+ var SummaryInjectionStrategy = class {
201
+ name = "summary_injection";
202
+ priority;
203
+ label;
204
+ constructor(config = {}) {
205
+ this.priority = config.priority ?? 1;
206
+ this.label = config.label ?? "Earlier conversation summary";
207
+ }
208
+ shouldApply(ctx) {
209
+ return !!ctx.compressionSummary && ctx.compressionSummary.trim().length > 0;
210
+ }
211
+ async apply(ctx) {
212
+ const summaryContent = `[${this.label}]
213
+ ${ctx.compressionSummary}`;
214
+ const summaryTokenCount = Math.ceil(summaryContent.length / 4);
215
+ const existingIndex = ctx.turns.findIndex((t) => t.compressed && t.role === "system" && t.turnIndex === -1);
216
+ let newTurns;
217
+ if (existingIndex !== -1) {
218
+ newTurns = ctx.turns.map((t, i) => {
219
+ if (i !== existingIndex) return t;
220
+ return {
221
+ ...t,
222
+ content: summaryContent,
223
+ tokenCount: summaryTokenCount
224
+ };
225
+ });
226
+ } else {
227
+ const summaryTurn = {
228
+ role: "system",
229
+ content: summaryContent,
230
+ tokenCount: summaryTokenCount,
231
+ turnIndex: -1,
232
+ compressed: true
233
+ };
234
+ newTurns = [summaryTurn, ...ctx.turns];
235
+ }
236
+ const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0);
237
+ return {
238
+ ...ctx,
239
+ turns: newTurns,
240
+ tokenCount: newTokenCount
241
+ };
242
+ }
243
+ };
192
244
  var ShortTermMemoryRegistry = class {
193
245
  storage;
194
246
  maxTextTokens;
@@ -311,11 +363,30 @@ var InMemoryStorageAdapter = class {
311
363
  }
312
364
  };
313
365
 
366
+ // src/context/InMemoryScratchpadAdapter.ts
367
+ var InMemoryScratchpadAdapter = class {
368
+ store = /* @__PURE__ */ new Map();
369
+ async read(sessionId) {
370
+ return this.store.get(sessionId);
371
+ }
372
+ async write(sessionId, content) {
373
+ this.store.set(sessionId, content);
374
+ }
375
+ async clear(sessionId) {
376
+ this.store.delete(sessionId);
377
+ }
378
+ async healthCheck() {
379
+ return true;
380
+ }
381
+ };
382
+
314
383
  exports.ContextManager = ContextManager;
315
384
  exports.HistoryCompressionStrategy = HistoryCompressionStrategy;
385
+ exports.InMemoryScratchpadAdapter = InMemoryScratchpadAdapter;
316
386
  exports.InMemoryStorageAdapter = InMemoryStorageAdapter;
317
387
  exports.SandwichCompressionStrategy = SandwichCompressionStrategy;
318
388
  exports.ScratchpadStrategy = ScratchpadStrategy;
319
389
  exports.ShortTermMemoryRegistry = ShortTermMemoryRegistry;
390
+ exports.SummaryInjectionStrategy = SummaryInjectionStrategy;
320
391
  //# sourceMappingURL=index.js.map
321
392
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/errors.ts","../../src/context/ContextManager.ts","../../src/context/SandwichCompressionStrategy.ts","../../src/context/HistoryCompressionStrategy.ts","../../src/context/ShortTermMemoryRegistry.ts","../../src/context/InMemoryStorageAdapter.ts"],"names":["randomUUID"],"mappings":";;;;;AAMO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,YACI,OAAA,EACgB,IAAA,EACA,OAAA,EACA,KAAA,GAAkB,EAAC,EACrC;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EACpD;AACJ,CAAA;AAGO,IAAM,0BAAA,GAAN,cAAyC,WAAA,CAAY;AAAA,EACxD,YAAY,OAAA,EAAiB;AACzB,IAAA,KAAA,CAAM,SAAS,kBAAkB,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AAAA,EAChB;AACJ,CAAA;;;ACzBO,IAAM,iBAAN,MAAqB;AAAA,EAChB,aAAiC,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1C,iBAAiB,QAAA,EAAkC;AAC/C,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,QAAQ,CAAA;AAC7B,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,CAAQ,OAAA,EAAwB,YAAA,GAAe,IAAA,EAA8B;AAC/E,IAAA,IAAI,UAAA,GAAa,EAAE,GAAG,OAAA,EAAS,OAAO,CAAC,GAAG,OAAA,CAAQ,KAAK,CAAA,EAAE;AACzD,IAAyB,WAAW,SAAA,GAAY;AAEhD,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,UAAA,EAAY;AAIpC,MAAA,IAAI,QAAA,CAAS,WAAA,CAAY,UAAU,CAAA,EAAG;AAClC,QAAA,UAAA,GAAa,MAAM,QAAA,CAAS,KAAA,CAAM,UAAU,CAAA;AAAA,MAChD;AAAA,IACJ;AAEA,IAAA,IAAI,UAAA,CAAW,UAAA,GAAa,UAAA,CAAW,SAAA,EAAW;AAC9C,MAAA,MAAM,IAAI,0BAAA;AAAA,QACN,CAAA,oBAAA,EAAuB,UAAA,CAAW,UAAU,CAAA,UAAA,EAAa,WAAW,SAAS,CAAA;AAAA,OACjF;AAAA,IACJ;AAEA,IAAA,OAAO,UAAA;AAAA,EACX;AACJ;;;ACrCO,IAAM,8BAAN,MAA8D;AAAA,EAIjE,WAAA,CACY,SACA,MAAA,EACV;AAFU,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACR;AAAA,EANK,IAAA,GAAO,sBAAA;AAAA,EACP,QAAA,GAAW,EAAA;AAAA,EAOpB,YAAY,GAAA,EAA6B;AACrC,IAAA,OACI,GAAA,CAAI,UAAA,IAAc,GAAA,CAAI,SAAA,GAAY,KAAK,MAAA,CAAO,gBAAA,IAC9C,GAAA,CAAI,KAAA,CAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,aAAA,GAAgB,KAAK,MAAA,CAAO,YAAA;AAAA,EAEnE;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AACpD,IAAA,MAAM,EAAE,aAAA,EAAe,YAAA,EAAa,GAAI,IAAA,CAAK,MAAA;AAE7C,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAG,aAAa,CAAA;AAC7C,IAAA,MAAM,OAAO,GAAA,CAAI,KAAA,CAAM,MAAM,GAAA,CAAI,KAAA,CAAM,SAAS,YAAY,CAAA;AAC5D,IAAA,MAAM,MAAA,GAAS,IAAI,KAAA,CAAM,KAAA,CAAM,eAAe,GAAA,CAAI,KAAA,CAAM,SAAS,YAAY,CAAA;AAE7E,IAAA,MAAM,aAAa,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,EAAE,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAEvF,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAA0D,UAAU,CAAA;AAAA,OAChF;AAAA,KACJ,CAAA;AAED,IAAA,MAAM,aAAa,eAAA,CAAgB,OAAA;AAEnC,IAAA,MAAM,qBAAA,GAAwB,GAAA,CAAI,kBAAA,GAC5B,CAAA,EAAG,IAAI,kBAAkB;AAAA,EAAK,UAAU,CAAA,CAAA,GACxC,UAAA;AAEN,IAAA,MAAM,WAAA,GAAoB;AAAA,MACtB,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,CAAA;AAAA,EAAiC,qBAAqB,CAAA,CAAA;AAAA,MAC/D,UAAA,EAAY,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,qBAAqB,CAAA;AAAA,MAC7D,SAAA,EAAW,EAAA;AAAA,MACX,UAAA,EAAY;AAAA,KAChB;AAEA,IAAA,MAAM,WAAW,CAAC,GAAG,IAAA,EAAM,WAAA,EAAa,GAAG,IAAI,CAAA;AAC/C,IAAA,MAAM,aAAA,GAAgB,SAAS,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,EAAE,UAAA,EAAY,CAAC,IACnE,IAAA,CAAK,OAAA,CAAQ,eAAe,GAAA,CAAI,YAAY,IAC5C,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA;AAE9C,IAAA,OAAO;AAAA,MACH,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,QAAA;AAAA,MACP,UAAA,EAAY,aAAA;AAAA,MACZ,kBAAA,EAAoB;AAAA,KACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,kBAAA,CAAmB,OAAA,EAAiB,YAAA,GAAuB,6BAAA,EAI9D;AAGC,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,OAAO,CAAA,GAAI,GAAI,CAAC,CAAA;AAC1F,IAAA,MAAM,QAAA,GAAW,uBAAuB,eAAe,CAAA,iBAAA,CAAA;AAKvD,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAAyB,YAAY;;AAAA;AAAA,EAAwB,OAAO;;AAAA;AAAA,EAA6B,YAAY,CAAA;AAAA,OACzH;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,YAAY,eAAA,CAAgB,OAAA;AAIlC,IAAA,MAAM,SAAA,GAAY,CAAA,+FAAA,CAAA;AAElB,IAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAU;AAAA,EAC5C;AACJ;;;ACrGO,IAAM,qBAAN,MAAqD;AAAA,EAC/C,IAAA,GAAO,qBAAA;AAAA,EACP,QAAA,GAAW,EAAA;AAAA,EAEpB,YAAY,GAAA,EAA6B;AAErC,IAAA,OAAO,GAAA,CAAI,WAAW,MAAA,GAAS,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AAEpD,IAAA,OAAO,GAAA;AAAA,EACX;AACJ;AAUO,IAAM,6BAAN,MAA6D;AAAA,EAIhE,WAAA,CACY,SACA,MAAA,EACV;AAFU,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACR;AAAA,EANK,IAAA,GAAO,qBAAA;AAAA,EACP,QAAA,GAAW,EAAA;AAAA,EAOpB,YAAY,GAAA,EAA6B;AACrC,IAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,gBAAA;AAGlD,IAAA,MAAM,iBAAA,GAAoB,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,QAAA,IAAY,CAAC,CAAA,CAAE,UAAU,CAAA;AACpF,IAAA,OAAO,IAAI,UAAA,IAAc,aAAA,IAAiB,iBAAA,CAAkB,MAAA,GAAS,KAAK,MAAA,CAAO,UAAA;AAAA,EACrF;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AAEpD,IAAA,MAAM,mBAAA,GAAsB,GAAA,CAAI,KAAA,CAC3B,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,EAAE,CAAE,CAAA,CACxB,MAAA,CAAO,CAAC,EAAE,CAAA,EAAE,KAAM,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAC,CAAA,CAAE,UAAU,CAAA,CACtD,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA;AAEpC,IAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,CAAC,CAAA;AACpD,IAAA,MAAM,aAAa,WAAA,CAAY,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,EAAE,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAE5F,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAAoD,UAAU,CAAA;AAAA,OAC1E;AAAA,KACJ,CAAA;AAED,IAAA,MAAM,aAAa,eAAA,CAAgB,OAAA;AACnC,IAAA,MAAM,qBAAA,GAAwB,GAAA,CAAI,kBAAA,GAC5B,CAAA,EAAG,IAAI,kBAAkB;AAAA,EAAK,UAAU,CAAA,CAAA,GACxC,UAAA;AAGN,IAAA,MAAM,eAAA,GAAkB,IAAI,GAAA,CAAI,mBAAA,CAAoB,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,CAAC,CAAC,CAAA;AACjE,IAAA,MAAM,QAAA,GAAW,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAC,eAAA,CAAgB,GAAA,CAAI,CAAC,CAAC,CAAA;AAEnE,IAAA,MAAM,UAAA,GAAa,SAAS,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,EAAE,UAAA,EAAY,CAAC,IAChE,IAAA,CAAK,OAAA,CAAQ,eAAe,GAAA,CAAI,YAAY,IAC5C,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA;AAE9C,IAAA,OAAO;AAAA,MACH,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,QAAA;AAAA,MACP,UAAA,EAAY,UAAA;AAAA,MACZ,kBAAA,EAAoB;AAAA,KACxB;AAAA,EACJ;AACJ;AC/DO,IAAM,0BAAN,MAA8B;AAAA,EACzB,OAAA;AAAA,EACA,aAAA;AAAA,EAER,YAAY,MAAA,EAA2B;AACnC,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACtB,IAAA,IAAA,CAAK,aAAA,GAAgB,OAAO,aAAA,IAAiB,GAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAAA,CACF,OAAA,EACA,IAAA,EACA,UACA,cAAA,EACe;AACf,IAAA,IAAI,SAAS,MAAA,EAAQ;AACjB,MAAA,MAAM,UAAA,GAAa,cAAA,GAAiB,cAAA,CAAe,OAAO,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAClG,MAAA,IAAI,UAAA,GAAa,KAAK,aAAA,EAAe;AACjC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yCAAA,EAA4C,KAAK,aAAa,CAAA,YAAA,EAAe,UAAU,CAAA,CAAA,CAAG,CAAA;AAAA,MAC9G;AAAA,IACJ;AAEA,IAAA,MAAM,KAAKA,iBAAA,EAAW;AACtB,IAAA,MAAM,IAAA,GAAgB;AAAA,MAClB,EAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAI,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,KAAa;AAAC,KACjD;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,IAAI,CAAA;AAC/B,IAAA,OAAO,QAAQ,EAAE,CAAA,CAAA,CAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CAAO,EAAA,EAAY,OAAA,EAA+E;AACpG,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,EAAE,CAAA;AACtC,IAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,EAAE,CAAA,CAAE,CAAA;AAEjE,IAAA,MAAM,WAAA,GAAuB;AAAA,MACzB,GAAG,IAAA;AAAA,MACH,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,MACpE,GAAI,OAAA,CAAQ,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,EAAE,GAAG,IAAA,CAAK,UAAU,GAAG,OAAA,CAAQ,QAAA,EAAS,KAAM;AAAC,KACpG;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,WAAW,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,GAAA,EAA2C;AACtD,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,gBAAgB,CAAA;AACxC,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,CAAM,CAAC,GAAG,OAAO,MAAA;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,EAAA,EAA2B;AACpC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAA;AAAA,EAChC;AACJ;AC9FO,IAAM,yBAAN,MAAwD;AAAA,EACnD,KAAA,uBAAY,GAAA,EAAkE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtF,MAAM,IAAI,EAAA,EAAsC;AAC5C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,EAAG,OAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,EAAA,EAAuF;AACjG,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,GAAA,CAAI,EAAA,EAAwB,OAAA,EAAc,QAAA,EAAqD;AACjG,IAAA,MAAM,UAAA,GAAa,MAAMA,iBAAAA,EAAW;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAA,EAAY,QAAA,KAAa,MAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAS,GAAI,EAAE,OAAA,EAAS,CAAA;AACvF,IAAA,OAAO,UAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,EAAA,EAA2B;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,EAAE,CAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,GAAgC;AAClC,IAAA,OAAO,IAAA;AAAA,EACX;AACJ","file":"index.js","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import { ContextWindow, IContextStrategy, LemuraContextOverflowError } from '../types/index.js';\n\n/**\n * Orchestrates a stack of IContextStrategy implementations to keep the\n * token count within the maxTokens limit.\n */\nexport class ContextManager {\n private strategies: IContextStrategy[] = [];\n\n /**\n * Registers a new compression or pre-turn strategy and sorts the stack by priority.\n *\n * @param strategy - The strategy implementation to register\n */\n registerStrategy(strategy: IContextStrategy): void {\n this.strategies.push(strategy);\n this.strategies.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Applies all registered strategies that return true for `shouldApply()`\n * until the context token count is safely below the maximum budget.\n *\n * @param context - The context window to prepare\n * @param safetyMargin - Modifier applied to maxTokens (default: 0.95 -> 95%)\n * @returns A new ContextWindow object potentially compressed\n * @throws {LemuraContextOverflowError} If the context is still over maxTokens after all strategies\n */\n async prepare(context: ContextWindow, safetyMargin = 0.95): Promise<ContextWindow> {\n let currentCtx = { ...context, turns: [...context.turns] };\n const targetTokenCount = currentCtx.maxTokens * safetyMargin;\n\n for (const strategy of this.strategies) {\n // If we are below the limit and it's not a pre-turn non-reducing strategy, skip it.\n // E.g., SummaryInjectionStrategy might still want to run.\n // But purely compression ones drop out early in our base architecture if they choose in `shouldApply`.\n if (strategy.shouldApply(currentCtx)) {\n currentCtx = await strategy.apply(currentCtx);\n }\n }\n\n if (currentCtx.tokenCount > currentCtx.maxTokens) {\n throw new LemuraContextOverflowError(\n `Context overflowed: ${currentCtx.tokenCount} tokens > ${currentCtx.maxTokens}`\n );\n }\n\n return currentCtx;\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\nexport interface SandwichCompressionConfig {\n preserveFirst: number;\n preserveLast: number;\n triggerThreshold: number; // e.g. 0.8\n}\n\n/**\n * Sandwich compression preserves the beginning and end of the conversation,\n * replacing the middle with a generated summary.\n */\nexport class SandwichCompressionStrategy implements IContextStrategy {\n readonly name = 'sandwich_compression';\n readonly priority = 20;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: SandwichCompressionConfig\n ) { }\n\n shouldApply(ctx: ContextWindow): boolean {\n return (\n ctx.tokenCount >= ctx.maxTokens * this.config.triggerThreshold &&\n ctx.turns.length > this.config.preserveFirst + this.config.preserveLast\n );\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const { preserveFirst, preserveLast } = this.config;\n\n const head = ctx.turns.slice(0, preserveFirst);\n const tail = ctx.turns.slice(ctx.turns.length - preserveLast);\n const middle = ctx.turns.slice(preserveFirst, ctx.turns.length - preserveLast);\n\n const middleText = middle.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the following conversation history briefly:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n const summaryTurn: Turn = {\n role: 'system',\n content: `[COMPRESSED HISTORY SUMMARY]\\n${newCompressionSummary}`,\n tokenCount: this.adapter.estimateTokens(newCompressionSummary),\n turnIndex: -1,\n compressed: true,\n };\n\n const newTurns = [...head, summaryTurn, ...tail];\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n\n /**\n * Applies sandwich compression specifically to a Short Term Memory item's content.\n * Implements a 3-layer pipeline: Pre-Layer (encoding), Core Layer (dense summary), Post-Layer (refinement cues).\n * \n * @param content - The heavy text content to compress\n * @param instructions - Guiding instructions for the core layer summary\n * @returns The three-layer sandwich result\n */\n async compressMemoryItem(content: string, instructions: string = 'Extract the key information'): Promise<{\n preLayer: string;\n coreLayer: string;\n postLayer: string;\n }> {\n // Pre-Layer: Chunking and initial encoding\n // Here we do a naive encoding representation to signify the pre-processed chunks\n const estimatedChunks = Math.max(1, Math.ceil(this.adapter.estimateTokens(content) / 2000));\n const preLayer = `[PRE-LAYER ENCODED: ${estimatedChunks} internal chunks]`;\n\n // Core Layer: Dense summary sandwich with instructions\n // We sandwich the content between the instructions to guide extraction\n // If content is extremely large, we might trim it here, but ideally the provider streaming handles it.\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `### INSTRUCTIONS ###\\n${instructions}\\n\\n### CONTENT ###\\n${content}\\n\\n### INSTRUCTIONS ###\\n${instructions}`\n }]\n });\n const coreLayer = summaryResponse.content;\n\n // Post-Layer: Decoding/Refinement hooks\n // Indicates that the LLM can use tools to drill down into specific chunks\n const postLayer = `[POST-LAYER DECODING: Use \\`refine_layer\\` or \\`read_chunk\\` tools to expand specific sections]`;\n\n return { preLayer, coreLayer, postLayer };\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\n/**\n * ScratchpadStrategy manages the thinking process separate from the turn history.\n * It is primarily a marker/pre-turn strategy that ensures scratchpad gets tokenized properly\n * but is not compressed.\n */\nexport class ScratchpadStrategy implements IContextStrategy {\n readonly name = 'scratchpad_strategy';\n readonly priority = 10;\n\n shouldApply(ctx: ContextWindow): boolean {\n // Only apply if there's actual scratchpad content to track\n return ctx.scratchpad.length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Basic implementation: we don't compress the scratchpad, we just ensure its tokens are counted\n return ctx;\n }\n}\n\nexport interface HistoryCompressionConfig {\n windowSize: number;\n triggerAtPercent: number; // e.g. 0.8\n}\n\n/**\n * Operates on a rolling window of the oldest N turns and summarizes them.\n */\nexport class HistoryCompressionStrategy implements IContextStrategy {\n readonly name = 'history_compression';\n readonly priority = 30;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: HistoryCompressionConfig\n ) { }\n\n shouldApply(ctx: ContextWindow): boolean {\n const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;\n // Apply if we are over the trigger threshold and have at least enough turns\n // Ignore system prompts and already compressed turns\n const uncompressedTurns = ctx.turns.filter(t => t.role !== 'system' && !t.compressed);\n return ctx.tokenCount >= triggerTokens && uncompressedTurns.length > this.config.windowSize;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Find the oldest N uncompressed turns that aren't the system prompt\n const uncompressedIndices = ctx.turns\n .map((t, i) => ({ t, i }))\n .filter(({ t }) => t.role !== 'system' && !t.compressed)\n .slice(0, this.config.windowSize);\n\n const targetTurns = uncompressedIndices.map(u => u.t);\n const middleText = targetTurns.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the oldest part of this conversation:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n // Filter out the summarized turns\n const indicesToRemove = new Set(uncompressedIndices.map(u => u.i));\n const newTurns = ctx.turns.filter((_, i) => !indicesToRemove.has(i));\n\n const TokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: TokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n}\n","import { IStorageAdapter, STMItem } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface STMRegistryConfig {\n /**\n * The storage backend to use for Short Term Memory items.\n */\n storage: IStorageAdapter;\n\n /**\n * The maximum number of tokens allowed for a 'text' type STM item.\n * If an item exceeds this, it may be rejected or truncated.\n * Default: 100000\n */\n maxTextTokens?: number;\n}\n\n/**\n * Registry for Short Term Memory (STM).\n * Manages the storage and retrieval of large context variables like long texts or blobs.\n * Generates '[STM:uuid]' references to be used within the ReAct agent context.\n */\nexport class ShortTermMemoryRegistry {\n private storage: IStorageAdapter;\n private maxTextTokens: number;\n\n constructor(config: STMRegistryConfig) {\n this.storage = config.storage;\n this.maxTextTokens = config.maxTextTokens ?? 100000;\n }\n\n /**\n * Registers a new memory item and returns its reference string.\n * \n * @param content - The raw content to store\n * @param type - The type of content ('text' or 'blob')\n * @param metadata - Optional metadata (e.g. sandwich layers, original filename)\n * @param estimateTokens - Optional function to estimate token count for 'text' type\n * @returns A reference string formatted as '[STM:uuid]'\n * @throws {Error} if a text item exceeds the maxTextTokens limit\n */\n async register(\n content: any,\n type: 'text' | 'blob',\n metadata?: Record<string, unknown>,\n estimateTokens?: (text: string) => number\n ): Promise<string> {\n if (type === 'text') {\n const tokenCount = estimateTokens ? estimateTokens(content) : Math.ceil(String(content).length / 4);\n if (tokenCount > this.maxTextTokens) {\n throw new Error(`Text content exceeds max tokens limit of ${this.maxTextTokens} (estimated ${tokenCount})`);\n }\n }\n\n const id = randomUUID();\n const item: STMItem = {\n id,\n content,\n type,\n ...(metadata !== undefined ? { metadata } : {})\n };\n\n await this.storage.set(id, item);\n return `[STM:${id}]`;\n }\n\n /**\n * Updates an existing STM item's content or metadata.\n * \n * @param id - The UUID of the item to update\n * @param updates - Partial updates to apply (content or metadata)\n */\n async update(id: string, updates: { content?: any; metadata?: Record<string, unknown> }): Promise<void> {\n const item = await this.storage.get(id);\n if (!item) throw new Error(`STM item not found for update: ${id}`);\n\n const updatedItem: STMItem = {\n ...item,\n ...(updates.content !== undefined ? { content: updates.content } : {}),\n ...(updates.metadata !== undefined ? { metadata: { ...item.metadata, ...updates.metadata } } : {})\n };\n\n await this.storage.set(id, updatedItem);\n }\n\n\n /**\n * Retrieves an STM item by its full reference string (e.g., '[STM:uuid]').\n * \n * @param ref - The full reference string\n * @returns The STMItem or undefined if not found\n */\n async getByRef(ref: string): Promise<STMItem | undefined> {\n const match = ref.match(/^\\[STM:(.+)\\]$/);\n if (!match || !match[1]) return undefined;\n return this.storage.get(match[1]);\n }\n\n /**\n * Deletes an STM item by its ID.\n * \n * @param id - The UUID of the item to delete\n */\n async delete(id: string): Promise<void> {\n await this.storage.delete(id);\n }\n}\n","import { IStorageAdapter } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\n/**\n * An in-memory implementation of IStorageAdapter for holding Short Term Memory.\n * Ideal for testing or single-process lightweight usage.\n *\n * @example\n * const storage = new InMemoryStorageAdapter();\n * const id = await storage.set(undefined, 'my content', { type: 'text' });\n * const retrieved = await storage.get(id);\n */\nexport class InMemoryStorageAdapter implements IStorageAdapter {\n private store = new Map<string, { content: any; metadata?: Record<string, unknown> }>();\n\n /**\n * Retrieves stored content by ID.\n *\n * @param id - The identifier of the stored item\n * @returns The stored content or undefined if not found\n */\n async get(id: string): Promise<any | undefined> {\n return this.store.get(id)?.content;\n }\n\n /**\n * Returns the full item including metadata.\n *\n * @param id - The identifier of the stored item\n * @returns The complete item with content and metadata\n * @internal\n */\n async getFull(id: string): Promise<{ content: any; metadata?: Record<string, unknown> } | undefined> {\n return this.store.get(id);\n }\n\n /**\n * Stores content, generating an ID if none is provided.\n *\n * @param id - Optional provided ID. If omitted, a UUID is generated.\n * @param content - The content to store\n * @param metadata - Optional metadata\n * @returns The ID under which the content is stored\n */\n async set(id: string | undefined, content: any, metadata?: Record<string, unknown>): Promise<string> {\n const resolvedId = id ?? randomUUID();\n this.store.set(resolvedId, metadata !== undefined ? { content, metadata } : { content });\n return resolvedId;\n }\n\n /**\n * Deletes the content for the given ID.\n *\n * @param id - The identifier of the item to delete\n */\n async delete(id: string): Promise<void> {\n this.store.delete(id);\n }\n\n /**\n * Synchronous health check, always true for in-memory.\n *\n * @returns true\n */\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/errors.ts","../../src/context/ContextManager.ts","../../src/context/SandwichCompressionStrategy.ts","../../src/context/HistoryCompressionStrategy.ts","../../src/context/SummaryInjectionStrategy.ts","../../src/context/ShortTermMemoryRegistry.ts","../../src/context/InMemoryStorageAdapter.ts","../../src/context/InMemoryScratchpadAdapter.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import { ContextWindow, IContextStrategy, LemuraContextOverflowError } from '../types/index.js';\n\n/**\n * Orchestrates a stack of IContextStrategy implementations to keep the\n * token count within the maxTokens limit.\n */\nexport class ContextManager {\n private strategies: IContextStrategy[] = [];\n\n /**\n * Registers a new compression or pre-turn strategy and sorts the stack by priority.\n *\n * @param strategy - The strategy implementation to register\n */\n registerStrategy(strategy: IContextStrategy): void {\n this.strategies.push(strategy);\n this.strategies.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Applies all registered strategies that return true for `shouldApply()`\n * until the context token count is safely below the maximum budget.\n *\n * @param context - The context window to prepare\n * @param safetyMargin - Modifier applied to maxTokens (default: 0.95 -> 95%)\n * @returns A new ContextWindow object potentially compressed\n * @throws {LemuraContextOverflowError} If the context is still over maxTokens after all strategies\n */\n async prepare(context: ContextWindow, safetyMargin = 0.95): Promise<ContextWindow> {\n let currentCtx = { ...context, turns: [...context.turns] };\n\n // Recalculate token count from actual turns + system prompt so compression\n // strategies always see an up-to-date figure regardless of how callers\n // track incremental additions (they often forget to update tokenCount).\n const systemTokens = currentCtx.systemPrompt\n ? Math.ceil(currentCtx.systemPrompt.length / 4)\n : 0;\n currentCtx.tokenCount =\n currentCtx.turns.reduce((sum, t) => sum + t.tokenCount, 0) + systemTokens;\n\n const targetTokenCount = currentCtx.maxTokens * safetyMargin;\n\n for (const strategy of this.strategies) {\n // If we are below the limit and it's not a pre-turn non-reducing strategy, skip it.\n // E.g., SummaryInjectionStrategy might still want to run.\n // But purely compression ones drop out early in our base architecture if they choose in `shouldApply`.\n if (strategy.shouldApply(currentCtx)) {\n currentCtx = await strategy.apply(currentCtx);\n }\n }\n\n if (currentCtx.tokenCount > currentCtx.maxTokens) {\n throw new LemuraContextOverflowError(\n `Context overflowed: ${currentCtx.tokenCount} tokens > ${currentCtx.maxTokens}`\n );\n }\n\n return currentCtx;\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\nexport interface SandwichCompressionConfig {\n preserveFirst: number;\n preserveLast: number;\n /** Fire when context reaches this fraction of maxTokens (e.g. 0.80 = 80%). Default: 0.80 */\n triggerThreshold?: number;\n /** Max tokens for the generated summary turn. Default: unlimited */\n summaryMaxTokens?: number;\n /** Strategy execution priority — lower number runs first. Default: 20 */\n priority?: number;\n}\n\n/**\n * Sandwich compression preserves the beginning and end of the conversation,\n * replacing the middle with a generated summary.\n *\n * Pair with `SummaryInjectionStrategy` to ensure the compression summary is\n * visible to the model on every subsequent call.\n */\nexport class SandwichCompressionStrategy implements IContextStrategy {\n readonly name = 'sandwich_compression';\n readonly priority: number;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: SandwichCompressionConfig\n ) {\n this.priority = config.priority ?? 20;\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n const threshold = this.config.triggerThreshold ?? 0.80;\n return (\n ctx.tokenCount >= ctx.maxTokens * threshold &&\n ctx.turns.length > this.config.preserveFirst + this.config.preserveLast\n );\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const { preserveFirst, preserveLast } = this.config;\n\n const head = ctx.turns.slice(0, preserveFirst);\n const tail = ctx.turns.slice(ctx.turns.length - preserveLast);\n const middle = ctx.turns.slice(preserveFirst, ctx.turns.length - preserveLast);\n\n const middleText = middle.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the following conversation history briefly:\\n${middleText}`\n }],\n ...(this.config.summaryMaxTokens ? { maxTokens: this.config.summaryMaxTokens } : {})\n });\n\n const summaryStr = summaryResponse.content;\n\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n const summaryTurn: Turn = {\n role: 'system',\n content: `[COMPRESSED HISTORY SUMMARY]\\n${newCompressionSummary}`,\n tokenCount: this.adapter.estimateTokens(newCompressionSummary),\n turnIndex: -1,\n compressed: true,\n };\n\n const newTurns = [...head, summaryTurn, ...tail];\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n\n /**\n * Applies sandwich compression specifically to a Short Term Memory item's content.\n * Implements a 3-layer pipeline: Pre-Layer (encoding), Core Layer (dense summary), Post-Layer (refinement cues).\n * \n * @param content - The heavy text content to compress\n * @param instructions - Guiding instructions for the core layer summary\n * @returns The three-layer sandwich result\n */\n async compressMemoryItem(content: string, instructions: string = 'Extract the key information'): Promise<{\n preLayer: string;\n coreLayer: string;\n postLayer: string;\n }> {\n // Pre-Layer: Chunking and initial encoding\n // Here we do a naive encoding representation to signify the pre-processed chunks\n const estimatedChunks = Math.max(1, Math.ceil(this.adapter.estimateTokens(content) / 2000));\n const preLayer = `[PRE-LAYER ENCODED: ${estimatedChunks} internal chunks]`;\n\n // Core Layer: Dense summary sandwich with instructions\n // We sandwich the content between the instructions to guide extraction\n // If content is extremely large, we might trim it here, but ideally the provider streaming handles it.\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `### INSTRUCTIONS ###\\n${instructions}\\n\\n### CONTENT ###\\n${content}\\n\\n### INSTRUCTIONS ###\\n${instructions}`\n }]\n });\n const coreLayer = summaryResponse.content;\n\n // Post-Layer: Decoding/Refinement hooks\n // Indicates that the LLM can use tools to drill down into specific chunks\n const postLayer = `[POST-LAYER DECODING: Use \\`refine_layer\\` or \\`read_chunk\\` tools to expand specific sections]`;\n\n return { preLayer, coreLayer, postLayer };\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\n/**\n * ScratchpadStrategy manages the thinking process separate from the turn history.\n * It is primarily a marker/pre-turn strategy that ensures scratchpad gets tokenized properly\n * but is not compressed.\n */\nexport class ScratchpadStrategy implements IContextStrategy {\n readonly name = 'scratchpad_strategy';\n readonly priority = 10;\n\n shouldApply(ctx: ContextWindow): boolean {\n // Only apply if there's actual scratchpad content to track\n return ctx.scratchpad.length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Basic implementation: we don't compress the scratchpad, we just ensure its tokens are counted\n return ctx;\n }\n}\n\nexport interface HistoryCompressionConfig {\n /** Number of oldest turns to summarize in each compression pass */\n windowSize: number;\n /** Fire when context reaches this fraction of maxTokens (e.g. 0.8 = 80%) */\n triggerAtPercent: number;\n /** Strategy execution priority — lower number runs first. Default: 30 */\n priority?: number;\n}\n\n/**\n * Summarizes the oldest N uncompressed turns using a rolling-window approach.\n *\n * Pair with `SummaryInjectionStrategy` (priority < this one) to ensure the\n * accumulated summary is re-injected before each provider call.\n */\nexport class HistoryCompressionStrategy implements IContextStrategy {\n readonly name = 'history_compression';\n readonly priority: number;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: HistoryCompressionConfig\n ) {\n this.priority = config.priority ?? 30;\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;\n // Apply if we are over the trigger threshold and have at least enough turns\n // Ignore system prompts and already compressed turns\n const uncompressedTurns = ctx.turns.filter(t => t.role !== 'system' && !t.compressed);\n return ctx.tokenCount >= triggerTokens && uncompressedTurns.length > this.config.windowSize;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Find the oldest N uncompressed turns that aren't the system prompt\n const uncompressedIndices = ctx.turns\n .map((t, i) => ({ t, i }))\n .filter(({ t }) => t.role !== 'system' && !t.compressed)\n .slice(0, this.config.windowSize);\n\n const targetTurns = uncompressedIndices.map(u => u.t);\n const middleText = targetTurns.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the oldest part of this conversation:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n // Filter out the summarized turns\n const indicesToRemove = new Set(uncompressedIndices.map(u => u.i));\n const newTurns = ctx.turns.filter((_, i) => !indicesToRemove.has(i));\n\n const TokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: TokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n}\n","import { ContextWindow, IContextStrategy, Turn } from '../types/index.js';\n\nexport interface SummaryInjectionConfig {\n /** Strategy priority — lower number runs first. Default: 1 (runs before compression). */\n priority?: number;\n /** Label prepended to the injected summary block. */\n label?: string;\n}\n\n/**\n * SummaryInjectionStrategy ensures that whenever a `compressionSummary` exists on\n * the context window, it is re-injected as a synthetic system turn at the beginning\n * of the turn list before each provider call.\n *\n * **Why this matters:** `HistoryCompressionStrategy` and `SandwichCompressionStrategy`\n * store compressed context in `ctx.compressionSummary`, but without this strategy the\n * summary never reaches the model — the pruned turns are simply gone.\n *\n * Pair this with any compression strategy:\n *\n * @example\n * ```typescript\n * compressionStrategies: [\n * new SummaryInjectionStrategy({ priority: 1 }), // always runs first\n * new SandwichCompressionStrategy(adapter, { priority: 2, triggerThreshold: 0.80 }),\n * ]\n * ```\n *\n * The strategy is idempotent: if a summary turn already exists it is updated in-place\n * rather than appended again.\n */\nexport class SummaryInjectionStrategy implements IContextStrategy {\n readonly name = 'summary_injection';\n readonly priority: number;\n\n private readonly label: string;\n\n constructor(config: SummaryInjectionConfig = {}) {\n this.priority = config.priority ?? 1;\n this.label = config.label ?? 'Earlier conversation summary';\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n return !!ctx.compressionSummary && ctx.compressionSummary.trim().length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const summaryContent = `[${this.label}]\\n${ctx.compressionSummary}`;\n const summaryTokenCount = Math.ceil(summaryContent.length / 4);\n\n // Check if a summary turn already exists (role=system, compressed=true at turnIndex=-1)\n const existingIndex = ctx.turns.findIndex(t => t.compressed && t.role === 'system' && t.turnIndex === -1);\n\n let newTurns: Turn[];\n\n if (existingIndex !== -1) {\n // Update the existing summary turn in-place\n newTurns = ctx.turns.map((t, i) => {\n if (i !== existingIndex) return t;\n return {\n ...t,\n content: summaryContent,\n tokenCount: summaryTokenCount,\n };\n });\n } else {\n // Prepend a new summary turn\n const summaryTurn: Turn = {\n role: 'system',\n content: summaryContent,\n tokenCount: summaryTokenCount,\n turnIndex: -1,\n compressed: true,\n };\n newTurns = [summaryTurn, ...ctx.turns];\n }\n\n // Recalculate token count\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n };\n }\n}\n","import { IStorageAdapter, STMItem } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface STMRegistryConfig {\n /**\n * The storage backend to use for Short Term Memory items.\n */\n storage: IStorageAdapter;\n\n /**\n * The maximum number of tokens allowed for a 'text' type STM item.\n * If an item exceeds this, it may be rejected or truncated.\n * Default: 100000\n */\n maxTextTokens?: number;\n}\n\n/**\n * Registry for Short Term Memory (STM).\n * Manages the storage and retrieval of large context variables like long texts or blobs.\n * Generates '[STM:uuid]' references to be used within the ReAct agent context.\n */\nexport class ShortTermMemoryRegistry {\n private storage: IStorageAdapter;\n private maxTextTokens: number;\n\n constructor(config: STMRegistryConfig) {\n this.storage = config.storage;\n this.maxTextTokens = config.maxTextTokens ?? 100000;\n }\n\n /**\n * Registers a new memory item and returns its reference string.\n * \n * @param content - The raw content to store\n * @param type - The type of content ('text' or 'blob')\n * @param metadata - Optional metadata (e.g. sandwich layers, original filename)\n * @param estimateTokens - Optional function to estimate token count for 'text' type\n * @returns A reference string formatted as '[STM:uuid]'\n * @throws {Error} if a text item exceeds the maxTextTokens limit\n */\n async register(\n content: any,\n type: 'text' | 'blob',\n metadata?: Record<string, unknown>,\n estimateTokens?: (text: string) => number\n ): Promise<string> {\n if (type === 'text') {\n const tokenCount = estimateTokens ? estimateTokens(content) : Math.ceil(String(content).length / 4);\n if (tokenCount > this.maxTextTokens) {\n throw new Error(`Text content exceeds max tokens limit of ${this.maxTextTokens} (estimated ${tokenCount})`);\n }\n }\n\n const id = randomUUID();\n const item: STMItem = {\n id,\n content,\n type,\n ...(metadata !== undefined ? { metadata } : {})\n };\n\n await this.storage.set(id, item);\n return `[STM:${id}]`;\n }\n\n /**\n * Updates an existing STM item's content or metadata.\n * \n * @param id - The UUID of the item to update\n * @param updates - Partial updates to apply (content or metadata)\n */\n async update(id: string, updates: { content?: any; metadata?: Record<string, unknown> }): Promise<void> {\n const item = await this.storage.get(id);\n if (!item) throw new Error(`STM item not found for update: ${id}`);\n\n const updatedItem: STMItem = {\n ...item,\n ...(updates.content !== undefined ? { content: updates.content } : {}),\n ...(updates.metadata !== undefined ? { metadata: { ...item.metadata, ...updates.metadata } } : {})\n };\n\n await this.storage.set(id, updatedItem);\n }\n\n\n /**\n * Retrieves an STM item by its full reference string (e.g., '[STM:uuid]').\n * \n * @param ref - The full reference string\n * @returns The STMItem or undefined if not found\n */\n async getByRef(ref: string): Promise<STMItem | undefined> {\n const match = ref.match(/^\\[STM:(.+)\\]$/);\n if (!match || !match[1]) return undefined;\n return this.storage.get(match[1]);\n }\n\n /**\n * Deletes an STM item by its ID.\n * \n * @param id - The UUID of the item to delete\n */\n async delete(id: string): Promise<void> {\n await this.storage.delete(id);\n }\n}\n","import { IStorageAdapter } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\n/**\n * An in-memory implementation of IStorageAdapter for holding Short Term Memory.\n * Ideal for testing or single-process lightweight usage.\n *\n * @example\n * const storage = new InMemoryStorageAdapter();\n * const id = await storage.set(undefined, 'my content', { type: 'text' });\n * const retrieved = await storage.get(id);\n */\nexport class InMemoryStorageAdapter implements IStorageAdapter {\n private store = new Map<string, { content: any; metadata?: Record<string, unknown> }>();\n\n /**\n * Retrieves stored content by ID.\n *\n * @param id - The identifier of the stored item\n * @returns The stored content or undefined if not found\n */\n async get(id: string): Promise<any | undefined> {\n return this.store.get(id)?.content;\n }\n\n /**\n * Returns the full item including metadata.\n *\n * @param id - The identifier of the stored item\n * @returns The complete item with content and metadata\n * @internal\n */\n async getFull(id: string): Promise<{ content: any; metadata?: Record<string, unknown> } | undefined> {\n return this.store.get(id);\n }\n\n /**\n * Stores content, generating an ID if none is provided.\n *\n * @param id - Optional provided ID. If omitted, a UUID is generated.\n * @param content - The content to store\n * @param metadata - Optional metadata\n * @returns The ID under which the content is stored\n */\n async set(id: string | undefined, content: any, metadata?: Record<string, unknown>): Promise<string> {\n const resolvedId = id ?? randomUUID();\n this.store.set(resolvedId, metadata !== undefined ? { content, metadata } : { content });\n return resolvedId;\n }\n\n /**\n * Deletes the content for the given ID.\n *\n * @param id - The identifier of the item to delete\n */\n async delete(id: string): Promise<void> {\n this.store.delete(id);\n }\n\n /**\n * Synchronous health check, always true for in-memory.\n *\n * @returns true\n */\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n","import { IScratchpadAdapter } from '../types/index.js';\n\n/**\n * In-memory scratchpad adapter, keyed by sessionId.\n * Ideal for testing or single-process usage.\n */\nexport class InMemoryScratchpadAdapter implements IScratchpadAdapter {\n private store = new Map<string, string>();\n\n async read(sessionId: string): Promise<string | undefined> {\n return this.store.get(sessionId);\n }\n\n async write(sessionId: string, content: string): Promise<void> {\n this.store.set(sessionId, content);\n }\n\n async clear(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n"]}
@@ -47,6 +47,8 @@ var ContextManager = class {
47
47
  */
48
48
  async prepare(context, safetyMargin = 0.95) {
49
49
  let currentCtx = { ...context, turns: [...context.turns] };
50
+ const systemTokens = currentCtx.systemPrompt ? Math.ceil(currentCtx.systemPrompt.length / 4) : 0;
51
+ currentCtx.tokenCount = currentCtx.turns.reduce((sum, t) => sum + t.tokenCount, 0) + systemTokens;
50
52
  currentCtx.maxTokens * safetyMargin;
51
53
  for (const strategy of this.strategies) {
52
54
  if (strategy.shouldApply(currentCtx)) {
@@ -67,11 +69,13 @@ var SandwichCompressionStrategy = class {
67
69
  constructor(adapter, config) {
68
70
  this.adapter = adapter;
69
71
  this.config = config;
72
+ this.priority = config.priority ?? 20;
70
73
  }
71
74
  name = "sandwich_compression";
72
- priority = 20;
75
+ priority;
73
76
  shouldApply(ctx) {
74
- return ctx.tokenCount >= ctx.maxTokens * this.config.triggerThreshold && ctx.turns.length > this.config.preserveFirst + this.config.preserveLast;
77
+ const threshold = this.config.triggerThreshold ?? 0.8;
78
+ return ctx.tokenCount >= ctx.maxTokens * threshold && ctx.turns.length > this.config.preserveFirst + this.config.preserveLast;
75
79
  }
76
80
  async apply(ctx) {
77
81
  const { preserveFirst, preserveLast } = this.config;
@@ -85,7 +89,8 @@ var SandwichCompressionStrategy = class {
85
89
  role: "user",
86
90
  content: `Summarize the following conversation history briefly:
87
91
  ${middleText}`
88
- }]
92
+ }],
93
+ ...this.config.summaryMaxTokens ? { maxTokens: this.config.summaryMaxTokens } : {}
89
94
  });
90
95
  const summaryStr = summaryResponse.content;
91
96
  const newCompressionSummary = ctx.compressionSummary ? `${ctx.compressionSummary}
@@ -153,9 +158,10 @@ var HistoryCompressionStrategy = class {
153
158
  constructor(adapter, config) {
154
159
  this.adapter = adapter;
155
160
  this.config = config;
161
+ this.priority = config.priority ?? 30;
156
162
  }
157
163
  name = "history_compression";
158
- priority = 30;
164
+ priority;
159
165
  shouldApply(ctx) {
160
166
  const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;
161
167
  const uncompressedTurns = ctx.turns.filter((t) => t.role !== "system" && !t.compressed);
@@ -187,6 +193,52 @@ ${summaryStr}` : summaryStr;
187
193
  };
188
194
  }
189
195
  };
196
+
197
+ // src/context/SummaryInjectionStrategy.ts
198
+ var SummaryInjectionStrategy = class {
199
+ name = "summary_injection";
200
+ priority;
201
+ label;
202
+ constructor(config = {}) {
203
+ this.priority = config.priority ?? 1;
204
+ this.label = config.label ?? "Earlier conversation summary";
205
+ }
206
+ shouldApply(ctx) {
207
+ return !!ctx.compressionSummary && ctx.compressionSummary.trim().length > 0;
208
+ }
209
+ async apply(ctx) {
210
+ const summaryContent = `[${this.label}]
211
+ ${ctx.compressionSummary}`;
212
+ const summaryTokenCount = Math.ceil(summaryContent.length / 4);
213
+ const existingIndex = ctx.turns.findIndex((t) => t.compressed && t.role === "system" && t.turnIndex === -1);
214
+ let newTurns;
215
+ if (existingIndex !== -1) {
216
+ newTurns = ctx.turns.map((t, i) => {
217
+ if (i !== existingIndex) return t;
218
+ return {
219
+ ...t,
220
+ content: summaryContent,
221
+ tokenCount: summaryTokenCount
222
+ };
223
+ });
224
+ } else {
225
+ const summaryTurn = {
226
+ role: "system",
227
+ content: summaryContent,
228
+ tokenCount: summaryTokenCount,
229
+ turnIndex: -1,
230
+ compressed: true
231
+ };
232
+ newTurns = [summaryTurn, ...ctx.turns];
233
+ }
234
+ const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0);
235
+ return {
236
+ ...ctx,
237
+ turns: newTurns,
238
+ tokenCount: newTokenCount
239
+ };
240
+ }
241
+ };
190
242
  var ShortTermMemoryRegistry = class {
191
243
  storage;
192
244
  maxTextTokens;
@@ -309,6 +361,23 @@ var InMemoryStorageAdapter = class {
309
361
  }
310
362
  };
311
363
 
312
- export { ContextManager, HistoryCompressionStrategy, InMemoryStorageAdapter, SandwichCompressionStrategy, ScratchpadStrategy, ShortTermMemoryRegistry };
364
+ // src/context/InMemoryScratchpadAdapter.ts
365
+ var InMemoryScratchpadAdapter = class {
366
+ store = /* @__PURE__ */ new Map();
367
+ async read(sessionId) {
368
+ return this.store.get(sessionId);
369
+ }
370
+ async write(sessionId, content) {
371
+ this.store.set(sessionId, content);
372
+ }
373
+ async clear(sessionId) {
374
+ this.store.delete(sessionId);
375
+ }
376
+ async healthCheck() {
377
+ return true;
378
+ }
379
+ };
380
+
381
+ export { ContextManager, HistoryCompressionStrategy, InMemoryScratchpadAdapter, InMemoryStorageAdapter, SandwichCompressionStrategy, ScratchpadStrategy, ShortTermMemoryRegistry, SummaryInjectionStrategy };
313
382
  //# sourceMappingURL=index.mjs.map
314
383
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/errors.ts","../../src/context/ContextManager.ts","../../src/context/SandwichCompressionStrategy.ts","../../src/context/HistoryCompressionStrategy.ts","../../src/context/ShortTermMemoryRegistry.ts","../../src/context/InMemoryStorageAdapter.ts"],"names":["randomUUID"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import { ContextWindow, IContextStrategy, LemuraContextOverflowError } from '../types/index.js';\n\n/**\n * Orchestrates a stack of IContextStrategy implementations to keep the\n * token count within the maxTokens limit.\n */\nexport class ContextManager {\n private strategies: IContextStrategy[] = [];\n\n /**\n * Registers a new compression or pre-turn strategy and sorts the stack by priority.\n *\n * @param strategy - The strategy implementation to register\n */\n registerStrategy(strategy: IContextStrategy): void {\n this.strategies.push(strategy);\n this.strategies.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Applies all registered strategies that return true for `shouldApply()`\n * until the context token count is safely below the maximum budget.\n *\n * @param context - The context window to prepare\n * @param safetyMargin - Modifier applied to maxTokens (default: 0.95 -> 95%)\n * @returns A new ContextWindow object potentially compressed\n * @throws {LemuraContextOverflowError} If the context is still over maxTokens after all strategies\n */\n async prepare(context: ContextWindow, safetyMargin = 0.95): Promise<ContextWindow> {\n let currentCtx = { ...context, turns: [...context.turns] };\n const targetTokenCount = currentCtx.maxTokens * safetyMargin;\n\n for (const strategy of this.strategies) {\n // If we are below the limit and it's not a pre-turn non-reducing strategy, skip it.\n // E.g., SummaryInjectionStrategy might still want to run.\n // But purely compression ones drop out early in our base architecture if they choose in `shouldApply`.\n if (strategy.shouldApply(currentCtx)) {\n currentCtx = await strategy.apply(currentCtx);\n }\n }\n\n if (currentCtx.tokenCount > currentCtx.maxTokens) {\n throw new LemuraContextOverflowError(\n `Context overflowed: ${currentCtx.tokenCount} tokens > ${currentCtx.maxTokens}`\n );\n }\n\n return currentCtx;\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\nexport interface SandwichCompressionConfig {\n preserveFirst: number;\n preserveLast: number;\n triggerThreshold: number; // e.g. 0.8\n}\n\n/**\n * Sandwich compression preserves the beginning and end of the conversation,\n * replacing the middle with a generated summary.\n */\nexport class SandwichCompressionStrategy implements IContextStrategy {\n readonly name = 'sandwich_compression';\n readonly priority = 20;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: SandwichCompressionConfig\n ) { }\n\n shouldApply(ctx: ContextWindow): boolean {\n return (\n ctx.tokenCount >= ctx.maxTokens * this.config.triggerThreshold &&\n ctx.turns.length > this.config.preserveFirst + this.config.preserveLast\n );\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const { preserveFirst, preserveLast } = this.config;\n\n const head = ctx.turns.slice(0, preserveFirst);\n const tail = ctx.turns.slice(ctx.turns.length - preserveLast);\n const middle = ctx.turns.slice(preserveFirst, ctx.turns.length - preserveLast);\n\n const middleText = middle.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the following conversation history briefly:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n const summaryTurn: Turn = {\n role: 'system',\n content: `[COMPRESSED HISTORY SUMMARY]\\n${newCompressionSummary}`,\n tokenCount: this.adapter.estimateTokens(newCompressionSummary),\n turnIndex: -1,\n compressed: true,\n };\n\n const newTurns = [...head, summaryTurn, ...tail];\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n\n /**\n * Applies sandwich compression specifically to a Short Term Memory item's content.\n * Implements a 3-layer pipeline: Pre-Layer (encoding), Core Layer (dense summary), Post-Layer (refinement cues).\n * \n * @param content - The heavy text content to compress\n * @param instructions - Guiding instructions for the core layer summary\n * @returns The three-layer sandwich result\n */\n async compressMemoryItem(content: string, instructions: string = 'Extract the key information'): Promise<{\n preLayer: string;\n coreLayer: string;\n postLayer: string;\n }> {\n // Pre-Layer: Chunking and initial encoding\n // Here we do a naive encoding representation to signify the pre-processed chunks\n const estimatedChunks = Math.max(1, Math.ceil(this.adapter.estimateTokens(content) / 2000));\n const preLayer = `[PRE-LAYER ENCODED: ${estimatedChunks} internal chunks]`;\n\n // Core Layer: Dense summary sandwich with instructions\n // We sandwich the content between the instructions to guide extraction\n // If content is extremely large, we might trim it here, but ideally the provider streaming handles it.\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `### INSTRUCTIONS ###\\n${instructions}\\n\\n### CONTENT ###\\n${content}\\n\\n### INSTRUCTIONS ###\\n${instructions}`\n }]\n });\n const coreLayer = summaryResponse.content;\n\n // Post-Layer: Decoding/Refinement hooks\n // Indicates that the LLM can use tools to drill down into specific chunks\n const postLayer = `[POST-LAYER DECODING: Use \\`refine_layer\\` or \\`read_chunk\\` tools to expand specific sections]`;\n\n return { preLayer, coreLayer, postLayer };\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\n/**\n * ScratchpadStrategy manages the thinking process separate from the turn history.\n * It is primarily a marker/pre-turn strategy that ensures scratchpad gets tokenized properly\n * but is not compressed.\n */\nexport class ScratchpadStrategy implements IContextStrategy {\n readonly name = 'scratchpad_strategy';\n readonly priority = 10;\n\n shouldApply(ctx: ContextWindow): boolean {\n // Only apply if there's actual scratchpad content to track\n return ctx.scratchpad.length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Basic implementation: we don't compress the scratchpad, we just ensure its tokens are counted\n return ctx;\n }\n}\n\nexport interface HistoryCompressionConfig {\n windowSize: number;\n triggerAtPercent: number; // e.g. 0.8\n}\n\n/**\n * Operates on a rolling window of the oldest N turns and summarizes them.\n */\nexport class HistoryCompressionStrategy implements IContextStrategy {\n readonly name = 'history_compression';\n readonly priority = 30;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: HistoryCompressionConfig\n ) { }\n\n shouldApply(ctx: ContextWindow): boolean {\n const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;\n // Apply if we are over the trigger threshold and have at least enough turns\n // Ignore system prompts and already compressed turns\n const uncompressedTurns = ctx.turns.filter(t => t.role !== 'system' && !t.compressed);\n return ctx.tokenCount >= triggerTokens && uncompressedTurns.length > this.config.windowSize;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Find the oldest N uncompressed turns that aren't the system prompt\n const uncompressedIndices = ctx.turns\n .map((t, i) => ({ t, i }))\n .filter(({ t }) => t.role !== 'system' && !t.compressed)\n .slice(0, this.config.windowSize);\n\n const targetTurns = uncompressedIndices.map(u => u.t);\n const middleText = targetTurns.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the oldest part of this conversation:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n // Filter out the summarized turns\n const indicesToRemove = new Set(uncompressedIndices.map(u => u.i));\n const newTurns = ctx.turns.filter((_, i) => !indicesToRemove.has(i));\n\n const TokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: TokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n}\n","import { IStorageAdapter, STMItem } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface STMRegistryConfig {\n /**\n * The storage backend to use for Short Term Memory items.\n */\n storage: IStorageAdapter;\n\n /**\n * The maximum number of tokens allowed for a 'text' type STM item.\n * If an item exceeds this, it may be rejected or truncated.\n * Default: 100000\n */\n maxTextTokens?: number;\n}\n\n/**\n * Registry for Short Term Memory (STM).\n * Manages the storage and retrieval of large context variables like long texts or blobs.\n * Generates '[STM:uuid]' references to be used within the ReAct agent context.\n */\nexport class ShortTermMemoryRegistry {\n private storage: IStorageAdapter;\n private maxTextTokens: number;\n\n constructor(config: STMRegistryConfig) {\n this.storage = config.storage;\n this.maxTextTokens = config.maxTextTokens ?? 100000;\n }\n\n /**\n * Registers a new memory item and returns its reference string.\n * \n * @param content - The raw content to store\n * @param type - The type of content ('text' or 'blob')\n * @param metadata - Optional metadata (e.g. sandwich layers, original filename)\n * @param estimateTokens - Optional function to estimate token count for 'text' type\n * @returns A reference string formatted as '[STM:uuid]'\n * @throws {Error} if a text item exceeds the maxTextTokens limit\n */\n async register(\n content: any,\n type: 'text' | 'blob',\n metadata?: Record<string, unknown>,\n estimateTokens?: (text: string) => number\n ): Promise<string> {\n if (type === 'text') {\n const tokenCount = estimateTokens ? estimateTokens(content) : Math.ceil(String(content).length / 4);\n if (tokenCount > this.maxTextTokens) {\n throw new Error(`Text content exceeds max tokens limit of ${this.maxTextTokens} (estimated ${tokenCount})`);\n }\n }\n\n const id = randomUUID();\n const item: STMItem = {\n id,\n content,\n type,\n ...(metadata !== undefined ? { metadata } : {})\n };\n\n await this.storage.set(id, item);\n return `[STM:${id}]`;\n }\n\n /**\n * Updates an existing STM item's content or metadata.\n * \n * @param id - The UUID of the item to update\n * @param updates - Partial updates to apply (content or metadata)\n */\n async update(id: string, updates: { content?: any; metadata?: Record<string, unknown> }): Promise<void> {\n const item = await this.storage.get(id);\n if (!item) throw new Error(`STM item not found for update: ${id}`);\n\n const updatedItem: STMItem = {\n ...item,\n ...(updates.content !== undefined ? { content: updates.content } : {}),\n ...(updates.metadata !== undefined ? { metadata: { ...item.metadata, ...updates.metadata } } : {})\n };\n\n await this.storage.set(id, updatedItem);\n }\n\n\n /**\n * Retrieves an STM item by its full reference string (e.g., '[STM:uuid]').\n * \n * @param ref - The full reference string\n * @returns The STMItem or undefined if not found\n */\n async getByRef(ref: string): Promise<STMItem | undefined> {\n const match = ref.match(/^\\[STM:(.+)\\]$/);\n if (!match || !match[1]) return undefined;\n return this.storage.get(match[1]);\n }\n\n /**\n * Deletes an STM item by its ID.\n * \n * @param id - The UUID of the item to delete\n */\n async delete(id: string): Promise<void> {\n await this.storage.delete(id);\n }\n}\n","import { IStorageAdapter } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\n/**\n * An in-memory implementation of IStorageAdapter for holding Short Term Memory.\n * Ideal for testing or single-process lightweight usage.\n *\n * @example\n * const storage = new InMemoryStorageAdapter();\n * const id = await storage.set(undefined, 'my content', { type: 'text' });\n * const retrieved = await storage.get(id);\n */\nexport class InMemoryStorageAdapter implements IStorageAdapter {\n private store = new Map<string, { content: any; metadata?: Record<string, unknown> }>();\n\n /**\n * Retrieves stored content by ID.\n *\n * @param id - The identifier of the stored item\n * @returns The stored content or undefined if not found\n */\n async get(id: string): Promise<any | undefined> {\n return this.store.get(id)?.content;\n }\n\n /**\n * Returns the full item including metadata.\n *\n * @param id - The identifier of the stored item\n * @returns The complete item with content and metadata\n * @internal\n */\n async getFull(id: string): Promise<{ content: any; metadata?: Record<string, unknown> } | undefined> {\n return this.store.get(id);\n }\n\n /**\n * Stores content, generating an ID if none is provided.\n *\n * @param id - Optional provided ID. If omitted, a UUID is generated.\n * @param content - The content to store\n * @param metadata - Optional metadata\n * @returns The ID under which the content is stored\n */\n async set(id: string | undefined, content: any, metadata?: Record<string, unknown>): Promise<string> {\n const resolvedId = id ?? randomUUID();\n this.store.set(resolvedId, metadata !== undefined ? { content, metadata } : { content });\n return resolvedId;\n }\n\n /**\n * Deletes the content for the given ID.\n *\n * @param id - The identifier of the item to delete\n */\n async delete(id: string): Promise<void> {\n this.store.delete(id);\n }\n\n /**\n * Synchronous health check, always true for in-memory.\n *\n * @returns true\n */\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/errors.ts","../../src/context/ContextManager.ts","../../src/context/SandwichCompressionStrategy.ts","../../src/context/HistoryCompressionStrategy.ts","../../src/context/SummaryInjectionStrategy.ts","../../src/context/ShortTermMemoryRegistry.ts","../../src/context/InMemoryStorageAdapter.ts","../../src/context/InMemoryScratchpadAdapter.ts"],"names":["randomUUID"],"mappings":";;;AAMO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,YACI,OAAA,EACgB,IAAA,EACA,OAAA,EACA,KAAA,GAAkB,EAAC,EACrC;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EACpD;AACJ,CAAA;AAGO,IAAM,0BAAA,GAAN,cAAyC,WAAA,CAAY;AAAA,EACxD,YAAY,OAAA,EAAiB;AACzB,IAAA,KAAA,CAAM,SAAS,kBAAkB,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AAAA,EAChB;AACJ,CAAA;;;ACzBO,IAAM,iBAAN,MAAqB;AAAA,EAChB,aAAiC,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1C,iBAAiB,QAAA,EAAkC;AAC/C,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,QAAQ,CAAA;AAC7B,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,CAAQ,OAAA,EAAwB,YAAA,GAAe,IAAA,EAA8B;AAC/E,IAAA,IAAI,UAAA,GAAa,EAAE,GAAG,OAAA,EAAS,OAAO,CAAC,GAAG,OAAA,CAAQ,KAAK,CAAA,EAAE;AAKzD,IAAA,MAAM,YAAA,GAAe,WAAW,YAAA,GAC1B,IAAA,CAAK,KAAK,UAAA,CAAW,YAAA,CAAa,MAAA,GAAS,CAAC,CAAA,GAC5C,CAAA;AACN,IAAA,UAAA,CAAW,UAAA,GACP,UAAA,CAAW,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,CAAA,CAAE,UAAA,EAAY,CAAC,CAAA,GAAI,YAAA;AAEjE,IAAyB,WAAW,SAAA,GAAY;AAEhD,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,UAAA,EAAY;AAIpC,MAAA,IAAI,QAAA,CAAS,WAAA,CAAY,UAAU,CAAA,EAAG;AAClC,QAAA,UAAA,GAAa,MAAM,QAAA,CAAS,KAAA,CAAM,UAAU,CAAA;AAAA,MAChD;AAAA,IACJ;AAEA,IAAA,IAAI,UAAA,CAAW,UAAA,GAAa,UAAA,CAAW,SAAA,EAAW;AAC9C,MAAA,MAAM,IAAI,0BAAA;AAAA,QACN,CAAA,oBAAA,EAAuB,UAAA,CAAW,UAAU,CAAA,UAAA,EAAa,WAAW,SAAS,CAAA;AAAA,OACjF;AAAA,IACJ;AAEA,IAAA,OAAO,UAAA;AAAA,EACX;AACJ;;;ACvCO,IAAM,8BAAN,MAA8D;AAAA,EAIjE,WAAA,CACY,SACA,MAAA,EACV;AAFU,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAER,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,EAAA;AAAA,EACvC;AAAA,EARS,IAAA,GAAO,sBAAA;AAAA,EACP,QAAA;AAAA,EAST,YAAY,GAAA,EAA6B;AACrC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,gBAAA,IAAoB,GAAA;AAClD,IAAA,OACI,GAAA,CAAI,UAAA,IAAc,GAAA,CAAI,SAAA,GAAY,SAAA,IAClC,GAAA,CAAI,KAAA,CAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,YAAA;AAAA,EAEnE;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AACpD,IAAA,MAAM,EAAE,aAAA,EAAe,YAAA,EAAa,GAAI,IAAA,CAAK,MAAA;AAE7C,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAG,aAAa,CAAA;AAC7C,IAAA,MAAM,OAAO,GAAA,CAAI,KAAA,CAAM,MAAM,GAAA,CAAI,KAAA,CAAM,SAAS,YAAY,CAAA;AAC5D,IAAA,MAAM,MAAA,GAAS,IAAI,KAAA,CAAM,KAAA,CAAM,eAAe,GAAA,CAAI,KAAA,CAAM,SAAS,YAAY,CAAA;AAE7E,IAAA,MAAM,aAAa,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,EAAE,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAEvF,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAA0D,UAAU,CAAA;AAAA,OAChF,CAAA;AAAA,MACD,GAAI,IAAA,CAAK,MAAA,CAAO,gBAAA,GAAmB,EAAE,WAAW,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAiB,GAAI;AAAC,KACrF,CAAA;AAED,IAAA,MAAM,aAAa,eAAA,CAAgB,OAAA;AAEnC,IAAA,MAAM,qBAAA,GAAwB,GAAA,CAAI,kBAAA,GAC5B,CAAA,EAAG,IAAI,kBAAkB;AAAA,EAAK,UAAU,CAAA,CAAA,GACxC,UAAA;AAEN,IAAA,MAAM,WAAA,GAAoB;AAAA,MACtB,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,CAAA;AAAA,EAAiC,qBAAqB,CAAA,CAAA;AAAA,MAC/D,UAAA,EAAY,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,qBAAqB,CAAA;AAAA,MAC7D,SAAA,EAAW,EAAA;AAAA,MACX,UAAA,EAAY;AAAA,KAChB;AAEA,IAAA,MAAM,WAAW,CAAC,GAAG,IAAA,EAAM,WAAA,EAAa,GAAG,IAAI,CAAA;AAC/C,IAAA,MAAM,aAAA,GAAgB,SAAS,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,EAAE,UAAA,EAAY,CAAC,IACnE,IAAA,CAAK,OAAA,CAAQ,eAAe,GAAA,CAAI,YAAY,IAC5C,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA;AAE9C,IAAA,OAAO;AAAA,MACH,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,QAAA;AAAA,MACP,UAAA,EAAY,aAAA;AAAA,MACZ,kBAAA,EAAoB;AAAA,KACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,kBAAA,CAAmB,OAAA,EAAiB,YAAA,GAAuB,6BAAA,EAI9D;AAGC,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,OAAO,CAAA,GAAI,GAAI,CAAC,CAAA;AAC1F,IAAA,MAAM,QAAA,GAAW,uBAAuB,eAAe,CAAA,iBAAA,CAAA;AAKvD,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAAyB,YAAY;;AAAA;AAAA,EAAwB,OAAO;;AAAA;AAAA,EAA6B,YAAY,CAAA;AAAA,OACzH;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,YAAY,eAAA,CAAgB,OAAA;AAIlC,IAAA,MAAM,SAAA,GAAY,CAAA,+FAAA,CAAA;AAElB,IAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAU;AAAA,EAC5C;AACJ;;;ACjHO,IAAM,qBAAN,MAAqD;AAAA,EAC/C,IAAA,GAAO,qBAAA;AAAA,EACP,QAAA,GAAW,EAAA;AAAA,EAEpB,YAAY,GAAA,EAA6B;AAErC,IAAA,OAAO,GAAA,CAAI,WAAW,MAAA,GAAS,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AAEpD,IAAA,OAAO,GAAA;AAAA,EACX;AACJ;AAiBO,IAAM,6BAAN,MAA6D;AAAA,EAIhE,WAAA,CACY,SACA,MAAA,EACV;AAFU,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAER,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,EAAA;AAAA,EACvC;AAAA,EARS,IAAA,GAAO,qBAAA;AAAA,EACP,QAAA;AAAA,EAST,YAAY,GAAA,EAA6B;AACrC,IAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,gBAAA;AAGlD,IAAA,MAAM,iBAAA,GAAoB,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,QAAA,IAAY,CAAC,CAAA,CAAE,UAAU,CAAA;AACpF,IAAA,OAAO,IAAI,UAAA,IAAc,aAAA,IAAiB,iBAAA,CAAkB,MAAA,GAAS,KAAK,MAAA,CAAO,UAAA;AAAA,EACrF;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AAEpD,IAAA,MAAM,mBAAA,GAAsB,GAAA,CAAI,KAAA,CAC3B,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,EAAE,CAAE,CAAA,CACxB,MAAA,CAAO,CAAC,EAAE,CAAA,EAAE,KAAM,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAC,CAAA,CAAE,UAAU,CAAA,CACtD,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA;AAEpC,IAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,CAAC,CAAA;AACpD,IAAA,MAAM,aAAa,WAAA,CAAY,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,EAAE,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAE5F,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS;AAAA,MAChD,KAAA,EAAO,EAAA;AAAA,MACP,UAAU,CAAC;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA;AAAA,EAAoD,UAAU,CAAA;AAAA,OAC1E;AAAA,KACJ,CAAA;AAED,IAAA,MAAM,aAAa,eAAA,CAAgB,OAAA;AACnC,IAAA,MAAM,qBAAA,GAAwB,GAAA,CAAI,kBAAA,GAC5B,CAAA,EAAG,IAAI,kBAAkB;AAAA,EAAK,UAAU,CAAA,CAAA,GACxC,UAAA;AAGN,IAAA,MAAM,eAAA,GAAkB,IAAI,GAAA,CAAI,mBAAA,CAAoB,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,CAAC,CAAC,CAAA;AACjE,IAAA,MAAM,QAAA,GAAW,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAC,eAAA,CAAgB,GAAA,CAAI,CAAC,CAAC,CAAA;AAEnE,IAAA,MAAM,UAAA,GAAa,SAAS,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,EAAE,UAAA,EAAY,CAAC,IAChE,IAAA,CAAK,OAAA,CAAQ,eAAe,GAAA,CAAI,YAAY,IAC5C,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA;AAE9C,IAAA,OAAO;AAAA,MACH,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,QAAA;AAAA,MACP,UAAA,EAAY,UAAA;AAAA,MACZ,kBAAA,EAAoB;AAAA,KACxB;AAAA,EACJ;AACJ;;;AC/DO,IAAM,2BAAN,MAA2D;AAAA,EACrD,IAAA,GAAO,mBAAA;AAAA,EACP,QAAA;AAAA,EAEQ,KAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,GAAiC,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,CAAA;AACnC,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAO,KAAA,IAAS,8BAAA;AAAA,EACjC;AAAA,EAEA,YAAY,GAAA,EAA6B;AACrC,IAAA,OAAO,CAAC,CAAC,GAAA,CAAI,kBAAA,IAAsB,IAAI,kBAAA,CAAmB,IAAA,GAAO,MAAA,GAAS,CAAA;AAAA,EAC9E;AAAA,EAEA,MAAM,MAAM,GAAA,EAA4C;AACpD,IAAA,MAAM,cAAA,GAAiB,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAA;AAAA,EAAM,IAAI,kBAAkB,CAAA,CAAA;AACjE,IAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,SAAS,CAAC,CAAA;AAG7D,IAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,KAAA,CAAM,SAAA,CAAU,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,IAAc,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,SAAA,KAAc,EAAE,CAAA;AAExG,IAAA,IAAI,QAAA;AAEJ,IAAA,IAAI,kBAAkB,EAAA,EAAI;AAEtB,MAAA,QAAA,GAAW,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AAC/B,QAAA,IAAI,CAAA,KAAM,eAAe,OAAO,CAAA;AAChC,QAAA,OAAO;AAAA,UACH,GAAG,CAAA;AAAA,UACH,OAAA,EAAS,cAAA;AAAA,UACT,UAAA,EAAY;AAAA,SAChB;AAAA,MACJ,CAAC,CAAA;AAAA,IACL,CAAA,MAAO;AAEH,MAAA,MAAM,WAAA,GAAoB;AAAA,QACtB,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,cAAA;AAAA,QACT,UAAA,EAAY,iBAAA;AAAA,QACZ,SAAA,EAAW,EAAA;AAAA,QACX,UAAA,EAAY;AAAA,OAChB;AACA,MAAA,QAAA,GAAW,CAAC,WAAA,EAAa,GAAG,GAAA,CAAI,KAAK,CAAA;AAAA,IACzC;AAGA,IAAA,MAAM,aAAA,GAAgB,SAAS,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,CAAA,CAAE,UAAA,EAAY,CAAC,CAAA;AAEvE,IAAA,OAAO;AAAA,MACH,GAAG,GAAA;AAAA,MACH,KAAA,EAAO,QAAA;AAAA,MACP,UAAA,EAAY;AAAA,KAChB;AAAA,EACJ;AACJ;AChEO,IAAM,0BAAN,MAA8B;AAAA,EACzB,OAAA;AAAA,EACA,aAAA;AAAA,EAER,YAAY,MAAA,EAA2B;AACnC,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACtB,IAAA,IAAA,CAAK,aAAA,GAAgB,OAAO,aAAA,IAAiB,GAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAAA,CACF,OAAA,EACA,IAAA,EACA,UACA,cAAA,EACe;AACf,IAAA,IAAI,SAAS,MAAA,EAAQ;AACjB,MAAA,MAAM,UAAA,GAAa,cAAA,GAAiB,cAAA,CAAe,OAAO,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAClG,MAAA,IAAI,UAAA,GAAa,KAAK,aAAA,EAAe;AACjC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yCAAA,EAA4C,KAAK,aAAa,CAAA,YAAA,EAAe,UAAU,CAAA,CAAA,CAAG,CAAA;AAAA,MAC9G;AAAA,IACJ;AAEA,IAAA,MAAM,KAAK,UAAA,EAAW;AACtB,IAAA,MAAM,IAAA,GAAgB;AAAA,MAClB,EAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAI,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,KAAa;AAAC,KACjD;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,IAAI,CAAA;AAC/B,IAAA,OAAO,QAAQ,EAAE,CAAA,CAAA,CAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CAAO,EAAA,EAAY,OAAA,EAA+E;AACpG,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,EAAE,CAAA;AACtC,IAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,EAAE,CAAA,CAAE,CAAA;AAEjE,IAAA,MAAM,WAAA,GAAuB;AAAA,MACzB,GAAG,IAAA;AAAA,MACH,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,MACpE,GAAI,OAAA,CAAQ,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,EAAE,GAAG,IAAA,CAAK,UAAU,GAAG,OAAA,CAAQ,QAAA,EAAS,KAAM;AAAC,KACpG;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,WAAW,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,GAAA,EAA2C;AACtD,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,gBAAgB,CAAA;AACxC,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,CAAM,CAAC,GAAG,OAAO,MAAA;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,EAAA,EAA2B;AACpC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAA;AAAA,EAChC;AACJ;AC9FO,IAAM,yBAAN,MAAwD;AAAA,EACnD,KAAA,uBAAY,GAAA,EAAkE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtF,MAAM,IAAI,EAAA,EAAsC;AAC5C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,EAAG,OAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,EAAA,EAAuF;AACjG,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,GAAA,CAAI,EAAA,EAAwB,OAAA,EAAc,QAAA,EAAqD;AACjG,IAAA,MAAM,UAAA,GAAa,MAAMA,UAAAA,EAAW;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAA,EAAY,QAAA,KAAa,MAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAS,GAAI,EAAE,OAAA,EAAS,CAAA;AACvF,IAAA,OAAO,UAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,EAAA,EAA2B;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,EAAE,CAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,GAAgC;AAClC,IAAA,OAAO,IAAA;AAAA,EACX;AACJ;;;AC7DO,IAAM,4BAAN,MAA8D;AAAA,EACzD,KAAA,uBAAY,GAAA,EAAoB;AAAA,EAExC,MAAM,KAAK,SAAA,EAAgD;AACvD,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,SAAS,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,KAAA,CAAM,SAAA,EAAmB,OAAA,EAAgC;AAC3D,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,SAAA,EAAW,OAAO,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,MAAM,SAAA,EAAkC;AAC1C,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,SAAS,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,WAAA,GAAgC;AAClC,IAAA,OAAO,IAAA;AAAA,EACX;AACJ","file":"index.mjs","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import { ContextWindow, IContextStrategy, LemuraContextOverflowError } from '../types/index.js';\n\n/**\n * Orchestrates a stack of IContextStrategy implementations to keep the\n * token count within the maxTokens limit.\n */\nexport class ContextManager {\n private strategies: IContextStrategy[] = [];\n\n /**\n * Registers a new compression or pre-turn strategy and sorts the stack by priority.\n *\n * @param strategy - The strategy implementation to register\n */\n registerStrategy(strategy: IContextStrategy): void {\n this.strategies.push(strategy);\n this.strategies.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Applies all registered strategies that return true for `shouldApply()`\n * until the context token count is safely below the maximum budget.\n *\n * @param context - The context window to prepare\n * @param safetyMargin - Modifier applied to maxTokens (default: 0.95 -> 95%)\n * @returns A new ContextWindow object potentially compressed\n * @throws {LemuraContextOverflowError} If the context is still over maxTokens after all strategies\n */\n async prepare(context: ContextWindow, safetyMargin = 0.95): Promise<ContextWindow> {\n let currentCtx = { ...context, turns: [...context.turns] };\n\n // Recalculate token count from actual turns + system prompt so compression\n // strategies always see an up-to-date figure regardless of how callers\n // track incremental additions (they often forget to update tokenCount).\n const systemTokens = currentCtx.systemPrompt\n ? Math.ceil(currentCtx.systemPrompt.length / 4)\n : 0;\n currentCtx.tokenCount =\n currentCtx.turns.reduce((sum, t) => sum + t.tokenCount, 0) + systemTokens;\n\n const targetTokenCount = currentCtx.maxTokens * safetyMargin;\n\n for (const strategy of this.strategies) {\n // If we are below the limit and it's not a pre-turn non-reducing strategy, skip it.\n // E.g., SummaryInjectionStrategy might still want to run.\n // But purely compression ones drop out early in our base architecture if they choose in `shouldApply`.\n if (strategy.shouldApply(currentCtx)) {\n currentCtx = await strategy.apply(currentCtx);\n }\n }\n\n if (currentCtx.tokenCount > currentCtx.maxTokens) {\n throw new LemuraContextOverflowError(\n `Context overflowed: ${currentCtx.tokenCount} tokens > ${currentCtx.maxTokens}`\n );\n }\n\n return currentCtx;\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\nexport interface SandwichCompressionConfig {\n preserveFirst: number;\n preserveLast: number;\n /** Fire when context reaches this fraction of maxTokens (e.g. 0.80 = 80%). Default: 0.80 */\n triggerThreshold?: number;\n /** Max tokens for the generated summary turn. Default: unlimited */\n summaryMaxTokens?: number;\n /** Strategy execution priority — lower number runs first. Default: 20 */\n priority?: number;\n}\n\n/**\n * Sandwich compression preserves the beginning and end of the conversation,\n * replacing the middle with a generated summary.\n *\n * Pair with `SummaryInjectionStrategy` to ensure the compression summary is\n * visible to the model on every subsequent call.\n */\nexport class SandwichCompressionStrategy implements IContextStrategy {\n readonly name = 'sandwich_compression';\n readonly priority: number;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: SandwichCompressionConfig\n ) {\n this.priority = config.priority ?? 20;\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n const threshold = this.config.triggerThreshold ?? 0.80;\n return (\n ctx.tokenCount >= ctx.maxTokens * threshold &&\n ctx.turns.length > this.config.preserveFirst + this.config.preserveLast\n );\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const { preserveFirst, preserveLast } = this.config;\n\n const head = ctx.turns.slice(0, preserveFirst);\n const tail = ctx.turns.slice(ctx.turns.length - preserveLast);\n const middle = ctx.turns.slice(preserveFirst, ctx.turns.length - preserveLast);\n\n const middleText = middle.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the following conversation history briefly:\\n${middleText}`\n }],\n ...(this.config.summaryMaxTokens ? { maxTokens: this.config.summaryMaxTokens } : {})\n });\n\n const summaryStr = summaryResponse.content;\n\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n const summaryTurn: Turn = {\n role: 'system',\n content: `[COMPRESSED HISTORY SUMMARY]\\n${newCompressionSummary}`,\n tokenCount: this.adapter.estimateTokens(newCompressionSummary),\n turnIndex: -1,\n compressed: true,\n };\n\n const newTurns = [...head, summaryTurn, ...tail];\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n\n /**\n * Applies sandwich compression specifically to a Short Term Memory item's content.\n * Implements a 3-layer pipeline: Pre-Layer (encoding), Core Layer (dense summary), Post-Layer (refinement cues).\n * \n * @param content - The heavy text content to compress\n * @param instructions - Guiding instructions for the core layer summary\n * @returns The three-layer sandwich result\n */\n async compressMemoryItem(content: string, instructions: string = 'Extract the key information'): Promise<{\n preLayer: string;\n coreLayer: string;\n postLayer: string;\n }> {\n // Pre-Layer: Chunking and initial encoding\n // Here we do a naive encoding representation to signify the pre-processed chunks\n const estimatedChunks = Math.max(1, Math.ceil(this.adapter.estimateTokens(content) / 2000));\n const preLayer = `[PRE-LAYER ENCODED: ${estimatedChunks} internal chunks]`;\n\n // Core Layer: Dense summary sandwich with instructions\n // We sandwich the content between the instructions to guide extraction\n // If content is extremely large, we might trim it here, but ideally the provider streaming handles it.\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `### INSTRUCTIONS ###\\n${instructions}\\n\\n### CONTENT ###\\n${content}\\n\\n### INSTRUCTIONS ###\\n${instructions}`\n }]\n });\n const coreLayer = summaryResponse.content;\n\n // Post-Layer: Decoding/Refinement hooks\n // Indicates that the LLM can use tools to drill down into specific chunks\n const postLayer = `[POST-LAYER DECODING: Use \\`refine_layer\\` or \\`read_chunk\\` tools to expand specific sections]`;\n\n return { preLayer, coreLayer, postLayer };\n }\n}\n","import { ContextWindow, IContextStrategy, IProviderAdapter, Turn } from '../types/index.js';\n\n/**\n * ScratchpadStrategy manages the thinking process separate from the turn history.\n * It is primarily a marker/pre-turn strategy that ensures scratchpad gets tokenized properly\n * but is not compressed.\n */\nexport class ScratchpadStrategy implements IContextStrategy {\n readonly name = 'scratchpad_strategy';\n readonly priority = 10;\n\n shouldApply(ctx: ContextWindow): boolean {\n // Only apply if there's actual scratchpad content to track\n return ctx.scratchpad.length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Basic implementation: we don't compress the scratchpad, we just ensure its tokens are counted\n return ctx;\n }\n}\n\nexport interface HistoryCompressionConfig {\n /** Number of oldest turns to summarize in each compression pass */\n windowSize: number;\n /** Fire when context reaches this fraction of maxTokens (e.g. 0.8 = 80%) */\n triggerAtPercent: number;\n /** Strategy execution priority — lower number runs first. Default: 30 */\n priority?: number;\n}\n\n/**\n * Summarizes the oldest N uncompressed turns using a rolling-window approach.\n *\n * Pair with `SummaryInjectionStrategy` (priority < this one) to ensure the\n * accumulated summary is re-injected before each provider call.\n */\nexport class HistoryCompressionStrategy implements IContextStrategy {\n readonly name = 'history_compression';\n readonly priority: number;\n\n constructor(\n private adapter: IProviderAdapter,\n private config: HistoryCompressionConfig\n ) {\n this.priority = config.priority ?? 30;\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n const triggerTokens = ctx.maxTokens * this.config.triggerAtPercent;\n // Apply if we are over the trigger threshold and have at least enough turns\n // Ignore system prompts and already compressed turns\n const uncompressedTurns = ctx.turns.filter(t => t.role !== 'system' && !t.compressed);\n return ctx.tokenCount >= triggerTokens && uncompressedTurns.length > this.config.windowSize;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n // Find the oldest N uncompressed turns that aren't the system prompt\n const uncompressedIndices = ctx.turns\n .map((t, i) => ({ t, i }))\n .filter(({ t }) => t.role !== 'system' && !t.compressed)\n .slice(0, this.config.windowSize);\n\n const targetTurns = uncompressedIndices.map(u => u.t);\n const middleText = targetTurns.map(t => `${t.role}: ${JSON.stringify(t.content)}`).join('\\n');\n\n const summaryResponse = await this.adapter.complete({\n model: '',\n messages: [{\n role: 'user',\n content: `Summarize the oldest part of this conversation:\\n${middleText}`\n }]\n });\n\n const summaryStr = summaryResponse.content;\n const newCompressionSummary = ctx.compressionSummary\n ? `${ctx.compressionSummary}\\n${summaryStr}`\n : summaryStr;\n\n // Filter out the summarized turns\n const indicesToRemove = new Set(uncompressedIndices.map(u => u.i));\n const newTurns = ctx.turns.filter((_, i) => !indicesToRemove.has(i));\n\n const TokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0) +\n this.adapter.estimateTokens(ctx.systemPrompt) +\n this.adapter.estimateTokens(ctx.scratchpad);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: TokenCount,\n compressionSummary: newCompressionSummary,\n };\n }\n}\n","import { ContextWindow, IContextStrategy, Turn } from '../types/index.js';\n\nexport interface SummaryInjectionConfig {\n /** Strategy priority — lower number runs first. Default: 1 (runs before compression). */\n priority?: number;\n /** Label prepended to the injected summary block. */\n label?: string;\n}\n\n/**\n * SummaryInjectionStrategy ensures that whenever a `compressionSummary` exists on\n * the context window, it is re-injected as a synthetic system turn at the beginning\n * of the turn list before each provider call.\n *\n * **Why this matters:** `HistoryCompressionStrategy` and `SandwichCompressionStrategy`\n * store compressed context in `ctx.compressionSummary`, but without this strategy the\n * summary never reaches the model — the pruned turns are simply gone.\n *\n * Pair this with any compression strategy:\n *\n * @example\n * ```typescript\n * compressionStrategies: [\n * new SummaryInjectionStrategy({ priority: 1 }), // always runs first\n * new SandwichCompressionStrategy(adapter, { priority: 2, triggerThreshold: 0.80 }),\n * ]\n * ```\n *\n * The strategy is idempotent: if a summary turn already exists it is updated in-place\n * rather than appended again.\n */\nexport class SummaryInjectionStrategy implements IContextStrategy {\n readonly name = 'summary_injection';\n readonly priority: number;\n\n private readonly label: string;\n\n constructor(config: SummaryInjectionConfig = {}) {\n this.priority = config.priority ?? 1;\n this.label = config.label ?? 'Earlier conversation summary';\n }\n\n shouldApply(ctx: ContextWindow): boolean {\n return !!ctx.compressionSummary && ctx.compressionSummary.trim().length > 0;\n }\n\n async apply(ctx: ContextWindow): Promise<ContextWindow> {\n const summaryContent = `[${this.label}]\\n${ctx.compressionSummary}`;\n const summaryTokenCount = Math.ceil(summaryContent.length / 4);\n\n // Check if a summary turn already exists (role=system, compressed=true at turnIndex=-1)\n const existingIndex = ctx.turns.findIndex(t => t.compressed && t.role === 'system' && t.turnIndex === -1);\n\n let newTurns: Turn[];\n\n if (existingIndex !== -1) {\n // Update the existing summary turn in-place\n newTurns = ctx.turns.map((t, i) => {\n if (i !== existingIndex) return t;\n return {\n ...t,\n content: summaryContent,\n tokenCount: summaryTokenCount,\n };\n });\n } else {\n // Prepend a new summary turn\n const summaryTurn: Turn = {\n role: 'system',\n content: summaryContent,\n tokenCount: summaryTokenCount,\n turnIndex: -1,\n compressed: true,\n };\n newTurns = [summaryTurn, ...ctx.turns];\n }\n\n // Recalculate token count\n const newTokenCount = newTurns.reduce((sum, t) => sum + t.tokenCount, 0);\n\n return {\n ...ctx,\n turns: newTurns,\n tokenCount: newTokenCount,\n };\n }\n}\n","import { IStorageAdapter, STMItem } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface STMRegistryConfig {\n /**\n * The storage backend to use for Short Term Memory items.\n */\n storage: IStorageAdapter;\n\n /**\n * The maximum number of tokens allowed for a 'text' type STM item.\n * If an item exceeds this, it may be rejected or truncated.\n * Default: 100000\n */\n maxTextTokens?: number;\n}\n\n/**\n * Registry for Short Term Memory (STM).\n * Manages the storage and retrieval of large context variables like long texts or blobs.\n * Generates '[STM:uuid]' references to be used within the ReAct agent context.\n */\nexport class ShortTermMemoryRegistry {\n private storage: IStorageAdapter;\n private maxTextTokens: number;\n\n constructor(config: STMRegistryConfig) {\n this.storage = config.storage;\n this.maxTextTokens = config.maxTextTokens ?? 100000;\n }\n\n /**\n * Registers a new memory item and returns its reference string.\n * \n * @param content - The raw content to store\n * @param type - The type of content ('text' or 'blob')\n * @param metadata - Optional metadata (e.g. sandwich layers, original filename)\n * @param estimateTokens - Optional function to estimate token count for 'text' type\n * @returns A reference string formatted as '[STM:uuid]'\n * @throws {Error} if a text item exceeds the maxTextTokens limit\n */\n async register(\n content: any,\n type: 'text' | 'blob',\n metadata?: Record<string, unknown>,\n estimateTokens?: (text: string) => number\n ): Promise<string> {\n if (type === 'text') {\n const tokenCount = estimateTokens ? estimateTokens(content) : Math.ceil(String(content).length / 4);\n if (tokenCount > this.maxTextTokens) {\n throw new Error(`Text content exceeds max tokens limit of ${this.maxTextTokens} (estimated ${tokenCount})`);\n }\n }\n\n const id = randomUUID();\n const item: STMItem = {\n id,\n content,\n type,\n ...(metadata !== undefined ? { metadata } : {})\n };\n\n await this.storage.set(id, item);\n return `[STM:${id}]`;\n }\n\n /**\n * Updates an existing STM item's content or metadata.\n * \n * @param id - The UUID of the item to update\n * @param updates - Partial updates to apply (content or metadata)\n */\n async update(id: string, updates: { content?: any; metadata?: Record<string, unknown> }): Promise<void> {\n const item = await this.storage.get(id);\n if (!item) throw new Error(`STM item not found for update: ${id}`);\n\n const updatedItem: STMItem = {\n ...item,\n ...(updates.content !== undefined ? { content: updates.content } : {}),\n ...(updates.metadata !== undefined ? { metadata: { ...item.metadata, ...updates.metadata } } : {})\n };\n\n await this.storage.set(id, updatedItem);\n }\n\n\n /**\n * Retrieves an STM item by its full reference string (e.g., '[STM:uuid]').\n * \n * @param ref - The full reference string\n * @returns The STMItem or undefined if not found\n */\n async getByRef(ref: string): Promise<STMItem | undefined> {\n const match = ref.match(/^\\[STM:(.+)\\]$/);\n if (!match || !match[1]) return undefined;\n return this.storage.get(match[1]);\n }\n\n /**\n * Deletes an STM item by its ID.\n * \n * @param id - The UUID of the item to delete\n */\n async delete(id: string): Promise<void> {\n await this.storage.delete(id);\n }\n}\n","import { IStorageAdapter } from '../types/index.js';\nimport { randomUUID } from 'crypto';\n\n/**\n * An in-memory implementation of IStorageAdapter for holding Short Term Memory.\n * Ideal for testing or single-process lightweight usage.\n *\n * @example\n * const storage = new InMemoryStorageAdapter();\n * const id = await storage.set(undefined, 'my content', { type: 'text' });\n * const retrieved = await storage.get(id);\n */\nexport class InMemoryStorageAdapter implements IStorageAdapter {\n private store = new Map<string, { content: any; metadata?: Record<string, unknown> }>();\n\n /**\n * Retrieves stored content by ID.\n *\n * @param id - The identifier of the stored item\n * @returns The stored content or undefined if not found\n */\n async get(id: string): Promise<any | undefined> {\n return this.store.get(id)?.content;\n }\n\n /**\n * Returns the full item including metadata.\n *\n * @param id - The identifier of the stored item\n * @returns The complete item with content and metadata\n * @internal\n */\n async getFull(id: string): Promise<{ content: any; metadata?: Record<string, unknown> } | undefined> {\n return this.store.get(id);\n }\n\n /**\n * Stores content, generating an ID if none is provided.\n *\n * @param id - Optional provided ID. If omitted, a UUID is generated.\n * @param content - The content to store\n * @param metadata - Optional metadata\n * @returns The ID under which the content is stored\n */\n async set(id: string | undefined, content: any, metadata?: Record<string, unknown>): Promise<string> {\n const resolvedId = id ?? randomUUID();\n this.store.set(resolvedId, metadata !== undefined ? { content, metadata } : { content });\n return resolvedId;\n }\n\n /**\n * Deletes the content for the given ID.\n *\n * @param id - The identifier of the item to delete\n */\n async delete(id: string): Promise<void> {\n this.store.delete(id);\n }\n\n /**\n * Synchronous health check, always true for in-memory.\n *\n * @returns true\n */\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n","import { IScratchpadAdapter } from '../types/index.js';\n\n/**\n * In-memory scratchpad adapter, keyed by sessionId.\n * Ideal for testing or single-process usage.\n */\nexport class InMemoryScratchpadAdapter implements IScratchpadAdapter {\n private store = new Map<string, string>();\n\n async read(sessionId: string): Promise<string | undefined> {\n return this.store.get(sessionId);\n }\n\n async write(sessionId: string, content: string): Promise<void> {\n this.store.set(sessionId, content);\n }\n\n async clear(sessionId: string): Promise<void> {\n this.store.delete(sessionId);\n }\n\n async healthCheck(): Promise<boolean> {\n return true;\n }\n}\n"]}