@code-yeongyu/senpi 2026.8.19 → 2026.8.20
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 +117 -0
- package/dist/cli-main.js +4 -0
- package/dist/cli-main.js.map +1 -1
- package/dist/cli.js +31 -3
- package/dist/cli.js.map +1 -1
- package/dist/compile-cache.d.ts +2 -0
- package/dist/compile-cache.d.ts.map +1 -0
- package/dist/compile-cache.js +33 -0
- package/dist/compile-cache.js.map +1 -0
- package/dist/core/agent-session.d.ts +5 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +94 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +6 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +13 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/cursor-exec-bridge-session.d.ts +2 -1
- package/dist/core/cursor-exec-bridge-session.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge-session.js +5 -2
- package/dist/core/cursor-exec-bridge-session.js.map +1 -1
- package/dist/core/cursor-exec-bridge.d.ts +9 -1
- package/dist/core/cursor-exec-bridge.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge.js +26 -2
- package/dist/core/cursor-exec-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.d.ts +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.js +5 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.d.ts +6 -4
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.js +24 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.d.ts +39 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.d.ts.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.js +31 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +2 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +35 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts +8 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +4 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +28 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js +5 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +5 -0
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +1 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +4 -0
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +13 -10
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts +8 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.js +98 -18
- package/dist/core/extensions/builtin/config-reload/watch-engine.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js +7 -2
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js.map +1 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.js +15 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +7 -22
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/stale-context.d.ts +9 -0
- package/dist/core/extensions/builtin/goal/stale-context.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/stale-context.js +11 -0
- package/dist/core/extensions/builtin/goal/stale-context.js.map +1 -0
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts +8 -0
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-ticker.js +37 -3
- package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +12 -1
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.js +7 -15
- package/dist/core/extensions/builtin/prompt-url-widget.js.map +1 -1
- package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js +21 -25
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.js +20 -0
- package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts +3 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js +22 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.d.ts +17 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.js +22 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +3 -3
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -1
- package/dist/core/messages.d.ts +9 -2
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +13 -18
- package/dist/core/messages.js.map +1 -1
- package/dist/core/retry-fallback/hint-policy.d.ts +3 -2
- package/dist/core/retry-fallback/hint-policy.d.ts.map +1 -1
- package/dist/core/retry-fallback/hint-policy.js +19 -8
- package/dist/core/retry-fallback/hint-policy.js.map +1 -1
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/session-discovery.d.ts +16 -0
- package/dist/core/session-discovery.d.ts.map +1 -0
- package/dist/core/session-discovery.js +101 -0
- package/dist/core/session-discovery.js.map +1 -0
- package/dist/core/session-manager.d.ts +2 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -170
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-record.d.ts +14 -0
- package/dist/core/session-record.d.ts.map +1 -0
- package/dist/core/session-record.js +47 -0
- package/dist/core/session-record.js.map +1 -0
- package/dist/core/session-summary-cache.d.ts +40 -0
- package/dist/core/session-summary-cache.d.ts.map +1 -0
- package/dist/core/session-summary-cache.js +79 -0
- package/dist/core/session-summary-cache.js.map +1 -0
- package/dist/core/session-summary-lru.d.ts +54 -0
- package/dist/core/session-summary-lru.d.ts.map +1 -0
- package/dist/core/session-summary-lru.js +72 -0
- package/dist/core/session-summary-lru.js.map +1 -0
- package/dist/core/session-summary.d.ts +29 -0
- package/dist/core/session-summary.d.ts.map +1 -0
- package/dist/core/session-summary.js +90 -0
- package/dist/core/session-summary.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inspector-policy.d.ts +6 -0
- package/dist/inspector-policy.d.ts.map +1 -1
- package/dist/inspector-policy.js +6 -1
- package/dist/inspector-policy.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js +8 -8
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/progressive-transcript-container.d.ts +72 -0
- package/dist/modes/interactive/components/progressive-transcript-container.d.ts.map +1 -0
- package/dist/modes/interactive/components/progressive-transcript-container.js +150 -0
- package/dist/modes/interactive/components/progressive-transcript-container.js.map +1 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +8 -2
- package/dist/modes/interactive/components/status-indicator.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 +127 -65
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/split-trailing-assistant-text.d.ts +7 -0
- package/dist/modes/interactive/split-trailing-assistant-text.d.ts.map +1 -0
- package/dist/modes/interactive/split-trailing-assistant-text.js +19 -0
- package/dist/modes/interactive/split-trailing-assistant-text.js.map +1 -0
- package/dist/senpi +31 -3
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +38 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +8 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +25 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +284 -209
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +37 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +110 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.js +17 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js +27 -11
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +33 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -18,7 +18,7 @@ import { basename, dirname } from "node:path";
|
|
|
18
18
|
import { isDeepStrictEqual } from "node:util";
|
|
19
19
|
import { prepareAgentToolCall } from "@earendil-works/pi-agent-core";
|
|
20
20
|
import { contentText, SERVER_FALLBACK_ABORTED_DIAGNOSTIC } from "@earendil-works/pi-ai";
|
|
21
|
-
import { cleanupSessionResources, isClassifierRefusal, isContextOverflow, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
21
|
+
import { cleanupSessionResources, cursorOverflowCompactionSettings, isClassifierRefusal, isContextOverflow, isCursorPayloadResourceExhausted, isCursorZeroTokenResourceExhausted, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, shouldRetryOverflowWithoutCompact, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
22
22
|
import { extract429RetryAfterMs, parseRetryAfterMsMarker } from "@earendil-works/pi-ai/utils/retry-hint";
|
|
23
23
|
import { getAgentDir } from "../config.js";
|
|
24
24
|
import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
|
|
@@ -31,7 +31,7 @@ import { AgentSettledDelivery } from "./agent-settled-delivery.js";
|
|
|
31
31
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
32
32
|
import { executeBashWithOperations } from "./bash-executor.js";
|
|
33
33
|
import { envValue } from "./brand.js";
|
|
34
|
-
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
34
|
+
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, resolveThresholdContextTokens, shouldCompact, } from "./compaction/index.js";
|
|
35
35
|
import { CompactionLifecycleCoordinator } from "./compaction/lifecycle.js";
|
|
36
36
|
import { isWarmSummaryAnchorValid } from "./compaction/warm-anchor.js";
|
|
37
37
|
import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
|
|
@@ -349,6 +349,7 @@ export class AgentSession {
|
|
|
349
349
|
this._compactionLifecycle = new CompactionLifecycleCoordinator();
|
|
350
350
|
this._sessionWorkBarrier = new SessionWorkBarrier();
|
|
351
351
|
this._overflowRecoveryAttempted = false;
|
|
352
|
+
this._compactionSkippedTooSmall = false;
|
|
352
353
|
// A retry continuation immediately follows an accepted compaction. Its first
|
|
353
354
|
// response must not retrigger threshold compaction from stale provider usage.
|
|
354
355
|
this._skipNextPostRetryCompactionCheck = false;
|
|
@@ -719,6 +720,12 @@ export class AgentSession {
|
|
|
719
720
|
// completed turn with no continuation keeps pre-PR timing, while the
|
|
720
721
|
// prior prepare callback and context refresh below still run every turn.
|
|
721
722
|
const compactBeforeNextAdmission = async () => {
|
|
723
|
+
const provider = this.model?.provider;
|
|
724
|
+
// Cursor rebuilds the full conversation each hop. Compacting here
|
|
725
|
+
// mutates rootPrompt mid-run and poisons conversationId.
|
|
726
|
+
if (provider === "cursor" || provider === "cursor-cli-oauth") {
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
722
729
|
if (turn.toolResults.length === 0 && !this.agent.hasQueuedMessages()) {
|
|
723
730
|
return false;
|
|
724
731
|
}
|
|
@@ -1061,7 +1068,9 @@ export class AgentSession {
|
|
|
1061
1068
|
}
|
|
1062
1069
|
const lastAssistant = this._findLastAssistantInMessages(event.messages);
|
|
1063
1070
|
if (!lastAssistant ||
|
|
1064
|
-
(!this._isRetryableError(lastAssistant) &&
|
|
1071
|
+
(!this._isRetryableError(lastAssistant) &&
|
|
1072
|
+
!this._isHardErrorFallbackEligible(lastAssistant) &&
|
|
1073
|
+
!isCursorZeroTokenResourceExhausted(lastAssistant))) {
|
|
1065
1074
|
return;
|
|
1066
1075
|
}
|
|
1067
1076
|
this._retryPromise = new Promise((resolve) => {
|
|
@@ -1119,7 +1128,7 @@ export class AgentSession {
|
|
|
1119
1128
|
*/
|
|
1120
1129
|
_resolveThresholdContextTokens(directContextTokens) {
|
|
1121
1130
|
const messages = filterContextExcludedMessages(this.agent.state.messages);
|
|
1122
|
-
return
|
|
1131
|
+
return resolveThresholdContextTokens(directContextTokens, estimateMessagesTokens(messages));
|
|
1123
1132
|
}
|
|
1124
1133
|
_getAutoCompactionReason(message) {
|
|
1125
1134
|
const settings = this.settingsManager.getCompactionSettings();
|
|
@@ -1138,6 +1147,9 @@ export class AgentSession {
|
|
|
1138
1147
|
if (isContextOverflow(message, model.contextWindow) && (sameModel || currentContextNeedsCompaction)) {
|
|
1139
1148
|
return "overflow";
|
|
1140
1149
|
}
|
|
1150
|
+
if (this._isCursorPayloadOverflow(message)) {
|
|
1151
|
+
return "overflow";
|
|
1152
|
+
}
|
|
1141
1153
|
let contextTokens;
|
|
1142
1154
|
const directContextTokens = message.usage ? calculateContextTokens(message.usage) : 0;
|
|
1143
1155
|
if (message.stopReason !== "error" && directContextTokens !== 0) {
|
|
@@ -1225,6 +1237,9 @@ export class AgentSession {
|
|
|
1225
1237
|
return false;
|
|
1226
1238
|
}
|
|
1227
1239
|
const retryableError = this._isRetryableError(lastAssistant);
|
|
1240
|
+
if (isCursorZeroTokenResourceExhausted(lastAssistant)) {
|
|
1241
|
+
return true;
|
|
1242
|
+
}
|
|
1228
1243
|
if (!retryableError && this._isHardErrorFallbackEligible(lastAssistant)) {
|
|
1229
1244
|
return true;
|
|
1230
1245
|
}
|
|
@@ -1369,22 +1384,26 @@ export class AgentSession {
|
|
|
1369
1384
|
// Retry transient failures normally and eligible hard errors only through a fallback.
|
|
1370
1385
|
const retryableError = this._isRetryableError(msg);
|
|
1371
1386
|
const hardErrorFallbackEligible = this._isHardErrorFallbackEligible(msg);
|
|
1387
|
+
const cursorZeroTokenRe = isCursorZeroTokenResourceExhausted(msg);
|
|
1372
1388
|
const retryCanAdmitProvider = !userAbortSuppressedQueuedContinuation &&
|
|
1373
1389
|
this.settingsManager.getRetrySettings().enabled &&
|
|
1374
|
-
(retryableError || hardErrorFallbackEligible);
|
|
1390
|
+
(retryableError || hardErrorFallbackEligible || cursorZeroTokenRe);
|
|
1375
1391
|
let compactedBeforeRetry = false;
|
|
1376
1392
|
if (retryCanAdmitProvider &&
|
|
1377
1393
|
requiredAutoCompaction &&
|
|
1378
1394
|
!(requiredAutoCompaction === "threshold" && this._hasPendingPostCompactionUsageExemption(msg))) {
|
|
1379
1395
|
this._retireFailedRetryAssistant(msg);
|
|
1380
|
-
compactedBeforeRetry = await this._runPrePromptCompaction(msg, true,
|
|
1396
|
+
compactedBeforeRetry = await this._runPrePromptCompaction(msg, true, requiredAutoCompaction, true);
|
|
1381
1397
|
retryContinuationBlocked = !compactedBeforeRetry && !this._isCompactionDelegated();
|
|
1382
1398
|
}
|
|
1383
1399
|
let retryOutcome = "not-handled";
|
|
1384
1400
|
const retryOwnedDeferredQueue = DEFERRED_RETRY_QUEUE_OWNERS.has(this);
|
|
1385
1401
|
DEFERRED_RETRY_QUEUE_OWNERS.delete(this);
|
|
1386
1402
|
if (!retryContinuationBlocked && !userAbortSuppressedQueuedContinuation) {
|
|
1387
|
-
if (
|
|
1403
|
+
if (cursorZeroTokenRe) {
|
|
1404
|
+
retryOutcome = await this._handleRetryableError(msg, { sameModelRemint: true });
|
|
1405
|
+
}
|
|
1406
|
+
else if (retryableError) {
|
|
1388
1407
|
retryOutcome = await this._handleRetryableError(msg);
|
|
1389
1408
|
}
|
|
1390
1409
|
else if (hardErrorFallbackEligible) {
|
|
@@ -2014,6 +2033,15 @@ export class AgentSession {
|
|
|
2014
2033
|
getRegisteredTool(name) {
|
|
2015
2034
|
return this._toolRegistry.get(name);
|
|
2016
2035
|
}
|
|
2036
|
+
/** Cursor exec already ran the tool; still emit tool_result so plan-touch trackers see .omo/plans writes. */
|
|
2037
|
+
async emitExecBridgeToolResult(toolName, toolCallId, args, result, isError) {
|
|
2038
|
+
await this._emitAfterToolCallHooks({
|
|
2039
|
+
type: "toolCall",
|
|
2040
|
+
id: toolCallId,
|
|
2041
|
+
name: toolName,
|
|
2042
|
+
arguments: args && typeof args === "object" && !Array.isArray(args) ? args : {},
|
|
2043
|
+
}, args, result, isError);
|
|
2044
|
+
}
|
|
2017
2045
|
setActiveToolsByName(toolNames) {
|
|
2018
2046
|
const tools = [];
|
|
2019
2047
|
const validToolNames = [];
|
|
@@ -2743,7 +2771,7 @@ export class AgentSession {
|
|
|
2743
2771
|
}
|
|
2744
2772
|
async _generateSessionTitle(firstPrompt, model, abortController) {
|
|
2745
2773
|
try {
|
|
2746
|
-
const auth = await this.
|
|
2774
|
+
const auth = await this._getSummarizationRequestAuth(model);
|
|
2747
2775
|
const title = await generateSessionTitle({
|
|
2748
2776
|
firstPrompt,
|
|
2749
2777
|
model,
|
|
@@ -3885,7 +3913,7 @@ export class AgentSession {
|
|
|
3885
3913
|
throw new CompactionCancelledError();
|
|
3886
3914
|
}
|
|
3887
3915
|
const pathEntries = this.sessionManager.getBranch();
|
|
3888
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
3916
|
+
const settings = cursorOverflowCompactionSettings(this.settingsManager.getCompactionSettings(), this.model?.provider, request.reason);
|
|
3889
3917
|
let compactionResult = request.precomputed;
|
|
3890
3918
|
let fromExtension = request.precomputed !== undefined;
|
|
3891
3919
|
if (!compactionResult) {
|
|
@@ -4284,7 +4312,8 @@ export class AgentSession {
|
|
|
4284
4312
|
shouldCompact(contextUsage.tokens, contextUsage.contextWindow, settings);
|
|
4285
4313
|
const recoverableLength = sameModel && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
|
|
4286
4314
|
const isOverflow = (isContextOverflow(assistantMessage, contextWindow) && (sameModel || currentContextNeedsCompaction)) ||
|
|
4287
|
-
recoverableLength
|
|
4315
|
+
recoverableLength ||
|
|
4316
|
+
this._isCursorPayloadOverflow(assistantMessage);
|
|
4288
4317
|
if (isOverflow &&
|
|
4289
4318
|
assistantMessage.stopReason === "stop" &&
|
|
4290
4319
|
this._consumePostCompactionUsageExemption(assistantMessage)) {
|
|
@@ -4343,6 +4372,14 @@ export class AgentSession {
|
|
|
4343
4372
|
this._incrementMessageRevision();
|
|
4344
4373
|
}
|
|
4345
4374
|
if (!compacted && inlineReason && !this._isCompactionDelegated() && !this._hasSupersedingCompactionClaim()) {
|
|
4375
|
+
if (this._compactionSkippedTooSmall) {
|
|
4376
|
+
this._compactionSkippedTooSmall = false;
|
|
4377
|
+
const provider = this.model?.provider;
|
|
4378
|
+
if (provider === "cursor" || provider === "cursor-cli-oauth") {
|
|
4379
|
+
this._truncateAgentMessagesToLastUserTurn();
|
|
4380
|
+
}
|
|
4381
|
+
return true;
|
|
4382
|
+
}
|
|
4346
4383
|
throw new RequiredCompactionError();
|
|
4347
4384
|
}
|
|
4348
4385
|
return compacted;
|
|
@@ -4462,6 +4499,7 @@ export class AgentSession {
|
|
|
4462
4499
|
this._overflowRecoveryAttempted = false;
|
|
4463
4500
|
}
|
|
4464
4501
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
4502
|
+
this._compactionSkippedTooSmall = shouldRetryOverflowWithoutCompact(false, errorMessage);
|
|
4465
4503
|
const aborted = isCompactionExecutionAborted(error);
|
|
4466
4504
|
this._emit({
|
|
4467
4505
|
type: "compaction_end",
|
|
@@ -4645,7 +4683,7 @@ export class AgentSession {
|
|
|
4645
4683
|
}
|
|
4646
4684
|
if (!this._ownsCompactionController(autoCompactionController, "auto"))
|
|
4647
4685
|
return false;
|
|
4648
|
-
const preparation = prepareCompaction(this.sessionManager.getBranch(), this.settingsManager.getCompactionSettings(), reason === "overflow");
|
|
4686
|
+
const preparation = prepareCompaction(this.sessionManager.getBranch(), cursorOverflowCompactionSettings(this.settingsManager.getCompactionSettings(), this.model?.provider, reason), reason === "overflow");
|
|
4649
4687
|
if (!preparation) {
|
|
4650
4688
|
return endBeforeExecution();
|
|
4651
4689
|
}
|
|
@@ -5388,10 +5426,31 @@ export class AgentSession {
|
|
|
5388
5426
|
}
|
|
5389
5427
|
return isRetryableAssistantError(message);
|
|
5390
5428
|
}
|
|
5429
|
+
_isCursorPayloadOverflow(message) {
|
|
5430
|
+
return isCursorPayloadResourceExhausted(message, 0);
|
|
5431
|
+
}
|
|
5432
|
+
_truncateAgentMessagesToLastUserTurn() {
|
|
5433
|
+
const messages = this.agent?.state?.messages;
|
|
5434
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
5435
|
+
return false;
|
|
5436
|
+
let lastUser = -1;
|
|
5437
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5438
|
+
if (messages[i]?.role === "user") {
|
|
5439
|
+
lastUser = i;
|
|
5440
|
+
break;
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
if (lastUser <= 0)
|
|
5444
|
+
return false;
|
|
5445
|
+
this.agent.state.messages = messages.slice(lastUser);
|
|
5446
|
+
return true;
|
|
5447
|
+
}
|
|
5391
5448
|
_isHardErrorFallbackEligible(message) {
|
|
5392
5449
|
return (!message.errorMessage?.startsWith(TURN_RETRY_SUPPRESSION_PREFIX) &&
|
|
5393
5450
|
message.stopReason === "error" &&
|
|
5394
5451
|
!isContextOverflow(message, this.model?.contextWindow ?? 0) &&
|
|
5452
|
+
!this._isCursorPayloadOverflow(message) &&
|
|
5453
|
+
!isCursorZeroTokenResourceExhausted(message) &&
|
|
5395
5454
|
!isClassifierRefusal(message) &&
|
|
5396
5455
|
!message.content.some((content) => content.type === "toolCall") &&
|
|
5397
5456
|
this._retryFallback.canTryFallback());
|
|
@@ -5495,10 +5554,28 @@ export class AgentSession {
|
|
|
5495
5554
|
const errorMessage = message.errorMessage || "Unknown error";
|
|
5496
5555
|
const isRefusal = isClassifierRefusal(message);
|
|
5497
5556
|
const hardErrorFallback = options.hardErrorFallback === true;
|
|
5557
|
+
const sameModelRemint = options.sameModelRemint === true;
|
|
5498
5558
|
let switchedFallback = false;
|
|
5499
5559
|
let is429TierRouted = false;
|
|
5500
5560
|
let hintTierDelayMs;
|
|
5501
|
-
if (
|
|
5561
|
+
if (sameModelRemint) {
|
|
5562
|
+
this._retryAttempt++;
|
|
5563
|
+
if (this._retryAttempt > settings.maxRetries) {
|
|
5564
|
+
if (this._retryAttempt > 1) {
|
|
5565
|
+
this._emit({
|
|
5566
|
+
type: "auto_retry_end",
|
|
5567
|
+
success: false,
|
|
5568
|
+
attempt: this._retryAttempt,
|
|
5569
|
+
finalError: message.errorMessage,
|
|
5570
|
+
});
|
|
5571
|
+
}
|
|
5572
|
+
this._retryAttempt = 0;
|
|
5573
|
+
this._resetHintTierState();
|
|
5574
|
+
this._resolveRetry();
|
|
5575
|
+
return "not-handled";
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5578
|
+
else if (hardErrorFallback) {
|
|
5502
5579
|
// A non-retryable provider failure must never replay on the same model.
|
|
5503
5580
|
// Billing-class failures never recover on this account, so the fallback
|
|
5504
5581
|
// switch pins as the session model instead of reverting after the cooldown.
|
|
@@ -5563,6 +5640,9 @@ export class AgentSession {
|
|
|
5563
5640
|
// because a stall carries no rate-limit markers or retry-after hint.
|
|
5564
5641
|
const stallError = isProviderStreamStallError(message);
|
|
5565
5642
|
// 429-class detection: retryable AND message carries rate-limit markers.
|
|
5643
|
+
// Every same-model wait derived below is floored by the exponential schedule
|
|
5644
|
+
// inside the pure hint policy, so repeated tiny retry-after hints cannot pin
|
|
5645
|
+
// the cadence at a few milliseconds. Do not recompute that floor here.
|
|
5566
5646
|
const is429Class = !stallError &&
|
|
5567
5647
|
/rate.?limit|(?:^429(?=\s+\{)|(?:\bHTTP\/1\.[01]\s+|\bHTTP\s+|\bstatus(?:\s+code)?\s+|\berror\s+|\bcode\s+)429\b)|too many requests|resource.?exhausted/i.test(errorMessage);
|
|
5568
5648
|
if (is429Class) {
|
|
@@ -5753,6 +5833,8 @@ export class AgentSession {
|
|
|
5753
5833
|
// reach this point with a fallback already applied (hard-error, refusal) set
|
|
5754
5834
|
// switchedFallback first and force providerDelayMs undefined, so no branch may
|
|
5755
5835
|
// be reordered to fall through here expecting an implicit switch.
|
|
5836
|
+
// 429-tier delays already carry the exponential floor from nextInTurnDelayMs /
|
|
5837
|
+
// degradeWithoutFallback; the non-tier branch keeps its own exponential fallback.
|
|
5756
5838
|
const nonTierProviderDelayMs = providerDelayMs === 0 ? undefined : providerDelayMs;
|
|
5757
5839
|
const delayMs = switchedFallback
|
|
5758
5840
|
? 0
|