mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-01-16 08:21:55 +00:00
update hello world
This commit is contained in:
parent
b1315aa6b1
commit
d83ea57fca
@ -59,12 +59,12 @@ import { editorStateToPlainText } from './chat-input/utils/editor-state-to-plain
|
||||
import { ChatHistory } from './ChatHistoryView'
|
||||
import CommandsView from './CommandsView'
|
||||
import CustomModeView from './CustomModeView'
|
||||
import MarkdownReasoningBlock from './Markdown/MarkdownReasoningBlock'
|
||||
import HelloInfo from './HelloInfo'
|
||||
import McpHubView from './McpHubView' // Moved after MarkdownReasoningBlock
|
||||
import QueryProgress, { QueryProgressState } from './QueryProgress'
|
||||
import ReactMarkdown from './ReactMarkdown'
|
||||
import ShortcutInfo from './ShortcutInfo'
|
||||
import SimilaritySearchResults from './SimilaritySearchResults'
|
||||
import MarkdownReasoningBlock from './Markdown/MarkdownReasoningBlock'
|
||||
|
||||
// Add an empty line here
|
||||
const getNewInputMessage = (app: App, defaultMention: string): ChatUserMessage => {
|
||||
@ -609,7 +609,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
}
|
||||
} else if (toolArgs.type === 'regex_search_files') {
|
||||
// @ts-expect-error Obsidian API type mismatch
|
||||
const baseVaultPath = app.vault.adapter.getBasePath()
|
||||
const baseVaultPath = String(app.vault.adapter.getBasePath())
|
||||
const ripgrepPath = settings.ripgrepPath
|
||||
const absolutePath = path.join(baseVaultPath, toolArgs.filepath)
|
||||
const results = await regexSearchFiles(absolutePath, toolArgs.regex, ripgrepPath)
|
||||
@ -730,7 +730,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
return item.text
|
||||
}
|
||||
if (item.type === "resource") {
|
||||
const { blob: _, ...rest } = item.resource
|
||||
const { blob: _blob, ...rest } = item.resource
|
||||
return JSON.stringify(rest, null, 2)
|
||||
}
|
||||
return ""
|
||||
@ -776,7 +776,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
role: 'assistant',
|
||||
applyStatus: ApplyStatus.Idle,
|
||||
isToolResult: true,
|
||||
content: `<tool_result>${result.returnMsg.promptContent}</tool_result>`,
|
||||
content: `<tool_result>${typeof result.returnMsg.promptContent === 'string' ? result.returnMsg.promptContent : ''}</tool_result>`,
|
||||
reasoningContent: '',
|
||||
metadata: {
|
||||
usage: undefined,
|
||||
@ -1037,7 +1037,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
// If the chat is empty, show a message to start a new chat
|
||||
chatMessages.length === 0 && (
|
||||
<div className="infio-chat-empty-state">
|
||||
<ShortcutInfo />
|
||||
<HelloInfo onNavigate={(tab) => setTab(tab)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
144
src/components/chat-view/HelloInfo.tsx
Normal file
144
src/components/chat-view/HelloInfo.tsx
Normal file
@ -0,0 +1,144 @@
|
||||
import { NotebookPen, Server, SquareSlash } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
import { t } from '../../lang/helpers';
|
||||
|
||||
interface HelloInfoProps {
|
||||
onNavigate: (tab: 'commands' | 'custom-mode' | 'mcp') => void;
|
||||
}
|
||||
|
||||
const HelloInfo: React.FC<HelloInfoProps> = ({ onNavigate }) => {
|
||||
const navigationItems = [
|
||||
{
|
||||
label: t('chat.navigation.commands'),
|
||||
description: t('chat.navigation.commandsDesc'),
|
||||
icon: <SquareSlash size={20} />,
|
||||
action: () => onNavigate('commands'),
|
||||
},
|
||||
{
|
||||
label: t('chat.navigation.customMode'),
|
||||
description: t('chat.navigation.customModeDesc'),
|
||||
icon: <NotebookPen size={20} />,
|
||||
action: () => onNavigate('custom-mode'),
|
||||
},
|
||||
{
|
||||
label: t('chat.navigation.mcp'),
|
||||
description: t('chat.navigation.mcpDesc'),
|
||||
icon: <Server size={20} />,
|
||||
action: () => onNavigate('mcp'),
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="infio-hello-info">
|
||||
{/* <div className="infio-hello-title">
|
||||
<h3>{t('chat.welcome.title')}</h3>
|
||||
<p>{t('chat.welcome.subtitle')}</p>
|
||||
</div> */}
|
||||
<div className="infio-navigation-cards">
|
||||
{navigationItems.map((item, index) => (
|
||||
<a
|
||||
key={index}
|
||||
className="infio-navigation-card"
|
||||
onClick={item.action}
|
||||
>
|
||||
<div className="infio-navigation-icon">
|
||||
{item.icon}
|
||||
</div>
|
||||
<div className="infio-navigation-content">
|
||||
<div className="infio-navigation-label">{item.label}</div>
|
||||
<div className="infio-navigation-description">{item.description}</div>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<style>
|
||||
{`
|
||||
/*
|
||||
* Hello Info and Navigation
|
||||
*/
|
||||
.infio-hello-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: var(--size-4-8) var(--size-4-4);
|
||||
gap: var(--size-4-6);
|
||||
text-align: center;
|
||||
margin: var(--size-4-4);
|
||||
}
|
||||
|
||||
.infio-hello-title h3 {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
margin: 0 0 var(--size-4-3) 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.infio-hello-title p {
|
||||
font-size: var(--font-ui-medium);
|
||||
color: var(--text-muted);
|
||||
margin: 0;
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.infio-navigation-cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.infio-navigation-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--size-4-4);
|
||||
padding: var(--size-4-5) var(--size-4-6);
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.infio-navigation-card:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
border-color: var(--text-accent);
|
||||
}
|
||||
|
||||
.infio-navigation-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-m);
|
||||
color: var(--text-accent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.infio-navigation-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--size-2-2);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.infio-navigation-label {
|
||||
font-size: var(--font-ui-large);
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.infio-navigation-description {
|
||||
font-size: var(--font-ui-small);
|
||||
color: var(--text-muted);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HelloInfo;
|
||||
@ -1,4 +1,5 @@
|
||||
import { AlertTriangle, ChevronDown, ChevronRight, FileText, Folder, Power, RotateCcw, Trash2, Wrench } from 'lucide-react'
|
||||
import { Notice } from 'obsidian'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import { useMcpHub } from '../../contexts/McpHubContext'
|
||||
@ -13,6 +14,11 @@ const McpHubView = () => {
|
||||
const [expandedServers, setExpandedServers] = useState<Record<string, boolean>>({});
|
||||
const [activeServerDetailTab, setActiveServerDetailTab] = useState<Record<string, 'tools' | 'resources' | 'errors'>>({});
|
||||
|
||||
// 新增状态变量用于创建新服务器
|
||||
const [newServerName, setNewServerName] = useState('')
|
||||
const [newServerConfig, setNewServerConfig] = useState('')
|
||||
const [isCreateSectionExpanded, setIsCreateSectionExpanded] = useState(false)
|
||||
|
||||
const fetchServers = async () => {
|
||||
const hub = await getMcpHub()
|
||||
console.log('Fetching MCP Servers from hub:', hub)
|
||||
@ -67,6 +73,42 @@ const McpHubView = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleCreate = async () => {
|
||||
// 验证输入
|
||||
if (newServerName.trim().length === 0) {
|
||||
new Notice("服务器名称不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
if (newServerConfig.trim().length === 0) {
|
||||
new Notice("配置不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// check config is valid json
|
||||
try {
|
||||
JSON.parse(newServerConfig)
|
||||
} catch (error) {
|
||||
new Notice("配置格式无效,请输入有效的 JSON 格式")
|
||||
return
|
||||
}
|
||||
|
||||
const hub = await getMcpHub();
|
||||
if (hub) {
|
||||
try {
|
||||
await hub.createServer(newServerName, newServerConfig, "global")
|
||||
const updatedServers = hub.getAllServers()
|
||||
setMcpServers(updatedServers)
|
||||
|
||||
// 清空表单
|
||||
setNewServerName('')
|
||||
setNewServerConfig('')
|
||||
new Notice(`服务器 "${newServerName}" 创建成功`)
|
||||
} catch (error) {
|
||||
new Notice(`创建服务器失败: ${error.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const toggleServerExpansion = (serverKey: string) => {
|
||||
setExpandedServers(prev => ({ ...prev, [serverKey]: !prev[serverKey] }));
|
||||
@ -79,6 +121,10 @@ const McpHubView = () => {
|
||||
setActiveServerDetailTab(prev => ({ ...prev, [serverKey]: tab }));
|
||||
};
|
||||
|
||||
const toggleCreateSectionExpansion = () => {
|
||||
setIsCreateSectionExpanded(prev => !prev)
|
||||
}
|
||||
|
||||
const ToolRow = ({ tool }: { tool: McpTool }) => {
|
||||
return (
|
||||
<div className="infio-mcp-tool-row">
|
||||
@ -168,11 +214,66 @@ const McpHubView = () => {
|
||||
<span className="infio-mcp-setting-text">启用 MCP 服务器</span>
|
||||
</label>
|
||||
<p className="infio-mcp-setting-description">
|
||||
开启后 Roo 可用已连接 MCP 服务器的工具,能力更强。不用这些工具时建议关闭,节省 API Token 费用。
|
||||
开启后可用已连接 MCP 服务器的工具,能力更强。不用这些工具时建议关闭,节省 API Token 费用。
|
||||
<a href="https://modelcontextprotocol.io/introduction" target="_blank" rel="noopener noreferrer">
|
||||
Learn more about MCP
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Create New Server Section */}
|
||||
{settings.mcpEnabled && (
|
||||
<div className="infio-mcp-create-section">
|
||||
<div className="infio-mcp-create-item">
|
||||
<div className="infio-mcp-create-item-header" onClick={toggleCreateSectionExpansion}>
|
||||
<div className="infio-mcp-create-item-info">
|
||||
<div className="infio-mcp-hub-expander">
|
||||
{isCreateSectionExpanded ? <ChevronDown size={16} /> : <ChevronRight size={16} />}
|
||||
</div>
|
||||
<h3 className="infio-mcp-create-title">+ 添加新的 MCP 服务器</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isCreateSectionExpanded && (
|
||||
<div className="infio-mcp-create-expanded">
|
||||
<div className="infio-mcp-create-label">服务器名称</div>
|
||||
<input
|
||||
type="text"
|
||||
value={newServerName}
|
||||
onChange={(e) => setNewServerName(e.target.value)}
|
||||
placeholder="输入服务器名称"
|
||||
className="infio-mcp-create-input"
|
||||
/>
|
||||
<div className="infio-mcp-create-label">配置 (JSON 格式)</div>
|
||||
<textarea
|
||||
value={newServerConfig}
|
||||
onChange={(e) => setNewServerConfig(e.target.value)}
|
||||
placeholder='example: {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"/Users/username/Desktop",
|
||||
"/path/to/other/allowed/dir"
|
||||
]
|
||||
}'
|
||||
className="infio-mcp-create-textarea"
|
||||
rows={4}
|
||||
/>
|
||||
<button
|
||||
onClick={handleCreate}
|
||||
className="infio-mcp-create-btn"
|
||||
disabled={!newServerName.trim() || !newServerConfig.trim()}
|
||||
>
|
||||
<span>创建服务器</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Servers List */}
|
||||
{settings.mcpEnabled && (
|
||||
<div className="infio-mcp-hub-list">
|
||||
@ -300,8 +401,7 @@ const McpHubView = () => {
|
||||
padding: 16px;
|
||||
gap: 16px;
|
||||
color: var(--text-normal);
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
@ -376,8 +476,7 @@ const McpHubView = () => {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.infio-mcp-hub-item-header {
|
||||
@ -584,7 +683,21 @@ const McpHubView = () => {
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
background-color: var(--background-secondary);
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
padding-bottom: 16px;
|
||||
animation: expandContent 0.3s ease-out;
|
||||
border-bottom-left-radius: var(--radius-s);
|
||||
border-bottom-right-radius: var(--radius-s);
|
||||
}
|
||||
|
||||
@keyframes expandContent {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.infio-mcp-tabs {
|
||||
@ -747,6 +860,139 @@ const McpHubView = () => {
|
||||
padding: 40px 20px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Create New Server Section */
|
||||
.infio-mcp-create-section {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.infio-mcp-create-item {
|
||||
/* Remove background and padding since we're restructuring */
|
||||
}
|
||||
|
||||
.infio-mcp-create-item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.infio-mcp-create-item-header:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.infio-mcp-create-item-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.infio-mcp-create-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.infio-mcp-create-expanded {
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
background-color: var(--background-secondary);
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
animation: expandContent 0.3s ease-out;
|
||||
border-bottom-left-radius: var(--radius-s);
|
||||
border-bottom-right-radius: var(--radius-s);
|
||||
}
|
||||
|
||||
.infio-mcp-create-new {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.infio-mcp-create-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-normal);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.infio-mcp-create-input {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
color: var(--text-normal);
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.infio-mcp-create-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.infio-mcp-create-textarea {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: var(--radius-s);
|
||||
color: var(--text-normal);
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-family: var(--font-monospace);
|
||||
resize: vertical;
|
||||
min-height: 140px;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.infio-mcp-create-textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.infio-mcp-create-btn {
|
||||
background-color: var(--interactive-accent);
|
||||
color: var(--text-on-accent);
|
||||
border: none;
|
||||
border-radius: var(--radius-s);
|
||||
padding: 10px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.infio-mcp-create-btn:hover:not(:disabled) {
|
||||
background-color: var(--interactive-accent-hover);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.infio-mcp-create-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* Servers List */
|
||||
.infio-mcp-hub-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
import { Platform } from 'obsidian';
|
||||
import React from 'react';
|
||||
|
||||
import { t } from '../../lang/helpers'
|
||||
|
||||
const ShortcutInfo: React.FC = () => {
|
||||
const modKey = Platform.isMacOS ? 'Cmd' : 'Ctrl';
|
||||
|
||||
const shortcuts = [
|
||||
{
|
||||
label: t('chat.shortcutInfo.editInline'),
|
||||
shortcut: `${modKey}+Shift+K`,
|
||||
},
|
||||
{
|
||||
label: t('chat.shortcutInfo.chatWithSelect'),
|
||||
shortcut: `${modKey}+Shift+L`,
|
||||
},
|
||||
{
|
||||
label: t('chat.shortcutInfo.submitWithVault'),
|
||||
shortcut: `${modKey}+Shift+Enter`,
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="infio-shortcut-info">
|
||||
<table className="infio-shortcut-table">
|
||||
<tbody>
|
||||
{shortcuts.map((item, index) => (
|
||||
<tr key={index} className="infio-shortcut-item">
|
||||
<td className="infio-shortcut-label">{item.label}</td>
|
||||
<td className="infio-shortcut-key"><kbd>{item.shortcut}</kbd></td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShortcutInfo;
|
||||
@ -1108,6 +1108,84 @@ export class McpHub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MCP server with the given name and configuration
|
||||
* @param name The name of the server to create
|
||||
* @param config JSON string containing the server configuration
|
||||
* @param source Whether to create in global or project scope (defaults to global)
|
||||
*/
|
||||
public async createServer(
|
||||
name: string,
|
||||
config: string,
|
||||
source: "global" | "project" = "global"
|
||||
): Promise<void> {
|
||||
try {
|
||||
// Parse the JSON config string
|
||||
let parsedConfig: unknown
|
||||
try {
|
||||
parsedConfig = JSON.parse(config)
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid JSON format in config: ${error instanceof Error ? error.message : String(error)}`)
|
||||
}
|
||||
|
||||
// Validate the parsed config
|
||||
const validatedConfig = this.validateServerConfig(parsedConfig, name)
|
||||
|
||||
// Determine which config file to update
|
||||
let configPath: string
|
||||
if (source === "project") {
|
||||
const projectMcpPath = normalizePath(".infio_json_db/mcp/mcp.json")
|
||||
if (!await this.app.vault.adapter.exists(projectMcpPath)) {
|
||||
// Create project config file if it doesn't exist
|
||||
await this.app.vault.adapter.write(
|
||||
projectMcpPath,
|
||||
JSON.stringify({ mcpServers: {} }, null, 2)
|
||||
)
|
||||
}
|
||||
configPath = projectMcpPath
|
||||
} else {
|
||||
configPath = await this.getMcpSettingsFilePath()
|
||||
}
|
||||
|
||||
// Read current config
|
||||
const content = await this.app.vault.adapter.read(configPath)
|
||||
const currentConfig = JSON.parse(content)
|
||||
|
||||
// Validate the config structure
|
||||
if (!currentConfig || typeof currentConfig !== "object") {
|
||||
throw new Error("Invalid config file structure")
|
||||
}
|
||||
|
||||
// Ensure mcpServers object exists
|
||||
if (!currentConfig.mcpServers || typeof currentConfig.mcpServers !== "object") {
|
||||
currentConfig.mcpServers = {}
|
||||
}
|
||||
|
||||
// Check if server already exists
|
||||
if (currentConfig.mcpServers[name]) {
|
||||
throw new Error(`Server "${name}" already exists. Use updateServerConfig to modify existing servers.`)
|
||||
}
|
||||
|
||||
// Add the new server to the config
|
||||
currentConfig.mcpServers[name] = validatedConfig
|
||||
|
||||
// Write the updated config back to file
|
||||
const updatedConfig = {
|
||||
mcpServers: currentConfig.mcpServers,
|
||||
}
|
||||
|
||||
await this.app.vault.adapter.write(configPath, JSON.stringify(updatedConfig, null, 2))
|
||||
|
||||
// Update server connections to connect to the new server
|
||||
await this.updateServerConnections(currentConfig.mcpServers, source)
|
||||
|
||||
console.log(`Successfully created and connected to MCP server: ${name}`)
|
||||
} catch (error) {
|
||||
this.showErrorMessage(`Failed to create MCP server "${name}"`, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async readResource(serverName: string, uri: string, source: "global" | "project" = "global"): Promise<McpResourceResponse> {
|
||||
const connection = this.findConnection(serverName, source)
|
||||
if (!connection) {
|
||||
|
||||
@ -1,6 +1,18 @@
|
||||
export default {
|
||||
chat: {
|
||||
stop: "Stop",
|
||||
welcome: {
|
||||
title: "Welcome to Infio Copilot",
|
||||
subtitle: "Explore different modes to enhance your productivity"
|
||||
},
|
||||
navigation: {
|
||||
commands: "Commands",
|
||||
commandsDesc: "Create and manage custom commands for quick actions",
|
||||
customMode: "Custom Mode",
|
||||
customModeDesc: "Define personalized AI modes with specific behaviors",
|
||||
mcp: "MCP",
|
||||
mcpDesc: "Manage Model Context Protocol integrations"
|
||||
},
|
||||
errors: {
|
||||
failedToLoadConversation: "Failed to load conversation",
|
||||
failedToSaveHistory: "Failed to save chat history",
|
||||
|
||||
@ -2,6 +2,18 @@
|
||||
export default {
|
||||
chat: {
|
||||
stop: "停止",
|
||||
welcome: {
|
||||
title: "欢迎使用 Infio Copilot",
|
||||
subtitle: "探索不同模式来提升您的生产力"
|
||||
},
|
||||
navigation: {
|
||||
commands: "命令",
|
||||
commandsDesc: "创建和管理用于快速操作的自定义命令",
|
||||
customMode: "自定义模式",
|
||||
customModeDesc: "定义具有特定行为的个性化 AI 模式",
|
||||
mcp: "MCP",
|
||||
mcpDesc: "管理模型上下文协议集成"
|
||||
},
|
||||
errors: {
|
||||
failedToLoadConversation: "加载对话失败",
|
||||
failedToSaveHistory: "保存聊天记录失败",
|
||||
|
||||
@ -2242,6 +2242,8 @@ button.infio-chat-input-model-select {
|
||||
|
||||
/* 禁用Obsidian模态框的滚动 */
|
||||
.modal.mod-image-selector .modal-content {
|
||||
overflow: hidden !important;
|
||||
max-width: 80vw;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user