@bd7pil/opencode-deep-memory 0.4.3 → 0.5.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 +48 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -261,6 +261,7 @@ var PluginState = class {
|
|
|
261
261
|
_ccrCache = /* @__PURE__ */ new Map();
|
|
262
262
|
_lastInputTokens = 0;
|
|
263
263
|
_lastNudgeMessageCount = 0;
|
|
264
|
+
_modelContextWindow = 0;
|
|
264
265
|
agentOf(sessionID) {
|
|
265
266
|
return this._agents.get(sessionID);
|
|
266
267
|
}
|
|
@@ -415,6 +416,12 @@ var PluginState = class {
|
|
|
415
416
|
messagesSinceLastNudge(currentMessageCount) {
|
|
416
417
|
return currentMessageCount - this._lastNudgeMessageCount;
|
|
417
418
|
}
|
|
419
|
+
setModelContextWindow(tokens) {
|
|
420
|
+
if (tokens > 0) this._modelContextWindow = tokens;
|
|
421
|
+
}
|
|
422
|
+
getModelContextWindow() {
|
|
423
|
+
return this._modelContextWindow;
|
|
424
|
+
}
|
|
418
425
|
};
|
|
419
426
|
function createPluginState() {
|
|
420
427
|
return new PluginState();
|
|
@@ -15219,19 +15226,25 @@ function createCompactingHandler(args) {
|
|
|
15219
15226
|
}
|
|
15220
15227
|
|
|
15221
15228
|
// src/compress/pressure.ts
|
|
15222
|
-
var
|
|
15229
|
+
var FALLBACK_MAX_CONTEXT = 128e3;
|
|
15230
|
+
var OPENCODE_COMPACTION_RATIO = 0.75;
|
|
15223
15231
|
var THRESHOLDS = {
|
|
15224
15232
|
medium: 0.3,
|
|
15225
15233
|
high: 0.5
|
|
15226
15234
|
};
|
|
15227
|
-
var
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
}
|
|
15235
|
+
var calibratedMaxContext = 0;
|
|
15236
|
+
function calibrateFromCompaction(lastInputTokens) {
|
|
15237
|
+
if (lastInputTokens <= 0) return;
|
|
15238
|
+
calibratedMaxContext = Math.round(lastInputTokens / OPENCODE_COMPACTION_RATIO);
|
|
15239
|
+
}
|
|
15240
|
+
function getCalibratedMaxContext() {
|
|
15241
|
+
return calibratedMaxContext;
|
|
15242
|
+
}
|
|
15243
|
+
function maxContextFrom(modelContextWindow) {
|
|
15244
|
+
if (modelContextWindow > 0) return modelContextWindow;
|
|
15245
|
+
if (calibratedMaxContext > 0) return calibratedMaxContext;
|
|
15246
|
+
return FALLBACK_MAX_CONTEXT;
|
|
15247
|
+
}
|
|
15235
15248
|
function estimateTokens2(text) {
|
|
15236
15249
|
let cjk = 0;
|
|
15237
15250
|
let other = 0;
|
|
@@ -15285,16 +15298,16 @@ function extractInputTokensFromMessages(messages) {
|
|
|
15285
15298
|
}
|
|
15286
15299
|
return 0;
|
|
15287
15300
|
}
|
|
15288
|
-
function detectPressure(messages,
|
|
15289
|
-
const
|
|
15301
|
+
function detectPressure(messages, modelContextWindow) {
|
|
15302
|
+
const ctx = maxContextFrom(modelContextWindow || 0);
|
|
15290
15303
|
const inputTokens = extractInputTokensFromMessages(messages);
|
|
15291
15304
|
const estimated = inputTokens > 0 ? inputTokens : extractTokensFromMessages(messages);
|
|
15292
|
-
const ratio = Math.min(estimated /
|
|
15305
|
+
const ratio = Math.min(estimated / ctx, 1);
|
|
15293
15306
|
let level;
|
|
15294
15307
|
if (ratio >= THRESHOLDS.high) level = "high";
|
|
15295
15308
|
else if (ratio >= THRESHOLDS.medium) level = "medium";
|
|
15296
15309
|
else level = "low";
|
|
15297
|
-
return { level, ratio, estimatedTokens: estimated };
|
|
15310
|
+
return { level, ratio, estimatedTokens: estimated, maxContext: ctx };
|
|
15298
15311
|
}
|
|
15299
15312
|
|
|
15300
15313
|
// src/compress/dedup.ts
|
|
@@ -15402,7 +15415,7 @@ function purgeOldErrors(messages) {
|
|
|
15402
15415
|
const input = toolState["input"];
|
|
15403
15416
|
for (const key of Object.keys(input)) {
|
|
15404
15417
|
if (key === "command" || key === "query" || key === "path" || key === "filePath") continue;
|
|
15405
|
-
input[key]
|
|
15418
|
+
delete input[key];
|
|
15406
15419
|
}
|
|
15407
15420
|
}
|
|
15408
15421
|
purged++;
|
|
@@ -15558,55 +15571,6 @@ function sha2562(data) {
|
|
|
15558
15571
|
return createHash3("sha256").update(data).digest("hex");
|
|
15559
15572
|
}
|
|
15560
15573
|
|
|
15561
|
-
// src/compress/message-prune.ts
|
|
15562
|
-
var PRUNE_THRESHOLD = 8;
|
|
15563
|
-
function pruneOldMessages(messages) {
|
|
15564
|
-
let pruned = 0;
|
|
15565
|
-
const protectedTail = messages.length - PRUNE_THRESHOLD;
|
|
15566
|
-
for (let i = 3; i < protectedTail; i++) {
|
|
15567
|
-
const msg = messages[i];
|
|
15568
|
-
if (msg.info.role !== "assistant") continue;
|
|
15569
|
-
for (const part of msg.parts) {
|
|
15570
|
-
if (typeof part !== "object" || part === null) continue;
|
|
15571
|
-
const p = part;
|
|
15572
|
-
if (p["type"] !== "text" || typeof p["text"] !== "string") continue;
|
|
15573
|
-
const text = p["text"];
|
|
15574
|
-
if (text.length < 500) continue;
|
|
15575
|
-
if (text === "[cleared]" || text === "[stripped]") continue;
|
|
15576
|
-
if (text.includes("[compressed from")) continue;
|
|
15577
|
-
const keyInfo = extractKeyInfo(text);
|
|
15578
|
-
if (keyInfo.length < text.length * 0.6) {
|
|
15579
|
-
p["text"] = keyInfo + "\n[compressed from " + text.length + " chars]";
|
|
15580
|
-
pruned++;
|
|
15581
|
-
}
|
|
15582
|
-
}
|
|
15583
|
-
}
|
|
15584
|
-
return pruned;
|
|
15585
|
-
}
|
|
15586
|
-
function extractKeyInfo(text) {
|
|
15587
|
-
const lines = text.split("\n");
|
|
15588
|
-
const keyLines = [];
|
|
15589
|
-
let inCodeBlock = false;
|
|
15590
|
-
for (const line of lines) {
|
|
15591
|
-
if (line.trim().startsWith("```")) {
|
|
15592
|
-
inCodeBlock = !inCodeBlock;
|
|
15593
|
-
if (inCodeBlock) keyLines.push(line);
|
|
15594
|
-
continue;
|
|
15595
|
-
}
|
|
15596
|
-
if (inCodeBlock) {
|
|
15597
|
-
if (keyLines.length < 30 && line.trim()) keyLines.push(line);
|
|
15598
|
-
continue;
|
|
15599
|
-
}
|
|
15600
|
-
if (/^#{1,3}\s/.test(line) || /error|fail|warning|important|critical|decision|constraint/i.test(line) || /^\s*[-*]\s/.test(line) || /^\s*\d+\.\s/.test(line)) {
|
|
15601
|
-
keyLines.push(line);
|
|
15602
|
-
}
|
|
15603
|
-
}
|
|
15604
|
-
if (keyLines.length < 3) {
|
|
15605
|
-
return lines.slice(0, 5).join("\n");
|
|
15606
|
-
}
|
|
15607
|
-
return keyLines.join("\n");
|
|
15608
|
-
}
|
|
15609
|
-
|
|
15610
15574
|
// src/compress/nudge.ts
|
|
15611
15575
|
var NUDGE_COOLDOWN = 5;
|
|
15612
15576
|
function shouldInjectNudge(level, messagesSinceLastNudge) {
|
|
@@ -15700,14 +15664,13 @@ function detectContentType(content) {
|
|
|
15700
15664
|
// src/compress/index.ts
|
|
15701
15665
|
function runCompressionPipeline(ctx) {
|
|
15702
15666
|
const { messages, state, logger } = ctx;
|
|
15703
|
-
const pressure = detectPressure(messages,
|
|
15667
|
+
const pressure = detectPressure(messages, state.getModelContextWindow());
|
|
15704
15668
|
state.recordInputTokens(pressure.estimatedTokens);
|
|
15705
15669
|
const stats = {
|
|
15706
15670
|
toolDedup: 0,
|
|
15707
15671
|
errorPurge: 0,
|
|
15708
15672
|
toolOutputCompressed: 0,
|
|
15709
15673
|
jsonCrushed: 0,
|
|
15710
|
-
messagePruned: 0,
|
|
15711
15674
|
ccrStored: 0,
|
|
15712
15675
|
nudgeInjected: false,
|
|
15713
15676
|
pressureLevel: pressure.level,
|
|
@@ -15717,9 +15680,6 @@ function runCompressionPipeline(ctx) {
|
|
|
15717
15680
|
stats.errorPurge = purgeOldErrors(messages);
|
|
15718
15681
|
stats.jsonCrushed = crushJsonToolOutputs(messages, state);
|
|
15719
15682
|
stats.toolOutputCompressed = compressOldToolOutputs(messages, state);
|
|
15720
|
-
if (pressure.level === "medium" || pressure.level === "high") {
|
|
15721
|
-
stats.messagePruned = pruneOldMessages(messages);
|
|
15722
|
-
}
|
|
15723
15683
|
const messagesSinceNudge = state.messagesSinceLastNudge(messages.length);
|
|
15724
15684
|
if (shouldInjectNudge(pressure.level, messagesSinceNudge)) {
|
|
15725
15685
|
if (injectIntoLastAssistant(messages, buildNudgeText(pressure.level))) {
|
|
@@ -15734,7 +15694,7 @@ function runCompressionPipeline(ctx) {
|
|
|
15734
15694
|
logger?.debug("compress: memory nudge", { type: memoryNudge.type });
|
|
15735
15695
|
}
|
|
15736
15696
|
}
|
|
15737
|
-
const active = stats.toolDedup > 0 || stats.errorPurge > 0 || stats.toolOutputCompressed > 0 || stats.jsonCrushed > 0 || stats.
|
|
15697
|
+
const active = stats.toolDedup > 0 || stats.errorPurge > 0 || stats.toolOutputCompressed > 0 || stats.jsonCrushed > 0 || stats.nudgeInjected;
|
|
15738
15698
|
if (active) {
|
|
15739
15699
|
logger?.debug("compress: pipeline result", { ...stats });
|
|
15740
15700
|
} else {
|
|
@@ -15906,11 +15866,12 @@ function createMessagesTransformHandler(state, logger) {
|
|
|
15906
15866
|
tool_errors_truncated: 0,
|
|
15907
15867
|
thinking_stripped: 0
|
|
15908
15868
|
};
|
|
15869
|
+
const toRemove = [];
|
|
15909
15870
|
for (let i = PROTECTED_HEAD2; i < protectedTailStart; i++) {
|
|
15910
15871
|
const msg = messages[i];
|
|
15911
15872
|
if (!msg?.parts?.length) continue;
|
|
15912
15873
|
if (msg.info.role === "user") continue;
|
|
15913
|
-
for (let j =
|
|
15874
|
+
for (let j = msg.parts.length - 1; j >= 0; j--) {
|
|
15914
15875
|
const part = msg.parts[j];
|
|
15915
15876
|
if (typeof part !== "object" || part === null) continue;
|
|
15916
15877
|
const p = part;
|
|
@@ -15926,10 +15887,9 @@ function createMessagesTransformHandler(state, logger) {
|
|
|
15926
15887
|
stats.metadata_stripped++;
|
|
15927
15888
|
}
|
|
15928
15889
|
}
|
|
15929
|
-
|
|
15930
|
-
|
|
15931
|
-
|
|
15932
|
-
}
|
|
15890
|
+
msg.parts.splice(j, 1);
|
|
15891
|
+
stats.reasoning_cleared++;
|
|
15892
|
+
continue;
|
|
15933
15893
|
}
|
|
15934
15894
|
if (partType === "tool") {
|
|
15935
15895
|
const meta = p["metadata"];
|
|
@@ -15957,11 +15917,13 @@ function createMessagesTransformHandler(state, logger) {
|
|
|
15957
15917
|
}
|
|
15958
15918
|
}
|
|
15959
15919
|
if (isSystemInjected(msg)) {
|
|
15960
|
-
|
|
15961
|
-
msg.parts.push({ type: "text", text: "[stripped]" });
|
|
15920
|
+
toRemove.push(i);
|
|
15962
15921
|
stats.system_neutralized++;
|
|
15963
15922
|
}
|
|
15964
15923
|
}
|
|
15924
|
+
for (let r = toRemove.length - 1; r >= 0; r--) {
|
|
15925
|
+
messages.splice(toRemove[r], 1);
|
|
15926
|
+
}
|
|
15965
15927
|
repairOrphanedToolCalls(messages);
|
|
15966
15928
|
if (Object.values(stats).some((v) => v > 0)) {
|
|
15967
15929
|
logger?.debug("messages.transform: stripped", stats);
|
|
@@ -15972,7 +15934,7 @@ function createMessagesTransformHandler(state, logger) {
|
|
|
15972
15934
|
logger
|
|
15973
15935
|
});
|
|
15974
15936
|
const ds = pipelineResult.stats;
|
|
15975
|
-
if (ds.toolDedup > 0 || ds.errorPurge > 0 || ds.toolOutputCompressed > 0 || ds.jsonCrushed > 0 || ds.
|
|
15937
|
+
if (ds.toolDedup > 0 || ds.errorPurge > 0 || ds.toolOutputCompressed > 0 || ds.jsonCrushed > 0 || ds.nudgeInjected) {
|
|
15976
15938
|
logger?.debug("messages.transform: deep compression", { ...ds });
|
|
15977
15939
|
state.mergeNotify({
|
|
15978
15940
|
compression: stats,
|
|
@@ -16557,6 +16519,15 @@ var deepMemoryPlugin = async (input) => {
|
|
|
16557
16519
|
if (event.type === "session.compacted") {
|
|
16558
16520
|
const compactedSessionID = event.properties.sessionID;
|
|
16559
16521
|
logger.info("event session.compacted", { sessionID: compactedSessionID });
|
|
16522
|
+
const lastTokens = state.lastInputTokens();
|
|
16523
|
+
if (lastTokens > 0) {
|
|
16524
|
+
calibrateFromCompaction(lastTokens);
|
|
16525
|
+
logger.info("pressure calibrated", {
|
|
16526
|
+
trigger: "compaction",
|
|
16527
|
+
lastInputTokens: lastTokens,
|
|
16528
|
+
derivedMaxContext: getCalibratedMaxContext()
|
|
16529
|
+
});
|
|
16530
|
+
}
|
|
16560
16531
|
try {
|
|
16561
16532
|
const auditLogDir = projectMemoryDir(projectPath);
|
|
16562
16533
|
await mkdir4(auditLogDir, { recursive: true });
|