UNPKG

@notebook-intelligence/notebook-intelligence

Version:
522 lines (521 loc) 36.7 kB
// Copyright (c) Mehmet Bektas <mbektasgh@outlook.com> import React, { useEffect, useRef, useState } from 'react'; import { ReactWidget } from '@jupyterlab/apputils'; import { VscWarning } from 'react-icons/vsc'; import * as path from 'path'; import copySvgstr from '../../style/icons/copy.svg'; import claudeSvgStr from '../../style/icons/claude.svg'; import { ClaudeModelType, ClaudeToolType, NBIAPI } from '../api'; import { CheckBoxItem } from './checkbox'; import { PillItem } from './pill'; import { mcpServerSettingsToEnabledState } from './mcp-util'; const OPENAI_COMPATIBLE_CHAT_MODEL_ID = 'openai-compatible-chat-model'; const LITELLM_COMPATIBLE_CHAT_MODEL_ID = 'litellm-compatible-chat-model'; const OPENAI_COMPATIBLE_INLINE_COMPLETION_MODEL_ID = 'openai-compatible-inline-completion-model'; const LITELLM_COMPATIBLE_INLINE_COMPLETION_MODEL_ID = 'litellm-compatible-inline-completion-model'; export class SettingsPanel extends ReactWidget { constructor(options) { super(); this._onSave = options.onSave; this._onEditMCPConfigClicked = options.onEditMCPConfigClicked; } render() { return (React.createElement(SettingsPanelComponent, { onSave: this._onSave, onEditMCPConfigClicked: this._onEditMCPConfigClicked })); } } function SettingsPanelComponent(props) { const [activeTab, setActiveTab] = useState('general'); const onTabSelected = (tab) => { setActiveTab(tab); }; return (React.createElement("div", { className: "nbi-settings-panel" }, React.createElement("div", { className: "nbi-settings-panel-tabs" }, React.createElement(SettingsPanelTabsComponent, { onTabSelected: onTabSelected, activeTab: activeTab })), React.createElement("div", { className: "nbi-settings-panel-tab-content" }, activeTab === 'general' && (React.createElement(SettingsPanelComponentGeneral, { onSave: props.onSave, onEditMCPConfigClicked: props.onEditMCPConfigClicked })), activeTab === 'mcp-servers' && (React.createElement(SettingsPanelComponentMCPServers, { onEditMCPConfigClicked: props.onEditMCPConfigClicked })), activeTab === 'claude' && (React.createElement(SettingsPanelComponentClaude, { onEditMCPConfigClicked: props.onEditMCPConfigClicked }))))); } function SettingsPanelTabsComponent(props) { const [activeTab, setActiveTab] = useState(props.activeTab); return (React.createElement("div", null, React.createElement("div", { className: `nbi-settings-panel-tab ${activeTab === 'general' ? 'active' : ''}`, onClick: () => { setActiveTab('general'); props.onTabSelected('general'); } }, "General"), React.createElement("div", { className: `nbi-settings-panel-tab ${activeTab === 'claude' ? 'active' : ''}`, onClick: () => { setActiveTab('claude'); props.onTabSelected('claude'); } }, React.createElement("span", { className: "claude-icon", dangerouslySetInnerHTML: { __html: claudeSvgStr } }), "Claude"), React.createElement("div", { className: `nbi-settings-panel-tab ${activeTab === 'mcp-servers' ? 'active' : ''}`, onClick: () => { setActiveTab('mcp-servers'); props.onTabSelected('mcp-servers'); } }, "MCP Servers"))); } function SettingsPanelComponentGeneral(props) { const nbiConfig = NBIAPI.config; const llmProviders = nbiConfig.llmProviders; const [chatModels, setChatModels] = useState([]); const [inlineCompletionModels, setInlineCompletionModels] = useState([]); const handleSaveSettings = async () => { const config = { default_chat_mode: defaultChatMode, chat_model: { provider: chatModelProvider, model: chatModel, properties: chatModelProperties }, inline_completion_model: { provider: inlineCompletionModelProvider, model: inlineCompletionModel, properties: inlineCompletionModelProperties } }; if (chatModelProvider === 'github-copilot' || inlineCompletionModelProvider === 'github-copilot') { config.store_github_access_token = storeGitHubAccessToken; } await NBIAPI.setConfig(config); props.onSave(); }; const handleRefreshOllamaModelListClick = async () => { await NBIAPI.updateOllamaModelList(); updateModelOptionsForProvider(chatModelProvider, 'chat'); }; const [chatModelProvider, setChatModelProvider] = useState(nbiConfig.chatModel.provider || 'none'); const [inlineCompletionModelProvider, setInlineCompletionModelProvider] = useState(nbiConfig.inlineCompletionModel.provider || 'none'); const [defaultChatMode, setDefaultChatMode] = useState(nbiConfig.defaultChatMode); const [chatModel, setChatModel] = useState(nbiConfig.chatModel.model); const [chatModelProperties, setChatModelProperties] = useState([]); const [inlineCompletionModelProperties, setInlineCompletionModelProperties] = useState([]); const [inlineCompletionModel, setInlineCompletionModel] = useState(nbiConfig.inlineCompletionModel.model); const [storeGitHubAccessToken, setStoreGitHubAccessToken] = useState(nbiConfig.storeGitHubAccessToken); const updateModelOptionsForProvider = (providerId, modelType) => { if (modelType === 'chat') { setChatModelProvider(providerId); } else { setInlineCompletionModelProvider(providerId); } const models = modelType === 'chat' ? nbiConfig.chatModels : nbiConfig.inlineCompletionModels; const selectedModelId = modelType === 'chat' ? nbiConfig.chatModel.model : nbiConfig.inlineCompletionModel.model; const providerModels = models.filter((model) => model.provider === providerId); if (modelType === 'chat') { setChatModels(providerModels); } else { setInlineCompletionModels(providerModels); } let selectedModel = providerModels.find((model) => model.id === selectedModelId); if (!selectedModel) { selectedModel = providerModels === null || providerModels === void 0 ? void 0 : providerModels[0]; } if (selectedModel) { if (modelType === 'chat') { setChatModel(selectedModel.id); setChatModelProperties(selectedModel.properties); } else { setInlineCompletionModel(selectedModel.id); setInlineCompletionModelProperties(selectedModel.properties); } } else { if (modelType === 'chat') { setChatModelProperties([]); } else { setInlineCompletionModelProperties([]); } } }; const onModelPropertyChange = (modelType, propertyId, value) => { const modelProperties = modelType === 'chat' ? chatModelProperties : inlineCompletionModelProperties; const updatedProperties = modelProperties.map((property) => { if (property.id === propertyId) { return { ...property, value }; } return property; }); if (modelType === 'chat') { setChatModelProperties(updatedProperties); } else { setInlineCompletionModelProperties(updatedProperties); } }; useEffect(() => { updateModelOptionsForProvider(chatModelProvider, 'chat'); updateModelOptionsForProvider(inlineCompletionModelProvider, 'inline-completion'); }, []); useEffect(() => { handleSaveSettings(); }, [ defaultChatMode, chatModelProvider, chatModel, chatModelProperties, inlineCompletionModelProvider, inlineCompletionModel, inlineCompletionModelProperties, storeGitHubAccessToken ]); return (React.createElement("div", { className: "config-dialog" }, React.createElement("div", { className: "config-dialog-body" }, React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Default chat mode"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", value: defaultChatMode, onChange: event => setDefaultChatMode(event.target.value) }, React.createElement("option", { value: "ask" }, "Ask"), React.createElement("option", { value: "agent" }, "Agent")))), React.createElement("div", { className: "model-config-section-column" }, " ")))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Chat model"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Provider"), React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => updateModelOptionsForProvider(event.target.value, 'chat') }, llmProviders.map((provider, index) => (React.createElement("option", { key: index, value: provider.id, selected: provider.id === chatModelProvider }, provider.name))), React.createElement("option", { key: -1, value: "none", selected: chatModelProvider === 'none' || !llmProviders.find(provider => provider.id === chatModelProvider) }, "None")))), !['openai-compatible', 'litellm-compatible', 'none'].includes(chatModelProvider) && chatModels.length > 0 && (React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Model"), ![ OPENAI_COMPATIBLE_CHAT_MODEL_ID, LITELLM_COMPATIBLE_CHAT_MODEL_ID ].includes(chatModel) && chatModels.length > 0 && (React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => setChatModel(event.target.value) }, chatModels.map((model, index) => (React.createElement("option", { key: index, value: model.id, selected: model.id === chatModel }, model.name))))))))), React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, chatModelProvider === 'ollama' && chatModels.length === 0 && (React.createElement("div", { className: "ollama-warning-message" }, "No Ollama models found! Make sure", ' ', React.createElement("a", { href: "https://ollama.com/", target: "_blank" }, "Ollama"), ' ', "is running and models are downloaded to your computer.", ' ', React.createElement("a", { href: "javascript:void(0)", onClick: handleRefreshOllamaModelListClick }, "Try again"), ' ', "once ready.")))), React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, chatModelProperties.map((property, index) => (React.createElement("div", { className: "form-field-row", key: index }, React.createElement("div", { className: "form-field-description" }, property.name, " ", property.optional ? '(optional)' : ''), React.createElement("input", { name: "chat-model-id-input", placeholder: property.description, className: "jp-mod-styled", spellCheck: false, value: property.value, onChange: event => onModelPropertyChange('chat', property.id, event.target.value) })))))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Auto-complete model"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Provider"), React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => updateModelOptionsForProvider(event.target.value, 'inline-completion') }, llmProviders.map((provider, index) => (React.createElement("option", { key: index, value: provider.id, selected: provider.id === inlineCompletionModelProvider }, provider.name))), React.createElement("option", { key: -1, value: "none", selected: inlineCompletionModelProvider === 'none' || !llmProviders.find(provider => provider.id === inlineCompletionModelProvider) }, "None")))), !['openai-compatible', 'litellm-compatible', 'none'].includes(inlineCompletionModelProvider) && (React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Model"), ![ OPENAI_COMPATIBLE_INLINE_COMPLETION_MODEL_ID, LITELLM_COMPATIBLE_INLINE_COMPLETION_MODEL_ID ].includes(inlineCompletionModel) && (React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => setInlineCompletionModel(event.target.value) }, inlineCompletionModels.map((model, index) => (React.createElement("option", { key: index, value: model.id, selected: model.id === inlineCompletionModel }, model.name))))))))), React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, inlineCompletionModelProperties.map((property, index) => (React.createElement("div", { className: "form-field-row", key: index }, React.createElement("div", { className: "form-field-description" }, property.name, " ", property.optional ? '(optional)' : ''), React.createElement("input", { name: "inline-completion-model-id-input", placeholder: property.description, className: "jp-mod-styled", spellCheck: false, value: property.value, onChange: event => onModelPropertyChange('inline-completion', property.id, event.target.value) })))))))), (chatModelProvider === 'github-copilot' || inlineCompletionModelProvider === 'github-copilot') && (React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header access-token-config-header" }, "GitHub Copilot login", ' ', React.createElement("a", { href: "https://github.com/notebook-intelligence/notebook-intelligence/blob/main/README.md#remembering-github-copilot-login", target: "_blank" }, ' ', React.createElement(VscWarning, { className: "access-token-warning", title: "Click to learn more about security implications" }))), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("label", null, React.createElement("input", { type: "checkbox", checked: storeGitHubAccessToken, onChange: event => { setStoreGitHubAccessToken(event.target.checked); } }), "Remember my GitHub Copilot access token")))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Config file path"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("span", { className: "user-code-span", onClick: () => { navigator.clipboard.writeText(path.join(NBIAPI.config.userConfigDir, 'config.json')); return true; } }, path.join(NBIAPI.config.userConfigDir, 'config.json'), ' ', React.createElement("span", { className: "copy-icon", dangerouslySetInnerHTML: { __html: copySvgstr } }))))))))); } function SettingsPanelComponentMCPServers(props) { const nbiConfig = NBIAPI.config; const mcpServersRef = useRef(nbiConfig.toolConfig.mcpServers); const mcpServerSettingsRef = useRef(nbiConfig.mcpServerSettings); const [renderCount, setRenderCount] = useState(1); const [mcpServerEnabledState, setMCPServerEnabledState] = useState(new Map(mcpServerSettingsToEnabledState(mcpServersRef.current, mcpServerSettingsRef.current))); const mcpServerEnabledStateToMcpServerSettings = () => { const mcpServerSettings = {}; for (const mcpServer of mcpServersRef.current) { if (mcpServerEnabledState.has(mcpServer.id)) { const disabledTools = []; for (const tool of mcpServer.tools) { if (!mcpServerEnabledState.get(mcpServer.id).has(tool.name)) { disabledTools.push(tool.name); } } mcpServerSettings[mcpServer.id] = { disabled: false, disabled_tools: disabledTools }; } else { mcpServerSettings[mcpServer.id] = { disabled: true }; } } return mcpServerSettings; }; const syncSettingsToServerState = () => { NBIAPI.setConfig({ mcp_server_settings: mcpServerSettingsRef.current }); }; const handleReloadMCPServersClick = async () => { await NBIAPI.reloadMCPServers(); }; useEffect(() => { syncSettingsToServerState(); }, [mcpServerSettingsRef.current]); useEffect(() => { mcpServerSettingsRef.current = mcpServerEnabledStateToMcpServerSettings(); setRenderCount(renderCount => renderCount + 1); }, [mcpServerEnabledState]); const setMCPServerEnabled = (serverId, enabled) => { var _a; const currentState = new Map(mcpServerEnabledState); if (enabled) { if (!(serverId in currentState)) { currentState.set(serverId, new Set((_a = mcpServersRef.current .find((server) => server.id === serverId)) === null || _a === void 0 ? void 0 : _a.tools.map((tool) => tool.name))); } } else { currentState.delete(serverId); } setMCPServerEnabledState(currentState); }; const getMCPServerEnabled = (serverId) => { return mcpServerEnabledState.has(serverId); }; const getMCPServerToolEnabled = (serverId, toolName) => { return (mcpServerEnabledState.has(serverId) && mcpServerEnabledState.get(serverId).has(toolName)); }; const setMCPServerToolEnabled = (serverId, toolName, enabled) => { const currentState = new Map(mcpServerEnabledState); const serverState = currentState.get(serverId); if (enabled) { serverState.add(toolName); } else { serverState.delete(toolName); } setMCPServerEnabledState(currentState); }; useEffect(() => { NBIAPI.configChanged.connect(() => { mcpServersRef.current = nbiConfig.toolConfig.mcpServers; mcpServerSettingsRef.current = nbiConfig.mcpServerSettings; setRenderCount(renderCount => renderCount + 1); }); }, []); return (React.createElement("div", { className: "config-dialog" }, React.createElement("div", { className: "config-dialog-body" }, React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header", style: { display: 'flex' } }, React.createElement("div", { style: { flexGrow: 1 } }, "MCP Servers"), React.createElement("div", null, React.createElement("button", { className: "jp-toast-button jp-mod-small jp-Button", onClick: handleReloadMCPServersClick }, React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Reload")))), React.createElement("div", { className: "model-config-section-body" }, mcpServersRef.current.length === 0 && renderCount > 0 && (React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "No MCP servers found. Add MCP servers in the configuration file.")))), mcpServersRef.current.length > 0 && renderCount > 0 && (React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, mcpServersRef.current.map((server) => (React.createElement("div", { key: server.id }, React.createElement("div", { style: { display: 'flex', alignItems: 'center' } }, React.createElement(CheckBoxItem, { header: true, label: server.id, checked: getMCPServerEnabled(server.id), onClick: () => { setMCPServerEnabled(server.id, !getMCPServerEnabled(server.id)); } }), React.createElement("div", { className: `server-status-indicator ${server.status}`, title: server.status })), getMCPServerEnabled(server.id) && (React.createElement("div", null, server.tools.length > 0 && (React.createElement("div", { className: "mcp-server-tools" }, React.createElement("div", { className: "mcp-server-tools-header" }, "Tools"), React.createElement("div", null, server.tools.map((tool) => (React.createElement(PillItem, { label: tool.name, title: tool.description, checked: getMCPServerToolEnabled(server.id, tool.name), onClick: () => { setMCPServerToolEnabled(server.id, tool.name, !getMCPServerToolEnabled(server.id, tool.name)); } })))))), server.prompts.length > 0 && (React.createElement("div", { className: "mcp-server-prompts" }, React.createElement("div", { className: "mcp-server-prompts-header" }, "Prompts"), React.createElement("div", null, server.prompts.map((prompt) => (React.createElement(PillItem, { label: prompt.name, title: prompt.description, checked: true })))))))))))))), React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column", style: { flexGrow: 'initial' } }, React.createElement("button", { className: "jp-Dialog-button jp-mod-accept jp-mod-styled", style: { width: 'max-content' }, onClick: props.onEditMCPConfigClicked }, React.createElement("div", { className: "jp-Dialog-buttonLabel" }, "Add / Edit"))))))))); } function SettingsPanelComponentClaude(props) { var _a, _b, _c, _d, _e, _f; const nbiConfig = NBIAPI.config; const claudeSettingsRef = useRef(nbiConfig.claudeSettings); const [_renderCount, setRenderCount] = useState(1); const [claudeEnabled, setClaudeEnabled] = useState(nbiConfig.isInClaudeCodeMode); const [chatModel, setChatModel] = useState((_a = nbiConfig.claudeSettings.chat_model) !== null && _a !== void 0 ? _a : ClaudeModelType.Default); const [inlineCompletionModel, setInlineCompletionModel] = useState((_b = nbiConfig.claudeSettings.inline_completion_model) !== null && _b !== void 0 ? _b : ClaudeModelType.Default); const [apiKey, setApiKey] = useState((_c = nbiConfig.claudeSettings.api_key) !== null && _c !== void 0 ? _c : ''); const [baseUrl, setBaseUrl] = useState((_d = nbiConfig.claudeSettings.base_url) !== null && _d !== void 0 ? _d : ''); const [settingSources, setSettingSources] = useState((_e = nbiConfig.claudeSettings.setting_sources) !== null && _e !== void 0 ? _e : []); const [tools, setTools] = useState((_f = nbiConfig.claudeSettings.tools) !== null && _f !== void 0 ? _f : [ ClaudeToolType.ClaudeCodeTools, ClaudeToolType.JupyterUITools ]); useEffect(() => { NBIAPI.configChanged.connect(() => { claudeSettingsRef.current = nbiConfig.claudeSettings; setRenderCount(renderCount => renderCount + 1); }); }, []); const syncSettingsToServerState = () => { NBIAPI.setConfig({ claude_settings: { enabled: claudeEnabled, chat_model: chatModel, inline_completion_model: inlineCompletionModel, api_key: apiKey, base_url: baseUrl, setting_sources: settingSources, tools: tools } }); }; useEffect(() => { syncSettingsToServerState(); }, [ claudeEnabled, chatModel, inlineCompletionModel, apiKey, baseUrl, settingSources, tools ]); return (React.createElement("div", { className: "config-dialog claude-mode-config-dialog" }, React.createElement("div", { className: "config-dialog-body" }, React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Enable Claude mode"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("span", null, "This requires a", ' ', React.createElement("a", { href: "https://claude.ai", target: "_blank" }, "Claude"), ' ', "account and", ' ', React.createElement("a", { href: "https://code.claude.com/", target: "_blank" }, "Claude Code"), ' ', "installed in your system.")), React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement(CheckBoxItem, { header: true, label: "Enable Claude mode", checked: claudeEnabled, onClick: () => { setClaudeEnabled(!claudeEnabled); } })))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Models"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Chat model"), React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => setChatModel(event.target.value) }, React.createElement("option", { value: ClaudeModelType.Default, selected: chatModel === ClaudeModelType.Default }, "Default (recommended)"), React.createElement("option", { value: ClaudeModelType.ClaudeOpus45, selected: chatModel === ClaudeModelType.ClaudeOpus45 }, "Claude Opus 4.5"), React.createElement("option", { value: ClaudeModelType.ClaudeHaiku45, selected: chatModel === ClaudeModelType.ClaudeHaiku45 }, "Claude Haiku 4.5")))), React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, "Auto-complete model"), React.createElement("div", null, React.createElement("select", { className: "jp-mod-styled", onChange: event => setInlineCompletionModel(event.target.value) }, React.createElement("option", { value: ClaudeModelType.Default, selected: inlineCompletionModel === ClaudeModelType.Default }, "Default (recommended)"), React.createElement("option", { value: ClaudeModelType.ClaudeOpus45, selected: inlineCompletionModel === ClaudeModelType.ClaudeOpus45 }, "Claude Opus 4.5"), React.createElement("option", { value: ClaudeModelType.ClaudeHaiku45, selected: inlineCompletionModel === ClaudeModelType.ClaudeHaiku45 }, "Claude Haiku 4.5"))))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Chat Agent setting sources"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement(CheckBoxItem, { header: true, label: "User", checked: settingSources.includes('user'), onClick: () => { setSettingSources(settingSources.includes('user') ? settingSources.filter((source) => source !== 'user') : [...settingSources, 'user']); } }))), React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement(CheckBoxItem, { header: true, label: "Project (Jupyter root directory)", checked: settingSources.includes('project'), onClick: () => { setSettingSources(settingSources.includes('project') ? settingSources.filter((source) => source !== 'project') : [...settingSources, 'project']); } })))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Chat Agent tools"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement(CheckBoxItem, { header: true, label: "Claude Code tools", checked: tools.includes(ClaudeToolType.ClaudeCodeTools), disabled: true, onClick: () => { setTools(tools.includes(ClaudeToolType.ClaudeCodeTools) ? tools.filter((tool) => tool !== ClaudeToolType.ClaudeCodeTools) : [...tools, ClaudeToolType.ClaudeCodeTools]); } }))), React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", null, React.createElement(CheckBoxItem, { header: true, label: "Jupyter UI tools", checked: tools.includes(ClaudeToolType.JupyterUITools), onClick: () => { setTools(tools.includes(ClaudeToolType.JupyterUITools) ? tools.filter((tool) => tool !== ClaudeToolType.JupyterUITools) : [...tools, ClaudeToolType.JupyterUITools]); } })))))), React.createElement("div", { className: "model-config-section" }, React.createElement("div", { className: "model-config-section-header" }, "Claude account"), React.createElement("div", { className: "model-config-section-body" }, React.createElement("div", { className: "model-config-section-row" }, React.createElement("div", { className: "model-config-section-column" }, React.createElement("div", { className: "form-field-row" }, React.createElement("div", { className: "form-field-description" }, "API Key (optional)"), React.createElement("input", { name: "chat-model-id-input", placeholder: "API Key", className: "jp-mod-styled", spellCheck: false, value: apiKey, onChange: event => setApiKey(event.target.value) })), React.createElement("div", { className: "form-field-row" }, React.createElement("div", { className: "form-field-description" }, "Base URL (optional)"), React.createElement("input", { name: "chat-model-id-input", placeholder: "https://api.anthropic.com", className: "jp-mod-styled", spellCheck: false, value: baseUrl, onChange: event => setBaseUrl(event.target.value) }))))))))); }