Research tool row grays on the registry's own search signal (Teacher flag)
The teacher registry drops the research tool when no search engine is
live (chat-handler's searchAvailable, 2026-09-20) — the settings row
now grays on the SAME /api/search signal, so the row and the actual
registry availability can never disagree (Teacher-stream flag,
2026-09-22, routed by master).
- researchToolUnavailable (pure): research grays exactly when the live
status says unavailable; a loading/failed fetch grays nothing; the
other tools never touch the search port.
- The row: whole-row dim (graph-view graying) + disabled toggle + the
status reason as the hint — the same line the search-engine row
under it speaks from.
Two live-caught fixes while here:
- The reason line refreshed IN the pick handler raced the section PUT
(the hint could contradict the trigger it sits under — caught with a
Brave pin: trigger 'Brave', hint still 'tavily (auto)'). The refresh
now keys on the agent prop's engine pin, so it reads post-write
state.
- The engine menu options render from a map without React keys
(console warning) — keyed.
Live-verified on 3001: no engine key → research dimmed with reason,
siblings untouched; Tavily key saved + section reopened → row alive
('search engine: tavily (auto)'); Brave pinned without its key → both
rows gray with the honest missing-key reason; Automatic restored.
Gates: typecheck, lint, 803/803, build.
This commit is contained in:
@@ -8,7 +8,13 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { appearanceVars, derivedPalette, resolveAppearance } from "../components/settings/appearance.tsx";
|
||||
import { composePromptSwitch, composeSearchEngine, composeSlotModel, composeTool } from "../components/settings/agent-section.tsx";
|
||||
import {
|
||||
composePromptSwitch,
|
||||
composeSearchEngine,
|
||||
composeSlotModel,
|
||||
composeTool,
|
||||
researchToolUnavailable,
|
||||
} from "../components/settings/agent-section.tsx";
|
||||
import { nextOverrides } from "../components/settings/keyboard-section.tsx";
|
||||
import { classifyKeys, keyStatusLine, type ProviderKeyInfo } from "../components/settings/keys-section.tsx";
|
||||
import type { AgentSettings, AuthKeyStatus, ModelsSettings } from "../src/core";
|
||||
@@ -282,3 +288,18 @@ describe("first-run gate — slotsConfigured + setupStage (model-slots wave)", (
|
||||
assert.equal(setupStage([{ id: "zai", keyPresent: false }, { id: "openai", keyPresent: true }]), "pickers", "one keyed provider widens the pickers");
|
||||
});
|
||||
});
|
||||
|
||||
describe("researchToolUnavailable — the row grays on the registry's own signal", () => {
|
||||
it("research grays exactly when the live search status says unavailable", () => {
|
||||
// the SAME /api/search signal chat-handler's searchAvailable uses —
|
||||
// the row and the registry can never disagree (Teacher flag 2026-09-22)
|
||||
assert.equal(researchToolUnavailable("research", { available: false }), true);
|
||||
assert.equal(researchToolUnavailable("research", { available: true }), false);
|
||||
// loading/failed fetch grays nothing (never a false-negative row)
|
||||
assert.equal(researchToolUnavailable("research", null), false);
|
||||
// only research — the other tools never touch the search port
|
||||
for (const id of ["demo", "visual", "pdf"]) {
|
||||
assert.equal(researchToolUnavailable(id, { available: false }), false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user