feat(llm): add Novita provider via a Responses-API translation adapter (#55)
* feat(llm): add Novita provider via a Responses-API translation adapter Novita's LLM API is OpenAI-compatible only at the Chat Completions layer, not the Responses API cumora's agent turn/convene/triage/etc. call sites are written against — a base-URL swap alone would 404. server/src/novita.ts translates Responses-shaped requests (instructions/input/tools/streaming) into Chat Completions calls and translates the result (including streamed ChatCompletionChunks) back into the exact ResponseStreamEvent sequence turn-stream.ts already consumes, so no existing call site changes. getLlmClient() routes per-call based on a `novita/<model>` prefix on the model id (server/src/llm.ts's withNovitaRouting), so an agent opts in by setting that as its model — AgentEditor's model field hint documents the convention for Cloud agents. * fix(novita): drop undefined timeout/maxRetries keys before SDK call The OpenAI SDK's buildRequest() guards timeout validation with 'timeout' in options rather than a nullish check, so always including the key (even as undefined) threw OpenAIError: timeout must be an integer before any request was sent — surfacing upstream in turn.ts as a misleading connection/timeout failure. Only set signal/maxRetries/ timeout on the per-call options object when a real value is present. * fix(llm): don't route novita/ models to Novita when NOVITA_API_KEY is unset env.ts promised an unset key falls back to the tenant's normal client; the router actually sent the call to api.novita.ai with an empty bearer and the agent died on an unexplained 401. Make the documented fallback real, with a one-time warn so operators can see why the model isn't resolving to Novita. --------- Co-authored-by: jax-novita <jax-novita@users.noreply.github.com> Co-authored-by: yetone <yetoneful@gmail.com>
J
jax-novita committed
bd8dba8e45c91f685ea3c319aae173d44d26cbd6
Parent: 13222e3
Committed by GitHub <noreply@github.com>
on 8/22/2026, 12:01:08 PM