Поиск, установка и управление плагинами из реестра npm
Plugin Marketplace — это система для поиска, установки, обновления и управления плагинами Ollama Code через npm-реестр. Marketplace позволяет расширять функциональность Ollama Code без изменения исходного кода.
┌─────────────────────────────────────────────────────────────────┐
│ Marketplace Architecture │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
│ │ CLI Layer │────▶│ PluginMarketplace │ │
│ │ plugin search │ │ - search() │ │
│ │ plugin install │ │ - install() │ │
│ │ plugin update │ │ - update() │ │
│ └─────────────────┘ │ - uninstall() │ │
│ └────────────┬────────────────────┘ │
│ │ │
│ ┌────────────▼────────────────────┐ │
│ │ npm Registry │ │
│ │ - registry.npmjs.org │ │
│ │ - ollama-code-plugin-* │ │
│ └─────────────────────────────────┘ │
│ │
│ Installation Directories: │
│ ├─ User-level: ~/.ollama-code/plugins/ │
│ └─ Project-level: .ollama-code/plugins/ │
│ │
└─────────────────────────────────────────────────────────────────┘
# Базовый поиск
plugin search <query>
# Поиск с фильтрами
plugin search "git" --limit 10 --sort-by downloads
# Поиск только непроверенных плагинов
plugin search "database" --trust-level unverified
Опции поиска:
| Опция | Описание | По умолчанию |
|---|---|---|
--limit |
Максимальное количество результатов | 20 |
--sort-by |
Сортировка: downloads, stars, updated, name |
downloads |
--sort-order |
Порядок: asc, desc |
desc |
--trust-level |
Фильтр по уровню доверия | все |
--author |
Фильтр по автору | - |
--keywords |
Фильтр по ключевым словам | - |
# Получить детальную информацию о плагине
plugin info <plugin-id>
# Пример
plugin info git-tools
Вывод включает:
# Базовая установка (глобально)
plugin install <plugin-id>
# Установка конкретной версии
plugin install my-plugin --version 1.2.0
# Установка в проект (локально)
plugin install my-plugin --no-global
# Принудительная переустановка
plugin install my-plugin --force
# Пропуск верификации (для непроверенных плагинов)
plugin install experimental-plugin --skip-verification
# Тестовый запуск (без реальной установки)
plugin install my-plugin --dry-run
Опции установки:
| Опция | Описание | По умолчанию |
|---|---|---|
--version |
Конкретная версия | latest |
--global |
Глобальная установка (user-level) | true |
--force |
Переустановка при наличии | false |
--skip-verification |
Пропуск проверки безопасности | false |
--dry-run |
Тестовый запуск | false |
# Обновить конкретный плагин
plugin update <plugin-id>
# Обновить все установленные плагины
plugin update --all
# Только проверить наличие обновлений
plugin update --check-only
# Тестовый запуск обновления
plugin update --dry-run
# Удалить плагин
plugin uninstall <plugin-id>
# Удалить локально установленный плагин
plugin uninstall my-plugin --no-global
# Показать все установленные плагины
plugin list
import { createPluginMarketplace, PluginMarketplace } from '@ollama-code/ollama-code-core';
// Создать экземпляр с текущей директорией проекта
const marketplace = createPluginMarketplace(process.cwd());
// Или напрямую через класс
const marketplace = new PluginMarketplace('/path/to/project');
import type { MarketplaceSearchOptions } from '@ollama-code/ollama-code-core';
const options: MarketplaceSearchOptions = {
query: 'git',
keywords: ['version-control'],
sortBy: 'downloads',
sortOrder: 'desc',
limit: 10,
includeInstalled: true,
};
const plugins = await marketplace.search(options);
for (const plugin of plugins) {
console.log(`${plugin.name} v${plugin.version}`);
console.log(` Installed: ${plugin.installed}`);
console.log(` Trust Level: ${plugin.trustLevel}`);
}
// Получить плагин по ID или имени пакета
const plugin = await marketplace.getPlugin('git-tools');
if (plugin) {
console.log(`Name: ${plugin.name}`);
console.log(`Description: ${plugin.description}`);
console.log(`Author: ${plugin.author?.name}`);
console.log(`Repository: ${plugin.repository}`);
console.log(`Verified: ${plugin.verified}`);
}
import type { PluginInstallOptions } from '@ollama-code/ollama-code-core';
const options: PluginInstallOptions = {
version: '1.2.0', // Опционально: конкретная версия
global: true, // Глобальная установка
force: false, // Не переустанавливать
skipVerification: false, // Проверять безопасность
dryRun: false, // Реальная установка
};
const result = await marketplace.install('my-plugin', options);
if (result.success) {
console.log(result.message);
console.log(`Installed to: ${result.plugin?.installedPath}`);
} else {
console.error(`Failed: ${result.message}`);
}
import type { PluginUpdateOptions } from '@ollama-code/ollama-code-core';
// Обновить конкретный плагин
const result = await marketplace.update('my-plugin', {
checkOnly: true, // Только проверить
});
// Обновить все плагины
const results = await marketplace.updateAll({
checkOnly: false,
dryRun: false,
});
for (const result of results) {
console.log(`${result.pluginId}: ${result.message}`);
}
const result = await marketplace.uninstall('my-plugin', {
global: true,
});
if (result.success) {
console.log('Plugin uninstalled successfully');
}
const installed = await marketplace.getInstalledPlugins();
for (const plugin of installed) {
console.log(`${plugin.name} v${plugin.installedVersion}`);
console.log(` Path: ${plugin.installedPath}`);
console.log(` Update Available: ${plugin.updateAvailable}`);
}
interface MarketplacePlugin {
/** Уникальный ID плагина */
id: string;
/** Имя пакета на npm */
packageName: string;
/** Отображаемое имя */
name: string;
/** Описание плагина */
description: string;
/** Версия */
version: string;
/** Информация об авторе */
author?: {
name: string;
email?: string;
url?: string;
};
/** Ключевые слова для поиска */
keywords: string[];
/** Количество загрузок */
downloads?: number;
/** GitHub звёзды */
stars?: number;
/** Лицензия */
license?: string;
/** URL репозитория */
repository?: string;
/** URL домашней страницы */
homepage?: string;
/** Путь установки */
installedPath?: string;
/** Установлен ли плагин */
installed: boolean;
/** Установленная версия */
installedVersion?: string;
/** Доступно ли обновление */
updateAvailable: boolean;
/** Манифест плагина (если установлен) */
manifest?: PluginManifest;
/** Уровень доверия */
trustLevel: 'verified' | 'community' | 'unverified';
/** Верифицирован ли плагин */
verified: boolean;
/** Дата последнего обновления */
updatedAt?: string;
/** Дата создания */
createdAt?: string;
}
interface MarketplaceSearchOptions {
/** Поисковый запрос */
query?: string;
/** Фильтр по ключевым словам */
keywords?: string[];
/** Фильтр по автору */
author?: string;
/** Фильтр по уровню доверия */
trustLevel?: ('verified' | 'community' | 'unverified')[];
/** Сортировка */
sortBy?: 'downloads' | 'stars' | 'updated' | 'name';
/** Порядок сортировки */
sortOrder?: 'asc' | 'desc';
/** Максимум результатов */
limit?: number;
/** Включить установленные плагины */
includeInstalled?: boolean;
}
interface PluginInstallOptions {
/** Конкретная версия для установки */
version?: string;
/** Глобальная установка (user-level) */
global?: boolean;
/** Принудительная переустановка */
force?: boolean;
/** Пропуск верификации */
skipVerification?: boolean;
/** Тестовый запуск */
dryRun?: boolean;
}
interface PluginUpdateOptions {
/** Обновить до конкретной версии */
version?: string;
/** Обновить все плагины */
all?: boolean;
/** Только проверить обновления */
checkOnly?: boolean;
/** Тестовый запуск */
dryRun?: boolean;
}
Плагины, прошедшие официальную верификацию командой Ollama Code:
Плагины от сообщества с хорошей репутацией:
Непроверенные плагины:
--skip-verification для установки~/.ollama-code/plugins/
├── node_modules/
│ └── ollama-code-plugin-my-plugin/
│ ├── package.json
│ ├── plugin.json
│ └── index.js
└── package.json
.ollama-code/plugins/
├── node_modules/
│ └── ollama-code-plugin-my-plugin/
│ ├── package.json
│ ├── plugin.json
│ └── index.js
└── package.json
ollama-code-plugin-my-plugin/
├── package.json # Метаданные пакета npm
├── plugin.json # Манифест плагина Ollama Code
├── index.js # Точка входа
├── README.md # Документация
└── LICENSE # Лицензия
{
"name": "ollama-code-plugin-my-plugin",
"version": "1.0.0",
"description": "My awesome Ollama Code plugin",
"main": "index.js",
"keywords": [
"ollama-code-plugin",
"ollama-code",
"ai",
"tools"
],
"author": {
"name": "Your Name",
"email": "you@example.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/user/ollama-code-plugin-my-plugin"
},
"homepage": "https://github.com/user/ollama-code-plugin-my-plugin#readme",
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"@ollama-code/ollama-code-core": ">=4.0.0"
}
}
{
"entry": "index.js",
"metadata": {
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "Provides custom tools for my workflow",
"author": "Your Name",
"tags": ["productivity", "automation"],
"enabledByDefault": false
}
}
/**
* @type {import('@ollama-code/ollama-code-core').PluginDefinition}
*/
module.exports = {
metadata: {
id: 'my-plugin',
name: 'My Plugin',
version: '1.0.0',
description: 'Provides custom tools for my workflow',
},
tools: [
{
id: 'my-tool',
name: 'my_custom_tool',
description: 'Performs a custom operation',
parameters: {
type: 'object',
properties: {
input: {
type: 'string',
description: 'Input to process',
},
},
required: ['input'],
},
category: 'other',
execute: async (params, context) => {
context.logger.info('Executing my custom tool');
return {
success: true,
data: `Processed: ${params.input}`,
display: {
title: 'Custom Tool Result',
summary: `Successfully processed input`,
},
};
},
},
],
hooks: {
onLoad: async (context) => {
context.logger.info('My plugin loaded!');
},
},
};
# Авторизоваться в npm
npm login
# Опубликовать пакет
npm publish
# Опубликовать scoped пакет (для организаций)
npm publish --access public
ollama-code-plugin- или быть scoped @scope/ollama-code-plugin-*ollama-code-pluginMarketplace поддерживает интеграцию с расширениями Claude через файл .claude-plugin/marketplace.json:
{
"name": "My Claude Extension",
"description": "Extension for Claude",
"version": "1.0.0",
"plugins": [
{
"name": "main-plugin",
"path": "./plugins/main"
}
]
}
# Формат owner/repo
plugin install anthropics/skills
# Полный URL
plugin install https://github.com/user/plugin-repo
# С указанием имени плагина (для multi-plugin репозиториев)
plugin install https://github.com/user/multi-plugins:specific-plugin
try {
const result = await marketplace.install('nonexistent-plugin');
if (!result.success) {
console.error(result.message);
// Plugin "nonexistent-plugin" not found in marketplace
}
} catch (error) {
console.error('Network error:', error.message);
}
При отсутствии сети Marketplace возвращает список установленных плагинов:
// При ошибке сети search() возвращает установленные плагины
const plugins = await marketplace.search({ query: 'git' });
// plugins будет содержать только установленные плагины
Marketplace кэширует результаты запросов на 5 минут:
// Первый запрос - обращение к npm registry
const plugin1 = await marketplace.getPlugin('my-plugin');
// Повторный запрос в течение 5 минут - из кэша
const plugin2 = await marketplace.getPlugin('my-plugin');
const plugin = await marketplace.getPlugin('unverified-plugin');
if (plugin.trustLevel === 'unverified') {
console.warn('This plugin is unverified!');
console.warn('Review the source code before installing:');
console.warn(plugin.repository);
}
// Установка с явным подтверждением
const result = await marketplace.install('unverified-plugin', {
skipVerification: true,
});
При отображении плагинов используются следующие индикаторы:
| Индикатор | Значение |
|---|---|
| 📦 | Плагин доступен для установки |
| 📦✓ | Плагин установлен (актуальная версия) |
| 📦⬆️ | Плагин установлен, доступно обновление |
| ✓ | Верифицированный плагин |
| ○ | Плагин от сообщества |
| ? | Непроверенный плагин |
import { createPluginMarketplace } from '@ollama-code/ollama-code-core';
async function ensurePluginsInstalled() {
const marketplace = createPluginMarketplace(process.cwd());
// Требуемые плагины
const required = ['git-tools', 'file-tools', 'search-tools'];
// Получаем установленные
const installed = await marketplace.getInstalledPlugins();
const installedIds = new Set(installed.map(p => p.id));
// Устанавливаем недостающие
for (const pluginId of required) {
if (!installedIds.has(pluginId)) {
console.log(`Installing ${pluginId}...`);
const result = await marketplace.install(pluginId);
console.log(result.message);
}
}
// Проверяем обновления
const updates = await marketplace.updateAll({ checkOnly: true });
for (const update of updates) {
console.log(`${update.pluginId}: ${update.message}`);
}
}
async function findPluginsByCategory(category: string) {
const marketplace = createPluginMarketplace();
const plugins = await marketplace.search({
keywords: [category],
sortBy: 'downloads',
limit: 20,
});
// Фильтруем только verified
const verified = plugins.filter(p => p.verified);
// Группируем по авторам
const byAuthor = verified.reduce((acc, p) => {
const author = p.author?.name || 'Unknown';
acc[author] = acc[author] || [];
acc[author].push(p);
return acc;
}, {} as Record<string, typeof plugins>);
return byAuthor;
}