@code-yeongyu/senpi 2026.5.15 → 2026.5.18
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 +1170 -1161
- package/README.md +1 -2
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +11 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +160 -13
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +22 -14
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/dynamic-prompt/verification.d.ts +31 -0
- package/dist/core/dynamic-prompt/verification.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/verification.js +41 -0
- package/dist/core/dynamic-prompt/verification.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts +97 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js +420 -0
- package/dist/core/extensions/builtin/compaction/context-reduction.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +168 -31
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +197 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js +690 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/prompts.d.ts +3 -3
- package/dist/core/extensions/builtin/compaction/prompts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/prompts.js +0 -22
- package/dist/core/extensions/builtin/compaction/prompts.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +4 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +48 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +3 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +80 -33
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.js +12 -6
- package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/diff.d.ts.map +1 -1
- package/dist/core/extensions/builtin/diff.js +1 -1
- package/dist/core/extensions/builtin/diff.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.js +5 -128
- package/dist/core/extensions/builtin/gpt-apply-patch/preview-format.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts +6 -2
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +82 -10
- package/dist/core/extensions/builtin/openai-web-search/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.js +0 -5
- package/dist/core/extensions/builtin/permission-system/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/system-messages.d.ts +1 -1
- package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.js +8 -4
- package/dist/core/extensions/builtin/tool-pair-guard/index.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js +89 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js +122 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +22 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +3 -3
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +5 -10
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +66 -9
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +5 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +72 -31
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +6 -4
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -22
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -9
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +2 -5
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/thinking-levels.d.ts +6 -0
- package/dist/core/thinking-levels.d.ts.map +1 -0
- package/dist/core/thinking-levels.js +36 -0
- package/dist/core/thinking-levels.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +15 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/diff-render.d.ts +13 -0
- package/dist/core/tools/diff-render.d.ts.map +1 -0
- package/dist/core/tools/diff-render.js +130 -0
- package/dist/core/tools/diff-render.js.map +1 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +8 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +28 -7
- package/dist/core/tools/write.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +20 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +2 -2
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +7 -4
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +0 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +42 -44
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +177 -82
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-info-format.d.ts +3 -0
- package/dist/modes/interactive/session-info-format.d.ts.map +1 -0
- package/dist/modes/interactive/session-info-format.js +44 -0
- package/dist/modes/interactive/session-info-format.js.map +1 -0
- package/dist/modes/interactive/working-status.d.ts +21 -0
- package/dist/modes/interactive/working-status.d.ts.map +1 -0
- package/dist/modes/interactive/working-status.js +71 -0
- package/dist/modes/interactive/working-status.js.map +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +3 -4
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/senpi +5 -1
- package/dist/utils/child-process.d.ts +7 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +60 -7
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +4 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +55 -0
- package/docs/extensions.md +1 -2
- package/docs/index.md +0 -1
- package/docs/models.md +9 -0
- package/docs/sdk.md +0 -1
- package/docs/settings.md +2 -32
- package/docs/skills.md +3 -4
- package/docs/termux.md +2 -2
- package/docs/usage.md +1 -1
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +6 -6
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts +0 -10
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/cancel-tool.js +0 -109
- package/dist/core/extensions/builtin/background-task/cancel-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.d.ts +0 -3
- package/dist/core/extensions/builtin/background-task/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.js +0 -207
- package/dist/core/extensions/builtin/background-task/index.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.d.ts +0 -17
- package/dist/core/extensions/builtin/background-task/manager.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.js +0 -114
- package/dist/core/extensions/builtin/background-task/manager.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.d.ts +0 -22
- package/dist/core/extensions/builtin/background-task/notification.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.js +0 -105
- package/dist/core/extensions/builtin/background-task/notification.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts +0 -11
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.js +0 -127
- package/dist/core/extensions/builtin/background-task/output-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.d.ts +0 -8
- package/dist/core/extensions/builtin/background-task/spawner.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.js +0 -207
- package/dist/core/extensions/builtin/background-task/spawner.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts +0 -20
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.js +0 -302
- package/dist/core/extensions/builtin/background-task/task-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.d.ts +0 -72
- package/dist/core/extensions/builtin/background-task/types.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.js +0 -32
- package/dist/core/extensions/builtin/background-task/types.js.map +0 -1
- package/docs/agents.md +0 -348
- package/examples/extensions/subagent/README.md +0 -172
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -987
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
16
16
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { basename, dirname, resolve } from "node:path";
|
|
18
|
-
import { cleanupSessionResources,
|
|
18
|
+
import { cleanupSessionResources, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai";
|
|
19
19
|
import { expandTildePath } from "../config.js";
|
|
20
20
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
21
21
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
@@ -34,6 +34,7 @@ import { getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.j
|
|
|
34
34
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
35
35
|
import { buildSessionContext, CURRENT_SESSION_VERSION, getLatestCompactionEntry, } from "./session-manager.js";
|
|
36
36
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
37
|
+
import { getSupportedThinkingLevels, supportsMax, supportsXhigh } from "./thinking-levels.js";
|
|
37
38
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
38
39
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
39
40
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
@@ -96,6 +97,7 @@ export class AgentSession {
|
|
|
96
97
|
_retryAttempt = 0;
|
|
97
98
|
_retryPromise = undefined;
|
|
98
99
|
_retryResolve = undefined;
|
|
100
|
+
_userAbortPromise = undefined;
|
|
99
101
|
// Bash execution state
|
|
100
102
|
_bashAbortController = undefined;
|
|
101
103
|
_pendingBashMessages = [];
|
|
@@ -149,6 +151,19 @@ export class AgentSession {
|
|
|
149
151
|
}
|
|
150
152
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
151
153
|
this._installAgentToolHooks();
|
|
154
|
+
const previousPrepareNextTurn = this.agent.prepareNextTurn;
|
|
155
|
+
this.agent.prepareNextTurn = async (signal) => {
|
|
156
|
+
const nextTurn = await previousPrepareNextTurn?.(signal);
|
|
157
|
+
const model = this.agent.state.model;
|
|
158
|
+
if (!model) {
|
|
159
|
+
return nextTurn;
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
...nextTurn,
|
|
163
|
+
model,
|
|
164
|
+
thinkingLevel: this.agent.state.thinkingLevel,
|
|
165
|
+
};
|
|
166
|
+
};
|
|
152
167
|
this._buildRuntime({
|
|
153
168
|
activeToolNames: this._initialActiveToolNames,
|
|
154
169
|
includeAllExtensionTools: true,
|
|
@@ -177,6 +192,13 @@ export class AgentSession {
|
|
|
177
192
|
}
|
|
178
193
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
179
194
|
}
|
|
195
|
+
async _getCompactionRequestAuth(model) {
|
|
196
|
+
if (this.agent.streamFn === streamSimple) {
|
|
197
|
+
return this._getRequiredRequestAuth(model);
|
|
198
|
+
}
|
|
199
|
+
const result = await this._modelRegistry.getApiKeyAndHeaders(model);
|
|
200
|
+
return result.ok ? { apiKey: result.apiKey, headers: result.headers, extraBody: result.extraBody } : {};
|
|
201
|
+
}
|
|
180
202
|
/**
|
|
181
203
|
* Install tool hooks once on the Agent instance.
|
|
182
204
|
*
|
|
@@ -745,6 +767,10 @@ export class AgentSession {
|
|
|
745
767
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
746
768
|
*/
|
|
747
769
|
async prompt(text, options) {
|
|
770
|
+
const userAbortPromise = this._userAbortPromise;
|
|
771
|
+
if (userAbortPromise) {
|
|
772
|
+
await userAbortPromise;
|
|
773
|
+
}
|
|
748
774
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
|
749
775
|
const preflightResult = options?.preflightResult;
|
|
750
776
|
let messages;
|
|
@@ -1114,8 +1140,24 @@ export class AgentSession {
|
|
|
1114
1140
|
*/
|
|
1115
1141
|
async abort() {
|
|
1116
1142
|
this.abortRetry();
|
|
1117
|
-
this.
|
|
1118
|
-
|
|
1143
|
+
if (this._userAbortPromise) {
|
|
1144
|
+
this.agent.abort();
|
|
1145
|
+
await this._userAbortPromise;
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
const abortPromise = (async () => {
|
|
1149
|
+
this.agent.abort();
|
|
1150
|
+
await this.agent.waitForIdle();
|
|
1151
|
+
})();
|
|
1152
|
+
this._userAbortPromise = abortPromise;
|
|
1153
|
+
try {
|
|
1154
|
+
await abortPromise;
|
|
1155
|
+
}
|
|
1156
|
+
finally {
|
|
1157
|
+
if (this._userAbortPromise === abortPromise) {
|
|
1158
|
+
this._userAbortPromise = undefined;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1119
1161
|
}
|
|
1120
1162
|
// =========================================================================
|
|
1121
1163
|
// Model Management
|
|
@@ -1377,8 +1419,11 @@ export class AgentSession {
|
|
|
1377
1419
|
if (options.expectedRevision !== undefined && options.expectedRevision !== this._messageRevision) {
|
|
1378
1420
|
return { applied: false, reason: "stale" };
|
|
1379
1421
|
}
|
|
1380
|
-
this._compactionAbortController
|
|
1381
|
-
|
|
1422
|
+
const ownsController = this._compactionAbortController === undefined;
|
|
1423
|
+
if (ownsController) {
|
|
1424
|
+
this._compactionAbortController = new AbortController();
|
|
1425
|
+
this._emit({ type: "compaction_start", reason: options.reason });
|
|
1426
|
+
}
|
|
1382
1427
|
try {
|
|
1383
1428
|
const execution = await this._executeCompaction({
|
|
1384
1429
|
reason: options.reason,
|
|
@@ -1407,6 +1452,38 @@ export class AgentSession {
|
|
|
1407
1452
|
this._compactionAbortController = undefined;
|
|
1408
1453
|
}
|
|
1409
1454
|
}
|
|
1455
|
+
_beginExtensionCompactionFeedback(reason) {
|
|
1456
|
+
if (!this._compactionAbortController) {
|
|
1457
|
+
this._compactionAbortController = new AbortController();
|
|
1458
|
+
this._emit({ type: "compaction_start", reason });
|
|
1459
|
+
}
|
|
1460
|
+
return this._compactionAbortController.signal;
|
|
1461
|
+
}
|
|
1462
|
+
_updateExtensionCompactionFeedback(options) {
|
|
1463
|
+
if (!this._compactionAbortController && !this._autoCompactionAbortController)
|
|
1464
|
+
return;
|
|
1465
|
+
this._emit({
|
|
1466
|
+
type: "compaction_progress",
|
|
1467
|
+
reason: options.reason,
|
|
1468
|
+
...(options.delta !== undefined ? { delta: options.delta } : {}),
|
|
1469
|
+
...(options.text !== undefined ? { text: options.text } : {}),
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
_endExtensionCompactionFeedback(options) {
|
|
1473
|
+
const controller = this._compactionAbortController;
|
|
1474
|
+
if (!controller)
|
|
1475
|
+
return;
|
|
1476
|
+
const aborted = options.aborted ?? controller.signal.aborted;
|
|
1477
|
+
this._emit({
|
|
1478
|
+
type: "compaction_end",
|
|
1479
|
+
reason: options.reason,
|
|
1480
|
+
result: undefined,
|
|
1481
|
+
aborted,
|
|
1482
|
+
willRetry: false,
|
|
1483
|
+
errorMessage: aborted ? undefined : options.errorMessage,
|
|
1484
|
+
});
|
|
1485
|
+
this._compactionAbortController = undefined;
|
|
1486
|
+
}
|
|
1410
1487
|
async _executeCompaction(request) {
|
|
1411
1488
|
if (!this.model) {
|
|
1412
1489
|
throw new Error(formatNoModelSelectedMessage());
|
|
@@ -1449,8 +1526,8 @@ export class AgentSession {
|
|
|
1449
1526
|
}
|
|
1450
1527
|
}
|
|
1451
1528
|
if (!compactionResult) {
|
|
1452
|
-
const { apiKey, headers, extraBody } = await this.
|
|
1453
|
-
compactionResult = await compact(preparation, this.model, apiKey, headers, request.customInstructions, signal, extraBody, this.thinkingLevel);
|
|
1529
|
+
const { apiKey, headers, extraBody } = await this._getCompactionRequestAuth(this.model);
|
|
1530
|
+
compactionResult = await compact(preparation, this.model, apiKey, headers, request.customInstructions, signal, extraBody, this.thinkingLevel, this.agent.streamFn);
|
|
1454
1531
|
}
|
|
1455
1532
|
}
|
|
1456
1533
|
if (signal.aborted) {
|
|
@@ -1573,14 +1650,18 @@ export class AgentSession {
|
|
|
1573
1650
|
shouldCompact(contextUsage.tokens, contextUsage.contextWindow, settings);
|
|
1574
1651
|
if (isContextOverflow(assistantMessage, contextWindow) && (sameModel || currentContextNeedsCompaction)) {
|
|
1575
1652
|
if (this._overflowRecoveryAttempted) {
|
|
1653
|
+
const errorMessage = "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.";
|
|
1576
1654
|
this._emit({
|
|
1577
1655
|
type: "compaction_end",
|
|
1578
1656
|
reason: "overflow",
|
|
1579
1657
|
result: undefined,
|
|
1580
1658
|
aborted: false,
|
|
1581
1659
|
willRetry: false,
|
|
1582
|
-
errorMessage
|
|
1660
|
+
errorMessage,
|
|
1583
1661
|
});
|
|
1662
|
+
if (requestReason === "pre_prompt") {
|
|
1663
|
+
throw new Error(errorMessage);
|
|
1664
|
+
}
|
|
1584
1665
|
return;
|
|
1585
1666
|
}
|
|
1586
1667
|
this._overflowRecoveryAttempted = true;
|
|
@@ -1635,14 +1716,20 @@ export class AgentSession {
|
|
|
1635
1716
|
this._emit({ type: "compaction_start", reason: "pre_prompt" });
|
|
1636
1717
|
this._compactionAbortController = new AbortController();
|
|
1637
1718
|
try {
|
|
1638
|
-
await this._executeCompaction({
|
|
1719
|
+
const execution = await this._executeCompaction({
|
|
1639
1720
|
reason: "pre_prompt",
|
|
1640
1721
|
willRetry: false,
|
|
1641
1722
|
lastAssistantMessage,
|
|
1642
1723
|
skipAbortedCheck,
|
|
1643
1724
|
});
|
|
1725
|
+
if (!execution.accepted && isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
|
|
1726
|
+
this._overflowRecoveryAttempted = false;
|
|
1727
|
+
}
|
|
1644
1728
|
}
|
|
1645
1729
|
catch (error) {
|
|
1730
|
+
if (isContextOverflow(lastAssistantMessage, this.model?.contextWindow ?? 0)) {
|
|
1731
|
+
this._overflowRecoveryAttempted = false;
|
|
1732
|
+
}
|
|
1646
1733
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
1647
1734
|
const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
|
|
1648
1735
|
this._emit({
|
|
@@ -1666,6 +1753,8 @@ export class AgentSession {
|
|
|
1666
1753
|
this._autoCompactionAbortController = new AbortController();
|
|
1667
1754
|
try {
|
|
1668
1755
|
if (!this.model) {
|
|
1756
|
+
if (reason === "overflow")
|
|
1757
|
+
this._overflowRecoveryAttempted = false;
|
|
1669
1758
|
this._emit({
|
|
1670
1759
|
type: "compaction_end",
|
|
1671
1760
|
reason,
|
|
@@ -1676,7 +1765,9 @@ export class AgentSession {
|
|
|
1676
1765
|
return;
|
|
1677
1766
|
}
|
|
1678
1767
|
const authResult = await this._modelRegistry.getApiKeyAndHeaders(this.model);
|
|
1679
|
-
if (!authResult.ok || !authResult.apiKey) {
|
|
1768
|
+
if (this.agent.streamFn === streamSimple && (!authResult.ok || !authResult.apiKey)) {
|
|
1769
|
+
if (reason === "overflow")
|
|
1770
|
+
this._overflowRecoveryAttempted = false;
|
|
1680
1771
|
this._emit({
|
|
1681
1772
|
type: "compaction_end",
|
|
1682
1773
|
reason,
|
|
@@ -1688,6 +1779,8 @@ export class AgentSession {
|
|
|
1688
1779
|
}
|
|
1689
1780
|
const preparation = prepareCompaction(this.sessionManager.getBranch(), this.settingsManager.getCompactionSettings());
|
|
1690
1781
|
if (!preparation) {
|
|
1782
|
+
if (reason === "overflow")
|
|
1783
|
+
this._overflowRecoveryAttempted = false;
|
|
1691
1784
|
this._emit({
|
|
1692
1785
|
type: "compaction_end",
|
|
1693
1786
|
reason,
|
|
@@ -1699,6 +1792,8 @@ export class AgentSession {
|
|
|
1699
1792
|
}
|
|
1700
1793
|
const execution = await this._executeCompaction({ reason, willRetry });
|
|
1701
1794
|
if (!execution.accepted) {
|
|
1795
|
+
if (reason === "overflow")
|
|
1796
|
+
this._overflowRecoveryAttempted = false;
|
|
1702
1797
|
return;
|
|
1703
1798
|
}
|
|
1704
1799
|
if (willRetry) {
|
|
@@ -1721,6 +1816,8 @@ export class AgentSession {
|
|
|
1721
1816
|
}
|
|
1722
1817
|
}
|
|
1723
1818
|
catch (error) {
|
|
1819
|
+
if (reason === "overflow")
|
|
1820
|
+
this._overflowRecoveryAttempted = false;
|
|
1724
1821
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
1725
1822
|
const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
|
|
1726
1823
|
this._emit({
|
|
@@ -1943,6 +2040,9 @@ export class AgentSession {
|
|
|
1943
2040
|
}
|
|
1944
2041
|
})();
|
|
1945
2042
|
},
|
|
2043
|
+
beginCompaction: (options) => this._beginExtensionCompactionFeedback(options.reason),
|
|
2044
|
+
updateCompaction: (options) => this._updateExtensionCompactionFeedback(options),
|
|
2045
|
+
endCompaction: (options) => this._endExtensionCompactionFeedback(options),
|
|
1946
2046
|
getMessageRevision: () => this.getMessageRevision(),
|
|
1947
2047
|
applyCompaction: (precomputed, options) => this.applyCompaction(precomputed, options),
|
|
1948
2048
|
getSystemPrompt: () => this.systemPrompt,
|
|
@@ -2101,16 +2201,49 @@ export class AgentSession {
|
|
|
2101
2201
|
* Context overflow errors are NOT retryable (handled by compaction instead).
|
|
2102
2202
|
*/
|
|
2103
2203
|
_isRetryableError(message) {
|
|
2104
|
-
if (
|
|
2204
|
+
if (!message.errorMessage)
|
|
2105
2205
|
return false;
|
|
2106
2206
|
// Context overflow is handled by compaction, not retry
|
|
2107
2207
|
const contextWindow = this.model?.contextWindow ?? 0;
|
|
2108
2208
|
if (isContextOverflow(message, contextWindow))
|
|
2109
2209
|
return false;
|
|
2110
2210
|
const err = message.errorMessage;
|
|
2211
|
+
if (message.stopReason === "aborted") {
|
|
2212
|
+
return /timed? out|timeout/i.test(err);
|
|
2213
|
+
}
|
|
2214
|
+
if (message.stopReason !== "error")
|
|
2215
|
+
return false;
|
|
2111
2216
|
// Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, premature stream endings, HTTP/2 closed before response, terminated, retry delay exceeded
|
|
2112
2217
|
return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
|
|
2113
2218
|
}
|
|
2219
|
+
_getProviderRetryDelayMs(errorMessage) {
|
|
2220
|
+
const retryAfterMsMatch = errorMessage.match(/\bretry[-_ ]?after[-_ ]?ms\s*[:=]\s*(\d+(?:\.\d+)?)/i);
|
|
2221
|
+
if (retryAfterMsMatch) {
|
|
2222
|
+
const delayMs = Math.ceil(Number(retryAfterMsMatch[1]));
|
|
2223
|
+
return Number.isFinite(delayMs) && delayMs > 0 ? delayMs : undefined;
|
|
2224
|
+
}
|
|
2225
|
+
const retryAfterSecondsMatch = errorMessage.match(/\bretry[-_ ]?after\s*[:=]\s*(\d+(?:\.\d+)?)/i);
|
|
2226
|
+
if (retryAfterSecondsMatch) {
|
|
2227
|
+
const delayMs = Math.ceil(Number(retryAfterSecondsMatch[1]) * 1000);
|
|
2228
|
+
return Number.isFinite(delayMs) && delayMs > 0 ? delayMs : undefined;
|
|
2229
|
+
}
|
|
2230
|
+
const retryInMatch = errorMessage.match(/\b(?:retry|try again|wait)\s+(?:after|in)\s*(\d+(?:\.\d+)?)\s*(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m)\b/i);
|
|
2231
|
+
if (!retryInMatch) {
|
|
2232
|
+
return undefined;
|
|
2233
|
+
}
|
|
2234
|
+
const value = Number(retryInMatch[1]);
|
|
2235
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
2236
|
+
return undefined;
|
|
2237
|
+
}
|
|
2238
|
+
const unit = retryInMatch[2].toLowerCase();
|
|
2239
|
+
if (unit === "m" || unit.startsWith("min")) {
|
|
2240
|
+
return Math.ceil(value * 60_000);
|
|
2241
|
+
}
|
|
2242
|
+
if (unit.startsWith("s")) {
|
|
2243
|
+
return Math.ceil(value * 1000);
|
|
2244
|
+
}
|
|
2245
|
+
return Math.ceil(value);
|
|
2246
|
+
}
|
|
2114
2247
|
/**
|
|
2115
2248
|
* Handle retryable errors with exponential backoff.
|
|
2116
2249
|
* @returns true if retry was initiated, false if max retries exceeded or disabled
|
|
@@ -2141,13 +2274,27 @@ export class AgentSession {
|
|
|
2141
2274
|
this._resolveRetry(); // Resolve so waitForRetry() completes
|
|
2142
2275
|
return false;
|
|
2143
2276
|
}
|
|
2144
|
-
const
|
|
2277
|
+
const errorMessage = message.errorMessage || "Unknown error";
|
|
2278
|
+
const providerDelayMs = this._getProviderRetryDelayMs(errorMessage);
|
|
2279
|
+
const maxRetryDelayMs = this.settingsManager.getProviderRetrySettings().maxRetryDelayMs;
|
|
2280
|
+
if (providerDelayMs !== undefined && providerDelayMs > maxRetryDelayMs) {
|
|
2281
|
+
this._emit({
|
|
2282
|
+
type: "auto_retry_end",
|
|
2283
|
+
success: false,
|
|
2284
|
+
attempt: this._retryAttempt,
|
|
2285
|
+
finalError: `Provider requested retry delay ${providerDelayMs}ms, exceeding configured maximum ${maxRetryDelayMs}ms`,
|
|
2286
|
+
});
|
|
2287
|
+
this._retryAttempt = 0;
|
|
2288
|
+
this._resolveRetry();
|
|
2289
|
+
return false;
|
|
2290
|
+
}
|
|
2291
|
+
const delayMs = providerDelayMs ?? settings.baseDelayMs * 2 ** (this._retryAttempt - 1);
|
|
2145
2292
|
this._emit({
|
|
2146
2293
|
type: "auto_retry_start",
|
|
2147
2294
|
attempt: this._retryAttempt,
|
|
2148
2295
|
maxAttempts: settings.maxRetries,
|
|
2149
2296
|
delayMs,
|
|
2150
|
-
errorMessage
|
|
2297
|
+
errorMessage,
|
|
2151
2298
|
});
|
|
2152
2299
|
// Remove error message from agent state (keep in session for history)
|
|
2153
2300
|
const messages = this.agent.state.messages;
|