import type { JsonValue } from "agentlens-sdk"; export function truncate(str: string, maxLength: number): string { if (str.length <= maxLength) return str; return str.slice(0, maxLength) + "... [truncated]"; } export function extractToolMetadata( tool: string, args: unknown, ): Record { const a = args as Record | null | undefined; if (!a || typeof a !== "object") return {}; switch (tool) { case "read": case "mcp_read": return { filePath: a["filePath"] }; case "write": case "mcp_write": return { filePath: a["filePath"] }; case "edit": case "mcp_edit": return { filePath: a["filePath"] }; case "bash": case "mcp_bash": return { command: truncate(String(a["command"] ?? ""), 200), }; case "glob": case "mcp_glob": return { pattern: a["pattern"] }; case "grep": case "mcp_grep": return { pattern: a["pattern"], path: a["path"] }; case "task": case "mcp_task": return { category: a["category"], description: a["description"], }; default: return {}; } } const MODEL_COSTS: Record = { "gpt-5.2": { input: 1.75, output: 14 }, "gpt-5.1": { input: 1.25, output: 10 }, "gpt-5": { input: 1.25, output: 10 }, "gpt-5-mini": { input: 0.25, output: 2 }, "gpt-5-nano": { input: 0.05, output: 0.4 }, "gpt-4.1": { input: 2, output: 8 }, "gpt-4.1-mini": { input: 0.4, output: 1.6 }, "gpt-4.1-nano": { input: 0.1, output: 0.4 }, "o3": { input: 2, output: 8 }, "o3-mini": { input: 1.1, output: 4.4 }, "o4-mini": { input: 1.1, output: 4.4 }, "o1": { input: 15, output: 60 }, "gpt-4o": { input: 2.5, output: 10 }, "gpt-4o-mini": { input: 0.15, output: 0.6 }, "gpt-4-turbo": { input: 10, output: 30 }, "gpt-4": { input: 30, output: 60 }, "claude-opus-4-6": { input: 5, output: 25 }, "claude-opus-4-20250514": { input: 15, output: 75 }, "claude-sonnet-4-20250514": { input: 3, output: 15 }, "claude-4.5-opus": { input: 5, output: 25 }, "claude-4.5-sonnet": { input: 3, output: 15 }, "claude-4.5-haiku": { input: 1, output: 5 }, "claude-3-5-sonnet": { input: 3, output: 15 }, "claude-3-5-haiku": { input: 0.8, output: 4 }, "claude-3-opus": { input: 15, output: 75 }, "claude-3-haiku": { input: 0.25, output: 1.25 }, }; export function getModelCost( modelId: string, ): { input: number; output: number } | undefined { const direct = MODEL_COSTS[modelId]; if (direct) return direct; for (const [key, cost] of Object.entries(MODEL_COSTS)) { if (modelId.includes(key)) return cost; } return undefined; } /** Coerce arbitrary values into SDK-compatible `JsonValue`, stringifying unknowns. */ export function safeJsonValue(value: unknown): JsonValue { if (value === null || value === undefined) return null; if ( typeof value === "string" || typeof value === "number" || typeof value === "boolean" ) { return value; } if (Array.isArray(value)) { return value.map((v) => safeJsonValue(v)); } if (typeof value === "object") { const result: Record = {}; for (const [k, v] of Object.entries(value as Record)) { result[k] = safeJsonValue(v); } return result; } return String(value); }