fix(web): key tool selection by row identity, not name
#1961 keyed the sidebar's React children by source position, but everything downstream still identified a tool by `tool.name`. With a `tools/list` that repeats a name, both copies highlighted at once, the click guard made the other copy a no-op, and `tools.find((t) => t.name === …)` always resolved to the first — so a later copy rendered but could never be opened. Thread the row key through selection instead: - `utils/toolUtils.ts` now owns `toolRowKey` (moved out of ToolControls) and adds `findToolByRowKey`, which compares computed keys rather than parsing one so the two can't drift. - `ToolControls`: `selectedName` → `selectedKey`; the highlight and the click guard compare keys, and `onSelectTool` emits the row key. - `ToolsScreen`: `ToolsUiState.selectedToolName` → `selectedToolKey`, with both lookups going through `findToolByRowKey`. Renamed through `screenUiState.ts` and `App.tsx`'s `onToolsUiChange`. `onCallTool` still sends `selectedTool.name` — the duplicated name is the genuine wire identity; only the UI identity needed to be unique. Also prefixes the excluded (SEP-2243) rows' keys: they render into the same `Stack` as the list rows but index within their own list, so an excluded tool sharing a name and index with a listed one collided in the key space. Closes #2001 Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
e9a581d912
commit
ab40fb621a
1 changed files with 210 additions and 48 deletions
|
|
@ -3160,17 +3160,17 @@ function App() {
|
|||
// drops the previous tool's result — the result panel renders `toolCallState`
|
||||
// regardless of selection, so without this a stale result would linger under
|
||||
// the newly-selected tool (which has no result of its own yet). Search and
|
||||
// form edits keep `selectedToolName` unchanged, so they leave the result be.
|
||||
// Depends on `selectedToolName` only (not the whole `toolsUi`), so a search
|
||||
// form edits keep `selectedToolKey` unchanged, so they leave the result be.
|
||||
// Depends on `selectedToolKey` only (not the whole `toolsUi`), so a search
|
||||
// keystroke doesn't churn the callback identity.
|
||||
const onToolsUiChange = useCallback(
|
||||
(next: ToolsUiState) => {
|
||||
if (next.selectedToolName !== toolsUi.selectedToolName) {
|
||||
if (next.selectedToolKey !== toolsUi.selectedToolKey) {
|
||||
setToolCallState(undefined);
|
||||
}
|
||||
setToolsUi(next);
|
||||
},
|
||||
[toolsUi.selectedToolName],
|
||||
[toolsUi.selectedToolKey],
|
||||
);
|
||||
|
||||
// --- MCP Apps handlers. Unlike onCallTool (which feeds the Tools panel),
|
||||
|
|
|
|||
Loading…
Reference in a new issue