@ottocode/server 0.1.265 → 0.1.266
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/package.json +3 -3
- package/src/routes/auth/copilot.ts +699 -0
- package/src/routes/auth/oauth.ts +578 -0
- package/src/routes/auth/onboarding.ts +45 -0
- package/src/routes/auth/providers.ts +189 -0
- package/src/routes/auth/service.ts +167 -0
- package/src/routes/auth/state.ts +23 -0
- package/src/routes/auth/status.ts +203 -0
- package/src/routes/auth/wallet.ts +229 -0
- package/src/routes/auth.ts +12 -2080
- package/src/routes/config/models-service.ts +411 -0
- package/src/routes/config/models.ts +6 -426
- package/src/routes/config/providers-service.ts +237 -0
- package/src/routes/config/providers.ts +10 -242
- package/src/routes/files/handlers.ts +297 -0
- package/src/routes/files/service.ts +313 -0
- package/src/routes/files.ts +12 -608
- package/src/routes/git/commit-service.ts +207 -0
- package/src/routes/git/commit.ts +6 -220
- package/src/routes/git/remote-service.ts +116 -0
- package/src/routes/git/remote.ts +8 -115
- package/src/routes/git/staging-service.ts +111 -0
- package/src/routes/git/staging.ts +10 -205
- package/src/routes/mcp/auth.ts +338 -0
- package/src/routes/mcp/lifecycle.ts +263 -0
- package/src/routes/mcp/servers.ts +212 -0
- package/src/routes/mcp/service.ts +664 -0
- package/src/routes/mcp/state.ts +13 -0
- package/src/routes/mcp.ts +6 -1233
- package/src/routes/ottorouter/billing.ts +593 -0
- package/src/routes/ottorouter/service.ts +92 -0
- package/src/routes/ottorouter/topup.ts +301 -0
- package/src/routes/ottorouter/wallet.ts +370 -0
- package/src/routes/ottorouter.ts +6 -1319
- package/src/routes/research/service.ts +339 -0
- package/src/routes/research.ts +12 -390
- package/src/routes/sessions/crud.ts +563 -0
- package/src/routes/sessions/queue.ts +242 -0
- package/src/routes/sessions/retry.ts +121 -0
- package/src/routes/sessions/service.ts +768 -0
- package/src/routes/sessions/share.ts +434 -0
- package/src/routes/sessions.ts +8 -1977
- package/src/routes/skills/service.ts +221 -0
- package/src/routes/skills/spec.ts +309 -0
- package/src/routes/skills.ts +31 -909
- package/src/routes/terminals/service.ts +326 -0
- package/src/routes/terminals.ts +19 -295
- package/src/routes/tunnel/service.ts +217 -0
- package/src/routes/tunnel.ts +29 -219
- package/src/runtime/agent/registry-prompts.ts +147 -0
- package/src/runtime/agent/registry.ts +6 -124
- package/src/runtime/agent/runner-errors.ts +116 -0
- package/src/runtime/agent/runner-reminders.ts +45 -0
- package/src/runtime/agent/runner-setup-model.ts +75 -0
- package/src/runtime/agent/runner-setup-prompt.ts +185 -0
- package/src/runtime/agent/runner-setup-tools.ts +103 -0
- package/src/runtime/agent/runner-setup-utils.ts +21 -0
- package/src/runtime/agent/runner-setup.ts +54 -288
- package/src/runtime/agent/runner-telemetry.ts +112 -0
- package/src/runtime/agent/runner-text.ts +108 -0
- package/src/runtime/agent/runner-tool-observer.ts +86 -0
- package/src/runtime/agent/runner.ts +79 -378
- package/src/runtime/provider/custom.ts +73 -0
- package/src/runtime/provider/index.ts +2 -85
- package/src/runtime/provider/reasoning-builders.ts +280 -0
- package/src/runtime/provider/reasoning.ts +67 -264
- package/src/tools/adapter/events.ts +116 -0
- package/src/tools/adapter/execution.ts +160 -0
- package/src/tools/adapter/pending.ts +37 -0
- package/src/tools/adapter/persistence.ts +166 -0
- package/src/tools/adapter/results.ts +97 -0
- package/src/tools/adapter.ts +124 -451
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getConfiguredProviderApiKey,
|
|
3
|
+
normalizeOllamaBaseURL,
|
|
4
|
+
resolveOpenAIResponsesModel,
|
|
5
|
+
type getProviderDefinition,
|
|
6
|
+
type OttoConfig,
|
|
7
|
+
} from '@ottocode/sdk';
|
|
8
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
9
|
+
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
10
|
+
import { createOpenAI } from '@ai-sdk/openai';
|
|
11
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
12
|
+
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
13
|
+
import { createOllama } from 'ai-sdk-ollama';
|
|
14
|
+
|
|
15
|
+
export function resolveCustomConfiguredModel(
|
|
16
|
+
definition: NonNullable<ReturnType<typeof getProviderDefinition>>,
|
|
17
|
+
cfg: OttoConfig,
|
|
18
|
+
model: string,
|
|
19
|
+
options?: {
|
|
20
|
+
reasoningText?: boolean;
|
|
21
|
+
},
|
|
22
|
+
) {
|
|
23
|
+
const apiKey = getConfiguredProviderApiKey(cfg, definition.id) || '';
|
|
24
|
+
const baseURL =
|
|
25
|
+
definition.baseURL ||
|
|
26
|
+
(definition.id === 'ollama-cloud' ? 'https://ollama.com' : undefined);
|
|
27
|
+
|
|
28
|
+
if (!baseURL) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Custom provider ${definition.id} requires a baseURL in config.`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (definition.compatibility === 'openai') {
|
|
35
|
+
const instance = createOpenAI({ apiKey, baseURL });
|
|
36
|
+
return resolveOpenAIResponsesModel(instance, model);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (definition.compatibility === 'anthropic') {
|
|
40
|
+
const instance = createAnthropic({ apiKey, baseURL });
|
|
41
|
+
return instance(model);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (definition.compatibility === 'google') {
|
|
45
|
+
const instance = createGoogleGenerativeAI({ apiKey, baseURL });
|
|
46
|
+
return instance(model);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (definition.compatibility === 'openrouter') {
|
|
50
|
+
const instance = createOpenRouter({ apiKey, baseURL });
|
|
51
|
+
return instance.chat(model);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (definition.compatibility === 'ollama') {
|
|
55
|
+
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined;
|
|
56
|
+
const ollamaBaseURL = normalizeOllamaBaseURL(baseURL);
|
|
57
|
+
const instance = createOllama({
|
|
58
|
+
baseURL: ollamaBaseURL,
|
|
59
|
+
headers,
|
|
60
|
+
});
|
|
61
|
+
return instance(model, {
|
|
62
|
+
...(options?.reasoningText ? { think: true } : {}),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined;
|
|
67
|
+
const instance = createOpenAICompatible({
|
|
68
|
+
name: definition.label,
|
|
69
|
+
baseURL,
|
|
70
|
+
headers,
|
|
71
|
+
});
|
|
72
|
+
return instance(model);
|
|
73
|
+
}
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import type { OttoConfig, ProviderId } from '@ottocode/sdk';
|
|
2
|
-
import {
|
|
3
|
-
getConfiguredProviderApiKey,
|
|
4
|
-
getProviderDefinition,
|
|
5
|
-
isBuiltInProviderId,
|
|
6
|
-
normalizeOllamaBaseURL,
|
|
7
|
-
} from '@ottocode/sdk';
|
|
8
|
-
import { createOpenAI } from '@ai-sdk/openai';
|
|
9
|
-
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
10
|
-
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
11
|
-
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
12
|
-
import { createOllama } from 'ai-sdk-ollama';
|
|
13
|
-
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
2
|
+
import { getProviderDefinition, isBuiltInProviderId } from '@ottocode/sdk';
|
|
14
3
|
import { getAnthropicInstance } from './anthropic.ts';
|
|
15
4
|
import { resolveOpenAIModel } from './openai.ts';
|
|
16
5
|
import { resolveGoogleModel } from './google.ts';
|
|
@@ -25,6 +14,7 @@ import { resolveOpencodeModel } from './opencode.ts';
|
|
|
25
14
|
import { getMoonshotInstance } from './moonshot.ts';
|
|
26
15
|
import { getMinimaxInstance } from './minimax.ts';
|
|
27
16
|
import { resolveCopilotModel } from './copilot.ts';
|
|
17
|
+
import { resolveCustomConfiguredModel } from './custom.ts';
|
|
28
18
|
|
|
29
19
|
export type ProviderName = ProviderId;
|
|
30
20
|
|
|
@@ -96,76 +86,3 @@ export async function resolveModel(
|
|
|
96
86
|
}
|
|
97
87
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
98
88
|
}
|
|
99
|
-
|
|
100
|
-
function needsResponsesApi(model: string): boolean {
|
|
101
|
-
const lower = model.toLowerCase();
|
|
102
|
-
return (
|
|
103
|
-
lower.includes('gpt-5') ||
|
|
104
|
-
lower.startsWith('o1') ||
|
|
105
|
-
lower.startsWith('o3') ||
|
|
106
|
-
lower.startsWith('o4') ||
|
|
107
|
-
lower.includes('codex-mini')
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function resolveCustomConfiguredModel(
|
|
112
|
-
definition: NonNullable<ReturnType<typeof getProviderDefinition>>,
|
|
113
|
-
cfg: OttoConfig,
|
|
114
|
-
model: string,
|
|
115
|
-
options?: {
|
|
116
|
-
reasoningText?: boolean;
|
|
117
|
-
},
|
|
118
|
-
) {
|
|
119
|
-
const apiKey = getConfiguredProviderApiKey(cfg, definition.id) || '';
|
|
120
|
-
const baseURL =
|
|
121
|
-
definition.baseURL ||
|
|
122
|
-
(definition.id === 'ollama-cloud' ? 'https://ollama.com' : undefined);
|
|
123
|
-
|
|
124
|
-
if (!baseURL) {
|
|
125
|
-
throw new Error(
|
|
126
|
-
`Custom provider ${definition.id} requires a baseURL in config.`,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (definition.compatibility === 'openai') {
|
|
131
|
-
const instance = createOpenAI({ apiKey, baseURL });
|
|
132
|
-
return needsResponsesApi(model)
|
|
133
|
-
? instance.responses(model)
|
|
134
|
-
: instance(model);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (definition.compatibility === 'anthropic') {
|
|
138
|
-
const instance = createAnthropic({ apiKey, baseURL });
|
|
139
|
-
return instance(model);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (definition.compatibility === 'google') {
|
|
143
|
-
const instance = createGoogleGenerativeAI({ apiKey, baseURL });
|
|
144
|
-
return instance(model);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (definition.compatibility === 'openrouter') {
|
|
148
|
-
const instance = createOpenRouter({ apiKey, baseURL });
|
|
149
|
-
return instance.chat(model);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (definition.compatibility === 'ollama') {
|
|
153
|
-
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined;
|
|
154
|
-
const ollamaBaseURL = normalizeOllamaBaseURL(baseURL);
|
|
155
|
-
const instance = createOllama({
|
|
156
|
-
baseURL: ollamaBaseURL,
|
|
157
|
-
headers,
|
|
158
|
-
});
|
|
159
|
-
return instance(model, {
|
|
160
|
-
...(options?.reasoningText ? { think: true } : {}),
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined;
|
|
165
|
-
const instance = createOpenAICompatible({
|
|
166
|
-
name: definition.label,
|
|
167
|
-
baseURL,
|
|
168
|
-
headers,
|
|
169
|
-
});
|
|
170
|
-
return instance(model);
|
|
171
|
-
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import {
|
|
2
|
+
catalog,
|
|
3
|
+
getProviderDefinition,
|
|
4
|
+
isBuiltInProviderId,
|
|
5
|
+
type OttoConfig,
|
|
6
|
+
type ProviderId,
|
|
7
|
+
type ReasoningLevel,
|
|
8
|
+
} from '@ottocode/sdk';
|
|
9
|
+
import type { ReasoningConfigResult } from './reasoning.ts';
|
|
10
|
+
|
|
11
|
+
const THINKING_BUDGET = 16000;
|
|
12
|
+
|
|
13
|
+
type ReasoningBuilderArgs = {
|
|
14
|
+
cfg?: OttoConfig;
|
|
15
|
+
provider: ProviderId;
|
|
16
|
+
model: string;
|
|
17
|
+
reasoningLevel?: ReasoningLevel;
|
|
18
|
+
maxOutputTokens: number | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function normalizeReasoningLevel(
|
|
22
|
+
level: ReasoningLevel | undefined,
|
|
23
|
+
): Exclude<ReasoningLevel, 'xhigh'> {
|
|
24
|
+
if (!level) return 'high';
|
|
25
|
+
if (level === 'xhigh') return 'high';
|
|
26
|
+
return level;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toAnthropicEffort(
|
|
30
|
+
model: string,
|
|
31
|
+
level: ReasoningLevel | undefined,
|
|
32
|
+
): 'low' | 'medium' | 'high' | 'xhigh' | 'max' {
|
|
33
|
+
switch (level) {
|
|
34
|
+
case 'minimal':
|
|
35
|
+
case 'low':
|
|
36
|
+
return 'low';
|
|
37
|
+
case 'medium':
|
|
38
|
+
return 'medium';
|
|
39
|
+
case 'max':
|
|
40
|
+
return 'max';
|
|
41
|
+
case 'xhigh':
|
|
42
|
+
return isClaudeOpus47(model) ? 'xhigh' : 'max';
|
|
43
|
+
default:
|
|
44
|
+
return 'high';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function toOpenAIEffort(
|
|
49
|
+
level: ReasoningLevel | undefined,
|
|
50
|
+
): 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' {
|
|
51
|
+
switch (level) {
|
|
52
|
+
case 'minimal':
|
|
53
|
+
return 'minimal';
|
|
54
|
+
case 'low':
|
|
55
|
+
return 'low';
|
|
56
|
+
case 'medium':
|
|
57
|
+
return 'medium';
|
|
58
|
+
case 'max':
|
|
59
|
+
case 'xhigh':
|
|
60
|
+
return 'xhigh';
|
|
61
|
+
default:
|
|
62
|
+
return 'high';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function toGoogleThinkingLevel(
|
|
67
|
+
level: ReasoningLevel | undefined,
|
|
68
|
+
): 'minimal' | 'low' | 'medium' | 'high' {
|
|
69
|
+
switch (level) {
|
|
70
|
+
case 'minimal':
|
|
71
|
+
return 'minimal';
|
|
72
|
+
case 'low':
|
|
73
|
+
return 'low';
|
|
74
|
+
case 'medium':
|
|
75
|
+
return 'medium';
|
|
76
|
+
default:
|
|
77
|
+
return 'high';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function toThinkingBudget(
|
|
82
|
+
level: ReasoningLevel | undefined,
|
|
83
|
+
maxOutputTokens: number | undefined,
|
|
84
|
+
): number {
|
|
85
|
+
const cap = maxOutputTokens
|
|
86
|
+
? Math.max(maxOutputTokens, THINKING_BUDGET)
|
|
87
|
+
: THINKING_BUDGET;
|
|
88
|
+
switch (level) {
|
|
89
|
+
case 'minimal':
|
|
90
|
+
return Math.min(2048, cap);
|
|
91
|
+
case 'low':
|
|
92
|
+
return Math.min(4096, cap);
|
|
93
|
+
case 'medium':
|
|
94
|
+
return Math.min(8192, cap);
|
|
95
|
+
case 'max':
|
|
96
|
+
case 'xhigh':
|
|
97
|
+
return Math.min(24000, cap);
|
|
98
|
+
default:
|
|
99
|
+
return Math.min(16000, cap);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function toCamelCaseKey(value: string): string {
|
|
104
|
+
return value
|
|
105
|
+
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
106
|
+
.trim()
|
|
107
|
+
.split(/\s+/)
|
|
108
|
+
.map((segment, index) => {
|
|
109
|
+
const lower = segment.toLowerCase();
|
|
110
|
+
if (index === 0) return lower;
|
|
111
|
+
return lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
112
|
+
})
|
|
113
|
+
.join('');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getOpenAICompatibleProviderOptionKeys(
|
|
117
|
+
provider: ProviderId,
|
|
118
|
+
cfg?: OttoConfig,
|
|
119
|
+
): string[] {
|
|
120
|
+
const definition = cfg ? getProviderDefinition(cfg, provider) : undefined;
|
|
121
|
+
const entry = isBuiltInProviderId(provider) ? catalog[provider] : undefined;
|
|
122
|
+
const keys = new Set<string>(['openaiCompatible', toCamelCaseKey(provider)]);
|
|
123
|
+
const label = definition?.label ?? entry?.label;
|
|
124
|
+
if (label) {
|
|
125
|
+
keys.add(toCamelCaseKey(label));
|
|
126
|
+
}
|
|
127
|
+
return Array.from(keys).filter(Boolean);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function buildSharedProviderOptions(
|
|
131
|
+
provider: ProviderId,
|
|
132
|
+
options: Record<string, unknown>,
|
|
133
|
+
cfg?: OttoConfig,
|
|
134
|
+
): Record<string, unknown> {
|
|
135
|
+
const keys = getOpenAICompatibleProviderOptionKeys(provider, cfg);
|
|
136
|
+
return Object.fromEntries(keys.map((key) => [key, options]));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function isClaudeOpus47(model: string): boolean {
|
|
140
|
+
const lower = model.toLowerCase();
|
|
141
|
+
return lower.includes('claude-opus-4-7') || lower.includes('claude-opus-4.7');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function usesAdaptiveAnthropicThinking(model: string): boolean {
|
|
145
|
+
const lower = model.toLowerCase();
|
|
146
|
+
return (
|
|
147
|
+
isClaudeOpus47(model) ||
|
|
148
|
+
lower.includes('claude-opus-4-6') ||
|
|
149
|
+
lower.includes('claude-opus-4.6') ||
|
|
150
|
+
lower.includes('claude-sonnet-4-6') ||
|
|
151
|
+
lower.includes('claude-sonnet-4.6')
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function buildAnthropicReasoningOptions({
|
|
156
|
+
model,
|
|
157
|
+
reasoningLevel,
|
|
158
|
+
maxOutputTokens,
|
|
159
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
160
|
+
if (usesAdaptiveAnthropicThinking(model)) {
|
|
161
|
+
const thinking = isClaudeOpus47(model)
|
|
162
|
+
? { type: 'adaptive', display: 'summarized' }
|
|
163
|
+
: { type: 'adaptive' };
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
providerOptions: {
|
|
167
|
+
anthropic: {
|
|
168
|
+
thinking,
|
|
169
|
+
effort: toAnthropicEffort(model, reasoningLevel),
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
173
|
+
enabled: true,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const thinkingBudget = toThinkingBudget(reasoningLevel, maxOutputTokens);
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
providerOptions: {
|
|
181
|
+
anthropic: {
|
|
182
|
+
thinking: { type: 'enabled', budgetTokens: thinkingBudget },
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
effectiveMaxOutputTokens:
|
|
186
|
+
maxOutputTokens && maxOutputTokens > thinkingBudget
|
|
187
|
+
? maxOutputTokens - thinkingBudget
|
|
188
|
+
: maxOutputTokens,
|
|
189
|
+
enabled: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function buildOpenAIReasoningOptions({
|
|
194
|
+
reasoningLevel,
|
|
195
|
+
maxOutputTokens,
|
|
196
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
197
|
+
return {
|
|
198
|
+
providerOptions: {
|
|
199
|
+
openai: {
|
|
200
|
+
reasoningEffort: toOpenAIEffort(reasoningLevel),
|
|
201
|
+
reasoningSummary: 'auto',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
205
|
+
enabled: true,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function buildGoogleReasoningOptions({
|
|
210
|
+
model,
|
|
211
|
+
reasoningLevel,
|
|
212
|
+
maxOutputTokens,
|
|
213
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
214
|
+
const isGemini3 = model.includes('gemini-3');
|
|
215
|
+
return {
|
|
216
|
+
providerOptions: {
|
|
217
|
+
google: {
|
|
218
|
+
thinkingConfig: isGemini3
|
|
219
|
+
? {
|
|
220
|
+
thinkingLevel: toGoogleThinkingLevel(reasoningLevel),
|
|
221
|
+
includeThoughts: true,
|
|
222
|
+
}
|
|
223
|
+
: {
|
|
224
|
+
thinkingBudget: toThinkingBudget(reasoningLevel, maxOutputTokens),
|
|
225
|
+
includeThoughts: true,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
230
|
+
enabled: true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function buildOllamaReasoningOptions({
|
|
235
|
+
maxOutputTokens,
|
|
236
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
237
|
+
return {
|
|
238
|
+
providerOptions: {
|
|
239
|
+
ollama: {
|
|
240
|
+
think: true,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
244
|
+
enabled: true,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function buildOpenRouterReasoningOptions({
|
|
249
|
+
reasoningLevel,
|
|
250
|
+
maxOutputTokens,
|
|
251
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
252
|
+
return {
|
|
253
|
+
providerOptions: {
|
|
254
|
+
openrouter: {
|
|
255
|
+
reasoning: { effort: normalizeReasoningLevel(reasoningLevel) },
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
259
|
+
enabled: true,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function buildOpenAICompatibleReasoningOptions({
|
|
264
|
+
cfg,
|
|
265
|
+
provider,
|
|
266
|
+
reasoningLevel,
|
|
267
|
+
maxOutputTokens,
|
|
268
|
+
}: ReasoningBuilderArgs): ReasoningConfigResult {
|
|
269
|
+
return {
|
|
270
|
+
providerOptions: buildSharedProviderOptions(
|
|
271
|
+
provider,
|
|
272
|
+
{
|
|
273
|
+
reasoningEffort: normalizeReasoningLevel(reasoningLevel),
|
|
274
|
+
},
|
|
275
|
+
cfg,
|
|
276
|
+
),
|
|
277
|
+
effectiveMaxOutputTokens: maxOutputTokens,
|
|
278
|
+
enabled: true,
|
|
279
|
+
};
|
|
280
|
+
}
|