@bd7pil/opencode-deep-memory 0.6.0 → 0.7.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.
- package/dist/index.js +85 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15284,12 +15284,10 @@ function createCompactingHandler(args) {
|
|
|
15284
15284
|
}
|
|
15285
15285
|
|
|
15286
15286
|
// src/compress/pressure.ts
|
|
15287
|
-
var FALLBACK_MAX_CONTEXT =
|
|
15287
|
+
var FALLBACK_MAX_CONTEXT = 1e6;
|
|
15288
15288
|
var OPENCODE_COMPACTION_RATIO = 0.75;
|
|
15289
|
-
var
|
|
15290
|
-
|
|
15291
|
-
high: 0.4
|
|
15292
|
-
};
|
|
15289
|
+
var PRESSURE_MEDIUM_TOKENS = 5e4;
|
|
15290
|
+
var PRESSURE_HIGH_TOKENS = 15e4;
|
|
15293
15291
|
var calibratedMaxContext = 0;
|
|
15294
15292
|
function calibrateFromCompaction(lastInputTokens) {
|
|
15295
15293
|
if (lastInputTokens <= 0) return;
|
|
@@ -15303,67 +15301,33 @@ function maxContextFrom(modelContextWindow) {
|
|
|
15303
15301
|
if (calibratedMaxContext > 0) return calibratedMaxContext;
|
|
15304
15302
|
return FALLBACK_MAX_CONTEXT;
|
|
15305
15303
|
}
|
|
15306
|
-
function estimateTokens2(text) {
|
|
15307
|
-
let cjk = 0;
|
|
15308
|
-
let other = 0;
|
|
15309
|
-
for (const ch of text) {
|
|
15310
|
-
if (/[\u4e00-\u9fff\u3400-\u4dbf\u3000-\u303f\uff00-\uffef\u3040-\u309f\u30a0-\u30ff]/.test(ch)) {
|
|
15311
|
-
cjk++;
|
|
15312
|
-
} else {
|
|
15313
|
-
other++;
|
|
15314
|
-
}
|
|
15315
|
-
}
|
|
15316
|
-
return Math.ceil(cjk * 0.7 + other / 3.8);
|
|
15317
|
-
}
|
|
15318
|
-
function extractTokensFromMessages(messages) {
|
|
15319
|
-
let total = 0;
|
|
15320
|
-
for (const msg of messages) {
|
|
15321
|
-
for (const part of msg.parts) {
|
|
15322
|
-
if (typeof part !== "object" || part === null) continue;
|
|
15323
|
-
const p = part;
|
|
15324
|
-
if (p["type"] === "text" && typeof p["text"] === "string") {
|
|
15325
|
-
total += estimateTokens2(p["text"]);
|
|
15326
|
-
} else if (p["type"] === "tool") {
|
|
15327
|
-
const state = p["state"];
|
|
15328
|
-
if (state?.["output"] && typeof state["output"] === "string") {
|
|
15329
|
-
total += estimateTokens2(state["output"]);
|
|
15330
|
-
}
|
|
15331
|
-
if (state?.["error"] && typeof state["error"] === "string") {
|
|
15332
|
-
total += estimateTokens2(state["error"]);
|
|
15333
|
-
}
|
|
15334
|
-
} else if (p["type"] === "reasoning" || p["type"] === "thinking") {
|
|
15335
|
-
if (typeof p["text"] === "string") {
|
|
15336
|
-
total += estimateTokens2(p["text"]);
|
|
15337
|
-
}
|
|
15338
|
-
}
|
|
15339
|
-
}
|
|
15340
|
-
}
|
|
15341
|
-
return total;
|
|
15342
|
-
}
|
|
15343
15304
|
function extractInputTokensFromMessages(messages) {
|
|
15305
|
+
let best = 0;
|
|
15344
15306
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
15345
15307
|
const msg = messages[i];
|
|
15346
15308
|
for (const part of msg.parts) {
|
|
15347
15309
|
if (typeof part !== "object" || part === null) continue;
|
|
15348
15310
|
const p = part;
|
|
15349
15311
|
if (p["type"] === "step-finish") {
|
|
15350
|
-
const tokens = p
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15312
|
+
const tokens = p;
|
|
15313
|
+
const input = tokens.tokens?.input ?? 0;
|
|
15314
|
+
const cached2 = tokens.tokens?.cached ?? 0;
|
|
15315
|
+
const total = input + cached2;
|
|
15316
|
+
if (total > best) best = total;
|
|
15317
|
+
if (best > 0) return best;
|
|
15354
15318
|
}
|
|
15355
15319
|
}
|
|
15356
15320
|
}
|
|
15357
|
-
return
|
|
15321
|
+
return best;
|
|
15358
15322
|
}
|
|
15359
15323
|
function detectPressure(messages, modelContextWindow) {
|
|
15360
15324
|
const ctx = maxContextFrom(modelContextWindow || 0);
|
|
15361
15325
|
const inputTokens = extractInputTokensFromMessages(messages);
|
|
15362
|
-
const estimated = inputTokens > 0 ? inputTokens :
|
|
15326
|
+
const estimated = inputTokens > 0 ? inputTokens : 0;
|
|
15363
15327
|
const ratio = Math.min(estimated / ctx, 1);
|
|
15364
15328
|
let level;
|
|
15365
|
-
if (
|
|
15366
|
-
else if (
|
|
15329
|
+
if (estimated >= PRESSURE_HIGH_TOKENS) level = "high";
|
|
15330
|
+
else if (estimated >= PRESSURE_MEDIUM_TOKENS) level = "medium";
|
|
15367
15331
|
else level = "low";
|
|
15368
15332
|
return { level, ratio, estimatedTokens: estimated, maxContext: ctx };
|
|
15369
15333
|
}
|
|
@@ -15627,6 +15591,8 @@ var PROTECTED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
15627
15591
|
var NEVER_DEDUP = /* @__PURE__ */ new Set(["read", "bash", "grep", "glob", "find", "search"]);
|
|
15628
15592
|
var ERROR_PURGE_TURN_THRESHOLD = 4;
|
|
15629
15593
|
var PROTECTED_HEAD_SINGLE = 2;
|
|
15594
|
+
var ASSISTANT_COMPRESS_MIN_LENGTH = 500;
|
|
15595
|
+
var ASSISTANT_COMPRESS_SAVINGS_RATIO = 0.6;
|
|
15630
15596
|
function simpleHash(s) {
|
|
15631
15597
|
const len = s.length;
|
|
15632
15598
|
const sampleSize = 500;
|
|
@@ -15640,12 +15606,32 @@ function simpleHash(s) {
|
|
|
15640
15606
|
}
|
|
15641
15607
|
return `${len}:${h.toString(36)}`;
|
|
15642
15608
|
}
|
|
15609
|
+
function compressAssistantText(text) {
|
|
15610
|
+
if (text.length < ASSISTANT_COMPRESS_MIN_LENGTH) return text;
|
|
15611
|
+
const lines = text.split("\n");
|
|
15612
|
+
const head = 3;
|
|
15613
|
+
const tail = 3;
|
|
15614
|
+
const kept = [];
|
|
15615
|
+
for (let i = 0; i < lines.length; i++) {
|
|
15616
|
+
const line = lines[i];
|
|
15617
|
+
if (i < head || i >= lines.length - tail) {
|
|
15618
|
+
kept.push(line);
|
|
15619
|
+
continue;
|
|
15620
|
+
}
|
|
15621
|
+
if (/^#{1,3}\s/.test(line) || /error|fail|warning|critical|important/i.test(line) || /^\s*[-*]\s/.test(line) || /^\s*\d+\.\s/.test(line) || line.trim().startsWith("```") || /^\/[^\s:]+/.test(line)) {
|
|
15622
|
+
kept.push(line);
|
|
15623
|
+
}
|
|
15624
|
+
}
|
|
15625
|
+
const result = kept.join("\n");
|
|
15626
|
+
return result.length < text.length * ASSISTANT_COMPRESS_SAVINGS_RATIO ? result : text;
|
|
15627
|
+
}
|
|
15643
15628
|
function singlePassCompress(messages, state, protectedTail) {
|
|
15644
15629
|
const stats = {
|
|
15645
15630
|
toolDedup: 0,
|
|
15646
15631
|
errorPurge: 0,
|
|
15647
15632
|
toolOutputCompressed: 0,
|
|
15648
15633
|
jsonCrushed: 0,
|
|
15634
|
+
assistantCompressed: 0,
|
|
15649
15635
|
ccrStored: 0
|
|
15650
15636
|
};
|
|
15651
15637
|
const totalMessages = messages.length;
|
|
@@ -15725,6 +15711,21 @@ function singlePassCompress(messages, state, protectedTail) {
|
|
|
15725
15711
|
}
|
|
15726
15712
|
}
|
|
15727
15713
|
}
|
|
15714
|
+
if (i < protectedTail && msg.info.role === "assistant") {
|
|
15715
|
+
for (let j = msg.parts.length - 1; j >= 0; j--) {
|
|
15716
|
+
const part = msg.parts[j];
|
|
15717
|
+
if (typeof part !== "object" || part === null) continue;
|
|
15718
|
+
const p = part;
|
|
15719
|
+
if (p["type"] !== "text") continue;
|
|
15720
|
+
const text = p["text"];
|
|
15721
|
+
if (typeof text !== "string") continue;
|
|
15722
|
+
const compressed = compressAssistantText(text);
|
|
15723
|
+
if (compressed !== text) {
|
|
15724
|
+
p["text"] = compressed;
|
|
15725
|
+
stats.assistantCompressed++;
|
|
15726
|
+
}
|
|
15727
|
+
}
|
|
15728
|
+
}
|
|
15728
15729
|
}
|
|
15729
15730
|
return stats;
|
|
15730
15731
|
}
|
|
@@ -15766,6 +15767,7 @@ function runCompressionPipeline(ctx) {
|
|
|
15766
15767
|
errorPurge: spStats.errorPurge,
|
|
15767
15768
|
toolOutputCompressed: spStats.toolOutputCompressed,
|
|
15768
15769
|
jsonCrushed: spStats.jsonCrushed,
|
|
15770
|
+
assistantCompressed: spStats.assistantCompressed,
|
|
15769
15771
|
ccrStored: spStats.ccrStored,
|
|
15770
15772
|
nudgeInjected: false,
|
|
15771
15773
|
pressureLevel: pressure.level,
|
|
@@ -15786,7 +15788,7 @@ function runCompressionPipeline(ctx) {
|
|
|
15786
15788
|
logger?.debug("compress: memory nudge", { type: memoryNudge.type });
|
|
15787
15789
|
}
|
|
15788
15790
|
}
|
|
15789
|
-
const active = stats.toolDedup > 0 || stats.errorPurge > 0 || stats.toolOutputCompressed > 0 || stats.jsonCrushed > 0 || stats.nudgeInjected;
|
|
15791
|
+
const active = stats.toolDedup > 0 || stats.errorPurge > 0 || stats.toolOutputCompressed > 0 || stats.jsonCrushed > 0 || stats.assistantCompressed > 0 || stats.nudgeInjected;
|
|
15790
15792
|
if (active) {
|
|
15791
15793
|
logger?.debug("compress: pipeline result", { ...stats });
|
|
15792
15794
|
} else {
|
|
@@ -15976,7 +15978,7 @@ function createMessagesTransformHandler(state, logger) {
|
|
|
15976
15978
|
logger
|
|
15977
15979
|
});
|
|
15978
15980
|
const ds = pipelineResult.stats;
|
|
15979
|
-
if (ds.toolDedup > 0 || ds.errorPurge > 0 || ds.toolOutputCompressed > 0 || ds.jsonCrushed > 0 || ds.nudgeInjected) {
|
|
15981
|
+
if (ds.toolDedup > 0 || ds.errorPurge > 0 || ds.toolOutputCompressed > 0 || ds.jsonCrushed > 0 || ds.assistantCompressed > 0 || ds.nudgeInjected) {
|
|
15980
15982
|
logger?.debug("messages.transform: deep compression", { ...ds });
|
|
15981
15983
|
state.mergeNotify({
|
|
15982
15984
|
compression: stats,
|
|
@@ -16116,6 +16118,29 @@ function createNotifyHandler(client, logger) {
|
|
|
16116
16118
|
};
|
|
16117
16119
|
}
|
|
16118
16120
|
|
|
16121
|
+
// src/shared/model-limits.ts
|
|
16122
|
+
var KNOWN_MODEL_LIMITS = {
|
|
16123
|
+
"deepseek-v4-pro": 1e6,
|
|
16124
|
+
"deepseek-v4": 1e6,
|
|
16125
|
+
"deepseek-v3": 64e3,
|
|
16126
|
+
"deepseek-r1": 64e3,
|
|
16127
|
+
"claude-opus-4": 2e5,
|
|
16128
|
+
"claude-sonnet-4": 2e5,
|
|
16129
|
+
"gpt-4o": 128e3,
|
|
16130
|
+
"o1": 2e5,
|
|
16131
|
+
"o3-mini": 2e5,
|
|
16132
|
+
"gemini-2.5-pro": 1e6,
|
|
16133
|
+
"gemini-2.5-flash": 1e6,
|
|
16134
|
+
"qwen-max": 131072
|
|
16135
|
+
};
|
|
16136
|
+
function lookupModelLimit(modelID) {
|
|
16137
|
+
if (KNOWN_MODEL_LIMITS[modelID]) return KNOWN_MODEL_LIMITS[modelID];
|
|
16138
|
+
for (const [key, limit] of Object.entries(KNOWN_MODEL_LIMITS)) {
|
|
16139
|
+
if (modelID.includes(key)) return limit;
|
|
16140
|
+
}
|
|
16141
|
+
return void 0;
|
|
16142
|
+
}
|
|
16143
|
+
|
|
16119
16144
|
// src/extract/enrich.ts
|
|
16120
16145
|
import { stat } from "fs/promises";
|
|
16121
16146
|
|
|
@@ -16447,11 +16472,14 @@ var deepMemoryPlugin = async (input) => {
|
|
|
16447
16472
|
const defaultModel = configResult.data?.model;
|
|
16448
16473
|
if (typeof defaultModel === "string" && defaultModel.includes("/")) {
|
|
16449
16474
|
const slashIdx = defaultModel.indexOf("/");
|
|
16450
|
-
|
|
16451
|
-
|
|
16452
|
-
|
|
16453
|
-
|
|
16454
|
-
|
|
16475
|
+
const providerID = defaultModel.slice(0, slashIdx);
|
|
16476
|
+
const modelID = defaultModel.slice(slashIdx + 1);
|
|
16477
|
+
state.recordFallbackModel({ providerID, modelID });
|
|
16478
|
+
const limit = lookupModelLimit(modelID);
|
|
16479
|
+
if (limit) {
|
|
16480
|
+
state.setModelContextWindow(limit);
|
|
16481
|
+
logger.debug("resolved model context window", { modelID, limit });
|
|
16482
|
+
}
|
|
16455
16483
|
}
|
|
16456
16484
|
}).catch((err) => {
|
|
16457
16485
|
logger.debug("config.get failed, dream/distill will omit model", {
|