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.
- package/README.md +46 -19
- package/package.json +11 -1
- package/server/agent/agentCore.js +164 -55
- package/server/agent/cli.js +1315 -701
- package/server/agent/commandRegistry.js +436 -74
- package/server/agent/commands.js +640 -68
- package/server/agent/config.js +64 -48
- package/server/agent/doctor.js +7 -6
- package/server/agent/llmClient.js +26 -19
- package/server/agent/mcpClient.js +436 -364
- package/server/agent/modelManager.js +30 -13
- package/server/agent/queryDetails.js +182 -0
- package/server/agent/sanitizer.js +4 -4
- package/server/agent/subagent.js +1 -0
- package/server/agent/suggestions.js +346 -0
- package/server/agent/theme.js +12 -12
- package/server/agent/tools.js +118 -7
- package/server/agent/ui.js +433 -31
- package/server/agent/updateManager.js +438 -0
- package/server/agent/version.js +10 -0
- package/server/agent/youtubeAuth.js +1 -2
- package/server/mcp/data/brands.js +9 -4
- package/server/mcp/server.js +2 -1
- package/src/data/brandsData.js +65 -0
package/server/agent/config.js
CHANGED
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
|
|
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-
|
|
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://
|
|
30
|
-
apiRefUrl: 'https://
|
|
31
|
-
pricingSummary: '
|
|
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-
|
|
35
|
-
{ id: 'gpt-
|
|
36
|
-
{ id: '
|
|
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 || '
|
|
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/
|
|
53
|
-
apiRefUrl: 'https://openrouter.ai/docs/
|
|
54
|
-
pricingSummary: '
|
|
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: '
|
|
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 || '
|
|
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 (
|
|
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: '
|
|
80
|
-
{ id: '
|
|
81
|
-
|
|
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
|
|
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-
|
|
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: '
|
|
97
|
-
features: ['deepseek-
|
|
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-
|
|
100
|
-
{ id: 'deepseek-
|
|
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-
|
|
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: '
|
|
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-
|
|
117
|
-
{ id: 'gemini-
|
|
118
|
-
{ id: 'gemini-
|
|
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: {
|
package/server/agent/doctor.js
CHANGED
|
@@ -26,10 +26,10 @@ function commandAvailable(command, args = ['--version']) {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
async function checkDataDirectory() {
|
|
30
|
-
const probe = path.join(
|
|
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(
|
|
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:
|
|
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
|
|
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]
|
|
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 =
|
|
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
|
|
191
|
-
const
|
|
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 (!
|
|
201
|
-
p.temperature = temperature;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (
|
|
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 && !
|
|
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
|
}
|