feat(ollama): enhance model pull with improved error handling, persistence, and UI
- Add catalog metadata lookup for better error messages with hints (e.g., for missing manifests or tags) - Persist downloaded model references in saved remote models for future reuse - Replace searchRemoteModels import with getSavedRemoteModels in search route - Enhance pull progress UI to display download bytes, digest, and fallback message when data is unavailable - Improve error payload with model details, URL, and tags count to guide users toward valid tags or models
This commit is contained in:
1 parent
1545020afe
commit
a8bb7cc22d
33 files changed
+1298
-235
No files matched your search
@@ -129,18 +129,18 @@ export function MCPManualInstallModal({
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-3xl w-full max-h-[90vh] overflow-y-auto">
|
||||
<div className="bg-[var(--background)] rounded-lg shadow-xl max-w-3xl w-full max-h-[90vh] overflow-y-auto border border-[var(--border)]">
|
||||
{/* Header */}
|
||||
<div className="sticky top-0 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 p-4 flex items-center justify-between">
|
||||
<div className="sticky top-0 border-b border-[var(--border)] p-4 flex items-center justify-between bg-[color-mix(in_oklab,var(--background),black_2%)]/90 backdrop-blur supports-[backdrop-filter]:bg-[color-mix(in_oklab,var(--background),black_2%)]/70">
|
||||
<div className="flex items-center gap-2">
|
||||
<Upload className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
Install MCP Manually
|
||||
<Upload className="h-5 w-5 text-[var(--accent)]" />
|
||||
<h2 className="text-xl font-semibold">
|
||||
Instalar MCP Manualmente
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
|
||||
className="p-2 hover:bg-[var(--surface)] rounded-lg transition-colors"
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
@@ -149,46 +149,45 @@ export function MCPManualInstallModal({
|
||||
{/* Content */}
|
||||
<div className="p-6 space-y-6">
|
||||
{/* Description */}
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
|
||||
<h3 className="font-medium text-blue-900 dark:text-blue-100 mb-2">
|
||||
How to use
|
||||
<div className="rounded-lg p-4 border border-[var(--border)] bg-[var(--surface)]/60">
|
||||
<h3 className="font-medium mb-2">
|
||||
Como usar
|
||||
</h3>
|
||||
<p className="text-sm text-blue-700 dark:text-blue-300 mb-3">
|
||||
Cole a configuração do servidor MCP no formato do Claude Desktop
|
||||
(claude_desktop_config.json). Apenas instalação manual é suportada
|
||||
neste projeto.
|
||||
<p className="text-sm mb-3 text-[var(--foreground)]/80">
|
||||
Cole a configuração do servidor MCP no formato do Claude Desktop (claude_desktop_config.json).
|
||||
Apenas instalação manual é suportada neste projeto.
|
||||
</p>
|
||||
<button
|
||||
onClick={handlePasteExample}
|
||||
className="text-sm text-blue-600 dark:text-blue-400 hover:underline"
|
||||
className="text-sm text-[var(--accent)] hover:underline"
|
||||
>
|
||||
Click here to load an example
|
||||
Clique aqui para carregar um exemplo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* MCP ID (optional) */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
MCP ID (optional)
|
||||
MCP ID (opcional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={mcpId}
|
||||
onChange={(e) => setMcpId(e.target.value)}
|
||||
placeholder="my-custom-mcp (auto-detected if empty)"
|
||||
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
placeholder="my-custom-mcp (detectado automaticamente se vazio)"
|
||||
className="w-full px-4 py-2 border border-[var(--border)] rounded-lg bg-[var(--background)] focus:ring-2 focus:ring-[var(--accent)] focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Configuration JSON */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Configuration JSON *
|
||||
JSON de Configuração *
|
||||
</label>
|
||||
<textarea
|
||||
value={configJson}
|
||||
onChange={(e) => handleConfigChange(e.target.value)}
|
||||
placeholder={`Paste your configuration here, e.g.:
|
||||
placeholder={`Cole a configuração aqui, ex.:
|
||||
{
|
||||
"mcpServers": {
|
||||
"time-server": {
|
||||
@@ -198,7 +197,7 @@ export function MCPManualInstallModal({
|
||||
}
|
||||
}`}
|
||||
rows={15}
|
||||
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white font-mono text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
|
||||
className="w-full px-4 py-3 border border-[var(--border)] rounded-lg bg-[var(--background)] font-mono text-sm focus:ring-2 focus:ring-[var(--accent)] focus:border-transparent resize-none"
|
||||
/>
|
||||
|
||||
{/* Validation Status */}
|
||||
@@ -207,16 +206,12 @@ export function MCPManualInstallModal({
|
||||
{validationError ? (
|
||||
<>
|
||||
<AlertCircle className="h-4 w-4 text-red-500" />
|
||||
<span className="text-sm text-red-600 dark:text-red-400">
|
||||
{validationError}
|
||||
</span>
|
||||
<span className="text-sm text-red-600">{validationError}</span>
|
||||
</>
|
||||
) : parsedConfig ? (
|
||||
<>
|
||||
<CheckCircle className="h-4 w-4 text-green-500" />
|
||||
<span className="text-sm text-green-600 dark:text-green-400">
|
||||
Valid configuration
|
||||
</span>
|
||||
<span className="text-sm text-green-600">Configuração válida</span>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -225,24 +220,22 @@ export function MCPManualInstallModal({
|
||||
|
||||
{/* Preview */}
|
||||
{parsedConfig && !validationError && (
|
||||
<div className="bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
||||
<h3 className="font-medium text-gray-900 dark:text-white mb-3">
|
||||
Preview
|
||||
</h3>
|
||||
<div className="border border-[var(--border)] rounded-lg p-4 bg-[var(--surface)]/50">
|
||||
<h3 className="font-medium mb-3">Pré-visualização</h3>
|
||||
<div className="space-y-2 text-sm">
|
||||
{parsedConfig.mcpServers ? (
|
||||
Object.entries(parsedConfig.mcpServers).map(
|
||||
([name, config]: [string, any]) => (
|
||||
<div key={name} className="space-y-1">
|
||||
<div className="text-gray-700 dark:text-gray-300">
|
||||
<div className="">
|
||||
<span className="font-medium">Server:</span> {name}
|
||||
</div>
|
||||
<div className="text-gray-600 dark:text-gray-400">
|
||||
<div className="text-[var(--foreground)]/80">
|
||||
<span className="font-medium">Command:</span>{" "}
|
||||
{config.command} {(config.args || []).join(" ")}
|
||||
</div>
|
||||
{config.env && (
|
||||
<div className="text-gray-600 dark:text-gray-400">
|
||||
<div className="text-[var(--foreground)]/80">
|
||||
<span className="font-medium">Environment:</span>{" "}
|
||||
{Object.keys(config.env).length} variables
|
||||
</div>
|
||||
@@ -252,13 +245,13 @@ export function MCPManualInstallModal({
|
||||
)
|
||||
) : (
|
||||
<div className="space-y-1">
|
||||
<div className="text-gray-600 dark:text-gray-400">
|
||||
<div className="text-[var(--foreground)]/80">
|
||||
<span className="font-medium">Command:</span>{" "}
|
||||
{parsedConfig.command}{" "}
|
||||
{(parsedConfig.args || []).join(" ")}
|
||||
</div>
|
||||
{parsedConfig.env && (
|
||||
<div className="text-gray-600 dark:text-gray-400">
|
||||
<div className="text-[var(--foreground)]/80">
|
||||
<span className="font-medium">Environment:</span>{" "}
|
||||
{Object.keys(parsedConfig.env).length} variables
|
||||
</div>
|
||||
@@ -275,12 +268,8 @@ export function MCPManualInstallModal({
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertCircle className="h-5 w-5 text-red-500 shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-red-900 dark:text-red-100">
|
||||
Installation Error
|
||||
</h4>
|
||||
<p className="text-sm text-red-700 dark:text-red-300 mt-1">
|
||||
{error}
|
||||
</p>
|
||||
<h4 className="font-medium text-red-900">Erro na instalação</h4>
|
||||
<p className="text-sm text-red-700 mt-1">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -288,28 +277,28 @@ export function MCPManualInstallModal({
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="sticky bottom-0 bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 p-4 flex gap-3 justify-end">
|
||||
<div className="sticky bottom-0 bg-[var(--surface)]/60 border-t border-[var(--border)] p-4 flex gap-3 justify-end">
|
||||
<button
|
||||
onClick={onClose}
|
||||
disabled={isInstalling}
|
||||
className="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg transition-colors disabled:opacity-50"
|
||||
className="px-4 py-2 hover:bg-[var(--surface)] rounded-lg transition-colors disabled:opacity-50"
|
||||
>
|
||||
Cancel
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
onClick={handleInstall}
|
||||
disabled={isInstalling || !parsedConfig || !!validationError}
|
||||
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
className="px-6 py-2 bg-[var(--accent)] text-[var(--accent-foreground)] rounded-lg hover:bg-[color-mix(in_oklab,var(--accent),black_10%)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
>
|
||||
{isInstalling ? (
|
||||
<>
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
Installing...
|
||||
Instalando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="h-4 w-4" />
|
||||
Install MCP
|
||||
Instalar MCP
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
Reference in new issue
Block a user