mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 22:02:08 +03:00
refactor(sse): dedup fallback tool_call id helper (#4736)
Integrated into release/v3.8.36
This commit is contained in:
committed by
GitHub
parent
cc8557cedf
commit
6e28889aad
@@ -2,6 +2,12 @@
|
||||
|
||||
const ALPHANUM9 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
// Fallback streaming tool_call id when a provider response omits one (index optional).
|
||||
// `call_<ts>` when no index is given; `call_<index>_<ts>` when an index is supplied.
|
||||
export function fallbackToolCallId(index?: number): string {
|
||||
return index === undefined ? `call_${Date.now()}` : `call_${index}_${Date.now()}`;
|
||||
}
|
||||
|
||||
// Generate unique tool call ID (default long form)
|
||||
export function generateToolCallId() {
|
||||
return `call_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import { register } from "../registry.ts";
|
||||
import { FORMATS } from "../formats.ts";
|
||||
import { fallbackToolCallId } from "../helpers/toolCallHelper.ts";
|
||||
|
||||
/**
|
||||
* Parse Kiro SSE event and convert to OpenAI format
|
||||
@@ -116,7 +117,7 @@ export function convertKiroToOpenAI(chunk, state) {
|
||||
// Handle tool use events
|
||||
if (eventType === "toolUseEvent" || data.toolUseEvent) {
|
||||
const toolUse = data.toolUseEvent || data;
|
||||
const toolCallId = toolUse.toolUseId || `call_${Date.now()}`;
|
||||
const toolCallId = toolUse.toolUseId || fallbackToolCallId();
|
||||
const toolName = toolUse.name || "";
|
||||
const toolInput = toolUse.input || {};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import { register } from "../registry.ts";
|
||||
import { FORMATS } from "../formats.ts";
|
||||
import { appendToolCallArgumentDelta } from "../../utils/toolCallArguments.ts";
|
||||
import { fallbackToolCallId } from "../helpers/toolCallHelper.ts";
|
||||
|
||||
function normalizeToolName(value) {
|
||||
return typeof value === "string" ? value.trim() : "";
|
||||
@@ -615,7 +616,7 @@ function openaiResponsesToOpenAIResponseStream(chunk, state) {
|
||||
// Function call started
|
||||
if (eventType === "response.output_item.added" && data.item?.type === "function_call") {
|
||||
const item = data.item;
|
||||
state.currentToolCallId = item.call_id || `call_${Date.now()}`;
|
||||
state.currentToolCallId = item.call_id || fallbackToolCallId();
|
||||
state.currentToolCallArgsBuffer = ""; // reset per-call arg buffer
|
||||
state.currentToolCallDeferred = false;
|
||||
|
||||
@@ -694,7 +695,7 @@ function openaiResponsesToOpenAIResponseStream(chunk, state) {
|
||||
const item = data.item;
|
||||
const buffered = state.currentToolCallArgsBuffer || "";
|
||||
const currentIndex = state.toolCallIndex; // capture before increment
|
||||
const callId = item.call_id || state.currentToolCallId || `call_${Date.now()}`;
|
||||
const callId = item.call_id || state.currentToolCallId || fallbackToolCallId();
|
||||
const toolName = normalizeToolName(item.name);
|
||||
|
||||
if (state.currentToolCallDeferred) {
|
||||
|
||||
@@ -599,6 +599,26 @@ test("fixMissingToolResponses keeps OpenAI role:tool when assistant uses OpenAI
|
||||
assert.equal(fixed.messages[2].tool_call_id, "call_b");
|
||||
});
|
||||
|
||||
test("fallbackToolCallId returns the right id shape with and without an index", () => {
|
||||
const noIndex = toolCallHelper.fallbackToolCallId();
|
||||
assert.match(
|
||||
noIndex,
|
||||
/^call_\d+$/,
|
||||
"no-index form must be `call_<ts>` (matches kiro/openai-responses fallback shape)"
|
||||
);
|
||||
|
||||
const withIndex = toolCallHelper.fallbackToolCallId(2);
|
||||
assert.match(
|
||||
withIndex,
|
||||
/^call_2_\d+$/,
|
||||
"index form must be `call_<i>_<ts>` (matches indexed fallback shape)"
|
||||
);
|
||||
|
||||
// index 0 is falsy but defined — must still produce the indexed form, not the no-index form.
|
||||
const zeroIndex = toolCallHelper.fallbackToolCallId(0);
|
||||
assert.match(zeroIndex, /^call_0_\d+$/, "index 0 must use the indexed form, not the bare form");
|
||||
});
|
||||
|
||||
test("translateRequest replays cached reasoning-only messages when interleaved field is reasoning_content", () => {
|
||||
clearReasoningCacheAll();
|
||||
clearModelsDevCapabilities();
|
||||
|
||||
Reference in New Issue
Block a user