codehere 0.8.0 → 1.0.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/README.md +37 -184
- package/dist/application/use-cases/check-claimed-tests.js +81 -0
- package/dist/application/use-cases/detect-test-weakening.js +237 -0
- package/dist/application/use-cases/rerun-tests.js +329 -0
- package/dist/index.js +74 -1004
- package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -265
- package/dist/presentation/cli/commands/check-command.js +251 -0
- package/dist/presentation/cli/commands/help-command.js +22 -286
- package/dist/ui.js +19 -438
- package/dist/utils/version.js +0 -12
- package/package.json +18 -27
- package/dist/application/use-cases/domain-trust.js +0 -110
- package/dist/application/use-cases/generate-final-report.js +0 -134
- package/dist/application/use-cases/generate-narration.js +0 -128
- package/dist/application/use-cases/generate-thread-title.js +0 -178
- package/dist/application/use-cases/narrator-prompt-template.js +0 -158
- package/dist/application/use-cases/thread-export.js +0 -155
- package/dist/application/use-cases/verify-claim.js +0 -274
- package/dist/application/use-cases/write-pass.js +0 -277
- package/dist/domain/entities/task.js +0 -61
- package/dist/domain/services/codebase-detector.js +0 -91
- package/dist/error-handler.js +0 -251
- package/dist/infrastructure/completion/bash-completion.js +0 -25
- package/dist/infrastructure/completion/fish-completion.js +0 -22
- package/dist/infrastructure/completion/zsh-completion.js +0 -30
- package/dist/infrastructure/config/config-manager.js +0 -173
- package/dist/infrastructure/config/product-context.js +0 -67
- package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
- package/dist/infrastructure/context/adapters/figma-source.js +0 -163
- package/dist/infrastructure/context/adapters/github-issue-source.js +0 -159
- package/dist/infrastructure/context/adapters/linear-source.js +0 -190
- package/dist/infrastructure/context/context-resolver.js +0 -144
- package/dist/infrastructure/context/context-source.js +0 -114
- package/dist/infrastructure/context/oauth-flow.js +0 -207
- package/dist/infrastructure/context/oauth-store.js +0 -119
- package/dist/infrastructure/context/registry-bootstrap.js +0 -99
- package/dist/infrastructure/context/write-pass-resolver.js +0 -106
- package/dist/infrastructure/cost/budget-config.js +0 -113
- package/dist/infrastructure/cost/cost-router.js +0 -104
- package/dist/infrastructure/cost/spend-aggregator.js +0 -147
- package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -888
- package/dist/infrastructure/hooks/hook-mode.js +0 -71
- package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -43
- package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
- package/dist/infrastructure/hooks/session-analyzer.js +0 -177
- package/dist/infrastructure/observability/execution-tracer.js +0 -227
- package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
- package/dist/infrastructure/orchestration/agent-installer.js +0 -101
- package/dist/infrastructure/orchestration/agents-config-seed.js +0 -56
- package/dist/infrastructure/orchestration/aider-adapter.js +0 -447
- package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
- package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -478
- package/dist/infrastructure/orchestration/codex-adapter.js +0 -538
- package/dist/infrastructure/orchestration/conductor-adapter.js +0 -377
- package/dist/infrastructure/orchestration/context-handoff.js +0 -144
- package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
- package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
- package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
- package/dist/infrastructure/orchestration/failover-config.js +0 -77
- package/dist/infrastructure/orchestration/failover-policy.js +0 -106
- package/dist/infrastructure/orchestration/gemini-adapter.js +0 -583
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -558
- package/dist/infrastructure/orchestration/graphify-context.js +0 -254
- package/dist/infrastructure/orchestration/memory-injector.js +0 -380
- package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -233
- package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
- package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
- package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
- package/dist/infrastructure/orchestration/opencode-adapter.js +0 -510
- package/dist/infrastructure/orchestration/progress-aggregator.js +0 -689
- package/dist/infrastructure/orchestration/readiness.js +0 -103
- package/dist/infrastructure/orchestration/session-manager.js +0 -1091
- package/dist/infrastructure/orchestration/session-persistence.js +0 -258
- package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
- package/dist/infrastructure/orchestration/write-pass-store.js +0 -46
- package/dist/infrastructure/protocols/cloud-sync.js +0 -207
- package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
- package/dist/infrastructure/protocols/mcp-server-impl.js +0 -2853
- package/dist/infrastructure/protocols/probe-port.js +0 -36
- package/dist/infrastructure/protocols/thread-phase.js +0 -105
- package/dist/infrastructure/protocols/ui-page-v2.js +0 -4418
- package/dist/infrastructure/protocols/ui-page.js +0 -2377
- package/dist/infrastructure/protocols/verify-page.js +0 -983
- package/dist/infrastructure/security/file-collection.js +0 -118
- package/dist/infrastructure/security/input-validator.js +0 -152
- package/dist/infrastructure/security/permissions-config.js +0 -234
- package/dist/infrastructure/security/trust-scorer.js +0 -657
- package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
- package/dist/infrastructure/storage/embeddings-path.js +0 -37
- package/dist/infrastructure/storage/project-thread-migration.js +0 -237
- package/dist/infrastructure/storage/project-thread-mirror.js +0 -524
- package/dist/infrastructure/storage/project-thread-reader.js +0 -172
- package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
- package/dist/infrastructure/storage/task-repository.js +0 -206
- package/dist/monitoring.js +0 -212
- package/dist/presentation/cli/commands/audit-command.js +0 -126
- package/dist/presentation/cli/commands/budget-command.js +0 -79
- package/dist/presentation/cli/commands/config-command.js +0 -125
- package/dist/presentation/cli/commands/context-source-command.js +0 -198
- package/dist/presentation/cli/commands/hook-command.js +0 -265
- package/dist/presentation/cli/commands/init-command.js +0 -578
- package/dist/presentation/cli/commands/memory-command.js +0 -1031
- package/dist/presentation/cli/commands/narrator-command.js +0 -101
- package/dist/presentation/cli/commands/permission-command.js +0 -116
- package/dist/presentation/cli/commands/protocols-builder.js +0 -254
- package/dist/presentation/cli/commands/protocols-command.js +0 -84
- package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
- package/dist/presentation/cli/commands/report-command.js +0 -387
- package/dist/presentation/cli/commands/scan-tool-command.js +0 -94
- package/dist/presentation/cli/commands/setup-command.js +0 -307
- package/dist/presentation/cli/commands/status-command.js +0 -661
- package/dist/presentation/cli/commands/thread-command.js +0 -288
- package/dist/presentation/cli/commands/trust-command.js +0 -306
- package/dist/presentation/cli/commands/verify-command.js +0 -233
- package/dist/presentation/cli/error-display.js +0 -336
- package/dist/presentation/cli/repl.js +0 -797
- package/dist/presentation/cli/task-deliverable.js +0 -127
- package/dist/testing/cassette.js +0 -125
- package/dist/testing/replay-adapter.js +0 -166
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cost Router
|
|
3
|
-
*
|
|
4
|
-
* Given a trust score and task complexity, recommends the cheapest model
|
|
5
|
-
* that's safe to use. The 42x cost difference between Haiku and Opus means
|
|
6
|
-
* routing decisions have real financial impact at scale.
|
|
7
|
-
*
|
|
8
|
-
* Model tiers (approximate $/M output tokens, 2026):
|
|
9
|
-
* fast tier (e.g. claude-haiku-4-5) $1.25 — cheap, good for simple tasks
|
|
10
|
-
* balanced tier (e.g. claude-sonnet-4-6) $15.00 — good for most tasks
|
|
11
|
-
* max tier (e.g. claude-opus-4-6) $75.00 — strongest, use sparingly
|
|
12
|
-
*
|
|
13
|
-
* Routing logic:
|
|
14
|
-
* trust >= 90, simple task → fast tier (60x cheaper than max tier)
|
|
15
|
-
* trust >= 75, any task → balanced tier (5x cheaper than max tier)
|
|
16
|
-
* trust < 75, or critical → balanced tier with human review flag
|
|
17
|
-
* critical findings present → block before reaching model
|
|
18
|
-
*/
|
|
19
|
-
const MODEL_COSTS = {
|
|
20
|
-
haiku: 1.25,
|
|
21
|
-
sonnet: 15.0,
|
|
22
|
-
opus: 75.0,
|
|
23
|
-
};
|
|
24
|
-
const MODEL_IDS = {
|
|
25
|
-
haiku: 'claude-haiku-4-5-20251001',
|
|
26
|
-
sonnet: 'claude-sonnet-4-6',
|
|
27
|
-
opus: 'claude-opus-4-6',
|
|
28
|
-
};
|
|
29
|
-
const TIER_LABELS = {
|
|
30
|
-
haiku: 'fast tier',
|
|
31
|
-
sonnet: 'balanced tier',
|
|
32
|
-
opus: 'max tier',
|
|
33
|
-
};
|
|
34
|
-
function savingsLabel(chosen) {
|
|
35
|
-
if (chosen === 'opus')
|
|
36
|
-
return 'max tier (baseline)';
|
|
37
|
-
const ratio = MODEL_COSTS.opus / MODEL_COSTS[chosen];
|
|
38
|
-
return `${TIER_LABELS[chosen]} · ${Math.round(ratio)}x cheaper than max tier`;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Recommend the optimal model for a given trust score and task complexity.
|
|
42
|
-
*/
|
|
43
|
-
export function recommendModel(trustScore, complexity = 'standard', criticalFindings = 0) {
|
|
44
|
-
// Critical findings → require human review regardless of model
|
|
45
|
-
if (criticalFindings > 0) {
|
|
46
|
-
return {
|
|
47
|
-
model: 'sonnet',
|
|
48
|
-
modelId: MODEL_IDS.sonnet,
|
|
49
|
-
reason: `${criticalFindings} critical finding${criticalFindings !== 1 ? 's' : ''} — human review required before applying any edit`,
|
|
50
|
-
costPer1MTokens: MODEL_COSTS.sonnet,
|
|
51
|
-
savingsVsOpus: savingsLabel('sonnet'),
|
|
52
|
-
humanReview: true,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
// High-trust simple tasks → Haiku
|
|
56
|
-
if (trustScore >= 90 && complexity === 'simple') {
|
|
57
|
-
return {
|
|
58
|
-
model: 'haiku',
|
|
59
|
-
modelId: MODEL_IDS.haiku,
|
|
60
|
-
reason: `Trust ${trustScore}/100 · simple task — safe for fastest, cheapest model`,
|
|
61
|
-
costPer1MTokens: MODEL_COSTS.haiku,
|
|
62
|
-
savingsVsOpus: savingsLabel('haiku'),
|
|
63
|
-
humanReview: false,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
// Good trust, standard task → Sonnet
|
|
67
|
-
if (trustScore >= 75) {
|
|
68
|
-
return {
|
|
69
|
-
model: 'sonnet',
|
|
70
|
-
modelId: MODEL_IDS.sonnet,
|
|
71
|
-
reason: `Trust ${trustScore}/100 · ${complexity} task — Sonnet is the right balance`,
|
|
72
|
-
costPer1MTokens: MODEL_COSTS.sonnet,
|
|
73
|
-
savingsVsOpus: savingsLabel('sonnet'),
|
|
74
|
-
humanReview: false,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
// Low trust → Sonnet with human review
|
|
78
|
-
return {
|
|
79
|
-
model: 'sonnet',
|
|
80
|
-
modelId: MODEL_IDS.sonnet,
|
|
81
|
-
reason: `Trust ${trustScore}/100 — lower confidence; recommend reviewing the output`,
|
|
82
|
-
costPer1MTokens: MODEL_COSTS.sonnet,
|
|
83
|
-
savingsVsOpus: savingsLabel('sonnet'),
|
|
84
|
-
humanReview: true,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Estimate monthly savings from routing decisions.
|
|
89
|
-
* @param avgTokensPerTask Average output tokens per AI task
|
|
90
|
-
* @param tasksPerMonth Monthly task volume
|
|
91
|
-
* @param distribution Fraction of tasks at each tier
|
|
92
|
-
*/
|
|
93
|
-
export function estimateMonthlySavings(avgTokensPerTask = 2000, tasksPerMonth = 500, distribution = { haiku: 0.4, sonnet: 0.55, opus: 0.05 }) {
|
|
94
|
-
const tokensMillion = avgTokensPerTask / 1_000_000;
|
|
95
|
-
let routedCost = 0;
|
|
96
|
-
for (const [tier, fraction] of Object.entries(distribution)) {
|
|
97
|
-
routedCost += fraction * tasksPerMonth * tokensMillion * MODEL_COSTS[tier];
|
|
98
|
-
}
|
|
99
|
-
const opusCost = tasksPerMonth * tokensMillion * MODEL_COSTS.opus;
|
|
100
|
-
const saving = opusCost - routedCost;
|
|
101
|
-
const savingPct = (saving / opusCost) * 100;
|
|
102
|
-
return { routedCost, opusCost, saving, savingPct };
|
|
103
|
-
}
|
|
104
|
-
//# sourceMappingURL=cost-router.js.map
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v0.6 S3 slice 1 — spend-today aggregator.
|
|
3
|
-
*
|
|
4
|
-
* Reads ~/.codehere/sessions.jsonl (the same append-only log session-persistence
|
|
5
|
-
* writes), filters completed records to today (local timezone), and estimates
|
|
6
|
-
* dollar spend per agent based on token usage × per-tier output-rate ceilings.
|
|
7
|
-
*
|
|
8
|
-
* Why · claim_market_position v3 lists "cost-bounded execution" as one of the
|
|
9
|
-
* few capture-strategy edges still possibly open. Demonstrating cost awareness
|
|
10
|
-
* starts here: surface what the user has actually spent today across all spawned
|
|
11
|
-
* agents, then (slice 2) enforce a per-day ceiling.
|
|
12
|
-
*
|
|
13
|
-
* Why estimates not exact · codehere doesn't see provider invoices. Adapters
|
|
14
|
-
* report token counts via TaskArtifacts.usage; we multiply by published tier
|
|
15
|
-
* ceilings. Per feedback_overconfidence_guard.md, copy frames this as
|
|
16
|
-
* "estimate" and points to vendor dashboards as authoritative.
|
|
17
|
-
*
|
|
18
|
-
* Cost table · output-tier ceilings (input is rougher; we use a 5x ratio).
|
|
19
|
-
* All values 2026 published rates. When a model isn't surfaced in usage,
|
|
20
|
-
* default to the agent's typical tier.
|
|
21
|
-
*/
|
|
22
|
-
import { existsSync, readFileSync } from 'fs';
|
|
23
|
-
import { homedir } from 'os';
|
|
24
|
-
import { join } from 'path';
|
|
25
|
-
/** Resolved at call time, not module load, so test setups that swap $HOME
|
|
26
|
-
* after import still get a fresh path on each invocation. */
|
|
27
|
-
function sessionsFile() {
|
|
28
|
-
return join(process.env.CODEHERE_HOME || homedir(), '.codehere', 'sessions.jsonl');
|
|
29
|
-
}
|
|
30
|
-
/** USD per million OUTPUT tokens at the agent's typical 2026 tier. Input is
|
|
31
|
-
* estimated at 1/5 of output rate (Anthropic + OpenAI both publish ~5x
|
|
32
|
-
* output:input ratios on their flagship coding tiers). Cache reads ~1/10
|
|
33
|
-
* of input. Free-tier agents → 0.
|
|
34
|
-
*
|
|
35
|
-
* Conservative-ceiling philosophy: better to over-estimate spend than
|
|
36
|
-
* under-promise and miss a real bill. */
|
|
37
|
-
const COST_PER_M_OUTPUT_TOKENS_USD = {
|
|
38
|
-
'claude-code': 15.0, // Sonnet 4.6 baseline
|
|
39
|
-
codex: 10.0, // GPT-5 / codex baseline
|
|
40
|
-
aider: 15.0, // typically Sonnet
|
|
41
|
-
gemini: 0, // free tier (Google AI Studio)
|
|
42
|
-
opencode: 0, // typically free local / NIM-routed
|
|
43
|
-
conductor: 15.0, // routes to Claude Code by default
|
|
44
|
-
};
|
|
45
|
-
const INPUT_RATE_RATIO = 0.2; // input ≈ 1/5 of output
|
|
46
|
-
const CACHE_READ_RATIO = 0.1; // cache reads ≈ 1/10 of input (so 1/50 output)
|
|
47
|
-
/**
|
|
48
|
-
* Estimate dollar cost for one session's token usage at one agent's typical tier.
|
|
49
|
-
* Returns 0 for free-tier agents and unknown agents (no mapping → no estimate).
|
|
50
|
-
*/
|
|
51
|
-
export function estimateCostUsd(agent, usage) {
|
|
52
|
-
if (!usage)
|
|
53
|
-
return 0;
|
|
54
|
-
const outputRate = COST_PER_M_OUTPUT_TOKENS_USD[agent];
|
|
55
|
-
if (outputRate === undefined || outputRate === 0)
|
|
56
|
-
return 0;
|
|
57
|
-
const inputRate = outputRate * INPUT_RATE_RATIO;
|
|
58
|
-
const cacheReadRate = inputRate * CACHE_READ_RATIO;
|
|
59
|
-
// Cache CREATION is billed at input rate (Anthropic). Use same default.
|
|
60
|
-
const tokens = {
|
|
61
|
-
input: Math.max(0, usage.inputTokens || 0),
|
|
62
|
-
output: Math.max(0, usage.outputTokens || 0),
|
|
63
|
-
cacheRead: Math.max(0, usage.cacheReadTokens || 0),
|
|
64
|
-
cacheCreate: Math.max(0, usage.cacheCreationTokens || 0),
|
|
65
|
-
};
|
|
66
|
-
return ((tokens.input / 1_000_000) * inputRate +
|
|
67
|
-
(tokens.output / 1_000_000) * outputRate +
|
|
68
|
-
(tokens.cacheRead / 1_000_000) * cacheReadRate +
|
|
69
|
-
(tokens.cacheCreate / 1_000_000) * inputRate);
|
|
70
|
-
}
|
|
71
|
-
/** Return the millisecond timestamp for the start of "today" in local time. */
|
|
72
|
-
function startOfTodayLocalMs(now = new Date()) {
|
|
73
|
-
const d = new Date(now);
|
|
74
|
-
d.setHours(0, 0, 0, 0);
|
|
75
|
-
return d.getTime();
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Walk sessions.jsonl, sum estimated USD spend for sessions whose
|
|
79
|
-
* `completedAt` falls within today (local). Best-effort: missing file =
|
|
80
|
-
* empty report; parse errors per-line ignored. Pairs spawned + completed
|
|
81
|
-
* by id so we know which agent spent what.
|
|
82
|
-
*/
|
|
83
|
-
export function computeSpendToday(now = new Date()) {
|
|
84
|
-
const cutoff = startOfTodayLocalMs(now);
|
|
85
|
-
const empty = {
|
|
86
|
-
totalUsd: 0,
|
|
87
|
-
tokens: { input: 0, output: 0, cache: 0 },
|
|
88
|
-
sessionCount: 0,
|
|
89
|
-
byAgent: {},
|
|
90
|
-
windowStartedAt: cutoff,
|
|
91
|
-
};
|
|
92
|
-
if (!existsSync(sessionsFile()))
|
|
93
|
-
return empty;
|
|
94
|
-
let content;
|
|
95
|
-
try {
|
|
96
|
-
content = readFileSync(sessionsFile(), 'utf-8');
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return empty;
|
|
100
|
-
}
|
|
101
|
-
// Pair spawned (carries agent) with completed (carries usage + completedAt).
|
|
102
|
-
const spawnedAgent = new Map();
|
|
103
|
-
const report = { ...empty, byAgent: {} };
|
|
104
|
-
for (const line of content.split('\n')) {
|
|
105
|
-
const trimmed = line.trim();
|
|
106
|
-
if (!trimmed)
|
|
107
|
-
continue;
|
|
108
|
-
let rec;
|
|
109
|
-
try {
|
|
110
|
-
rec = JSON.parse(trimmed);
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (rec.t === 'spawned' && rec.id && rec.agent) {
|
|
116
|
-
spawnedAgent.set(rec.id, rec.agent);
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (rec.t !== 'completed' || !rec.id)
|
|
120
|
-
continue;
|
|
121
|
-
if (typeof rec.completedAt !== 'number' || rec.completedAt < cutoff)
|
|
122
|
-
continue;
|
|
123
|
-
const agent = spawnedAgent.get(rec.id);
|
|
124
|
-
if (!agent)
|
|
125
|
-
continue;
|
|
126
|
-
const usage = rec.artifacts?.usage;
|
|
127
|
-
const usd = estimateCostUsd(agent, usage);
|
|
128
|
-
report.sessionCount += 1;
|
|
129
|
-
if (usage) {
|
|
130
|
-
report.tokens.input += usage.inputTokens || 0;
|
|
131
|
-
report.tokens.output += usage.outputTokens || 0;
|
|
132
|
-
report.tokens.cache += (usage.cacheReadTokens || 0) + (usage.cacheCreationTokens || 0);
|
|
133
|
-
}
|
|
134
|
-
report.totalUsd += usd;
|
|
135
|
-
const cur = report.byAgent[agent] || { usd: 0, sessions: 0 };
|
|
136
|
-
cur.usd += usd;
|
|
137
|
-
cur.sessions += 1;
|
|
138
|
-
report.byAgent[agent] = cur;
|
|
139
|
-
}
|
|
140
|
-
// Round totals to 4 decimals (1/100 of a cent) — final display rounds to 2.
|
|
141
|
-
report.totalUsd = Math.round(report.totalUsd * 10_000) / 10_000;
|
|
142
|
-
for (const k of Object.keys(report.byAgent)) {
|
|
143
|
-
report.byAgent[k].usd = Math.round(report.byAgent[k].usd * 10_000) / 10_000;
|
|
144
|
-
}
|
|
145
|
-
return report;
|
|
146
|
-
}
|
|
147
|
-
//# sourceMappingURL=spend-aggregator.js.map
|