@astralyn/pi 0.84.11 → 0.84.12
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/CHANGELOG.md +21 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session.d.ts +62 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +395 -78
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +19 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +44 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +5 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/background/actions.d.ts +21 -0
- package/dist/extensions/background/actions.d.ts.map +1 -0
- package/dist/extensions/background/actions.js +264 -0
- package/dist/extensions/background/actions.js.map +1 -0
- package/dist/extensions/background/constants.d.ts +24 -0
- package/dist/extensions/background/constants.d.ts.map +1 -0
- package/dist/extensions/background/constants.js +24 -0
- package/dist/extensions/background/constants.js.map +1 -0
- package/dist/extensions/background/index.d.ts +6 -115
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +38 -509
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +2 -1
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +8 -10
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/notify.d.ts +16 -0
- package/dist/extensions/background/notify.d.ts.map +1 -0
- package/dist/extensions/background/notify.js +114 -0
- package/dist/extensions/background/notify.js.map +1 -0
- package/dist/extensions/background/output-file.d.ts +58 -0
- package/dist/extensions/background/output-file.d.ts.map +1 -0
- package/dist/extensions/background/output-file.js +122 -0
- package/dist/extensions/background/output-file.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +40 -72
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +71 -184
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/render.d.ts +3 -10
- package/dist/extensions/background/render.d.ts.map +1 -1
- package/dist/extensions/background/render.js +20 -60
- package/dist/extensions/background/render.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +34 -0
- package/dist/extensions/background/schema.d.ts.map +1 -0
- package/dist/extensions/background/schema.js +89 -0
- package/dist/extensions/background/schema.js.map +1 -0
- package/dist/extensions/background/task-view.d.ts +48 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -0
- package/dist/extensions/background/task-view.js +90 -0
- package/dist/extensions/background/task-view.js.map +1 -0
- package/dist/extensions/background/text.d.ts +15 -0
- package/dist/extensions/background/text.d.ts.map +1 -0
- package/dist/extensions/background/text.js +31 -0
- package/dist/extensions/background/text.js.map +1 -0
- package/dist/extensions/background/types.d.ts +74 -0
- package/dist/extensions/background/types.d.ts.map +1 -0
- package/dist/extensions/background/types.js +17 -0
- package/dist/extensions/background/types.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +6 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -0
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts +3 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +27 -6
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +5 -0
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +5 -0
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +6 -391
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +1 -0
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +15 -1
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +2 -4
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +8 -8
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +11 -0
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +90 -79
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts.map +1 -1
- package/dist/extensions/subagent/state.js +145 -126
- package/dist/extensions/subagent/state.js.map +1 -1
- package/dist/extensions/subagent/text.d.ts.map +1 -1
- package/dist/extensions/subagent/text.js +4 -0
- package/dist/extensions/subagent/text.js.map +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.d.ts +4 -0
- package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/agents-dialog.js +84 -0
- package/dist/extensions/subagent/ui/agents-dialog.js.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts +39 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.js +93 -0
- package/dist/extensions/subagent/ui/choice-menu.js.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts +47 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.js +142 -0
- package/dist/extensions/subagent/ui/model-picker.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +41 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js +98 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +71 -58
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +6 -4
- package/dist/utils/shell.js.map +1 -1
- package/docs/compaction.md +5 -12
- package/docs/environment-variables.md +3 -0
- package/docs/extensions.md +21 -5
- package/docs/keybindings.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +23 -0
- package/docs/settings.md +7 -0
- package/docs/terminal-setup.md +12 -0
- package/docs/usage.md +4 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +6 -6
- package/dist/core/compaction-controller.d.ts +0 -90
- package/dist/core/compaction-controller.d.ts.map +0 -1
- package/dist/core/compaction-controller.js +0 -471
- package/dist/core/compaction-controller.js.map +0 -1
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import type { Agent, AgentMessage, PrepareNextTurnContext, ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { AssistantMessage, Model } from "@earendil-works/pi-ai/compat";
|
|
3
|
-
import { type RetryCallbacks } from "@earendil-works/pi-ai/compat";
|
|
4
|
-
import type { AgentSessionEvent } from "./agent-session.ts";
|
|
5
|
-
import type { CompactionTiming, ExtensionRunner, SessionCompactFailedEvent } from "./extensions/index.ts";
|
|
6
|
-
import type { SessionManager } from "./session-manager.ts";
|
|
7
|
-
import type { SettingsManager } from "./settings-manager.ts";
|
|
8
|
-
export declare const CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD = "Estimated retained context remains above the configured auto-compaction threshold. Reduce compaction.keepRecentTokens, remove large retained content, or switch to a model with a larger context window before continuing.";
|
|
9
|
-
export declare const NOTHING_TO_COMPACT_WITHIN_KEEP_WINDOW = "Nothing to compact while preserving the configured recent context. Reduce compaction.keepRecentTokens, remove large retained content, or switch to a model with a larger context window before continuing.";
|
|
10
|
-
export declare const AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER = "Stopped before the next provider request because auto-compaction did not produce a safe context. Review the compaction warning before continuing.";
|
|
11
|
-
export interface MidTurnCompactionOutcome {
|
|
12
|
-
messages?: AgentMessage[];
|
|
13
|
-
stopErrorMessage?: string;
|
|
14
|
-
}
|
|
15
|
-
export declare function estimateMessagesTokens(messages: AgentMessage[]): number;
|
|
16
|
-
interface SummarizationRequestAuth {
|
|
17
|
-
model: Model<any>;
|
|
18
|
-
apiKey?: string;
|
|
19
|
-
headers?: Record<string, string>;
|
|
20
|
-
env?: Record<string, string>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* The slice of AgentSession that auto-compaction needs. Every member forwards
|
|
24
|
-
* to existing session state; the host does not grant new capabilities.
|
|
25
|
-
*/
|
|
26
|
-
export interface CompactionHost {
|
|
27
|
-
readonly agent: Agent;
|
|
28
|
-
readonly sessionManager: SessionManager;
|
|
29
|
-
readonly settingsManager: SettingsManager;
|
|
30
|
-
getModel(): Model<any> | undefined;
|
|
31
|
-
getThinkingLevel(): ThinkingLevel;
|
|
32
|
-
getExtensionRunner(): ExtensionRunner;
|
|
33
|
-
/** Whether a manual /compact run currently owns the compaction lifecycle. */
|
|
34
|
-
isManualCompactionActive(): boolean;
|
|
35
|
-
emit(event: AgentSessionEvent): void;
|
|
36
|
-
emitSessionCompactFailed(event: Omit<SessionCompactFailedEvent, "type">): Promise<void>;
|
|
37
|
-
getRequiredRequestAuth(model: Model<any>): Promise<SummarizationRequestAuth>;
|
|
38
|
-
getSummarizationRequestAuth(model: Model<any>, streamFunction: Agent["streamFunction"]): Promise<SummarizationRequestAuth>;
|
|
39
|
-
summarizationRetryCallbacks(source: {
|
|
40
|
-
source: "compaction";
|
|
41
|
-
reason: "manual" | "threshold" | "overflow";
|
|
42
|
-
}): RetryCallbacks;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Owns automatic compaction: threshold checks after tool batches (mid-turn),
|
|
46
|
-
* after a run, and before a prompt; overflow compact-and-retry recovery; and
|
|
47
|
-
* the fail-closed stop when compaction cannot produce a safe context.
|
|
48
|
-
* Manual /compact stays in AgentSession.
|
|
49
|
-
*/
|
|
50
|
-
export declare class CompactionController {
|
|
51
|
-
private readonly host;
|
|
52
|
-
private _abortController;
|
|
53
|
-
private _stopAfterTurnRequested;
|
|
54
|
-
/** An extension cancelled a mid-turn compaction; skip further mid-turn checks this run. */
|
|
55
|
-
private _midTurnDeclined;
|
|
56
|
-
private _overflowRecoveryAttempted;
|
|
57
|
-
constructor(host: CompactionHost);
|
|
58
|
-
/** Clear per-run state when a new agent run starts. */
|
|
59
|
-
noteRunStart(): void;
|
|
60
|
-
/** Read and clear the pending stop request. */
|
|
61
|
-
consumeStopAfterTurn(): boolean;
|
|
62
|
-
/** Stop the run at the next lifecycle boundary instead of sending an unsafe context. */
|
|
63
|
-
requestStopAfterTurn(): void;
|
|
64
|
-
/** A user message or a healthy assistant response resets overflow recovery. */
|
|
65
|
-
resetOverflowRecovery(): void;
|
|
66
|
-
get isAutoCompacting(): boolean;
|
|
67
|
-
abort(): void;
|
|
68
|
-
estimateContextTokens(messages: AgentMessage[]): number;
|
|
69
|
-
maybeCompactBeforeNextToolTurn(turn: PrepareNextTurnContext, signal?: AbortSignal): Promise<MidTurnCompactionOutcome>;
|
|
70
|
-
/**
|
|
71
|
-
* Check if compaction is needed and run it.
|
|
72
|
-
* Called after agent_end and before prompt submission.
|
|
73
|
-
*
|
|
74
|
-
* Two cases:
|
|
75
|
-
* 1. Recoverable failure: LLM returned context overflow or stopped below its desired output limit;
|
|
76
|
-
* remove the assistant message, compact, and auto-retry once
|
|
77
|
-
* 2. Threshold: Context over threshold, compact, NO auto-retry (user continues manually)
|
|
78
|
-
*
|
|
79
|
-
* @param assistantMessage The assistant message to check
|
|
80
|
-
* @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
|
|
81
|
-
*/
|
|
82
|
-
checkCompaction(assistantMessage: AssistantMessage, skipAbortedCheck?: boolean, timing?: CompactionTiming): Promise<boolean>;
|
|
83
|
-
/**
|
|
84
|
-
* Internal: Run auto-compaction with events.
|
|
85
|
-
*/
|
|
86
|
-
private _runAutoCompaction;
|
|
87
|
-
private _runAutoCompactionWithOutcome;
|
|
88
|
-
}
|
|
89
|
-
export {};
|
|
90
|
-
//# sourceMappingURL=compaction-controller.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compaction-controller.d.ts","sourceRoot":"","sources":["../../src/core/compaction-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
import { isContextOverflow, isRecoverableLength, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
2
|
-
import { calculateContextTokens, compact, estimateContextTokens, estimateTokens, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
3
|
-
import { getLatestCompactionEntry } from "./session-manager.js";
|
|
4
|
-
export const CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD = "Estimated retained context remains above the configured auto-compaction threshold. Reduce compaction.keepRecentTokens, remove large retained content, or switch to a model with a larger context window before continuing.";
|
|
5
|
-
export const NOTHING_TO_COMPACT_WITHIN_KEEP_WINDOW = "Nothing to compact while preserving the configured recent context. Reduce compaction.keepRecentTokens, remove large retained content, or switch to a model with a larger context window before continuing.";
|
|
6
|
-
export const AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER = "Stopped before the next provider request because auto-compaction did not produce a safe context. Review the compaction warning before continuing.";
|
|
7
|
-
export function estimateMessagesTokens(messages) {
|
|
8
|
-
let tokens = 0;
|
|
9
|
-
for (const message of messages) {
|
|
10
|
-
tokens += estimateTokens(message);
|
|
11
|
-
}
|
|
12
|
-
return tokens;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Owns automatic compaction: threshold checks after tool batches (mid-turn),
|
|
16
|
-
* after a run, and before a prompt; overflow compact-and-retry recovery; and
|
|
17
|
-
* the fail-closed stop when compaction cannot produce a safe context.
|
|
18
|
-
* Manual /compact stays in AgentSession.
|
|
19
|
-
*/
|
|
20
|
-
export class CompactionController {
|
|
21
|
-
constructor(host) {
|
|
22
|
-
this._abortController = undefined;
|
|
23
|
-
this._stopAfterTurnRequested = false;
|
|
24
|
-
/** An extension cancelled a mid-turn compaction; skip further mid-turn checks this run. */
|
|
25
|
-
this._midTurnDeclined = false;
|
|
26
|
-
this._overflowRecoveryAttempted = false;
|
|
27
|
-
this.host = host;
|
|
28
|
-
}
|
|
29
|
-
/** Clear per-run state when a new agent run starts. */
|
|
30
|
-
noteRunStart() {
|
|
31
|
-
this._stopAfterTurnRequested = false;
|
|
32
|
-
this._midTurnDeclined = false;
|
|
33
|
-
}
|
|
34
|
-
/** Read and clear the pending stop request. */
|
|
35
|
-
consumeStopAfterTurn() {
|
|
36
|
-
const requested = this._stopAfterTurnRequested;
|
|
37
|
-
this._stopAfterTurnRequested = false;
|
|
38
|
-
return requested;
|
|
39
|
-
}
|
|
40
|
-
/** Stop the run at the next lifecycle boundary instead of sending an unsafe context. */
|
|
41
|
-
requestStopAfterTurn() {
|
|
42
|
-
this._stopAfterTurnRequested = true;
|
|
43
|
-
}
|
|
44
|
-
/** A user message or a healthy assistant response resets overflow recovery. */
|
|
45
|
-
resetOverflowRecovery() {
|
|
46
|
-
this._overflowRecoveryAttempted = false;
|
|
47
|
-
}
|
|
48
|
-
get isAutoCompacting() {
|
|
49
|
-
return this._abortController !== undefined;
|
|
50
|
-
}
|
|
51
|
-
abort() {
|
|
52
|
-
this._abortController?.abort();
|
|
53
|
-
}
|
|
54
|
-
estimateContextTokens(messages) {
|
|
55
|
-
const estimate = estimateContextTokens(messages);
|
|
56
|
-
const compactionEntry = getLatestCompactionEntry(this.host.sessionManager.getBranch());
|
|
57
|
-
if (compactionEntry && estimate.lastUsageIndex !== null) {
|
|
58
|
-
const usageMessage = messages[estimate.lastUsageIndex];
|
|
59
|
-
if (usageMessage?.role === "assistant" &&
|
|
60
|
-
usageMessage.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
61
|
-
// A retained pre-compaction usage describes the old, larger context. Fall back
|
|
62
|
-
// to message estimates rather than immediately compacting again from stale data.
|
|
63
|
-
return estimateMessagesTokens(messages);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return estimate.tokens;
|
|
67
|
-
}
|
|
68
|
-
async maybeCompactBeforeNextToolTurn(turn, signal) {
|
|
69
|
-
if (signal?.aborted) {
|
|
70
|
-
return { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER };
|
|
71
|
-
}
|
|
72
|
-
// Tool batches always continue the run; a turn without tool results only
|
|
73
|
-
// continues when steering/follow-up messages are queued, otherwise the
|
|
74
|
-
// post-run path covers it.
|
|
75
|
-
if (turn.toolResults.length === 0 && !this.host.agent.hasQueuedMessages()) {
|
|
76
|
-
return {};
|
|
77
|
-
}
|
|
78
|
-
if (this._midTurnDeclined) {
|
|
79
|
-
return {};
|
|
80
|
-
}
|
|
81
|
-
const settings = this.host.settingsManager.getCompactionSettings();
|
|
82
|
-
if (!settings.enabled) {
|
|
83
|
-
return {};
|
|
84
|
-
}
|
|
85
|
-
const contextTokens = this.estimateContextTokens(turn.context.messages);
|
|
86
|
-
const contextWindow = this.host.getModel()?.contextWindow ?? 0;
|
|
87
|
-
if (!shouldCompact(contextTokens, contextWindow, settings)) {
|
|
88
|
-
return {};
|
|
89
|
-
}
|
|
90
|
-
const outcome = await this._runAutoCompactionWithOutcome("threshold", false, "midTurn", signal);
|
|
91
|
-
if (!outcome.compacted) {
|
|
92
|
-
if (outcome.cancelled && signal?.aborted !== true) {
|
|
93
|
-
// The extension took ownership of the risk; don't re-ask on every batch.
|
|
94
|
-
this._midTurnDeclined = true;
|
|
95
|
-
return {};
|
|
96
|
-
}
|
|
97
|
-
return { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER };
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
messages: this.host.agent.state.messages.slice(),
|
|
101
|
-
...(signal?.aborted === true
|
|
102
|
-
? { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER }
|
|
103
|
-
: outcome.mustStop === true
|
|
104
|
-
? { stopErrorMessage: CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD }
|
|
105
|
-
: {}),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Check if compaction is needed and run it.
|
|
110
|
-
* Called after agent_end and before prompt submission.
|
|
111
|
-
*
|
|
112
|
-
* Two cases:
|
|
113
|
-
* 1. Recoverable failure: LLM returned context overflow or stopped below its desired output limit;
|
|
114
|
-
* remove the assistant message, compact, and auto-retry once
|
|
115
|
-
* 2. Threshold: Context over threshold, compact, NO auto-retry (user continues manually)
|
|
116
|
-
*
|
|
117
|
-
* @param assistantMessage The assistant message to check
|
|
118
|
-
* @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
|
|
119
|
-
*/
|
|
120
|
-
async checkCompaction(assistantMessage, skipAbortedCheck = true, timing = "postRun") {
|
|
121
|
-
const settings = this.host.settingsManager.getCompactionSettings();
|
|
122
|
-
if (!settings.enabled)
|
|
123
|
-
return false;
|
|
124
|
-
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
125
|
-
if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
|
|
126
|
-
return false;
|
|
127
|
-
const model = this.host.getModel();
|
|
128
|
-
const contextWindow = model?.contextWindow ?? 0;
|
|
129
|
-
// Skip overflow check if the message came from a different model.
|
|
130
|
-
// This handles the case where user switched from a smaller-context model (e.g. opus)
|
|
131
|
-
// to a larger-context model (e.g. codex) - the overflow error from the old model
|
|
132
|
-
// shouldn't trigger compaction for the new model.
|
|
133
|
-
const sameModel = model && assistantMessage.provider === model.provider && assistantMessage.model === model.id;
|
|
134
|
-
// Skip compaction checks if this assistant message is older than the latest
|
|
135
|
-
// compaction boundary. This prevents a stale pre-compaction usage/error
|
|
136
|
-
// from retriggering compaction on the first prompt after compaction.
|
|
137
|
-
const compactionEntry = getLatestCompactionEntry(this.host.sessionManager.getBranch());
|
|
138
|
-
const assistantIsFromBeforeCompaction = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
|
|
139
|
-
if (assistantIsFromBeforeCompaction) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
// Case 1: Recoverable failure. Explicit/silent context overflow still uses context metadata.
|
|
143
|
-
// A length stop is recoverable when output ended below the model's original desired limit,
|
|
144
|
-
// independent of the configured context size or any context-clamped provider request limit.
|
|
145
|
-
// A successful response over the configured window should compact but must not retry: the
|
|
146
|
-
// assistant answer already completed and agent.continue() cannot continue from an assistant.
|
|
147
|
-
const contextOverflow = sameModel && isContextOverflow(assistantMessage, contextWindow);
|
|
148
|
-
const recoverableLength = sameModel && isRecoverableLength(assistantMessage, model?.maxTokens ?? 0);
|
|
149
|
-
if (contextOverflow || recoverableLength) {
|
|
150
|
-
const willRetry = assistantMessage.stopReason !== "stop";
|
|
151
|
-
if (!willRetry) {
|
|
152
|
-
return await this._runAutoCompaction("overflow", false, timing);
|
|
153
|
-
}
|
|
154
|
-
if (this._overflowRecoveryAttempted) {
|
|
155
|
-
this._stopAfterTurnRequested = true;
|
|
156
|
-
const errorMessage = contextOverflow
|
|
157
|
-
? "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model."
|
|
158
|
-
: "Truncated response recovery failed after one compact-and-retry attempt.";
|
|
159
|
-
this.host.emit({
|
|
160
|
-
type: "compaction_end",
|
|
161
|
-
reason: "overflow",
|
|
162
|
-
result: undefined,
|
|
163
|
-
aborted: false,
|
|
164
|
-
willRetry: false,
|
|
165
|
-
errorMessage,
|
|
166
|
-
});
|
|
167
|
-
await this.host.emitSessionCompactFailed({
|
|
168
|
-
reason: "overflow",
|
|
169
|
-
errorMessage,
|
|
170
|
-
aborted: false,
|
|
171
|
-
willRetry: false,
|
|
172
|
-
fromExtension: false,
|
|
173
|
-
});
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
this._overflowRecoveryAttempted = true;
|
|
177
|
-
// Remove the failed or truncated message from agent state. It remains in session history,
|
|
178
|
-
// but must not be included in the compact-and-retry context.
|
|
179
|
-
const messages = this.host.agent.state.messages;
|
|
180
|
-
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
181
|
-
this.host.agent.state.messages = messages.slice(0, -1);
|
|
182
|
-
}
|
|
183
|
-
return await this._runAutoCompaction("overflow", willRetry, timing);
|
|
184
|
-
}
|
|
185
|
-
// Case 2: Threshold - context is getting large
|
|
186
|
-
// For error messages or all-zero usage messages, estimate from the last valid response.
|
|
187
|
-
// This ensures sessions that hit persistent API errors (e.g. 529) or malformed zero-usage
|
|
188
|
-
// responses can still compact and do not reset context accounting.
|
|
189
|
-
let contextTokens;
|
|
190
|
-
const directContextTokens = assistantMessage.usage ? calculateContextTokens(assistantMessage.usage) : 0;
|
|
191
|
-
if (assistantMessage.stopReason === "error" || directContextTokens === 0) {
|
|
192
|
-
const messages = this.host.agent.state.messages;
|
|
193
|
-
const estimate = estimateContextTokens(messages);
|
|
194
|
-
// Without provider usage, estimate.tokens is the pure message-size estimate.
|
|
195
|
-
// Only usage-backed estimates need the stale pre-compaction check.
|
|
196
|
-
if (estimate.lastUsageIndex !== null) {
|
|
197
|
-
// Verify the usage source is post-compaction. Kept pre-compaction messages
|
|
198
|
-
// have stale usage reflecting the old (larger) context and would falsely
|
|
199
|
-
// trigger compaction right after one just finished.
|
|
200
|
-
const usageMsg = messages[estimate.lastUsageIndex];
|
|
201
|
-
if (compactionEntry &&
|
|
202
|
-
usageMsg.role === "assistant" &&
|
|
203
|
-
usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
contextTokens = estimate.tokens;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
contextTokens = directContextTokens;
|
|
211
|
-
}
|
|
212
|
-
if (shouldCompact(contextTokens, contextWindow, settings)) {
|
|
213
|
-
return await this._runAutoCompaction("threshold", false, timing);
|
|
214
|
-
}
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Internal: Run auto-compaction with events.
|
|
219
|
-
*/
|
|
220
|
-
async _runAutoCompaction(reason, willRetry, timing = "postRun") {
|
|
221
|
-
const outcome = await this._runAutoCompactionWithOutcome(reason, willRetry, timing);
|
|
222
|
-
if (!outcome.compacted || outcome.mustStop) {
|
|
223
|
-
this._stopAfterTurnRequested = true;
|
|
224
|
-
}
|
|
225
|
-
return outcome.shouldContinue;
|
|
226
|
-
}
|
|
227
|
-
async _runAutoCompactionWithOutcome(reason, willRetry, timing, parentSignal) {
|
|
228
|
-
const settings = this.host.settingsManager.getCompactionSettings();
|
|
229
|
-
let started = false;
|
|
230
|
-
let fromExtension = false;
|
|
231
|
-
let controller;
|
|
232
|
-
let removeParentAbortListener;
|
|
233
|
-
try {
|
|
234
|
-
const model = this.host.getModel();
|
|
235
|
-
if (!model || this._abortController || this.host.isManualCompactionActive() || parentSignal?.aborted) {
|
|
236
|
-
return { compacted: false, shouldContinue: false };
|
|
237
|
-
}
|
|
238
|
-
const streamFunction = this.host.agent.streamFunction;
|
|
239
|
-
const thinkingLevel = this.host.getThinkingLevel();
|
|
240
|
-
const retrySettings = this.host.settingsManager.getRetrySettings();
|
|
241
|
-
controller = new AbortController();
|
|
242
|
-
if (parentSignal) {
|
|
243
|
-
const abortFromParent = () => controller?.abort();
|
|
244
|
-
parentSignal.addEventListener("abort", abortFromParent, { once: true });
|
|
245
|
-
removeParentAbortListener = () => parentSignal.removeEventListener("abort", abortFromParent);
|
|
246
|
-
}
|
|
247
|
-
if (controller.signal.aborted) {
|
|
248
|
-
return { compacted: false, shouldContinue: false };
|
|
249
|
-
}
|
|
250
|
-
this._abortController = controller;
|
|
251
|
-
started = true;
|
|
252
|
-
this.host.emit({ type: "compaction_start", reason });
|
|
253
|
-
if (controller.signal.aborted) {
|
|
254
|
-
this.host.emit({
|
|
255
|
-
type: "compaction_end",
|
|
256
|
-
reason,
|
|
257
|
-
result: undefined,
|
|
258
|
-
aborted: true,
|
|
259
|
-
willRetry: false,
|
|
260
|
-
});
|
|
261
|
-
await this.host.emitSessionCompactFailed({
|
|
262
|
-
reason,
|
|
263
|
-
aborted: true,
|
|
264
|
-
willRetry: false,
|
|
265
|
-
fromExtension: false,
|
|
266
|
-
});
|
|
267
|
-
return { compacted: false, shouldContinue: false };
|
|
268
|
-
}
|
|
269
|
-
let extensionCompaction;
|
|
270
|
-
const pathEntries = this.host.sessionManager.getBranch();
|
|
271
|
-
const preparation = prepareCompaction(pathEntries, settings);
|
|
272
|
-
if (!preparation) {
|
|
273
|
-
throw new Error(NOTHING_TO_COMPACT_WITHIN_KEEP_WINDOW);
|
|
274
|
-
}
|
|
275
|
-
const extensionRunner = this.host.getExtensionRunner();
|
|
276
|
-
if (extensionRunner.hasHandlers("session_before_compact")) {
|
|
277
|
-
const extensionResult = (await extensionRunner.emit({
|
|
278
|
-
type: "session_before_compact",
|
|
279
|
-
preparation,
|
|
280
|
-
branchEntries: pathEntries,
|
|
281
|
-
customInstructions: undefined,
|
|
282
|
-
reason,
|
|
283
|
-
timing,
|
|
284
|
-
willRetry,
|
|
285
|
-
signal: controller.signal,
|
|
286
|
-
}));
|
|
287
|
-
if (extensionResult?.cancel) {
|
|
288
|
-
this.host.emit({
|
|
289
|
-
type: "compaction_end",
|
|
290
|
-
reason,
|
|
291
|
-
result: undefined,
|
|
292
|
-
aborted: true,
|
|
293
|
-
willRetry: false,
|
|
294
|
-
});
|
|
295
|
-
await this.host.emitSessionCompactFailed({
|
|
296
|
-
reason,
|
|
297
|
-
aborted: true,
|
|
298
|
-
willRetry: false,
|
|
299
|
-
fromExtension: false,
|
|
300
|
-
});
|
|
301
|
-
// A cancel produced by an abort (abortCompaction/parent abort) is not an
|
|
302
|
-
// extension decision; only a voluntary cancel hands the risk to the extension.
|
|
303
|
-
return { compacted: false, shouldContinue: false, cancelled: !controller.signal.aborted };
|
|
304
|
-
}
|
|
305
|
-
if (extensionResult?.compaction) {
|
|
306
|
-
extensionCompaction = extensionResult.compaction;
|
|
307
|
-
fromExtension = true;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
let summary;
|
|
311
|
-
let firstKeptEntryId;
|
|
312
|
-
let tokensBefore;
|
|
313
|
-
let usage;
|
|
314
|
-
let details;
|
|
315
|
-
if (extensionCompaction) {
|
|
316
|
-
// Extension provided compaction content
|
|
317
|
-
summary = extensionCompaction.summary;
|
|
318
|
-
firstKeptEntryId = extensionCompaction.firstKeptEntryId;
|
|
319
|
-
tokensBefore = extensionCompaction.tokensBefore;
|
|
320
|
-
usage = extensionCompaction.usage;
|
|
321
|
-
details = extensionCompaction.details;
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
let requestModel = model;
|
|
325
|
-
let apiKey;
|
|
326
|
-
let headers;
|
|
327
|
-
let env;
|
|
328
|
-
if (streamFunction === streamSimple) {
|
|
329
|
-
({ model: requestModel, apiKey, headers, env } = await this.host.getRequiredRequestAuth(model));
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
({
|
|
333
|
-
model: requestModel,
|
|
334
|
-
apiKey,
|
|
335
|
-
headers,
|
|
336
|
-
env,
|
|
337
|
-
} = await this.host.getSummarizationRequestAuth(model, streamFunction));
|
|
338
|
-
}
|
|
339
|
-
if (controller.signal.aborted) {
|
|
340
|
-
this.host.emit({
|
|
341
|
-
type: "compaction_end",
|
|
342
|
-
reason,
|
|
343
|
-
result: undefined,
|
|
344
|
-
aborted: true,
|
|
345
|
-
willRetry: false,
|
|
346
|
-
});
|
|
347
|
-
await this.host.emitSessionCompactFailed({
|
|
348
|
-
reason,
|
|
349
|
-
aborted: true,
|
|
350
|
-
willRetry: false,
|
|
351
|
-
fromExtension: false,
|
|
352
|
-
});
|
|
353
|
-
return { compacted: false, shouldContinue: false };
|
|
354
|
-
}
|
|
355
|
-
// Generate compaction result
|
|
356
|
-
const compactResult = await compact(preparation, requestModel, apiKey, headers, undefined, controller.signal, thinkingLevel, streamFunction, env, retrySettings, this.host.summarizationRetryCallbacks({ source: "compaction", reason }));
|
|
357
|
-
summary = compactResult.summary;
|
|
358
|
-
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
359
|
-
tokensBefore = compactResult.tokensBefore;
|
|
360
|
-
usage = compactResult.usage;
|
|
361
|
-
details = compactResult.details;
|
|
362
|
-
}
|
|
363
|
-
if (controller.signal.aborted) {
|
|
364
|
-
this.host.emit({
|
|
365
|
-
type: "compaction_end",
|
|
366
|
-
reason,
|
|
367
|
-
result: undefined,
|
|
368
|
-
aborted: true,
|
|
369
|
-
willRetry: false,
|
|
370
|
-
});
|
|
371
|
-
await this.host.emitSessionCompactFailed({
|
|
372
|
-
reason,
|
|
373
|
-
aborted: true,
|
|
374
|
-
willRetry: false,
|
|
375
|
-
fromExtension,
|
|
376
|
-
});
|
|
377
|
-
return { compacted: false, shouldContinue: false };
|
|
378
|
-
}
|
|
379
|
-
this.host.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
380
|
-
const newEntries = this.host.sessionManager.getEntries();
|
|
381
|
-
const sessionContext = this.host.sessionManager.buildSessionContext();
|
|
382
|
-
this.host.agent.state.messages = sessionContext.messages;
|
|
383
|
-
if (willRetry) {
|
|
384
|
-
const messages = this.host.agent.state.messages;
|
|
385
|
-
const lastMsg = messages[messages.length - 1];
|
|
386
|
-
// The overflow response was persisted on message_end before checkCompaction() removed it
|
|
387
|
-
// from agent state. Rebuilding state from the new compaction can restore that kept entry,
|
|
388
|
-
// leaving an assistant as the final message. agent.continue() rejects that state, so remove
|
|
389
|
-
// the retriable error or truncated-length response again before continuing the interrupted turn.
|
|
390
|
-
if (lastMsg?.role === "assistant" &&
|
|
391
|
-
(lastMsg.stopReason === "error" ||
|
|
392
|
-
lastMsg.stopReason === "length")) {
|
|
393
|
-
this.host.agent.state.messages = messages.slice(0, -1);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const estimatedTokensAfter = this.estimateContextTokens(this.host.agent.state.messages);
|
|
397
|
-
const contextStillOverThreshold = shouldCompact(estimatedTokensAfter, model.contextWindow, settings);
|
|
398
|
-
const effectiveWillRetry = willRetry && !contextStillOverThreshold;
|
|
399
|
-
// Get the saved compaction entry for the extension event
|
|
400
|
-
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
401
|
-
if (savedCompactionEntry) {
|
|
402
|
-
await extensionRunner.emit({
|
|
403
|
-
type: "session_compact",
|
|
404
|
-
compactionEntry: savedCompactionEntry,
|
|
405
|
-
fromExtension,
|
|
406
|
-
reason,
|
|
407
|
-
willRetry: effectiveWillRetry,
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
const result = {
|
|
411
|
-
summary,
|
|
412
|
-
firstKeptEntryId,
|
|
413
|
-
tokensBefore,
|
|
414
|
-
estimatedTokensAfter,
|
|
415
|
-
usage,
|
|
416
|
-
details,
|
|
417
|
-
};
|
|
418
|
-
this.host.emit({
|
|
419
|
-
type: "compaction_end",
|
|
420
|
-
reason,
|
|
421
|
-
result,
|
|
422
|
-
aborted: false,
|
|
423
|
-
willRetry: effectiveWillRetry,
|
|
424
|
-
...(contextStillOverThreshold ? { errorMessage: CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD } : {}),
|
|
425
|
-
});
|
|
426
|
-
if (contextStillOverThreshold) {
|
|
427
|
-
return { compacted: true, shouldContinue: false, mustStop: true };
|
|
428
|
-
}
|
|
429
|
-
if (effectiveWillRetry) {
|
|
430
|
-
return { compacted: true, shouldContinue: true };
|
|
431
|
-
}
|
|
432
|
-
// Auto-compaction can complete while follow-up/steering/custom messages are waiting.
|
|
433
|
-
// Continue once so queued messages are delivered.
|
|
434
|
-
return { compacted: true, shouldContinue: this.host.agent.hasQueuedMessages() };
|
|
435
|
-
}
|
|
436
|
-
catch (error) {
|
|
437
|
-
const aborted = controller?.signal.aborted || (error instanceof Error && error.name === "AbortError");
|
|
438
|
-
const message = error instanceof Error ? error.message : "compaction failed";
|
|
439
|
-
if (started) {
|
|
440
|
-
const errorMessage = aborted
|
|
441
|
-
? undefined
|
|
442
|
-
: reason === "overflow"
|
|
443
|
-
? `Context overflow recovery failed: ${message}`
|
|
444
|
-
: `Auto-compaction failed: ${message}`;
|
|
445
|
-
this.host.emit({
|
|
446
|
-
type: "compaction_end",
|
|
447
|
-
reason,
|
|
448
|
-
result: undefined,
|
|
449
|
-
aborted,
|
|
450
|
-
willRetry: false,
|
|
451
|
-
...(errorMessage ? { errorMessage } : {}),
|
|
452
|
-
});
|
|
453
|
-
await this.host.emitSessionCompactFailed({
|
|
454
|
-
reason,
|
|
455
|
-
errorMessage,
|
|
456
|
-
aborted,
|
|
457
|
-
willRetry: false,
|
|
458
|
-
fromExtension,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
return { compacted: false, shouldContinue: false };
|
|
462
|
-
}
|
|
463
|
-
finally {
|
|
464
|
-
removeParentAbortListener?.();
|
|
465
|
-
if (this._abortController === controller) {
|
|
466
|
-
this._abortController = undefined;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
//# sourceMappingURL=compaction-controller.js.map
|