ralph-starter 0.0.1 → 0.1.1-beta.1
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/README.md +707 -17
- package/dist/auth/browser.d.ts +10 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/browser.js +56 -0
- package/dist/auth/browser.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth-server.d.ts +20 -0
- package/dist/auth/oauth-server.d.ts.map +1 -0
- package/dist/auth/oauth-server.js +168 -0
- package/dist/auth/oauth-server.js.map +1 -0
- package/dist/auth/pkce.d.ts +46 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +57 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/providers/base.d.ts +52 -0
- package/dist/auth/providers/base.d.ts.map +1 -0
- package/dist/auth/providers/base.js +70 -0
- package/dist/auth/providers/base.js.map +1 -0
- package/dist/auth/providers/index.d.ts +23 -0
- package/dist/auth/providers/index.d.ts.map +1 -0
- package/dist/auth/providers/index.js +39 -0
- package/dist/auth/providers/index.js.map +1 -0
- package/dist/auth/providers/linear.d.ts +37 -0
- package/dist/auth/providers/linear.d.ts.map +1 -0
- package/dist/auth/providers/linear.js +46 -0
- package/dist/auth/providers/linear.js.map +1 -0
- package/dist/auth/providers/notion.d.ts +36 -0
- package/dist/auth/providers/notion.d.ts.map +1 -0
- package/dist/auth/providers/notion.js +75 -0
- package/dist/auth/providers/notion.js.map +1 -0
- package/dist/auth/providers/todoist.d.ts +29 -0
- package/dist/auth/providers/todoist.d.ts.map +1 -0
- package/dist/auth/providers/todoist.js +40 -0
- package/dist/auth/providers/todoist.js.map +1 -0
- package/dist/automation/git.d.ts +15 -0
- package/dist/automation/git.d.ts.map +1 -0
- package/dist/automation/git.js +73 -0
- package/dist/automation/git.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -19
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +14 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +243 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check.d.ts +12 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +124 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +13 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +374 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +31 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +353 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/integrations.d.ts +17 -0
- package/dist/commands/integrations.d.ts.map +1 -0
- package/dist/commands/integrations.js +193 -0
- package/dist/commands/integrations.js.map +1 -0
- package/dist/commands/plan.d.ts +5 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +80 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/run.d.ts +26 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +351 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scaffold.d.ts +9 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +128 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/setup.d.ts +12 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +27 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/skill.d.ts +6 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +151 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/source.d.ts +17 -0
- package/dist/commands/source.d.ts.map +1 -0
- package/dist/commands/source.js +173 -0
- package/dist/commands/source.js.map +1 -0
- package/dist/config/manager.d.ts +70 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +227 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -2
- package/dist/index.js.map +1 -0
- package/dist/integrations/_template/auth.d.ts +29 -0
- package/dist/integrations/_template/auth.d.ts.map +1 -0
- package/dist/integrations/_template/auth.js +42 -0
- package/dist/integrations/_template/auth.js.map +1 -0
- package/dist/integrations/_template/index.d.ts +8 -0
- package/dist/integrations/_template/index.d.ts.map +1 -0
- package/dist/integrations/_template/index.js +8 -0
- package/dist/integrations/_template/index.js.map +1 -0
- package/dist/integrations/_template/source.d.ts +34 -0
- package/dist/integrations/_template/source.d.ts.map +1 -0
- package/dist/integrations/_template/source.js +124 -0
- package/dist/integrations/_template/source.js.map +1 -0
- package/dist/integrations/base.d.ts +158 -0
- package/dist/integrations/base.d.ts.map +1 -0
- package/dist/integrations/base.js +109 -0
- package/dist/integrations/base.js.map +1 -0
- package/dist/integrations/github/index.d.ts +8 -0
- package/dist/integrations/github/index.d.ts.map +1 -0
- package/dist/integrations/github/index.js +8 -0
- package/dist/integrations/github/index.js.map +1 -0
- package/dist/integrations/github/source.d.ts +26 -0
- package/dist/integrations/github/source.d.ts.map +1 -0
- package/dist/integrations/github/source.js +190 -0
- package/dist/integrations/github/source.js.map +1 -0
- package/dist/integrations/index.d.ts +37 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +71 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/linear/auth.d.ts +37 -0
- package/dist/integrations/linear/auth.d.ts.map +1 -0
- package/dist/integrations/linear/auth.js +45 -0
- package/dist/integrations/linear/auth.js.map +1 -0
- package/dist/integrations/linear/index.d.ts +9 -0
- package/dist/integrations/linear/index.d.ts.map +1 -0
- package/dist/integrations/linear/index.js +9 -0
- package/dist/integrations/linear/index.js.map +1 -0
- package/dist/integrations/linear/source.d.ts +26 -0
- package/dist/integrations/linear/source.d.ts.map +1 -0
- package/dist/integrations/linear/source.js +248 -0
- package/dist/integrations/linear/source.js.map +1 -0
- package/dist/integrations/notion/index.d.ts +8 -0
- package/dist/integrations/notion/index.d.ts.map +1 -0
- package/dist/integrations/notion/index.js +8 -0
- package/dist/integrations/notion/index.js.map +1 -0
- package/dist/integrations/notion/source.d.ts +53 -0
- package/dist/integrations/notion/source.d.ts.map +1 -0
- package/dist/integrations/notion/source.js +463 -0
- package/dist/integrations/notion/source.js.map +1 -0
- package/dist/llm/api.d.ts +29 -0
- package/dist/llm/api.d.ts.map +1 -0
- package/dist/llm/api.js +152 -0
- package/dist/llm/api.js.map +1 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +7 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/providers.d.ts +24 -0
- package/dist/llm/providers.d.ts.map +1 -0
- package/dist/llm/providers.js +51 -0
- package/dist/llm/providers.js.map +1 -0
- package/dist/loop/__tests__/agents.test.d.ts +2 -0
- package/dist/loop/__tests__/agents.test.d.ts.map +1 -0
- package/dist/loop/__tests__/agents.test.js +183 -0
- package/dist/loop/__tests__/agents.test.js.map +1 -0
- package/dist/loop/__tests__/circuit-breaker.test.d.ts +2 -0
- package/dist/loop/__tests__/circuit-breaker.test.d.ts.map +1 -0
- package/dist/loop/__tests__/circuit-breaker.test.js +161 -0
- package/dist/loop/__tests__/circuit-breaker.test.js.map +1 -0
- package/dist/loop/__tests__/cost-tracker.test.d.ts +2 -0
- package/dist/loop/__tests__/cost-tracker.test.d.ts.map +1 -0
- package/dist/loop/__tests__/cost-tracker.test.js +200 -0
- package/dist/loop/__tests__/cost-tracker.test.js.map +1 -0
- package/dist/loop/__tests__/rate-limiter.test.d.ts +2 -0
- package/dist/loop/__tests__/rate-limiter.test.d.ts.map +1 -0
- package/dist/loop/__tests__/rate-limiter.test.js +198 -0
- package/dist/loop/__tests__/rate-limiter.test.js.map +1 -0
- package/dist/loop/__tests__/validation.test.d.ts +2 -0
- package/dist/loop/__tests__/validation.test.d.ts.map +1 -0
- package/dist/loop/__tests__/validation.test.js +234 -0
- package/dist/loop/__tests__/validation.test.js.map +1 -0
- package/dist/loop/agents.d.ts +26 -0
- package/dist/loop/agents.d.ts.map +1 -0
- package/dist/loop/agents.js +188 -0
- package/dist/loop/agents.js.map +1 -0
- package/dist/loop/circuit-breaker.d.ts +61 -0
- package/dist/loop/circuit-breaker.d.ts.map +1 -0
- package/dist/loop/circuit-breaker.js +143 -0
- package/dist/loop/circuit-breaker.js.map +1 -0
- package/dist/loop/cost-tracker.d.ts +90 -0
- package/dist/loop/cost-tracker.d.ts.map +1 -0
- package/dist/loop/cost-tracker.js +229 -0
- package/dist/loop/cost-tracker.js.map +1 -0
- package/dist/loop/estimator.d.ts +20 -0
- package/dist/loop/estimator.d.ts.map +1 -0
- package/dist/loop/estimator.js +123 -0
- package/dist/loop/estimator.js.map +1 -0
- package/dist/loop/executor.d.ts +44 -0
- package/dist/loop/executor.d.ts.map +1 -0
- package/dist/loop/executor.js +646 -0
- package/dist/loop/executor.js.map +1 -0
- package/dist/loop/progress.d.ts +34 -0
- package/dist/loop/progress.d.ts.map +1 -0
- package/dist/loop/progress.js +186 -0
- package/dist/loop/progress.js.map +1 -0
- package/dist/loop/rate-limiter.d.ts +71 -0
- package/dist/loop/rate-limiter.d.ts.map +1 -0
- package/dist/loop/rate-limiter.js +151 -0
- package/dist/loop/rate-limiter.js.map +1 -0
- package/dist/loop/semantic-analyzer.d.ts +33 -0
- package/dist/loop/semantic-analyzer.d.ts.map +1 -0
- package/dist/loop/semantic-analyzer.js +153 -0
- package/dist/loop/semantic-analyzer.js.map +1 -0
- package/dist/loop/skills.d.ts +29 -0
- package/dist/loop/skills.d.ts.map +1 -0
- package/dist/loop/skills.js +174 -0
- package/dist/loop/skills.js.map +1 -0
- package/dist/loop/step-detector.d.ts +17 -0
- package/dist/loop/step-detector.d.ts.map +1 -0
- package/dist/loop/step-detector.js +280 -0
- package/dist/loop/step-detector.js.map +1 -0
- package/dist/loop/task-counter.d.ts +41 -0
- package/dist/loop/task-counter.d.ts.map +1 -0
- package/dist/loop/task-counter.js +99 -0
- package/dist/loop/task-counter.js.map +1 -0
- package/dist/loop/validation.d.ts +28 -0
- package/dist/loop/validation.d.ts.map +1 -0
- package/dist/loop/validation.js +138 -0
- package/dist/loop/validation.js.map +1 -0
- package/dist/mcp/core/init.d.ts +15 -0
- package/dist/mcp/core/init.d.ts.map +1 -0
- package/dist/mcp/core/init.js +272 -0
- package/dist/mcp/core/init.js.map +1 -0
- package/dist/mcp/core/plan.d.ts +15 -0
- package/dist/mcp/core/plan.d.ts.map +1 -0
- package/dist/mcp/core/plan.js +90 -0
- package/dist/mcp/core/plan.js.map +1 -0
- package/dist/mcp/core/run.d.ts +26 -0
- package/dist/mcp/core/run.d.ts.map +1 -0
- package/dist/mcp/core/run.js +114 -0
- package/dist/mcp/core/run.js.map +1 -0
- package/dist/mcp/prompts.d.ts +10 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +163 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +16 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +114 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +73 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +15 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +316 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/presets/index.d.ts +36 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +236 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/setup/agent-detector.d.ts +57 -0
- package/dist/setup/agent-detector.d.ts.map +1 -0
- package/dist/setup/agent-detector.js +170 -0
- package/dist/setup/agent-detector.js.map +1 -0
- package/dist/setup/index.d.ts +7 -0
- package/dist/setup/index.d.ts.map +1 -0
- package/dist/setup/index.js +7 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/llm-tester.d.ts +33 -0
- package/dist/setup/llm-tester.d.ts.map +1 -0
- package/dist/setup/llm-tester.js +105 -0
- package/dist/setup/llm-tester.js.map +1 -0
- package/dist/setup/wizard.d.ts +19 -0
- package/dist/setup/wizard.d.ts.map +1 -0
- package/dist/setup/wizard.js +313 -0
- package/dist/setup/wizard.js.map +1 -0
- package/dist/sources/__tests__/file.test.d.ts +2 -0
- package/dist/sources/__tests__/file.test.d.ts.map +1 -0
- package/dist/sources/__tests__/file.test.js +126 -0
- package/dist/sources/__tests__/file.test.js.map +1 -0
- package/dist/sources/__tests__/github.test.d.ts +2 -0
- package/dist/sources/__tests__/github.test.d.ts.map +1 -0
- package/dist/sources/__tests__/github.test.js +157 -0
- package/dist/sources/__tests__/github.test.js.map +1 -0
- package/dist/sources/base.d.ts +72 -0
- package/dist/sources/base.d.ts.map +1 -0
- package/dist/sources/base.js +127 -0
- package/dist/sources/base.js.map +1 -0
- package/dist/sources/builtin/file.d.ts +21 -0
- package/dist/sources/builtin/file.d.ts.map +1 -0
- package/dist/sources/builtin/file.js +129 -0
- package/dist/sources/builtin/file.js.map +1 -0
- package/dist/sources/builtin/github-scraper.d.ts +65 -0
- package/dist/sources/builtin/github-scraper.d.ts.map +1 -0
- package/dist/sources/builtin/github-scraper.js +324 -0
- package/dist/sources/builtin/github-scraper.js.map +1 -0
- package/dist/sources/builtin/pdf.d.ts +24 -0
- package/dist/sources/builtin/pdf.d.ts.map +1 -0
- package/dist/sources/builtin/pdf.js +174 -0
- package/dist/sources/builtin/pdf.js.map +1 -0
- package/dist/sources/builtin/url.d.ts +47 -0
- package/dist/sources/builtin/url.d.ts.map +1 -0
- package/dist/sources/builtin/url.js +429 -0
- package/dist/sources/builtin/url.js.map +1 -0
- package/dist/sources/config.d.ts +72 -0
- package/dist/sources/config.d.ts.map +1 -0
- package/dist/sources/config.js +215 -0
- package/dist/sources/config.js.map +1 -0
- package/dist/sources/index.d.ts +47 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +210 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/integrations/github.d.ts +24 -0
- package/dist/sources/integrations/github.d.ts.map +1 -0
- package/dist/sources/integrations/github.js +193 -0
- package/dist/sources/integrations/github.js.map +1 -0
- package/dist/sources/integrations/linear.d.ts +18 -0
- package/dist/sources/integrations/linear.d.ts.map +1 -0
- package/dist/sources/integrations/linear.js +197 -0
- package/dist/sources/integrations/linear.js.map +1 -0
- package/dist/sources/integrations/notion.d.ts +39 -0
- package/dist/sources/integrations/notion.d.ts.map +1 -0
- package/dist/sources/integrations/notion.js +343 -0
- package/dist/sources/integrations/notion.js.map +1 -0
- package/dist/sources/integrations/todoist.d.ts +18 -0
- package/dist/sources/integrations/todoist.d.ts.map +1 -0
- package/dist/sources/integrations/todoist.js +154 -0
- package/dist/sources/integrations/todoist.js.map +1 -0
- package/dist/sources/types.d.ts +106 -0
- package/dist/sources/types.d.ts.map +1 -0
- package/dist/sources/types.js +9 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +3 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/progress-renderer.d.ts +54 -0
- package/dist/ui/progress-renderer.d.ts.map +1 -0
- package/dist/ui/progress-renderer.js +118 -0
- package/dist/ui/progress-renderer.js.map +1 -0
- package/dist/ui/shimmer.d.ts +16 -0
- package/dist/ui/shimmer.d.ts.map +1 -0
- package/dist/ui/shimmer.js +31 -0
- package/dist/ui/shimmer.js.map +1 -0
- package/dist/wizard/ascii-art.d.ts +93 -0
- package/dist/wizard/ascii-art.d.ts.map +1 -0
- package/dist/wizard/ascii-art.js +378 -0
- package/dist/wizard/ascii-art.js.map +1 -0
- package/dist/wizard/idea-prompts.d.ts +18 -0
- package/dist/wizard/idea-prompts.d.ts.map +1 -0
- package/dist/wizard/idea-prompts.js +154 -0
- package/dist/wizard/idea-prompts.js.map +1 -0
- package/dist/wizard/idea-ui.d.ts +34 -0
- package/dist/wizard/idea-ui.d.ts.map +1 -0
- package/dist/wizard/idea-ui.js +225 -0
- package/dist/wizard/idea-ui.js.map +1 -0
- package/dist/wizard/ideas.d.ts +27 -0
- package/dist/wizard/ideas.d.ts.map +1 -0
- package/dist/wizard/ideas.js +511 -0
- package/dist/wizard/ideas.js.map +1 -0
- package/dist/wizard/index.d.ts +11 -0
- package/dist/wizard/index.d.ts.map +1 -0
- package/dist/wizard/index.js +472 -0
- package/dist/wizard/index.js.map +1 -0
- package/dist/wizard/llm.d.ts +14 -0
- package/dist/wizard/llm.d.ts.map +1 -0
- package/dist/wizard/llm.js +420 -0
- package/dist/wizard/llm.js.map +1 -0
- package/dist/wizard/prompts.d.ts +75 -0
- package/dist/wizard/prompts.d.ts.map +1 -0
- package/dist/wizard/prompts.js +455 -0
- package/dist/wizard/prompts.js.map +1 -0
- package/dist/wizard/spec-generator.d.ts +14 -0
- package/dist/wizard/spec-generator.d.ts.map +1 -0
- package/dist/wizard/spec-generator.js +200 -0
- package/dist/wizard/spec-generator.js.map +1 -0
- package/dist/wizard/types.d.ts +53 -0
- package/dist/wizard/types.d.ts.map +1 -0
- package/dist/wizard/types.js +10 -0
- package/dist/wizard/types.js.map +1 -0
- package/dist/wizard/ui.d.ts +57 -0
- package/dist/wizard/ui.d.ts.map +1 -0
- package/dist/wizard/ui.js +211 -0
- package/dist/wizard/ui.js.map +1 -0
- package/package.json +67 -8
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
export const DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
3
|
+
maxConsecutiveFailures: 3,
|
|
4
|
+
maxSameErrorCount: 5,
|
|
5
|
+
cooldownMs: 30000,
|
|
6
|
+
};
|
|
7
|
+
export class CircuitBreaker {
|
|
8
|
+
config;
|
|
9
|
+
state;
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
|
|
12
|
+
this.state = {
|
|
13
|
+
consecutiveFailures: 0,
|
|
14
|
+
errorHistory: new Map(),
|
|
15
|
+
isOpen: false,
|
|
16
|
+
totalFailures: 0,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Hash an error message to track similar errors
|
|
21
|
+
*/
|
|
22
|
+
hashError(error) {
|
|
23
|
+
// Normalize the error by removing variable parts like line numbers, timestamps
|
|
24
|
+
const normalized = error
|
|
25
|
+
.replace(/\d+/g, 'N') // Replace numbers
|
|
26
|
+
.replace(/0x[a-fA-F0-9]+/g, 'HEX') // Replace hex values
|
|
27
|
+
.replace(/at\s+\S+\s+\(\S+:\d+:\d+\)/g, 'STACK') // Replace stack traces
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.trim()
|
|
30
|
+
.slice(0, 500); // Limit length
|
|
31
|
+
return crypto.createHash('md5').update(normalized).digest('hex').slice(0, 8);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Record a successful iteration - resets consecutive failures
|
|
35
|
+
*/
|
|
36
|
+
recordSuccess() {
|
|
37
|
+
this.state.consecutiveFailures = 0;
|
|
38
|
+
// Don't clear error history - we still want to track repeated errors
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Record a failed iteration
|
|
42
|
+
* @returns true if circuit should trip (open)
|
|
43
|
+
*/
|
|
44
|
+
recordFailure(errorMessage) {
|
|
45
|
+
this.state.consecutiveFailures++;
|
|
46
|
+
this.state.totalFailures++;
|
|
47
|
+
this.state.lastFailure = new Date();
|
|
48
|
+
// Track error by hash
|
|
49
|
+
const errorHash = this.hashError(errorMessage);
|
|
50
|
+
const currentCount = this.state.errorHistory.get(errorHash) || 0;
|
|
51
|
+
this.state.errorHistory.set(errorHash, currentCount + 1);
|
|
52
|
+
// Check if we should trip the circuit
|
|
53
|
+
if (this.shouldTrip(errorHash)) {
|
|
54
|
+
this.state.isOpen = true;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Determine if the circuit should trip
|
|
61
|
+
*/
|
|
62
|
+
shouldTrip(errorHash) {
|
|
63
|
+
// Trip on consecutive failures
|
|
64
|
+
if (this.state.consecutiveFailures >= this.config.maxConsecutiveFailures) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
// Trip on same error repeated too many times
|
|
68
|
+
const sameErrorCount = this.state.errorHistory.get(errorHash) || 0;
|
|
69
|
+
if (sameErrorCount >= this.config.maxSameErrorCount) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if circuit is open (tripped)
|
|
76
|
+
*/
|
|
77
|
+
isTripped() {
|
|
78
|
+
if (!this.state.isOpen) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
// Check if cooldown has passed
|
|
82
|
+
if (this.state.lastFailure) {
|
|
83
|
+
const elapsed = Date.now() - this.state.lastFailure.getTime();
|
|
84
|
+
if (elapsed >= this.config.cooldownMs) {
|
|
85
|
+
// Allow one retry attempt
|
|
86
|
+
this.state.isOpen = false;
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the reason why the circuit tripped
|
|
94
|
+
*/
|
|
95
|
+
getTripReason() {
|
|
96
|
+
if (!this.state.isOpen) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (this.state.consecutiveFailures >= this.config.maxConsecutiveFailures) {
|
|
100
|
+
return `${this.state.consecutiveFailures} consecutive failures (threshold: ${this.config.maxConsecutiveFailures})`;
|
|
101
|
+
}
|
|
102
|
+
// Find the most repeated error
|
|
103
|
+
let maxCount = 0;
|
|
104
|
+
for (const count of this.state.errorHistory.values()) {
|
|
105
|
+
if (count > maxCount) {
|
|
106
|
+
maxCount = count;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (maxCount >= this.config.maxSameErrorCount) {
|
|
110
|
+
return `Same error repeated ${maxCount} times (threshold: ${this.config.maxSameErrorCount})`;
|
|
111
|
+
}
|
|
112
|
+
return 'Circuit breaker tripped';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Reset the circuit breaker completely
|
|
116
|
+
*/
|
|
117
|
+
reset() {
|
|
118
|
+
this.state = {
|
|
119
|
+
consecutiveFailures: 0,
|
|
120
|
+
errorHistory: new Map(),
|
|
121
|
+
isOpen: false,
|
|
122
|
+
totalFailures: 0,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get current state for logging/debugging
|
|
127
|
+
*/
|
|
128
|
+
getState() {
|
|
129
|
+
return { ...this.state, errorHistory: new Map(this.state.errorHistory) };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get statistics for display
|
|
133
|
+
*/
|
|
134
|
+
getStats() {
|
|
135
|
+
return {
|
|
136
|
+
consecutiveFailures: this.state.consecutiveFailures,
|
|
137
|
+
totalFailures: this.state.totalFailures,
|
|
138
|
+
uniqueErrors: this.state.errorHistory.size,
|
|
139
|
+
isOpen: this.state.isOpen,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/loop/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost tracking for AI agent loops
|
|
3
|
+
* Estimates token usage and calculates costs based on model pricing
|
|
4
|
+
*/
|
|
5
|
+
export interface ModelPricing {
|
|
6
|
+
name: string;
|
|
7
|
+
inputPricePerMillion: number;
|
|
8
|
+
outputPricePerMillion: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const MODEL_PRICING: Record<string, ModelPricing>;
|
|
11
|
+
export interface TokenEstimate {
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
totalTokens: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CostEstimate {
|
|
17
|
+
inputCost: number;
|
|
18
|
+
outputCost: number;
|
|
19
|
+
totalCost: number;
|
|
20
|
+
}
|
|
21
|
+
export interface IterationCost {
|
|
22
|
+
iteration: number;
|
|
23
|
+
tokens: TokenEstimate;
|
|
24
|
+
cost: CostEstimate;
|
|
25
|
+
timestamp: Date;
|
|
26
|
+
}
|
|
27
|
+
export interface CostTrackerStats {
|
|
28
|
+
totalIterations: number;
|
|
29
|
+
totalTokens: TokenEstimate;
|
|
30
|
+
totalCost: CostEstimate;
|
|
31
|
+
avgTokensPerIteration: TokenEstimate;
|
|
32
|
+
avgCostPerIteration: CostEstimate;
|
|
33
|
+
projectedCost?: CostEstimate;
|
|
34
|
+
iterations: IterationCost[];
|
|
35
|
+
}
|
|
36
|
+
export interface CostTrackerConfig {
|
|
37
|
+
model: string;
|
|
38
|
+
maxIterations?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Estimate token count from text
|
|
42
|
+
* Rough approximation: ~4 characters per token for English text
|
|
43
|
+
*/
|
|
44
|
+
export declare function estimateTokens(text: string): number;
|
|
45
|
+
/**
|
|
46
|
+
* Calculate cost from tokens and pricing
|
|
47
|
+
*/
|
|
48
|
+
export declare function calculateCost(tokens: TokenEstimate, pricing: ModelPricing): CostEstimate;
|
|
49
|
+
/**
|
|
50
|
+
* Format cost as USD string
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatCost(cost: number): string;
|
|
53
|
+
/**
|
|
54
|
+
* Format token count with K/M suffixes
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatTokens(tokens: number): string;
|
|
57
|
+
/**
|
|
58
|
+
* Cost tracker for monitoring loop expenses
|
|
59
|
+
*/
|
|
60
|
+
export declare class CostTracker {
|
|
61
|
+
private config;
|
|
62
|
+
private pricing;
|
|
63
|
+
private iterations;
|
|
64
|
+
constructor(config: CostTrackerConfig);
|
|
65
|
+
/**
|
|
66
|
+
* Record an iteration's token usage
|
|
67
|
+
*/
|
|
68
|
+
recordIteration(input: string, output: string): IterationCost;
|
|
69
|
+
/**
|
|
70
|
+
* Get current statistics
|
|
71
|
+
*/
|
|
72
|
+
getStats(): CostTrackerStats;
|
|
73
|
+
/**
|
|
74
|
+
* Format stats for CLI display
|
|
75
|
+
*/
|
|
76
|
+
formatStats(): string;
|
|
77
|
+
/**
|
|
78
|
+
* Format a summary for activity.md
|
|
79
|
+
*/
|
|
80
|
+
formatSummary(): string;
|
|
81
|
+
/**
|
|
82
|
+
* Get the last iteration's cost
|
|
83
|
+
*/
|
|
84
|
+
getLastIterationCost(): IterationCost | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Reset the tracker
|
|
87
|
+
*/
|
|
88
|
+
reset(): void;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=cost-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost-tracker.d.ts","sourceRoot":"","sources":["../../src/loop/cost-tracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAGD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAgCtD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,aAAa,CAAC;IAC3B,SAAS,EAAE,YAAY,CAAC;IACxB,qBAAqB,EAAE,aAAa,CAAC;IACrC,mBAAmB,EAAE,YAAY,CAAC;IAClC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY,CAQxF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,UAAU,CAAuB;gBAE7B,MAAM,EAAE,iBAAiB;IAKrC;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa;IAuB7D;;OAEG;IACH,QAAQ,IAAI,gBAAgB;IA8D5B;;OAEG;IACH,WAAW,IAAI,MAAM;IAmBrB;;OAEG;IACH,aAAa,IAAI,MAAM;IAsBvB;;OAEG;IACH,oBAAoB,IAAI,aAAa,GAAG,SAAS;IAIjD;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost tracking for AI agent loops
|
|
3
|
+
* Estimates token usage and calculates costs based on model pricing
|
|
4
|
+
*/
|
|
5
|
+
// Pricing as of January 2026 (approximate)
|
|
6
|
+
export const MODEL_PRICING = {
|
|
7
|
+
'claude-3-opus': {
|
|
8
|
+
name: 'Claude 3 Opus',
|
|
9
|
+
inputPricePerMillion: 15,
|
|
10
|
+
outputPricePerMillion: 75,
|
|
11
|
+
},
|
|
12
|
+
'claude-3-sonnet': {
|
|
13
|
+
name: 'Claude 3.5 Sonnet',
|
|
14
|
+
inputPricePerMillion: 3,
|
|
15
|
+
outputPricePerMillion: 15,
|
|
16
|
+
},
|
|
17
|
+
'claude-3-haiku': {
|
|
18
|
+
name: 'Claude 3.5 Haiku',
|
|
19
|
+
inputPricePerMillion: 0.25,
|
|
20
|
+
outputPricePerMillion: 1.25,
|
|
21
|
+
},
|
|
22
|
+
'gpt-4': {
|
|
23
|
+
name: 'GPT-4',
|
|
24
|
+
inputPricePerMillion: 30,
|
|
25
|
+
outputPricePerMillion: 60,
|
|
26
|
+
},
|
|
27
|
+
'gpt-4-turbo': {
|
|
28
|
+
name: 'GPT-4 Turbo',
|
|
29
|
+
inputPricePerMillion: 10,
|
|
30
|
+
outputPricePerMillion: 30,
|
|
31
|
+
},
|
|
32
|
+
// Default for unknown models (conservative estimate)
|
|
33
|
+
default: {
|
|
34
|
+
name: 'Default',
|
|
35
|
+
inputPricePerMillion: 3,
|
|
36
|
+
outputPricePerMillion: 15,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Estimate token count from text
|
|
41
|
+
* Rough approximation: ~4 characters per token for English text
|
|
42
|
+
*/
|
|
43
|
+
export function estimateTokens(text) {
|
|
44
|
+
if (!text)
|
|
45
|
+
return 0;
|
|
46
|
+
// More accurate estimation considering code vs prose
|
|
47
|
+
// Code typically has more tokens per character due to special characters
|
|
48
|
+
const hasCode = /```|function|const |let |var |import |export |class |def |async |await /.test(text);
|
|
49
|
+
const charsPerToken = hasCode ? 3.5 : 4;
|
|
50
|
+
return Math.ceil(text.length / charsPerToken);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Calculate cost from tokens and pricing
|
|
54
|
+
*/
|
|
55
|
+
export function calculateCost(tokens, pricing) {
|
|
56
|
+
const inputCost = (tokens.inputTokens / 1_000_000) * pricing.inputPricePerMillion;
|
|
57
|
+
const outputCost = (tokens.outputTokens / 1_000_000) * pricing.outputPricePerMillion;
|
|
58
|
+
return {
|
|
59
|
+
inputCost,
|
|
60
|
+
outputCost,
|
|
61
|
+
totalCost: inputCost + outputCost,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Format cost as USD string
|
|
66
|
+
*/
|
|
67
|
+
export function formatCost(cost) {
|
|
68
|
+
if (cost < 0.01) {
|
|
69
|
+
return `$${(cost * 100).toFixed(2)}¢`;
|
|
70
|
+
}
|
|
71
|
+
if (cost < 1) {
|
|
72
|
+
return `$${cost.toFixed(3)}`;
|
|
73
|
+
}
|
|
74
|
+
return `$${cost.toFixed(2)}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Format token count with K/M suffixes
|
|
78
|
+
*/
|
|
79
|
+
export function formatTokens(tokens) {
|
|
80
|
+
if (tokens < 1000) {
|
|
81
|
+
return `${tokens}`;
|
|
82
|
+
}
|
|
83
|
+
if (tokens < 1_000_000) {
|
|
84
|
+
return `${(tokens / 1000).toFixed(1)}K`;
|
|
85
|
+
}
|
|
86
|
+
return `${(tokens / 1_000_000).toFixed(2)}M`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Cost tracker for monitoring loop expenses
|
|
90
|
+
*/
|
|
91
|
+
export class CostTracker {
|
|
92
|
+
config;
|
|
93
|
+
pricing;
|
|
94
|
+
iterations = [];
|
|
95
|
+
constructor(config) {
|
|
96
|
+
this.config = config;
|
|
97
|
+
this.pricing = MODEL_PRICING[config.model] || MODEL_PRICING.default;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Record an iteration's token usage
|
|
101
|
+
*/
|
|
102
|
+
recordIteration(input, output) {
|
|
103
|
+
const inputTokens = estimateTokens(input);
|
|
104
|
+
const outputTokens = estimateTokens(output);
|
|
105
|
+
const tokens = {
|
|
106
|
+
inputTokens,
|
|
107
|
+
outputTokens,
|
|
108
|
+
totalTokens: inputTokens + outputTokens,
|
|
109
|
+
};
|
|
110
|
+
const cost = calculateCost(tokens, this.pricing);
|
|
111
|
+
const iterationCost = {
|
|
112
|
+
iteration: this.iterations.length + 1,
|
|
113
|
+
tokens,
|
|
114
|
+
cost,
|
|
115
|
+
timestamp: new Date(),
|
|
116
|
+
};
|
|
117
|
+
this.iterations.push(iterationCost);
|
|
118
|
+
return iterationCost;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get current statistics
|
|
122
|
+
*/
|
|
123
|
+
getStats() {
|
|
124
|
+
const totalIterations = this.iterations.length;
|
|
125
|
+
if (totalIterations === 0) {
|
|
126
|
+
return {
|
|
127
|
+
totalIterations: 0,
|
|
128
|
+
totalTokens: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
129
|
+
totalCost: { inputCost: 0, outputCost: 0, totalCost: 0 },
|
|
130
|
+
avgTokensPerIteration: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
131
|
+
avgCostPerIteration: { inputCost: 0, outputCost: 0, totalCost: 0 },
|
|
132
|
+
iterations: [],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const totalTokens = {
|
|
136
|
+
inputTokens: this.iterations.reduce((sum, i) => sum + i.tokens.inputTokens, 0),
|
|
137
|
+
outputTokens: this.iterations.reduce((sum, i) => sum + i.tokens.outputTokens, 0),
|
|
138
|
+
totalTokens: this.iterations.reduce((sum, i) => sum + i.tokens.totalTokens, 0),
|
|
139
|
+
};
|
|
140
|
+
const totalCost = {
|
|
141
|
+
inputCost: this.iterations.reduce((sum, i) => sum + i.cost.inputCost, 0),
|
|
142
|
+
outputCost: this.iterations.reduce((sum, i) => sum + i.cost.outputCost, 0),
|
|
143
|
+
totalCost: this.iterations.reduce((sum, i) => sum + i.cost.totalCost, 0),
|
|
144
|
+
};
|
|
145
|
+
const avgTokensPerIteration = {
|
|
146
|
+
inputTokens: Math.round(totalTokens.inputTokens / totalIterations),
|
|
147
|
+
outputTokens: Math.round(totalTokens.outputTokens / totalIterations),
|
|
148
|
+
totalTokens: Math.round(totalTokens.totalTokens / totalIterations),
|
|
149
|
+
};
|
|
150
|
+
const avgCostPerIteration = {
|
|
151
|
+
inputCost: totalCost.inputCost / totalIterations,
|
|
152
|
+
outputCost: totalCost.outputCost / totalIterations,
|
|
153
|
+
totalCost: totalCost.totalCost / totalIterations,
|
|
154
|
+
};
|
|
155
|
+
// Calculate projected cost if max iterations is set
|
|
156
|
+
let projectedCost;
|
|
157
|
+
if (this.config.maxIterations && totalIterations >= 3) {
|
|
158
|
+
const remainingIterations = this.config.maxIterations - totalIterations;
|
|
159
|
+
if (remainingIterations > 0) {
|
|
160
|
+
projectedCost = {
|
|
161
|
+
inputCost: totalCost.inputCost + avgCostPerIteration.inputCost * remainingIterations,
|
|
162
|
+
outputCost: totalCost.outputCost + avgCostPerIteration.outputCost * remainingIterations,
|
|
163
|
+
totalCost: totalCost.totalCost + avgCostPerIteration.totalCost * remainingIterations,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
totalIterations,
|
|
169
|
+
totalTokens,
|
|
170
|
+
totalCost,
|
|
171
|
+
avgTokensPerIteration,
|
|
172
|
+
avgCostPerIteration,
|
|
173
|
+
projectedCost,
|
|
174
|
+
iterations: this.iterations,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Format stats for CLI display
|
|
179
|
+
*/
|
|
180
|
+
formatStats() {
|
|
181
|
+
const stats = this.getStats();
|
|
182
|
+
if (stats.totalIterations === 0) {
|
|
183
|
+
return 'No iterations recorded';
|
|
184
|
+
}
|
|
185
|
+
const lines = [
|
|
186
|
+
`Tokens: ${formatTokens(stats.totalTokens.totalTokens)} (${formatTokens(stats.totalTokens.inputTokens)} in / ${formatTokens(stats.totalTokens.outputTokens)} out)`,
|
|
187
|
+
`Cost: ${formatCost(stats.totalCost.totalCost)} (${formatCost(stats.avgCostPerIteration.totalCost)}/iteration avg)`,
|
|
188
|
+
];
|
|
189
|
+
if (stats.projectedCost) {
|
|
190
|
+
lines.push(`Projected max cost: ${formatCost(stats.projectedCost.totalCost)}`);
|
|
191
|
+
}
|
|
192
|
+
return lines.join('\n');
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Format a summary for activity.md
|
|
196
|
+
*/
|
|
197
|
+
formatSummary() {
|
|
198
|
+
const stats = this.getStats();
|
|
199
|
+
if (stats.totalIterations === 0) {
|
|
200
|
+
return '';
|
|
201
|
+
}
|
|
202
|
+
return `
|
|
203
|
+
## Cost Summary
|
|
204
|
+
|
|
205
|
+
| Metric | Value |
|
|
206
|
+
|--------|-------|
|
|
207
|
+
| Total Iterations | ${stats.totalIterations} |
|
|
208
|
+
| Total Tokens | ${formatTokens(stats.totalTokens.totalTokens)} |
|
|
209
|
+
| Input Tokens | ${formatTokens(stats.totalTokens.inputTokens)} |
|
|
210
|
+
| Output Tokens | ${formatTokens(stats.totalTokens.outputTokens)} |
|
|
211
|
+
| Total Cost | ${formatCost(stats.totalCost.totalCost)} |
|
|
212
|
+
| Avg Cost/Iteration | ${formatCost(stats.avgCostPerIteration.totalCost)} |
|
|
213
|
+
${stats.projectedCost ? `| Projected Max Cost | ${formatCost(stats.projectedCost.totalCost)} |` : ''}
|
|
214
|
+
`;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get the last iteration's cost
|
|
218
|
+
*/
|
|
219
|
+
getLastIterationCost() {
|
|
220
|
+
return this.iterations[this.iterations.length - 1];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Reset the tracker
|
|
224
|
+
*/
|
|
225
|
+
reset() {
|
|
226
|
+
this.iterations = [];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=cost-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost-tracker.js","sourceRoot":"","sources":["../../src/loop/cost-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TaskCount } from './task-counter.js';
|
|
2
|
+
export interface LoopEstimate {
|
|
3
|
+
estimatedTimeMinutes: number;
|
|
4
|
+
estimatedTokens: number;
|
|
5
|
+
estimatedCost: number;
|
|
6
|
+
confidence: 'low' | 'medium' | 'high';
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Estimate loop duration, tokens, and cost based on task count
|
|
10
|
+
*/
|
|
11
|
+
export declare function estimateLoop(taskCount: TaskCount): LoopEstimate;
|
|
12
|
+
/**
|
|
13
|
+
* Format estimate for display
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatEstimate(estimate: LoopEstimate): string;
|
|
16
|
+
/**
|
|
17
|
+
* Format estimate as multiple lines for detailed display
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatEstimateDetailed(estimate: LoopEstimate): string[];
|
|
20
|
+
//# sourceMappingURL=estimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../../src/loop/estimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,YAAY,CAgF/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAa7D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE,CAsBvE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Average estimates per task (based on typical Claude Code usage)
|
|
2
|
+
const ESTIMATES = {
|
|
3
|
+
// Time in minutes per task
|
|
4
|
+
timePerTask: {
|
|
5
|
+
simple: 0.5, // Simple file edits
|
|
6
|
+
medium: 1.5, // New files, multiple edits
|
|
7
|
+
complex: 3, // Complex features, multiple files
|
|
8
|
+
},
|
|
9
|
+
// Tokens per task
|
|
10
|
+
tokensPerTask: {
|
|
11
|
+
simple: 2000,
|
|
12
|
+
medium: 5000,
|
|
13
|
+
complex: 10000,
|
|
14
|
+
},
|
|
15
|
+
// Cost per 1K tokens (Claude Sonnet pricing approximation)
|
|
16
|
+
costPer1kTokens: {
|
|
17
|
+
input: 0.003,
|
|
18
|
+
output: 0.015,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Estimate loop duration, tokens, and cost based on task count
|
|
23
|
+
*/
|
|
24
|
+
export function estimateLoop(taskCount) {
|
|
25
|
+
const pendingTasks = taskCount.pending;
|
|
26
|
+
if (pendingTasks === 0) {
|
|
27
|
+
return {
|
|
28
|
+
estimatedTimeMinutes: 1,
|
|
29
|
+
estimatedTokens: 2000,
|
|
30
|
+
estimatedCost: 0.05,
|
|
31
|
+
confidence: 'high',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Classify tasks by complexity based on name keywords
|
|
35
|
+
let simpleCount = 0;
|
|
36
|
+
let mediumCount = 0;
|
|
37
|
+
let complexCount = 0;
|
|
38
|
+
for (const task of taskCount.tasks.filter((t) => !t.completed)) {
|
|
39
|
+
const name = task.name.toLowerCase();
|
|
40
|
+
// Complex indicators
|
|
41
|
+
if (name.includes('implement') ||
|
|
42
|
+
name.includes('create') ||
|
|
43
|
+
name.includes('build') ||
|
|
44
|
+
name.includes('feature') ||
|
|
45
|
+
name.includes('integration') ||
|
|
46
|
+
name.includes('api')) {
|
|
47
|
+
complexCount++;
|
|
48
|
+
}
|
|
49
|
+
// Simple indicators
|
|
50
|
+
else if (name.includes('fix') ||
|
|
51
|
+
name.includes('update') ||
|
|
52
|
+
name.includes('rename') ||
|
|
53
|
+
name.includes('move') ||
|
|
54
|
+
name.includes('delete') ||
|
|
55
|
+
name.includes('config')) {
|
|
56
|
+
simpleCount++;
|
|
57
|
+
}
|
|
58
|
+
// Default to medium
|
|
59
|
+
else {
|
|
60
|
+
mediumCount++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Calculate estimates
|
|
64
|
+
const estimatedTimeMinutes = simpleCount * ESTIMATES.timePerTask.simple +
|
|
65
|
+
mediumCount * ESTIMATES.timePerTask.medium +
|
|
66
|
+
complexCount * ESTIMATES.timePerTask.complex;
|
|
67
|
+
const estimatedTokens = simpleCount * ESTIMATES.tokensPerTask.simple +
|
|
68
|
+
mediumCount * ESTIMATES.tokensPerTask.medium +
|
|
69
|
+
complexCount * ESTIMATES.tokensPerTask.complex;
|
|
70
|
+
// Cost = input tokens + output tokens (assume 30% input, 70% output)
|
|
71
|
+
const inputTokens = estimatedTokens * 0.3;
|
|
72
|
+
const outputTokens = estimatedTokens * 0.7;
|
|
73
|
+
const estimatedCost = (inputTokens / 1000) * ESTIMATES.costPer1kTokens.input +
|
|
74
|
+
(outputTokens / 1000) * ESTIMATES.costPer1kTokens.output;
|
|
75
|
+
// Confidence based on task count
|
|
76
|
+
let confidence = 'medium';
|
|
77
|
+
if (pendingTasks <= 3) {
|
|
78
|
+
confidence = 'high';
|
|
79
|
+
}
|
|
80
|
+
else if (pendingTasks >= 10) {
|
|
81
|
+
confidence = 'low';
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
estimatedTimeMinutes: Math.round(estimatedTimeMinutes),
|
|
85
|
+
estimatedTokens: Math.round(estimatedTokens),
|
|
86
|
+
estimatedCost: Math.round(estimatedCost * 100) / 100, // Round to cents
|
|
87
|
+
confidence,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format estimate for display
|
|
92
|
+
*/
|
|
93
|
+
export function formatEstimate(estimate) {
|
|
94
|
+
const time = estimate.estimatedTimeMinutes;
|
|
95
|
+
const timeStr = time >= 60 ? `${Math.floor(time / 60)}h ${time % 60}m` : `~${time}m`;
|
|
96
|
+
const tokens = estimate.estimatedTokens;
|
|
97
|
+
const tokensStr = tokens >= 1000 ? `~${(tokens / 1000).toFixed(1)}K` : `~${tokens}`;
|
|
98
|
+
const costStr = estimate.estimatedCost < 1
|
|
99
|
+
? `~${Math.round(estimate.estimatedCost * 100)}¢`
|
|
100
|
+
: `~$${estimate.estimatedCost.toFixed(2)}`;
|
|
101
|
+
return `${timeStr} │ ${tokensStr} tokens │ ${costStr}`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Format estimate as multiple lines for detailed display
|
|
105
|
+
*/
|
|
106
|
+
export function formatEstimateDetailed(estimate) {
|
|
107
|
+
const lines = [];
|
|
108
|
+
const time = estimate.estimatedTimeMinutes;
|
|
109
|
+
const timeStr = time >= 60 ? `${Math.floor(time / 60)}h ${time % 60}m` : `${time} minutes`;
|
|
110
|
+
lines.push(`⏱ Estimated time: ${timeStr}`);
|
|
111
|
+
const tokens = estimate.estimatedTokens;
|
|
112
|
+
const tokensStr = tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}K` : `${tokens}`;
|
|
113
|
+
lines.push(`📊 Estimated tokens: ${tokensStr}`);
|
|
114
|
+
const costStr = estimate.estimatedCost < 1
|
|
115
|
+
? `${Math.round(estimate.estimatedCost * 100)}¢`
|
|
116
|
+
: `$${estimate.estimatedCost.toFixed(2)}`;
|
|
117
|
+
lines.push(`💰 Estimated cost: ${costStr}`);
|
|
118
|
+
if (estimate.confidence !== 'high') {
|
|
119
|
+
lines.push(`📈 Confidence: ${estimate.confidence}`);
|
|
120
|
+
}
|
|
121
|
+
return lines;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=estimator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimator.js","sourceRoot":"","sources":["../../src/loop/estimator.ts"],"names":[],"mappings":"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"}
|