()
| 41 | } |
| 42 | |
| 43 | incrementIteration(): void { |
| 44 | this.iterations++; |
| 45 | } |
| 46 | |
| 47 | /** Record non-model progress (a completed TOOL call). A 5-minute shell command is work, |
| 48 | * not a stall — without this, the wall ceiling read long tool runs as 'stalled' and |
| 49 | * killed the task right after the tool returned (live: 808s/600s, stalled 300s). */ |
| 50 | noteProgress(): void { |
| 51 | this.lastProgressAt = Date.now(); |
| 52 | } |
| 53 | |
| 54 | checkpoint(): void { |
| 55 | const wallMs = Date.now() - this.startTime; |
| 56 | // A value of 0 (or negative) on any limit means "no limit" — useful for local |
| 57 | // models where token/cost budgets are meaningless. Set perTaskMaxTokens: 0 in |
| 58 | // config.budget to disable the token cap entirely. |
| 59 | if (this.maxTokens > 0 && this.tokens > this.maxTokens) { |
| 60 | throw new BudgetExceededError(`Token budget exceeded: ${this.tokens}/${this.maxTokens}`, 'tokens'); |
| 61 | } |
| 62 | if (this.maxCostUsd > 0 && this.costUsd > this.maxCostUsd) { |
| 63 | throw new BudgetExceededError(`Cost budget exceeded: $${this.costUsd.toFixed(4)}/$${this.maxCostUsd}`, 'cost'); |
no outgoing calls
no test coverage detected