melchizedek-agents 1.1.0 → 1.2.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/.env.example +10 -0
- package/AGENT_SETUP.md +3 -1
- package/CHANGELOG.md +232 -0
- package/DOCUMENTATION.md +91 -16
- package/ONBOARDING.md +339 -0
- package/QUICKSTART.md +15 -2
- package/README.md +5 -2
- package/config/agents/examples/council.yaml +1 -1
- package/config/agents/examples/critic.yaml +8 -8
- package/config/agents/examples/image_production.yaml +4 -3
- package/config/agents/syndicate.schema.json +65 -7
- package/config/agents/syndicateSchema.yaml +18 -6
- package/config/agents/templates/intake_extractor.yaml +3 -2
- package/config/agents/templates/systems_operator.yaml +5 -2
- package/dist/lib/a2a/app.d.ts +12 -0
- package/dist/lib/a2a/app.js +22 -11
- package/dist/lib/a2a/executor.js +14 -6
- package/dist/lib/a2a/oauthSetup.d.ts +16 -0
- package/dist/lib/a2a/oauthSetup.js +57 -3
- package/dist/lib/agentDialect.d.ts +18 -8
- package/dist/lib/agentDialect.js +36 -19
- package/dist/lib/compile.d.ts +38 -7
- package/dist/lib/compile.js +57 -37
- package/dist/lib/compileNative.d.ts +11 -3
- package/dist/lib/compileNative.js +18 -1
- package/dist/lib/doctor.d.ts +76 -0
- package/dist/lib/doctor.js +159 -7
- package/dist/lib/loadSyndicate.d.ts +9 -0
- package/dist/lib/models/capabilities.d.ts +9 -0
- package/dist/lib/models/capabilities.js +24 -0
- package/dist/lib/models/chatCompletionsAdapter.d.ts +11 -3
- package/dist/lib/models/chatCompletionsAdapter.js +19 -5
- package/dist/lib/models/claudeAdapter.js +4 -0
- package/dist/lib/models/contract.d.ts +5 -2
- package/dist/lib/models/gateway.d.ts +2 -1
- package/dist/lib/models/gateway.js +4 -2
- package/dist/lib/models/gatewayAdapter.d.ts +7 -1
- package/dist/lib/models/gatewayAdapter.js +8 -0
- package/dist/lib/models/geminiAdapter.js +8 -2
- package/dist/lib/models/genaiMapping.d.ts +8 -4
- package/dist/lib/models/genaiMapping.js +23 -9
- package/dist/lib/models/gptAdapter.d.ts +4 -2
- package/dist/lib/models/gptAdapter.js +11 -4
- package/dist/lib/models/grokAdapter.d.ts +3 -1
- package/dist/lib/models/grokAdapter.js +11 -3
- package/dist/lib/models/kimiAdapter.d.ts +2 -1
- package/dist/lib/models/kimiAdapter.js +3 -3
- package/dist/lib/models/reasoning.d.ts +30 -2
- package/dist/lib/models/reasoning.js +56 -5
- package/dist/lib/onboarding.d.ts +134 -0
- package/dist/lib/onboarding.js +539 -0
- package/dist/lib/runtime/approvals.d.ts +2 -0
- package/dist/lib/runtime/approvals.js +4 -3
- package/dist/lib/runtime/credentials.d.ts +6 -0
- package/dist/lib/runtime/native/agentLoop.d.ts +5 -2
- package/dist/lib/runtime/native/agentLoop.js +2 -0
- package/dist/lib/runtime/native/checkpoint.d.ts +12 -5
- package/dist/lib/runtime/native/checkpoint.js +13 -19
- package/dist/lib/runtime/native/delegate.d.ts +82 -1
- package/dist/lib/runtime/native/delegate.js +157 -2
- package/dist/lib/runtime/native/interrupts.d.ts +88 -5
- package/dist/lib/runtime/native/interrupts.js +220 -30
- package/dist/lib/runtime/syndicateTurn.d.ts +4 -2
- package/dist/lib/runtime/syndicateTurn.js +295 -62
- package/dist/lib/runtime/turnControl.d.ts +41 -0
- package/dist/lib/session/transcript.d.ts +9 -0
- package/dist/lib/session/transcript.js +20 -1
- package/dist/lib/skills.d.ts +18 -0
- package/dist/lib/skills.js +73 -1
- package/dist/lib/storage/postgres/index.d.ts +6 -1
- package/dist/lib/storage/postgres/index.js +1 -1
- package/dist/lib/storage/postgres/taskQueue.d.ts +7 -3
- package/dist/lib/storage/postgres/taskQueue.js +10 -3
- package/dist/lib/syndicateSchema.d.ts +38 -1
- package/dist/lib/syndicateSchema.js +25 -18
- package/dist/lib/tools/auth.d.ts +13 -1
- package/dist/lib/tools/auth.js +10 -2
- package/dist/lib/tools/credentialHosts.d.ts +88 -0
- package/dist/lib/tools/credentialHosts.js +165 -0
- package/dist/lib/tools/credentialUses.d.ts +92 -0
- package/dist/lib/tools/credentialUses.js +112 -0
- package/dist/lib/tools/mcpToolFactory.js +1 -1
- package/dist/lib/tools/oauthConsent.js +8 -1
- package/dist/lib/tools/oauthHosts.d.ts +2 -0
- package/dist/lib/tools/oauthHosts.js +2 -2
- package/dist/lib/tools/oauthTools.d.ts +10 -1
- package/dist/lib/tools/oauthTools.js +29 -3
- package/dist/lib/tools/openapiTools.d.ts +7 -0
- package/dist/lib/tools/openapiTools.js +49 -3
- package/dist/lib/tools/taskTools.d.ts +32 -2
- package/dist/lib/tools/taskTools.js +93 -33
- package/dist/lib/workflow/turn.d.ts +22 -3
- package/dist/lib/workflow/turn.js +151 -31
- package/dist/lib/workflow.d.ts +10 -7
- package/dist/lib/workflow.js +10 -7
- package/dist/scripts/a2a_server.d.ts +2 -2
- package/dist/scripts/a2a_server.js +11 -2
- package/dist/scripts/assistant_worker.d.ts +2 -0
- package/dist/scripts/assistant_worker.js +13 -4
- package/dist/scripts/doctor.d.ts +4 -2
- package/dist/scripts/doctor.js +6 -4
- package/dist/scripts/setup.d.ts +23 -0
- package/dist/scripts/setup.js +154 -0
- package/dist/scripts/skills_install.d.ts +3 -1
- package/dist/scripts/skills_install.js +17 -2
- package/dist/scripts/yaml_codemod.d.ts +12 -2
- package/dist/scripts/yaml_codemod.js +115 -33
- package/package.json +4 -1
- package/skills/README.md +11 -2
- package/skills/briefs/_shared.md +1 -1
- package/skills/briefs/melchizedek-models.md +4 -2
- package/skills/briefs/skills-readme.md +3 -1
- package/skills/melchizedek-models/SKILL.md +6 -2
- package/skills/melchizedek-onboard/SKILL.md +49 -0
- package/skills/melchizedek-onboard-cloud/SKILL.md +38 -0
- package/skills/melchizedek-onboard-keys/SKILL.md +35 -0
- package/skills/melchizedek-onboard-local/SKILL.md +41 -0
- package/skills/melchizedek-onboard-serve/SKILL.md +43 -0
|
@@ -225,6 +225,23 @@ export function capabilityOf(model, capability, opts = {}) {
|
|
|
225
225
|
}
|
|
226
226
|
return { row, ...CAPABILITY_MATRIX[row][capability] };
|
|
227
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* The reasoning levels above `high` (ADR 0117), per row: what `reasoning:
|
|
230
|
+
* xhigh` and `reasoning: max` reach the provider as. A level a model lacks
|
|
231
|
+
* goes as its highest setting, and the request's `llm.request` span carries
|
|
232
|
+
* `llm.reasoning.weakened` with the level asked for. Asserted against the
|
|
233
|
+
* request bodies in tests/toolChoiceEffort.test.ts; the direct adapters read
|
|
234
|
+
* lib/models/reasoning.ts effortCeiling.
|
|
235
|
+
*/
|
|
236
|
+
export const REASONING_ABOVE_HIGH = {
|
|
237
|
+
gemini: 'xhigh and max go as thinkingLevel HIGH (a 16,384-token budget on Gemini 2.x), weakened',
|
|
238
|
+
anthropic: 'output_config.effort xhigh and max as asked on the adaptive generations (Opus 4.7 and later, Sonnet 5 and later, Haiku 5.5); a 16,384-token budget, weakened, on Claude 4.6 and earlier',
|
|
239
|
+
openai: 'xhigh as asked on GPT-5.2 and later, and max goes as xhigh there, weakened; high, weakened, on the o-series, GPT-5 and GPT-5.1',
|
|
240
|
+
xai: 'xhigh as asked on grok-4.7, and max goes as xhigh there, weakened; high, weakened, on grok-4.5 and grok-4.6',
|
|
241
|
+
moonshot: 'max as asked on kimi-k3, and xhigh rounds up to max; the K2 generation takes a thinking switch, which these leave on',
|
|
242
|
+
ollama: 'reasoning_effort high, weakened',
|
|
243
|
+
gateway: 'reasoning_effort high, weakened, whatever the id: the words above high are not accepted across gateways',
|
|
244
|
+
};
|
|
228
245
|
/**
|
|
229
246
|
* Whether an outputSchema goes in the same request as the agent's tools, as
|
|
230
247
|
* the provider's own structured-output field, on the path `model` takes
|
|
@@ -347,6 +364,13 @@ export function renderCapabilityMatrix() {
|
|
|
347
364
|
lines.push('');
|
|
348
365
|
notes.forEach((n, i) => lines.push(`${i + 1}. ${n}`));
|
|
349
366
|
lines.push('');
|
|
367
|
+
lines.push('**Reasoning above high** (ADR 0117): what `reasoning: xhigh` and `reasoning: max` reach each path as. "Weakened" means the model\'s highest setting is sent and the span carries `llm.reasoning.weakened`.');
|
|
368
|
+
lines.push('');
|
|
369
|
+
lines.push('| Path | xhigh and max |');
|
|
370
|
+
lines.push('|---|---|');
|
|
371
|
+
for (const r of rows)
|
|
372
|
+
lines.push(`| ${label(r)} | ${REASONING_ABOVE_HIGH[r]} |`);
|
|
373
|
+
lines.push('');
|
|
350
374
|
lines.push('**Cloud platforms** (ADR 0023): the same adapter and request as the provider\'s own API, except as listed. These paths are tested against mocks, not against the live clouds.');
|
|
351
375
|
lines.push('');
|
|
352
376
|
lines.push('| Path | Differs from the provider row |');
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
* ADR 0053): llm.transport, llm.finish_reason, llm.http_status,
|
|
55
55
|
* llm.retries, llm.retry_without_thinking, and the search and drop marks.
|
|
56
56
|
*/
|
|
57
|
-
import type { ModelAdapter, ModelRequest, ModelResponse, ReasoningSetting, ToolChoiceMode, Usage } from './contract.ts';
|
|
57
|
+
import type { ModelAdapter, ModelRequest, ModelResponse, ReasoningLevel, ReasoningSetting, ToolChoiceMode, Usage } from './contract.ts';
|
|
58
58
|
type ChatContentPart = {
|
|
59
59
|
type: 'text';
|
|
60
60
|
text: string;
|
|
@@ -190,10 +190,18 @@ export declare abstract class ChatCompletionsAdapter implements ModelAdapter {
|
|
|
190
190
|
/**
|
|
191
191
|
* The body fields for the request's reasoning. Default: `reasoning_effort`
|
|
192
192
|
* as the effort word ADR 0047 gives this model (lib/models/reasoning.ts),
|
|
193
|
-
* the field every chat-completions provider and gateway reads
|
|
194
|
-
* when the request sets no reasoning.
|
|
193
|
+
* the field every chat-completions provider and gateway reads, held at
|
|
194
|
+
* `reasoningCeiling(model)`; nothing when the request sets no reasoning.
|
|
195
195
|
*/
|
|
196
196
|
protected reasoningFields(model: string, setting: ReasoningSetting | undefined): Record<string, unknown>;
|
|
197
|
+
/**
|
|
198
|
+
* The highest reasoning level this adapter sends as asked for `model`
|
|
199
|
+
* (ADR 0117). Default: the direct provider's (lib/models/reasoning.ts
|
|
200
|
+
* effortCeiling); the gateway holds every id at `high`.
|
|
201
|
+
*/
|
|
202
|
+
protected reasoningCeiling(model: string): ReasoningLevel;
|
|
203
|
+
/** The effort word for one setting, held at reasoningCeiling; a held level is marked on the span (`llm.reasoning.weakened`). */
|
|
204
|
+
protected effortFor(model: string, setting: ReasoningSetting): string;
|
|
197
205
|
/** Provider-specific body fields, merged last. */
|
|
198
206
|
protected extraBodyFields(_request: ModelRequest): Record<string, unknown>;
|
|
199
207
|
/**
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
*/
|
|
57
57
|
import { errorDecision, errorText, statusDecision } from './errorResponse.js';
|
|
58
58
|
import { currentTurnStart, providerStateOf } from './providerState.js';
|
|
59
|
-
import {
|
|
59
|
+
import { effortCeiling as effortCeilingOf, effortWord } from './reasoning.js';
|
|
60
60
|
import { fetchWithRetry } from './retry.js';
|
|
61
61
|
import { toStrictJsonSchema } from './schemaNormalize.js';
|
|
62
62
|
import { setLlmSpanAttribute } from '../observability/tracer.js';
|
|
@@ -327,12 +327,26 @@ export class ChatCompletionsAdapter {
|
|
|
327
327
|
/**
|
|
328
328
|
* The body fields for the request's reasoning. Default: `reasoning_effort`
|
|
329
329
|
* as the effort word ADR 0047 gives this model (lib/models/reasoning.ts),
|
|
330
|
-
* the field every chat-completions provider and gateway reads
|
|
331
|
-
* when the request sets no reasoning.
|
|
330
|
+
* the field every chat-completions provider and gateway reads, held at
|
|
331
|
+
* `reasoningCeiling(model)`; nothing when the request sets no reasoning.
|
|
332
332
|
*/
|
|
333
333
|
reasoningFields(model, setting) {
|
|
334
|
-
|
|
335
|
-
|
|
334
|
+
return setting !== undefined ? { reasoning_effort: this.effortFor(model, setting) } : {};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* The highest reasoning level this adapter sends as asked for `model`
|
|
338
|
+
* (ADR 0117). Default: the direct provider's (lib/models/reasoning.ts
|
|
339
|
+
* effortCeiling); the gateway holds every id at `high`.
|
|
340
|
+
*/
|
|
341
|
+
reasoningCeiling(model) {
|
|
342
|
+
return effortCeilingOf(model);
|
|
343
|
+
}
|
|
344
|
+
/** The effort word for one setting, held at reasoningCeiling; a held level is marked on the span (`llm.reasoning.weakened`). */
|
|
345
|
+
effortFor(model, setting) {
|
|
346
|
+
const { word, weakened } = effortWord(model, setting, this.reasoningCeiling(model));
|
|
347
|
+
if (weakened)
|
|
348
|
+
setLlmSpanAttribute('llm.reasoning.weakened', weakened);
|
|
349
|
+
return word;
|
|
336
350
|
}
|
|
337
351
|
/** Provider-specific body fields, merged last. */
|
|
338
352
|
extraBodyFields(_request) {
|
|
@@ -46,6 +46,7 @@ import { claudeClientSpec, endpointFromEnv, endpointLabel, instantiateClient, na
|
|
|
46
46
|
import { currentTurnStart, providerStateOf, withProviderState } from './providerState.js';
|
|
47
47
|
import { errorDecision, errorText } from './errorResponse.js';
|
|
48
48
|
import { adaptiveThinkingFor, claudeGeneration, claudeReasoningOf, claudeUrlImagesOn, THINKING_BINDING_BETA } from './claudeModels.js';
|
|
49
|
+
import { isAboveHigh } from './reasoning.js';
|
|
49
50
|
/** The provider id this adapter reports and writes its state under (lib/models/providerMap.ts). */
|
|
50
51
|
export const ANTHROPIC_PROVIDER = 'anthropic';
|
|
51
52
|
/** The providerState kind this adapter writes: the signed blocks that preceded a part. */
|
|
@@ -393,6 +394,9 @@ export class ClaudeAdapter {
|
|
|
393
394
|
else {
|
|
394
395
|
const requestedBudget = reasoning.budget;
|
|
395
396
|
thinkingConfigured = typeof requestedBudget === 'number' && requestedBudget > 0;
|
|
397
|
+
// The budget generations stop at `high`'s budget (ADR 0117).
|
|
398
|
+
if (isAboveHigh(request.reasoning))
|
|
399
|
+
setLlmSpanAttribute('llm.reasoning.weakened', request.reasoning);
|
|
396
400
|
if (thinkingConfigured && continuesUnsignedToolLoop(messages)) {
|
|
397
401
|
// The tool call this step answers carries no signed thinking (another
|
|
398
402
|
// provider or model made it, or its state was lost), and Anthropic
|
|
@@ -181,9 +181,12 @@ export type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
|
181
181
|
/**
|
|
182
182
|
* How hard an agent reasons, on any provider (ADR 0047): a level, or a token
|
|
183
183
|
* budget. A budget of 0 is `none`, and `none` means as little reasoning as
|
|
184
|
-
* the model allows.
|
|
184
|
+
* the model allows. `xhigh` and `max` are the levels above `high` that some
|
|
185
|
+
* models take (ADR 0117): an adapter whose model stops lower sends its
|
|
186
|
+
* highest setting and marks the span `llm.reasoning.weakened`; a budget
|
|
187
|
+
* never reads as either.
|
|
185
188
|
*/
|
|
186
|
-
export type ReasoningLevel = 'none' | 'low' | 'medium' | 'high';
|
|
189
|
+
export type ReasoningLevel = 'none' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
187
190
|
export type ReasoningSetting = ReasoningLevel | {
|
|
188
191
|
budget_tokens: number;
|
|
189
192
|
};
|
|
@@ -70,7 +70,8 @@ export interface GatewayConfig {
|
|
|
70
70
|
*/
|
|
71
71
|
export declare function gatewayConfig(): GatewayConfig | null;
|
|
72
72
|
/** A human-readable misconfiguration, or undefined when the gateway is
|
|
73
|
-
* either off or usable.
|
|
73
|
+
* either off or usable. An unrecognised value is named as such and never
|
|
74
|
+
* repeated, since it may be a secret pasted into the wrong variable. */
|
|
74
75
|
export declare function gatewayProblem(): string | undefined;
|
|
75
76
|
/** True when a gateway is configured well enough to serve requests. */
|
|
76
77
|
export declare function gatewayUsable(): boolean;
|
|
@@ -81,14 +81,16 @@ export function gatewayConfig() {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
/** A human-readable misconfiguration, or undefined when the gateway is
|
|
84
|
-
* either off or usable.
|
|
84
|
+
* either off or usable. An unrecognised value is named as such and never
|
|
85
|
+
* repeated, since it may be a secret pasted into the wrong variable. */
|
|
85
86
|
export function gatewayProblem() {
|
|
86
87
|
const id = (process.env[GATEWAY_ENV] ?? '').trim();
|
|
87
88
|
if (!id)
|
|
88
89
|
return undefined;
|
|
89
90
|
const cfg = gatewayConfig();
|
|
90
91
|
if (!cfg) {
|
|
91
|
-
|
|
92
|
+
// The value is never echoed: a key pasted into the wrong variable is still a secret.
|
|
93
|
+
return `${GATEWAY_ENV} is set to an unrecognised value (not shown); it must be one of: ${Object.keys(GATEWAYS).join(', ')}`;
|
|
92
94
|
}
|
|
93
95
|
if (!cfg.keyPresent)
|
|
94
96
|
return `${GATEWAY_ENV}=${cfg.gateway.id} is set but ${GATEWAY_KEY_ENV} is not`;
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* adapter replays no providerState: a chat-completions wire has no place
|
|
29
29
|
* for Claude's signed blocks or OpenAI's reasoning items.
|
|
30
30
|
*/
|
|
31
|
-
import type { ToolChoiceMode } from './contract.ts';
|
|
31
|
+
import type { ReasoningLevel, ToolChoiceMode } from './contract.ts';
|
|
32
32
|
import { ChatCompletionsAdapter } from './chatCompletionsAdapter.ts';
|
|
33
33
|
import type { ChatFailure } from './chatCompletionsAdapter.ts';
|
|
34
34
|
export interface GatewayAdapterOptions {
|
|
@@ -44,6 +44,12 @@ export declare class GatewayAdapter extends ChatCompletionsAdapter {
|
|
|
44
44
|
protected endpointUrl(): string;
|
|
45
45
|
protected headers(): Record<string, string>;
|
|
46
46
|
protected wireModelName(model: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* A gateway reads `reasoning_effort` up to `high` whatever the id: the
|
|
49
|
+
* words above it (`xhigh`, `max`) are not accepted across gateways, so
|
|
50
|
+
* they go as `high`, marked on the span (ADR 0117).
|
|
51
|
+
*/
|
|
52
|
+
protected reasoningCeiling(): ReasoningLevel;
|
|
47
53
|
/** A gateway passes tool_choice to the upstream as asked. */
|
|
48
54
|
protected toolChoiceModes(): readonly ToolChoiceMode[];
|
|
49
55
|
protected missingRequirement(): ChatFailure | undefined;
|
|
@@ -52,6 +52,14 @@ export class GatewayAdapter extends ChatCompletionsAdapter {
|
|
|
52
52
|
wireModelName(model) {
|
|
53
53
|
return this.#cfg ? gatewayWireModel(model, this.#cfg.gateway) : model;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* A gateway reads `reasoning_effort` up to `high` whatever the id: the
|
|
57
|
+
* words above it (`xhigh`, `max`) are not accepted across gateways, so
|
|
58
|
+
* they go as `high`, marked on the span (ADR 0117).
|
|
59
|
+
*/
|
|
60
|
+
reasoningCeiling() {
|
|
61
|
+
return 'high';
|
|
62
|
+
}
|
|
55
63
|
/** A gateway passes tool_choice to the upstream as asked. */
|
|
56
64
|
toolChoiceModes() {
|
|
57
65
|
return ['auto', 'none', 'required', 'named'];
|
|
@@ -50,7 +50,7 @@ import { endpointFromEnv, endpointProblems, platformModel } from './endpoints.js
|
|
|
50
50
|
import { CARRIED_PARTS_KIND, GEMINI_PROVIDER, GENAI_PART_KIND, MINTED_CALL_ID_PREFIX, PLACEHOLDER_THOUGHT_SIGNATURE, THOUGHT_SIGNATURE_KIND, isCarriedWirePart, } from './geminiState.js';
|
|
51
51
|
import { currentTurnStart, providerStateOf } from './providerState.js';
|
|
52
52
|
import { classifyError, errorStatus, retryUntilFirstYield } from './retry.js';
|
|
53
|
-
import { reasoningConfig } from './reasoning.js';
|
|
53
|
+
import { isAboveHigh, reasoningConfig } from './reasoning.js';
|
|
54
54
|
import { setLlmSpanAttribute } from '../observability/tracer.js';
|
|
55
55
|
/**
|
|
56
56
|
* The provider id this adapter reports and writes its state under, and the
|
|
@@ -445,11 +445,17 @@ function toolConfigFor(request) {
|
|
|
445
445
|
: undefined;
|
|
446
446
|
return mode ? { functionCallingConfig: { mode } } : undefined;
|
|
447
447
|
}
|
|
448
|
-
/**
|
|
448
|
+
/**
|
|
449
|
+
* ADR 0047's mapping for this model, with the thoughts asked for unless the
|
|
450
|
+
* setting is `none`. Gemini's top is `HIGH` (or `high`'s budget on 2.x), so
|
|
451
|
+
* `xhigh` and `max` go as that, marked on the span (ADR 0117).
|
|
452
|
+
*/
|
|
449
453
|
function thinkingConfigFor(model, setting) {
|
|
450
454
|
const mapped = reasoningConfig(model, setting).thinkingConfig;
|
|
451
455
|
if (!mapped)
|
|
452
456
|
return undefined;
|
|
457
|
+
if (isAboveHigh(setting))
|
|
458
|
+
setLlmSpanAttribute('llm.reasoning.weakened', setting);
|
|
453
459
|
const none = setting === 'none' || (typeof setting === 'object' && setting.budget_tokens <= 0);
|
|
454
460
|
return none ? { ...mapped } : { ...mapped, includeThoughts: true };
|
|
455
461
|
}
|
|
@@ -271,11 +271,15 @@ export interface ModelRequestOptions {
|
|
|
271
271
|
* which every adapter maps to what the budget maps to today (0 included).
|
|
272
272
|
* - else `reasoningEffort`: a level word is that level, and `minimal` is
|
|
273
273
|
* `none` (ADR 0047's rendering of it on the first GPT-5 generation).
|
|
274
|
+
* The words above `high` (`xhigh`, `max`) win over a thinkingConfig that
|
|
275
|
+
* says `high` (`HIGH`, or `high`'s budget of 16,384), which is what the
|
|
276
|
+
* compiler writes beside them (ADR 0117); a thinkingConfig that says less
|
|
277
|
+
* keeps its own reading.
|
|
274
278
|
* Lossy, and absent: a budget of -1 (Gemini's dynamic thinking, which is
|
|
275
|
-
* the provider's default), `THINKING_LEVEL_UNSPECIFIED`,
|
|
276
|
-
* `
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
+
* the provider's default), `THINKING_LEVEL_UNSPECIFIED`, and
|
|
280
|
+
* `includeThoughts`. The compiler writes the effort word beside
|
|
281
|
+
* thinkingConfig from one setting, so preferring thinkingConfig loses
|
|
282
|
+
* nothing it wrote; only the older spelling can set the two apart.
|
|
279
283
|
*/
|
|
280
284
|
export declare function reasoningOf(config: GenerateContentConfig | undefined): ReasoningSetting | undefined;
|
|
281
285
|
/** The function-calling mode as a ToolChoice, and VALIDATED as strict tools. The native request builder reads an agent's config through it too. */
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
import { FinishReason, FunctionCallingConfigMode } from '@google/genai';
|
|
153
153
|
import { ERROR_RETRYABLE_KEY, ERROR_STATUS_KEY, errorText, withRetryVerdict } from './errorResponse.js';
|
|
154
154
|
import { CARRIED_PARTS_KIND, GEMINI_PROVIDER, GENAI_PART_KIND, MINTED_CALL_ID_PREFIX, THOUGHT_SIGNATURE_KIND } from './geminiState.js';
|
|
155
|
-
import { reasoningConfig } from './reasoning.js';
|
|
155
|
+
import { REASONING_BUDGETS, reasoningConfig } from './reasoning.js';
|
|
156
156
|
import { contractToolDeclaration, nativeToolOf, toContractJsonSchema } from './schemaNormalize.js';
|
|
157
157
|
import { MAX_VALUE_DEPTH, nestedDeeperThan } from '../runtime/valueDepth.js';
|
|
158
158
|
/**
|
|
@@ -473,7 +473,15 @@ export function messagesToContents(history) {
|
|
|
473
473
|
}
|
|
474
474
|
// Maps, not object literals: a config value such as `constructor` must read as nothing.
|
|
475
475
|
const THINKING_LEVELS = new Map([['MINIMAL', 'none'], ['LOW', 'low'], ['MEDIUM', 'medium'], ['HIGH', 'high']]);
|
|
476
|
-
const EFFORT_LEVELS = new Map([
|
|
476
|
+
const EFFORT_LEVELS = new Map([
|
|
477
|
+
['none', 'none'],
|
|
478
|
+
['minimal', 'none'],
|
|
479
|
+
['low', 'low'],
|
|
480
|
+
['medium', 'medium'],
|
|
481
|
+
['high', 'high'],
|
|
482
|
+
['xhigh', 'xhigh'],
|
|
483
|
+
['max', 'max'],
|
|
484
|
+
]);
|
|
477
485
|
/**
|
|
478
486
|
* The ReasoningSetting a generateContentConfig asks for, where one is exact:
|
|
479
487
|
* - `thinkingConfig.thinkingLevel`: `MINIMAL` is `none` (ADR 0047's
|
|
@@ -482,24 +490,30 @@ const EFFORT_LEVELS = new Map([['none', 'none'], ['minimal', 'none'], ['low', 'l
|
|
|
482
490
|
* which every adapter maps to what the budget maps to today (0 included).
|
|
483
491
|
* - else `reasoningEffort`: a level word is that level, and `minimal` is
|
|
484
492
|
* `none` (ADR 0047's rendering of it on the first GPT-5 generation).
|
|
493
|
+
* The words above `high` (`xhigh`, `max`) win over a thinkingConfig that
|
|
494
|
+
* says `high` (`HIGH`, or `high`'s budget of 16,384), which is what the
|
|
495
|
+
* compiler writes beside them (ADR 0117); a thinkingConfig that says less
|
|
496
|
+
* keeps its own reading.
|
|
485
497
|
* Lossy, and absent: a budget of -1 (Gemini's dynamic thinking, which is
|
|
486
|
-
* the provider's default), `THINKING_LEVEL_UNSPECIFIED`,
|
|
487
|
-
* `
|
|
488
|
-
*
|
|
489
|
-
*
|
|
498
|
+
* the provider's default), `THINKING_LEVEL_UNSPECIFIED`, and
|
|
499
|
+
* `includeThoughts`. The compiler writes the effort word beside
|
|
500
|
+
* thinkingConfig from one setting, so preferring thinkingConfig loses
|
|
501
|
+
* nothing it wrote; only the older spelling can set the two apart.
|
|
490
502
|
*/
|
|
491
503
|
export function reasoningOf(config) {
|
|
492
504
|
const cfg = (config ?? {});
|
|
505
|
+
const word = EFFORT_LEVELS.get(cfg.reasoningEffort);
|
|
506
|
+
const above = word === 'xhigh' || word === 'max' ? word : undefined;
|
|
493
507
|
const thinking = cfg.thinkingConfig;
|
|
494
508
|
if (isObject(thinking)) {
|
|
495
509
|
const level = THINKING_LEVELS.get(thinking.thinkingLevel);
|
|
496
510
|
if (level)
|
|
497
|
-
return level;
|
|
511
|
+
return above && level === 'high' ? above : level;
|
|
498
512
|
const budget = thinking.thinkingBudget;
|
|
499
513
|
if (typeof budget === 'number' && Number.isInteger(budget) && budget >= 0)
|
|
500
|
-
return { budget_tokens: budget };
|
|
514
|
+
return above && budget === REASONING_BUDGETS.high ? above : { budget_tokens: budget };
|
|
501
515
|
}
|
|
502
|
-
return
|
|
516
|
+
return word;
|
|
503
517
|
}
|
|
504
518
|
function nativeToolsOf(llmRequest) {
|
|
505
519
|
const tools = new Set();
|
|
@@ -187,8 +187,10 @@ export declare class GptAdapter implements ModelAdapter {
|
|
|
187
187
|
* The `reasoning` request field for one setting (ADR 0047), or undefined to
|
|
188
188
|
* send none. OpenAI's reasoning ids ask for summaries, plus the effort in
|
|
189
189
|
* that model's own word (`reasoningConfig`: `none` is `minimal` on the
|
|
190
|
-
* first GPT-5 generation and `low` on the o-series)
|
|
191
|
-
*
|
|
190
|
+
* first GPT-5 generation and `low` on the o-series), held at the model's
|
|
191
|
+
* ceiling (`xhigh` from GPT-5.2, else `high`; ADR 0117), a held level
|
|
192
|
+
* marked on the span. Other ids: nothing. A 400 on the field is retried
|
|
193
|
+
* once without it.
|
|
192
194
|
*/
|
|
193
195
|
reasoningParam(setting: ReasoningSetting | undefined, model?: string): Record<string, unknown> | undefined;
|
|
194
196
|
/**
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
import { endpointFromEnv, entraTokenSource, nativeSearchOn, platformModel } from './endpoints.js';
|
|
46
46
|
import { errorDecision, errorText, statusDecision } from './errorResponse.js';
|
|
47
47
|
import { currentTurnStart, providerStateOf } from './providerState.js';
|
|
48
|
-
import {
|
|
48
|
+
import { effortWord } from './reasoning.js';
|
|
49
49
|
import { toContractJsonSchema } from './schemaNormalize.js';
|
|
50
50
|
import { setLlmSpanAttribute } from '../observability/tracer.js';
|
|
51
51
|
/** The providerState kind the Responses adapters write: the reasoning output items that preceded a part (ADR 0046, ADR 0050). */
|
|
@@ -423,13 +423,20 @@ export class GptAdapter {
|
|
|
423
423
|
* The `reasoning` request field for one setting (ADR 0047), or undefined to
|
|
424
424
|
* send none. OpenAI's reasoning ids ask for summaries, plus the effort in
|
|
425
425
|
* that model's own word (`reasoningConfig`: `none` is `minimal` on the
|
|
426
|
-
* first GPT-5 generation and `low` on the o-series)
|
|
427
|
-
*
|
|
426
|
+
* first GPT-5 generation and `low` on the o-series), held at the model's
|
|
427
|
+
* ceiling (`xhigh` from GPT-5.2, else `high`; ADR 0117), a held level
|
|
428
|
+
* marked on the span. Other ids: nothing. A 400 on the field is retried
|
|
429
|
+
* once without it.
|
|
428
430
|
*/
|
|
429
431
|
reasoningParam(setting, model = this.model) {
|
|
430
432
|
if (!isOpenAiReasoningModel(model))
|
|
431
433
|
return undefined;
|
|
432
|
-
|
|
434
|
+
if (setting === undefined)
|
|
435
|
+
return { summary: 'auto' };
|
|
436
|
+
const { word, weakened } = effortWord(model, setting);
|
|
437
|
+
if (weakened)
|
|
438
|
+
setLlmSpanAttribute('llm.reasoning.weakened', weakened);
|
|
439
|
+
return { summary: 'auto', effort: word };
|
|
433
440
|
}
|
|
434
441
|
/**
|
|
435
442
|
* Whether this id carries its reasoning across the steps of a tool loop
|
|
@@ -63,7 +63,9 @@ export declare class GrokAdapter extends GptAdapter {
|
|
|
63
63
|
* `high`; xAI's own default is `high`, and reasoning cannot be turned off).
|
|
64
64
|
* The request's setting maps through ADR 0047's table, which sends `none`
|
|
65
65
|
* as `low`; with none set, DEFAULT_GROK_REASONING_EFFORT (medium) is pinned,
|
|
66
|
-
* since effort is part of the price.
|
|
66
|
+
* since effort is part of the price. grok-4.7 also takes `xhigh`; `max`,
|
|
67
|
+
* and `xhigh` on 4.5 and 4.6, go as the model's highest word, marked on the
|
|
68
|
+
* span (ADR 0117). Other grok ids take no field.
|
|
67
69
|
*/
|
|
68
70
|
reasoningParam(setting: ReasoningSetting | undefined, model?: string): Record<string, unknown> | undefined;
|
|
69
71
|
/**
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { DEFAULT_GROK_REASONING_EFFORT } from '../config.js';
|
|
28
28
|
import { GptAdapter } from './gptAdapter.js';
|
|
29
|
-
import {
|
|
29
|
+
import { effortWord } from './reasoning.js';
|
|
30
30
|
import { collectionIdsFromEnv, collectionsMaxResultsFromEnv, xaiWebSearchParamsFromEnv, xSearchParamsFromEnv, } from '../tools/xaiSearchParams.js';
|
|
31
|
+
import { setLlmSpanAttribute } from '../observability/tracer.js';
|
|
31
32
|
export const XAI_BASE_URL = 'https://api.x.ai/v1';
|
|
32
33
|
/**
|
|
33
34
|
* The ids that take a reasoning effort and return encrypted reasoning:
|
|
@@ -81,12 +82,19 @@ export class GrokAdapter extends GptAdapter {
|
|
|
81
82
|
* `high`; xAI's own default is `high`, and reasoning cannot be turned off).
|
|
82
83
|
* The request's setting maps through ADR 0047's table, which sends `none`
|
|
83
84
|
* as `low`; with none set, DEFAULT_GROK_REASONING_EFFORT (medium) is pinned,
|
|
84
|
-
* since effort is part of the price.
|
|
85
|
+
* since effort is part of the price. grok-4.7 also takes `xhigh`; `max`,
|
|
86
|
+
* and `xhigh` on 4.5 and 4.6, go as the model's highest word, marked on the
|
|
87
|
+
* span (ADR 0117). Other grok ids take no field.
|
|
85
88
|
*/
|
|
86
89
|
reasoningParam(setting, model = this.model) {
|
|
87
90
|
if (!GROK_REASONING_IDS.test(model))
|
|
88
91
|
return undefined;
|
|
89
|
-
|
|
92
|
+
if (setting === undefined)
|
|
93
|
+
return { effort: DEFAULT_GROK_REASONING_EFFORT };
|
|
94
|
+
const { word, weakened } = effortWord(model, setting);
|
|
95
|
+
if (weakened)
|
|
96
|
+
setLlmSpanAttribute('llm.reasoning.weakened', weakened);
|
|
97
|
+
return { effort: word };
|
|
90
98
|
}
|
|
91
99
|
/**
|
|
92
100
|
* grok-4.5, grok-4.6 and grok-4.7 carry their reasoning across a tool loop
|
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
* goes as its Kimi word (`medium` → `high`, a budget → the level that
|
|
69
69
|
* covers it), `none` as `low` since K3 cannot switch thinking off, and a
|
|
70
70
|
* request with none pins DEFAULT_KIMI_REASONING_EFFORT (lib/config.ts).
|
|
71
|
-
* `max`
|
|
71
|
+
* `reasoning: max` sends `max`, and `xhigh` rounds up to it (ADR 0117):
|
|
72
|
+
* Moonshot's costliest effort, and its default, which the pin avoids.
|
|
72
73
|
* K2.x models take no reasoning_effort: a `thinking: { type }` switch
|
|
73
74
|
* instead, so `none` (or a budget of 0) sends `disabled` and any other
|
|
74
75
|
* setting sends nothing. K2.7 Code (and its highspeed variant) cannot
|
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
* goes as its Kimi word (`medium` → `high`, a budget → the level that
|
|
69
69
|
* covers it), `none` as `low` since K3 cannot switch thinking off, and a
|
|
70
70
|
* request with none pins DEFAULT_KIMI_REASONING_EFFORT (lib/config.ts).
|
|
71
|
-
* `max`
|
|
71
|
+
* `reasoning: max` sends `max`, and `xhigh` rounds up to it (ADR 0117):
|
|
72
|
+
* Moonshot's costliest effort, and its default, which the pin avoids.
|
|
72
73
|
* K2.x models take no reasoning_effort: a `thinking: { type }` switch
|
|
73
74
|
* instead, so `none` (or a budget of 0) sends `disabled` and any other
|
|
74
75
|
* setting sends nothing. K2.7 Code (and its highspeed variant) cannot
|
|
@@ -118,7 +119,6 @@
|
|
|
118
119
|
*/
|
|
119
120
|
import { DEFAULT_KIMI_REASONING_EFFORT } from '../config.js';
|
|
120
121
|
import { ChatCompletionsAdapter, reasonsNotAtAll } from './chatCompletionsAdapter.js';
|
|
121
|
-
import { reasoningConfig } from './reasoning.js';
|
|
122
122
|
import { trimTrailingSlashes } from './urls.js';
|
|
123
123
|
export const MOONSHOT_BASE_URL = 'https://api.moonshot.ai/v1';
|
|
124
124
|
/** The flagship takes `reasoning_effort`; the K2 generation takes a `thinking` switch. */
|
|
@@ -191,7 +191,7 @@ export class KimiAdapter extends ChatCompletionsAdapter {
|
|
|
191
191
|
if (isKimiK3(model)) {
|
|
192
192
|
if (setting === undefined)
|
|
193
193
|
return { reasoning_effort: DEFAULT_KIMI_REASONING_EFFORT };
|
|
194
|
-
const word =
|
|
194
|
+
const word = this.effortFor(model, setting);
|
|
195
195
|
return { reasoning_effort: word === 'none' ? 'low' : word }; // K3 cannot switch thinking off
|
|
196
196
|
}
|
|
197
197
|
// K2.7 Code always thinks, and Moonshot refuses `disabled` for it.
|
|
@@ -12,15 +12,43 @@ import type { ReasoningLevel, ReasoningSetting } from './contract.ts';
|
|
|
12
12
|
/**
|
|
13
13
|
* Thinking tokens per level, for the providers that take a budget (Claude,
|
|
14
14
|
* Gemini 2.x). The same table rounds a `budget_tokens` value up to a level
|
|
15
|
-
* for the providers that take only a level or an effort word.
|
|
15
|
+
* for the providers that take only a level or an effort word. `xhigh` and
|
|
16
|
+
* `max` take `high`'s budget (ADR 0117): above it a non-streaming Claude
|
|
17
|
+
* request passes the Anthropic SDK's ceiling (ADR 0047), so a budget path
|
|
18
|
+
* sends them as `high`, and a budget never rounds up to either.
|
|
16
19
|
*/
|
|
17
20
|
export declare const REASONING_BUDGETS: Readonly<Record<ReasoningLevel, number>>;
|
|
21
|
+
/** The levels in order of how hard they ask the model to think. */
|
|
22
|
+
export declare const REASONING_ORDER: readonly ReasoningLevel[];
|
|
23
|
+
/** The levels above `high`, which only some models take (ADR 0117). */
|
|
24
|
+
export declare const isAboveHigh: (setting: ReasoningSetting | undefined) => setting is 'xhigh' | 'max';
|
|
25
|
+
/**
|
|
26
|
+
* The highest level the direct adapter for `model` sends as asked (ADR
|
|
27
|
+
* 0117); a level above it goes as this one. `max` where every level
|
|
28
|
+
* passes: Claude's adaptive generations (the Claude adapter sends its budget
|
|
29
|
+
* generations `high`'s budget) and Kimi K3. OpenAI's GPT-5.2 and later and
|
|
30
|
+
* grok-4.7 stop at `xhigh`; other OpenAI and Grok ids, Gemini and Ollama at
|
|
31
|
+
* `high`. A gateway stops at `high` whatever the id (gatewayAdapter.ts).
|
|
32
|
+
*/
|
|
33
|
+
export declare function effortCeiling(model: string): ReasoningLevel;
|
|
34
|
+
/**
|
|
35
|
+
* The effort word an adapter sends for one setting: ADR 0047's word for the
|
|
36
|
+
* model, held at `ceiling` (default effortCeiling(model)). `weakened` is the
|
|
37
|
+
* level asked for when the word sent is below it; the adapter marks the span
|
|
38
|
+
* `llm.reasoning.weakened` with it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function effortWord(model: string, setting: ReasoningSetting, ceiling?: ReasoningLevel): {
|
|
41
|
+
word: string;
|
|
42
|
+
weakened?: ReasoningLevel;
|
|
43
|
+
};
|
|
18
44
|
/**
|
|
19
45
|
* The generateContentConfig fields a `reasoning:` setting becomes for one
|
|
20
46
|
* model (ADR 0047). `reasoningEffort` is always set, so the gateway (which
|
|
21
47
|
* may serve any id) carries the level too; the Claude adapter reads it first
|
|
22
48
|
* on the adaptive generations (ADR 0049), and the genai SDK drops it from a
|
|
23
49
|
* Gemini request. Claude and Gemini also get the `thinkingConfig` their
|
|
24
|
-
* adapters read.
|
|
50
|
+
* adapters read. `xhigh` and `max` are written as asked (Kimi's `xhigh` as
|
|
51
|
+
* `max`), beside `high`'s thinkingConfig: the adapter holds the word at its
|
|
52
|
+
* model's ceiling (effortWord), so the setting reaches it intact (ADR 0117).
|
|
25
53
|
*/
|
|
26
54
|
export declare function reasoningConfig(model: string, setting: ReasoningSetting): Record<string, unknown>;
|
|
@@ -2,10 +2,25 @@ import { providerForModel } from './providerMap.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Thinking tokens per level, for the providers that take a budget (Claude,
|
|
4
4
|
* Gemini 2.x). The same table rounds a `budget_tokens` value up to a level
|
|
5
|
-
* for the providers that take only a level or an effort word.
|
|
5
|
+
* for the providers that take only a level or an effort word. `xhigh` and
|
|
6
|
+
* `max` take `high`'s budget (ADR 0117): above it a non-streaming Claude
|
|
7
|
+
* request passes the Anthropic SDK's ceiling (ADR 0047), so a budget path
|
|
8
|
+
* sends them as `high`, and a budget never rounds up to either.
|
|
6
9
|
*/
|
|
7
|
-
export const REASONING_BUDGETS = { none: 0, low: 2048, medium: 8192, high: 16384 };
|
|
8
|
-
const GEMINI_THINKING_LEVEL = { none: 'MINIMAL', low: 'LOW', medium: 'MEDIUM', high: 'HIGH' };
|
|
10
|
+
export const REASONING_BUDGETS = { none: 0, low: 2048, medium: 8192, high: 16384, xhigh: 16384, max: 16384 };
|
|
11
|
+
const GEMINI_THINKING_LEVEL = { none: 'MINIMAL', low: 'LOW', medium: 'MEDIUM', high: 'HIGH', xhigh: 'HIGH', max: 'HIGH' };
|
|
12
|
+
/** The levels in order of how hard they ask the model to think. */
|
|
13
|
+
export const REASONING_ORDER = ['none', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
14
|
+
/** The levels above `high`, which only some models take (ADR 0117). */
|
|
15
|
+
export const isAboveHigh = (setting) => setting === 'xhigh' || setting === 'max';
|
|
16
|
+
/** An OpenAI id that takes `xhigh`: GPT-5.2 and later (the o-series and GPT-5 and 5.1 stop at `high`). */
|
|
17
|
+
function openAiTakesXhigh(model) {
|
|
18
|
+
const m = /^gpt-(\d{1,3})(?:\.(\d{1,3}))?/.exec(model);
|
|
19
|
+
if (!m)
|
|
20
|
+
return false;
|
|
21
|
+
const major = Number(m[1]);
|
|
22
|
+
return major > 5 || (major === 5 && Number(m[2] ?? 0) >= 2);
|
|
23
|
+
}
|
|
9
24
|
/** The smallest level whose budget covers the setting: never less thought than asked. */
|
|
10
25
|
function reasoningLevel(setting) {
|
|
11
26
|
if (typeof setting === 'string')
|
|
@@ -29,18 +44,54 @@ function reasoningEffort(model, level) {
|
|
|
29
44
|
case 'xai':
|
|
30
45
|
return level === 'none' ? 'low' : level; // Grok 4.5/4.7 cannot stop reasoning
|
|
31
46
|
case 'moonshot':
|
|
32
|
-
|
|
47
|
+
// K3 has low | high | max: a missing word rounds up.
|
|
48
|
+
return level === 'medium' ? 'high' : level === 'xhigh' ? 'max' : level;
|
|
33
49
|
default:
|
|
34
50
|
return level;
|
|
35
51
|
}
|
|
36
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The highest level the direct adapter for `model` sends as asked (ADR
|
|
55
|
+
* 0117); a level above it goes as this one. `max` where every level
|
|
56
|
+
* passes: Claude's adaptive generations (the Claude adapter sends its budget
|
|
57
|
+
* generations `high`'s budget) and Kimi K3. OpenAI's GPT-5.2 and later and
|
|
58
|
+
* grok-4.7 stop at `xhigh`; other OpenAI and Grok ids, Gemini and Ollama at
|
|
59
|
+
* `high`. A gateway stops at `high` whatever the id (gatewayAdapter.ts).
|
|
60
|
+
*/
|
|
61
|
+
export function effortCeiling(model) {
|
|
62
|
+
switch (providerForModel(model)) {
|
|
63
|
+
case 'anthropic':
|
|
64
|
+
case 'moonshot':
|
|
65
|
+
return 'max';
|
|
66
|
+
case 'openai':
|
|
67
|
+
return openAiTakesXhigh(model) ? 'xhigh' : 'high';
|
|
68
|
+
case 'xai':
|
|
69
|
+
return /^grok-4\.7(?!\d)/.test(model) ? 'xhigh' : 'high';
|
|
70
|
+
default:
|
|
71
|
+
return 'high';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The effort word an adapter sends for one setting: ADR 0047's word for the
|
|
76
|
+
* model, held at `ceiling` (default effortCeiling(model)). `weakened` is the
|
|
77
|
+
* level asked for when the word sent is below it; the adapter marks the span
|
|
78
|
+
* `llm.reasoning.weakened` with it.
|
|
79
|
+
*/
|
|
80
|
+
export function effortWord(model, setting, ceiling = effortCeiling(model)) {
|
|
81
|
+
const word = reasoningConfig(model, setting).reasoningEffort;
|
|
82
|
+
if (!isAboveHigh(setting) || REASONING_ORDER.indexOf(word) <= REASONING_ORDER.indexOf(ceiling))
|
|
83
|
+
return { word };
|
|
84
|
+
return { word: ceiling, weakened: setting };
|
|
85
|
+
}
|
|
37
86
|
/**
|
|
38
87
|
* The generateContentConfig fields a `reasoning:` setting becomes for one
|
|
39
88
|
* model (ADR 0047). `reasoningEffort` is always set, so the gateway (which
|
|
40
89
|
* may serve any id) carries the level too; the Claude adapter reads it first
|
|
41
90
|
* on the adaptive generations (ADR 0049), and the genai SDK drops it from a
|
|
42
91
|
* Gemini request. Claude and Gemini also get the `thinkingConfig` their
|
|
43
|
-
* adapters read.
|
|
92
|
+
* adapters read. `xhigh` and `max` are written as asked (Kimi's `xhigh` as
|
|
93
|
+
* `max`), beside `high`'s thinkingConfig: the adapter holds the word at its
|
|
94
|
+
* model's ceiling (effortWord), so the setting reaches it intact (ADR 0117).
|
|
44
95
|
*/
|
|
45
96
|
export function reasoningConfig(model, setting) {
|
|
46
97
|
const level = reasoningLevel(setting);
|