mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
fix(kiro): map GPT-5.6 reasoning effort fields
Route GPT-5.6 reasoning effort through Kiro's native reasoning.effort field instead of the legacy Claude output_config.effort path. GPT-5.6 models now emit reasoning.effort for low/medium/high/xhigh, with max mapped to the xhigh wire value. Preserve the Responses API reasoning.effort through the OpenAI intermediate by copying it to reasoning_effort before the field is dropped. Skip legacy thinking_mode prompt tags when a supported native GPT effort is emitted, while keeping the legacy fallback for unsupported values (auto/minimal/ultra) and explicit disable semantics (none/off/disabled). Claude adaptive effort continues to use thinking plus output_config.effort.
This commit is contained in:
@@ -8,8 +8,8 @@
|
|||||||
* - `-agentic` model suffix detection + chunked-write system prompt
|
* - `-agentic` model suffix detection + chunked-write system prompt
|
||||||
* - reasoning / thinking trigger detection (Anthropic-Beta header,
|
* - reasoning / thinking trigger detection (Anthropic-Beta header,
|
||||||
* Claude `thinking`, OpenAI `reasoning_effort`, AMP/Cursor magic tag)
|
* Claude `thinking`, OpenAI `reasoning_effort`, AMP/Cursor magic tag)
|
||||||
* - the `<thinking_mode>enabled</thinking_mode>` system-prompt injection
|
* - schema-specific native effort fields for supported GPT and Claude models
|
||||||
* that turns Kiro reasoning on
|
* - legacy `<thinking_mode>` system-prompt injection for other models
|
||||||
*
|
*
|
||||||
* Kiro upstream does not advertise `-agentic` model IDs; they are a 9router
|
* Kiro upstream does not advertise `-agentic` model IDs; they are a 9router
|
||||||
* fiction. The suffix is stripped before the request leaves this process.
|
* fiction. The suffix is stripped before the request leaves this process.
|
||||||
@@ -109,6 +109,7 @@ export function resolveKiroThinkingBudget(body, headers, model) {
|
|||||||
const cfg = extractThinking(body);
|
const cfg = extractThinking(body);
|
||||||
if (cfg) {
|
if (cfg) {
|
||||||
if (cfg.mode === "none") return null;
|
if (cfg.mode === "none") return null;
|
||||||
|
if (cfg.mode === "level" && cfg.level === "disabled") return null;
|
||||||
if (cfg.mode === "budget") return cfg.budget;
|
if (cfg.mode === "budget") return cfg.budget;
|
||||||
if (cfg.mode === "level") return effortToBudget(cfg.level) ?? KIRO_THINKING_BUDGET_DEFAULT;
|
if (cfg.mode === "level") return effortToBudget(cfg.level) ?? KIRO_THINKING_BUDGET_DEFAULT;
|
||||||
return KIRO_THINKING_BUDGET_DEFAULT;
|
return KIRO_THINKING_BUDGET_DEFAULT;
|
||||||
@@ -144,8 +145,25 @@ export function extractKiroEffortLevel(body) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractKiroGptEffortLevel(body) {
|
||||||
|
const effort =
|
||||||
|
body?.output_config?.effort ??
|
||||||
|
body?.reasoning_effort ??
|
||||||
|
(typeof body?.reasoning === "object" ? body.reasoning?.effort : null);
|
||||||
|
if (typeof effort !== "string") return null;
|
||||||
|
const normalized = effort.toLowerCase();
|
||||||
|
if (normalized === "max") return "xhigh";
|
||||||
|
// Kiro CLI does not advertise an explicit GPT "none" wire value; omit it.
|
||||||
|
if (["low", "medium", "high", "xhigh"].includes(normalized)) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildKiroAdditionalModelRequestFields(body, effortPath = "output_config") {
|
export function buildKiroAdditionalModelRequestFields(body, effortPath = "output_config") {
|
||||||
const effort = extractKiroEffortLevel(body);
|
const effort = effortPath === "reasoning"
|
||||||
|
? extractKiroGptEffortLevel(body)
|
||||||
|
: extractKiroEffortLevel(body);
|
||||||
if (!effort) return undefined;
|
if (!effort) return undefined;
|
||||||
if (effortPath === "reasoning") {
|
if (effortPath === "reasoning") {
|
||||||
// Mirrors Kiro CLI/KAS buildEffortRequestFields("reasoning") for GPT.
|
// Mirrors Kiro CLI/KAS buildEffortRequestFields("reasoning") for GPT.
|
||||||
@@ -183,6 +201,11 @@ export function supportsKiroAdditionalModelRequestFields(model) {
|
|||||||
return resolveKiroEffortPath(model) !== null;
|
return resolveKiroEffortPath(model) !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function usesKiroNativeGptEffort(body, model) {
|
||||||
|
return resolveKiroEffortPath(model) === "reasoning"
|
||||||
|
&& extractKiroGptEffortLevel(body) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildKiroAdditionalModelRequestFieldsForModel(body, model) {
|
export function buildKiroAdditionalModelRequestFieldsForModel(body, model) {
|
||||||
const effortPath = resolveKiroEffortPath(model);
|
const effortPath = resolveKiroEffortPath(model);
|
||||||
if (!effortPath) return undefined;
|
if (!effortPath) return undefined;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
KIRO_AGENTIC_SYSTEM_PROMPT,
|
KIRO_AGENTIC_SYSTEM_PROMPT,
|
||||||
resolveDefaultProfileArn,
|
resolveDefaultProfileArn,
|
||||||
buildKiroAdditionalModelRequestFieldsForModel,
|
buildKiroAdditionalModelRequestFieldsForModel,
|
||||||
|
usesKiroNativeGptEffort,
|
||||||
} from "../../config/kiroConstants.js";
|
} from "../../config/kiroConstants.js";
|
||||||
import { DEFAULT_IMAGE_MIME } from "../schema/index.js";
|
import { DEFAULT_IMAGE_MIME } from "../schema/index.js";
|
||||||
import { ROLE, CLAUDE_BLOCK } from "../schema/index.js";
|
import { ROLE, CLAUDE_BLOCK } from "../schema/index.js";
|
||||||
@@ -390,6 +391,8 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
|||||||
|
|
||||||
const { upstream: upstreamModel, agentic } = resolveKiroModel(model);
|
const { upstream: upstreamModel, agentic } = resolveKiroModel(model);
|
||||||
const thinkingBudget = resolveKiroThinkingBudget(body, credentials?.rawHeaders, model);
|
const thinkingBudget = resolveKiroThinkingBudget(body, credentials?.rawHeaders, model);
|
||||||
|
const additionalModelRequestFields = buildKiroAdditionalModelRequestFieldsForModel(body, upstreamModel);
|
||||||
|
const usesNativeGptEffort = usesKiroNativeGptEffort(body, upstreamModel);
|
||||||
|
|
||||||
// Guard 1: no client tools → flatten all tool interactions to text.
|
// Guard 1: no client tools → flatten all tool interactions to text.
|
||||||
if (!clientProvidedTools) {
|
if (!clientProvidedTools) {
|
||||||
@@ -421,7 +424,9 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
|||||||
// enforce top-level systemPrompt for direct calls.
|
// enforce top-level systemPrompt for direct calls.
|
||||||
const timestamp = new Date().toISOString();
|
const timestamp = new Date().toISOString();
|
||||||
const systemPromptParts = [];
|
const systemPromptParts = [];
|
||||||
if (thinkingBudget !== null) systemPromptParts.push(buildThinkingSystemPrefix(thinkingBudget));
|
if (thinkingBudget !== null && !usesNativeGptEffort) {
|
||||||
|
systemPromptParts.push(buildThinkingSystemPrefix(thinkingBudget));
|
||||||
|
}
|
||||||
if (agentic) systemPromptParts.push(KIRO_AGENTIC_SYSTEM_PROMPT);
|
if (agentic) systemPromptParts.push(KIRO_AGENTIC_SYSTEM_PROMPT);
|
||||||
const systemInstruction = extractClaudeSystemText(body.system);
|
const systemInstruction = extractClaudeSystemText(body.system);
|
||||||
if (systemInstruction) systemPromptParts.push(systemInstruction);
|
if (systemInstruction) systemPromptParts.push(systemInstruction);
|
||||||
@@ -481,7 +486,6 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
|||||||
|
|
||||||
if (profileArn) payload.profileArn = profileArn;
|
if (profileArn) payload.profileArn = profileArn;
|
||||||
if (systemPrompt) payload.systemPrompt = systemPrompt;
|
if (systemPrompt) payload.systemPrompt = systemPrompt;
|
||||||
const additionalModelRequestFields = buildKiroAdditionalModelRequestFieldsForModel(body, upstreamModel);
|
|
||||||
if (additionalModelRequestFields) {
|
if (additionalModelRequestFields) {
|
||||||
payload.additionalModelRequestFields = additionalModelRequestFields;
|
payload.additionalModelRequestFields = additionalModelRequestFields;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ export function openaiResponsesToOpenAIRequest(model, body, stream, credentials)
|
|||||||
delete result.include;
|
delete result.include;
|
||||||
delete result.prompt_cache_key;
|
delete result.prompt_cache_key;
|
||||||
delete result.store;
|
delete result.store;
|
||||||
|
if (typeof result.reasoning?.effort === "string") {
|
||||||
|
result.reasoning_effort = result.reasoning.effort;
|
||||||
|
}
|
||||||
delete result.reasoning;
|
delete result.reasoning;
|
||||||
delete result.client_metadata;
|
delete result.client_metadata;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import {
|
|||||||
buildThinkingSystemPrefix,
|
buildThinkingSystemPrefix,
|
||||||
KIRO_AGENTIC_SYSTEM_PROMPT,
|
KIRO_AGENTIC_SYSTEM_PROMPT,
|
||||||
resolveDefaultProfileArn,
|
resolveDefaultProfileArn,
|
||||||
buildKiroAdditionalModelRequestFieldsForModel
|
buildKiroAdditionalModelRequestFieldsForModel,
|
||||||
|
usesKiroNativeGptEffort
|
||||||
} from "../../config/kiroConstants.js";
|
} from "../../config/kiroConstants.js";
|
||||||
import { parseDataUri } from "../concerns/image.js";
|
import { parseDataUri } from "../concerns/image.js";
|
||||||
import { DEFAULT_IMAGE_MIME } from "../schema/index.js";
|
import { DEFAULT_IMAGE_MIME } from "../schema/index.js";
|
||||||
@@ -513,8 +514,8 @@ function convertMessages(messages, tools, model) {
|
|||||||
*
|
*
|
||||||
* 2. Thinking / reasoning. Detection covers Anthropic-Beta header, Claude API
|
* 2. Thinking / reasoning. Detection covers Anthropic-Beta header, Claude API
|
||||||
* `thinking`, OpenAI `reasoning_effort`, AMP/Cursor magic tags, and model
|
* `thinking`, OpenAI `reasoning_effort`, AMP/Cursor magic tags, and model
|
||||||
* name hints. Kiro's prompt tags remain for compatibility, while supported
|
* name hints. Supported models receive Kiro's schema-specific effort fields;
|
||||||
* models also receive the same schema-specific effort fields as Kiro CLI.
|
* legacy prompt tags remain only for models that need them.
|
||||||
*/
|
*/
|
||||||
export function openaiToKiroRequest(model, body, stream, credentials) {
|
export function openaiToKiroRequest(model, body, stream, credentials) {
|
||||||
const messages = body.messages || [];
|
const messages = body.messages || [];
|
||||||
@@ -525,6 +526,8 @@ export function openaiToKiroRequest(model, body, stream, credentials) {
|
|||||||
|
|
||||||
const { upstream: upstreamModel, agentic } = resolveKiroModel(model);
|
const { upstream: upstreamModel, agentic } = resolveKiroModel(model);
|
||||||
const thinkingBudget = resolveKiroThinkingBudget(body, credentials?.rawHeaders, model);
|
const thinkingBudget = resolveKiroThinkingBudget(body, credentials?.rawHeaders, model);
|
||||||
|
const additionalModelRequestFields = buildKiroAdditionalModelRequestFieldsForModel(body, upstreamModel);
|
||||||
|
const usesNativeGptEffort = usesKiroNativeGptEffort(body, upstreamModel);
|
||||||
|
|
||||||
const { history, currentMessage } = convertMessages(messages, tools, upstreamModel);
|
const { history, currentMessage } = convertMessages(messages, tools, upstreamModel);
|
||||||
|
|
||||||
@@ -552,7 +555,7 @@ export function openaiToKiroRequest(model, body, stream, credentials) {
|
|||||||
// too because the CodeWhisperer surface does not always enforce top-level
|
// too because the CodeWhisperer surface does not always enforce top-level
|
||||||
// systemPrompt for direct calls.
|
// systemPrompt for direct calls.
|
||||||
const systemPromptParts = [];
|
const systemPromptParts = [];
|
||||||
if (thinkingBudget !== null) {
|
if (thinkingBudget !== null && !usesNativeGptEffort) {
|
||||||
systemPromptParts.push(buildThinkingSystemPrefix(thinkingBudget));
|
systemPromptParts.push(buildThinkingSystemPrefix(thinkingBudget));
|
||||||
}
|
}
|
||||||
if (agentic) {
|
if (agentic) {
|
||||||
@@ -610,7 +613,6 @@ export function openaiToKiroRequest(model, body, stream, credentials) {
|
|||||||
payload.profileArn = profileArn;
|
payload.profileArn = profileArn;
|
||||||
}
|
}
|
||||||
if (systemPrompt) payload.systemPrompt = systemPrompt;
|
if (systemPrompt) payload.systemPrompt = systemPrompt;
|
||||||
const additionalModelRequestFields = buildKiroAdditionalModelRequestFieldsForModel(body, upstreamModel);
|
|
||||||
if (additionalModelRequestFields) {
|
if (additionalModelRequestFields) {
|
||||||
payload.additionalModelRequestFields = additionalModelRequestFields;
|
payload.additionalModelRequestFields = additionalModelRequestFields;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,34 @@ import { translateRequest } from "../../open-sse/translator/index.js";
|
|||||||
import { FORMATS } from "../../open-sse/translator/formats.js";
|
import { FORMATS } from "../../open-sse/translator/formats.js";
|
||||||
|
|
||||||
const O2K = (body) => translateRequest(FORMATS.OPENAI, FORMATS.KIRO, "m", body, true, null, "kiro");
|
const O2K = (body) => translateRequest(FORMATS.OPENAI, FORMATS.KIRO, "m", body, true, null, "kiro");
|
||||||
|
const R2K = (model, body) => translateRequest(
|
||||||
|
FORMATS.OPENAI_RESPONSES,
|
||||||
|
FORMATS.KIRO,
|
||||||
|
model,
|
||||||
|
body,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
"kiro"
|
||||||
|
);
|
||||||
|
|
||||||
describe("OpenAI → Kiro", () => {
|
describe("OpenAI → Kiro", () => {
|
||||||
|
it.each([
|
||||||
|
["high", "gpt-5.6-sol"],
|
||||||
|
["medium", "gpt-5.6-terra"],
|
||||||
|
["low", "gpt-5.6-luna"],
|
||||||
|
])("preserves Responses reasoning.effort %s through the full Kiro route", (effort, model) => {
|
||||||
|
const out = R2K(model, {
|
||||||
|
input: "Use the requested effort",
|
||||||
|
reasoning: { effort },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(out.additionalModelRequestFields).toEqual({
|
||||||
|
reasoning: { effort },
|
||||||
|
});
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<thinking_mode>");
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<max_thinking_length>");
|
||||||
|
});
|
||||||
|
|
||||||
// openai-to-kiro.js — safeJSONParse guards bad tool-call JSON (fixed in PR #1582)
|
// openai-to-kiro.js — safeJSONParse guards bad tool-call JSON (fixed in PR #1582)
|
||||||
it("malformed tool arguments do not throw the whole request", () => {
|
it("malformed tool arguments do not throw the whole request", () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
|||||||
@@ -112,12 +112,54 @@ describe("Claude → Kiro (direct route)", () => {
|
|||||||
expect(out.systemPrompt).toContain("<max_thinking_length>24576</max_thinking_length>");
|
expect(out.systemPrompt).toContain("<max_thinking_length>24576</max_thinking_length>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps Claude-format effort to GPT-5.6 Kiro CLI reasoning fields", () => {
|
it("maps Claude-format effort to GPT-5.6 reasoning fields without legacy prompt tags", () => {
|
||||||
const out = C2K({
|
const out = C2K({
|
||||||
output_config: { effort: "low" },
|
output_config: { effort: "low" },
|
||||||
messages: [{ role: "user", content: "think lightly" }],
|
messages: [{ role: "user", content: "think lightly" }],
|
||||||
}, null, "gpt-5.6-sol");
|
}, null, "gpt-5.6-sol");
|
||||||
|
|
||||||
|
expect(out.additionalModelRequestFields).toEqual({
|
||||||
|
reasoning: { effort: "low" },
|
||||||
|
});
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<thinking_mode>");
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<max_thinking_length>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(["auto", "minimal", "ultra"])(
|
||||||
|
"keeps the legacy thinking fallback for unsupported GPT-5.6 effort %s",
|
||||||
|
(effort) => {
|
||||||
|
const out = C2K({
|
||||||
|
output_config: { effort },
|
||||||
|
messages: [{ role: "user", content: "Use legacy thinking" }],
|
||||||
|
}, null, "gpt-5.6-sol");
|
||||||
|
|
||||||
|
expect(out.additionalModelRequestFields).toBeUndefined();
|
||||||
|
expect(out.systemPrompt).toContain("<thinking_mode>enabled</thinking_mode>");
|
||||||
|
expect(out.systemPrompt).toContain("<max_thinking_length>");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(["none", "off", "disabled"])(
|
||||||
|
"keeps GPT-5.6 reasoning intentionally disabled for effort %s",
|
||||||
|
(effort) => {
|
||||||
|
const out = C2K({
|
||||||
|
output_config: { effort },
|
||||||
|
messages: [{ role: "user", content: "Do not reason" }],
|
||||||
|
}, null, "gpt-5.6-sol");
|
||||||
|
|
||||||
|
expect(out.additionalModelRequestFields).toBeUndefined();
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<thinking_mode>");
|
||||||
|
expect(out.systemPrompt || "").not.toContain("<max_thinking_length>");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it("keeps explicit Claude effort ahead of an injected OpenAI effort", () => {
|
||||||
|
const out = C2K({
|
||||||
|
output_config: { effort: "low" },
|
||||||
|
reasoning_effort: "high",
|
||||||
|
messages: [{ role: "user", content: "honor the client effort" }],
|
||||||
|
}, null, "gpt-5.6-sol");
|
||||||
|
|
||||||
expect(out.additionalModelRequestFields).toEqual({
|
expect(out.additionalModelRequestFields).toEqual({
|
||||||
reasoning: { effort: "low" },
|
reasoning: { effort: "low" },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -316,42 +316,100 @@ describe("openaiToKiroRequest", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps GPT-5.6 reasoning.effort high to Kiro CLI reasoning fields", () => {
|
it.each([
|
||||||
|
["high", "gpt-5.6-sol"],
|
||||||
|
["medium", "kiro/gpt-5.6-terra"],
|
||||||
|
["low", "gpt-5.6-luna"],
|
||||||
|
])("maps GPT-5.6 reasoning.effort %s without legacy prompt tags", (effort, model) => {
|
||||||
const body = {
|
const body = {
|
||||||
reasoning: { effort: "high" },
|
reasoning: { effort },
|
||||||
messages: [{ role: "user", content: "Think deeply" }]
|
messages: [{ role: "user", content: "Use the requested effort" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = openaiToKiroRequest(model, body, true, {});
|
||||||
|
|
||||||
|
expect(result.additionalModelRequestFields).toEqual({
|
||||||
|
reasoning: { effort },
|
||||||
|
});
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<thinking_mode>");
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<max_thinking_length>");
|
||||||
|
expect(contentOf(result)).not.toContain("<thinking_mode>");
|
||||||
|
expect(contentOf(result)).not.toContain("<max_thinking_length>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
["xhigh", "gpt-5.6-terra", "xhigh"],
|
||||||
|
["max", "gpt-5.6-sol", "xhigh"],
|
||||||
|
])("preserves GPT-5.6 effort %s as supported wire effort %s", (effort, model, wireEffort) => {
|
||||||
|
const body = {
|
||||||
|
reasoning: { effort },
|
||||||
|
messages: [{ role: "user", content: "Use extended effort" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = openaiToKiroRequest(model, body, true, {});
|
||||||
|
|
||||||
|
expect(result.additionalModelRequestFields).toEqual({
|
||||||
|
reasoning: { effort: wireEffort },
|
||||||
|
});
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<thinking_mode>");
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<max_thinking_length>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("omits GPT-5.6 effort fields and legacy prompt tags when effort is absent", () => {
|
||||||
|
const body = {
|
||||||
|
messages: [{ role: "user", content: "No explicit reasoning effort" }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = openaiToKiroRequest("gpt-5.6-sol", body, true, {});
|
const result = openaiToKiroRequest("gpt-5.6-sol", body, true, {});
|
||||||
|
|
||||||
expect(systemPromptOf(result)).toContain("<max_thinking_length>24576</max_thinking_length>");
|
expect(result.additionalModelRequestFields).toBeUndefined();
|
||||||
expect(result.additionalModelRequestFields).toEqual({
|
expect(systemPromptOf(result)).not.toContain("<thinking_mode>");
|
||||||
reasoning: { effort: "high" },
|
expect(systemPromptOf(result)).not.toContain("<max_thinking_length>");
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps prefixed GPT-5.6 reasoning_effort medium to Kiro CLI reasoning fields", () => {
|
it.each(["auto", "minimal", "ultra"])(
|
||||||
|
"keeps the legacy thinking fallback for unsupported GPT-5.6 effort %s",
|
||||||
|
(effort) => {
|
||||||
|
const body = {
|
||||||
|
reasoning: { effort },
|
||||||
|
messages: [{ role: "user", content: "Use legacy thinking" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = openaiToKiroRequest("gpt-5.6-luna", body, true, {});
|
||||||
|
|
||||||
|
expect(result.additionalModelRequestFields).toBeUndefined();
|
||||||
|
expect(systemPromptOf(result)).toContain("<thinking_mode>enabled</thinking_mode>");
|
||||||
|
expect(systemPromptOf(result)).toContain("<max_thinking_length>");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(["none", "off", "disabled"])(
|
||||||
|
"keeps GPT-5.6 reasoning intentionally disabled for effort %s",
|
||||||
|
(effort) => {
|
||||||
|
const body = {
|
||||||
|
reasoning: { effort },
|
||||||
|
messages: [{ role: "user", content: "Do not reason" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = openaiToKiroRequest("gpt-5.6-luna", body, true, {});
|
||||||
|
|
||||||
|
expect(result.additionalModelRequestFields).toBeUndefined();
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<thinking_mode>");
|
||||||
|
expect(systemPromptOf(result)).not.toContain("<max_thinking_length>");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it("keeps the thinking-alias fallback when GPT effort is blank", () => {
|
||||||
const body = {
|
const body = {
|
||||||
reasoning_effort: "medium",
|
reasoning: { effort: "" },
|
||||||
messages: [{ role: "user", content: "Think normally" }]
|
messages: [{ role: "user", content: "Use the thinking alias" }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = openaiToKiroRequest("kiro/gpt-5.6-terra", body, true, {});
|
const result = openaiToKiroRequest("gpt-5.6-sol-thinking", body, true, {});
|
||||||
|
|
||||||
expect(result.additionalModelRequestFields).toEqual({
|
|
||||||
reasoning: { effort: "medium" },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not forward unsupported GPT-5.6 effort values", () => {
|
|
||||||
const body = {
|
|
||||||
reasoning: { effort: "ultra" },
|
|
||||||
messages: [{ role: "user", content: "Unknown effort" }]
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = openaiToKiroRequest("gpt-5.6-luna", body, true, {});
|
|
||||||
|
|
||||||
expect(result.additionalModelRequestFields).toBeUndefined();
|
expect(result.additionalModelRequestFields).toBeUndefined();
|
||||||
|
expect(systemPromptOf(result)).toContain("<thinking_mode>enabled</thinking_mode>");
|
||||||
|
expect(systemPromptOf(result)).toContain("<max_thinking_length>");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not send additionalModelRequestFields for legacy Kiro model ids", () => {
|
it("does not send additionalModelRequestFields for legacy Kiro model ids", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user