import type { StreamFn } from "@mariozechner/pi-agent-core"; import type { Api, Model, SimpleStreamOptions } from "@mariozechner/pi-ai"; import { streamSimple } from "@mariozechner/pi-ai"; import type { ClawdbotConfig } from "../../config/config.js"; import { log } from "./logger.js"; /** * Resolve provider-specific extra params from model config. * Used to pass through stream params like temperature/maxTokens. * * @internal Exported for testing only */ export function resolveExtraParams(params: { cfg: ClawdbotConfig | undefined; provider: string; modelId: string; }): Record | undefined { const modelKey = `${params.provider}/${params.modelId}`; const modelConfig = params.cfg?.agents?.defaults?.models?.[modelKey]; return modelConfig?.params ? { ...modelConfig.params } : undefined; } function createStreamFnWithExtraParams( baseStreamFn: StreamFn | undefined, extraParams: Record | undefined, ): StreamFn | undefined { if (!extraParams || Object.keys(extraParams).length === 0) { return undefined; } const streamParams: Partial = {}; if (typeof extraParams.temperature === "number") { streamParams.temperature = extraParams.temperature; } if (typeof extraParams.maxTokens === "number") { streamParams.maxTokens = extraParams.maxTokens; } if (Object.keys(streamParams).length === 0) { return undefined; } log.debug(`creating streamFn wrapper with params: ${JSON.stringify(streamParams)}`); const underlying = baseStreamFn ?? streamSimple; const wrappedStreamFn: StreamFn = (model, context, options) => underlying(model as Model, context, { ...streamParams, ...options, }); return wrappedStreamFn; } /** * Apply extra params (like temperature) to an agent's streamFn. * * @internal Exported for testing */ export function applyExtraParamsToAgent( agent: { streamFn?: StreamFn }, cfg: ClawdbotConfig | undefined, provider: string, modelId: string, ): void { const extraParams = resolveExtraParams({ cfg, provider, modelId, }); const wrappedStreamFn = createStreamFnWithExtraParams(agent.streamFn, extraParams); if (wrappedStreamFn) { log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`); agent.streamFn = wrappedStreamFn; } }