@dreb/coding-agent 2.47.0 → 2.49.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/README.md +1 -1
- package/dist/core/agent-session.d.ts +22 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +90 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/k3-context-tier.d.ts +67 -0
- package/dist/core/k3-context-tier.d.ts.map +1 -0
- package/dist/core/k3-context-tier.js +76 -0
- package/dist/core/k3-context-tier.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tools/ask-user.d.ts.map +1 -1
- package/dist/core/tools/ask-user.js +1 -1
- package/dist/core/tools/ask-user.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/dashboard.md +8 -5
- package/docs/providers.md +1 -0
- package/docs/rpc.md +1 -0
- package/package.json +1 -1
|
@@ -29,6 +29,7 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
|
29
29
|
import { checkScriptContent, extractScriptPaths, isForbiddenCommand } from "./forbidden-commands.js";
|
|
30
30
|
import { getGitRepoState, getGitStatusMetadata } from "./git-repo-state.js";
|
|
31
31
|
import { findGitRoot } from "./git-root.js";
|
|
32
|
+
import { deriveK3ContextTierModel, isK3256kTier, K3_1M_CONTEXT_WINDOW, K3_256K_CONTEXT_WINDOW, K3_UPGRADE_CUTOFF_TOKENS, shouldUpgradeK3Tier, } from "./k3-context-tier.js";
|
|
32
33
|
import { log } from "./logger.js";
|
|
33
34
|
import { computeNestedContextBlock } from "./nested-context.js";
|
|
34
35
|
import { PerformanceTracker } from "./performance-tracker.js";
|
|
@@ -1697,7 +1698,7 @@ export class AgentSession {
|
|
|
1697
1698
|
}
|
|
1698
1699
|
const previousModel = this.model;
|
|
1699
1700
|
const thinkingLevel = this._getThinkingLevelForModelSwitch();
|
|
1700
|
-
this.agent.setModel(model);
|
|
1701
|
+
this.agent.setModel(this._applyContextTier(model));
|
|
1701
1702
|
this._refreshThinkingDisplay(model);
|
|
1702
1703
|
this.sessionManager.appendModelChange(model.provider, model.id);
|
|
1703
1704
|
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
@@ -1760,7 +1761,7 @@ export class AgentSession {
|
|
|
1760
1761
|
const next = scopedModels[nextIndex];
|
|
1761
1762
|
const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
|
|
1762
1763
|
// Apply model
|
|
1763
|
-
this.agent.setModel(next.model);
|
|
1764
|
+
this.agent.setModel(this._applyContextTier(next.model));
|
|
1764
1765
|
this._refreshThinkingDisplay(next.model);
|
|
1765
1766
|
this.sessionManager.appendModelChange(next.model.provider, next.model.id);
|
|
1766
1767
|
this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
|
|
@@ -1790,7 +1791,7 @@ export class AgentSession {
|
|
|
1790
1791
|
throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
|
|
1791
1792
|
}
|
|
1792
1793
|
const thinkingLevel = this._getThinkingLevelForModelSwitch();
|
|
1793
|
-
this.agent.setModel(nextModel);
|
|
1794
|
+
this.agent.setModel(this._applyContextTier(nextModel));
|
|
1794
1795
|
this._refreshThinkingDisplay(nextModel);
|
|
1795
1796
|
this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
|
|
1796
1797
|
this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
|
|
@@ -1979,6 +1980,11 @@ export class AgentSession {
|
|
|
1979
1980
|
const newEntries = this.sessionManager.getEntries();
|
|
1980
1981
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1981
1982
|
this.agent.replaceMessages(sessionContext.messages);
|
|
1983
|
+
// Re-derive the K3 context tier: the compacted context is small again,
|
|
1984
|
+
// so the session returns to the cheaper 256k wire tier.
|
|
1985
|
+
if (this.model) {
|
|
1986
|
+
this.agent.setModel(this._applyContextTier(this.model));
|
|
1987
|
+
}
|
|
1982
1988
|
// Get the saved compaction entry for the extension event
|
|
1983
1989
|
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
1984
1990
|
if (this._extensionRunner && savedCompactionEntry) {
|
|
@@ -2026,12 +2032,10 @@ export class AgentSession {
|
|
|
2026
2032
|
*/
|
|
2027
2033
|
async _checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
2028
2034
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2029
|
-
if (!settings.enabled)
|
|
2030
|
-
return;
|
|
2031
2035
|
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
2032
2036
|
if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
|
|
2033
2037
|
return;
|
|
2034
|
-
|
|
2038
|
+
let contextWindow = this.model?.contextWindow ?? 0;
|
|
2035
2039
|
// Skip overflow check if the message came from a different model.
|
|
2036
2040
|
// This handles the case where user switched from a smaller-context model (e.g. opus)
|
|
2037
2041
|
// to a larger-context model (e.g. codex) - the overflow error from the old model
|
|
@@ -2047,6 +2051,23 @@ export class AgentSession {
|
|
|
2047
2051
|
}
|
|
2048
2052
|
// Case 1: Overflow - LLM returned context overflow error
|
|
2049
2053
|
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
|
2054
|
+
// K3 auto context tier: an overflow in the 256k tier upgrades to the
|
|
2055
|
+
// 1M tier instead of compacting — the Kimi backend grows the prompt
|
|
2056
|
+
// cache seamlessly. This runs even when compaction is disabled since
|
|
2057
|
+
// no context reduction is involved.
|
|
2058
|
+
if (this._tryUpgradeK3ContextTier()) {
|
|
2059
|
+
// Remove the error message from agent state (it IS saved to session
|
|
2060
|
+
// for history, but we don't want it in context for the retry)
|
|
2061
|
+
this._removeLastAssistantMessage();
|
|
2062
|
+
setTimeout(() => {
|
|
2063
|
+
this.agent.continue().catch((err) => {
|
|
2064
|
+
this.warnInSession(`Agent failed to continue after context window upgrade: ${err instanceof Error ? err.message : String(err)}`);
|
|
2065
|
+
});
|
|
2066
|
+
}, 100);
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
if (!settings.enabled)
|
|
2070
|
+
return;
|
|
2050
2071
|
if (this._overflowRecoveryAttempted) {
|
|
2051
2072
|
this._emit({
|
|
2052
2073
|
type: "auto_compaction_end",
|
|
@@ -2060,10 +2081,7 @@ export class AgentSession {
|
|
|
2060
2081
|
this._overflowRecoveryAttempted = true;
|
|
2061
2082
|
// Remove the error message from agent state (it IS saved to session for history,
|
|
2062
2083
|
// but we don't want it in context for the retry)
|
|
2063
|
-
|
|
2064
|
-
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
2065
|
-
this.agent.replaceMessages(messages.slice(0, -1));
|
|
2066
|
-
}
|
|
2084
|
+
this._removeLastAssistantMessage();
|
|
2067
2085
|
await this._runAutoCompaction("overflow", true);
|
|
2068
2086
|
return;
|
|
2069
2087
|
}
|
|
@@ -2090,10 +2108,65 @@ export class AgentSession {
|
|
|
2090
2108
|
else {
|
|
2091
2109
|
contextTokens = calculateContextTokens(assistantMessage.usage);
|
|
2092
2110
|
}
|
|
2111
|
+
// K3 auto context tier: reaching the 256k cutoff upgrades to the 1M tier
|
|
2112
|
+
// instead of compacting. This is model-capability management, not context
|
|
2113
|
+
// reduction, so it applies even when compaction is disabled. The cutoff is
|
|
2114
|
+
// fixed at the default compaction threshold of the 256k window; a
|
|
2115
|
+
// user-lowered compaction threshold takes precedence and effectively
|
|
2116
|
+
// disables the upgrade.
|
|
2117
|
+
if (shouldUpgradeK3Tier(this.model, contextTokens)) {
|
|
2118
|
+
// A user-lowered compaction threshold takes precedence over the
|
|
2119
|
+
// upgrade: if the user's compact point for the 256k window sits below
|
|
2120
|
+
// the default cutoff and is already exceeded, compact instead.
|
|
2121
|
+
const userCompactPoint = K3_256K_CONTEXT_WINDOW - settings.reserveTokens;
|
|
2122
|
+
const userThresholdPreempts = settings.enabled && userCompactPoint < K3_UPGRADE_CUTOFF_TOKENS && contextTokens > userCompactPoint;
|
|
2123
|
+
if (!userThresholdPreempts) {
|
|
2124
|
+
this._tryUpgradeK3ContextTier();
|
|
2125
|
+
contextWindow = this.model?.contextWindow ?? contextWindow;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
if (!settings.enabled)
|
|
2129
|
+
return;
|
|
2093
2130
|
if (shouldCompact(contextTokens, contextWindow, settings)) {
|
|
2094
2131
|
await this._runAutoCompaction("threshold", false);
|
|
2095
2132
|
}
|
|
2096
2133
|
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Apply the K3 auto context tier to a model being set on the agent. The
|
|
2136
|
+
* user-facing `k3` model runs on the cheaper `k3-256k` wire model ID until
|
|
2137
|
+
* the session context grows past the 256k cutoff; no-op for other models.
|
|
2138
|
+
* See k3-context-tier.ts.
|
|
2139
|
+
*/
|
|
2140
|
+
_applyContextTier(model) {
|
|
2141
|
+
return deriveK3ContextTierModel(model, estimateContextTokens(this.agent.state.messages).tokens);
|
|
2142
|
+
}
|
|
2143
|
+
/** Remove the last message from agent state when it is an assistant message. */
|
|
2144
|
+
_removeLastAssistantMessage() {
|
|
2145
|
+
const messages = this.agent.state.messages;
|
|
2146
|
+
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
2147
|
+
this.agent.replaceMessages(messages.slice(0, -1));
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Upgrade the K3 auto context tier from 256k to 1M. The Kimi backend
|
|
2152
|
+
* upgrades the prompt cache seamlessly, so no context is lost or
|
|
2153
|
+
* compacted. Returns true when the upgrade was applied.
|
|
2154
|
+
*/
|
|
2155
|
+
_tryUpgradeK3ContextTier() {
|
|
2156
|
+
const model = this.model;
|
|
2157
|
+
if (!model || !isK3256kTier(model))
|
|
2158
|
+
return false;
|
|
2159
|
+
const upgraded = deriveK3ContextTierModel(model, K3_UPGRADE_CUTOFF_TOKENS + 1);
|
|
2160
|
+
this.agent.setModel(upgraded);
|
|
2161
|
+
this._emit({
|
|
2162
|
+
type: "context_window_upgrade",
|
|
2163
|
+
provider: upgraded.provider,
|
|
2164
|
+
modelId: upgraded.id,
|
|
2165
|
+
fromContextWindow: K3_256K_CONTEXT_WINDOW,
|
|
2166
|
+
toContextWindow: K3_1M_CONTEXT_WINDOW,
|
|
2167
|
+
});
|
|
2168
|
+
return true;
|
|
2169
|
+
}
|
|
2097
2170
|
/**
|
|
2098
2171
|
* Internal: Run auto-compaction with events.
|
|
2099
2172
|
*/
|
|
@@ -2163,6 +2236,11 @@ export class AgentSession {
|
|
|
2163
2236
|
const newEntries = this.sessionManager.getEntries();
|
|
2164
2237
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2165
2238
|
this.agent.replaceMessages(sessionContext.messages);
|
|
2239
|
+
// Re-derive the K3 context tier: the compacted context is small again,
|
|
2240
|
+
// so the session returns to the cheaper 256k wire tier.
|
|
2241
|
+
if (this.model) {
|
|
2242
|
+
this.agent.setModel(this._applyContextTier(this.model));
|
|
2243
|
+
}
|
|
2166
2244
|
// Get the saved compaction entry for the extension event
|
|
2167
2245
|
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
2168
2246
|
if (this._extensionRunner && savedCompactionEntry) {
|
|
@@ -2305,7 +2383,7 @@ export class AgentSession {
|
|
|
2305
2383
|
if (!refreshedModel || refreshedModel === currentModel) {
|
|
2306
2384
|
return;
|
|
2307
2385
|
}
|
|
2308
|
-
this.agent.setModel(refreshedModel);
|
|
2386
|
+
this.agent.setModel(this._applyContextTier(refreshedModel));
|
|
2309
2387
|
this._refreshThinkingDisplay(refreshedModel);
|
|
2310
2388
|
}
|
|
2311
2389
|
_bindExtensionCore(runner) {
|
|
@@ -2875,7 +2953,7 @@ export class AgentSession {
|
|
|
2875
2953
|
const availableModels = await this._modelRegistry.getAvailable();
|
|
2876
2954
|
const match = availableModels.find((m) => m.provider === sessionContext.model.provider && m.id === sessionContext.model.modelId);
|
|
2877
2955
|
if (match) {
|
|
2878
|
-
this.agent.setModel(match);
|
|
2956
|
+
this.agent.setModel(this._applyContextTier(match));
|
|
2879
2957
|
this._refreshThinkingDisplay(match);
|
|
2880
2958
|
await this._emitModelSelect(match, previousModel, "restore");
|
|
2881
2959
|
}
|