import type { McpTool,OpenApiEndpoint } from "./types"; export type BenchmarkTask={operation_id:string;arguments:Record}; function tokens(value:unknown){return Math.ceil(JSON.stringify(value).length/4);} function required(schema:unknown){return schema&&typeof schema==="object"&&Array.isArray((schema as Record).required)?(schema as Record).required as string[]:[];} export function benchmarkSemanticCompression(endpoints:OpenApiEndpoint[],tools:McpTool[],tasks:BenchmarkTask[]=[]){const started=performance.now();const rawTokens=tokens(endpoints.map((e)=>({method:e.method,path:e.path,parameters:e.parameters,request_body:e.request_body,description:e.description})));const directTokens=tokens(tools.map((t)=>({name:t.name,description:t.description,input_schema:t.input_schema})));const modes=[{mode:"raw_1_to_1",schema_tokens:rawTokens,tools:endpoints.length},{mode:"direct_tools",schema_tokens:directTokens,tools:tools.length},{mode:"catalog",schema_tokens:tokens({tools:["list_api_endpoints","get_api_endpoint_schema","invoke_api_endpoint"]}),tools:3},{mode:"code",schema_tokens:tokens({tools:["search_docs","execute"]}),tools:2}];return {measured_at:new Date().toISOString(),target_savings_percent:"70-75",claim_verified:false,results:modes.map((mode)=>{const modeStarted=performance.now();const selected=tasks.filter((task)=>endpoints.some((e)=>e.operation_id===task.operation_id));const valid=selected.filter((task)=>{const endpoint=endpoints.find((e)=>e.operation_id===task.operation_id);return required(endpoint?.input_schema).every((key)=>key in task.arguments);});return {...mode,schema_token_savings_percent:rawTokens?Number(((1-mode.schema_tokens/rawTokens)*100).toFixed(1)):0,tool_choice_accuracy:tasks.length?selected.length/tasks.length:null,argument_validity:tasks.length?valid.length/tasks.length:null,task_success:tasks.length?valid.length/tasks.length:null,latency_ms:Number((performance.now()-modeStarted).toFixed(3))};}),benchmark_latency_ms:Number((performance.now()-started).toFixed(3)),note:"Token counts use a deterministic four-characters-per-token estimate. Accuracy, validity, and task success require representative task fixtures; latency measures this local benchmark evaluation. No savings claim is made automatically."};}