mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
* fix(translator): synthesize tool call chunks from response.completed output[]
When an upstream provider sends a batched response.completed event carrying
function_call items in its data.response.output[] array — without having
sent the individual response.output_item.added / .delta / .done events —
the state variables toolCallIndex and currentToolCallId were never set,
causing computeFinishReason to return 'stop' instead of 'tool_calls'.
This broke the agent loop for downstream Chat Completions clients
(OpenCode, Hermes, etc.) when routing through providers that batch their
output into the completed event.
Fix: parse data.response.output[] for function_call items in the
response.completed handler, synthesize the tool call header + arguments
delta chunks, advance state, and emit finish_reason: 'tool_calls'.
Also updates withAssistantRoleOnFirstDelta to handle array results.
Fixes #180, #3980
Refs: https://github.com/diegosouzapw/OmniRoute/issues/180
Refs: https://github.com/diegosouzapw/OmniRoute/issues/3980
* fix(translator): guard against double-emission for incrementally-streamed tool calls
Add a guard that skips response.completed synthesis for call_ids already
tracked via incremental output_item.added/.done events. Without this,
providers that stream incrementally AND echo function_call items in the
response.completed output[] snapshot get duplicate tool call chunks.
Also adds a regression test combining both incremental events and a
response.completed snapshot in the same turn.
Refs: diegosouzapw/OmniRoute#7613
* chore: add docker-compose.yml.bak to gitignore
* refactor(translator): extract response.completed synthesis, fix ratchets
Fixes the file-size and complexity/cognitive-complexity ratchet
regressions the dedup-guard commit (6bbff5ea) introduced, so the PR's
own validation block (typecheck, eslint, file-size, complexity,
cognitive-complexity, changelog-integrity, test-discovery) is fully
green, not just its own tests:
- Extract the response.completed batched-tool-call synthesis body into
a new leaf module
open-sse/translator/response/openai-responses/synthesizeCompletedToolCalls.ts,
mirroring this file's own established eventEmitter.ts/toolSchemas.ts/
pureHelpers.ts extraction pattern, further split internally
(buildToolCallChunks/buildFinalChunk/resolveArgsStr/baseChunk) to
keep synthesizeCompletedToolCalls() itself under the complexity/
cognitive-complexity/max-lines-per-function thresholds.
- computeFinishReason moves alongside it (not into the sibling
pureHelpers.ts) because it takes stream `state` — pureHelpers.ts is
guarded by tests/unit/response-openai-responses-purehelpers-split.test.ts
to have NO state coupling at all.
- DRY the withAssistantRoleOnFirstDelta array/single-result branches
into a shared setAssistantRoleIfEligible(state, delta) helper — the
array branch alone pushed this function's cyclomatic complexity to
16 (over the 15 threshold).
- Split the 5 new response.completed tests out of
tests/unit/translator-resp-openai-responses.test.ts (which would
have exceeded the 800-line test-file-size cap) into a new sibling
tests/unit/translator-resp-openai-responses-completed-synthesis.test.ts.
- Bump the frozen open-sse/translator/response/openai-responses.ts
file-size baseline for the small irreducible remainder (dedup-guard
state tracking + call-site wiring) with a justification entry in
config/quality/file-size-baseline.json.
Independently re-verified red-first (temporarily reintroducing the
pre-guard filter reproduces exactly one failure — the dedup test — no
collateral damage) and confirmed check:complexity-ratchets is back to
exactly baseline (2058/890) and check:file-size is fully green.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* refactor(translator): move completed-tool-call glue into module (file-size cap)
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: Erick Kinnee <erick@ekinnee.dev>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
5.6 KiB
5.6 KiB