mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 14:52:09 +03:00
fix(kiro): stabilize conversationId across prompt compression (#2630)
Integrated into release/v3.8.3
This commit is contained in:
@@ -2106,6 +2106,7 @@ export async function handleChatCore({
|
||||
const allMessages = compressionBody?.messages || body?.contents || body?.request?.contents || [];
|
||||
let cavemanOutputModeApplied = false;
|
||||
let cavemanOutputModeIntensity: string | null = null;
|
||||
let preCompressionBody: typeof body | null = null;
|
||||
if (body && Array.isArray(allMessages) && allMessages.length > 0) {
|
||||
let estimatedTokens = estimateTokens(JSON.stringify(allMessages));
|
||||
let promptCompressionEnabled = false;
|
||||
@@ -2557,6 +2558,10 @@ export async function handleChatCore({
|
||||
`Checking compression: ${estimatedTokens} tokens vs ${threshold} threshold (${contextLimit} limit, ${reservedTokens} reserved)`
|
||||
);
|
||||
|
||||
// Capture pre-compression body so translators can access original message
|
||||
// content even after compression alters it (e.g. stable Kiro conversationId).
|
||||
preCompressionBody = body;
|
||||
|
||||
if (promptCompressionEnabled && estimatedTokens > threshold) {
|
||||
log?.info?.(
|
||||
"CONTEXT",
|
||||
@@ -2933,6 +2938,7 @@ export async function handleChatCore({
|
||||
preserveDeveloperRole,
|
||||
preserveCacheControl,
|
||||
signatureNamespace: connectionId,
|
||||
...(preCompressionBody ? { preCompressionBody } : {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ export function translateRequest(
|
||||
preserveDeveloperRole?: boolean;
|
||||
preserveCacheControl?: boolean;
|
||||
signatureNamespace?: string | null;
|
||||
preCompressionBody?: Record<string, unknown> | null;
|
||||
}
|
||||
) {
|
||||
let result = body;
|
||||
@@ -185,12 +186,16 @@ export function translateRequest(
|
||||
if (targetFormat !== FORMATS.OPENAI) {
|
||||
const fromOpenAI = getRequestTranslator(FORMATS.OPENAI, targetFormat);
|
||||
if (fromOpenAI) {
|
||||
const translationCredentials = options?.signatureNamespace
|
||||
? {
|
||||
...(credentials && typeof credentials === "object" ? credentials : {}),
|
||||
_signatureNamespace: options.signatureNamespace,
|
||||
}
|
||||
: credentials;
|
||||
const hasNs = options?.signatureNamespace != null;
|
||||
const hasPreCompression = options?.preCompressionBody != null;
|
||||
const translationCredentials =
|
||||
hasNs || hasPreCompression
|
||||
? {
|
||||
...(credentials && typeof credentials === "object" ? credentials : {}),
|
||||
...(hasNs ? { _signatureNamespace: options.signatureNamespace } : {}),
|
||||
...(hasPreCompression ? { _preCompressionBody: options.preCompressionBody } : {}),
|
||||
}
|
||||
: credentials;
|
||||
result = fromOpenAI(model, result, stream, translationCredentials);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,8 +746,33 @@ export function buildKiroPayload(model, body, stream, credentials) {
|
||||
// upstream Kiro/AWS conversation context, leaking prior state across
|
||||
// sessions. See conversionMessages() above for the `__synthetic` marker.
|
||||
const NAMESPACE_KIRO = "34f7193f-561d-4050-bc84-9547d953d6bf";
|
||||
|
||||
// Priority 1: Extract first user message from pre-compression body (passed by chatCore before
|
||||
// compressContext runs). This keeps conversationId stable even when compression alters content.
|
||||
// Priority 2: Deterministic hash from first user message in translated history (fallback).
|
||||
const preCompressionBody = credentials?._preCompressionBody as
|
||||
| Record<string, unknown>
|
||||
| null
|
||||
| undefined;
|
||||
const preCompressionMessages = Array.isArray(preCompressionBody?.messages)
|
||||
? preCompressionBody.messages
|
||||
: null;
|
||||
const preCompressionFirstUser = preCompressionMessages?.find(
|
||||
(m: Record<string, unknown>) => m.role === "user"
|
||||
);
|
||||
const seedFromPreCompression = preCompressionFirstUser
|
||||
? typeof preCompressionFirstUser.content === "string"
|
||||
? preCompressionFirstUser.content
|
||||
: Array.isArray(preCompressionFirstUser.content)
|
||||
? (preCompressionFirstUser.content as Array<{ type: string; text?: string }>)
|
||||
.filter((b) => b.type === "text")
|
||||
.map((b) => b.text || "")
|
||||
.join(" ")
|
||||
: ""
|
||||
: "";
|
||||
const firstRealUserTurn = history.find((h) => h?.userInputMessage?.content && !h.__synthetic);
|
||||
const firstContent = firstRealUserTurn?.userInputMessage?.content || finalContent;
|
||||
const firstContent =
|
||||
seedFromPreCompression || firstRealUserTurn?.userInputMessage?.content || finalContent;
|
||||
|
||||
// Use uuidv5 with the hash of the system prompt / first message to maintain AWS Builder ID context cache
|
||||
payload.conversationState.conversationId = uuidv5(
|
||||
|
||||
Reference in New Issue
Block a user