Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 126 additions & 7 deletions src/cli/commands/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
listMarketplacePlugins,
getWellKnownMarketplaces,
} from '../../core/marketplace.js';
import { isJsonMode, jsonOutput } from '../json-output.js';

// =============================================================================
// plugin marketplace list
Expand All @@ -20,6 +21,15 @@ const marketplaceListCmd = command({
try {
const marketplaces = await listMarketplaces();

if (isJsonMode()) {
jsonOutput({
success: true,
command: 'plugin marketplace list',
data: { marketplaces },
});
return;
}

if (marketplaces.length === 0) {
console.log('No marketplaces registered.\n');
console.log('Add a marketplace with:');
Expand Down Expand Up @@ -53,6 +63,10 @@ const marketplaceListCmd = command({
console.log(`Total: ${marketplaces.length} marketplace(s)`);
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace list', error: error.message });
process.exit(1);
}
console.error(`Error: ${error.message}`);
process.exit(1);
}
Expand All @@ -74,19 +88,43 @@ const marketplaceAddCmd = command({
},
handler: async ({ source, name }) => {
try {
console.log(`Adding marketplace: ${source}...`);
if (!isJsonMode()) {
console.log(`Adding marketplace: ${source}...`);
}

const result = await addMarketplace(source, name);

if (!result.success) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace add', error: result.error ?? 'Unknown error' });
process.exit(1);
}
console.error(`\nError: ${result.error}`);
process.exit(1);
}

if (isJsonMode()) {
jsonOutput({
success: true,
command: 'plugin marketplace add',
data: {
marketplace: {
name: result.marketplace?.name,
path: result.marketplace?.path,
},
},
});
return;
}

console.log(`\u2713 Marketplace '${result.marketplace?.name}' added`);
console.log(` Path: ${result.marketplace?.path}`);
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace add', error: error.message });
process.exit(1);
}
console.error(`Error: ${error.message}`);
process.exit(1);
}
Expand All @@ -110,14 +148,34 @@ const marketplaceRemoveCmd = command({
const result = await removeMarketplace(name);

if (!result.success) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace remove', error: result.error ?? 'Unknown error' });
process.exit(1);
}
console.error(`Error: ${result.error}`);
process.exit(1);
}

if (isJsonMode()) {
jsonOutput({
success: true,
command: 'plugin marketplace remove',
data: {
name,
path: result.marketplace?.path,
},
});
return;
}

console.log(`\u2713 Marketplace '${name}' removed from registry`);
console.log(` Note: Files at ${result.marketplace?.path} were not deleted`);
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace remove', error: error.message });
process.exit(1);
}
console.error(`Error: ${error.message}`);
process.exit(1);
}
Expand All @@ -138,15 +196,32 @@ const marketplaceUpdateCmd = command({
},
handler: async ({ name }) => {
try {
console.log(
name
? `Updating marketplace: ${name}...`
: 'Updating all marketplaces...',
);
console.log();
if (!isJsonMode()) {
console.log(
name
? `Updating marketplace: ${name}...`
: 'Updating all marketplaces...',
);
console.log();
}

const results = await updateMarketplace(name);

if (isJsonMode()) {
const succeeded = results.filter((r) => r.success).length;
const failed = results.filter((r) => !r.success).length;
jsonOutput({
success: failed === 0,
command: 'plugin marketplace update',
data: { results, succeeded, failed },
...(failed > 0 && { error: `${failed} marketplace(s) failed to update` }),
});
if (failed > 0) {
process.exit(1);
}
return;
}

if (results.length === 0) {
console.log('No marketplaces to update.');
return;
Expand All @@ -173,6 +248,10 @@ const marketplaceUpdateCmd = command({
}
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin marketplace update', error: error.message });
process.exit(1);
}
console.error(`Error: ${error.message}`);
process.exit(1);
}
Expand Down Expand Up @@ -211,6 +290,14 @@ const pluginListCmd = command({
const marketplaces = await listMarketplaces();

if (marketplaces.length === 0) {
if (isJsonMode()) {
jsonOutput({
success: true,
command: 'plugin list',
data: { plugins: [], total: 0 },
});
return;
}
console.log('No marketplaces registered.\n');
console.log('Add a marketplace first:');
console.log(' allagents plugin marketplace add <source>');
Expand All @@ -223,10 +310,30 @@ const pluginListCmd = command({
: marketplaces;

if (marketplace && toList.length === 0) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin list', error: `Marketplace '${marketplace}' not found` });
process.exit(1);
}
console.error(`Marketplace '${marketplace}' not found`);
process.exit(1);
}

if (isJsonMode()) {
const allPlugins: Array<{ name: string; marketplace: string }> = [];
for (const mp of toList) {
const plugins = await listMarketplacePlugins(mp.name);
for (const plugin of plugins) {
allPlugins.push({ name: plugin.name, marketplace: mp.name });
}
}
jsonOutput({
success: true,
command: 'plugin list',
data: { plugins: allPlugins, total: allPlugins.length },
});
return;
}

let totalPlugins = 0;

for (const mp of toList) {
Expand All @@ -252,6 +359,10 @@ const pluginListCmd = command({
}
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'plugin list', error: error.message });
process.exit(1);
}
console.error(`Error: ${error.message}`);
process.exit(1);
}
Expand All @@ -271,6 +382,14 @@ const pluginValidateCmd = command({
path: positional({ type: string, displayName: 'path' }),
},
handler: async ({ path }) => {
if (isJsonMode()) {
jsonOutput({
success: true,
command: 'plugin validate',
data: { path, valid: false, message: 'not yet implemented' },
});
return;
}
// TODO: Implement plugin validation
console.log(`Validating plugin at: ${path}`);
console.log('(validation not yet implemented)');
Expand Down
56 changes: 50 additions & 6 deletions src/cli/commands/self.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { execa } from 'execa';
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { isJsonMode, jsonOutput } from '../json-output.js';

/**
* Detect package manager from a script path
Expand Down Expand Up @@ -54,6 +55,10 @@ const updateCmd = command({
let packageManager: 'bun' | 'npm';

if (npm && bun) {
if (isJsonMode()) {
jsonOutput({ success: false, command: 'self update', error: 'Cannot specify both --npm and --bun' });
process.exit(1);
}
console.error('Error: Cannot specify both --npm and --bun');
process.exit(1);
}
Expand All @@ -67,33 +72,72 @@ const updateCmd = command({
}

const currentVersion = getCurrentVersion();
console.log(`Current version: ${currentVersion}`);
console.log(`Updating allagents using ${packageManager}...\n`);

if (!isJsonMode()) {
console.log(`Current version: ${currentVersion}`);
console.log(`Updating allagents using ${packageManager}...\n`);
}

// Build the update command
const args =
packageManager === 'npm'
? ['install', '-g', 'allagents@latest']
: ['add', '-g', 'allagents@latest'];

// Execute the update
// In JSON mode, capture output instead of inheriting stdio
const result = await execa(packageManager, args, {
stdio: 'inherit',
stdio: isJsonMode() ? 'pipe' : 'inherit',
});

if (result.exitCode === 0) {
// Get the new version by spawning allagents --version
let newVersion: string | undefined;
try {
const versionResult = await execa('allagents', ['--version']);
const newVersion = versionResult.stdout.trim();
console.log(`\nUpdate complete: ${currentVersion} \u2192 ${newVersion}`);
newVersion = versionResult.stdout.trim();
} catch {
// Fallback if we can't get new version
}

if (isJsonMode()) {
jsonOutput({
success: true,
command: 'self update',
data: {
previousVersion: currentVersion,
newVersion: newVersion ?? 'unknown',
packageManager,
},
});
return;
}

if (newVersion) {
console.log(`\nUpdate complete: ${currentVersion} \u2192 ${newVersion}`);
} else {
console.log('\nUpdate complete.');
}
}
} catch (error) {
if (error instanceof Error) {
if (isJsonMode()) {
// Check if package manager is not available
if (
error.message.includes('ENOENT') ||
error.message.includes('not found')
) {
const detected = detectPackageManager();
const alternative = detected === 'npm' ? 'bun' : 'npm';
jsonOutput({
success: false,
command: 'self update',
error: `${detected} not found. Try using --${alternative} flag.`,
});
} else {
jsonOutput({ success: false, command: 'self update', error: error.message });
}
process.exit(1);
}
// Check if package manager is not available
if (
error.message.includes('ENOENT') ||
Expand Down
Loading