erosolar-cli 1.7.81 → 1.7.83
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/agents/erosolar-code.rules.json +5 -0
- package/agents/general.rules.json +5 -0
- package/dist/bin/erosolar.js +0 -2
- package/dist/bin/erosolar.js.map +1 -1
- package/dist/contracts/agent-schemas.json +20 -12
- package/dist/contracts/unified-schema.json +1 -1
- package/dist/core/agent.d.ts +36 -3
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +223 -8
- package/dist/core/agent.js.map +1 -1
- package/dist/core/cliTestHarness.d.ts +200 -0
- package/dist/core/cliTestHarness.d.ts.map +1 -0
- package/dist/core/cliTestHarness.js +549 -0
- package/dist/core/cliTestHarness.js.map +1 -0
- package/dist/core/errors/apiKeyErrors.js +1 -1
- package/dist/core/errors/apiKeyErrors.js.map +1 -1
- package/dist/core/isolatedVerifier.js +274 -22
- package/dist/core/isolatedVerifier.js.map +1 -1
- package/dist/core/modelDiscovery.d.ts.map +1 -1
- package/dist/core/modelDiscovery.js +23 -28
- package/dist/core/modelDiscovery.js.map +1 -1
- package/dist/core/multilinePasteHandler.d.ts +35 -0
- package/dist/core/multilinePasteHandler.d.ts.map +1 -0
- package/dist/core/multilinePasteHandler.js +80 -0
- package/dist/core/multilinePasteHandler.js.map +1 -0
- package/dist/core/secretStore.d.ts +9 -0
- package/dist/core/secretStore.d.ts.map +1 -1
- package/dist/core/secretStore.js +52 -2
- package/dist/core/secretStore.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/headless/headlessApp.d.ts.map +1 -1
- package/dist/headless/headlessApp.js +16 -0
- package/dist/headless/headlessApp.js.map +1 -1
- package/dist/plugins/providers/google/index.js +3 -2
- package/dist/plugins/providers/google/index.js.map +1 -1
- package/dist/providers/anthropicProvider.d.ts.map +1 -1
- package/dist/providers/anthropicProvider.js +27 -1
- package/dist/providers/anthropicProvider.js.map +1 -1
- package/dist/providers/googleProvider.d.ts.map +1 -1
- package/dist/providers/googleProvider.js +23 -1
- package/dist/providers/googleProvider.js.map +1 -1
- package/dist/providers/openaiChatCompletionsProvider.d.ts +2 -1
- package/dist/providers/openaiChatCompletionsProvider.d.ts.map +1 -1
- package/dist/providers/openaiChatCompletionsProvider.js +111 -4
- package/dist/providers/openaiChatCompletionsProvider.js.map +1 -1
- package/dist/providers/openaiResponsesProvider.d.ts.map +1 -1
- package/dist/providers/openaiResponsesProvider.js +39 -18
- package/dist/providers/openaiResponsesProvider.js.map +1 -1
- package/dist/runtime/agentController.d.ts +4 -0
- package/dist/runtime/agentController.d.ts.map +1 -1
- package/dist/runtime/agentController.js +29 -3
- package/dist/runtime/agentController.js.map +1 -1
- package/dist/security/persistence-research.d.ts +0 -2
- package/dist/security/persistence-research.d.ts.map +1 -1
- package/dist/security/persistence-research.js +0 -2
- package/dist/security/persistence-research.js.map +1 -1
- package/dist/security/security-testing-framework.d.ts +0 -2
- package/dist/security/security-testing-framework.d.ts.map +1 -1
- package/dist/security/security-testing-framework.js +0 -2
- package/dist/security/security-testing-framework.js.map +1 -1
- package/dist/shell/bracketedPasteManager.d.ts +8 -5
- package/dist/shell/bracketedPasteManager.d.ts.map +1 -1
- package/dist/shell/bracketedPasteManager.js +27 -43
- package/dist/shell/bracketedPasteManager.js.map +1 -1
- package/dist/shell/composableMessage.d.ts +1 -1
- package/dist/shell/composableMessage.js +2 -2
- package/dist/shell/composableMessage.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +7 -48
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +144 -340
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/shellApp.d.ts.map +1 -1
- package/dist/shell/shellApp.js +54 -3
- package/dist/shell/shellApp.js.map +1 -1
- package/dist/shell/systemPrompt.d.ts +1 -1
- package/dist/shell/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +10 -3
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/updateManager.js +4 -2
- package/dist/shell/updateManager.js.map +1 -1
- package/dist/subagents/taskRunner.js +2 -2
- package/dist/subagents/taskRunner.js.map +1 -1
- package/dist/tools/cloudTools.d.ts +0 -2
- package/dist/tools/cloudTools.d.ts.map +1 -1
- package/dist/tools/cloudTools.js +0 -2
- package/dist/tools/cloudTools.js.map +1 -1
- package/dist/tools/fileTools.d.ts.map +1 -1
- package/dist/tools/fileTools.js +31 -3
- package/dist/tools/fileTools.js.map +1 -1
- package/dist/ui/ShellUIAdapter.d.ts +10 -2
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +123 -11
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/display.d.ts +14 -2
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +177 -38
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/keyboardShortcuts.d.ts.map +1 -1
- package/dist/ui/keyboardShortcuts.js +12 -2
- package/dist/ui/keyboardShortcuts.js.map +1 -1
- package/dist/ui/persistentPrompt.d.ts +24 -0
- package/dist/ui/persistentPrompt.d.ts.map +1 -1
- package/dist/ui/persistentPrompt.js +86 -4
- package/dist/ui/persistentPrompt.js.map +1 -1
- package/dist/ui/toolDisplay.d.ts.map +1 -1
- package/dist/ui/toolDisplay.js +652 -0
- package/dist/ui/toolDisplay.js.map +1 -1
- package/package.json +3 -3
- package/dist/shell/inputProcessor.d.ts +0 -55
- package/dist/shell/inputProcessor.d.ts.map +0 -1
- package/dist/shell/inputProcessor.js +0 -171
- package/dist/shell/inputProcessor.js.map +0 -1
|
@@ -43,6 +43,11 @@
|
|
|
43
43
|
"summary": "Narrate intent before running tools/commands and summarize output afterward.",
|
|
44
44
|
"severity": "required"
|
|
45
45
|
},
|
|
46
|
+
{
|
|
47
|
+
"id": "guardrail.continuous_execution",
|
|
48
|
+
"summary": "CRITICAL: Continue using tools until the task is complete. Do NOT stop after reading files—immediately proceed to make the requested edits. Do NOT describe what you WILL do—just DO it by calling the appropriate tools. After each tool call, continue with the next step until the task is fully accomplished.",
|
|
49
|
+
"severity": "critical"
|
|
50
|
+
},
|
|
46
51
|
{
|
|
47
52
|
"id": "guardrail.manual_loop_supervision",
|
|
48
53
|
"summary": "Stop if you lack evidence—surface blockers instead of guessing or editing blindly.",
|
|
@@ -42,6 +42,11 @@
|
|
|
42
42
|
"detail": "Keep tool usage auditable by narrating the intent before running them and summarizing their output afterward.",
|
|
43
43
|
"severity": "required"
|
|
44
44
|
},
|
|
45
|
+
{
|
|
46
|
+
"id": "guardrail.continuous_execution",
|
|
47
|
+
"summary": "CRITICAL: Continue using tools until the task is complete. Do NOT stop after reading files—immediately proceed to make the requested edits. Do NOT describe what you WILL do—just DO it by calling the appropriate tools. After each tool call, continue with the next step until the task is fully accomplished.",
|
|
48
|
+
"severity": "critical"
|
|
49
|
+
},
|
|
45
50
|
{
|
|
46
51
|
"id": "guardrail.manual_loop_supervision",
|
|
47
52
|
"summary": "Humans supervise the loop manually—escalate when you lack evidence or stall.",
|
package/dist/bin/erosolar.js
CHANGED
package/dist/bin/erosolar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"erosolar.js","sourceRoot":"","sources":["../../src/bin/erosolar.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"erosolar.js","sourceRoot":"","sources":["../../src/bin/erosolar.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC5B,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACvC,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,WAAW,CAAC,eAAe,EAAE,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7E,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -61,6 +61,14 @@
|
|
|
61
61
|
],
|
|
62
62
|
|
|
63
63
|
"models": [
|
|
64
|
+
{
|
|
65
|
+
"id": "gpt-5.1-codex-mini",
|
|
66
|
+
"label": "gpt-5.1-codex-mini",
|
|
67
|
+
"provider": "openai",
|
|
68
|
+
"description": "Lightweight GPT-5.1 Codex for fast iteration and quick tasks.",
|
|
69
|
+
"reasoningEffort": "low",
|
|
70
|
+
"capabilities": ["chat", "reasoning", "tools", "streaming"]
|
|
71
|
+
},
|
|
64
72
|
{
|
|
65
73
|
"id": "gpt-5.1-codex",
|
|
66
74
|
"label": "gpt-5.1-codex",
|
|
@@ -111,8 +119,8 @@
|
|
|
111
119
|
"capabilities": ["chat", "reasoning", "tools", "streaming"]
|
|
112
120
|
},
|
|
113
121
|
{
|
|
114
|
-
"id": "claude-opus-4
|
|
115
|
-
"label": "opus-4
|
|
122
|
+
"id": "claude-opus-4-20250514",
|
|
123
|
+
"label": "opus-4",
|
|
116
124
|
"provider": "anthropic",
|
|
117
125
|
"description": "Anthropic Opus 4.1 for the richest Claude reasoning runs.",
|
|
118
126
|
"temperature": 0.7,
|
|
@@ -120,7 +128,7 @@
|
|
|
120
128
|
"capabilities": ["chat", "reasoning", "tools", "streaming"]
|
|
121
129
|
},
|
|
122
130
|
{
|
|
123
|
-
"id": "claude-haiku-4
|
|
131
|
+
"id": "claude-haiku-4-5-20251001",
|
|
124
132
|
"label": "haiku-4.5",
|
|
125
133
|
"provider": "anthropic",
|
|
126
134
|
"description": "Anthropic Haiku 4.5 focused on latency-sensitive workflows.",
|
|
@@ -143,12 +151,19 @@
|
|
|
143
151
|
"capabilities": ["chat", "tools", "streaming"]
|
|
144
152
|
},
|
|
145
153
|
{
|
|
146
|
-
"id": "grok-4
|
|
147
|
-
"label": "grok-4
|
|
154
|
+
"id": "grok-4-1-fast-reasoning",
|
|
155
|
+
"label": "grok-4-1-fast-reasoning",
|
|
148
156
|
"provider": "xai",
|
|
149
157
|
"description": "Grok-4.1 fast reasoning mode with improved performance and enhanced thinking capabilities.",
|
|
150
158
|
"capabilities": ["chat", "reasoning", "tools", "streaming"]
|
|
151
159
|
},
|
|
160
|
+
{
|
|
161
|
+
"id": "grok-4-1-fast-non-reasoning",
|
|
162
|
+
"label": "grok-4-1-fast-non-reasoning",
|
|
163
|
+
"provider": "xai",
|
|
164
|
+
"description": "Grok-4.1 fast non-reasoning mode for lower latency without thinking.",
|
|
165
|
+
"capabilities": ["chat", "tools", "streaming"]
|
|
166
|
+
},
|
|
152
167
|
{
|
|
153
168
|
"id": "grok-4",
|
|
154
169
|
"label": "grok-4",
|
|
@@ -191,13 +206,6 @@
|
|
|
191
206
|
"description": "Google Gemini 2.5 Flash for lower-latency edits and iterative coding.",
|
|
192
207
|
"capabilities": ["chat", "tools", "streaming", "multimodal"]
|
|
193
208
|
},
|
|
194
|
-
{
|
|
195
|
-
"id": "gemini-3.0-pro-preview",
|
|
196
|
-
"label": "gemini-3.0-pro-preview",
|
|
197
|
-
"provider": "google",
|
|
198
|
-
"description": "Google Gemini 3.0 Pro Preview for next-generation multimodal reasoning and advanced capabilities.",
|
|
199
|
-
"capabilities": ["chat", "reasoning", "tools", "streaming", "multimodal"]
|
|
200
|
-
},
|
|
201
209
|
{
|
|
202
210
|
"id": "llama3.1:8b",
|
|
203
211
|
"label": "llama3.1:8b",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"maxDelayMs": 40000,
|
|
23
23
|
"backoffMultiplier": 2
|
|
24
24
|
},
|
|
25
|
-
"models": ["claude-opus-4-5-20251101", "claude-sonnet-4-5-20250929", "claude-haiku-4-5"],
|
|
25
|
+
"models": ["claude-opus-4-5-20251101", "claude-sonnet-4-5-20250929", "claude-haiku-4-5-20251001"],
|
|
26
26
|
"defaultModel": "claude-sonnet-4-5-20250929",
|
|
27
27
|
"status": "production"
|
|
28
28
|
},
|
package/dist/core/agent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolRuntime } from './toolRuntime.js';
|
|
2
2
|
import { type ConversationMessage, type LLMProvider, type ProviderUsage } from './types.js';
|
|
3
3
|
import { ContextManager } from './contextManager.js';
|
|
4
|
+
import { type PasteSummary } from './multilinePasteHandler.js';
|
|
4
5
|
export interface AgentCallbacks {
|
|
5
6
|
onAssistantMessage?(content: string, metadata: AssistantMessageMetadata): void;
|
|
6
7
|
onStreamChunk?(chunk: string): void;
|
|
@@ -11,12 +12,30 @@ export interface AgentCallbacks {
|
|
|
11
12
|
onContextRecovery?(attempt: number, maxAttempts: number, message: string): void;
|
|
12
13
|
/** Called when agent continues after context recovery - useful for updating UI */
|
|
13
14
|
onContinueAfterRecovery?(): void;
|
|
15
|
+
/** Called when auto-continuing because model expressed intent but didn't act */
|
|
16
|
+
onAutoContinue?(attempt: number, maxAttempts: number, message: string): void;
|
|
17
|
+
/** Called when multi-line paste is detected - displays summary instead of full content */
|
|
18
|
+
onMultilinePaste?(summary: string, metadata: PasteSummary): void;
|
|
19
|
+
/** Called when verification should be triggered for a final response */
|
|
20
|
+
onVerificationNeeded?(response: string, context: VerificationCallbackContext): void;
|
|
21
|
+
}
|
|
22
|
+
export interface VerificationCallbackContext {
|
|
23
|
+
/** Working directory for verification */
|
|
24
|
+
workingDirectory: string;
|
|
25
|
+
/** Recent conversation history for context */
|
|
26
|
+
conversationHistory: string[];
|
|
27
|
+
/** Provider ID */
|
|
28
|
+
provider: string;
|
|
29
|
+
/** Model ID */
|
|
30
|
+
model: string;
|
|
14
31
|
}
|
|
15
32
|
export interface AssistantMessageMetadata {
|
|
16
33
|
isFinal: boolean;
|
|
17
34
|
elapsedMs?: number;
|
|
18
35
|
usage?: ProviderUsage | null;
|
|
19
36
|
contextStats?: Record<string, unknown> | null;
|
|
37
|
+
/** True if content was already displayed via streaming chunks */
|
|
38
|
+
wasStreamed?: boolean;
|
|
20
39
|
}
|
|
21
40
|
interface AgentOptions {
|
|
22
41
|
provider: LLMProvider;
|
|
@@ -24,6 +43,12 @@ interface AgentOptions {
|
|
|
24
43
|
systemPrompt: string;
|
|
25
44
|
callbacks?: AgentCallbacks;
|
|
26
45
|
contextManager?: ContextManager;
|
|
46
|
+
/** Provider ID for verification context */
|
|
47
|
+
providerId?: string;
|
|
48
|
+
/** Model ID for verification context */
|
|
49
|
+
modelId?: string;
|
|
50
|
+
/** Working directory for verification */
|
|
51
|
+
workingDirectory?: string;
|
|
27
52
|
}
|
|
28
53
|
export declare class AgentRuntime {
|
|
29
54
|
private readonly messages;
|
|
@@ -33,6 +58,9 @@ export declare class AgentRuntime {
|
|
|
33
58
|
private readonly contextManager;
|
|
34
59
|
private activeRun;
|
|
35
60
|
private readonly baseSystemPrompt;
|
|
61
|
+
private readonly providerId;
|
|
62
|
+
private readonly modelId;
|
|
63
|
+
private readonly workingDirectory;
|
|
36
64
|
constructor(options: AgentOptions);
|
|
37
65
|
send(text: string, useStreaming?: boolean): Promise<string>;
|
|
38
66
|
private processConversation;
|
|
@@ -48,6 +76,11 @@ export declare class AgentRuntime {
|
|
|
48
76
|
private resolveToolCalls;
|
|
49
77
|
private get providerTools();
|
|
50
78
|
private emitAssistantMessage;
|
|
79
|
+
/**
|
|
80
|
+
* Trigger verification for a final response if callback is registered
|
|
81
|
+
* and response contains verifiable claims (implementation, build success, etc.)
|
|
82
|
+
*/
|
|
83
|
+
private triggerVerificationIfNeeded;
|
|
51
84
|
getHistory(): ConversationMessage[];
|
|
52
85
|
loadHistory(history: ConversationMessage[]): void;
|
|
53
86
|
clearHistory(): void;
|
|
@@ -72,9 +105,9 @@ export declare class AgentRuntime {
|
|
|
72
105
|
*
|
|
73
106
|
* This is called when an API call fails due to context length exceeding limits.
|
|
74
107
|
* It performs increasingly aggressive pruning on each attempt:
|
|
75
|
-
* - Attempt 1: Remove 30% of oldest messages
|
|
76
|
-
* - Attempt 2: Remove 50% of oldest messages
|
|
77
|
-
* - Attempt 3: Remove 70% of oldest messages
|
|
108
|
+
* - Attempt 1: Remove 30% of oldest messages + truncate tool outputs to 5k
|
|
109
|
+
* - Attempt 2: Remove 50% of oldest messages + truncate tool outputs to 2k
|
|
110
|
+
* - Attempt 3: Remove 70% of oldest messages + truncate tool outputs to 500 chars
|
|
78
111
|
*
|
|
79
112
|
* @returns true if recovery was successful (context was reduced)
|
|
80
113
|
*/
|
package/dist/core/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAGhB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/core/agent.js
CHANGED
|
@@ -1,7 +1,54 @@
|
|
|
1
|
+
import { isMultilinePaste, processPaste } from './multilinePasteHandler.js';
|
|
1
2
|
/**
|
|
2
3
|
* Maximum number of context overflow recovery attempts
|
|
3
4
|
*/
|
|
4
5
|
const MAX_CONTEXT_RECOVERY_ATTEMPTS = 3;
|
|
6
|
+
/**
|
|
7
|
+
* Maximum number of auto-continuation attempts when model expresses intent but doesn't act
|
|
8
|
+
*/
|
|
9
|
+
const MAX_AUTO_CONTINUE_ATTEMPTS = 3;
|
|
10
|
+
/**
|
|
11
|
+
* Patterns that indicate the model intends to take action but hasn't yet
|
|
12
|
+
* These suggest the model should be prompted to continue
|
|
13
|
+
*/
|
|
14
|
+
const INTENT_WITHOUT_ACTION_PATTERNS = [
|
|
15
|
+
// "Let me X" patterns - model is stating what it will do
|
|
16
|
+
/\blet me\s+(create|write|implement|add|update|edit|modify|fix|build|make|refactor|read|check|look|search|find|analyze|examine|review)/i,
|
|
17
|
+
// "I'll X" / "I will X" patterns
|
|
18
|
+
/\bi['']ll\s+(create|write|implement|add|update|edit|modify|fix|build|make|refactor|read|check|look|search|find|analyze|start|begin|now)/i,
|
|
19
|
+
/\bi will\s+(create|write|implement|add|update|edit|modify|fix|build|make|refactor|read|check|look|search|find|analyze|start|begin|now)/i,
|
|
20
|
+
// "I'm going to X" patterns
|
|
21
|
+
/\bi['']m going to\s+(create|write|implement|add|update|edit|modify|fix|build|make|refactor|read|check|look|search|find|analyze)/i,
|
|
22
|
+
// "Now I'll X" / "First, I'll X" patterns
|
|
23
|
+
/\b(now|first|next)\s*(,)?\s*i['']ll\s+/i,
|
|
24
|
+
// Explicit continuation signals
|
|
25
|
+
/\bhere['']s (the|my) (plan|approach|solution|implementation)/i,
|
|
26
|
+
// Numbered steps suggesting action to come
|
|
27
|
+
/^\s*\d+\.\s+(create|write|implement|add|update|edit|modify|fix|show|read|check)/im,
|
|
28
|
+
// Bullet points suggesting planned actions
|
|
29
|
+
/^[\s•\-\*]+\s*(create|write|implement|add|update|edit|modify|fix|shows?|reads?|checks?)\s/im,
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Check if response indicates intent to act without actually acting
|
|
33
|
+
* This detects when the model says "let me do X" but doesn't call any tools
|
|
34
|
+
*/
|
|
35
|
+
function shouldAutoContinue(content, hasToolCalls) {
|
|
36
|
+
// If there are tool calls, no need to auto-continue
|
|
37
|
+
if (hasToolCalls) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
// If content is very short, likely not an incomplete intent
|
|
41
|
+
if (content.length < 50) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// Check for intent patterns
|
|
45
|
+
for (const pattern of INTENT_WITHOUT_ACTION_PATTERNS) {
|
|
46
|
+
if (pattern.test(content)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
5
52
|
/**
|
|
6
53
|
* Check if an error is a context overflow error
|
|
7
54
|
*/
|
|
@@ -24,11 +71,17 @@ export class AgentRuntime {
|
|
|
24
71
|
contextManager;
|
|
25
72
|
activeRun = null;
|
|
26
73
|
baseSystemPrompt;
|
|
74
|
+
providerId;
|
|
75
|
+
modelId;
|
|
76
|
+
workingDirectory;
|
|
27
77
|
constructor(options) {
|
|
28
78
|
this.provider = options.provider;
|
|
29
79
|
this.toolRuntime = options.toolRuntime;
|
|
30
80
|
this.callbacks = options.callbacks ?? {};
|
|
31
81
|
this.contextManager = options.contextManager ?? null;
|
|
82
|
+
this.providerId = options.providerId ?? 'unknown';
|
|
83
|
+
this.modelId = options.modelId ?? 'unknown';
|
|
84
|
+
this.workingDirectory = options.workingDirectory ?? process.cwd();
|
|
32
85
|
const trimmedPrompt = options.systemPrompt.trim();
|
|
33
86
|
this.baseSystemPrompt = trimmedPrompt || null;
|
|
34
87
|
if (trimmedPrompt) {
|
|
@@ -40,7 +93,18 @@ export class AgentRuntime {
|
|
|
40
93
|
if (!prompt) {
|
|
41
94
|
return '';
|
|
42
95
|
}
|
|
43
|
-
|
|
96
|
+
// Handle multi-line paste: show summary to user, send full content to AI
|
|
97
|
+
if (isMultilinePaste(prompt)) {
|
|
98
|
+
const processed = processPaste(prompt);
|
|
99
|
+
// Notify UI about the paste summary
|
|
100
|
+
this.callbacks.onMultilinePaste?.(processed.displaySummary, processed.metadata);
|
|
101
|
+
// But send the full content to the AI
|
|
102
|
+
this.messages.push({ role: 'user', content: processed.fullContent });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Single-line or short text: send as-is
|
|
106
|
+
this.messages.push({ role: 'user', content: prompt });
|
|
107
|
+
}
|
|
44
108
|
const run = { startedAt: Date.now() };
|
|
45
109
|
this.activeRun = run;
|
|
46
110
|
try {
|
|
@@ -57,6 +121,7 @@ export class AgentRuntime {
|
|
|
57
121
|
}
|
|
58
122
|
async processConversation() {
|
|
59
123
|
let contextRecoveryAttempts = 0;
|
|
124
|
+
let autoContinueAttempts = 0;
|
|
60
125
|
while (true) {
|
|
61
126
|
// Prune messages if approaching context limit (BEFORE generation)
|
|
62
127
|
await this.pruneMessagesIfNeeded();
|
|
@@ -80,13 +145,40 @@ export class AgentRuntime {
|
|
|
80
145
|
}
|
|
81
146
|
this.messages.push(assistantMessage);
|
|
82
147
|
await this.resolveToolCalls(response.toolCalls);
|
|
148
|
+
// Reset auto-continue counter since model is actively working
|
|
149
|
+
autoContinueAttempts = 0;
|
|
83
150
|
continue;
|
|
84
151
|
}
|
|
85
152
|
const reply = response.content?.trim() ?? '';
|
|
153
|
+
// Check if model expressed intent to act but didn't call tools
|
|
154
|
+
// This catches "Let me create..." without actual tool calls
|
|
155
|
+
if (shouldAutoContinue(reply, false) && autoContinueAttempts < MAX_AUTO_CONTINUE_ATTEMPTS) {
|
|
156
|
+
autoContinueAttempts++;
|
|
157
|
+
// Emit the planning content but mark as non-final
|
|
158
|
+
if (reply) {
|
|
159
|
+
this.emitAssistantMessage(reply, { isFinal: false, usage, contextStats });
|
|
160
|
+
}
|
|
161
|
+
this.messages.push({ role: 'assistant', content: reply });
|
|
162
|
+
// Auto-prompt with increasingly direct instructions
|
|
163
|
+
const prompts = [
|
|
164
|
+
'Continue. Execute the actions you described using the available tools.',
|
|
165
|
+
'You MUST use tools NOW. Call write_file or edit_file immediately. Do not explain - just call the tool.',
|
|
166
|
+
'CRITICAL: Call a tool right now. Use write_file with file_path and content parameters. No more text - only tool calls.',
|
|
167
|
+
];
|
|
168
|
+
this.messages.push({
|
|
169
|
+
role: 'user',
|
|
170
|
+
content: prompts[Math.min(autoContinueAttempts - 1, prompts.length - 1)],
|
|
171
|
+
});
|
|
172
|
+
const autoContinueMessage = `Model expressed intent but didn't use tools. Auto-prompting to continue...`;
|
|
173
|
+
this.callbacks.onAutoContinue?.(autoContinueAttempts, MAX_AUTO_CONTINUE_ATTEMPTS, autoContinueMessage);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
86
176
|
if (reply) {
|
|
87
177
|
this.emitAssistantMessage(reply, { isFinal: true, usage, contextStats });
|
|
88
178
|
}
|
|
89
179
|
this.messages.push({ role: 'assistant', content: reply });
|
|
180
|
+
// Trigger verification for final responses with verifiable claims
|
|
181
|
+
this.triggerVerificationIfNeeded(reply);
|
|
90
182
|
return reply;
|
|
91
183
|
}
|
|
92
184
|
catch (error) {
|
|
@@ -111,6 +203,7 @@ export class AgentRuntime {
|
|
|
111
203
|
return this.processConversation();
|
|
112
204
|
}
|
|
113
205
|
let contextRecoveryAttempts = 0;
|
|
206
|
+
let autoContinueAttempts = 0;
|
|
114
207
|
while (true) {
|
|
115
208
|
// Prune messages if approaching context limit (BEFORE generation)
|
|
116
209
|
await this.pruneMessagesIfNeeded();
|
|
@@ -138,7 +231,8 @@ export class AgentRuntime {
|
|
|
138
231
|
if (toolCalls.length > 0) {
|
|
139
232
|
const narration = fullContent.trim();
|
|
140
233
|
if (narration) {
|
|
141
|
-
|
|
234
|
+
// Mark as wasStreamed since content was already output via onStreamChunk
|
|
235
|
+
this.emitAssistantMessage(narration, { isFinal: false, usage, contextStats, wasStreamed: true });
|
|
142
236
|
}
|
|
143
237
|
const assistantMessage = {
|
|
144
238
|
role: 'assistant',
|
|
@@ -147,14 +241,42 @@ export class AgentRuntime {
|
|
|
147
241
|
};
|
|
148
242
|
this.messages.push(assistantMessage);
|
|
149
243
|
await this.resolveToolCalls(toolCalls);
|
|
244
|
+
// Reset auto-continue counter since model is actively working
|
|
245
|
+
autoContinueAttempts = 0;
|
|
150
246
|
continue;
|
|
151
247
|
}
|
|
152
|
-
//
|
|
248
|
+
// Check if model expressed intent to act but didn't call tools
|
|
249
|
+
// This catches "Let me create..." without actual tool calls
|
|
153
250
|
const reply = fullContent.trim();
|
|
251
|
+
if (shouldAutoContinue(reply, false) && autoContinueAttempts < MAX_AUTO_CONTINUE_ATTEMPTS) {
|
|
252
|
+
autoContinueAttempts++;
|
|
253
|
+
// Emit the planning content but mark as non-final
|
|
254
|
+
// Mark as wasStreamed since content was already output via onStreamChunk
|
|
255
|
+
if (reply) {
|
|
256
|
+
this.emitAssistantMessage(reply, { isFinal: false, usage, contextStats, wasStreamed: true });
|
|
257
|
+
}
|
|
258
|
+
this.messages.push({ role: 'assistant', content: reply });
|
|
259
|
+
// Auto-prompt with increasingly direct instructions
|
|
260
|
+
const prompts = [
|
|
261
|
+
'Continue. Execute the actions you described using the available tools.',
|
|
262
|
+
'You MUST use tools NOW. Call write_file or edit_file immediately. Do not explain - just call the tool.',
|
|
263
|
+
'CRITICAL: Call a tool right now. Use write_file with file_path and content parameters. No more text - only tool calls.',
|
|
264
|
+
];
|
|
265
|
+
this.messages.push({
|
|
266
|
+
role: 'user',
|
|
267
|
+
content: prompts[Math.min(autoContinueAttempts - 1, prompts.length - 1)],
|
|
268
|
+
});
|
|
269
|
+
const autoContinueMessage = `Model expressed intent but didn't use tools. Auto-prompting to continue...`;
|
|
270
|
+
this.callbacks.onAutoContinue?.(autoContinueAttempts, MAX_AUTO_CONTINUE_ATTEMPTS, autoContinueMessage);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
// Final message - mark as streamed to avoid double-display in UI
|
|
154
274
|
if (reply) {
|
|
155
|
-
this.emitAssistantMessage(reply, { isFinal: true, usage, contextStats });
|
|
275
|
+
this.emitAssistantMessage(reply, { isFinal: true, usage, contextStats, wasStreamed: true });
|
|
156
276
|
}
|
|
157
277
|
this.messages.push({ role: 'assistant', content: reply });
|
|
278
|
+
// Trigger verification for final responses with verifiable claims
|
|
279
|
+
this.triggerVerificationIfNeeded(reply);
|
|
158
280
|
return reply;
|
|
159
281
|
}
|
|
160
282
|
catch (error) {
|
|
@@ -249,6 +371,46 @@ export class AgentRuntime {
|
|
|
249
371
|
}
|
|
250
372
|
this.callbacks.onAssistantMessage?.(content, payload);
|
|
251
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Trigger verification for a final response if callback is registered
|
|
376
|
+
* and response contains verifiable claims (implementation, build success, etc.)
|
|
377
|
+
*/
|
|
378
|
+
triggerVerificationIfNeeded(response) {
|
|
379
|
+
if (!this.callbacks.onVerificationNeeded) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
// Only trigger verification for responses that likely contain verifiable claims
|
|
383
|
+
// These patterns indicate the model is claiming to have completed work
|
|
384
|
+
const verifiablePatterns = [
|
|
385
|
+
/\b(implemented|created|wrote|added|fixed|built|deployed|completed|refactored)\b/i,
|
|
386
|
+
/\b(tests?\s+(are\s+)?pass(ing)?|build\s+succeed)/i,
|
|
387
|
+
/\b(file|function|class|module|component)\s+(has been|is now|was)\s+(created|updated|modified)/i,
|
|
388
|
+
/✅|✓|\[done\]|\[complete\]/i,
|
|
389
|
+
/\bcommit(ted)?\b.*\b(success|done)\b/i,
|
|
390
|
+
];
|
|
391
|
+
const hasVerifiableClaims = verifiablePatterns.some(pattern => pattern.test(response));
|
|
392
|
+
if (!hasVerifiableClaims) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
// Build conversation history for context (last 5 user/assistant exchanges)
|
|
396
|
+
const conversationHistory = [];
|
|
397
|
+
const recentMessages = this.messages.slice(-10);
|
|
398
|
+
for (const msg of recentMessages) {
|
|
399
|
+
if (msg.role === 'user' || msg.role === 'assistant') {
|
|
400
|
+
const content = typeof msg.content === 'string' ? msg.content : '';
|
|
401
|
+
if (content.length > 0) {
|
|
402
|
+
conversationHistory.push(`${msg.role}: ${content.slice(0, 500)}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Trigger verification callback
|
|
407
|
+
this.callbacks.onVerificationNeeded(response, {
|
|
408
|
+
workingDirectory: this.workingDirectory,
|
|
409
|
+
conversationHistory,
|
|
410
|
+
provider: this.providerId,
|
|
411
|
+
model: this.modelId,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
252
414
|
getHistory() {
|
|
253
415
|
return this.messages.map(cloneMessage);
|
|
254
416
|
}
|
|
@@ -323,9 +485,9 @@ export class AgentRuntime {
|
|
|
323
485
|
*
|
|
324
486
|
* This is called when an API call fails due to context length exceeding limits.
|
|
325
487
|
* It performs increasingly aggressive pruning on each attempt:
|
|
326
|
-
* - Attempt 1: Remove 30% of oldest messages
|
|
327
|
-
* - Attempt 2: Remove 50% of oldest messages
|
|
328
|
-
* - Attempt 3: Remove 70% of oldest messages
|
|
488
|
+
* - Attempt 1: Remove 30% of oldest messages + truncate tool outputs to 5k
|
|
489
|
+
* - Attempt 2: Remove 50% of oldest messages + truncate tool outputs to 2k
|
|
490
|
+
* - Attempt 3: Remove 70% of oldest messages + truncate tool outputs to 500 chars
|
|
329
491
|
*
|
|
330
492
|
* @returns true if recovery was successful (context was reduced)
|
|
331
493
|
*/
|
|
@@ -333,6 +495,9 @@ export class AgentRuntime {
|
|
|
333
495
|
// Calculate reduction percentage based on attempt
|
|
334
496
|
const reductionPercentages = [0.3, 0.5, 0.7];
|
|
335
497
|
const reductionPercent = reductionPercentages[attempt - 1] ?? 0.7;
|
|
498
|
+
// Increasingly aggressive tool output truncation limits
|
|
499
|
+
const toolOutputLimits = [5000, 2000, 500];
|
|
500
|
+
const toolOutputLimit = toolOutputLimits[attempt - 1] ?? 500;
|
|
336
501
|
// Notify UI about recovery attempt
|
|
337
502
|
const message = `Context overflow detected. Auto-squishing context (attempt ${attempt}/${MAX_CONTEXT_RECOVERY_ATTEMPTS}, removing ${Math.round(reductionPercent * 100)}% of history)...`;
|
|
338
503
|
this.callbacks.onContextRecovery?.(attempt, MAX_CONTEXT_RECOVERY_ATTEMPTS, message);
|
|
@@ -433,6 +598,39 @@ export class AgentRuntime {
|
|
|
433
598
|
// Flatten valid turns back to messages
|
|
434
599
|
const keepMessages = validTurns.flat();
|
|
435
600
|
const actualRemoveCount = conversationMessages.length - keepMessages.length;
|
|
601
|
+
// Aggressively truncate tool outputs in remaining messages
|
|
602
|
+
let truncatedCount = 0;
|
|
603
|
+
for (const msg of keepMessages) {
|
|
604
|
+
if (msg.role === 'tool' && msg.content) {
|
|
605
|
+
const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
|
|
606
|
+
if (content.length > toolOutputLimit) {
|
|
607
|
+
// Truncate with smart ending
|
|
608
|
+
const truncated = content.slice(0, toolOutputLimit);
|
|
609
|
+
const lastNewline = truncated.lastIndexOf('\n');
|
|
610
|
+
const cutPoint = lastNewline > toolOutputLimit * 0.7 ? lastNewline : toolOutputLimit;
|
|
611
|
+
msg.content = truncated.slice(0, cutPoint) + `\n\n[... truncated ${content.length - cutPoint} chars for context recovery ...]`;
|
|
612
|
+
truncatedCount++;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// Also truncate very long assistant messages
|
|
616
|
+
if (msg.role === 'assistant' && msg.content && msg.content.length > toolOutputLimit * 2) {
|
|
617
|
+
const content = msg.content;
|
|
618
|
+
const limit = toolOutputLimit * 2;
|
|
619
|
+
const truncated = content.slice(0, limit);
|
|
620
|
+
const lastNewline = truncated.lastIndexOf('\n');
|
|
621
|
+
const cutPoint = lastNewline > limit * 0.8 ? lastNewline : limit;
|
|
622
|
+
msg.content = truncated.slice(0, cutPoint) + `\n\n[... truncated for context recovery ...]`;
|
|
623
|
+
truncatedCount++;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
// Also truncate system messages if they're huge (except first system prompt)
|
|
627
|
+
for (let i = 1; i < systemMessages.length; i++) {
|
|
628
|
+
const sys = systemMessages[i];
|
|
629
|
+
if (sys && sys.content && sys.content.length > toolOutputLimit) {
|
|
630
|
+
sys.content = sys.content.slice(0, toolOutputLimit) + '\n[... truncated ...]';
|
|
631
|
+
truncatedCount++;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
436
634
|
// Rebuild message array
|
|
437
635
|
this.messages.length = 0;
|
|
438
636
|
// Add system messages
|
|
@@ -442,7 +640,7 @@ export class AgentRuntime {
|
|
|
442
640
|
// Add summary notice
|
|
443
641
|
this.messages.push({
|
|
444
642
|
role: 'system',
|
|
445
|
-
content: `[Auto Context Recovery] Removed ${actualRemoveCount}
|
|
643
|
+
content: `[Auto Context Recovery] Removed ${actualRemoveCount} messages and truncated ${truncatedCount} large outputs to stay within token limits.`,
|
|
446
644
|
});
|
|
447
645
|
// Add remaining conversation (maintaining tool call/result pairing)
|
|
448
646
|
for (const msg of keepMessages) {
|
|
@@ -456,7 +654,24 @@ export class AgentRuntime {
|
|
|
456
654
|
attempt,
|
|
457
655
|
removedPercent: reductionPercent * 100,
|
|
458
656
|
turnsRemoved: targetTurnsToRemove + startIndex,
|
|
657
|
+
truncatedOutputs: truncatedCount,
|
|
658
|
+
toolOutputLimit,
|
|
459
659
|
});
|
|
660
|
+
// Check if we're still over limit after all reductions
|
|
661
|
+
const newStats = this.contextManager?.getStats(this.messages);
|
|
662
|
+
if (newStats && newStats.percentage > 100) {
|
|
663
|
+
// Still over limit - do one more aggressive pass
|
|
664
|
+
// Truncate ALL tool outputs to absolute minimum
|
|
665
|
+
const minLimit = 200;
|
|
666
|
+
for (const msg of this.messages) {
|
|
667
|
+
if (msg.role === 'tool' && msg.content) {
|
|
668
|
+
const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
|
|
669
|
+
if (content.length > minLimit) {
|
|
670
|
+
msg.content = content.slice(0, minLimit) + '\n[... severely truncated ...]';
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
460
675
|
return true;
|
|
461
676
|
}
|
|
462
677
|
}
|