fix(extensions): dedupe MCP detail API key lookups
This commit is contained in:
parent
0d6276ea0b
commit
3f03bc720a
2 changed files with 38 additions and 32 deletions
|
|
@ -128,38 +128,6 @@ export const McpServerDetailDialog = ({
|
||||||
);
|
);
|
||||||
}, [server?.id, open]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [server?.id, open]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
// Auto-fill env vars from saved API keys
|
|
||||||
useEffect(() => {
|
|
||||||
if (!server || server.envVars.length === 0 || !api.apiKeys) return;
|
|
||||||
|
|
||||||
const envVarNames = server.envVars.map((env) => env.name);
|
|
||||||
void api.apiKeys.lookup(envVarNames).then(
|
|
||||||
(results) => {
|
|
||||||
if (results.length === 0) return;
|
|
||||||
const filled = new Set<string>();
|
|
||||||
const updates: Record<string, string> = {};
|
|
||||||
for (const r of results) {
|
|
||||||
updates[r.envVarName] = r.value;
|
|
||||||
filled.add(r.envVarName);
|
|
||||||
}
|
|
||||||
setEnvValues((prev) => {
|
|
||||||
const next = { ...prev };
|
|
||||||
for (const [k, v] of Object.entries(updates)) {
|
|
||||||
// Only auto-fill if the field is empty
|
|
||||||
if (!next[k]) {
|
|
||||||
next[k] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
setAutoFilledFields(filled);
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
// Silently ignore lookup failures
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}, [server?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
||||||
|
|
||||||
if (!server) return <></>;
|
if (!server) return <></>;
|
||||||
|
|
||||||
const canAutoInstall = !!server.installSpec;
|
const canAutoInstall = !!server.installSpec;
|
||||||
|
|
|
||||||
|
|
@ -219,4 +219,42 @@ describe('McpServerDetailDialog installed entry handling', () => {
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('looks up saved API keys only once per dialog open', async () => {
|
||||||
|
const host = document.createElement('div');
|
||||||
|
document.body.appendChild(host);
|
||||||
|
const root = createRoot(host);
|
||||||
|
const server = makeServer();
|
||||||
|
server.envVars = [{ name: 'CONTEXT7_API_KEY', isSecret: true }];
|
||||||
|
lookupMock.mockResolvedValue([
|
||||||
|
{
|
||||||
|
envVarName: 'CONTEXT7_API_KEY',
|
||||||
|
value: 'secret',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
root.render(
|
||||||
|
React.createElement(McpServerDetailDialog, {
|
||||||
|
server,
|
||||||
|
isInstalled: false,
|
||||||
|
installedEntry: null,
|
||||||
|
diagnostic: null,
|
||||||
|
diagnosticsLoading: false,
|
||||||
|
open: true,
|
||||||
|
onClose: vi.fn(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
await Promise.resolve();
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(lookupMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(lookupMock).toHaveBeenCalledWith(['CONTEXT7_API_KEY']);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
root.unmount();
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue