Skip to content

Commit 91d82c7

Browse files
committed
feat: nudgeGrowthTokens — token-based Tips gating (default 6K)
1 parent c687a98 commit 91d82c7

4 files changed

Lines changed: 25 additions & 21 deletions

File tree

‎dcp.schema.json‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@
275275
"default": 4000,
276276
"minimum": 1,
277277
"description": "Hard limit for summary length in characters"
278+
},
279+
"nudgeGrowthTokens": {
280+
"type": "number",
281+
"default": 6000,
282+
"description": "Token growth required between per-message nudges (absolute, not percentage). Shows Tips only after context grows by this many tokens."
278283
}
279284
},
280285
"default": {
@@ -291,7 +296,8 @@
291296
"protectTags": false,
292297
"protectUserMessages": false,
293298
"minNudgeContextPercent": 15,
294-
"maxSummaryLengthHard": 3000
299+
"maxSummaryLengthHard": 3000,
300+
"nudgeGrowthTokens": 6000
295301
}
296302
},
297303
"gc": {
@@ -431,4 +437,4 @@
431437
}
432438
}
433439
}
434-
}
440+
}

‎lib/config-validation.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const VALID_CONFIG_KEYS = new Set([
3535
"compress.modelMinLimits",
3636
"compress.nudgeFrequency",
3737
"compress.minNudgeContextPercent",
38+
"compress.nudgeGrowthTokens",
3839
"compress.iterationNudgeThreshold",
3940
"compress.nudgeForce",
4041
"compress.protectedTools",

‎lib/config.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface CompressConfig {
2525
modelMinLimits?: Record<string, number | `${number}%`>
2626
nudgeFrequency: number
2727
minNudgeContextPercent: number
28+
nudgeGrowthTokens: number
2829
iterationNudgeThreshold: number
2930
nudgeForce: "strong" | "soft"
3031
protectedTools: string[]
@@ -191,6 +192,7 @@ const defaultConfig: PluginConfig = {
191192
minContextLimit: "45%",
192193
nudgeFrequency: 5,
193194
minNudgeContextPercent: 15,
195+
nudgeGrowthTokens: 6000,
194196
iterationNudgeThreshold: 15,
195197
nudgeForce: "soft",
196198
protectedTools: [...COMPRESS_DEFAULT_PROTECTED_TOOLS],
@@ -400,6 +402,7 @@ function mergeCompress(
400402
modelMinLimits: override.modelMinLimits ?? base.modelMinLimits,
401403
nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,
402404
minNudgeContextPercent: override.minNudgeContextPercent ?? base.minNudgeContextPercent,
405+
nudgeGrowthTokens: override.nudgeGrowthTokens ?? base.nudgeGrowthTokens,
403406
iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,
404407
nudgeForce: override.nudgeForce ?? base.nudgeForce,
405408
protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],

‎lib/messages/inject/inject.ts‎

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,31 +167,25 @@ export const injectCompressNudges = (
167167

168168
const contextPct = modelContextLimit && currentTokens ? (currentTokens / modelContextLimit) * 100 : 0
169169
const minPercent = config.compress?.minNudgeContextPercent ?? 15
170+
const growthTokens = config.compress?.nudgeGrowthTokens ?? 6000
171+
const lastNudgeTokens = state.nudges.lastPerMessageNudgeTokens ?? 0
172+
const growthSinceLastNudge = (currentTokens ?? 0) - lastNudgeTokens
173+
const shouldNudge = lastNudgeTokens === 0 || growthSinceLastNudge >= growthTokens
170174

171175
injectContextUsage(suffixMessage, config, currentTokens, modelContextLimit)
172176

173-
// Determine tips tier: light (every turn) vs warning (key nodes only)
174177
let tipsText: string | null = null
175178

176-
if (overMaxLimit || overMinLimit) {
177-
// Warning zone: show at key nodes only (first crossing or 10pp growth)
178-
const lastWarnPct = state.nudges.lastPerMessageNudgeTokens && modelContextLimit
179-
? (state.nudges.lastPerMessageNudgeTokens / modelContextLimit) * 100
180-
: 0
181-
const growthSinceWarn = contextPct - lastWarnPct
182-
if (lastWarnPct === 0 || growthSinceWarn >= 10) {
183-
tipsText = overMaxLimit
184-
? "\n\n⚠️ Context limit reached — compress now. Prioritize consumed tool outputs.\n\n{ \"topic\": \"...\", \"content\": [{ \"startId\": \"<ID>\", \"endId\": \"<ID>\", \"summary\": \"...\" }] }\n\nOnly use IDs from visible messages above. Compress older work first."
185-
: "\n\n⚠️ Context is growing — consider compressing older work. Tools: compress, decompress, search_context."
186-
state.nudges.lastPerMessageNudgeTokens = currentTokens ?? 0
187-
state.nudges.lastPerMessageNudgeTurn = state.currentTurn ?? 0
188-
}
189-
} else if (contextPct >= minPercent) {
190-
tipsText = "\n\n💡 Tools: compress, decompress, search_context."
191-
// Reset warning tracking when context drops below warning zone
192-
if (state.nudges.lastPerMessageNudgeTokens) {
193-
state.nudges.lastPerMessageNudgeTokens = 0
179+
if (contextPct >= minPercent && shouldNudge) {
180+
if (overMaxLimit) {
181+
tipsText = "\n\n⚠️ Context limit reached — compress now. Prioritize consumed tool outputs.\n\n{ \"topic\": \"...\", \"content\": [{ \"startId\": \"<ID>\", \"endId\": \"<ID>\", \"summary\": \"...\" }] }\n\nOnly use IDs from visible messages above. Compress older work first."
182+
} else if (overMinLimit) {
183+
tipsText = "\n\n⚠️ Context is growing — consider compressing older work. Tools: compress, decompress, search_context."
184+
} else {
185+
tipsText = "\n\n💡 Tools: compress, decompress, search_context."
194186
}
187+
state.nudges.lastPerMessageNudgeTokens = currentTokens ?? 0
188+
state.nudges.lastPerMessageNudgeTurn = state.currentTurn ?? 0
195189
}
196190

197191
if (config.compress.mode !== "message") {

0 commit comments

Comments
 (0)