@selesai/code 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -4
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts +4 -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/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +13 -25
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/core/agent-session.d.ts +22 -5
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +130 -49
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +13 -5
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/cache-stats.d.ts +49 -0
- package/dist/core/cache-stats.d.ts.map +1 -0
- package/dist/core/cache-stats.js +101 -0
- package/dist/core/cache-stats.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +1 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +56 -81
- 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/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +38 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +41 -12
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +28 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -6
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +34 -8
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +10 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +15 -18
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +68 -26
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js +0 -10
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/resource-loader.d.ts +2 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +8 -7
- package/dist/core/resource-loader.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 +8 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +21 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +104 -72
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +14 -3
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +29 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/timings.d.ts +4 -2
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +24 -14
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +2 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +12 -25
- package/dist/core/tools/read.js.map +1 -1
- package/dist/defaults/models.json +2 -3
- package/dist/extensions/caveman/index.js +16 -1
- package/dist/extensions/caveman/test/extension.test.js +7 -4
- package/dist/extensions/caveman/test/helpers.test.js +12 -1
- package/dist/extensions/context-compaction-reminder.test.ts +82 -0
- package/dist/extensions/context-compaction-reminder.ts +28 -0
- package/dist/extensions/handoff-new.test.ts +2 -13
- package/dist/extensions/handoff-new.ts +16 -25
- package/dist/extensions/package.json +1 -0
- package/dist/extensions/pi-subagents/agents/architect.md +25 -173
- package/dist/extensions/pi-subagents/agents/builder.md +16 -105
- package/dist/extensions/pi-subagents/agents/commentator.md +19 -116
- package/dist/extensions/pi-subagents/agents/explorer.md +13 -33
- package/dist/extensions/pi-subagents/agents/recapper.md +19 -11
- package/dist/extensions/pi-subagents/agents/researcher.md +10 -33
- package/dist/extensions/question/constants.ts +0 -7
- package/dist/extensions/question/index.ts +11 -108
- package/dist/extensions/question/schemas.ts +1 -26
- package/dist/extensions/question/shortcuts.ts +5 -14
- package/dist/extensions/question/tests/question-list.test.ts +8 -0
- package/dist/extensions/question/tests/ui-protocol.test.ts +1 -7
- package/dist/extensions/question/tui-adapter.ts +3 -20
- package/dist/extensions/question/types.ts +0 -6
- package/dist/extensions/question/ui-protocol.ts +2 -17
- package/dist/extensions/workflow/adapter.ts +384 -124
- package/dist/extensions/workflow/extension.ts +2 -1
- package/dist/extensions/workflow/modes/prototype.ts +6 -6
- package/dist/extensions/workflow/modes/quick.ts +6 -6
- package/dist/extensions/workflow/modes/task.ts +79 -0
- package/dist/extensions/workflow/run-state.ts +124 -0
- package/dist/extensions/workflow/state-machine.ts +4 -8
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +17 -4
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +23 -15
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +34 -3
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +280 -25
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-entry.js +52 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +3 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +12 -3
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +4 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +3 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +17 -6
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +25 -2
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +28 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-indicator.js +60 -0
- package/dist/modes/interactive/components/status-indicator.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +2 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +6 -2
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +19 -6
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +21 -10
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +417 -196
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -0
- package/dist/modes/interactive/theme/light.json +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +6 -2
- package/dist/modes/interactive/theme/theme.d.ts +3 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +21 -6
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +17 -3
- 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 +20 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +26 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +2 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +71 -17
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +10 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/skills/workflow-creation/SKILL.md +72 -0
- 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/image-convert.d.ts +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +21 -15
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts +18 -0
- package/dist/utils/image-process.d.ts.map +1 -0
- package/dist/utils/image-process.js +83 -0
- package/dist/utils/image-process.js.map +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +41 -0
- package/dist/utils/mime.js.map +1 -1
- package/docs/workflows.md +40 -6
- package/package.json +8 -5
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { basename, dirname } from "node:path";
|
|
17
|
-
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
17
|
+
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
18
18
|
import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
|
|
19
19
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
20
20
|
import { resolvePath } from "../utils/paths.js";
|
|
@@ -73,6 +73,9 @@ export class AgentSession {
|
|
|
73
73
|
// Event subscription state
|
|
74
74
|
_unsubscribeAgent;
|
|
75
75
|
_eventListeners = [];
|
|
76
|
+
_isAgentRunActive = false;
|
|
77
|
+
_idleWaitPromise;
|
|
78
|
+
_resolveIdleWait;
|
|
76
79
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
77
80
|
_steeringMessages = [];
|
|
78
81
|
/** Tracks pending follow-up messages for UI display. Removed when delivered. */
|
|
@@ -121,6 +124,7 @@ export class AgentSession {
|
|
|
121
124
|
// Base system prompt (without extension appends) - used to apply fresh appends each turn
|
|
122
125
|
_baseSystemPrompt = "";
|
|
123
126
|
_baseSystemPromptOptions;
|
|
127
|
+
_systemPromptOverride;
|
|
124
128
|
constructor(config) {
|
|
125
129
|
this.agent = config.agent;
|
|
126
130
|
this.sessionManager = config.sessionManager;
|
|
@@ -140,6 +144,7 @@ export class AgentSession {
|
|
|
140
144
|
// (session persistence, extensions, auto-compaction, retry logic)
|
|
141
145
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
142
146
|
this._installAgentToolHooks();
|
|
147
|
+
this._installAgentNextTurnRefresh();
|
|
143
148
|
this._buildRuntime({
|
|
144
149
|
activeToolNames: this._initialActiveToolNames,
|
|
145
150
|
includeAllExtensionTools: true,
|
|
@@ -228,6 +233,26 @@ export class AgentSession {
|
|
|
228
233
|
};
|
|
229
234
|
};
|
|
230
235
|
}
|
|
236
|
+
_installAgentNextTurnRefresh() {
|
|
237
|
+
const previousPrepareNextTurnWithContext = this.agent.prepareNextTurnWithContext ??
|
|
238
|
+
(this.agent.prepareNextTurn
|
|
239
|
+
? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
|
|
240
|
+
: undefined);
|
|
241
|
+
this.agent.prepareNextTurnWithContext = async (turn, signal) => {
|
|
242
|
+
const previousSnapshot = await previousPrepareNextTurnWithContext?.(turn, signal);
|
|
243
|
+
const previousContext = previousSnapshot?.context ?? turn.context;
|
|
244
|
+
return {
|
|
245
|
+
...previousSnapshot,
|
|
246
|
+
context: {
|
|
247
|
+
...previousContext,
|
|
248
|
+
systemPrompt: this._systemPromptOverride ?? this._baseSystemPrompt,
|
|
249
|
+
tools: this.agent.state.tools.slice(),
|
|
250
|
+
},
|
|
251
|
+
model: this.agent.state.model,
|
|
252
|
+
thinkingLevel: this.agent.state.thinkingLevel,
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
}
|
|
231
256
|
// =========================================================================
|
|
232
257
|
// Event Subscription
|
|
233
258
|
// =========================================================================
|
|
@@ -244,6 +269,33 @@ export class AgentSession {
|
|
|
244
269
|
followUp: [...this._followUpMessages],
|
|
245
270
|
});
|
|
246
271
|
}
|
|
272
|
+
_getIdleWaitPromise() {
|
|
273
|
+
if (!this._idleWaitPromise) {
|
|
274
|
+
this._idleWaitPromise = new Promise((resolve) => {
|
|
275
|
+
this._resolveIdleWait = resolve;
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
return this._idleWaitPromise;
|
|
279
|
+
}
|
|
280
|
+
_resolveIdleWaitIfIdle() {
|
|
281
|
+
if (this._isAgentRunActive || !this._resolveIdleWait) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const resolve = this._resolveIdleWait;
|
|
285
|
+
this._idleWaitPromise = undefined;
|
|
286
|
+
this._resolveIdleWait = undefined;
|
|
287
|
+
resolve();
|
|
288
|
+
}
|
|
289
|
+
async _emitAgentSettled() {
|
|
290
|
+
this._isAgentRunActive = false;
|
|
291
|
+
try {
|
|
292
|
+
await this._extensionRunner.emit({ type: "agent_settled" });
|
|
293
|
+
this._emit({ type: "agent_settled" });
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
this._resolveIdleWaitIfIdle();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
247
299
|
// Track last assistant message for auto-compaction check
|
|
248
300
|
_lastAssistantMessage = undefined;
|
|
249
301
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
@@ -412,7 +464,16 @@ export class AgentSession {
|
|
|
412
464
|
};
|
|
413
465
|
const replacement = await this._extensionRunner.emitMessageEnd(extensionEvent);
|
|
414
466
|
if (replacement) {
|
|
415
|
-
|
|
467
|
+
// Untyped extension handlers can return messages with null/missing content;
|
|
468
|
+
// normalize so it never enters agent state or session history.
|
|
469
|
+
const normalized = (replacement.role === "user" ||
|
|
470
|
+
replacement.role === "assistant" ||
|
|
471
|
+
replacement.role === "toolResult" ||
|
|
472
|
+
replacement.role === "custom") &&
|
|
473
|
+
replacement.content == null
|
|
474
|
+
? { ...replacement, content: [] }
|
|
475
|
+
: replacement;
|
|
476
|
+
this._replaceMessageInPlace(event.message, normalized);
|
|
416
477
|
}
|
|
417
478
|
}
|
|
418
479
|
else if (event.type === "tool_execution_start") {
|
|
@@ -515,9 +576,13 @@ export class AgentSession {
|
|
|
515
576
|
get thinkingLevel() {
|
|
516
577
|
return this.agent.state.thinkingLevel;
|
|
517
578
|
}
|
|
518
|
-
/** Whether
|
|
579
|
+
/** Whether the session is currently processing an agent run or post-run continuation. */
|
|
519
580
|
get isStreaming() {
|
|
520
|
-
return this.
|
|
581
|
+
return this._isAgentRunActive;
|
|
582
|
+
}
|
|
583
|
+
/** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
|
|
584
|
+
get isIdle() {
|
|
585
|
+
return !this._isAgentRunActive;
|
|
521
586
|
}
|
|
522
587
|
/** Current effective system prompt (includes any per-turn extension modifications) */
|
|
523
588
|
get systemPrompt() {
|
|
@@ -568,7 +633,7 @@ export class AgentSession {
|
|
|
568
633
|
this.agent.state.tools = tools;
|
|
569
634
|
// Rebuild base system prompt with new tool set
|
|
570
635
|
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
571
|
-
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
636
|
+
this.agent.state.systemPrompt = this._systemPromptOverride ?? this._baseSystemPrompt;
|
|
572
637
|
}
|
|
573
638
|
/** Whether compaction or branch summarization is currently running */
|
|
574
639
|
get isCompacting() {
|
|
@@ -671,6 +736,7 @@ export class AgentSession {
|
|
|
671
736
|
// Prompting
|
|
672
737
|
// =========================================================================
|
|
673
738
|
async _runAgentPrompt(messages) {
|
|
739
|
+
this._isAgentRunActive = true;
|
|
674
740
|
try {
|
|
675
741
|
await this.agent.prompt(messages);
|
|
676
742
|
while (await this._handlePostAgentRun()) {
|
|
@@ -678,7 +744,9 @@ export class AgentSession {
|
|
|
678
744
|
}
|
|
679
745
|
}
|
|
680
746
|
finally {
|
|
747
|
+
this._systemPromptOverride = undefined;
|
|
681
748
|
this._flushPendingBashMessages();
|
|
749
|
+
await this._emitAgentSettled();
|
|
682
750
|
}
|
|
683
751
|
}
|
|
684
752
|
async _handlePostAgentRun() {
|
|
@@ -779,18 +847,11 @@ export class AgentSession {
|
|
|
779
847
|
}
|
|
780
848
|
throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
|
|
781
849
|
}
|
|
782
|
-
// Check if we need to compact before sending (catches aborted responses)
|
|
850
|
+
// Check if we need to compact before sending (catches aborted responses).
|
|
851
|
+
// The user's new prompt is sent below, so do not call agent.continue() here.
|
|
783
852
|
const lastAssistant = this._findLastAssistantMessage();
|
|
784
|
-
if (lastAssistant
|
|
785
|
-
|
|
786
|
-
await this.agent.continue();
|
|
787
|
-
while (await this._handlePostAgentRun()) {
|
|
788
|
-
await this.agent.continue();
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
finally {
|
|
792
|
-
this._flushPendingBashMessages();
|
|
793
|
-
}
|
|
853
|
+
if (lastAssistant) {
|
|
854
|
+
await this._checkCompaction(lastAssistant, false);
|
|
794
855
|
}
|
|
795
856
|
// Build messages array (custom message if any, then user message)
|
|
796
857
|
messages = [];
|
|
@@ -817,7 +878,8 @@ export class AgentSession {
|
|
|
817
878
|
messages.push({
|
|
818
879
|
role: "custom",
|
|
819
880
|
customType: msg.customType,
|
|
820
|
-
content
|
|
881
|
+
// Untyped extensions can pass null/missing content; normalize at ingestion.
|
|
882
|
+
content: msg.content ?? [],
|
|
821
883
|
display: msg.display,
|
|
822
884
|
details: msg.details,
|
|
823
885
|
timestamp: Date.now(),
|
|
@@ -825,11 +887,13 @@ export class AgentSession {
|
|
|
825
887
|
}
|
|
826
888
|
}
|
|
827
889
|
// Apply extension-modified system prompt, or reset to base
|
|
828
|
-
if (result?.systemPrompt) {
|
|
890
|
+
if (result?.systemPrompt !== undefined) {
|
|
891
|
+
this._systemPromptOverride = result.systemPrompt;
|
|
829
892
|
this.agent.state.systemPrompt = result.systemPrompt;
|
|
830
893
|
}
|
|
831
894
|
else {
|
|
832
895
|
// Ensure we're using the base prompt (in case previous turn had modifications)
|
|
896
|
+
this._systemPromptOverride = undefined;
|
|
833
897
|
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
834
898
|
}
|
|
835
899
|
}
|
|
@@ -994,7 +1058,8 @@ export class AgentSession {
|
|
|
994
1058
|
const appMessage = {
|
|
995
1059
|
role: "custom",
|
|
996
1060
|
customType: message.customType,
|
|
997
|
-
content
|
|
1061
|
+
// Untyped extensions can pass null/missing content; normalize at ingestion.
|
|
1062
|
+
content: message.content ?? [],
|
|
998
1063
|
display: message.display,
|
|
999
1064
|
details: message.details,
|
|
1000
1065
|
timestamp: Date.now(),
|
|
@@ -1092,7 +1157,13 @@ export class AgentSession {
|
|
|
1092
1157
|
async abort() {
|
|
1093
1158
|
this.abortRetry();
|
|
1094
1159
|
this.agent.abort();
|
|
1095
|
-
await this.
|
|
1160
|
+
await this.waitForIdle();
|
|
1161
|
+
}
|
|
1162
|
+
async waitForIdle() {
|
|
1163
|
+
if (this.isIdle) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
await this._getIdleWaitPromise();
|
|
1096
1167
|
}
|
|
1097
1168
|
// =========================================================================
|
|
1098
1169
|
// Model Management
|
|
@@ -1777,7 +1848,11 @@ export class AgentSession {
|
|
|
1777
1848
|
});
|
|
1778
1849
|
},
|
|
1779
1850
|
appendEntry: (customType, data) => {
|
|
1780
|
-
this.sessionManager.appendCustomEntry(customType, data);
|
|
1851
|
+
const entryId = this.sessionManager.appendCustomEntry(customType, data);
|
|
1852
|
+
const entry = this.sessionManager.getEntry(entryId);
|
|
1853
|
+
if (entry) {
|
|
1854
|
+
this._emit({ type: "entry_appended", entry });
|
|
1855
|
+
}
|
|
1781
1856
|
},
|
|
1782
1857
|
setSessionName: (name) => {
|
|
1783
1858
|
this.setSessionName(name);
|
|
@@ -1803,7 +1878,7 @@ export class AgentSession {
|
|
|
1803
1878
|
setThinkingLevel: (level) => this.setThinkingLevel(level),
|
|
1804
1879
|
}, {
|
|
1805
1880
|
getModel: () => this.model,
|
|
1806
|
-
isIdle: () =>
|
|
1881
|
+
isIdle: () => this.isIdle,
|
|
1807
1882
|
isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
|
|
1808
1883
|
getSignal: () => this.agent.signal,
|
|
1809
1884
|
abort: () => {
|
|
@@ -1980,25 +2055,15 @@ export class AgentSession {
|
|
|
1980
2055
|
// =========================================================================
|
|
1981
2056
|
// Auto-Retry
|
|
1982
2057
|
// =========================================================================
|
|
1983
|
-
_isNonRetryableProviderLimitError(errorMessage) {
|
|
1984
|
-
return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorMessage);
|
|
1985
|
-
}
|
|
1986
2058
|
/**
|
|
1987
2059
|
* Check if an error is retryable (overloaded, rate limit, server errors).
|
|
1988
2060
|
* Context overflow errors are NOT retryable (handled by compaction instead).
|
|
1989
2061
|
*/
|
|
1990
2062
|
_isRetryableError(message) {
|
|
1991
|
-
|
|
2063
|
+
// Context overflow is handled by compaction, not retry.
|
|
2064
|
+
if (isContextOverflow(message, this.model?.contextWindow ?? 0))
|
|
1992
2065
|
return false;
|
|
1993
|
-
|
|
1994
|
-
const contextWindow = this.model?.contextWindow ?? 0;
|
|
1995
|
-
if (isContextOverflow(message, contextWindow))
|
|
1996
|
-
return false;
|
|
1997
|
-
const err = message.errorMessage;
|
|
1998
|
-
if (this._isNonRetryableProviderLimitError(err))
|
|
1999
|
-
return false;
|
|
2000
|
-
// 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
|
|
2001
|
-
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);
|
|
2066
|
+
return isRetryableAssistantError(message);
|
|
2002
2067
|
}
|
|
2003
2068
|
/**
|
|
2004
2069
|
* Prepare a retryable error for continuation with exponential backoff.
|
|
@@ -2371,28 +2436,44 @@ export class AgentSession {
|
|
|
2371
2436
|
return "";
|
|
2372
2437
|
}
|
|
2373
2438
|
/**
|
|
2374
|
-
* Get session statistics.
|
|
2439
|
+
* Get session statistics. Aggregates over ALL session entries (including
|
|
2440
|
+
* history that was compacted away), so token/cost totals reflect what was
|
|
2441
|
+
* actually billed across the session.
|
|
2375
2442
|
*/
|
|
2376
2443
|
getSessionStats() {
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2444
|
+
let userMessages = 0;
|
|
2445
|
+
let assistantMessages = 0;
|
|
2446
|
+
let toolResults = 0;
|
|
2447
|
+
let totalMessages = 0;
|
|
2381
2448
|
let toolCalls = 0;
|
|
2382
2449
|
let totalInput = 0;
|
|
2383
2450
|
let totalOutput = 0;
|
|
2384
2451
|
let totalCacheRead = 0;
|
|
2385
2452
|
let totalCacheWrite = 0;
|
|
2386
2453
|
let totalCost = 0;
|
|
2387
|
-
for (const
|
|
2388
|
-
if (
|
|
2454
|
+
for (const entry of this.sessionManager.getEntries()) {
|
|
2455
|
+
if (entry.type !== "message")
|
|
2456
|
+
continue;
|
|
2457
|
+
totalMessages++;
|
|
2458
|
+
const message = entry.message;
|
|
2459
|
+
if (message.role === "user") {
|
|
2460
|
+
userMessages++;
|
|
2461
|
+
}
|
|
2462
|
+
else if (message.role === "toolResult") {
|
|
2463
|
+
toolResults++;
|
|
2464
|
+
}
|
|
2465
|
+
else if (message.role === "assistant") {
|
|
2466
|
+
assistantMessages++;
|
|
2389
2467
|
const assistantMsg = message;
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2468
|
+
if (Array.isArray(assistantMsg.content)) {
|
|
2469
|
+
toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
|
|
2470
|
+
}
|
|
2471
|
+
const usage = assistantMsg.usage;
|
|
2472
|
+
totalInput += usage.input;
|
|
2473
|
+
totalOutput += usage.output;
|
|
2474
|
+
totalCacheRead += usage.cacheRead;
|
|
2475
|
+
totalCacheWrite += usage.cacheWrite;
|
|
2476
|
+
totalCost += usage.cost.total;
|
|
2396
2477
|
}
|
|
2397
2478
|
}
|
|
2398
2479
|
return {
|
|
@@ -2402,7 +2483,7 @@ export class AgentSession {
|
|
|
2402
2483
|
assistantMessages,
|
|
2403
2484
|
toolCalls,
|
|
2404
2485
|
toolResults,
|
|
2405
|
-
totalMessages
|
|
2486
|
+
totalMessages,
|
|
2406
2487
|
tokens: {
|
|
2407
2488
|
input: totalInput,
|
|
2408
2489
|
output: totalOutput,
|