melchizedek-agents 1.0.3 → 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 +29 -2
- package/AGENT_SETUP.md +3 -1
- package/CHANGELOG.md +524 -0
- package/DOCUMENTATION.md +178 -43
- package/ONBOARDING.md +339 -0
- package/QUICKSTART.md +15 -2
- package/README.md +6 -2
- package/config/agents/README.md +2 -2
- package/config/agents/examples/ares.yaml +6 -10
- package/config/agents/examples/assistant.yaml +6 -6
- package/config/agents/examples/augustin.yaml +9 -15
- package/config/agents/examples/cartographers.yaml +6 -6
- package/config/agents/examples/council.yaml +7 -7
- package/config/agents/examples/critic.yaml +24 -24
- package/config/agents/examples/harness.yaml +4 -4
- package/config/agents/examples/image_production.yaml +37 -35
- package/config/agents/examples/librarian.yaml +4 -4
- package/config/agents/examples/patient_advocate.yaml +6 -10
- package/config/agents/examples/pipeline.yaml +20 -19
- package/config/agents/examples/research.yaml +36 -43
- package/config/agents/examples/scribe.yaml +31 -32
- package/config/agents/examples/scriptorium.yaml +6 -6
- package/config/agents/examples/structured_critic.yaml +82 -0
- package/config/agents/examples/style_council.yaml +9 -11
- package/config/agents/examples/syndicate.yaml +3 -5
- package/config/agents/examples/tutor.yaml +2 -2
- package/config/agents/examples/weather.yaml +2 -2
- package/config/agents/syndicate.schema.json +859 -13
- package/config/agents/syndicateSchema.yaml +122 -73
- package/config/agents/templates/README.md +1 -1
- package/config/agents/templates/account_memory.yaml +4 -4
- package/config/agents/templates/case_desk.yaml +6 -6
- package/config/agents/templates/conversational.yaml +2 -2
- package/config/agents/templates/draft_review.yaml +6 -6
- package/config/agents/templates/intake_extractor.yaml +64 -62
- package/config/agents/templates/research_brief.yaml +6 -6
- package/config/agents/templates/research_desk.yaml +6 -6
- package/config/agents/templates/review_panel.yaml +8 -8
- package/config/agents/templates/support_triage.yaml +30 -29
- package/config/agents/templates/systems_operator.yaml +24 -5
- package/db/migrations/0014_durable_runs.sql +31 -0
- package/dist/lib/a2a/app.d.ts +27 -0
- package/dist/lib/a2a/app.js +64 -5
- package/dist/lib/a2a/executor.d.ts +7 -1
- package/dist/lib/a2a/executor.js +43 -5
- package/dist/lib/a2a/oauthSetup.d.ts +106 -0
- package/dist/lib/a2a/oauthSetup.js +259 -0
- package/dist/lib/agentDialect.d.ts +76 -0
- package/dist/lib/agentDialect.js +151 -0
- package/dist/lib/compile.d.ts +42 -6
- package/dist/lib/compile.js +97 -45
- package/dist/lib/compileNative.d.ts +11 -3
- package/dist/lib/compileNative.js +20 -1
- package/dist/lib/dispatch.d.ts +10 -5
- package/dist/lib/dispatch.js +10 -5
- package/dist/lib/doctor.d.ts +110 -1
- package/dist/lib/doctor.js +205 -9
- package/dist/lib/loadSyndicate.d.ts +54 -2
- package/dist/lib/loadSyndicate.js +22 -2
- package/dist/lib/memory/namespace.d.ts +6 -5
- package/dist/lib/memory/namespace.js +6 -5
- package/dist/lib/memory/providers.js +3 -4
- package/dist/lib/models/capabilities.d.ts +25 -1
- package/dist/lib/models/capabilities.js +79 -1
- 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/observability/tracer.d.ts +8 -1
- package/dist/lib/observability/tracer.js +33 -5
- package/dist/lib/onboarding.d.ts +134 -0
- package/dist/lib/onboarding.js +539 -0
- package/dist/lib/runtime/approvals.d.ts +8 -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 +23 -3
- package/dist/lib/runtime/native/agentLoop.js +107 -11
- package/dist/lib/runtime/native/checkpoint.d.ts +171 -0
- package/dist/lib/runtime/native/checkpoint.js +359 -0
- package/dist/lib/runtime/native/delegate.d.ts +222 -18
- package/dist/lib/runtime/native/delegate.js +390 -39
- package/dist/lib/runtime/native/interrupts.d.ts +184 -2
- package/dist/lib/runtime/native/interrupts.js +391 -1
- package/dist/lib/runtime/native/request.d.ts +13 -3
- package/dist/lib/runtime/native/request.js +28 -4
- package/dist/lib/runtime/native/telemetry.js +10 -15
- package/dist/lib/runtime/questions.d.ts +7 -4
- package/dist/lib/runtime/sessions.d.ts +1 -1
- package/dist/lib/runtime/syndicateTurn.d.ts +11 -3
- package/dist/lib/runtime/syndicateTurn.js +353 -68
- package/dist/lib/runtime/turnControl.d.ts +56 -0
- package/dist/lib/runtime/turnControl.js +10 -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 +12 -2
- package/dist/lib/storage/postgres/index.js +8 -3
- package/dist/lib/storage/postgres/taskQueue.d.ts +20 -4
- package/dist/lib/storage/postgres/taskQueue.js +29 -5
- package/dist/lib/storage/postgres/taskStore.d.ts +26 -2
- package/dist/lib/storage/postgres/taskStore.js +74 -8
- package/dist/lib/syndicateSchema.d.ts +316 -1
- package/dist/lib/syndicateSchema.js +203 -29
- package/dist/lib/tools/auth.d.ts +20 -6
- package/dist/lib/tools/auth.js +21 -5
- package/dist/lib/tools/credentialEnv.d.ts +28 -0
- package/dist/lib/tools/credentialEnv.js +52 -0
- package/dist/lib/tools/credentialHosts.d.ts +88 -0
- package/dist/lib/tools/credentialHosts.js +165 -0
- package/dist/lib/tools/credentialStore.js +9 -2
- package/dist/lib/tools/credentialUses.d.ts +92 -0
- package/dist/lib/tools/credentialUses.js +112 -0
- package/dist/lib/tools/mcpToolFactory.d.ts +25 -2
- package/dist/lib/tools/mcpToolFactory.js +179 -21
- package/dist/lib/tools/oauthConsent.js +8 -1
- package/dist/lib/tools/oauthHosts.d.ts +73 -0
- package/dist/lib/tools/oauthHosts.js +154 -0
- package/dist/lib/tools/oauthTools.d.ts +242 -0
- package/dist/lib/tools/oauthTools.js +447 -0
- package/dist/lib/tools/openapiTools.d.ts +11 -6
- package/dist/lib/tools/openapiTools.js +88 -38
- package/dist/lib/tools/taskTools.d.ts +61 -6
- package/dist/lib/tools/taskTools.js +145 -21
- package/dist/lib/workflow/turn.d.ts +22 -3
- package/dist/lib/workflow/turn.js +151 -31
- package/dist/lib/workflow.d.ts +14 -7
- package/dist/lib/workflow.js +14 -7
- package/dist/lib/workflowConfig.d.ts +6 -0
- package/dist/scripts/a2a_server.d.ts +36 -0
- package/dist/scripts/a2a_server.js +131 -1
- package/dist/scripts/assistant_worker.d.ts +12 -0
- package/dist/scripts/assistant_worker.js +81 -22
- package/dist/scripts/doctor.d.ts +7 -2
- package/dist/scripts/doctor.js +9 -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 +62 -0
- package/dist/scripts/yaml_codemod.js +652 -0
- package/package.json +8 -2
- package/skills/README.md +11 -2
- package/skills/briefs/_shared.md +1 -1
- package/skills/briefs/melchizedek-author.md +7 -5
- package/skills/briefs/melchizedek-models.md +7 -4
- package/skills/briefs/melchizedek.md +1 -0
- package/skills/briefs/skills-readme.md +3 -1
- package/skills/melchizedek/SKILL.md +1 -0
- package/skills/melchizedek-author/SKILL.md +7 -4
- package/skills/melchizedek-author/assets/minimal.yaml +13 -13
- package/skills/melchizedek-models/SKILL.md +11 -4
- 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
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { PROVIDERS } from './providerMap.js';
|
|
21
21
|
import { planTransport } from './gateway.js';
|
|
22
22
|
import { nativeSearchOn, PLATFORMS_FOR, platformFromEnv } from './endpoints.js';
|
|
23
|
-
import { claudeUrlImagesOn } from './claudeModels.js';
|
|
23
|
+
import { claudeGeneration, claudeUrlImagesOn } from './claudeModels.js';
|
|
24
24
|
/** The platform a direct path uses (ADR 0023); a misconfigured one reads as direct here, the doctor reports it. */
|
|
25
25
|
function directPlatform(provider) {
|
|
26
26
|
try {
|
|
@@ -117,6 +117,7 @@ export const CAPABILITIES = [
|
|
|
117
117
|
'delegation',
|
|
118
118
|
'memory_tools',
|
|
119
119
|
'structured_output',
|
|
120
|
+
'structured_output_with_tools',
|
|
120
121
|
'thinking_with_tools',
|
|
121
122
|
'streaming',
|
|
122
123
|
'vision',
|
|
@@ -126,6 +127,7 @@ export const CAPABILITY_LABELS = {
|
|
|
126
127
|
delegation: 'delegation (subagents as tools)',
|
|
127
128
|
memory_tools: 'memory tools (load_memory)',
|
|
128
129
|
structured_output: 'structured output (outputSchema)',
|
|
130
|
+
structured_output_with_tools: 'structured output beside tools (an outputSchema on an agent that calls tools or delegates)',
|
|
129
131
|
thinking_with_tools: 'thinking with tool use',
|
|
130
132
|
streaming: 'token streaming',
|
|
131
133
|
vision: 'image input',
|
|
@@ -138,12 +140,14 @@ const nativeSearch = (row) => SERVER_SIDE_TOOLS.web_search.includes(row)
|
|
|
138
140
|
? ok()
|
|
139
141
|
: unsupported('no native search on this path; the web_search sentinel is dropped (use web_extract)');
|
|
140
142
|
const responsesReasoningNote = (ids) => `encrypted reasoning items are replayed verbatim within the turn's tool loop, with store: false (ADR 0050); ${ids}`;
|
|
143
|
+
const setModelResponseNote = (why) => `the schema travels as a set_model_response tool beside the agent's tools, so the model is asked, not held, to answer in it: the turn ends when it calls the tool, and its arguments are the answer (${why}; ADR 0109)`;
|
|
141
144
|
const CHAT_THINKING_NOTE = "reasoning: is the lever, sent as reasoning_effort in the model's word, a thinking budget as the level that covers it (ADR 0047); the reasoning is not carried between tool steps, so the model re-reasons each step";
|
|
142
145
|
export const CAPABILITY_MATRIX = {
|
|
143
146
|
gemini: {
|
|
144
147
|
delegation: ok(),
|
|
145
148
|
memory_tools: ok(),
|
|
146
149
|
structured_output: ok(),
|
|
150
|
+
structured_output_with_tools: degraded(setModelResponseNote('on the Gemini API; Gemini 2 and later on Vertex AI take responseJsonSchema beside the tools in one request')),
|
|
147
151
|
thinking_with_tools: ok(),
|
|
148
152
|
streaming: ok(),
|
|
149
153
|
vision: ok(),
|
|
@@ -153,6 +157,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
153
157
|
delegation: ok(),
|
|
154
158
|
memory_tools: ok(),
|
|
155
159
|
structured_output: ok('test', 'output_config.format (json_schema) from Opus 4.8, Sonnet 5 and Haiku 5.5 on; a forced tool call on Claude 4.6 and earlier and Opus 4.7, offered under tool_choice auto when thinking is on (ADR 0049)'),
|
|
160
|
+
structured_output_with_tools: ok('test', 'output_config.format beside the tools in one request from Opus 4.8, Sonnet 5 and Haiku 5.5 on; Claude 4.6 and earlier and Opus 4.7 get a set_model_response tool beside them (ADR 0109)'),
|
|
156
161
|
thinking_with_tools: ok('test', "a thinking budget on Claude 4.6 and earlier, adaptive thinking with output_config.effort after (ADR 0049); signed thinking blocks are replayed verbatim within the turn's tool loop (ADR 0046), and where the model binds them to the conversation (Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5) under drop_block, so a block whose history changed is dropped rather than rejected; with a budget, a step answering another model's tool call runs without thinking"),
|
|
157
162
|
streaming: ok(),
|
|
158
163
|
vision: ok('test', 'user-turn images only'),
|
|
@@ -162,6 +167,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
162
167
|
delegation: ok(),
|
|
163
168
|
memory_tools: ok(),
|
|
164
169
|
structured_output: ok(),
|
|
170
|
+
structured_output_with_tools: ok('test', 'text.format (strict json_schema) beside the tools in one request (ADR 0109)'),
|
|
165
171
|
thinking_with_tools: ok('test', responsesReasoningNote('reasoning ids only (o-series, gpt-5*)')),
|
|
166
172
|
streaming: ok(),
|
|
167
173
|
vision: ok('test', 'user-turn images only'),
|
|
@@ -171,6 +177,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
171
177
|
delegation: ok(),
|
|
172
178
|
memory_tools: ok(),
|
|
173
179
|
structured_output: ok(),
|
|
180
|
+
structured_output_with_tools: degraded(setModelResponseNote('the schema is not yet sent beside tools on xAI')),
|
|
174
181
|
thinking_with_tools: ok('test', responsesReasoningNote('grok-4.5, grok-4.6 and grok-4.7; other grok ids re-reason each step')),
|
|
175
182
|
streaming: ok(),
|
|
176
183
|
vision: ok('test', 'user-turn images only'),
|
|
@@ -180,6 +187,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
180
187
|
delegation: ok(),
|
|
181
188
|
memory_tools: ok(),
|
|
182
189
|
structured_output: ok('test', 'strict json_schema; kimi-k2.6 is documented as unstable on complex schemas ($ref, oneOf)'),
|
|
190
|
+
structured_output_with_tools: degraded(setModelResponseNote('the schema is not yet sent beside tools on Moonshot')),
|
|
183
191
|
thinking_with_tools: ok('test', "reasoning_content is sent back on the turn's tool-loop assistant messages for the same model (ADR 0046) on kimi-k3, kimi-k2.6 and kimi-k2.7-code; earlier turns' reasoning is not, which K3 and K2.7 Code also ask for; effort travels as reasoning_effort (K3) or a thinking switch (K2.x)"),
|
|
184
192
|
streaming: ok(),
|
|
185
193
|
vision: ok('test', 'user-turn images only, sent as base64 (Moonshot takes no public image URLs)'),
|
|
@@ -189,6 +197,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
189
197
|
delegation: ok(),
|
|
190
198
|
memory_tools: ok(),
|
|
191
199
|
structured_output: ok('test', 'json_schema, enforced by grammar-constrained decoding from Ollama 0.5.0 (an older server ignores it); not enforced on Ollama Cloud (ADR 0096)'),
|
|
200
|
+
structured_output_with_tools: degraded(setModelResponseNote('grammar-constrained decoding to the schema would hold back the tool calls')),
|
|
192
201
|
thinking_with_tools: degraded(CHAT_THINKING_NOTE),
|
|
193
202
|
streaming: ok(),
|
|
194
203
|
vision: ok('test', 'needs a vision model, e.g. ollama/qwen3-vl:8b'),
|
|
@@ -198,6 +207,7 @@ export const CAPABILITY_MATRIX = {
|
|
|
198
207
|
delegation: ok(),
|
|
199
208
|
memory_tools: ok(),
|
|
200
209
|
structured_output: ok('test', 'strict json_schema; upstream support varies by model'),
|
|
210
|
+
structured_output_with_tools: degraded(setModelResponseNote('upstream support for a schema beside tools varies by model')),
|
|
201
211
|
thinking_with_tools: degraded(CHAT_THINKING_NOTE),
|
|
202
212
|
streaming: ok(),
|
|
203
213
|
vision: ok('test', 'upstream model must accept images'),
|
|
@@ -215,6 +225,62 @@ export function capabilityOf(model, capability, opts = {}) {
|
|
|
215
225
|
}
|
|
216
226
|
return { row, ...CAPABILITY_MATRIX[row][capability] };
|
|
217
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
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Whether an outputSchema goes in the same request as the agent's tools, as
|
|
247
|
+
* the provider's own structured-output field, on the path `model` takes
|
|
248
|
+
* (ADR 0109). True only where the `structured_output_with_tools` cell is
|
|
249
|
+
* supported and the model's generation takes it: Claude from Opus 4.8,
|
|
250
|
+
* Sonnet 5 and Haiku 5.5 on (`output_config.format`), every OpenAI id
|
|
251
|
+
* (`text.format`), Gemini 2 and later on Vertex AI (`responseJsonSchema`).
|
|
252
|
+
* Elsewhere the native loop declares set_model_response beside the tools
|
|
253
|
+
* (lib/runtime/native/request.ts), which works on every path. A path that
|
|
254
|
+
* cannot be planned (a malformed gateway setting) answers false, the form
|
|
255
|
+
* that works everywhere.
|
|
256
|
+
*/
|
|
257
|
+
export function outputSchemaBesideTools(model, opts = {}) {
|
|
258
|
+
let cell;
|
|
259
|
+
try {
|
|
260
|
+
cell = capabilityOf(model, 'structured_output_with_tools', opts);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
if (cell.support !== 'supported')
|
|
266
|
+
return false;
|
|
267
|
+
switch (cell.row) {
|
|
268
|
+
case 'anthropic':
|
|
269
|
+
return claudeGeneration(model).structuredOutput === 'output_format';
|
|
270
|
+
case 'gemini':
|
|
271
|
+
return geminiMajorVersion(model) >= 2;
|
|
272
|
+
default:
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/** A Gemini id's major version (a Vertex AI resource name's last segment), or 0 when it is not a `gemini-<n>` id. Read without a pattern. */
|
|
277
|
+
function geminiMajorVersion(model) {
|
|
278
|
+
const name = model.slice(model.lastIndexOf('/') + 1);
|
|
279
|
+
if (!name.startsWith('gemini-'))
|
|
280
|
+
return 0;
|
|
281
|
+
const major = Number.parseInt(name.slice('gemini-'.length), 10);
|
|
282
|
+
return Number.isFinite(major) ? major : 0;
|
|
283
|
+
}
|
|
218
284
|
export function requiredCapabilities(agent) {
|
|
219
285
|
const tools = agent.tools ?? [];
|
|
220
286
|
const needs = new Set();
|
|
@@ -224,6 +290,8 @@ export function requiredCapabilities(agent) {
|
|
|
224
290
|
needs.add('memory_tools');
|
|
225
291
|
if (agent.outputSchema)
|
|
226
292
|
needs.add('structured_output');
|
|
293
|
+
if (agent.outputSchema && (tools.length > 0 || agent.delegates))
|
|
294
|
+
needs.add('structured_output_with_tools');
|
|
227
295
|
const thinking = agent.generateContentConfig?.thinkingConfig;
|
|
228
296
|
const thinks = agent.reasoning !== undefined
|
|
229
297
|
? agent.reasoning !== 'none' && !(typeof agent.reasoning === 'object' && agent.reasoning.budget_tokens === 0)
|
|
@@ -256,6 +324,9 @@ export function capabilityGaps(model, agent, opts = {}) {
|
|
|
256
324
|
export function platformCell(provider, platform, capability) {
|
|
257
325
|
if (platform === 'direct')
|
|
258
326
|
return undefined;
|
|
327
|
+
if (capability === 'structured_output_with_tools' && provider === 'gemini' && platform === 'vertex') {
|
|
328
|
+
return ok('test', 'responseJsonSchema beside the tools in one request on Gemini 2 and later; an earlier id gets set_model_response (ADR 0109)');
|
|
329
|
+
}
|
|
259
330
|
if (capability === 'vision' && provider === 'anthropic' && !claudeUrlImagesOn(platform)) {
|
|
260
331
|
return degraded(`user-turn images inline (base64) only; an image given by URL is dropped, since ${PLATFORM_LABEL[platform]} takes no URL image source`);
|
|
261
332
|
}
|
|
@@ -293,6 +364,13 @@ export function renderCapabilityMatrix() {
|
|
|
293
364
|
lines.push('');
|
|
294
365
|
notes.forEach((n, i) => lines.push(`${i + 1}. ${n}`));
|
|
295
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('');
|
|
296
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.');
|
|
297
375
|
lines.push('');
|
|
298
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.
|