From 361854189a7530b673bfb174f81be79a09c0a899 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Jun 2026 13:54:09 +0000 Subject: [PATCH 1/2] DiffusionGemma: disable tools, enable artifacts canvas by default DiffusionGemma serves via the visual runner, which streams per-step canvas frames so the answer resolves live in the bubble. The agentic tool loop (generate_chat_completion_with_tools) does not forward those frames, so whenever a tool pill (Search/Code) was on the live canvas silently vanished while text still streamed. DiffusionGemma is not a tool-calling target anyway, so report supports_tools=False for it: the chat always takes the frame-forwarding path, and the Search/Code pills disable themselves (a local model has no builtin web search either). Also turn the artifacts canvas on by default for DiffusionGemma so a full-HTML answer (e.g. a playable game) renders as an interactive sandboxed card without the user flipping the global artifacts toggle. --- studio/backend/core/inference/llama_cpp.py | 4 ++++ .../src/components/assistant-ui/markdown-text.tsx | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py index b5d5328fb0..f30a8acf89 100644 --- a/studio/backend/core/inference/llama_cpp.py +++ b/studio/backend/core/inference/llama_cpp.py @@ -1042,6 +1042,10 @@ class LlamaCppBackend: @property def supports_tools(self) -> bool: + # DiffusionGemma serves via the visual runner, whose live per-step canvas + # frames are dropped by the agentic tool loop; never route it through tools. + if self._is_diffusion: + return False return self._supports_tools @property diff --git a/studio/frontend/src/components/assistant-ui/markdown-text.tsx b/studio/frontend/src/components/assistant-ui/markdown-text.tsx index 45a0082a57..61b97e619f 100644 --- a/studio/frontend/src/components/assistant-ui/markdown-text.tsx +++ b/studio/frontend/src/components/assistant-ui/markdown-text.tsx @@ -285,11 +285,14 @@ function CodeBlockActions({ } // DiffusionGemma renders its denoising live in the bubble (see DiffusionCanvas in -// thread.tsx), so it no longer forces HTML into an iframe artifact; it follows the -// same artifact rules as every other model. +// thread.tsx) and has the artifacts canvas on by default, so a full-HTML answer +// (e.g. a playable game) renders as an interactive card without the global toggle. function StreamdownBlock(props: BlockProps) { const shouldCollapseHtmlArtifacts = useChatRuntimeStore( - (state) => state.artifactsEnabled || state.collapseHtmlArtifacts, + (state) => + state.artifactsEnabled || + state.collapseHtmlArtifacts || + state.loadedIsDiffusion, ); const messageHasRenderableRenderHtmlTool = useAuiState(({ message }) => message.parts.some(isRenderableRenderHtmlToolPart), From 1c58c00b54bdafbd98d2899bca86f03304a0a9ed Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 12 Jun 2026 14:17:42 +0000 Subject: [PATCH 2/2] DiffusionGemma: set UNSLOTH_IS_PRESENT for the shim subprocess A clean install could not run DiffusionGemma: the runner spawns python -m unsloth_zoo.diffusion_studio.shim, and unsloth_zoo refuses to import unless UNSLOTH_IS_PRESENT is set (normally by import unsloth). The shim never imports unsloth, so the subprocess died with 'Please install Unsloth via pip install unsloth!' and the model load failed with a 500. Set the flag in the runner child env, as unsloth does on import. --- studio/backend/core/inference/llama_cpp.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py index f30a8acf89..a25ed0889a 100644 --- a/studio/backend/core/inference/llama_cpp.py +++ b/studio/backend/core/inference/llama_cpp.py @@ -2527,6 +2527,10 @@ class LlamaCppBackend: ] env = child_env_without_native_path_secret() + # `python -m unsloth_zoo.diffusion_studio.shim` imports unsloth_zoo, which + # refuses to load unless UNSLOTH_IS_PRESENT is set (normally by `import + # unsloth`). The shim never imports unsloth, so set it here as unsloth does. + env["UNSLOTH_IS_PRESENT"] = "1" env["DG_VISUAL_BIN"] = visual_bin env["DG_GPU"] = gpu # The file-override shim imports its sibling visual_engine; put its dir on PYTHONPATH.