| import type { StreamFn } from "@mariozechner/pi-agent-core"; |
| import type { SimpleStreamOptions } from "@mariozechner/pi-ai"; |
| import { streamSimple } from "@mariozechner/pi-ai"; |
|
|
| import type { OpenClawConfig } from "../../config/config.js"; |
| import { log } from "./logger.js"; |
|
|
| |
| |
| |
| |
| |
| |
| export function resolveExtraParams(params: { |
| cfg: OpenClawConfig | undefined; |
| provider: string; |
| modelId: string; |
| }): Record<string, unknown> | undefined { |
| const modelKey = `${params.provider}/${params.modelId}`; |
| const modelConfig = params.cfg?.agents?.defaults?.models?.[modelKey]; |
| return modelConfig?.params ? { ...modelConfig.params } : undefined; |
| } |
|
|
| type CacheControlTtl = "5m" | "1h"; |
|
|
| function resolveCacheControlTtl( |
| extraParams: Record<string, unknown> | undefined, |
| provider: string, |
| modelId: string, |
| ): CacheControlTtl | undefined { |
| const raw = extraParams?.cacheControlTtl; |
| if (raw !== "5m" && raw !== "1h") { |
| return undefined; |
| } |
| if (provider === "anthropic") { |
| return raw; |
| } |
| if (provider === "openrouter" && modelId.startsWith("anthropic/")) { |
| return raw; |
| } |
| return undefined; |
| } |
|
|
| function createStreamFnWithExtraParams( |
| baseStreamFn: StreamFn | undefined, |
| extraParams: Record<string, unknown> | undefined, |
| provider: string, |
| modelId: string, |
| ): StreamFn | undefined { |
| if (!extraParams || Object.keys(extraParams).length === 0) { |
| return undefined; |
| } |
|
|
| const streamParams: Partial<SimpleStreamOptions> & { cacheControlTtl?: CacheControlTtl } = {}; |
| if (typeof extraParams.temperature === "number") { |
| streamParams.temperature = extraParams.temperature; |
| } |
| if (typeof extraParams.maxTokens === "number") { |
| streamParams.maxTokens = extraParams.maxTokens; |
| } |
| const cacheControlTtl = resolveCacheControlTtl(extraParams, provider, modelId); |
| if (cacheControlTtl) { |
| streamParams.cacheControlTtl = cacheControlTtl; |
| } |
|
|
| 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, context, { |
| ...streamParams, |
| ...options, |
| }); |
|
|
| return wrappedStreamFn; |
| } |
|
|
| |
| |
| |
| |
| |
| export function applyExtraParamsToAgent( |
| agent: { streamFn?: StreamFn }, |
| cfg: OpenClawConfig | undefined, |
| provider: string, |
| modelId: string, |
| extraParamsOverride?: Record<string, unknown>, |
| ): void { |
| const extraParams = resolveExtraParams({ |
| cfg, |
| provider, |
| modelId, |
| }); |
| const override = |
| extraParamsOverride && Object.keys(extraParamsOverride).length > 0 |
| ? Object.fromEntries( |
| Object.entries(extraParamsOverride).filter(([, value]) => value !== undefined), |
| ) |
| : undefined; |
| const merged = Object.assign({}, extraParams, override); |
| const wrappedStreamFn = createStreamFnWithExtraParams(agent.streamFn, merged, provider, modelId); |
|
|
| if (wrappedStreamFn) { |
| log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`); |
| agent.streamFn = wrappedStreamFn; |
| } |
| } |
|
|