Skip to content

fix: OpenAI-compatible provider calls wrong endpoint (/responses), breaking self-hosted chat backends - #63

Merged
kartikmanimuthu merged 2 commits into
offloadmemory:mainfrom
fabicarvano:fix/openai-compatible-responses-and-ai-exports
Oct 19, 2026
Merged

kartikmanimuthu merged 2 commits into
offloadmemory:mainfrom
fabicarvano:fix/openai-compatible-responses-and-ai-exports

Conversation

@fabicarvano

Copy link
Copy Markdown
Contributor

Issue 1 — Chat/streaming broken against any self-hosted OpenAI-compatible backend

OpenAICompatibleProvider calls 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/completions as intended. Embeddings are unaffected (already used textEmbeddingModel() correctly).

Issue 2 — Claw tools and scheduler sweep failing silently in the workers Docker image

In apps/workers/Dockerfile, the generated package.json for @chatbot/ai has no exports map, unlike @chatbot/shared and @chatbot/agent-studio in the same file. This breaks subpath imports like @chatbot/ai/tools/built-in-registry at runtime inside the container.

Observed effect: Claw's web-search, web-fetch and URL-guard tools become unavailable, and the claw-scheduler sweep fails every 30 seconds (Cannot find module '@chatbot/ai/tools/built-in-registry'), with no visible signal to the user.

Fix: add the same exports map 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.

…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.
fabicarvano added a commit to fabicarvano/agentfork that referenced this pull request Oct 17, 2026
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 kartikmanimuthu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 embeddingDimensions to 3072, which can't satisfy the vector(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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants