aboutsummaryrefslogtreecommitdiff
path: root/modules/core/core-bundle.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/core/core-bundle.js')
-rw-r--r--modules/core/core-bundle.js29
1 files changed, 26 insertions, 3 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js
index f72a20e..8e19189 100644
--- a/modules/core/core-bundle.js
+++ b/modules/core/core-bundle.js
@@ -9348,7 +9348,17 @@ buildSystemPrompt() {
// every later turn started blind and the model re-read the same files.
this._flushToolTrace(sess, _traceTag);
if (sess.context.length > this.maxContext * 2) {
- sess.context.splice(0, sess.context.length - this.maxContext * 2);
+ // Silently splicing the opening turns is how a long task forgets its own brief:
+ // the model then "remembers" a conversation that never started that way. Drop
+ // the same messages, but leave a marker saying how many and what the first was.
+ const cap = this.maxContext * 2;
+ const dropped = sess.context.splice(0, sess.context.length - (cap - 1));
+ const firstUser = dropped.find(m => m.role === 'user');
+ const note = '[context trim: ' + dropped.length + ' earlier message(s) left this window'
+ + (firstUser && firstUser.content ? ' — the earliest was: "' + String(firstUser.content).replace(/\s+/g, ' ').slice(0, 90) + '…"' : '')
+ + ']';
+ sess.context.unshift({ role: 'system', content: note });
+ this.terminal.print('✂️ Context trimmed: ' + dropped.length + ' message(s) — the model is told what it lost', 'text-muted');
}
// Reflection: after complex tasks, run health scan and auto-skill creation
if (loopResult.toolTurns >= 2 && !this._cancelled) {
@@ -12197,7 +12207,7 @@ buildSystemPrompt() {
this.terminal.print('=== AI Config ===', 'info');
this.terminal.print(`max-turns: ${this.MAX_TOOL_TURNS} (default: 8)`, '');
this.terminal.print(`max-context: ${this.maxContext} (default: 10)`, '');
- this.terminal.print(`max-context-tokens: ${this.maxContextTokens} (default: 2000)`, '');
+ this.terminal.print(`max-context-tokens: ${this.maxContextTokens} (code default: 12000)`, '');
this.terminal.print(`trivial-optimization: ${(this.terminal?.ollamaManager?.optimizationEnabled) ? 'on' : 'off (default)'}`, '');
this.terminal.print(`confirm-timeout: ${this._confirmTimeoutMs > 0 ? this._confirmTimeoutMs / 1000 + 's' : 'disabled (no auto-deny)'} (default: 120s)`, '');
this.terminal.print(`chat-lock-timeout: ${this._chatLockTimeoutMs / 1000}s (default: 10s)`, '');
@@ -12520,7 +12530,20 @@ buildSystemPrompt() {
async _compressContext() {
if (this.context.length <= 6) return;
const totalTokens = this._estimateContextTokens();
- if (totalTokens < this.maxContextTokens) return;
+ if (totalTokens < this.maxContextTokens) {
+ // Warn before the cliff rather than only reporting the fall. Once per crossing,
+ // so a long session is not nagged every turn.
+ const pct = Math.round((totalTokens / this.maxContextTokens) * 100);
+ if (pct >= 80 && !this._ctxWarned) {
+ this._ctxWarned = true;
+ this.terminal.print('⚠️ Context ' + pct + '% full (' + totalTokens + '/' + this.maxContextTokens +
+ ' tokens) — the next few turns will compress earlier history into a summary', 'warning');
+ } else if (pct < 60) {
+ this._ctxWarned = false;
+ }
+ return;
+ }
+ this._ctxWarned = false;
const keepCount = 8;
const oldMsgs = this.context.slice(0, -keepCount * 2);
if (oldMsgs.length < 2) return;