mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
* fix(responses): escape literal control chars in tool call JSON; emit status=failed on upstream error #6785 Two bugfixes in the Responses API translator: 1. escapeJsonStringValues() sanitizes tool call arguments containing literal 0x0A/0x0D/0x09 bytes (emitted by Gemma4 models) into valid JSON \n/\r/\t escapes, preventing SSE framing corruption. Only escapes inside JSON string contexts — already-escaped sequences and structural JSON pass through unchanged. 2. sendCompleted() checks state.upstreamError and emits status="failed" with error.code + error.message instead of silently hardcoding status="completed" + error=null, so mid-stream errors (e.g. Gemini 503 after partial content) are properly surfaced to the client. 3. stream.ts: calls translateResponse(null,...) before controller.error() so the translator can emit close events (reasoning item done, response.completed) before the stream is terminated. * test(boundary): fix ESLint no-explicit-any warnings and quality gates Green the PR against release/v3.8.47 quality gates without weakening tests: - Replace @typescript-eslint/no-explicit-any in the new boundary/gemma4 tests with proper interfaces (ResponseBody, ToolDef, ToolArgs, SseEvent item accessors) — fixes the "No new ESLint warnings" gate. - Split tests/unit/translator-resp-openai-responses.test.ts (1079 LOC) by extracting the round-trip suite into a sibling file so both stay under the 800-line test cap — fixes check:file-size. - Rename the 5 live boundary tests to *.live.test.ts, gate them behind RUN_BOUNDARY_LIVE=1, add a test:boundary:live npm script and register the glob in check-test-discovery COLLECTORS — fixes check:test-discovery (they hit a live remote and must never run unopted in CI). Co-authored-by: Markus Hartung <mail@hartmark.se> --------- Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
294 lines
6.3 KiB
HTTP
294 lines
6.3 KiB
HTTP
###
|
|
# @name OpenAI Response - Test streaming response
|
|
POST {{omniroute-address}}/v1/responses
|
|
Authorization: Bearer {{OMNIROUTE_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemini/gemma-4-31b-it",
|
|
"stream": true,
|
|
"input": [
|
|
{
|
|
"type": "message",
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "input_text",
|
|
"text": "Ansver 1+1 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Gemini Response - Test streaming response
|
|
POST https://generativelanguage.googleapis.com/v1beta/models/gemma-4-31b-it:streamGenerateContent?alt=sse
|
|
x-goog-api-key: {{GEMINI_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemma-4-31b-it",
|
|
"contents": [
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "Ansver 1+1 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Gemini Response - Test streaming response - 26B
|
|
POST https://generativelanguage.googleapis.com/v1beta/models/gemma-4-26b-a4b-it:streamGenerateContent?alt=sse
|
|
x-goog-api-key: {{GEMINI_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemma-4-26b-a4b-it",
|
|
"contents": [
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "Ansver 1+1 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name OpenAI Response - Test non-streaming response
|
|
POST {{omniroute-address}}/v1/responses
|
|
Authorization: Bearer {{OMNIROUTE_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemini/gemma-4-31b-it",
|
|
"stream": false,
|
|
"input": [
|
|
{
|
|
"type": "message",
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "input_text",
|
|
"text": "Ansver 11+212 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Gemini Response - Test non-streaming response
|
|
POST https://generativelanguage.googleapis.com/v1beta/models/gemma-4-31b-it:generateContent
|
|
x-goog-api-key: {{GEMINI_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemma-4-31b-it",
|
|
"contents": [
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "Ansver 1+1 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Gemini Response - Test non-streaming response - 26B
|
|
POST https://generativelanguage.googleapis.com/v1beta/models/gemma-4-26b-a4b-it:generateContent
|
|
x-goog-api-key: {{GEMINI_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemma-4-26b-a4b-it",
|
|
"contents": [
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "Ansver 1+1 only."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Tool history via OmniRoute — native functionCall/functionResponse round-trip
|
|
# Tool calls in conversation history are mapped to native Gemini functionCall parts
|
|
# (no text serialization). The model should respond with either natural language or
|
|
# proper functionCall — never with text labels like [tool_history_call:.
|
|
POST {{omniroute-address}}/v1/chat/completions
|
|
Authorization: Bearer {{OMNIROUTE_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemini/gemma-4-31b-it",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": "What is the weather in Stockholm?"
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": null,
|
|
"tool_calls": [
|
|
{
|
|
"id": "call_abc123",
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"arguments": "{\"location\": \"Stockholm, Sweden\"}"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "tool",
|
|
"tool_call_id": "call_abc123",
|
|
"content": "{\"temperature\": 22, \"conditions\": \"Sunny\", \"humidity\": 45}"
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Stockholm has sunny weather at 22°C."
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": "Summarize the weather briefly."
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Simple Q&A — no tool calls in history
|
|
POST {{omniroute-address}}/v1/chat/completions
|
|
Authorization: Bearer {{OMNIROUTE_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemini/gemma-4-31b-it",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": "What is 1+1? Only respond with the number."
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Direct Gemini: native functionCall/functionResponse format
|
|
# Baseline — native Gemini contents with functionCall/functionResponse parts.
|
|
# No text labels should appear in the response.
|
|
POST https://generativelanguage.googleapis.com/v1beta/models/gemma-4-31b-it:generateContent
|
|
x-goog-api-key: {{GEMINI_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemma-4-31b-it",
|
|
"contents": [
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "What is the weather in Stockholm?"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "model",
|
|
"parts": [
|
|
{
|
|
"functionCall": {
|
|
"id": "call_abc123",
|
|
"name": "get_weather",
|
|
"args": {
|
|
"location": "Stockholm, Sweden"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"functionResponse": {
|
|
"id": "call_abc123",
|
|
"name": "get_weather",
|
|
"response": {
|
|
"result": {
|
|
"temperature": 22,
|
|
"conditions": "Sunny",
|
|
"humidity": 45
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "user",
|
|
"parts": [
|
|
{
|
|
"text": "Summarize the weather briefly."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
###
|
|
# @name Tool history via OmniRoute — thinking model
|
|
# Same as native test above but with a thinking model (gemini-2.5-flash)
|
|
# that cryptographically validates thoughtSignature on functionCall parts.
|
|
POST {{omniroute-address}}/v1/chat/completions
|
|
Authorization: Bearer {{OMNIROUTE_API_KEY}}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"model": "gemini/gemini-2.5-flash",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": "What is the weather in Stockholm?"
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": null,
|
|
"tool_calls": [
|
|
{
|
|
"id": "call_abc123",
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"arguments": "{\"location\": \"Stockholm, Sweden\"}"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "tool",
|
|
"tool_call_id": "call_abc123",
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Stockholm has sunny weather at 22°C."
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": "Summarize the weather briefly."
|
|
}
|
|
]
|
|
}
|