agent-accelerator 0.2.0 → 0.3.0
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 +94 -14
- package/package.json +1 -1
- package/src/agent/agent.ts +194 -2
- package/src/agent/delegation.ts +388 -24
- package/src/agent/loop.ts +112 -5
- package/src/index.ts +34 -2
- package/src/models/catalog.ts +4 -3
- package/src/providers.ts +11 -9
- package/src/session/store.ts +806 -0
- package/src/tools/executor.ts +4 -1
- package/src/types/agent.ts +25 -1
- package/src/types/core.ts +2 -1
- package/src/types/response.ts +24 -0
- package/src/types/tool.ts +2 -0
- package/src/utils/session.ts +36 -0
package/src/agent/loop.ts
CHANGED
|
@@ -22,6 +22,53 @@ export interface AgentLoopConfig {
|
|
|
22
22
|
maxTurns?: number;
|
|
23
23
|
/** Convert `file` parts client-side for pdf-incapable models (see Agent flag). */
|
|
24
24
|
bypassInputFileModality?: boolean;
|
|
25
|
+
/** Called after every turn for durable persistence checkpoints (never fails a turn). */
|
|
26
|
+
onProgress?: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function emitTurn(
|
|
30
|
+
runOptions: AgentRunOptions | undefined,
|
|
31
|
+
turn: { turns: number; text?: string; thinking?: string; toolCalls?: ToolCallRecord[]; toolResults?: ToolResultRecord[] }
|
|
32
|
+
): void {
|
|
33
|
+
try {
|
|
34
|
+
runOptions?.onTurn?.({
|
|
35
|
+
turns: turn.turns,
|
|
36
|
+
text: turn.text,
|
|
37
|
+
thinking: turn.thinking,
|
|
38
|
+
toolCalls: turn.toolCalls?.map((c) => ({ id: c.id, name: c.name })),
|
|
39
|
+
toolResults: turn.toolResults?.map((r) => ({ id: r.id, name: r.name, isError: r.isError })),
|
|
40
|
+
});
|
|
41
|
+
} catch {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function emitProgress(config: { onProgress?: () => void }): void {
|
|
45
|
+
try { config.onProgress?.(); } catch {}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Normalizes `maxTurns` to a safe positive integer (default Infinity).
|
|
50
|
+
* `0` means infinite (no limit), matching the `timeout: 0` convention.
|
|
51
|
+
* Prevents silent zero-turn runs from negative values (clamped to 1).
|
|
52
|
+
*/
|
|
53
|
+
function normalizeMaxTurns(value?: number): number {
|
|
54
|
+
if (value === undefined) return Infinity;
|
|
55
|
+
if (value === 0 || value === Infinity) return Infinity;
|
|
56
|
+
if (!Number.isFinite(value as number)) return Infinity;
|
|
57
|
+
return Math.max(1, Math.floor(value as number));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Warns when an agent run stops because `maxTurns` was exhausted while
|
|
62
|
+
* the model still wanted to call tools. Without this, the loop simply
|
|
63
|
+
* returns the last tool-turn text (often empty) with `finishReason:
|
|
64
|
+
* "tool_calls"`, which looks like success while dropping pending work.
|
|
65
|
+
*/
|
|
66
|
+
function warnMaxTurnsHit(agentName: string | undefined, maxTurns: number, pendingTools: string[]): void {
|
|
67
|
+
const who = agentName ? `"${agentName}"` : "Agent";
|
|
68
|
+
const tools = pendingTools.length > 0 ? ` Pending tool calls dropped: ${pendingTools.join(", ")}.` : "";
|
|
69
|
+
// Leading newline: runs often end mid-line on streamed output; without it
|
|
70
|
+
// the warning glues onto the last streamed chunk.
|
|
71
|
+
console.warn(`\n[Agent Accelerator] WARNING [agent] ${who} hit maxTurns (${maxTurns}) with unfinished tool calls.${tools} Increase maxTurns or split the task.`);
|
|
25
72
|
}
|
|
26
73
|
|
|
27
74
|
export function computeCostFromPricing(usage: TokenUsage, spec?: ModelSpec): TokenUsage["cost"] {
|
|
@@ -131,6 +178,7 @@ async function executeToolCallsWithRepeatGuard(options: {
|
|
|
131
178
|
agentName?: string;
|
|
132
179
|
signal?: AbortSignal;
|
|
133
180
|
sessionId?: string;
|
|
181
|
+
onSubagentEvent?: (event: { trackingId: string; delta?: string; thinkingDelta?: string; partialText?: string; partialThinking?: string }) => void;
|
|
134
182
|
}): Promise<{ results: ToolResultRecord[]; fingerprints: Set<string> }> {
|
|
135
183
|
const { toolCalls, previousFingerprints } = options;
|
|
136
184
|
const currentFingerprints = new Set<string>();
|
|
@@ -163,6 +211,7 @@ async function executeToolCallsWithRepeatGuard(options: {
|
|
|
163
211
|
parallel: true,
|
|
164
212
|
signal: options.signal,
|
|
165
213
|
sessionId: options.sessionId,
|
|
214
|
+
onSubagentEvent: options.onSubagentEvent,
|
|
166
215
|
})
|
|
167
216
|
: [];
|
|
168
217
|
const byId = new Map<string, ToolResultRecord[]>();
|
|
@@ -202,8 +251,9 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
|
|
|
202
251
|
tools,
|
|
203
252
|
options,
|
|
204
253
|
runOptions,
|
|
205
|
-
maxTurns =
|
|
254
|
+
maxTurns: rawMaxTurns = Infinity,
|
|
206
255
|
} = config;
|
|
256
|
+
const maxTurns = normalizeMaxTurns(rawMaxTurns);
|
|
207
257
|
|
|
208
258
|
if (config.bypassInputFileModality) {
|
|
209
259
|
await preprocessFilePartsForBypass(config.context.messages, {
|
|
@@ -289,6 +339,8 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
|
|
|
289
339
|
|
|
290
340
|
// If no tool calls, generation is complete!
|
|
291
341
|
if (!genResult.toolCalls || genResult.toolCalls.length === 0) {
|
|
342
|
+
emitTurn(runOptions, { turns, text: genResult.text, thinking: genResult.thinking });
|
|
343
|
+
emitProgress(config);
|
|
292
344
|
break;
|
|
293
345
|
}
|
|
294
346
|
|
|
@@ -325,10 +377,31 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
|
|
|
325
377
|
|
|
326
378
|
allToolResults.push(...sanitizedResults);
|
|
327
379
|
context.addToolResults(sanitizedResults);
|
|
380
|
+
emitTurn(runOptions, {
|
|
381
|
+
turns,
|
|
382
|
+
text: genResult.text,
|
|
383
|
+
thinking: genResult.thinking,
|
|
384
|
+
toolCalls: genResult.toolCalls,
|
|
385
|
+
toolResults: sanitizedResults,
|
|
386
|
+
});
|
|
387
|
+
emitProgress(config);
|
|
328
388
|
|
|
329
389
|
if (runOptions?.signal?.aborted) break;
|
|
330
390
|
}
|
|
331
391
|
|
|
392
|
+
// maxTurns exhausted while the model still requested tools: the tool
|
|
393
|
+
// results above were never sent back, so the run is truncated — surface
|
|
394
|
+
// it via finishReason + warning instead of silently returning.
|
|
395
|
+
const truncatedByMaxTurns =
|
|
396
|
+
turns >= maxTurns && !!finalResult?.toolCalls && finalResult.toolCalls.length > 0;
|
|
397
|
+
if (truncatedByMaxTurns) {
|
|
398
|
+
warnMaxTurnsHit(
|
|
399
|
+
agentName,
|
|
400
|
+
maxTurns,
|
|
401
|
+
finalResult.toolCalls.map((c: ToolCallRecord) => c.name)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
332
405
|
return new AgentResponse({
|
|
333
406
|
text: finalResult?.text || "",
|
|
334
407
|
thinking: finalResult?.thinking,
|
|
@@ -340,7 +413,7 @@ export async function runAgentLoop(config: AgentLoopConfig): Promise<AgentRespon
|
|
|
340
413
|
responseId: finalResult?.responseId,
|
|
341
414
|
model: modelId,
|
|
342
415
|
provider: provider.id,
|
|
343
|
-
finishReason: finalResult?.finishReason,
|
|
416
|
+
finishReason: truncatedByMaxTurns ? "max_turns" : finalResult?.finishReason,
|
|
344
417
|
durationMs: Date.now() - startTime,
|
|
345
418
|
raw: finalResult?.raw,
|
|
346
419
|
turns,
|
|
@@ -409,8 +482,9 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
409
482
|
tools,
|
|
410
483
|
options,
|
|
411
484
|
runOptions,
|
|
412
|
-
maxTurns =
|
|
485
|
+
maxTurns: rawMaxTurns = Infinity,
|
|
413
486
|
} = config;
|
|
487
|
+
const maxTurns = normalizeMaxTurns(rawMaxTurns);
|
|
414
488
|
|
|
415
489
|
const standardTools = toStandardToolDeclarations(tools);
|
|
416
490
|
|
|
@@ -495,6 +569,8 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
495
569
|
);
|
|
496
570
|
|
|
497
571
|
if (!turnResponse.toolCalls || turnResponse.toolCalls.length === 0) {
|
|
572
|
+
emitTurn(runOptions, { turns, text: turnResponse.text, thinking: turnResponse.thinking });
|
|
573
|
+
emitProgress(config);
|
|
498
574
|
break;
|
|
499
575
|
}
|
|
500
576
|
|
|
@@ -506,6 +582,18 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
506
582
|
agentName,
|
|
507
583
|
signal: linked.signal,
|
|
508
584
|
sessionId: runOptions?.sessionId || options?.sessionId || options?.cache?.sessionId,
|
|
585
|
+
onSubagentEvent: (ev) => {
|
|
586
|
+
try {
|
|
587
|
+
outerStream.push({
|
|
588
|
+
type: "subagent_delta",
|
|
589
|
+
subagentTrackingId: ev.trackingId,
|
|
590
|
+
delta: ev.delta,
|
|
591
|
+
thinkingDelta: ev.thinkingDelta,
|
|
592
|
+
partialText: ev.partialText,
|
|
593
|
+
partialThinking: ev.partialThinking,
|
|
594
|
+
});
|
|
595
|
+
} catch {}
|
|
596
|
+
},
|
|
509
597
|
});
|
|
510
598
|
throwIfCancelled();
|
|
511
599
|
const results = guarded.results;
|
|
@@ -541,7 +629,26 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
541
629
|
|
|
542
630
|
allToolResults.push(...sanitizedResults);
|
|
543
631
|
context.addToolResults(sanitizedResults);
|
|
632
|
+
emitTurn(runOptions, {
|
|
633
|
+
turns,
|
|
634
|
+
text: turnResponse.text,
|
|
635
|
+
thinking: turnResponse.thinking,
|
|
636
|
+
toolCalls: turnResponse.toolCalls,
|
|
637
|
+
toolResults: sanitizedResults,
|
|
638
|
+
});
|
|
639
|
+
emitProgress(config);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const truncatedByMaxTurns =
|
|
643
|
+
turns >= maxTurns && !!lastResponse?.toolCalls && lastResponse.toolCalls.length > 0;
|
|
644
|
+
if (truncatedByMaxTurns) {
|
|
645
|
+
warnMaxTurnsHit(
|
|
646
|
+
agentName,
|
|
647
|
+
maxTurns,
|
|
648
|
+
lastResponse!.toolCalls.map((c) => c.name)
|
|
649
|
+
);
|
|
544
650
|
}
|
|
651
|
+
const truncatedFinishReason = truncatedByMaxTurns ? "max_turns" : lastResponse?.finishReason;
|
|
545
652
|
|
|
546
653
|
const finalAgentResponse = new AgentResponse({
|
|
547
654
|
text: lastResponse?.text || "",
|
|
@@ -554,7 +661,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
554
661
|
responseId: lastResponse?.responseId,
|
|
555
662
|
model: modelId,
|
|
556
663
|
provider: provider.id,
|
|
557
|
-
finishReason:
|
|
664
|
+
finishReason: truncatedFinishReason,
|
|
558
665
|
durationMs: Date.now() - startTime,
|
|
559
666
|
raw: lastResponse?.raw as any,
|
|
560
667
|
turns,
|
|
@@ -564,7 +671,7 @@ export function streamAgentLoop(config: AgentLoopConfig): AssistantMessageEventS
|
|
|
564
671
|
type: "done",
|
|
565
672
|
delta: "",
|
|
566
673
|
usage: accumulatedUsage,
|
|
567
|
-
finishReason:
|
|
674
|
+
finishReason: truncatedFinishReason,
|
|
568
675
|
responseId: lastResponse?.responseId,
|
|
569
676
|
});
|
|
570
677
|
|
package/src/index.ts
CHANGED
|
@@ -31,8 +31,14 @@ export {
|
|
|
31
31
|
buildAgentTools,
|
|
32
32
|
agentToTool,
|
|
33
33
|
createSubagentSpawnTool,
|
|
34
|
+
createChildSessionId,
|
|
35
|
+
createFixedChildSessionId,
|
|
36
|
+
isSessionDescendant,
|
|
37
|
+
getSubAgentTrace,
|
|
38
|
+
listSubAgentTraceIds,
|
|
39
|
+
subscribeToSubAgent,
|
|
34
40
|
} from "./agent/delegation.ts";
|
|
35
|
-
export type { DynamicSubagentTask, AgentAsToolTarget } from "./agent/delegation.ts";
|
|
41
|
+
export type { DynamicSubagentTask, AgentAsToolTarget, SubAgentTrace } from "./agent/delegation.ts";
|
|
36
42
|
|
|
37
43
|
// Providers & Registry — unified multi-provider layer, all native REST
|
|
38
44
|
export {
|
|
@@ -160,8 +166,32 @@ export { SSEParser } from "./streaming/sse-parser.ts";
|
|
|
160
166
|
// Responses
|
|
161
167
|
export { AgentResponse } from "./types/response.ts";
|
|
162
168
|
|
|
169
|
+
// Session persistence & telemetry (conversation history + cost rollup)
|
|
170
|
+
export {
|
|
171
|
+
SessionTelemetry,
|
|
172
|
+
loadSessionFile,
|
|
173
|
+
saveSessionFile,
|
|
174
|
+
loadSessionDir,
|
|
175
|
+
saveSessionDir,
|
|
176
|
+
writeFileAtomic,
|
|
177
|
+
findLatestSessionDir,
|
|
178
|
+
sessionDirFor,
|
|
179
|
+
extractMediaToDir,
|
|
180
|
+
resolveMediaPaths,
|
|
181
|
+
buildSessionData,
|
|
182
|
+
serializeSession,
|
|
183
|
+
deserializeSession,
|
|
184
|
+
getSessionContextWindow,
|
|
185
|
+
computeSessionTurnCost,
|
|
186
|
+
formatSessionTokens,
|
|
187
|
+
formatSessionCost,
|
|
188
|
+
formatSessionBanner,
|
|
189
|
+
emptyTotals,
|
|
190
|
+
} from "./session/store.ts";
|
|
191
|
+
export type { PersistedAgentSession, SessionTotals, SessionAgentLike, LoadedSessionDir, PersistedSubAgentTrace } from "./session/store.ts";
|
|
192
|
+
|
|
163
193
|
// Utilities
|
|
164
|
-
export { createSessionId } from "./utils/session.ts";
|
|
194
|
+
export { createSessionId, hashSessionPart, createTrackingId } from "./utils/session.ts";
|
|
165
195
|
export { getApiKey, getEnv } from "./utils/env.ts";
|
|
166
196
|
export { buildSessionHeaders } from "./utils/headers.ts";
|
|
167
197
|
export { normalizeMediaInput, inferMimeType } from "./utils/media.ts";
|
|
@@ -218,6 +248,7 @@ export type {
|
|
|
218
248
|
export type {
|
|
219
249
|
AgentResponseJSON,
|
|
220
250
|
SubAgentExecutionMetadata,
|
|
251
|
+
SubAgentStep,
|
|
221
252
|
StreamEvent,
|
|
222
253
|
StreamEventType,
|
|
223
254
|
} from "./types/response.ts";
|
|
@@ -225,6 +256,7 @@ export type {
|
|
|
225
256
|
export type {
|
|
226
257
|
AgentConfig,
|
|
227
258
|
AgentRunOptions,
|
|
259
|
+
AgentTurnEvent,
|
|
228
260
|
DynamicSubagentsConfig,
|
|
229
261
|
} from "./types/agent.ts";
|
|
230
262
|
|
package/src/models/catalog.ts
CHANGED
|
@@ -244,7 +244,7 @@ export function getModelThinkingInfo(provider: string, modelId: string): ModelTh
|
|
|
244
244
|
if (!spec) {
|
|
245
245
|
return {
|
|
246
246
|
supportsThinking: true,
|
|
247
|
-
allowedLevels: ["none", "minimal", "low", "medium", "high", "xhigh", "dynamic"],
|
|
247
|
+
allowedLevels: ["none", "minimal", "low", "medium", "high", "xhigh", "max", "dynamic"],
|
|
248
248
|
supportsDisable: true,
|
|
249
249
|
description: "Model not found in catalog; generic thinking levels allowed.",
|
|
250
250
|
};
|
|
@@ -295,6 +295,7 @@ export function getModelThinkingInfo(provider: string, modelId: string): ModelTh
|
|
|
295
295
|
allowed.add("medium");
|
|
296
296
|
allowed.add("high");
|
|
297
297
|
allowed.add("xhigh");
|
|
298
|
+
allowed.add("max");
|
|
298
299
|
}
|
|
299
300
|
|
|
300
301
|
// Fixed reasoning model (no reasoning_options) e.g. DeepSeek-R1, QwQ-32B
|
|
@@ -510,7 +511,7 @@ export {
|
|
|
510
511
|
|
|
511
512
|
/**
|
|
512
513
|
* Permissive placeholder so custom endpoints never fail preflight:
|
|
513
|
-
* allows every ThinkingLevel (none ->
|
|
514
|
+
* allows every ThinkingLevel (none -> max + dynamic).
|
|
514
515
|
* @example `const spec = createGenericModelSpec("groq", "llama-3.3-70b-versatile");`
|
|
515
516
|
*/
|
|
516
517
|
export function createGenericModelSpec(provider: string, modelId: string): ModelSpec {
|
|
@@ -527,7 +528,7 @@ export function createGenericModelSpec(provider: string, modelId: string): Model
|
|
|
527
528
|
reasoning: true,
|
|
528
529
|
reasoning_options: [
|
|
529
530
|
{ type: "toggle" },
|
|
530
|
-
{ type: "effort", values: ["minimal", "low", "medium", "high", "xhigh"] },
|
|
531
|
+
{ type: "effort", values: ["minimal", "low", "medium", "high", "xhigh", "max"] },
|
|
531
532
|
{ type: "budget_tokens", min: 0, max: 128000 },
|
|
532
533
|
],
|
|
533
534
|
tool_call: true,
|
package/src/providers.ts
CHANGED
|
@@ -108,7 +108,7 @@ export function clearSessionRouting(sessionId?: string): void {
|
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
110
|
* Maps a canonical ThinkingLevel onto Google Interactions `thinking_level`.
|
|
111
|
-
* Google values: minimal|low|medium|high (no off switch, no xhigh).
|
|
111
|
+
* Google values: minimal|low|medium|high (no off switch, no xhigh/max).
|
|
112
112
|
*/
|
|
113
113
|
export function mapThinkingLevelToGoogle(
|
|
114
114
|
level: ThinkingLevel | string | undefined
|
|
@@ -126,7 +126,7 @@ export function mapThinkingLevelToGoogle(
|
|
|
126
126
|
});
|
|
127
127
|
return {};
|
|
128
128
|
}
|
|
129
|
-
if (norm === "xhigh") {
|
|
129
|
+
if (norm === "xhigh" || norm === "max") {
|
|
130
130
|
emitProviderWarning({
|
|
131
131
|
provider: "google",
|
|
132
132
|
capability: "thinking level",
|
|
@@ -155,7 +155,7 @@ export function mapServiceTierToGoogle(tier: ServiceTier | undefined): "flex" |
|
|
|
155
155
|
* Completions documents `reasoning_effort: xhigh|high|medium|low|minimal|none`
|
|
156
156
|
* (parameters.md) and live probes accept `xhigh` verbatim (`03`), so — unlike
|
|
157
157
|
* the discontinued Responses skin, which clamped `xhigh` — everything passes
|
|
158
|
-
* through. `dynamic` omits (server default).
|
|
158
|
+
* through. `max` rides the same verbatim path. `dynamic` omits (server default).
|
|
159
159
|
*/
|
|
160
160
|
export function mapThinkingLevelToOpenRouterChat(
|
|
161
161
|
level: ThinkingLevel | string | undefined
|
|
@@ -169,7 +169,8 @@ export function mapThinkingLevelToOpenRouterChat(
|
|
|
169
169
|
norm === "low" ||
|
|
170
170
|
norm === "medium" ||
|
|
171
171
|
norm === "high" ||
|
|
172
|
-
norm === "xhigh"
|
|
172
|
+
norm === "xhigh" ||
|
|
173
|
+
norm === "max"
|
|
173
174
|
) {
|
|
174
175
|
return { effort: norm };
|
|
175
176
|
}
|
|
@@ -179,8 +180,8 @@ export function mapThinkingLevelToOpenRouterChat(
|
|
|
179
180
|
/**
|
|
180
181
|
* Maps a canonical ThinkingLevel onto OpenRouter Responses `reasoning.effort`.
|
|
181
182
|
* Documented efforts: minimal|low|medium|high (server default medium).
|
|
182
|
-
* Wire-validated extras: `none` disables reasoning output; `xhigh`
|
|
183
|
-
* but
|
|
183
|
+
* Wire-validated extras: `none` disables reasoning output; `xhigh`/`max` are
|
|
184
|
+
* echoed but are NOT documented levels, so they clamp to `high` with a warning.
|
|
184
185
|
*
|
|
185
186
|
* @deprecated The Responses skin is discontinued for OpenRouter
|
|
186
187
|
* (`src/providers/openrouter-responses.ts`, archived). Use
|
|
@@ -194,7 +195,7 @@ export function mapThinkingLevelToOpenRouter(
|
|
|
194
195
|
const norm = String(level).toLowerCase().trim();
|
|
195
196
|
if (norm === "dynamic") return {}; // server default (medium)
|
|
196
197
|
if (norm === "none") return { effort: "none" };
|
|
197
|
-
if (norm === "xhigh") {
|
|
198
|
+
if (norm === "xhigh" || norm === "max") {
|
|
198
199
|
emitProviderWarning({
|
|
199
200
|
provider: "openrouter",
|
|
200
201
|
capability: "thinking level",
|
|
@@ -327,7 +328,7 @@ export function mapToolChoiceToOpenRouter(
|
|
|
327
328
|
* Maps a canonical ThinkingLevel onto OpenAI Responses `reasoning.effort`.
|
|
328
329
|
* Documented efforts: none|minimal|low|medium|high|xhigh|max (server default
|
|
329
330
|
* medium). Unlike OpenRouter (which clamps xhigh), OpenAI documents xhigh
|
|
330
|
-
* natively so
|
|
331
|
+
* and max natively so they pass through verbatim. `dynamic` omits (server default).
|
|
331
332
|
*/
|
|
332
333
|
export function mapThinkingLevelToOpenAI(
|
|
333
334
|
level: ThinkingLevel | string | undefined
|
|
@@ -341,7 +342,8 @@ export function mapThinkingLevelToOpenAI(
|
|
|
341
342
|
norm === "low" ||
|
|
342
343
|
norm === "medium" ||
|
|
343
344
|
norm === "high" ||
|
|
344
|
-
norm === "xhigh"
|
|
345
|
+
norm === "xhigh" ||
|
|
346
|
+
norm === "max"
|
|
345
347
|
) {
|
|
346
348
|
return { effort: norm };
|
|
347
349
|
}
|