fix(kiro): deliver system prompt natively, add Opus 4.5/4.7/4.8, tolerate dash version ids (#2366)
- Pass system prompt via native systemInstruction field (+ <instructions> fallback) so Claude models stop treating it as info-only <system-reminder> - Add Opus 4.5/4.7/4.8 (base/thinking/agentic/thinking+agentic) to Kiro registry - normalizeModelId(): dash->dot version separator, scoped to Kiro provider only - Replace <system-reminder> with <instructions> in claude-to-openai/openai-to-kiro Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -404,7 +404,10 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
||||
|
||||
let finalContent = currentMessage?.userInputMessage?.content || "";
|
||||
|
||||
// System prompt → prepend to the user content.
|
||||
// System prompt: pass via native systemInstruction field (Kiro/Q API supports it)
|
||||
// and also prepend as <instructions> in user content as fallback for upstreams
|
||||
// that don't support the native field.
|
||||
let systemInstruction = undefined;
|
||||
if (body.system) {
|
||||
let systemText = "";
|
||||
if (typeof body.system === "string") {
|
||||
@@ -412,7 +415,10 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
||||
} else if (Array.isArray(body.system)) {
|
||||
systemText = body.system.map((s) => s.text || "").join("\n");
|
||||
}
|
||||
if (systemText) finalContent = `${systemText}\n\n${finalContent}`;
|
||||
if (systemText) {
|
||||
systemInstruction = systemText;
|
||||
finalContent = `<instructions>\n${systemText}\n</instructions>\n\n${finalContent}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix order: thinking_mode tag, timestamp marker, then agentic prompt.
|
||||
@@ -423,23 +429,29 @@ export function claudeToKiroRequest(model, body, stream, credentials) {
|
||||
if (agentic) prefixParts.push(KIRO_AGENTIC_SYSTEM_PROMPT);
|
||||
finalContent = `${prefixParts.join("\n\n")}\n\n${finalContent}`;
|
||||
|
||||
const userInputMessage = {
|
||||
content: finalContent,
|
||||
modelId: upstreamModel,
|
||||
origin: "AI_EDITOR",
|
||||
...(currentMessage?.userInputMessage?.userInputMessageContext && {
|
||||
userInputMessageContext:
|
||||
currentMessage.userInputMessage.userInputMessageContext,
|
||||
}),
|
||||
...(currentMessage?.userInputMessage?.images && {
|
||||
images: currentMessage.userInputMessage.images,
|
||||
}),
|
||||
};
|
||||
|
||||
if (systemInstruction) {
|
||||
userInputMessage.systemInstruction = systemInstruction;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
conversationState: {
|
||||
chatTriggerType: "MANUAL",
|
||||
conversationId: uuidv4(),
|
||||
currentMessage: {
|
||||
userInputMessage: {
|
||||
content: finalContent,
|
||||
modelId: upstreamModel,
|
||||
origin: "AI_EDITOR",
|
||||
...(currentMessage?.userInputMessage?.userInputMessageContext && {
|
||||
userInputMessageContext:
|
||||
currentMessage.userInputMessage.userInputMessageContext,
|
||||
}),
|
||||
...(currentMessage?.userInputMessage?.images && {
|
||||
images: currentMessage.userInputMessage.images,
|
||||
}),
|
||||
},
|
||||
userInputMessage,
|
||||
},
|
||||
history,
|
||||
},
|
||||
|
||||
@@ -129,14 +129,15 @@ function fixMissingToolResponsesOpenAI(messages) {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap mid-conversation system text so it ends as a user turn (avoids Anthropic prefill 400)
|
||||
// Wrap mid-conversation system text so it ends as a user turn (avoids Anthropic prefill 400).
|
||||
// Uses <instructions> tags that Claude models treat as authoritative directives.
|
||||
function systemReminderText(content) {
|
||||
const parts = Array.isArray(content)
|
||||
? content.filter(c => c?.type === CLAUDE_BLOCK.TEXT).map(c => c.text || "")
|
||||
: [typeof content === "string" ? content : ""];
|
||||
const text = parts.filter(Boolean).join("\n");
|
||||
if (!text.trim()) return "";
|
||||
return `<system-reminder>\n${text}\n</system-reminder>`;
|
||||
return `<instructions>\n${text}\n</instructions>`;
|
||||
}
|
||||
|
||||
// Convert single Claude message - returns single message or array of messages
|
||||
|
||||
@@ -270,6 +270,7 @@ function convertMessages(messages, tools, model) {
|
||||
let role = msg.role;
|
||||
|
||||
// Normalize: system/tool -> user
|
||||
const wasSystem = role === ROLE.SYSTEM;
|
||||
if (role === ROLE.SYSTEM || role === ROLE.TOOL) {
|
||||
role = ROLE.USER;
|
||||
}
|
||||
@@ -338,7 +339,10 @@ function convertMessages(messages, tools, model) {
|
||||
content: [{ text: toolContent }]
|
||||
});
|
||||
} else if (content) {
|
||||
pendingUserContent.push(content);
|
||||
// <instructions> tags: Claude models treat these as authoritative directives.
|
||||
pendingUserContent.push(
|
||||
wasSystem ? `<instructions>\n${content}\n</instructions>` : content
|
||||
);
|
||||
}
|
||||
} else if (role === ROLE.ASSISTANT) {
|
||||
// Extract text content and tool uses
|
||||
|
||||
Reference in New Issue
Block a user