UNPKG

assistant-cloud

Version:

Cloud integration for assistant-ui

75 lines (74 loc) • 2.65 kB
// src/instrumentMcpSampling.ts const reportSamplingError = (error) => { try { console.error("[assistant-cloud] onSamplingCall callback threw an error", error); } catch {} }; /** * Wraps an MCP sampling handler to intercept and measure sampling calls. * * @param handler - The original sampling handler from the MCP client * @param onSamplingCall - Callback invoked with metrics for each sampling call * @returns A wrapped handler that transparently captures sampling metrics * * @example * ```ts * const samplingCalls: SamplingCallData[] = []; * const wrapped = wrapSamplingHandler( * originalHandler, * (data) => samplingCalls.push(data), * ); * // Use `wrapped` as the MCP client's sampling handler * // After tool execution, `samplingCalls` contains metrics for all nested LLM calls * ``` */ function wrapSamplingHandler(handler, onSamplingCall) { return async (request) => { const startTime = Date.now(); const response = await handler(request); const durationMs = Date.now() - startTime; const modelId = response.model ?? request.params.modelPreferences?.hints?.[0]?.name; const inputTokens = response.usage?.inputTokens ?? response.usage?.promptTokens; const outputTokens = response.usage?.outputTokens ?? response.usage?.completionTokens; const reasoningTokens = response.usage?.reasoningTokens; const cachedInputTokens = response.usage?.cachedInputTokens; const data = { ...modelId ? { model_id: modelId } : void 0, ...inputTokens != null ? { input_tokens: inputTokens } : void 0, ...outputTokens != null ? { output_tokens: outputTokens } : void 0, ...reasoningTokens != null ? { reasoning_tokens: reasoningTokens } : void 0, ...cachedInputTokens != null ? { cached_input_tokens: cachedInputTokens } : void 0, duration_ms: durationMs }; try { Promise.resolve(onSamplingCall(data)).catch(reportSamplingError); } catch (error) { reportSamplingError(error); } return response; }; } /** * Creates a collector that accumulates sampling call data during tool execution. * Use with `wrapSamplingHandler` to capture all sampling calls for a tool invocation. * * @example * ```ts * const collector = createSamplingCollector(); * const wrappedHandler = wrapSamplingHandler(handler, collector.collect); * // ... execute MCP tool ... * const calls = collector.getCalls(); // SamplingCallData[] * ``` */ function createSamplingCollector() { const calls = []; return { collect: (data) => calls.push(data), getCalls: () => [...calls], reset: () => { calls.length = 0; } }; } export { createSamplingCollector, wrapSamplingHandler }; //# sourceMappingURL=instrumentMcpSampling.js.map