Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ program
'--context-budget <n>',
'Max input tokens per iteration for smart context trimming (0 = unlimited)'
)
.option('--max-cost <amount>', 'Maximum cost in USD before stopping (0 = unlimited)', parseFloat)
// Figma integration options
.option('--figma-mode <mode>', 'Figma mode: spec, tokens, components, assets, content')
.option(
Expand Down
2 changes: 2 additions & 0 deletions src/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export interface RunCommandOptions {
circuitBreakerErrors?: number;
contextBudget?: number;
validationWarmup?: number;
maxCost?: number;
// Figma options
figmaMode?: 'spec' | 'tokens' | 'components' | 'assets' | 'content';
figmaFramework?: 'react' | 'vue' | 'svelte' | 'astro' | 'nextjs' | 'nuxt' | 'html';
Expand Down Expand Up @@ -653,6 +654,7 @@ Focus on one task at a time. After completing a task, update IMPLEMENTATION_PLAN
model: agent.type === 'claude-code' ? 'claude-3-sonnet' : 'default',
checkFileCompletion: true, // Always check for file-based completion
contextBudget: options.contextBudget ? Number(options.contextBudget) : undefined,
maxCost: options.maxCost,
circuitBreaker: preset?.circuitBreaker
? {
maxConsecutiveFailures:
Expand Down
16 changes: 16 additions & 0 deletions src/loop/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ export async function runLoop(options: LoopOptions): Promise<LoopResult> {

// Track cost for this iteration (silent - summary shown at end)
if (costTracker) {
const prevTotal = costTracker.getStats().totalCost.totalCost;
costTracker.recordIteration(options.task, result.output);

// Post-iteration cost ceiling check — prevent starting another expensive iteration
Expand All @@ -897,6 +898,21 @@ export async function runLoop(options: LoopOptions): Promise<LoopResult> {
exitReason = 'cost_ceiling';
break;
}

// Warn at cost thresholds when no --max-cost is set
if (!options.maxCost) {
const total = costTracker.getStats().totalCost.totalCost;
const thresholds = [2, 5, 10];
for (const t of thresholds) {
if (total >= t && prevTotal < t) {
console.log(
chalk.yellow(
`\n ⚠ Estimated cost has reached $${t}. Use --max-cost to set a budget limit.`
)
);
}
}
}
}

// Check for completion using enhanced detection (single-pass: status + reason)
Expand Down
Loading