Files
sim/apps
Waleed 844733a5ea feat(providers): add Sakana AI provider with Fugu models (#5169)
* feat(providers): add Sakana AI provider with Fugu models

OpenAI-compatible provider at https://api.sakana.ai/v1 (bearer auth).
Registers fugu (fast default) and fugu-ultra (reasoning flagship), both
1M context. BYOK-only, never hosted/auto-billed. Streaming, tool loop,
and response_format supported; attachments mirror deepseek (unsupported
in the current adapter).

* fix(providers): defer Sakana structured output until after tool loop

OpenAI-compatible backends reject a request carrying both response_format
and active tools/tool_choice. Mirror the LiteLLM pattern: withhold the
JSON schema while tools are active and apply it on a final tool-free call
(tool_choice: none) for both streaming and non-streaming paths.

* fix(providers): harden Sakana tool-loop error + final-stream tool_choice

- Rethrow tool-loop failures instead of swallowing them, so a failed run
  surfaces as a ProviderError rather than a partial success (matches LiteLLM).
- Force tool_choice: 'none' on the post-tool streaming pass so the model
  cannot emit fresh tool calls that the text-only stream adapter would drop.

* fix(providers): Sakana streaming usage + filtered-tools stream guard

- Pass stream_options: { include_usage: true } on both streaming calls so
  token/cost data is captured (the shared OpenAI-compatible stream helper
  only fills usage from chunk usage, which the API omits without the flag).
- Include !hasActiveTools in the early-stream guard so requests whose tools
  are all filtered out (e.g. usageControl 'none') still take the fast
  streaming path instead of the tool-loop path. Mirrors LiteLLM.

* fix(providers): answer every Sakana tool_call to keep message history valid

An assistant message lists all tool_calls, so a call for an unconfigured
tool must still get a matching `tool` response or the next request violates
the OpenAI message contract. Emit an error tool-result for unknown tools
instead of dropping them.

* test(session): de-flake SessionProvider normal-load test

flush() only drained microtasks, so the query->render update occasionally
lost the race and ctx.data was still null after the flush budget. Yield one
macrotask tick per flush so React Query's notifyManager and deferred renders
settle deterministically. Verified across repeated local runs.
2026-06-22 13:35:11 -07:00
..