@bd7pil/opencode-deep-memory 0.4.2 → 0.4.3

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.
package/dist/index.js CHANGED
@@ -390,6 +390,10 @@ var PluginState = class {
390
390
  return this._toolSignatures.get(callID);
391
391
  }
392
392
  ccStore(hash2, entry) {
393
+ const now = Date.now();
394
+ for (const [k, v] of this._ccrCache) {
395
+ if (now - v.createdAt > 3e5) this._ccrCache.delete(k);
396
+ }
393
397
  if (this._ccrCache.size > 200) {
394
398
  const oldest = [...this._ccrCache.entries()].sort((a, b) => a[1].createdAt - b[1].createdAt).slice(0, 50);
395
399
  for (const [k] of oldest) this._ccrCache.delete(k);
@@ -15366,11 +15370,17 @@ function deduplicateToolOutputs(messages, state) {
15366
15370
  return deduped;
15367
15371
  }
15368
15372
  function simpleHash(s) {
15369
- let h = 0;
15370
- for (let i = 0; i < Math.min(s.length, 1e3); i++) {
15373
+ const len = s.length;
15374
+ const sampleSize = 500;
15375
+ let h = len;
15376
+ for (let i = 0; i < Math.min(len, sampleSize); i++) {
15377
+ h = h * 31 + s.charCodeAt(i) | 0;
15378
+ }
15379
+ const tailStart = Math.max(sampleSize, len - sampleSize);
15380
+ for (let i = tailStart; i < len; i++) {
15371
15381
  h = h * 31 + s.charCodeAt(i) | 0;
15372
15382
  }
15373
- return h.toString(36);
15383
+ return `${len}:${h.toString(36)}`;
15374
15384
  }
15375
15385
 
15376
15386
  // src/compress/error-purge.ts
@@ -15562,7 +15572,8 @@ function pruneOldMessages(messages) {
15562
15572
  if (p["type"] !== "text" || typeof p["text"] !== "string") continue;
15563
15573
  const text = p["text"];
15564
15574
  if (text.length < 500) continue;
15565
- if (text === "[cleared]" || text === "[stripped]" || text.startsWith("[compressed")) continue;
15575
+ if (text === "[cleared]" || text === "[stripped]") continue;
15576
+ if (text.includes("[compressed from")) continue;
15566
15577
  const keyInfo = extractKeyInfo(text);
15567
15578
  if (keyInfo.length < text.length * 0.6) {
15568
15579
  p["text"] = keyInfo + "\n[compressed from " + text.length + " chars]";
@@ -15678,7 +15689,7 @@ function detectContentType(content) {
15678
15689
  if (/Traceback \(most recent call last\)|at \S+\.\S+\(|Error: |Exception: |TypeError: |ReferenceError: /m.test(content)) return "error-trace";
15679
15690
  if (/<[a-z][\s\S]*>/i.test(content) && /<(html|div|span|body|head|script|style)[\s>]/i.test(content)) return "html";
15680
15691
  const lines = content.split("\n");
15681
- const logLineCount = lines.filter((l) => /^\d{4}-\d{2}-\d{2}|^\[\d{4}|ERROR|WARN|INFO|DEBUG|FATAL|TRACE/.test(l)).length;
15692
+ const logLineCount = lines.filter((l) => /^\s*(\d{4}-\d{2}-\d{2}|\[\d{4}|ERROR\b|WARN\b|INFO\b|DEBUG\b|FATAL\b|TRACE\b)/.test(l)).length;
15682
15693
  if (lines.length > 5 && logLineCount / lines.length > 0.3) return "log";
15683
15694
  const codePatterns = /\b(function |class |def |import |from .+ import|const |let |var |export |interface |type |struct |fn |func |pub |private |protected )\b/;
15684
15695
  const codeLines = lines.filter((l) => codePatterns.test(l)).length;
@@ -15704,39 +15715,23 @@ function runCompressionPipeline(ctx) {
15704
15715
  };
15705
15716
  stats.toolDedup = deduplicateToolOutputs(messages, state);
15706
15717
  stats.errorPurge = purgeOldErrors(messages);
15707
- stats.toolOutputCompressed = compressOldToolOutputs(messages, state);
15708
15718
  stats.jsonCrushed = crushJsonToolOutputs(messages, state);
15719
+ stats.toolOutputCompressed = compressOldToolOutputs(messages, state);
15709
15720
  if (pressure.level === "medium" || pressure.level === "high") {
15710
15721
  stats.messagePruned = pruneOldMessages(messages);
15711
15722
  }
15712
15723
  const messagesSinceNudge = state.messagesSinceLastNudge(messages.length);
15713
15724
  if (shouldInjectNudge(pressure.level, messagesSinceNudge)) {
15714
- const lastMsg = messages[messages.length - 1];
15715
- if (lastMsg) {
15716
- const textParts = lastMsg.parts.filter(
15717
- (p) => typeof p === "object" && p !== null && p.type === "text"
15718
- );
15719
- const lastTextPart = textParts[textParts.length - 1];
15720
- if (lastTextPart && typeof lastTextPart.text === "string") {
15721
- lastTextPart.text += buildNudgeText(pressure.level);
15722
- stats.nudgeInjected = true;
15723
- state.recordNudge(messages.length);
15724
- }
15725
+ if (injectIntoLastAssistant(messages, buildNudgeText(pressure.level))) {
15726
+ stats.nudgeInjected = true;
15727
+ state.recordNudge(messages.length);
15725
15728
  }
15726
15729
  }
15727
15730
  const memoryNudge = detectMemoryNudge(messages, state.messagesSinceLastNudge(messages.length));
15728
15731
  if (memoryNudge.injected) {
15729
- const lastMsg = messages[messages.length - 1];
15730
- if (lastMsg) {
15731
- const textParts = lastMsg.parts.filter(
15732
- (p) => typeof p === "object" && p !== null && p.type === "text"
15733
- );
15734
- const lastTextPart = textParts[textParts.length - 1];
15735
- if (lastTextPart && typeof lastTextPart.text === "string") {
15736
- lastTextPart.text += buildMemoryNudge(memoryNudge.type);
15737
- state.recordNudge(messages.length);
15738
- logger?.debug("compress: memory nudge", { type: memoryNudge.type });
15739
- }
15732
+ if (injectIntoLastAssistant(messages, buildMemoryNudge(memoryNudge.type))) {
15733
+ state.recordNudge(messages.length);
15734
+ logger?.debug("compress: memory nudge", { type: memoryNudge.type });
15740
15735
  }
15741
15736
  }
15742
15737
  const active = stats.toolDedup > 0 || stats.errorPurge > 0 || stats.toolOutputCompressed > 0 || stats.jsonCrushed > 0 || stats.messagePruned > 0 || stats.nudgeInjected;
@@ -15747,6 +15742,21 @@ function runCompressionPipeline(ctx) {
15747
15742
  }
15748
15743
  return { stats };
15749
15744
  }
15745
+ function injectIntoLastAssistant(messages, text) {
15746
+ for (let i = messages.length - 1; i >= 0; i--) {
15747
+ const msg = messages[i];
15748
+ if (msg.info.role !== "assistant") continue;
15749
+ const textParts = msg.parts.filter(
15750
+ (p) => typeof p === "object" && p !== null && p.type === "text"
15751
+ );
15752
+ const lastTextPart = textParts[textParts.length - 1];
15753
+ if (lastTextPart && typeof lastTextPart.text === "string") {
15754
+ lastTextPart.text += text;
15755
+ return true;
15756
+ }
15757
+ }
15758
+ return false;
15759
+ }
15750
15760
  function compressOldToolOutputs(messages, state) {
15751
15761
  let compressed = 0;
15752
15762
  const protectedTail = messages.length - 8;
@@ -15759,7 +15769,6 @@ function compressOldToolOutputs(messages, state) {
15759
15769
  if (p.state?.status !== "completed") continue;
15760
15770
  if (!p.state.output) continue;
15761
15771
  if (p.state.output === "[superseded by duplicate call]") continue;
15762
- if (p.state.output.startsWith("[compressed")) continue;
15763
15772
  if (p.state.output.includes("[ccr:")) continue;
15764
15773
  const toolName = p.tool || "unknown";
15765
15774
  const output = p.state.output;
@@ -15784,7 +15793,6 @@ function crushJsonToolOutputs(messages, state) {
15784
15793
  if (p.type !== "tool") continue;
15785
15794
  if (p.state?.status !== "completed") continue;
15786
15795
  if (!p.state.output) continue;
15787
- if (p.state.output.startsWith("[compressed")) continue;
15788
15796
  if (p.state.output.startsWith("[superseded")) continue;
15789
15797
  if (p.state.output.includes("[ccr:")) continue;
15790
15798
  if (detectContentType(p.state.output) !== "json") continue;