Repository navigation
fix: OpenAI-compatible provider calls wrong endpoint (/responses), breaking self-hosted chat backends - #63
Conversation
…d chat backends The OpenAICompatibleProvider called the AI SDK client as a bare function (this.client(model)), which routes to the Responses API (/v1/responses). Any self-hosted OpenAI-compatible backend that only implements /v1/chat/completions (Ollama, vLLM, LiteLLM, etc.) 404s on every chat/streaming request. The failure surfaces to end users only as a generic "An error occurred.", with the real cause (unsupported path /v1/responses) visible only in server logs. Switched to this.client.chat(model), which targets /v1/chat/completions as intended. Embeddings were unaffected (already used textEmbeddingModel() correctly). Also add an exports map to the @chatbot/ai package.json generated in apps/workers/Dockerfile, matching the pattern already used for @chatbot/shared and @chatbot/agent-studio in the same file. Without it, subpath imports such as @chatbot/ai/tools/built-in-registry fail to resolve at runtime inside the workers container. This silently broke Claw's web-search, web-fetch and URL-guard tools and caused the claw-scheduler sweep to fail every 30 seconds in any Docker-deployed workers container. Both issues were confirmed by running the full stack in Docker end-to-end (agent create/publish/inference against a real OpenAI-compatible backend), not just by code review.
streamChat now calls this.client.chat(model) instead of the bare this.client(model) call (see the previous commit on this branch), but this test's mock only exposed the provider as a bare callable, so every streamChat assertion broke with 'this.client.chat is not a function'. Add provider.chat alongside the existing bare callable and textEmbeddingModel, matching the real @ai-sdk/openai client shape. Caught by actually running bun run test for the ai project end to end, which the original fix wasn't validated against.
kartikmanimuthu
left a comment
There was a problem hiding this comment.
Thanks for this one, @fabicarvano — the diagnosis is right and it's a real bug: openai('model-id') routes to the Responses API, and openai.chat() is the documented way to target /v1/chat/completions for backends that only implement that endpoint. I confirmed streamChat was the only affected path — embed/embedBatch already used textEmbeddingModel() — and the mock update is the right way to pin the routing.
The Dockerfile exports fix is the other half of this and it genuinely matters: libs/claw-studio/src/agent/web-tools.ts and browser-session.ts import @chatbot/ai/tools/*, and claw-studio ships inside the workers image, so the missing exports map really did take those tools offline at runtime. Good catch on both, and thanks for confirming it end-to-end in Docker rather than by inspection.
Two non-blocking follow-ups I'll file separately rather than hold this up:
- The same provider defaults
embeddingDimensionsto 3072, which can't satisfy thevector(1024)columns — same class of bug as known issue #15. "./*": "./src/*.js"also resolves@chatbot/ai/src/...; harmless, but explicit subpaths (./tools/*) would keep the public surface intentional.
Approving — thanks for the careful root-cause work.
Issue 1 — Chat/streaming broken against any self-hosted OpenAI-compatible backend
OpenAICompatibleProvidercalls the AI SDK client as a bare function (this.client(model)), which the SDK routes to the Responses API (/v1/responses). Any self-hosted backend that only implements/v1/chat/completions(Ollama, vLLM, LiteLLM, etc.) 404s on every chat/streaming request.The end user only sees a generic "An error occurred." — the real cause (
unsupported path /v1/responses) only shows up in server logs.Fix: use
this.client.chat(model), which targets/v1/chat/completionsas intended. Embeddings are unaffected (already usedtextEmbeddingModel()correctly).Issue 2 — Claw tools and scheduler sweep failing silently in the workers Docker image
In
apps/workers/Dockerfile, the generatedpackage.jsonfor@chatbot/aihas noexportsmap, unlike@chatbot/sharedand@chatbot/agent-studioin the same file. This breaks subpath imports like@chatbot/ai/tools/built-in-registryat runtime inside the container.Observed effect: Claw's web-search, web-fetch and URL-guard tools become unavailable, and the
claw-schedulersweep fails every 30 seconds (Cannot find module '@chatbot/ai/tools/built-in-registry'), with no visible signal to the user.Fix: add the same
exportsmap already used for@chatbot/agent-studio.How this was found
Both issues were confirmed by running the full stack in Docker end-to-end (build, agent create/publish, real inference call against an OpenAI-compatible backend) — not just by reading the code.