/** * Tool Token Utilities * * Functions for estimating and calculating token counts for tool operations. */ import { estimateTokens } from '@shared/utils/tokenFormatting'; import type { ItemStatus } from '@renderer/components/chat/items/BaseItem';import type { LinkedToolItem } from '@renderer/types/groups'; /** * Calculates total context tokens consumed by a tool operation. */export function getToolContextTokens(linkedTool: LinkedToolItem): number { let totalTokens = 0; // Tool CALL tokens (what Claude generated) if (linkedTool.callTokens !== undefined) { totalTokens += linkedTool.callTokens; } else { // Fallback: estimate from input totalTokens += estimateTokens(JSON.stringify(linkedTool.input)); } // Tool RESULT tokens (what Claude reads back) if (linkedTool.result?.tokenCount !== undefined) { totalTokens += linkedTool.result.tokenCount; } else if (linkedTool.result?.content) { const content = linkedTool.result.content; if (typeof content === 'string') { totalTokens += estimateTokens(content); } else if (Array.isArray(content)) { totalTokens += estimateTokens(JSON.stringify(content)); } } // For Skill tools, also add skill instructions tokens if (linkedTool.name === 'Skill') { if (linkedTool.skillInstructionsTokenCount !== undefined) { totalTokens += linkedTool.skillInstructionsTokenCount; } else if (linkedTool.skillInstructions) { totalTokens += estimateTokens(linkedTool.skillInstructions); } } return totalTokens;} /** * Gets the status of a tool execution. */export function getToolStatus(linkedTool: LinkedToolItem): ItemStatus { if (linkedTool.isOrphaned) return 'orphaned'; if (linkedTool.result?.isError) return 'error'; return 'ok';}
/**
* Tool Token Utilities
*
* Functions for estimating and calculating token counts for tool operations.
*/
import { estimateTokens } from '@shared/utils/tokenFormatting';
import type { ItemStatus } from '@renderer/components/chat/items/BaseItem';
import type { LinkedToolItem } from '@renderer/types/groups';
/**
* Calculates total context tokens consumed by a tool operation.
*/
export function getToolContextTokens(linkedTool: LinkedToolItem): number {
let totalTokens = 0;
// Tool CALL tokens (what Claude generated)
if (linkedTool.callTokens !== undefined) {
totalTokens += linkedTool.callTokens;
} else {
// Fallback: estimate from input
totalTokens += estimateTokens(JSON.stringify(linkedTool.input));
}
// Tool RESULT tokens (what Claude reads back)
if (linkedTool.result?.tokenCount !== undefined) {
totalTokens += linkedTool.result.tokenCount;
} else if (linkedTool.result?.content) {
const content = linkedTool.result.content;
if (typeof content === 'string') {
totalTokens += estimateTokens(content);
} else if (Array.isArray(content)) {
totalTokens += estimateTokens(JSON.stringify(content));
}
}
// For Skill tools, also add skill instructions tokens
if (linkedTool.name === 'Skill') {
if (linkedTool.skillInstructionsTokenCount !== undefined) {
totalTokens += linkedTool.skillInstructionsTokenCount;
} else if (linkedTool.skillInstructions) {
totalTokens += estimateTokens(linkedTool.skillInstructions);
}
}
return totalTokens;
}
/**
* Gets the status of a tool execution.
*/
export function getToolStatus(linkedTool: LinkedToolItem): ItemStatus {
if (linkedTool.isOrphaned) return 'orphaned';
if (linkedTool.result?.isError) return 'error';
return 'ok';
}