Studio: grey out RAG pill when the model can't call tools

RAG retrieval runs entirely through the local search_knowledge_base
tool. If the loaded model doesn't support tool calling (e.g. a
safetensors model whose template advertises tools in an unparsable
emission format, so supports_tools is suppressed), enabling RAG does
nothing — the model never calls the tool. The pill stayed lit and
clickable, which was misleading.

Gate the RAG pill on supportsTools (in addition to modelLoaded), the
same condition web/code use when there's no provider builtin. Applied
to both composer surfaces (shared-composer and the in-thread
RagToggle), with a 'RAG needs a model that supports tool calling'
tooltip on the disabled state.
This commit is contained in:
Roland Tannous 2026-05-28 16:02:50 +04:00
commit cf7dec1f13
2 changed files with 21 additions and 9 deletions

View file

@ -1149,7 +1149,10 @@ const RagToggle: FC = () => {
const setRagToolEnabled = useChatRuntimeStore((s) => s.setRagToolEnabled);
const ragSource = useChatRuntimeStore((s) => s.ragSource);
const setRagSource = useChatRuntimeStore((s) => s.setRagSource);
const disabled = !modelLoaded;
const supportsTools = useChatRuntimeStore((s) => s.supportsTools);
// RAG runs through the local search_knowledge_base tool, so it needs
// tool-calling support (mirrors shared-composer's ragDisabled).
const disabled = !modelLoaded || !supportsTools;
return (
<button
type="button"
@ -1165,9 +1168,11 @@ const RagToggle: FC = () => {
data-active={ragToolEnabled && !disabled ? "true" : "false"}
aria-label={ragToolEnabled ? "Disable RAG" : "Enable RAG"}
title={
ragToolEnabled
? "RAG on — the model can search your attached documents"
: "Enable RAG — let the model search your documents"
disabled
? "RAG needs a model that supports tool calling"
: ragToolEnabled
? "RAG on — the model can search your attached documents"
: "Enable RAG — let the model search your documents"
}
>
<BookOpenIcon className="size-3.5" />

View file

@ -518,6 +518,11 @@ export function SharedComposer({
// Images pill is only ever lit on OpenAI cloud's Responses-API models
// and Gemini Nano Banana family. No local tool runtime fallback.
const showImagePill = supportsBuiltinImageGeneration;
// RAG retrieval runs entirely through the local search_knowledge_base
// tool, so it needs the tool-calling loop. No external-builtin RAG
// equivalent — gate purely on supportsTools (mirrors web/code when not
// backed by a provider builtin).
const ragDisabled = !modelLoaded || !supportsTools;
// Fetch pill: Anthropic-only (web_fetch_20250910 / web_fetch_20260209).
const webFetchDisabled = !modelLoaded || !supportsBuiltinWebFetch;
const showWebFetchPill = supportsBuiltinWebFetch;
@ -1405,7 +1410,7 @@ export function SharedComposer({
{/* Master RAG toggle; sidebar Retrieval section configures the rest. */}
<button
type="button"
disabled={!modelLoaded}
disabled={ragDisabled}
onClick={() => {
const next = !ragToolEnabled;
setRagToolEnabled(next);
@ -1414,12 +1419,14 @@ export function SharedComposer({
}
}}
className="composer-pill-btn"
data-active={ragToolEnabled && modelLoaded ? "true" : "false"}
data-active={ragToolEnabled && !ragDisabled ? "true" : "false"}
aria-label={ragToolEnabled ? "Disable RAG" : "Enable RAG"}
title={
ragToolEnabled
? "RAG on — the model can search your attached documents"
: "Enable RAG — let the model search your documents"
ragDisabled
? "RAG needs a model that supports tool calling"
: ragToolEnabled
? "RAG on — the model can search your attached documents"
: "Enable RAG — let the model search your documents"
}
>
<BookOpenIcon className="size-3.5" />