Originally created by: yablokolabs
Problem
Some Qwen deployments behind OpenAI-compatible endpoints return tool calls as tagged text in content or reasoning_content, rather than native message.tool_calls. Atomic therefore treated valid calls as assistant prose. The model may also emit dotted names such as os.fs.read while Atomic advertises os__fs__read.
Change
- Add an explicit opt-in OpenAI-compatible Qwen adapter instead of changing every OpenAI provider globally.
- Prefer native
message.tool_calls; parse tagged calls only when native calls are absent.
- Resolve dotted and escaped names only against tools actually offered in the request.
- Coerce and validate tagged parameter values against the offered JSON schema, including nested arrays/objects, unions, enums, required fields, and additional-property rules.
- Preserve multiple-call order and distinct IDs through
completeStream(); Atomic's existing executor then assigns deterministic batch indices.
- Fail closed for malformed tags, unknown tools or parameters, duplicate or missing required parameters, prototype-named edge cases, and invalid values; ordinary prose remains prose.
Scope
The adapter is provider-specific and does not change generic OpenAI, OpenRouter, AIMLAPI, or Gemini behavior. Generic SSE reconstruction remains tracked separately by [#103].
Testing
npm run lint
- Focused adapter/provider suite: 14 passed, 0 failed
- Affected provider/config/TUI suite: 392 passed, 0 failed
npm run build
- Full suite: 3,956 passed, 6 failed, 4 skipped; all six failure names exactly match the captured upstream baseline (one upstream baseline failure — LlmHealthPoller re-probe — no longer reproduces) and no new failures were introduced
git diff --check
- Public diff credential/private-path audit
Closes [#105]
Implementation and test preparation were LLM-assisted, then independently reviewed by Yabloko Labs.