attocode 0.2.0 → 0.2.2
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 +111 -1
- package/README.md +7 -0
- package/dist/src/adapters.d.ts +6 -1
- package/dist/src/adapters.d.ts.map +1 -1
- package/dist/src/adapters.js +14 -1
- package/dist/src/adapters.js.map +1 -1
- package/dist/src/agent.d.ts +50 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +734 -316
- package/dist/src/agent.js.map +1 -1
- package/dist/src/defaults.d.ts +1 -1
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/defaults.js +2 -0
- package/dist/src/defaults.js.map +1 -1
- package/dist/src/integrations/agent-registry.d.ts +9 -2
- package/dist/src/integrations/agent-registry.d.ts.map +1 -1
- package/dist/src/integrations/agent-registry.js +30 -4
- package/dist/src/integrations/agent-registry.js.map +1 -1
- package/dist/src/integrations/async-subagent.d.ts +135 -0
- package/dist/src/integrations/async-subagent.d.ts.map +1 -0
- package/dist/src/integrations/async-subagent.js +213 -0
- package/dist/src/integrations/async-subagent.js.map +1 -0
- package/dist/src/integrations/auto-checkpoint.d.ts +98 -0
- package/dist/src/integrations/auto-checkpoint.d.ts.map +1 -0
- package/dist/src/integrations/auto-checkpoint.js +252 -0
- package/dist/src/integrations/auto-checkpoint.js.map +1 -0
- package/dist/src/integrations/budget-pool.d.ts +13 -1
- package/dist/src/integrations/budget-pool.d.ts.map +1 -1
- package/dist/src/integrations/budget-pool.js +17 -0
- package/dist/src/integrations/budget-pool.js.map +1 -1
- package/dist/src/integrations/complexity-classifier.d.ts +86 -0
- package/dist/src/integrations/complexity-classifier.d.ts.map +1 -0
- package/dist/src/integrations/complexity-classifier.js +233 -0
- package/dist/src/integrations/complexity-classifier.js.map +1 -0
- package/dist/src/integrations/delegation-protocol.d.ts +86 -0
- package/dist/src/integrations/delegation-protocol.d.ts.map +1 -0
- package/dist/src/integrations/delegation-protocol.js +127 -0
- package/dist/src/integrations/delegation-protocol.js.map +1 -0
- package/dist/src/integrations/dynamic-budget.d.ts +81 -0
- package/dist/src/integrations/dynamic-budget.d.ts.map +1 -0
- package/dist/src/integrations/dynamic-budget.js +151 -0
- package/dist/src/integrations/dynamic-budget.js.map +1 -0
- package/dist/src/integrations/economics.d.ts +44 -1
- package/dist/src/integrations/economics.d.ts.map +1 -1
- package/dist/src/integrations/economics.js +182 -3
- package/dist/src/integrations/economics.js.map +1 -1
- package/dist/src/integrations/environment-facts.d.ts +52 -0
- package/dist/src/integrations/environment-facts.d.ts.map +1 -0
- package/dist/src/integrations/environment-facts.js +84 -0
- package/dist/src/integrations/environment-facts.js.map +1 -0
- package/dist/src/integrations/index.d.ts +16 -1
- package/dist/src/integrations/index.d.ts.map +1 -1
- package/dist/src/integrations/index.js +31 -1
- package/dist/src/integrations/index.js.map +1 -1
- package/dist/src/integrations/injection-budget.d.ts +71 -0
- package/dist/src/integrations/injection-budget.d.ts.map +1 -0
- package/dist/src/integrations/injection-budget.js +136 -0
- package/dist/src/integrations/injection-budget.js.map +1 -0
- package/dist/src/integrations/mcp-client.d.ts.map +1 -1
- package/dist/src/integrations/mcp-client.js +14 -0
- package/dist/src/integrations/mcp-client.js.map +1 -1
- package/dist/src/integrations/mcp-custom-tools.d.ts +102 -0
- package/dist/src/integrations/mcp-custom-tools.d.ts.map +1 -0
- package/dist/src/integrations/mcp-custom-tools.js +232 -0
- package/dist/src/integrations/mcp-custom-tools.js.map +1 -0
- package/dist/src/integrations/mcp-tool-validator.d.ts +60 -0
- package/dist/src/integrations/mcp-tool-validator.d.ts.map +1 -0
- package/dist/src/integrations/mcp-tool-validator.js +141 -0
- package/dist/src/integrations/mcp-tool-validator.js.map +1 -0
- package/dist/src/integrations/routing.d.ts +2 -1
- package/dist/src/integrations/routing.d.ts.map +1 -1
- package/dist/src/integrations/routing.js.map +1 -1
- package/dist/src/integrations/self-improvement.d.ts +90 -0
- package/dist/src/integrations/self-improvement.d.ts.map +1 -0
- package/dist/src/integrations/self-improvement.js +217 -0
- package/dist/src/integrations/self-improvement.js.map +1 -0
- package/dist/src/integrations/smart-decomposer.d.ts +4 -0
- package/dist/src/integrations/smart-decomposer.d.ts.map +1 -1
- package/dist/src/integrations/smart-decomposer.js +55 -28
- package/dist/src/integrations/smart-decomposer.js.map +1 -1
- package/dist/src/integrations/subagent-output-store.d.ts +91 -0
- package/dist/src/integrations/subagent-output-store.d.ts.map +1 -0
- package/dist/src/integrations/subagent-output-store.js +257 -0
- package/dist/src/integrations/subagent-output-store.js.map +1 -0
- package/dist/src/integrations/swarm/index.d.ts +1 -1
- package/dist/src/integrations/swarm/index.d.ts.map +1 -1
- package/dist/src/integrations/swarm/index.js +1 -1
- package/dist/src/integrations/swarm/index.js.map +1 -1
- package/dist/src/integrations/swarm/model-selector.d.ts +1 -0
- package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
- package/dist/src/integrations/swarm/model-selector.js +37 -3
- package/dist/src/integrations/swarm/model-selector.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-config-loader.d.ts +10 -1
- package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-config-loader.js +72 -6
- package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-event-bridge.js +26 -4
- package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-events.d.ts +11 -0
- package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-events.js +4 -0
- package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +11 -0
- package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-orchestrator.js +233 -10
- package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-quality-gate.d.ts +9 -2
- package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-quality-gate.js +128 -11
- package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
- package/dist/src/integrations/swarm/task-queue.d.ts +11 -1
- package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
- package/dist/src/integrations/swarm/task-queue.js +125 -15
- package/dist/src/integrations/swarm/task-queue.js.map +1 -1
- package/dist/src/integrations/swarm/types.d.ts +40 -1
- package/dist/src/integrations/swarm/types.d.ts.map +1 -1
- package/dist/src/integrations/swarm/types.js +6 -1
- package/dist/src/integrations/swarm/types.js.map +1 -1
- package/dist/src/integrations/swarm/worker-pool.d.ts +9 -3
- package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
- package/dist/src/integrations/swarm/worker-pool.js +89 -17
- package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
- package/dist/src/integrations/thinking-strategy.d.ts +52 -0
- package/dist/src/integrations/thinking-strategy.d.ts.map +1 -0
- package/dist/src/integrations/thinking-strategy.js +129 -0
- package/dist/src/integrations/thinking-strategy.js.map +1 -0
- package/dist/src/integrations/tool-recommendation.d.ts +58 -0
- package/dist/src/integrations/tool-recommendation.d.ts.map +1 -0
- package/dist/src/integrations/tool-recommendation.js +215 -0
- package/dist/src/integrations/tool-recommendation.js.map +1 -0
- package/dist/src/integrations/verification-gate.d.ts +80 -0
- package/dist/src/integrations/verification-gate.d.ts.map +1 -0
- package/dist/src/integrations/verification-gate.js +146 -0
- package/dist/src/integrations/verification-gate.js.map +1 -0
- package/dist/src/integrations/work-log.d.ts +87 -0
- package/dist/src/integrations/work-log.d.ts.map +1 -0
- package/dist/src/integrations/work-log.js +275 -0
- package/dist/src/integrations/work-log.js.map +1 -0
- package/dist/src/main.js +5 -4
- package/dist/src/main.js.map +1 -1
- package/dist/src/modes.d.ts +6 -0
- package/dist/src/modes.d.ts.map +1 -1
- package/dist/src/modes.js +73 -2
- package/dist/src/modes.js.map +1 -1
- package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
- package/dist/src/providers/adapters/anthropic.js +20 -3
- package/dist/src/providers/adapters/anthropic.js.map +1 -1
- package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
- package/dist/src/providers/adapters/openrouter.js +3 -1
- package/dist/src/providers/adapters/openrouter.js.map +1 -1
- package/dist/src/providers/types.d.ts +4 -0
- package/dist/src/providers/types.d.ts.map +1 -1
- package/dist/src/providers/types.js.map +1 -1
- package/dist/src/tools/bash.d.ts +8 -2
- package/dist/src/tools/bash.d.ts.map +1 -1
- package/dist/src/tools/bash.js +14 -1
- package/dist/src/tools/bash.js.map +1 -1
- package/dist/src/tools/coercion.d.ts +14 -0
- package/dist/src/tools/coercion.d.ts.map +1 -0
- package/dist/src/tools/coercion.js +25 -0
- package/dist/src/tools/coercion.js.map +1 -0
- package/dist/src/tools/file.d.ts +2 -2
- package/dist/src/tools/file.d.ts.map +1 -1
- package/dist/src/tools/file.js +2 -1
- package/dist/src/tools/file.js.map +1 -1
- package/dist/src/tools/standard.d.ts +17 -1
- package/dist/src/tools/standard.d.ts.map +1 -1
- package/dist/src/tools/standard.js +64 -11
- package/dist/src/tools/standard.js.map +1 -1
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +8 -1
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/event-display.d.ts.map +1 -1
- package/dist/src/tui/event-display.js +8 -1
- package/dist/src/tui/event-display.js.map +1 -1
- package/dist/src/types.d.ts +26 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Budget Rebalancing
|
|
3
|
+
*
|
|
4
|
+
* Extends SharedBudgetPool with dynamic rebalancing that prevents
|
|
5
|
+
* starvation when spawning subagents sequentially.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - setExpectedChildren(count) for upfront capacity planning
|
|
9
|
+
* - Sequential spawn cap: never take >60% of remaining budget
|
|
10
|
+
* - Rebalance on child completion (return unused budget to pool)
|
|
11
|
+
* - Priority-based allocation (critical children get more)
|
|
12
|
+
*/
|
|
13
|
+
import { SharedBudgetPool } from './budget-pool.js';
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// CONSTANTS
|
|
16
|
+
// =============================================================================
|
|
17
|
+
const PRIORITY_MULTIPLIERS = {
|
|
18
|
+
low: 0.5,
|
|
19
|
+
normal: 1.0,
|
|
20
|
+
high: 1.5,
|
|
21
|
+
critical: 2.0,
|
|
22
|
+
};
|
|
23
|
+
const DEFAULT_DYNAMIC_CONFIG = {
|
|
24
|
+
maxRemainingRatio: 0.6,
|
|
25
|
+
minPerExpectedChild: 10000,
|
|
26
|
+
autoRebalance: true,
|
|
27
|
+
};
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// DYNAMIC BUDGET POOL
|
|
30
|
+
// =============================================================================
|
|
31
|
+
export class DynamicBudgetPool extends SharedBudgetPool {
|
|
32
|
+
dynamicConfig;
|
|
33
|
+
expectedChildren = 0;
|
|
34
|
+
spawnedCount = 0;
|
|
35
|
+
completedCount = 0;
|
|
36
|
+
childPriorities = new Map();
|
|
37
|
+
constructor(config) {
|
|
38
|
+
super(config);
|
|
39
|
+
this.dynamicConfig = {
|
|
40
|
+
...config,
|
|
41
|
+
maxRemainingRatio: config.maxRemainingRatio ?? DEFAULT_DYNAMIC_CONFIG.maxRemainingRatio,
|
|
42
|
+
minPerExpectedChild: config.minPerExpectedChild ?? DEFAULT_DYNAMIC_CONFIG.minPerExpectedChild,
|
|
43
|
+
autoRebalance: config.autoRebalance ?? DEFAULT_DYNAMIC_CONFIG.autoRebalance,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Set the expected number of children for capacity planning.
|
|
48
|
+
* This adjusts maxPerChild to ensure fair distribution.
|
|
49
|
+
*/
|
|
50
|
+
setExpectedChildren(count) {
|
|
51
|
+
this.expectedChildren = count;
|
|
52
|
+
this.updateMaxPerChild();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Set priority for a child agent.
|
|
56
|
+
*/
|
|
57
|
+
setChildPriority(priority) {
|
|
58
|
+
this.childPriorities.set(priority.childId, priority);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reserve with dynamic capacity planning.
|
|
62
|
+
* Respects expected children and remaining ratio cap.
|
|
63
|
+
*/
|
|
64
|
+
reserveDynamic(childId, priority) {
|
|
65
|
+
// Set priority if provided
|
|
66
|
+
if (priority) {
|
|
67
|
+
this.setChildPriority({ childId, priority });
|
|
68
|
+
}
|
|
69
|
+
// Calculate dynamic max for this child
|
|
70
|
+
const stats = this.getStats();
|
|
71
|
+
const remaining = stats.tokensRemaining;
|
|
72
|
+
if (remaining <= 0)
|
|
73
|
+
return null;
|
|
74
|
+
// Cap at maxRemainingRatio of remaining budget
|
|
75
|
+
const ratioCap = Math.floor(remaining * this.dynamicConfig.maxRemainingRatio);
|
|
76
|
+
// Reserve for expected future children
|
|
77
|
+
const unreservedChildren = Math.max(0, this.expectedChildren - this.spawnedCount - 1);
|
|
78
|
+
const reserveForFuture = unreservedChildren * this.dynamicConfig.minPerExpectedChild;
|
|
79
|
+
const afterReserve = Math.max(0, remaining - reserveForFuture);
|
|
80
|
+
// Apply priority multiplier
|
|
81
|
+
const priorityLevel = this.childPriorities.get(childId)?.priority ?? 'normal';
|
|
82
|
+
const multiplier = PRIORITY_MULTIPLIERS[priorityLevel] ?? 1.0;
|
|
83
|
+
const priorityAdjusted = Math.floor(afterReserve * multiplier / Math.max(1, unreservedChildren + 1));
|
|
84
|
+
// Final allocation: min of all caps
|
|
85
|
+
const dynamicMax = Math.min(ratioCap, afterReserve, Math.max(priorityAdjusted, this.dynamicConfig.minPerExpectedChild));
|
|
86
|
+
// Temporarily set max per child for this reservation
|
|
87
|
+
this.setMaxPerChild(dynamicMax);
|
|
88
|
+
const allocation = this.reserve(childId);
|
|
89
|
+
this.resetMaxPerChild();
|
|
90
|
+
if (allocation) {
|
|
91
|
+
this.spawnedCount++;
|
|
92
|
+
}
|
|
93
|
+
return allocation;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Release with optional auto-rebalancing.
|
|
97
|
+
*/
|
|
98
|
+
releaseDynamic(childId) {
|
|
99
|
+
this.release(childId);
|
|
100
|
+
this.completedCount++;
|
|
101
|
+
this.childPriorities.delete(childId);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get enhanced stats including dynamic info.
|
|
105
|
+
*/
|
|
106
|
+
getDynamicStats() {
|
|
107
|
+
const base = this.getStats();
|
|
108
|
+
const pending = this.spawnedCount - this.completedCount;
|
|
109
|
+
return {
|
|
110
|
+
...base,
|
|
111
|
+
expectedChildren: this.expectedChildren,
|
|
112
|
+
spawnedCount: this.spawnedCount,
|
|
113
|
+
completedCount: this.completedCount,
|
|
114
|
+
pendingCount: pending,
|
|
115
|
+
avgPerChild: this.spawnedCount > 0
|
|
116
|
+
? Math.floor(base.tokensUsed / this.spawnedCount)
|
|
117
|
+
: 0,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// ===========================================================================
|
|
121
|
+
// INTERNAL
|
|
122
|
+
// ===========================================================================
|
|
123
|
+
updateMaxPerChild() {
|
|
124
|
+
if (this.expectedChildren <= 0)
|
|
125
|
+
return;
|
|
126
|
+
const stats = this.getStats();
|
|
127
|
+
const remaining = stats.tokensRemaining;
|
|
128
|
+
const unreserved = Math.max(1, this.expectedChildren - this.spawnedCount);
|
|
129
|
+
// Fair share: remaining / unreserved children, capped by ratio
|
|
130
|
+
const fairShare = Math.floor(remaining / unreserved);
|
|
131
|
+
const ratioCap = Math.floor(remaining * this.dynamicConfig.maxRemainingRatio);
|
|
132
|
+
this.setMaxPerChild(Math.min(fairShare, ratioCap));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create a dynamic budget pool from a parent's budget.
|
|
137
|
+
*/
|
|
138
|
+
export function createDynamicBudgetPool(parentBudgetTokens, parentReserveRatio = 0.25, config) {
|
|
139
|
+
const parentReserve = Math.floor(parentBudgetTokens * parentReserveRatio);
|
|
140
|
+
const poolTokens = parentBudgetTokens - parentReserve;
|
|
141
|
+
return new DynamicBudgetPool({
|
|
142
|
+
totalTokens: poolTokens,
|
|
143
|
+
maxPerChild: Math.min(config?.maxPerChild ?? 100000, poolTokens),
|
|
144
|
+
totalCost: 0.50,
|
|
145
|
+
maxCostPerChild: 0.25,
|
|
146
|
+
maxRemainingRatio: config?.maxRemainingRatio ?? 0.6,
|
|
147
|
+
minPerExpectedChild: config?.minPerExpectedChild ?? 10000,
|
|
148
|
+
autoRebalance: config?.autoRebalance ?? true,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=dynamic-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-budget.js","sourceRoot":"","sources":["../../../src/integrations/dynamic-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,6 +62,8 @@ export interface LoopDetectionState {
|
|
|
62
62
|
consecutiveCount: number;
|
|
63
63
|
/** Threshold for doom loop detection (default: 3) */
|
|
64
64
|
threshold: number;
|
|
65
|
+
/** Threshold for fuzzy doom loop detection (default: threshold + 1) */
|
|
66
|
+
fuzzyThreshold: number;
|
|
65
67
|
/** Timestamp of last doom loop warning */
|
|
66
68
|
lastWarningTime: number;
|
|
67
69
|
}
|
|
@@ -87,6 +89,24 @@ export interface PhaseState {
|
|
|
87
89
|
iterationsInPhase: number;
|
|
88
90
|
/** Files read in recent iterations (for diminishing returns) */
|
|
89
91
|
recentNewFiles: number;
|
|
92
|
+
/** Whether the last test passed */
|
|
93
|
+
lastTestPassed: boolean | null;
|
|
94
|
+
/** Consecutive test failures count */
|
|
95
|
+
consecutiveTestFailures: number;
|
|
96
|
+
/** Whether agent is in a test-fix cycle */
|
|
97
|
+
inTestFixCycle: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Phase-aware budget allocation config.
|
|
101
|
+
* Prevents spending too long in exploration and reserves time for verification.
|
|
102
|
+
*/
|
|
103
|
+
export interface PhaseBudgetConfig {
|
|
104
|
+
/** Max percent of iterations for exploration (default: 30%) */
|
|
105
|
+
maxExplorationPercent: number;
|
|
106
|
+
/** Percent of iterations reserved for verification (default: 20%) */
|
|
107
|
+
reservedVerificationPercent: number;
|
|
108
|
+
/** Whether phase budget enforcement is enabled */
|
|
109
|
+
enabled: boolean;
|
|
90
110
|
}
|
|
91
111
|
/**
|
|
92
112
|
* Budget check result.
|
|
@@ -163,6 +183,13 @@ export type EconomicsEventListener = (event: EconomicsEvent) => void;
|
|
|
163
183
|
* Forces a structured JSON summary so the parent agent can make intelligent follow-up decisions.
|
|
164
184
|
*/
|
|
165
185
|
export declare const TIMEOUT_WRAPUP_PROMPT = "[System] You are about to be stopped due to timeout. You MUST respond with a structured summary NOW.\n\nRespond with ONLY this JSON (no tool calls):\n{\n \"findings\": [\"what you discovered or accomplished\"],\n \"actionsTaken\": [\"files read, modifications made, commands run\"],\n \"failures\": [\"what failed or was blocked\"],\n \"remainingWork\": [\"what you didn't finish\"],\n \"suggestedNextSteps\": [\"what the parent agent should do next\"]\n}";
|
|
186
|
+
/**
|
|
187
|
+
* Compute a structural fingerprint for a tool call.
|
|
188
|
+
* Extracts only the primary argument (path, command, pattern, query) and ignores
|
|
189
|
+
* secondary arguments (encoding, timeout, flags). This catches near-identical calls
|
|
190
|
+
* that differ only in optional parameters.
|
|
191
|
+
*/
|
|
192
|
+
export declare function computeToolFingerprint(toolName: string, argsStr: string): string;
|
|
166
193
|
/**
|
|
167
194
|
* ExecutionEconomicsManager handles budget tracking and progress detection.
|
|
168
195
|
*/
|
|
@@ -172,6 +199,7 @@ export declare class ExecutionEconomicsManager {
|
|
|
172
199
|
private progress;
|
|
173
200
|
private loopState;
|
|
174
201
|
private phaseState;
|
|
202
|
+
private phaseBudget;
|
|
175
203
|
private startTime;
|
|
176
204
|
private pausedDuration;
|
|
177
205
|
private pauseStart;
|
|
@@ -192,6 +220,11 @@ export declare class ExecutionEconomicsManager {
|
|
|
192
220
|
* Get the effective duration accounting for paused time.
|
|
193
221
|
*/
|
|
194
222
|
private getEffectiveDuration;
|
|
223
|
+
/**
|
|
224
|
+
* Configure phase-aware budget allocation.
|
|
225
|
+
* Only active when enabled=true (eval mode). TUI mode leaves it off.
|
|
226
|
+
*/
|
|
227
|
+
setPhaseBudget(config: PhaseBudgetConfig): void;
|
|
195
228
|
/**
|
|
196
229
|
* Set the extension request handler.
|
|
197
230
|
*/
|
|
@@ -210,7 +243,9 @@ export declare class ExecutionEconomicsManager {
|
|
|
210
243
|
recordToolCall(toolName: string, args: Record<string, unknown>, _result?: unknown): void;
|
|
211
244
|
/**
|
|
212
245
|
* Update doom loop detection state.
|
|
213
|
-
*
|
|
246
|
+
* Uses two-tier detection:
|
|
247
|
+
* 1. Exact match: same tool+args string (threshold: 3)
|
|
248
|
+
* 2. Fuzzy match: same tool + same primary args, ignoring optional params (threshold: 4)
|
|
214
249
|
*/
|
|
215
250
|
private updateDoomLoopState;
|
|
216
251
|
/**
|
|
@@ -283,6 +318,9 @@ export declare class ExecutionEconomicsManager {
|
|
|
283
318
|
testsRun: number;
|
|
284
319
|
shouldTransition: boolean;
|
|
285
320
|
iterationsInPhase: number;
|
|
321
|
+
lastTestPassed: boolean | null;
|
|
322
|
+
consecutiveTestFailures: number;
|
|
323
|
+
inTestFixCycle: boolean;
|
|
286
324
|
};
|
|
287
325
|
/**
|
|
288
326
|
* Subscribe to events.
|
|
@@ -293,6 +331,11 @@ export declare class ExecutionEconomicsManager {
|
|
|
293
331
|
*/
|
|
294
332
|
reset(): void;
|
|
295
333
|
private emit;
|
|
334
|
+
/**
|
|
335
|
+
* Parse test outcome from bash command output.
|
|
336
|
+
* Updates phaseState test tracking fields.
|
|
337
|
+
*/
|
|
338
|
+
private parseTestOutcome;
|
|
296
339
|
private isStuck;
|
|
297
340
|
}
|
|
298
341
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"economics.d.ts","sourceRoot":"","sources":["../../../src/integrations/economics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH;;GAEG;AACH,MAAM,WAAW,eAAe;IAE9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IAGpB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAG1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;IACzD,yCAAyC;IACzC,yBAAyB,EAAE,MAAM,CAAC;IAClC,2CAA2C;IAC3C,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,sCAAsC;IACtC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,oCAAoC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,gBAAgB,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"economics.d.ts","sourceRoot":"","sources":["../../../src/integrations/economics.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,55 @@ const EXPLORATION_NUDGE_PROMPT = (filesRead, iterations) => `[System] You've rea
|
|
|
51
51
|
- Make the code changes now
|
|
52
52
|
- Run tests to verify
|
|
53
53
|
If you're still gathering context, briefly explain what you're looking for.`;
|
|
54
|
+
/**
|
|
55
|
+
* Test-fix rethink prompt - injected after consecutive test failures.
|
|
56
|
+
*/
|
|
57
|
+
const TEST_FIX_RETHINK_PROMPT = (failures) => `[System] You've had ${failures} consecutive test failures. Step back and rethink:
|
|
58
|
+
1. Re-read the error messages carefully
|
|
59
|
+
2. Consider whether your approach is fundamentally wrong
|
|
60
|
+
3. Try a DIFFERENT fix strategy instead of iterating on the same one
|
|
61
|
+
Do not retry the same fix. Try a new approach.`;
|
|
62
|
+
/**
|
|
63
|
+
* Phase budget exploration exceeded prompt.
|
|
64
|
+
*/
|
|
65
|
+
const EXPLORATION_BUDGET_EXCEEDED_PROMPT = (pct) => `[System] You've spent ${pct}% of your iterations in exploration. Start making edits NOW.
|
|
66
|
+
Do not read more files. Use what you know to make the fix.`;
|
|
67
|
+
/**
|
|
68
|
+
* Phase budget verification reserve prompt.
|
|
69
|
+
*/
|
|
70
|
+
const VERIFICATION_RESERVE_PROMPT = `[System] You are running low on iterations. Run your tests NOW to verify your changes.
|
|
71
|
+
Do not make more edits until you've confirmed whether the current fix works.`;
|
|
72
|
+
/**
|
|
73
|
+
* Primary argument keys that identify the *target* of a tool call.
|
|
74
|
+
* Used for fuzzy doom loop detection — ignoring secondary/optional args.
|
|
75
|
+
*/
|
|
76
|
+
const PRIMARY_KEYS = ['path', 'file_path', 'command', 'pattern', 'query', 'url', 'content', 'filename'];
|
|
77
|
+
/**
|
|
78
|
+
* Compute a structural fingerprint for a tool call.
|
|
79
|
+
* Extracts only the primary argument (path, command, pattern, query) and ignores
|
|
80
|
+
* secondary arguments (encoding, timeout, flags). This catches near-identical calls
|
|
81
|
+
* that differ only in optional parameters.
|
|
82
|
+
*/
|
|
83
|
+
export function computeToolFingerprint(toolName, argsStr) {
|
|
84
|
+
try {
|
|
85
|
+
const args = JSON.parse(argsStr || '{}');
|
|
86
|
+
const primaryArgs = {};
|
|
87
|
+
for (const key of PRIMARY_KEYS) {
|
|
88
|
+
if (key in args) {
|
|
89
|
+
primaryArgs[key] = args[key];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// If no primary keys found, fall back to full args
|
|
93
|
+
if (Object.keys(primaryArgs).length === 0) {
|
|
94
|
+
return `${toolName}:${stableStringify(args)}`;
|
|
95
|
+
}
|
|
96
|
+
return `${toolName}:${stableStringify(primaryArgs)}`;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// If args can't be parsed, use raw string
|
|
100
|
+
return `${toolName}:${argsStr}`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
54
103
|
/**
|
|
55
104
|
* ExecutionEconomicsManager handles budget tracking and progress detection.
|
|
56
105
|
*/
|
|
@@ -60,6 +109,7 @@ export class ExecutionEconomicsManager {
|
|
|
60
109
|
progress;
|
|
61
110
|
loopState;
|
|
62
111
|
phaseState;
|
|
112
|
+
phaseBudget = null;
|
|
63
113
|
startTime;
|
|
64
114
|
pausedDuration = 0;
|
|
65
115
|
pauseStart = null;
|
|
@@ -103,6 +153,7 @@ export class ExecutionEconomicsManager {
|
|
|
103
153
|
lastTool: null,
|
|
104
154
|
consecutiveCount: 0,
|
|
105
155
|
threshold: 3,
|
|
156
|
+
fuzzyThreshold: 4,
|
|
106
157
|
lastWarningTime: 0,
|
|
107
158
|
};
|
|
108
159
|
// Initialize phase tracking state
|
|
@@ -116,6 +167,9 @@ export class ExecutionEconomicsManager {
|
|
|
116
167
|
shouldTransition: false,
|
|
117
168
|
iterationsInPhase: 0,
|
|
118
169
|
recentNewFiles: 0,
|
|
170
|
+
lastTestPassed: null,
|
|
171
|
+
consecutiveTestFailures: 0,
|
|
172
|
+
inTestFixCycle: false,
|
|
119
173
|
};
|
|
120
174
|
this.startTime = Date.now();
|
|
121
175
|
}
|
|
@@ -145,6 +199,13 @@ export class ExecutionEconomicsManager {
|
|
|
145
199
|
const currentPaused = this.pauseStart !== null ? Date.now() - this.pauseStart : 0;
|
|
146
200
|
return Date.now() - this.startTime - this.pausedDuration - currentPaused;
|
|
147
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Configure phase-aware budget allocation.
|
|
204
|
+
* Only active when enabled=true (eval mode). TUI mode leaves it off.
|
|
205
|
+
*/
|
|
206
|
+
setPhaseBudget(config) {
|
|
207
|
+
this.phaseBudget = config;
|
|
208
|
+
}
|
|
148
209
|
/**
|
|
149
210
|
* Set the extension request handler.
|
|
150
211
|
*/
|
|
@@ -232,13 +293,18 @@ export class ExecutionEconomicsManager {
|
|
|
232
293
|
this.progress.commandsRun.push(command);
|
|
233
294
|
this.progress.lastMeaningfulProgress = now;
|
|
234
295
|
this.progress.stuckCount = 0;
|
|
235
|
-
// Detect test runs
|
|
296
|
+
// Detect test runs and track outcomes
|
|
236
297
|
if (command.includes('test') || command.includes('pytest') || command.includes('npm test') || command.includes('jest')) {
|
|
237
298
|
this.phaseState.testsRun++;
|
|
238
299
|
// Transition to verifying phase when tests are run after edits
|
|
239
300
|
if (this.phaseState.phase === 'acting' && this.phaseState.filesModified.size > 0) {
|
|
240
301
|
this.transitionPhase('verifying', 'Tests run after edits');
|
|
241
302
|
}
|
|
303
|
+
// Track test pass/fail from result if available
|
|
304
|
+
if (_result !== undefined) {
|
|
305
|
+
const resultStr = typeof _result === 'string' ? _result : '';
|
|
306
|
+
this.parseTestOutcome(command, resultStr);
|
|
307
|
+
}
|
|
242
308
|
}
|
|
243
309
|
}
|
|
244
310
|
// Update exploration saturation check
|
|
@@ -258,12 +324,14 @@ export class ExecutionEconomicsManager {
|
|
|
258
324
|
}
|
|
259
325
|
/**
|
|
260
326
|
* Update doom loop detection state.
|
|
261
|
-
*
|
|
327
|
+
* Uses two-tier detection:
|
|
328
|
+
* 1. Exact match: same tool+args string (threshold: 3)
|
|
329
|
+
* 2. Fuzzy match: same tool + same primary args, ignoring optional params (threshold: 4)
|
|
262
330
|
*/
|
|
263
331
|
updateDoomLoopState(toolName, argsStr) {
|
|
264
332
|
const currentCall = `${toolName}:${argsStr}`;
|
|
265
333
|
const recentCalls = this.progress.recentToolCalls;
|
|
266
|
-
// Count consecutive identical calls from the end
|
|
334
|
+
// === EXACT MATCH: Count consecutive identical calls from the end ===
|
|
267
335
|
let consecutiveCount = 0;
|
|
268
336
|
for (let i = recentCalls.length - 1; i >= 0; i--) {
|
|
269
337
|
const call = recentCalls[i];
|
|
@@ -274,6 +342,26 @@ export class ExecutionEconomicsManager {
|
|
|
274
342
|
break;
|
|
275
343
|
}
|
|
276
344
|
}
|
|
345
|
+
// === FUZZY MATCH: Catches near-identical calls that differ only in optional params ===
|
|
346
|
+
// Only check if exact match didn't already trigger
|
|
347
|
+
if (consecutiveCount < this.loopState.threshold) {
|
|
348
|
+
const currentFingerprint = computeToolFingerprint(toolName, argsStr);
|
|
349
|
+
let fuzzyCount = 0;
|
|
350
|
+
for (let i = recentCalls.length - 1; i >= 0; i--) {
|
|
351
|
+
const call = recentCalls[i];
|
|
352
|
+
const callFingerprint = computeToolFingerprint(call.tool, call.args);
|
|
353
|
+
if (callFingerprint === currentFingerprint) {
|
|
354
|
+
fuzzyCount++;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Use fuzzy count if it exceeds the fuzzy threshold
|
|
361
|
+
if (fuzzyCount >= this.loopState.fuzzyThreshold) {
|
|
362
|
+
consecutiveCount = Math.max(consecutiveCount, fuzzyCount);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
277
365
|
this.loopState.consecutiveCount = consecutiveCount;
|
|
278
366
|
this.loopState.lastTool = toolName;
|
|
279
367
|
// Detect doom loop when threshold reached
|
|
@@ -436,6 +524,60 @@ export class ExecutionEconomicsManager {
|
|
|
436
524
|
injectedPrompt: EXPLORATION_NUDGE_PROMPT(this.phaseState.uniqueFilesRead.size, this.phaseState.iterationsInPhase),
|
|
437
525
|
};
|
|
438
526
|
}
|
|
527
|
+
// =========================================================================
|
|
528
|
+
// TEST-FIX CYCLE - Nudge to rethink after 3+ consecutive failures
|
|
529
|
+
// =========================================================================
|
|
530
|
+
if (this.phaseState.consecutiveTestFailures >= 3) {
|
|
531
|
+
return {
|
|
532
|
+
canContinue: true,
|
|
533
|
+
reason: `${this.phaseState.consecutiveTestFailures} consecutive test failures`,
|
|
534
|
+
budgetType: 'iterations',
|
|
535
|
+
isHardLimit: false,
|
|
536
|
+
isSoftLimit: true,
|
|
537
|
+
percentUsed: (this.usage.iterations / this.budget.targetIterations) * 100,
|
|
538
|
+
suggestedAction: 'warn',
|
|
539
|
+
injectedPrompt: TEST_FIX_RETHINK_PROMPT(this.phaseState.consecutiveTestFailures),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
// =========================================================================
|
|
543
|
+
// PHASE-AWARE BUDGET ALLOCATION (opt-in, used in eval mode)
|
|
544
|
+
// =========================================================================
|
|
545
|
+
if (this.phaseBudget?.enabled) {
|
|
546
|
+
const iterPct = (this.usage.iterations / this.budget.maxIterations) * 100;
|
|
547
|
+
const explorationPct = this.phaseState.phase === 'exploring'
|
|
548
|
+
? (this.phaseState.iterationsInPhase / this.budget.maxIterations) * 100
|
|
549
|
+
: 0;
|
|
550
|
+
// Too much time in exploration
|
|
551
|
+
if (explorationPct > this.phaseBudget.maxExplorationPercent && this.phaseState.filesModified.size === 0) {
|
|
552
|
+
return {
|
|
553
|
+
canContinue: true,
|
|
554
|
+
reason: `Exploration exceeds ${this.phaseBudget.maxExplorationPercent}% of budget`,
|
|
555
|
+
budgetType: 'iterations',
|
|
556
|
+
isHardLimit: false,
|
|
557
|
+
isSoftLimit: true,
|
|
558
|
+
percentUsed: iterPct,
|
|
559
|
+
suggestedAction: 'warn',
|
|
560
|
+
injectedPrompt: EXPLORATION_BUDGET_EXCEEDED_PROMPT(Math.round(explorationPct)),
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
// Only verification-reserve iterations remain
|
|
564
|
+
const remainingPct = 100 - iterPct;
|
|
565
|
+
if (remainingPct <= this.phaseBudget.reservedVerificationPercent
|
|
566
|
+
&& this.phaseState.phase !== 'verifying'
|
|
567
|
+
&& this.phaseState.filesModified.size > 0
|
|
568
|
+
&& this.phaseState.testsRun === 0) {
|
|
569
|
+
return {
|
|
570
|
+
canContinue: true,
|
|
571
|
+
reason: `Only ${Math.round(remainingPct)}% budget remaining, verification needed`,
|
|
572
|
+
budgetType: 'iterations',
|
|
573
|
+
isHardLimit: false,
|
|
574
|
+
isSoftLimit: true,
|
|
575
|
+
percentUsed: iterPct,
|
|
576
|
+
suggestedAction: 'warn',
|
|
577
|
+
injectedPrompt: VERIFICATION_RESERVE_PROMPT,
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
}
|
|
439
581
|
// Check soft limits (warnings)
|
|
440
582
|
// Two-tier approach: 67-79% = warning, 80%+ = forceTextOnly to prevent overshoot
|
|
441
583
|
if (this.usage.tokens >= this.budget.softTokenLimit) {
|
|
@@ -631,6 +773,9 @@ export class ExecutionEconomicsManager {
|
|
|
631
773
|
testsRun: this.phaseState.testsRun,
|
|
632
774
|
shouldTransition: this.phaseState.shouldTransition,
|
|
633
775
|
iterationsInPhase: this.phaseState.iterationsInPhase,
|
|
776
|
+
lastTestPassed: this.phaseState.lastTestPassed,
|
|
777
|
+
consecutiveTestFailures: this.phaseState.consecutiveTestFailures,
|
|
778
|
+
inTestFixCycle: this.phaseState.inTestFixCycle,
|
|
634
779
|
};
|
|
635
780
|
}
|
|
636
781
|
/**
|
|
@@ -672,6 +817,7 @@ export class ExecutionEconomicsManager {
|
|
|
672
817
|
lastTool: null,
|
|
673
818
|
consecutiveCount: 0,
|
|
674
819
|
threshold: 3,
|
|
820
|
+
fuzzyThreshold: 4,
|
|
675
821
|
lastWarningTime: 0,
|
|
676
822
|
};
|
|
677
823
|
// Reset phase tracking state
|
|
@@ -685,6 +831,9 @@ export class ExecutionEconomicsManager {
|
|
|
685
831
|
shouldTransition: false,
|
|
686
832
|
iterationsInPhase: 0,
|
|
687
833
|
recentNewFiles: 0,
|
|
834
|
+
lastTestPassed: null,
|
|
835
|
+
consecutiveTestFailures: 0,
|
|
836
|
+
inTestFixCycle: false,
|
|
688
837
|
};
|
|
689
838
|
this.startTime = Date.now();
|
|
690
839
|
this.pausedDuration = 0;
|
|
@@ -703,6 +852,36 @@ export class ExecutionEconomicsManager {
|
|
|
703
852
|
}
|
|
704
853
|
}
|
|
705
854
|
}
|
|
855
|
+
/**
|
|
856
|
+
* Parse test outcome from bash command output.
|
|
857
|
+
* Updates phaseState test tracking fields.
|
|
858
|
+
*/
|
|
859
|
+
parseTestOutcome(_command, output) {
|
|
860
|
+
if (!output)
|
|
861
|
+
return;
|
|
862
|
+
// Detect pass/fail from pytest-style output
|
|
863
|
+
const hasPassed = /(\d+)\s+passed/.test(output) || output.includes('PASSED');
|
|
864
|
+
const hasFailed = /(\d+)\s+failed/.test(output) || output.includes('FAILED') || output.includes('ERROR');
|
|
865
|
+
if (hasFailed && !hasPassed) {
|
|
866
|
+
// Pure failure
|
|
867
|
+
this.phaseState.lastTestPassed = false;
|
|
868
|
+
this.phaseState.consecutiveTestFailures++;
|
|
869
|
+
this.phaseState.inTestFixCycle = true;
|
|
870
|
+
}
|
|
871
|
+
else if (hasPassed && !hasFailed) {
|
|
872
|
+
// Pure pass
|
|
873
|
+
this.phaseState.lastTestPassed = true;
|
|
874
|
+
this.phaseState.consecutiveTestFailures = 0;
|
|
875
|
+
this.phaseState.inTestFixCycle = false;
|
|
876
|
+
}
|
|
877
|
+
else if (hasPassed && hasFailed) {
|
|
878
|
+
// Mixed - some passed, some failed
|
|
879
|
+
this.phaseState.lastTestPassed = false;
|
|
880
|
+
this.phaseState.consecutiveTestFailures++;
|
|
881
|
+
this.phaseState.inTestFixCycle = true;
|
|
882
|
+
}
|
|
883
|
+
// If no clear signal, don't update
|
|
884
|
+
}
|
|
706
885
|
isStuck() {
|
|
707
886
|
// Check for repeated tool calls
|
|
708
887
|
if (this.progress.recentToolCalls.length >= 3) {
|