opencode-acp 1.5.0 → 1.5.1
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 +62 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/inject/utils.d.ts +1 -1
- package/dist/lib/messages/inject/utils.d.ts.map +1 -1
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/prompts/extensions/nudge.d.ts +1 -0
- package/dist/lib/prompts/extensions/nudge.d.ts.map +1 -1
- package/dist/lib/state/persistence.d.ts +2 -0
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +2 -0
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -894,6 +894,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
894
894
|
"compress.modelMaxLimits",
|
|
895
895
|
"compress.modelMinLimits",
|
|
896
896
|
"compress.nudgeFrequency",
|
|
897
|
+
"compress.perMessageNudgeGrowthPercent",
|
|
897
898
|
"compress.iterationNudgeThreshold",
|
|
898
899
|
"compress.nudgeForce",
|
|
899
900
|
"compress.protectedTools",
|
|
@@ -1117,6 +1118,13 @@ function validateConfigTypes(config) {
|
|
|
1117
1118
|
actual: `${compress.nudgeFrequency} (will be clamped to 1)`
|
|
1118
1119
|
});
|
|
1119
1120
|
}
|
|
1121
|
+
if (compress.perMessageNudgeGrowthPercent !== void 0 && typeof compress.perMessageNudgeGrowthPercent !== "number") {
|
|
1122
|
+
errors.push({
|
|
1123
|
+
key: "compress.perMessageNudgeGrowthPercent",
|
|
1124
|
+
expected: "number",
|
|
1125
|
+
actual: typeof compress.perMessageNudgeGrowthPercent
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1120
1128
|
if (compress.iterationNudgeThreshold !== void 0 && typeof compress.iterationNudgeThreshold !== "number") {
|
|
1121
1129
|
errors.push({
|
|
1122
1130
|
key: "compress.iterationNudgeThreshold",
|
|
@@ -1461,6 +1469,7 @@ var defaultConfig = {
|
|
|
1461
1469
|
maxContextLimit: "55%",
|
|
1462
1470
|
minContextLimit: "45%",
|
|
1463
1471
|
nudgeFrequency: 5,
|
|
1472
|
+
perMessageNudgeGrowthPercent: 3,
|
|
1464
1473
|
iterationNudgeThreshold: 15,
|
|
1465
1474
|
nudgeForce: "soft",
|
|
1466
1475
|
protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],
|
|
@@ -1612,6 +1621,7 @@ function mergeCompress(base, override) {
|
|
|
1612
1621
|
modelMaxLimits: override.modelMaxLimits ?? base.modelMaxLimits,
|
|
1613
1622
|
modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,
|
|
1614
1623
|
nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,
|
|
1624
|
+
perMessageNudgeGrowthPercent: override.perMessageNudgeGrowthPercent ?? base.perMessageNudgeGrowthPercent,
|
|
1615
1625
|
iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,
|
|
1616
1626
|
nudgeForce: override.nudgeForce ?? base.nudgeForce,
|
|
1617
1627
|
protectedTools: [.../* @__PURE__ */ new Set([...base.protectedTools, ...override.protectedTools ?? []])],
|
|
@@ -3019,7 +3029,9 @@ function resetOnCompaction(state) {
|
|
|
3019
3029
|
state.nudges = {
|
|
3020
3030
|
contextLimitAnchors: /* @__PURE__ */ new Set(),
|
|
3021
3031
|
turnNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3022
|
-
iterationNudgeAnchors: /* @__PURE__ */ new Set()
|
|
3032
|
+
iterationNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3033
|
+
lastPerMessageNudgeTurn: 0,
|
|
3034
|
+
lastPerMessageNudgeTokens: 0
|
|
3023
3035
|
};
|
|
3024
3036
|
state.messageIds = {
|
|
3025
3037
|
byRawId: /* @__PURE__ */ new Map(),
|
|
@@ -3085,7 +3097,9 @@ async function saveSessionState(sessionState, logger, sessionName) {
|
|
|
3085
3097
|
nudges: {
|
|
3086
3098
|
contextLimitAnchors: Array.from(sessionState.nudges.contextLimitAnchors),
|
|
3087
3099
|
turnNudgeAnchors: Array.from(sessionState.nudges.turnNudgeAnchors),
|
|
3088
|
-
iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors)
|
|
3100
|
+
iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors),
|
|
3101
|
+
lastPerMessageNudgeTurn: sessionState.nudges.lastPerMessageNudgeTurn ?? 0,
|
|
3102
|
+
lastPerMessageNudgeTokens: sessionState.nudges.lastPerMessageNudgeTokens ?? 0
|
|
3089
3103
|
},
|
|
3090
3104
|
stats: sessionState.stats,
|
|
3091
3105
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3299,7 +3313,9 @@ function createSessionState() {
|
|
|
3299
3313
|
nudges: {
|
|
3300
3314
|
contextLimitAnchors: /* @__PURE__ */ new Set(),
|
|
3301
3315
|
turnNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3302
|
-
iterationNudgeAnchors: /* @__PURE__ */ new Set()
|
|
3316
|
+
iterationNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3317
|
+
lastPerMessageNudgeTurn: 0,
|
|
3318
|
+
lastPerMessageNudgeTokens: 0
|
|
3303
3319
|
},
|
|
3304
3320
|
stats: {
|
|
3305
3321
|
pruneTokenCounter: 0,
|
|
@@ -3336,7 +3352,9 @@ function resetSessionState(state) {
|
|
|
3336
3352
|
state.nudges = {
|
|
3337
3353
|
contextLimitAnchors: /* @__PURE__ */ new Set(),
|
|
3338
3354
|
turnNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3339
|
-
iterationNudgeAnchors: /* @__PURE__ */ new Set()
|
|
3355
|
+
iterationNudgeAnchors: /* @__PURE__ */ new Set(),
|
|
3356
|
+
lastPerMessageNudgeTurn: 0,
|
|
3357
|
+
lastPerMessageNudgeTokens: 0
|
|
3340
3358
|
};
|
|
3341
3359
|
state.stats = {
|
|
3342
3360
|
pruneTokenCounter: 0,
|
|
@@ -3381,6 +3399,8 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
3381
3399
|
state.nudges.iterationNudgeAnchors = new Set(
|
|
3382
3400
|
persisted.nudges.iterationNudgeAnchors || []
|
|
3383
3401
|
);
|
|
3402
|
+
state.nudges.lastPerMessageNudgeTurn = persisted.nudges.lastPerMessageNudgeTurn ?? 0;
|
|
3403
|
+
state.nudges.lastPerMessageNudgeTokens = persisted.nudges.lastPerMessageNudgeTokens ?? 0;
|
|
3384
3404
|
state.stats = {
|
|
3385
3405
|
pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0,
|
|
3386
3406
|
totalPruneTokens: persisted.stats?.totalPruneTokens || 0
|
|
@@ -4815,7 +4835,8 @@ var createSyntheticUserMessage = (baseMessage, content, stableSeed) => {
|
|
|
4815
4835
|
sessionID: userInfo.sessionID,
|
|
4816
4836
|
messageID: messageId,
|
|
4817
4837
|
type: "text",
|
|
4818
|
-
text: content
|
|
4838
|
+
text: content,
|
|
4839
|
+
synthetic: true
|
|
4819
4840
|
}
|
|
4820
4841
|
]
|
|
4821
4842
|
};
|
|
@@ -5225,12 +5246,18 @@ function buildCompressedBlockGuidance(state, gcConfig, context) {
|
|
|
5225
5246
|
const recent = refs.slice(-20).join(", ");
|
|
5226
5247
|
blockList = `${recent} (+${blockCount - 20} older, use decompress to access by ID)`;
|
|
5227
5248
|
}
|
|
5249
|
+
const includeHint = context?.includeHint ?? true;
|
|
5228
5250
|
const lines = [
|
|
5229
5251
|
"Compressed block context:",
|
|
5230
5252
|
`- Active compressed blocks: ${blockCount} (${blockList})`,
|
|
5231
|
-
"- If your selected compression range includes any listed block, include each required placeholder exactly once in the summary using `(bN)`."
|
|
5232
|
-
"- \u{1F4A1} When you've finished using tool outputs, compress them \u2014 you can decompress later if needed. Lean context improves accuracy."
|
|
5253
|
+
"- If your selected compression range includes any listed block, include each required placeholder exactly once in the summary using `(bN)`."
|
|
5233
5254
|
];
|
|
5255
|
+
if (includeHint) {
|
|
5256
|
+
lines.push("- \u{1F4A1} When you've finished using tool outputs, compress them \u2014 you can decompress later if needed. Lean context improves accuracy.");
|
|
5257
|
+
}
|
|
5258
|
+
if (blockCount > 50) {
|
|
5259
|
+
lines.push(`- \u{1F500} You have ${blockCount} blocks \u2014 consider merging adjacent same-topic blocks instead of finding new content to compress. This permanently reduces per-turn overhead.`);
|
|
5260
|
+
}
|
|
5234
5261
|
const usageRatio = context?.currentTokens && context?.modelContextLimit ? context.currentTokens / context.modelContextLimit : 0;
|
|
5235
5262
|
if (gcConfig && usageRatio > 0.5) {
|
|
5236
5263
|
const promotionThreshold = gcConfig.promotionThreshold;
|
|
@@ -5573,7 +5600,7 @@ function resolveThresholdPercent(threshold, modelContextLimit) {
|
|
|
5573
5600
|
const parsed = parseFloat(threshold);
|
|
5574
5601
|
return isNaN(parsed) ? void 0 : parsed;
|
|
5575
5602
|
}
|
|
5576
|
-
function buildContextUsageGuidance(config, currentTokens, modelContextLimit) {
|
|
5603
|
+
function buildContextUsageGuidance(config, currentTokens, modelContextLimit, minimal = false) {
|
|
5577
5604
|
if (currentTokens === void 0 || modelContextLimit === void 0 || modelContextLimit === 0) {
|
|
5578
5605
|
return "";
|
|
5579
5606
|
}
|
|
@@ -5583,9 +5610,14 @@ function buildContextUsageGuidance(config, currentTokens, modelContextLimit) {
|
|
|
5583
5610
|
const minPct = resolveThresholdPercent(config.compress.minContextLimit, modelContextLimit) ?? 45;
|
|
5584
5611
|
const maxPct = resolveThresholdPercent(config.compress.maxContextLimit, modelContextLimit) ?? 55;
|
|
5585
5612
|
const base = `Context usage: ${formatK(currentTokens)} / ${formatK(modelContextLimit)} tokens (${percentage}%).`;
|
|
5613
|
+
if (minimal) {
|
|
5614
|
+
return `
|
|
5615
|
+
|
|
5616
|
+
${base}`;
|
|
5617
|
+
}
|
|
5586
5618
|
let guidance;
|
|
5587
5619
|
if (pct < minPct) {
|
|
5588
|
-
guidance = " \u{1F4A1} Be frugal with context \u2014
|
|
5620
|
+
guidance = " \u{1F4A1} Be frugal with context \u2014 if you see large completed outputs (>2000 tokens), compress them into summaries. If everything is already compressed, skip this nudge. You can decompress later if needed. Extract and keep what matters: user intent, key decisions, file paths, and important findings. Compress everything else.";
|
|
5589
5621
|
} else if (pct < maxPct) {
|
|
5590
5622
|
guidance = " \u26A0\uFE0F Context is growing \u2014 compress completed sections and high-token waste now. Preserve key details.";
|
|
5591
5623
|
} else {
|
|
@@ -5687,6 +5719,18 @@ function createSuffixMessage(messages) {
|
|
|
5687
5719
|
messages.push(synthetic);
|
|
5688
5720
|
return synthetic;
|
|
5689
5721
|
}
|
|
5722
|
+
function shouldInjectPerMessageNudge(state, config, currentTokens, modelContextLimit) {
|
|
5723
|
+
const turn = state.currentTurn ?? 0;
|
|
5724
|
+
const lastTurn = state.nudges.lastPerMessageNudgeTurn ?? 0;
|
|
5725
|
+
const turnsSinceLast = turn - lastTurn;
|
|
5726
|
+
const tokens = currentTokens ?? 0;
|
|
5727
|
+
const lastTokens = state.nudges.lastPerMessageNudgeTokens ?? 0;
|
|
5728
|
+
const tokenGrowth = tokens - lastTokens;
|
|
5729
|
+
const tokenGrowthPercent = modelContextLimit ? tokenGrowth / modelContextLimit * 100 : 0;
|
|
5730
|
+
const frequency = config.compress.nudgeFrequency ?? 5;
|
|
5731
|
+
const growthThreshold = config.compress.perMessageNudgeGrowthPercent ?? 3;
|
|
5732
|
+
return turnsSinceLast >= frequency || tokenGrowthPercent >= growthThreshold;
|
|
5733
|
+
}
|
|
5690
5734
|
var injectCompressNudges = (state, config, logger, messages, prompts, compressionPriorities) => {
|
|
5691
5735
|
if (compressPermission(state, config) === "deny") {
|
|
5692
5736
|
return;
|
|
@@ -5771,21 +5815,26 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
5771
5815
|
}
|
|
5772
5816
|
const suffixMessage = createSuffixMessage(messages);
|
|
5773
5817
|
applyAnchoredNudges(state, config, messages, prompts, compressionPriorities, currentTokens, modelContextLimit, suffixMessage);
|
|
5774
|
-
|
|
5818
|
+
const shouldNudge = shouldInjectPerMessageNudge(state, config, currentTokens, modelContextLimit);
|
|
5819
|
+
injectContextUsage(suffixMessage, config, currentTokens, modelContextLimit, !shouldNudge);
|
|
5775
5820
|
if (config.compress.mode !== "message") {
|
|
5776
|
-
const blockGuidance = buildCompressedBlockGuidance(state, config.gc, { currentTokens, modelContextLimit });
|
|
5821
|
+
const blockGuidance = buildCompressedBlockGuidance(state, config.gc, { currentTokens, modelContextLimit, includeHint: shouldNudge });
|
|
5777
5822
|
if (blockGuidance.trim() && suffixMessage) {
|
|
5778
5823
|
appendToLastTextPart(suffixMessage, "\n\n" + blockGuidance);
|
|
5779
5824
|
}
|
|
5780
5825
|
}
|
|
5826
|
+
if (shouldNudge) {
|
|
5827
|
+
state.nudges.lastPerMessageNudgeTurn = state.currentTurn ?? 0;
|
|
5828
|
+
state.nudges.lastPerMessageNudgeTokens = currentTokens ?? 0;
|
|
5829
|
+
}
|
|
5781
5830
|
injectVisibleIdRange(state, messages, suffixMessage);
|
|
5782
5831
|
if (anchorsChanged) {
|
|
5783
5832
|
void saveSessionState(state, logger);
|
|
5784
5833
|
}
|
|
5785
5834
|
};
|
|
5786
|
-
function injectContextUsage(target, config, currentTokens, modelContextLimit) {
|
|
5835
|
+
function injectContextUsage(target, config, currentTokens, modelContextLimit, minimal = false) {
|
|
5787
5836
|
if (!target) return;
|
|
5788
|
-
const usageTag = buildContextUsageGuidance(config, currentTokens, modelContextLimit);
|
|
5837
|
+
const usageTag = buildContextUsageGuidance(config, currentTokens, modelContextLimit, minimal);
|
|
5789
5838
|
if (!usageTag) return;
|
|
5790
5839
|
for (const part of target.parts) {
|
|
5791
5840
|
if (part.type === "text") {
|