Skip to content

cost: estimateNeurons is duplicated 4x and the copies drop the calls multiplier, under-reporting AI spend #10169

Description

@JSONbored

estimateNeurons exists four times and has already drifted

src/services/ai-review.ts exports the canonical implementation:

export function estimateNeurons(promptChars: number, maxOutputTokens: number, calls: number): number {
  const inputTokens = Math.ceil(promptChars / 4);
  return Math.max(1, Math.ceil((inputTokens + maxOutputTokens) * 0.035) * Math.max(1, calls));
}

Three other services define a private copy that drops the calls multiplier:

// ai-chat-qa.ts, ai-summaries.ts, ai-intent-router.ts — identical to each other, all private
function estimateNeurons(prompt: string, maxOutputTokens: number): number {
  const inputTokens = Math.ceil(prompt.length / 4);
  return Math.max(1, Math.ceil((inputTokens + maxOutputTokens) * 0.035));
}

Same formula, different arity, and the exported one is right there to import.

This under-reports real spend

ai-chat-qa.ts:158 retries the provider call:

for (let attempt = 0; attempt < 2 && !rawText; attempt += 1) {

Two provider calls, one call's worth of neurons recorded. The figure lands in ai_usage_events.estimated_neurons, which is what cost tracking reads and what the daily neuron-budget backstop (#budget-no-starve) compares against — so a runaway-loop guard is reading a number that is too small by exactly the factor that would indicate a runaway loop.

ai-summaries.ts and ai-intent-router.ts each call theirs from more than one site as well.

Fix

Delete the three private copies and import the exported one, passing the actual call count. The signatures differ (prompt: string vs promptChars: number), so each call site becomes estimateNeurons(text.length, maxTokens, calls).

Why it is worth doing beyond the arithmetic

extractAiText is duplicated across the same three files too. This is a cluster of copy-paste from one service to the next, and the drift is already visible: the version that got a needed third parameter is the one that stayed put, while the copies did not follow. Whichever service is written next will copy whichever neighbour is nearest.

Found during the maintainability audit; see the umbrella issue for the wider duplication survey.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions