|
4 | 4 | * Selects models, wires built-in/custom tools, loads resources, and creates AgentSession instances. |
5 | 5 | */ |
6 | 6 | import { join } from "node:path"; |
7 | | -import { resolveThinkingDefaultForModel } from "../../auto-reply/thinking.js"; |
| 7 | +import { |
| 8 | + resolveThinkingDefaultForModel, |
| 9 | + type ThinkingCatalogEntry, |
| 10 | +} from "../../auto-reply/thinking.js"; |
8 | 11 | import { clampThinkingLevel } from "../../llm/model-utils.js"; |
9 | 12 | import { streamSimple } from "../../llm/stream.js"; |
10 | 13 | import type { Message, Model } from "../../llm/types.js"; |
@@ -42,6 +45,28 @@ import { |
42 | 45 | withFileMutationQueue, |
43 | 46 | } from "./tools/index.js"; |
44 | 47 |
|
| 48 | +type ThinkingCatalogCompat = NonNullable<ThinkingCatalogEntry["compat"]>; |
| 49 | + |
| 50 | +function projectThinkingCatalogCompat(compat: Model["compat"]) { |
| 51 | + if (!compat || typeof compat !== "object") { |
| 52 | + return undefined; |
| 53 | + } |
| 54 | + const record = compat as Record<string, unknown>; |
| 55 | + const projected: ThinkingCatalogCompat = {}; |
| 56 | + if (typeof record.thinkingFormat === "string") { |
| 57 | + projected.thinkingFormat = record.thinkingFormat; |
| 58 | + } |
| 59 | + if (record.supportedReasoningEfforts === null) { |
| 60 | + projected.supportedReasoningEfforts = null; |
| 61 | + } else if ( |
| 62 | + Array.isArray(record.supportedReasoningEfforts) && |
| 63 | + record.supportedReasoningEfforts.every((effort) => typeof effort === "string") |
| 64 | + ) { |
| 65 | + projected.supportedReasoningEfforts = record.supportedReasoningEfforts; |
| 66 | + } |
| 67 | + return Object.keys(projected).length > 0 ? projected : undefined; |
| 68 | +} |
| 69 | + |
45 | 70 | export interface CreateAgentSessionOptions { |
46 | 71 | /** Working directory for project-local discovery. Default: process.cwd() */ |
47 | 72 | cwd?: string; |
@@ -272,13 +297,25 @@ export async function createAgentSession( |
272 | 297 | // Use "off" when a provider explicitly opts out of thinking (e.g. Ollama). Non-off |
273 | 298 | // provider defaults (high, low, adaptive) fall back to DEFAULT_THINKING_LEVEL to avoid |
274 | 299 | // silent cost changes for DeepSeek, OpenRouter, xAI, and other providers. |
275 | | - const resolvedProviderDefault = model |
276 | | - ? resolveThinkingDefaultForModel({ |
277 | | - provider: model.api === "ollama" ? "ollama" : model.provider, |
278 | | - model: model.id, |
279 | | - catalog: [model], |
280 | | - }) |
281 | | - : undefined; |
| 300 | + const modelThinkingProvider = model?.api === "ollama" ? "ollama" : model?.provider; |
| 301 | + const modelThinkingCompat = model ? projectThinkingCatalogCompat(model.compat) : undefined; |
| 302 | + const resolvedProviderDefault = |
| 303 | + model && modelThinkingProvider |
| 304 | + ? resolveThinkingDefaultForModel({ |
| 305 | + provider: modelThinkingProvider, |
| 306 | + model: model.id, |
| 307 | + catalog: [ |
| 308 | + { |
| 309 | + provider: modelThinkingProvider, |
| 310 | + id: model.id, |
| 311 | + api: model.api, |
| 312 | + reasoning: model.reasoning, |
| 313 | + ...(model.params ? { params: model.params } : {}), |
| 314 | + ...(modelThinkingCompat ? { compat: modelThinkingCompat } : {}), |
| 315 | + }, |
| 316 | + ], |
| 317 | + }) |
| 318 | + : undefined; |
282 | 319 | const modelThinkingDefault: ThinkingLevel = |
283 | 320 | resolvedProviderDefault === "off" ? "off" : DEFAULT_THINKING_LEVEL; |
284 | 321 |
|
|
0 commit comments