kiku-agent 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,31 @@
1
- export const CLOUD_PROVIDERS = {
1
+ const PROVIDER_MODEL_ALIASES = {
2
+ openai: {
3
+ 'o1-mini': 'gpt-5.6-luna',
4
+ 'o3-mini': 'gpt-5.6-luna',
5
+ },
6
+ openrouter: {
7
+ auto: 'openrouter/auto',
8
+ },
9
+ groq: {
10
+ 'gpt-oss-120b': 'openai/gpt-oss-120b',
11
+ 'gpt-oss-20b': 'openai/gpt-oss-20b',
12
+ },
13
+ deepseek: {
14
+ 'deepseek-chat': 'deepseek-v4-flash',
15
+ 'deepseek-reasoner': 'deepseek-v4-flash',
16
+ },
17
+ gemini: {
18
+ 'gemini-3.1-pro': 'gemini-3.1-pro-preview',
19
+ },
20
+ };
21
+
22
+ export function normalizeProviderModel(providerId, modelId) {
23
+ const normalizedProvider = String(providerId || '').toLowerCase().trim();
24
+ const normalizedModel = String(modelId || '').trim();
25
+ return PROVIDER_MODEL_ALIASES[normalizedProvider]?.[normalizedModel] || normalizedModel;
26
+ }
27
+
28
+ export const CLOUD_PROVIDERS = {
2
29
  lmstudio: {
3
30
  id: 'lmstudio',
4
31
  name: 'LM Studio (Local)',
@@ -23,18 +50,17 @@ export const CLOUD_PROVIDERS = {
23
50
  name: 'OpenAI Cloud',
24
51
  baseUrl: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1',
25
52
  apiKey: process.env.OPENAI_API_KEY || '',
26
- defaultModel: process.env.OPENAI_MODEL || 'gpt-4o-mini',
53
+ defaultModel: normalizeProviderModel('openai', process.env.OPENAI_MODEL || 'gpt-5.6-luna'),
27
54
  isLocal: false,
28
55
  envKey: 'OPENAI_API_KEY',
29
- docUrl: 'https://platform.openai.com/docs',
30
- apiRefUrl: 'https://platform.openai.com/docs/api-reference',
31
- pricingSummary: 'Pay-per-token (gpt-4o-mini: ~$0.15/1M in, $0.60/1M out)',
56
+ docUrl: 'https://developers.openai.com/api/docs/models',
57
+ apiRefUrl: 'https://developers.openai.com/api/reference',
58
+ pricingSummary: 'GPT-5.6 Luna: $0.20/1M in, $1.20/1M out; Terra/Sol available for higher capability',
32
59
  features: ['tools', 'streaming', 'vision', 'reasoning', 'system-prompt'],
33
60
  recommendedModels: [
34
- { id: 'gpt-4o-mini', name: 'GPT-4o Mini', tier: 'ultra-cheap', cost: '$0.15 / 1M in', context: '128k', hasTools: true, description: 'Recommended default. Fast, intelligent, and highly cost-effective with tool use.' },
35
- { id: 'gpt-4o', name: 'GPT-4o', tier: 'flagship', cost: '$2.50 / 1M in', context: '128k', hasTools: true, description: 'OpenAI flagship multimodal model for complex multimodal & reasoning tasks.' },
36
- { id: 'o3-mini', name: 'o3 Mini', tier: 'reasoning', cost: '$1.10 / 1M in', context: '200k', hasTools: true, description: 'Fast, cost-efficient reasoning model with function calling capabilities.' },
37
- { id: 'o1-mini', name: 'o1 Mini', tier: 'reasoning', cost: '$1.10 / 1M in', context: '128k', hasTools: true, description: 'Reasoning model specialized for complex STEM logic and coding.' },
61
+ { id: 'gpt-5.6-luna', name: 'GPT-5.6 Luna', tier: 'cost-sensitive', cost: '$0.20 / 1M in', context: '1.05M', hasTools: true, description: 'Recommended default for efficient, high-volume multilingual agent workloads.' },
62
+ { id: 'gpt-5.6-terra', name: 'GPT-5.6 Terra', tier: 'balanced', cost: '$2.00 / 1M in', context: '1.05M', hasTools: true, description: 'Balances intelligence and cost for production reasoning and tool use.' },
63
+ { id: 'gpt-5.6-sol', name: 'GPT-5.6 Sol', tier: 'flagship', cost: '$4.00 / 1M in', context: '1.05M', hasTools: true, description: 'Flagship model for complex professional reasoning and coding.' },
38
64
  ],
39
65
  },
40
66
  openrouter: {
@@ -42,62 +68,53 @@ export const CLOUD_PROVIDERS = {
42
68
  name: 'OpenRouter Cloud',
43
69
  baseUrl: process.env.OPENROUTER_BASE_URL || 'https://openrouter.ai/api/v1',
44
70
  apiKey: process.env.OPENROUTER_API_KEY || '',
45
- defaultModel: process.env.OPENROUTER_MODEL || 'google/gemini-2.5-flash',
46
- extraHeaders: {
47
- 'HTTP-Referer': 'https://jujingyi-kikuuu.vercel.app/',
48
- 'X-Title': 'Kiku Agent',
49
- },
71
+ defaultModel: normalizeProviderModel('openrouter', process.env.OPENROUTER_MODEL || 'openrouter/auto'),
72
+ extraHeaders: {
73
+ 'HTTP-Referer': 'https://jujingyi-kikuuu.vercel.app/',
74
+ 'X-OpenRouter-Title': 'Kiku Agent',
75
+ },
50
76
  isLocal: false,
51
77
  envKey: 'OPENROUTER_API_KEY',
52
- docUrl: 'https://openrouter.ai/docs/quick-start',
53
- apiRefUrl: 'https://openrouter.ai/docs/api_reference/overview',
54
- pricingSummary: 'Universal aggregator with free tiers & flexible pay-as-you-go',
78
+ docUrl: 'https://openrouter.ai/docs/guides/routing/routers/auto-router',
79
+ apiRefUrl: 'https://openrouter.ai/docs/api/reference/overview',
80
+ pricingSummary: 'Auto Router selects a current model dynamically; usage is billed at the routed model rate',
55
81
  features: ['universal-routing', 'tools', 'streaming', 'free-tier', 'fallback'],
56
82
  recommendedModels: [
57
- { id: 'google/gemini-2.5-flash', name: 'Gemini 2.5 Flash', tier: 'ultra-cheap', cost: '$0.10 / 1M in', context: '1M', hasTools: true, description: 'Super fast with huge 1M context window and native function calling.' },
58
- { id: 'deepseek/deepseek-chat', name: 'DeepSeek Chat (V3)', tier: 'ultra-cheap', cost: '$0.14 / 1M in', context: '64k', hasTools: true, description: 'DeepSeek-V3 671B MoE via OpenRouter at ultra-low price.' },
59
- { id: 'deepseek/deepseek-r1', name: 'DeepSeek Reasoner (R1)', tier: 'reasoning', cost: '$0.55 / 1M in', context: '64k', hasTools: false, description: 'Full DeepSeek-R1 reasoning with Chain-of-Thought output.' },
60
- { id: 'meta-llama/llama-3.3-70b-instruct', name: 'Llama 3.3 70B Instruct', tier: 'balanced', cost: '$0.40 / 1M in', context: '128k', hasTools: true, description: 'State-of-the-art open-weights flagship model.' },
61
- { id: 'openai/gpt-4o-mini', name: 'GPT-4o Mini', tier: 'ultra-cheap', cost: '$0.15 / 1M in', context: '128k', hasTools: true, description: 'OpenAI mini model routed via OpenRouter.' },
62
- { id: 'qwen/qwen-2.5-72b-instruct', name: 'Qwen 2.5 72B Instruct', tier: 'balanced', cost: '$0.35 / 1M in', context: '128k', hasTools: true, description: 'Top-tier open-weights multilingual and coding model.' },
63
- { id: 'meta-llama/llama-3.1-8b-instruct:free', name: 'Llama 3.1 8B (Free)', tier: 'free', cost: '$0.00', context: '128k', hasTools: true, description: 'Free tier Llama 3.1 8B on OpenRouter.' },
83
+ { id: 'openrouter/auto', name: 'OpenRouter Auto Router', tier: 'dynamic', cost: 'Routed model rate', context: 'Model-dependent', hasTools: true, description: 'Recommended default. Chooses from the current catalog so a retired third-party model does not break startup.' },
64
84
  ],
65
85
  },
66
- groq: {
86
+ groq: {
67
87
  id: 'groq',
68
88
  name: 'Groq Cloud',
69
89
  baseUrl: process.env.GROQ_BASE_URL || 'https://api.groq.com/openai/v1',
70
90
  apiKey: process.env.GROQ_API_KEY || '',
71
- defaultModel: process.env.GROQ_MODEL || 'llama-3.3-70b-versatile',
91
+ defaultModel: normalizeProviderModel('groq', process.env.GROQ_MODEL || 'openai/gpt-oss-120b'),
72
92
  isLocal: false,
73
93
  envKey: 'GROQ_API_KEY',
74
94
  docUrl: 'https://console.groq.com/docs/quickstart',
75
95
  apiRefUrl: 'https://console.groq.com/docs/api-reference',
76
- pricingSummary: 'Ultra-fast LPU inference (llama-3.1-8b: $0.05/1M, llama-3.3-70b: $0.59/1M)',
96
+ pricingSummary: 'Ultra-fast LPU inference (GPT-OSS 20B: $0.075/1M in, GPT-OSS 120B: $0.15/1M in)',
77
97
  features: ['lpu-speed', 'tools', 'streaming', 'openai-compatible'],
78
- recommendedModels: [
79
- { id: 'llama-3.3-70b-versatile', name: 'Llama 3.3 70B Versatile', tier: 'balanced', cost: '$0.59 / 1M in', context: '128k', hasTools: true, description: 'Recommended default. 70B flagship quality with fast LPU speed and tool use.' },
80
- { id: 'llama-3.1-8b-instant', name: 'Llama 3.1 8B Instant', tier: 'ultra-cheap', cost: '$0.05 / 1M in', context: '128k', hasTools: true, description: 'Blazing fast (~800 tokens/s) and ultra-low cost for quick inquiries.' },
81
- { id: 'gpt-oss-120b', name: 'GPT-OSS 120B', tier: 'balanced', cost: '$0.59 / 1M in', context: '128k', hasTools: true, description: 'Open-weights 120B flagship model running with ultra-fast Groq LPU inference.' },
82
- { id: 'mixtral-8x7b-32768', name: 'Mixtral 8x7B', tier: 'cheap', cost: '$0.24 / 1M in', context: '32k', hasTools: true, description: 'Mistral MoE architecture with 32k context.' },
83
- { id: 'gemma2-9b-it', name: 'Gemma 2 9B IT', tier: 'cheap', cost: '$0.20 / 1M in', context: '8k', hasTools: true, description: 'Google Gemma 2 on Groq LPU hardware.' },
84
- ],
98
+ recommendedModels: [
99
+ { id: 'openai/gpt-oss-120b', name: 'GPT-OSS 120B', tier: 'flagship', cost: '$0.15 / 1M in', context: '131k', hasTools: true, description: 'Recommended default. Production-grade 120B reasoning model with tool use on Groq.' },
100
+ { id: 'openai/gpt-oss-20b', name: 'GPT-OSS 20B', tier: 'ultra-cheap', cost: '$0.075 / 1M in', context: '131k', hasTools: true, description: 'Fast production model for lower-cost, high-volume requests.' },
101
+ ],
85
102
  },
86
103
  deepseek: {
87
104
  id: 'deepseek',
88
105
  name: 'DeepSeek Cloud',
89
- baseUrl: process.env.DEEPSEEK_BASE_URL || 'https://api.deepseek.com/v1',
106
+ baseUrl: process.env.DEEPSEEK_BASE_URL || 'https://api.deepseek.com',
90
107
  apiKey: process.env.DEEPSEEK_API_KEY || '',
91
- defaultModel: process.env.DEEPSEEK_MODEL || 'deepseek-chat',
108
+ defaultModel: normalizeProviderModel('deepseek', process.env.DEEPSEEK_MODEL || 'deepseek-v4-flash'),
92
109
  isLocal: false,
93
110
  envKey: 'DEEPSEEK_API_KEY',
94
111
  docUrl: 'https://api-docs.deepseek.com',
95
112
  apiRefUrl: 'https://api-docs.deepseek.com/api/create-chat-completion',
96
- pricingSummary: 'Ultra-low cost (deepseek-chat: $0.14 cached / $0.27 uncached / 1M)',
97
- features: ['deepseek-v3', 'deepseek-r1-reasoning', 'tools', 'streaming', 'context-cache'],
113
+ pricingSummary: 'V4 Flash: $0.22-$0.44/1M uncached input; V4 Pro: $0.66-$1.32/1M (off-peak/peak)',
114
+ features: ['deepseek-v4', 'thinking', 'tools', 'streaming', 'context-cache', '1m-context'],
98
115
  recommendedModels: [
99
- { id: 'deepseek-chat', name: 'DeepSeek Chat (V3)', tier: 'ultra-cheap', cost: '$0.14-$0.27 / 1M in', context: '64k', hasTools: true, description: 'Recommended default. DeepSeek-V3 671B MoE, top-tier reasoning, tool calling, fast & ultra-cheap.' },
100
- { id: 'deepseek-reasoner', name: 'DeepSeek Reasoner (R1)', tier: 'reasoning', cost: '$0.55 / 1M in', context: '64k', hasTools: false, description: 'DeepSeek-R1 full Chain-of-Thought reasoning with native thinking output.' },
116
+ { id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash', tier: 'balanced', cost: '$0.22-$0.44 / 1M uncached in', context: '1M', hasTools: true, description: 'Recommended default. Current V4 model with tool calls and thinking/non-thinking modes.' },
117
+ { id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro', tier: 'flagship', cost: '$0.66-$1.32 / 1M uncached in', context: '1M', hasTools: true, description: 'Higher-capability V4 model with tool calls and thinking mode.' },
101
118
  ],
102
119
  },
103
120
  gemini: {
@@ -105,18 +122,17 @@ export const CLOUD_PROVIDERS = {
105
122
  name: 'Google Gemini Cloud',
106
123
  baseUrl: process.env.GEMINI_BASE_URL || 'https://generativelanguage.googleapis.com/v1beta/openai/',
107
124
  apiKey: process.env.GEMINI_API_KEY || '',
108
- defaultModel: process.env.GEMINI_MODEL || 'gemini-2.5-flash',
125
+ defaultModel: normalizeProviderModel('gemini', process.env.GEMINI_MODEL || 'gemini-3.7-flash'),
109
126
  isLocal: false,
110
127
  envKey: 'GEMINI_API_KEY',
111
- docUrl: 'https://ai.google.dev/docs',
112
- apiRefUrl: 'https://ai.google.dev/api',
113
- pricingSummary: 'Ultra-cheap (gemini-2.5-flash: $0.10/1M in, $0.40/1M out)',
128
+ docUrl: 'https://ai.google.dev/gemini-api/docs',
129
+ apiRefUrl: 'https://ai.google.dev/api/generate-content',
130
+ pricingSummary: 'Gemini 3.7 Flash: free tier available; paid standard $0.75/1M input through 2026',
114
131
  features: ['1m-context', 'multimodal', 'tools', 'streaming', 'thinking'],
115
132
  recommendedModels: [
116
- { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', tier: 'ultra-cheap', cost: '$0.10 / 1M in', context: '1M', hasTools: true, description: 'Recommended default. Advanced reasoning and thinking capabilities with 1M context.' },
117
- { id: 'gemini-2.5-flash-lite', name: 'Gemini 2.5 Flash Lite', tier: 'lowest-cost', cost: '$0.075 / 1M in', context: '1M', hasTools: true, description: 'Cost-optimized 2.5 lightweight model for high volume queries.' },
118
- { id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro', tier: 'flagship', cost: '$1.25 / 1M in', context: '2M', hasTools: true, description: 'Deep reasoning and 2M context for complex multimodal analysis.' },
119
- { id: 'gemini-3.1-pro', name: 'Gemini 3.1 Pro', tier: 'flagship', cost: '$1.50 / 1M in', context: '2M', hasTools: true, description: 'Next-gen Gemini 3.1 flagship with state-of-the-art coding and multimodal reasoning.' },
133
+ { id: 'gemini-3.7-flash', name: 'Gemini 3.7 Flash', tier: 'latest-stable', cost: '$0.75 / 1M in (2026)', context: '1M', hasTools: true, description: 'Recommended default. Latest stable Flash model for agentic workflows and multimodal reasoning.' },
134
+ { id: 'gemini-3.5-flash-lite', name: 'Gemini 3.5 Flash-Lite', tier: 'lowest-cost', cost: '$0.30 / 1M in', context: '1M', hasTools: true, description: 'Stable, cost-efficient model for high-volume translation and simple processing.' },
135
+ { id: 'gemini-3.6-flash', name: 'Gemini 3.6 Flash', tier: 'stable', cost: '$0.75 / 1M in (2026)', context: '1M', hasTools: true, description: 'Stable previous-generation Flash fallback with function calling and thinking.' },
120
136
  ],
121
137
  },
122
138
  custom: {
@@ -26,10 +26,10 @@ function commandAvailable(command, args = ['--version']) {
26
26
  });
27
27
  }
28
28
 
29
- async function checkDataDirectory() {
30
- const probe = path.join(KIKU_DATA_DIR, `.write-test-${process.pid}`);
29
+ async function checkDataDirectory(dataDir = KIKU_DATA_DIR) {
30
+ const probe = path.join(dataDir, `.write-test-${process.pid}`);
31
31
  try {
32
- await fs.mkdir(KIKU_DATA_DIR, { recursive: true, mode: 0o700 });
32
+ await fs.mkdir(dataDir, { recursive: true, mode: 0o700 });
33
33
  await fs.writeFile(probe, 'ok', { mode: 0o600 });
34
34
  await fs.unlink(probe);
35
35
  return true;
@@ -42,8 +42,9 @@ import { getGpuMetrics } from './gpuMetrics.js';
42
42
 
43
43
  export async function runDoctor(options = {}) {
44
44
  const client = options.client;
45
+ const dataDir = options.dataDir || KIKU_DATA_DIR;
45
46
  const [dataWritable, speaker, ffmpegStatic, fluentFfmpeg, ytDlp, lm, gpu] = await Promise.all([
46
- checkDataDirectory(),
47
+ checkDataDirectory(dataDir),
47
48
  optionalImport('speaker'),
48
49
  optionalImport('ffmpeg-static'),
49
50
  optionalImport('fluent-ffmpeg'),
@@ -54,7 +55,7 @@ export async function runDoctor(options = {}) {
54
55
  const nodeMajor = Number(process.versions.node.split('.')[0]);
55
56
  const checks = [
56
57
  { id: 'node', required: true, ok: nodeMajor >= 20, detail: `Node ${process.versions.node} (requires >=20)` },
57
- { id: 'data', required: true, ok: dataWritable, detail: KIKU_DATA_DIR },
58
+ { id: 'data', required: true, ok: dataWritable, detail: dataDir },
58
59
  { id: 'gpu', required: false, ok: Boolean(gpu.available), detail: gpu.available && gpu.primary ? `${gpu.primary.name} (${gpu.primary.totalGb} GB VRAM${gpu.primary.driverVersion !== 'N/A' ? `, Driver ${gpu.primary.driverVersion}` : ''})` : 'CPU fallback / no dedicated acceleration detected' },
59
60
  { id: 'lmstudio', required: false, ok: Boolean(lm.connected), detail: lm.connected ? `${lm.models?.length || 0} loaded model(s)` : 'offline; catalog-only mode is available' },
60
61
  { id: 'ffmpeg', required: false, ok: ffmpegStatic && fluentFfmpeg, detail: 'audio add-on only; intentionally not installed with the core CLI' },
@@ -64,6 +65,6 @@ export async function runDoctor(options = {}) {
64
65
  return {
65
66
  ok: checks.every(check => !check.required || check.ok),
66
67
  checks,
67
- dataDir: KIKU_DATA_DIR,
68
+ dataDir,
68
69
  };
69
70
  }
@@ -1,9 +1,12 @@
1
- import { config, CLOUD_PROVIDERS } from './config.js';
1
+ import { config, CLOUD_PROVIDERS, normalizeProviderModel } from './config.js';
2
2
 
3
3
  export class LLMClient {
4
4
  constructor(options = {}) {
5
- const providerId = (options.provider || config.activeProvider || 'lmstudio').toLowerCase();
6
- const providerDef = CLOUD_PROVIDERS[providerId] || CLOUD_PROVIDERS.lmstudio;
5
+ const providerId = (options.provider || config.activeProvider || 'lmstudio').toLowerCase();
6
+ const providerDef = CLOUD_PROVIDERS[providerId];
7
+ if (!providerDef) {
8
+ throw new Error(`Unknown provider "${providerId}". Supported: ${Object.keys(CLOUD_PROVIDERS).join(', ')}`);
9
+ }
7
10
 
8
11
  this.provider = providerId;
9
12
  this.providerName = providerDef.name || providerId;
@@ -11,7 +14,10 @@ export class LLMClient {
11
14
  this.apiKey = options.apiKey !== undefined
12
15
  ? options.apiKey
13
16
  : (providerDef.apiKey !== undefined ? providerDef.apiKey : (providerDef.isLocal ? (config.lmStudio.apiKey || 'lm-studio') : ''));
14
- this.model = options.model || providerDef.defaultModel || config.lmStudio.model || 'google/gemma-4-e4b';
17
+ this.model = normalizeProviderModel(
18
+ providerId,
19
+ options.model || providerDef.defaultModel || config.lmStudio.model || 'google/gemma-4-e4b'
20
+ );
15
21
  this.timeout = options.timeout || config.lmStudio.requestTimeoutMs || 180000;
16
22
  this.extraHeaders = { ...(providerDef.extraHeaders || {}), ...(options.extraHeaders || {}) };
17
23
  }
@@ -27,7 +33,7 @@ export class LLMClient {
27
33
  this.providerName = providerDef.name || pId;
28
34
  this.baseUrl = (options.baseUrl || providerDef.baseUrl).replace(/\/+$/, '');
29
35
  this.apiKey = options.apiKey !== undefined ? options.apiKey : (providerDef.apiKey || '');
30
- this.model = options.model || providerDef.defaultModel;
36
+ this.model = normalizeProviderModel(pId, options.model || providerDef.defaultModel);
31
37
  this.extraHeaders = { ...(providerDef.extraHeaders || {}), ...(options.extraHeaders || {}) };
32
38
  return this.getProviderInfo();
33
39
  }
@@ -40,7 +46,7 @@ export class LLMClient {
40
46
  setModel(model) {
41
47
  const trimmed = String(model || '').trim();
42
48
  if (!trimmed) throw new Error('A model ID is required.');
43
- this.model = trimmed;
49
+ this.model = normalizeProviderModel(this.provider, trimmed);
44
50
  return this.model;
45
51
  }
46
52
 
@@ -187,8 +193,9 @@ export class LLMClient {
187
193
  onToken = null,
188
194
  onThought = null
189
195
  }) {
190
- const isReasoningModel = /^(o1|o3|deepseek-reasoner)/i.test(this.model) || this.model.includes('reasoner');
191
- const isO1OrO3 = /^(o1|o3)/i.test(this.model);
196
+ const isLegacyReasoningModel = /^(o1|o3|deepseek-reasoner)/i.test(this.model) || this.model.includes('reasoner');
197
+ const usesCompletionTokenLimit = /^(o1|o3|gpt-5(?:\.|-|$))/i.test(this.model);
198
+ const rejectsTemperature = /^(o1|o3|gpt-5(?:\.|-|$))/i.test(this.model);
192
199
 
193
200
  const buildPayload = (includeTools = true, includeTemp = true) => {
194
201
  const p = {
@@ -197,17 +204,17 @@ export class LLMClient {
197
204
  stream
198
205
  };
199
206
 
200
- if (!isO1OrO3 && includeTemp && temperature !== undefined && temperature !== null) {
201
- p.temperature = temperature;
202
- }
203
-
204
- if (isO1OrO3) {
205
- p.max_completion_tokens = maxTokens;
206
- } else {
207
- p.max_tokens = maxTokens;
208
- }
209
-
210
- if (includeTools && tools && Array.isArray(tools) && tools.length > 0 && !isReasoningModel) {
207
+ if (!rejectsTemperature && includeTemp && temperature !== undefined && temperature !== null) {
208
+ p.temperature = temperature;
209
+ }
210
+
211
+ if (usesCompletionTokenLimit) {
212
+ p.max_completion_tokens = maxTokens;
213
+ } else {
214
+ p.max_tokens = maxTokens;
215
+ }
216
+
217
+ if (includeTools && tools && Array.isArray(tools) && tools.length > 0 && !isLegacyReasoningModel) {
211
218
  p.tools = tools;
212
219
  p.tool_choice = "auto";
213
220
  }