@kenkaiiii/ggcoder 5.19.0 → 5.19.2
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/app-sidecar.js +15 -1
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-compaction.test.js +437 -9
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-review-coverage.test.js +26 -0
- package/dist/core/agent-session-review-coverage.test.js.map +1 -1
- package/dist/core/agent-session-tool-result-policy.test.js +14 -1
- package/dist/core/agent-session-tool-result-policy.test.js.map +1 -1
- package/dist/core/agent-session.d.ts +21 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +175 -33
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/active-context.d.ts +17 -0
- package/dist/core/compaction/active-context.d.ts.map +1 -0
- package/dist/core/compaction/active-context.js +20 -0
- package/dist/core/compaction/active-context.js.map +1 -0
- package/dist/core/compaction/active-context.test.d.ts +2 -0
- package/dist/core/compaction/active-context.test.d.ts.map +1 -0
- package/dist/core/compaction/active-context.test.js +36 -0
- package/dist/core/compaction/active-context.test.js.map +1 -0
- package/dist/core/compaction/compactor.d.ts +10 -17
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +21 -33
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +74 -66
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/compaction/token-estimator.d.ts +25 -1
- package/dist/core/compaction/token-estimator.d.ts.map +1 -1
- package/dist/core/compaction/token-estimator.js +86 -1
- package/dist/core/compaction/token-estimator.js.map +1 -1
- package/dist/core/compaction/token-estimator.test.js +147 -1
- package/dist/core/compaction/token-estimator.test.js.map +1 -1
- package/dist/core/compaction/tool-result-pruner.d.ts +37 -0
- package/dist/core/compaction/tool-result-pruner.d.ts.map +1 -0
- package/dist/core/compaction/tool-result-pruner.js +103 -0
- package/dist/core/compaction/tool-result-pruner.js.map +1 -0
- package/dist/core/compaction/tool-result-pruner.test.d.ts +2 -0
- package/dist/core/compaction/tool-result-pruner.test.d.ts.map +1 -0
- package/dist/core/compaction/tool-result-pruner.test.js +148 -0
- package/dist/core/compaction/tool-result-pruner.test.js.map +1 -0
- package/dist/core/ideal-review.d.ts +6 -0
- package/dist/core/ideal-review.d.ts.map +1 -1
- package/dist/core/ideal-review.js +14 -0
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/ideal-review.test.js +10 -1
- package/dist/core/ideal-review.test.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/settings-manager.js +2 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/tools/bash.d.ts +9 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +28 -18
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/bash.test.d.ts +2 -0
- package/dist/tools/bash.test.d.ts.map +1 -0
- package/dist/tools/bash.test.js +56 -0
- package/dist/tools/bash.test.js.map +1 -0
- package/dist/tools/overflow.d.ts +12 -2
- package/dist/tools/overflow.d.ts.map +1 -1
- package/dist/tools/overflow.js +49 -4
- package/dist/tools/overflow.js.map +1 -1
- package/dist/tools/overflow.test.d.ts +2 -0
- package/dist/tools/overflow.test.d.ts.map +1 -0
- package/dist/tools/overflow.test.js +62 -0
- package/dist/tools/overflow.test.js.map +1 -0
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +3 -16
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +2 -4
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +6 -2
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.test.js +31 -0
- package/dist/ui/hooks/useAgentLoop.test.js.map +1 -1
- package/dist/ui/hooks/useContextCompaction.d.ts +5 -8
- package/dist/ui/hooks/useContextCompaction.d.ts.map +1 -1
- package/dist/ui/hooks/useContextCompaction.js +77 -16
- package/dist/ui/hooks/useContextCompaction.js.map +1 -1
- package/dist/ui/hooks/useContextCompaction.test.d.ts +2 -0
- package/dist/ui/hooks/useContextCompaction.test.d.ts.map +1 -0
- package/dist/ui/hooks/useContextCompaction.test.js +135 -0
- package/dist/ui/hooks/useContextCompaction.test.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { resolveSessionToolResultCharLimit } from "./agent-session.js";
|
|
2
|
+
import { resolveSessionToolResultCharLimit, resolveSessionTurnToolResultCharLimit, } from "./agent-session.js";
|
|
3
3
|
describe("AgentSession tool-result policy", () => {
|
|
4
4
|
it("passes the Codex 10k-token approximation for OpenAI OAuth sessions", () => {
|
|
5
5
|
expect(resolveSessionToolResultCharLimit("gpt-5.6-sol", "openai", "acct_123")).toBe(40_000);
|
|
@@ -9,4 +9,17 @@ describe("AgentSession tool-result policy", () => {
|
|
|
9
9
|
expect(resolveSessionToolResultCharLimit("gpt-5.6-sol", "openai")).toBe(1_102_500);
|
|
10
10
|
});
|
|
11
11
|
});
|
|
12
|
+
describe("AgentSession per-turn tool-result budget", () => {
|
|
13
|
+
it("scales with the context window at 15% of context chars", () => {
|
|
14
|
+
// claude-sonnet-5: 1M-token window → ceiling applies.
|
|
15
|
+
expect(resolveSessionTurnToolResultCharLimit("claude-sonnet-5", "anthropic", "acct_123")).toBe(240_000);
|
|
16
|
+
// OpenAI public API gpt-5.6-sol: 15% of ctx*3.5, within floor/ceiling.
|
|
17
|
+
const publicApi = resolveSessionTurnToolResultCharLimit("gpt-5.6-sol", "openai");
|
|
18
|
+
expect(publicApi).toBeGreaterThanOrEqual(100_000);
|
|
19
|
+
expect(publicApi).toBeLessThanOrEqual(240_000);
|
|
20
|
+
});
|
|
21
|
+
it("floors at 100KB so small windows still allow two full-size reads", () => {
|
|
22
|
+
expect(resolveSessionTurnToolResultCharLimit("unknown-model", "openai", "acct_123")).toBeGreaterThanOrEqual(100_000);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
12
25
|
//# sourceMappingURL=agent-session-tool-result-policy.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-tool-result-policy.test.js","sourceRoot":"","sources":["../../src/core/agent-session-tool-result-policy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"agent-session-tool-result-policy.test.js","sourceRoot":"","sources":["../../src/core/agent-session-tool-result-policy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAE5B,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,CAAC,iCAAiC,CAAC,aAAa,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,CAAC,iCAAiC,CAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CACxF,SAAS,CACV,CAAC;QACF,MAAM,CAAC,iCAAiC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,sDAAsD;QACtD,MAAM,CAAC,qCAAqC,CAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAC5F,OAAO,CACR,CAAC;QACF,uEAAuE;QACvE,MAAM,SAAS,GAAG,qCAAqC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACjF,MAAM,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CACJ,qCAAqC,CAAC,eAAe,EAAE,QAAQ,EAAE,UAAU,CAAC,CAC7E,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -125,6 +125,15 @@ export interface AgentSessionOptions {
|
|
|
125
125
|
}
|
|
126
126
|
/** Resolve the per-result cap passed to the agent loop for the active transport. */
|
|
127
127
|
export declare function resolveSessionToolResultCharLimit(model: string, provider: Provider, accountId?: string): number;
|
|
128
|
+
/**
|
|
129
|
+
* Aggregate budget for ALL tool results produced in one assistant turn.
|
|
130
|
+
* Individual results are already capped, but wide parallel fan-outs (GPT-5.6's
|
|
131
|
+
* signature behavior) were observed injecting 100k+ uncached tokens in a single
|
|
132
|
+
* turn. ~15% of the context window in chars (1 token ≈ 3.5 chars), floored at
|
|
133
|
+
* 100KB so small windows still fit two full-size reads, ceilinged at 240KB so
|
|
134
|
+
* 1M-context models don't waive the budget entirely.
|
|
135
|
+
*/
|
|
136
|
+
export declare function resolveSessionTurnToolResultCharLimit(model: string, provider: Provider, accountId?: string): number;
|
|
128
137
|
export interface AgentSessionState {
|
|
129
138
|
provider: Provider;
|
|
130
139
|
model: string;
|
|
@@ -165,10 +174,16 @@ export declare class AgentSession {
|
|
|
165
174
|
private hookFileEditCounts;
|
|
166
175
|
private hookToolCalls;
|
|
167
176
|
private idealReviewPhase;
|
|
177
|
+
/** Runtime-only suppression while Ken owns verification in autopilot mode. */
|
|
178
|
+
private idealReviewSuppressed;
|
|
168
179
|
private readonly reviewCoverage;
|
|
169
180
|
private loopBreakInjected;
|
|
170
181
|
private regroundingInjected;
|
|
171
182
|
private compactionOccurred;
|
|
183
|
+
private lastCompactionCompacted;
|
|
184
|
+
private compactionRetryAfter;
|
|
185
|
+
/** Latest provider count, anchored to the assistant response it measured. */
|
|
186
|
+
private providerContext;
|
|
172
187
|
private originalRequest;
|
|
173
188
|
private userQueue;
|
|
174
189
|
private processManager?;
|
|
@@ -324,6 +339,12 @@ export declare class AgentSession {
|
|
|
324
339
|
listBranches(): Promise<BranchInfo[]>;
|
|
325
340
|
getState(): AgentSessionState;
|
|
326
341
|
getPlanMode(): boolean;
|
|
342
|
+
/**
|
|
343
|
+
* Suppress only the pre-final Ideal self-review for this live session.
|
|
344
|
+
* Autopilot uses this while Ken independently owns verification; loop-break
|
|
345
|
+
* and post-compaction re-grounding remain active.
|
|
346
|
+
*/
|
|
347
|
+
setIdealReviewSuppressed(suppressed: boolean): void;
|
|
327
348
|
/** Queue a user message (optionally with attachments) to be injected mid-run
|
|
328
349
|
* as steering. Returns the new queue length. No-op semantics are the caller's
|
|
329
350
|
* concern. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ import { getClaudeCliUserAgent } from "./claude-code-version.js";
|
|
|
11
11
|
import { kimiCodingHeaders, isKimiCodingEndpoint } from "./oauth/kimi.js";
|
|
12
12
|
import { SessionManager, KEN_TURN_CUSTOM_KIND, AUTOPILOT_MARKER_CUSTOM_KIND, APP_MARKER_CUSTOM_KIND, } from "./session-manager.js";
|
|
13
13
|
import { ExtensionLoader } from "./extensions/loader.js";
|
|
14
|
-
import { shouldCompact, compact
|
|
14
|
+
import { shouldCompact, compact } from "./compaction/compactor.js";
|
|
15
15
|
import { getAuthStorageKeys, getContextWindow, getModel, getToolResultCharLimit, MODELS, } from "./model-registry.js";
|
|
16
16
|
import { discoverSkills } from "./skills.js";
|
|
17
17
|
import { ensureAppDirs } from "../config.js";
|
|
@@ -23,11 +23,13 @@ import { MCPClientManager, getAllMcpServers } from "./mcp/index.js";
|
|
|
23
23
|
import { DeferredToolCatalog } from "./mcp/deferred-catalog.js";
|
|
24
24
|
import { createToolSearchTool } from "../tools/tool-search.js";
|
|
25
25
|
import { log } from "./logger.js";
|
|
26
|
-
import { setEstimatorModel } from "./compaction/token-estimator.js";
|
|
26
|
+
import { setEstimatorModel, calibrateEstimatorFromUsage } from "./compaction/token-estimator.js";
|
|
27
|
+
import { calculateActiveContextTokens } from "./compaction/active-context.js";
|
|
28
|
+
import { pruneStaleToolResults } from "./compaction/tool-result-pruner.js";
|
|
27
29
|
import { discoverAgents } from "./agents.js";
|
|
28
30
|
import { enhancePrompt } from "../utils/prompt-enhancer.js";
|
|
29
31
|
import { detectProjectStack } from "./language-detector.js";
|
|
30
|
-
import { evaluateIdealReview, buildIdealReviewMessage, buildReviewCoverageMessage, detectTestDrift, ReviewCoverageTracker, } from "./ideal-review.js";
|
|
32
|
+
import { evaluateIdealReview, buildIdealReviewMessage, buildReviewCoverageMessage, withReviewCoverageRequirements, detectTestDrift, ReviewCoverageTracker, } from "./ideal-review.js";
|
|
31
33
|
import { evaluateLoopBreak, buildLoopBreakMessage, ToolCallProgressTracker, detectTextRepetition, } from "./loop-breaker.js";
|
|
32
34
|
import { buildRegroundingMessage } from "./regrounding.js";
|
|
33
35
|
import { wrapSteeringText, STEERING_PREFIX } from "./steering.js";
|
|
@@ -41,6 +43,18 @@ export function resolveSessionToolResultCharLimit(model, provider, accountId) {
|
|
|
41
43
|
return (getToolResultCharLimit(model, { provider, accountId }) ??
|
|
42
44
|
Math.floor(getContextWindow(model, { provider, accountId }) * 3.5 * 0.3));
|
|
43
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Aggregate budget for ALL tool results produced in one assistant turn.
|
|
48
|
+
* Individual results are already capped, but wide parallel fan-outs (GPT-5.6's
|
|
49
|
+
* signature behavior) were observed injecting 100k+ uncached tokens in a single
|
|
50
|
+
* turn. ~15% of the context window in chars (1 token ≈ 3.5 chars), floored at
|
|
51
|
+
* 100KB so small windows still fit two full-size reads, ceilinged at 240KB so
|
|
52
|
+
* 1M-context models don't waive the budget entirely.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveSessionTurnToolResultCharLimit(model, provider, accountId) {
|
|
55
|
+
const contextChars = getContextWindow(model, { provider, accountId }) * 3.5;
|
|
56
|
+
return Math.max(100_000, Math.min(Math.floor(contextChars * 0.15), 240_000));
|
|
57
|
+
}
|
|
44
58
|
// ── Agent Session ──────────────────────────────────────────
|
|
45
59
|
export class AgentSession {
|
|
46
60
|
eventBus = new EventBus();
|
|
@@ -94,10 +108,16 @@ export class AgentSession {
|
|
|
94
108
|
hookFileEditCounts = new Map();
|
|
95
109
|
hookToolCalls = new Map();
|
|
96
110
|
idealReviewPhase = "idle";
|
|
111
|
+
/** Runtime-only suppression while Ken owns verification in autopilot mode. */
|
|
112
|
+
idealReviewSuppressed = false;
|
|
97
113
|
reviewCoverage;
|
|
98
114
|
loopBreakInjected = false;
|
|
99
115
|
regroundingInjected = false;
|
|
100
116
|
compactionOccurred = false;
|
|
117
|
+
lastCompactionCompacted = false;
|
|
118
|
+
compactionRetryAfter = 0;
|
|
119
|
+
/** Latest provider count, anchored to the assistant response it measured. */
|
|
120
|
+
providerContext = null;
|
|
101
121
|
originalRequest = "";
|
|
102
122
|
// Messages queued by the user while a run is in flight. Drained at the
|
|
103
123
|
// mid-loop steering boundary (user steering wins over the hooks), mirroring
|
|
@@ -635,6 +655,13 @@ export class AgentSession {
|
|
|
635
655
|
}
|
|
636
656
|
case "turn_end":
|
|
637
657
|
this.hookStats.turns = event.turn;
|
|
658
|
+
for (let index = this.messages.length - 1; index >= 0; index--) {
|
|
659
|
+
const anchor = this.messages[index];
|
|
660
|
+
if (anchor?.role === "assistant") {
|
|
661
|
+
this.providerContext = { usage: { ...event.usage }, anchor };
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
638
665
|
await this.persistTurnMetric(event);
|
|
639
666
|
break;
|
|
640
667
|
}
|
|
@@ -702,7 +729,7 @@ export class AgentSession {
|
|
|
702
729
|
const childCompletionFollowUp = buildSubAgentCompletionFollowUp(this.subAgentManager);
|
|
703
730
|
if (childCompletionFollowUp)
|
|
704
731
|
return childCompletionFollowUp;
|
|
705
|
-
if (this.opts.selfCorrectionHooks === false)
|
|
732
|
+
if (this.opts.selfCorrectionHooks === false || this.idealReviewSuppressed)
|
|
706
733
|
return null;
|
|
707
734
|
if (this.idealReviewPhase === "reviewing") {
|
|
708
735
|
const coverage = this.reviewCoverage.evidence();
|
|
@@ -747,7 +774,7 @@ export class AgentSession {
|
|
|
747
774
|
lspMissing: lspEvidence.missing,
|
|
748
775
|
});
|
|
749
776
|
return [
|
|
750
|
-
this.withReviewLspEvidence(buildIdealReviewMessage(decision.reasons, driftedFiles), lspEvidence),
|
|
777
|
+
this.withReviewLspEvidence(withReviewCoverageRequirements(buildIdealReviewMessage(decision.reasons, driftedFiles), coverage.missing), lspEvidence),
|
|
751
778
|
];
|
|
752
779
|
}
|
|
753
780
|
reviewLspEvidence(files) {
|
|
@@ -807,24 +834,45 @@ export class AgentSession {
|
|
|
807
834
|
this.lastAccountId = creds.accountId;
|
|
808
835
|
// Auto-compact if needed. This must happen after credential resolution so
|
|
809
836
|
// OpenAI OAuth/Codex sessions use the Codex product context window instead
|
|
810
|
-
// of the public API model window.
|
|
811
|
-
|
|
837
|
+
// of the public API model window. Failed/no-op attempts cool down across
|
|
838
|
+
// prompts; provider overflow recovery still bypasses this path entirely.
|
|
839
|
+
if (this.settingsManager.get("autoCompact") && Date.now() >= this.compactionRetryAfter) {
|
|
812
840
|
const contextWindow = getContextWindow(this.model, {
|
|
813
841
|
provider: this.provider,
|
|
814
842
|
accountId: creds.accountId,
|
|
815
843
|
});
|
|
816
844
|
const threshold = this.settingsManager.get("compactThreshold");
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
845
|
+
let activeTokens;
|
|
846
|
+
if (this.providerContext) {
|
|
847
|
+
const anchorIndex = this.messages.lastIndexOf(this.providerContext.anchor);
|
|
848
|
+
if (anchorIndex >= 0) {
|
|
849
|
+
activeTokens = calculateActiveContextTokens(this.messages, {
|
|
850
|
+
usage: this.providerContext.usage,
|
|
851
|
+
pendingMessages: this.messages.slice(anchorIndex + 1),
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
else {
|
|
855
|
+
this.providerContext = null;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (shouldCompact(this.messages, contextWindow, threshold, activeTokens)) {
|
|
859
|
+
try {
|
|
860
|
+
await this.compact(creds);
|
|
861
|
+
if (this.lastCompactionCompacted) {
|
|
862
|
+
// Re-grounding hook keys off this — the context was just summarized.
|
|
863
|
+
this.compactionOccurred = true;
|
|
864
|
+
this.compactionRetryAfter = 0;
|
|
865
|
+
}
|
|
866
|
+
else {
|
|
867
|
+
this.compactionRetryAfter = Date.now() + 30_000;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
catch (error) {
|
|
871
|
+
this.compactionRetryAfter = Date.now() + 30_000;
|
|
872
|
+
if (isAbortError(error) || this.opts.signal?.aborted)
|
|
873
|
+
throw error;
|
|
874
|
+
log("WARN", "compaction", `Pre-run compaction failed; cooling down for 30s: ${error instanceof Error ? error.message : String(error)}`);
|
|
875
|
+
}
|
|
828
876
|
}
|
|
829
877
|
}
|
|
830
878
|
const userAgent = this.provider === "anthropic" ? await getClaudeCliUserAgent() : undefined;
|
|
@@ -861,26 +909,96 @@ export class AgentSession {
|
|
|
861
909
|
// Codex caps each tool output at 10K tokens. Other transports retain the
|
|
862
910
|
// generic 30%-of-context allowance used before this provider policy.
|
|
863
911
|
maxToolResultChars: resolveSessionToolResultCharLimit(this.model, this.provider, accountId),
|
|
912
|
+
// Aggregate per-turn budget across parallel tool results (fan-out guard).
|
|
913
|
+
maxTurnToolResultChars: resolveSessionTurnToolResultCharLimit(this.model, this.provider, accountId),
|
|
864
914
|
// Self-correction hooks (same as the TUI): loop-break + re-grounding are
|
|
865
915
|
// polled mid-loop; the ideal review is polled when the agent would stop.
|
|
866
916
|
getSteeringMessages: () => this.getHookSteeringMessages(),
|
|
867
917
|
getFollowUpMessages: () => this.getHookFollowUpMessages(),
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
// loop retries with a smaller request, instead of surfacing the error.
|
|
872
|
-
// Without this the desktop app (which drives the loop through
|
|
873
|
-
// AgentSession, not the TUI's useContextCompaction hook) had NO auto
|
|
874
|
-
// recovery on 413 — the error went straight to the user. The non-force
|
|
875
|
-
// pre-call invocations pass through untouched: pre-turn compaction is
|
|
876
|
-
// already handled above, so we only act on the overflow force path.
|
|
877
|
-
// `loopMessages === this.messages` (prepareDynamicContext returns it by
|
|
878
|
-
// reference) and the post-loop `this.messages = loopMessages` re-sync
|
|
879
|
-
// keeps persistence correct after compact() swaps the array.
|
|
918
|
+
// Check authoritative provider usage before every model/tool step.
|
|
919
|
+
// Forced overflow recovery bypasses settings and cooldown; proactive
|
|
920
|
+
// checks honor both and estimate only messages unseen by the provider.
|
|
880
921
|
transformContext: async (messages, transformOpts) => {
|
|
881
|
-
if (
|
|
922
|
+
if (transformOpts.usage) {
|
|
923
|
+
const anchorIndex = messages.length - transformOpts.pendingMessages.length - 1;
|
|
924
|
+
const anchor = messages[anchorIndex];
|
|
925
|
+
if (anchor?.role === "assistant") {
|
|
926
|
+
this.providerContext = { usage: { ...transformOpts.usage }, anchor };
|
|
927
|
+
// Feed the authoritative usage back into the token estimator so
|
|
928
|
+
// char-based estimates track this session's real tokenizer.
|
|
929
|
+
calibrateEstimatorFromUsage(messages.slice(0, anchorIndex), transformOpts.usage);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
const force = transformOpts.force === true;
|
|
933
|
+
if (!force) {
|
|
934
|
+
if (!this.settingsManager.get("autoCompact"))
|
|
935
|
+
return messages;
|
|
936
|
+
// Cheap stale-tool-output pruning before the expensive LLM
|
|
937
|
+
// compaction check. In-place mutation preserves anchors; drop the
|
|
938
|
+
// retained usage afterwards since it counted the pruned content.
|
|
939
|
+
const pruneResult = pruneStaleToolResults(messages);
|
|
940
|
+
if (pruneResult.pruned) {
|
|
941
|
+
this.providerContext = null;
|
|
942
|
+
log("INFO", "compaction", "Pruned stale tool outputs", {
|
|
943
|
+
prunedResults: String(pruneResult.prunedResults),
|
|
944
|
+
freedTokens: String(pruneResult.freedTokens),
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
if (Date.now() < this.compactionRetryAfter)
|
|
948
|
+
return messages;
|
|
949
|
+
// The turn's own usage also counted the pruned content — after a
|
|
950
|
+
// prune, fall back to estimating the (now smaller) history so the
|
|
951
|
+
// freed tokens actually defer the LLM compaction.
|
|
952
|
+
let usage = pruneResult.pruned ? undefined : transformOpts.usage;
|
|
953
|
+
let pendingMessages = transformOpts.pendingMessages;
|
|
954
|
+
if (!usage && this.providerContext) {
|
|
955
|
+
const anchorIndex = messages.lastIndexOf(this.providerContext.anchor);
|
|
956
|
+
if (anchorIndex >= 0) {
|
|
957
|
+
usage = this.providerContext.usage;
|
|
958
|
+
pendingMessages = messages.slice(anchorIndex + 1);
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
this.providerContext = null;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
const contextWindow = getContextWindow(this.model, {
|
|
965
|
+
provider: this.provider,
|
|
966
|
+
accountId,
|
|
967
|
+
});
|
|
968
|
+
const threshold = this.settingsManager.get("compactThreshold");
|
|
969
|
+
const activeTokens = calculateActiveContextTokens(messages, {
|
|
970
|
+
usage,
|
|
971
|
+
pendingMessages,
|
|
972
|
+
});
|
|
973
|
+
if (!shouldCompact(messages, contextWindow, threshold, activeTokens))
|
|
974
|
+
return messages;
|
|
975
|
+
}
|
|
976
|
+
// compact() operates on this.messages, while an earlier transform may
|
|
977
|
+
// have replaced the loop's in-flight array. Rebind before every attempt
|
|
978
|
+
// so the current tool results are included in the summary.
|
|
979
|
+
this.messages = messages;
|
|
980
|
+
try {
|
|
981
|
+
await this.compact({
|
|
982
|
+
accessToken: apiKey,
|
|
983
|
+
accountId,
|
|
984
|
+
projectId,
|
|
985
|
+
baseUrl: effectiveBaseUrl,
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
catch (error) {
|
|
989
|
+
this.messages = messages;
|
|
990
|
+
this.compactionRetryAfter = Date.now() + 30_000;
|
|
991
|
+
if (force || isAbortError(error) || this.opts.signal?.aborted)
|
|
992
|
+
throw error;
|
|
993
|
+
log("WARN", "compaction", `In-flight compaction failed; cooling down for 30s: ${error instanceof Error ? error.message : String(error)}`);
|
|
882
994
|
return messages;
|
|
883
|
-
|
|
995
|
+
}
|
|
996
|
+
if (!this.lastCompactionCompacted) {
|
|
997
|
+
this.messages = messages;
|
|
998
|
+
this.compactionRetryAfter = Date.now() + 30_000;
|
|
999
|
+
return messages;
|
|
1000
|
+
}
|
|
1001
|
+
this.compactionRetryAfter = 0;
|
|
884
1002
|
this.compactionOccurred = true;
|
|
885
1003
|
return this.messages;
|
|
886
1004
|
},
|
|
@@ -977,6 +1095,7 @@ export class AgentSession {
|
|
|
977
1095
|
if (provider)
|
|
978
1096
|
this.provider = provider;
|
|
979
1097
|
this.model = model;
|
|
1098
|
+
this.providerContext = null;
|
|
980
1099
|
// Keep host-provided option closures (notably chat delegation) aligned with
|
|
981
1100
|
// the live selection after an in-session model switch.
|
|
982
1101
|
this.opts.provider = this.provider;
|
|
@@ -1054,6 +1173,7 @@ export class AgentSession {
|
|
|
1054
1173
|
}
|
|
1055
1174
|
}
|
|
1056
1175
|
async compact(existingCredentials) {
|
|
1176
|
+
this.lastCompactionCompacted = false;
|
|
1057
1177
|
const creds = existingCredentials ??
|
|
1058
1178
|
(await this.authStorage.resolveCredentials(this.provider, {
|
|
1059
1179
|
storageKeys: this.currentAuthStorageKeys(),
|
|
@@ -1074,6 +1194,15 @@ export class AgentSession {
|
|
|
1074
1194
|
signal: this.opts.signal,
|
|
1075
1195
|
});
|
|
1076
1196
|
this.messages = result.messages;
|
|
1197
|
+
this.lastCompactionCompacted = result.result.compacted;
|
|
1198
|
+
if (!result.result.compacted) {
|
|
1199
|
+
this.eventBus.emit("compaction_end", {
|
|
1200
|
+
originalCount: result.result.originalCount,
|
|
1201
|
+
newCount: result.result.newCount,
|
|
1202
|
+
});
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
this.providerContext = null;
|
|
1077
1206
|
// Transient sessions (Ken chat/autopilot, subagent spawns) must NEVER touch
|
|
1078
1207
|
// the session store: without this guard, the first auto-compaction called
|
|
1079
1208
|
// sessionManager.create() and assigned a real sessionPath, silently turning
|
|
@@ -1224,6 +1353,18 @@ export class AgentSession {
|
|
|
1224
1353
|
getPlanMode() {
|
|
1225
1354
|
return this.planModeRef.current;
|
|
1226
1355
|
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Suppress only the pre-final Ideal self-review for this live session.
|
|
1358
|
+
* Autopilot uses this while Ken independently owns verification; loop-break
|
|
1359
|
+
* and post-compaction re-grounding remain active.
|
|
1360
|
+
*/
|
|
1361
|
+
setIdealReviewSuppressed(suppressed) {
|
|
1362
|
+
this.idealReviewSuppressed = suppressed;
|
|
1363
|
+
if (suppressed) {
|
|
1364
|
+
this.idealReviewPhase = "idle";
|
|
1365
|
+
this.reviewCoverage.reset();
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1227
1368
|
/** Queue a user message (optionally with attachments) to be injected mid-run
|
|
1228
1369
|
* as steering. Returns the new queue length. No-op semantics are the caller's
|
|
1229
1370
|
* concern. */
|
|
@@ -1672,7 +1813,8 @@ export class AgentSession {
|
|
|
1672
1813
|
provider: this.provider,
|
|
1673
1814
|
accountId: creds.accountId,
|
|
1674
1815
|
});
|
|
1675
|
-
const needsLoadCompaction =
|
|
1816
|
+
const needsLoadCompaction = this.settingsManager.get("autoCompact") &&
|
|
1817
|
+
shouldCompact(this.messages, contextWindow, this.settingsManager.get("compactThreshold"));
|
|
1676
1818
|
if (needsLoadCompaction && this.opts.deferLoadCompaction) {
|
|
1677
1819
|
// Host readiness is gated on initialize() — don't block it on a summary
|
|
1678
1820
|
// LLM call (up to 30s). runLoop()'s pre-run auto-compaction picks this
|