@swarmify/agents-cli 1.5.16 → 1.5.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import { AGENTS, ALL_AGENT_IDS, MCP_CAPABLE_AGENTS, SKILLS_CAPABLE_AGENTS, HOOKS
20
20
  import { readManifest, writeManifest, createDefaultManifest, MANIFEST_FILENAME, } from './lib/manifest.js';
21
21
  import { readState, getRepoLocalPath, getScope, setScope, removeScope, getScopesByPriority, getScopePriority, } from './lib/state.js';
22
22
  import { SCOPE_PRIORITIES, DEFAULT_SYSTEM_REPO } from './lib/types.js';
23
- import { cloneRepo, parseSource } from './lib/git.js';
23
+ import { cloneRepo, parseSource, getGitHubUsername, getRemoteUrl, setRemoteUrl, checkGitHubRepoExists, commitAndPush, hasUncommittedChanges, } from './lib/git.js';
24
24
  import { discoverCommands, resolveCommandSource, installCommand, uninstallCommand, listInstalledCommandsWithScope, promoteCommandToUser, commandExists, commandContentMatches, } from './lib/commands.js';
25
25
  import { discoverHooksFromRepo, installHooks, listInstalledHooksWithScope, promoteHookToUser, removeHook, hookExists, hookContentMatches, getSourceHookEntry, } from './lib/hooks.js';
26
26
  import { discoverSkillsFromRepo, installSkill, uninstallSkill, listInstalledSkillsWithScope, promoteSkillToUser, getSkillInfo, getSkillRules, skillExists, skillContentMatches, } from './lib/skills.js';
@@ -1041,106 +1041,147 @@ program
1041
1041
  // =============================================================================
1042
1042
  program
1043
1043
  .command('push')
1044
- .description('Export local configuration to .agents repo for manual commit')
1044
+ .description('Push local configuration to your .agents repo on GitHub')
1045
1045
  .option('-s, --scope <scope>', 'Target scope (default: user)', 'user')
1046
- .option('--export-only', 'Only export, do not update manifest')
1046
+ .option('--export-only', 'Only export to local repo, do not push to GitHub')
1047
+ .option('-m, --message <msg>', 'Commit message', 'Update agent configuration')
1047
1048
  .action(async (options) => {
1048
- const scopeName = options.scope;
1049
- const scope = getScope(scopeName);
1050
- if (!scope) {
1051
- console.log(chalk.red(`Scope '${scopeName}' not configured.`));
1052
- const scopeHint = scopeName === 'user' ? '' : ` --scope ${scopeName}`;
1053
- console.log(chalk.gray(` Run: agents repo add <source>${scopeHint}`));
1054
- process.exit(1);
1055
- }
1056
- if (scope.readonly) {
1057
- console.log(chalk.red(`Scope '${scopeName}' is readonly. Cannot push.`));
1058
- process.exit(1);
1059
- }
1060
- const localPath = getRepoLocalPath(scope.source);
1061
- const manifest = readManifest(localPath) || createDefaultManifest();
1062
- console.log(chalk.bold('\nExporting local configuration...\n'));
1063
- const cliStates = await getAllCliStates();
1064
- let exported = 0;
1065
- for (const agentId of ALL_AGENT_IDS) {
1066
- const agent = AGENTS[agentId];
1067
- const cli = cliStates[agentId];
1068
- if (cli?.installed && cli.version) {
1069
- manifest.clis = manifest.clis || {};
1070
- manifest.clis[agentId] = {
1071
- package: agent.npmPackage,
1072
- version: cli.version,
1073
- };
1074
- console.log(` ${chalk.green('+')} ${agent.name} @ ${cli.version}`);
1075
- exported++;
1049
+ try {
1050
+ const scopeName = options.scope;
1051
+ const scope = getScope(scopeName);
1052
+ if (!scope) {
1053
+ console.log(chalk.red(`Scope '${scopeName}' not configured.`));
1054
+ console.log(chalk.gray(' Run: agents pull'));
1055
+ process.exit(1);
1076
1056
  }
1077
- }
1078
- // Export MCP servers from installed agents
1079
- console.log();
1080
- let mcpExported = 0;
1081
- const mcpByName = new Map();
1082
- for (const agentId of MCP_CAPABLE_AGENTS) {
1083
- if (!cliStates[agentId]?.installed)
1084
- continue;
1085
- const mcps = listInstalledMcpsWithScope(agentId);
1086
- for (const mcp of mcps) {
1087
- if (mcp.scope !== 'user')
1088
- continue; // Only export user-scoped MCPs
1089
- const existing = mcpByName.get(mcp.name);
1090
- if (existing) {
1091
- if (!existing.agents.includes(agentId)) {
1092
- existing.agents.push(agentId);
1057
+ if (scope.readonly) {
1058
+ console.log(chalk.red(`Scope '${scopeName}' is readonly. Cannot push.`));
1059
+ process.exit(1);
1060
+ }
1061
+ const localPath = getRepoLocalPath(scope.source);
1062
+ const manifest = readManifest(localPath) || createDefaultManifest();
1063
+ console.log(chalk.bold('\nExporting local configuration...\n'));
1064
+ const cliStates = await getAllCliStates();
1065
+ let exported = 0;
1066
+ for (const agentId of ALL_AGENT_IDS) {
1067
+ const agent = AGENTS[agentId];
1068
+ const cli = cliStates[agentId];
1069
+ if (cli?.installed && cli.version) {
1070
+ manifest.clis = manifest.clis || {};
1071
+ manifest.clis[agentId] = {
1072
+ package: agent.npmPackage,
1073
+ version: cli.version,
1074
+ };
1075
+ console.log(` ${chalk.green('+')} ${agent.name} @ ${cli.version}`);
1076
+ exported++;
1077
+ }
1078
+ }
1079
+ // Export MCP servers from installed agents
1080
+ console.log();
1081
+ let mcpExported = 0;
1082
+ const mcpByName = new Map();
1083
+ for (const agentId of MCP_CAPABLE_AGENTS) {
1084
+ if (!cliStates[agentId]?.installed)
1085
+ continue;
1086
+ const mcps = listInstalledMcpsWithScope(agentId);
1087
+ for (const mcp of mcps) {
1088
+ if (mcp.scope !== 'user')
1089
+ continue; // Only export user-scoped MCPs
1090
+ const existing = mcpByName.get(mcp.name);
1091
+ if (existing) {
1092
+ if (!existing.agents.includes(agentId)) {
1093
+ existing.agents.push(agentId);
1094
+ }
1095
+ }
1096
+ else {
1097
+ mcpByName.set(mcp.name, {
1098
+ command: mcp.command || '',
1099
+ agents: [agentId],
1100
+ });
1093
1101
  }
1094
- }
1095
- else {
1096
- mcpByName.set(mcp.name, {
1097
- command: mcp.command || '',
1098
- agents: [agentId],
1099
- });
1100
1102
  }
1101
1103
  }
1102
- }
1103
- if (mcpByName.size > 0) {
1104
- manifest.mcp = manifest.mcp || {};
1105
- for (const [name, config] of mcpByName) {
1106
- manifest.mcp[name] = {
1107
- command: config.command,
1108
- transport: 'stdio',
1109
- agents: config.agents,
1110
- scope: 'user',
1111
- };
1112
- console.log(` ${chalk.green('+')} MCP: ${name} (${config.agents.map(id => AGENTS[id].name).join(', ')})`);
1113
- mcpExported++;
1104
+ if (mcpByName.size > 0) {
1105
+ manifest.mcp = manifest.mcp || {};
1106
+ for (const [name, config] of mcpByName) {
1107
+ manifest.mcp[name] = {
1108
+ command: config.command,
1109
+ transport: 'stdio',
1110
+ agents: config.agents,
1111
+ scope: 'user',
1112
+ };
1113
+ console.log(` ${chalk.green('+')} MCP: ${name} (${config.agents.map((id) => AGENTS[id].name).join(', ')})`);
1114
+ mcpExported++;
1115
+ }
1114
1116
  }
1115
- }
1116
- if (!options.exportOnly) {
1117
1117
  writeManifest(localPath, manifest);
1118
1118
  console.log(chalk.bold(`\nUpdated ${MANIFEST_FILENAME}`));
1119
+ if (options.exportOnly) {
1120
+ console.log(chalk.bold('\nExport complete. Changes saved locally.'));
1121
+ console.log(chalk.gray(` Path: ${localPath}`));
1122
+ return;
1123
+ }
1124
+ // Check if there are changes to push
1125
+ const hasChanges = await hasUncommittedChanges(localPath);
1126
+ if (!hasChanges) {
1127
+ console.log(chalk.green('\nNo changes to push.'));
1128
+ return;
1129
+ }
1130
+ // Get GitHub username
1131
+ const spinner = ora('Checking GitHub authentication...').start();
1132
+ const username = await getGitHubUsername();
1133
+ if (!username) {
1134
+ spinner.fail('GitHub CLI not authenticated');
1135
+ console.log(chalk.yellow('\nTo push changes, authenticate with GitHub:'));
1136
+ console.log(chalk.gray(' gh auth login'));
1137
+ console.log(chalk.gray('\nOr push manually:'));
1138
+ console.log(chalk.gray(` cd ${localPath}`));
1139
+ console.log(chalk.gray(' git add -A && git commit -m "Update" && git push'));
1140
+ return;
1141
+ }
1142
+ spinner.text = 'Checking remote configuration...';
1143
+ // Check if remote is set to user's repo
1144
+ const currentRemote = await getRemoteUrl(localPath);
1145
+ const userRepoUrl = `https://github.com/${username}/.agents.git`;
1146
+ const isUserRepo = currentRemote?.includes(`${username}/.agents`);
1147
+ if (!isUserRepo) {
1148
+ // Check if user's repo exists on GitHub
1149
+ spinner.text = `Checking if ${username}/.agents exists...`;
1150
+ const repoExists = await checkGitHubRepoExists(username, '.agents');
1151
+ if (!repoExists) {
1152
+ spinner.fail(`Repository ${username}/.agents does not exist`);
1153
+ console.log(chalk.yellow('\nCreate your .agents repo on GitHub:'));
1154
+ console.log(chalk.cyan(` gh repo create .agents --public --description "My agent configurations"`));
1155
+ console.log(chalk.gray('\nThen run: agents push'));
1156
+ return;
1157
+ }
1158
+ // Update remote to user's repo
1159
+ spinner.text = `Switching remote to ${username}/.agents...`;
1160
+ await setRemoteUrl(localPath, userRepoUrl);
1161
+ }
1162
+ // Commit and push
1163
+ spinner.text = 'Pushing changes...';
1164
+ const result = await commitAndPush(localPath, options.message);
1165
+ if (result.success) {
1166
+ spinner.succeed(`Pushed to ${username}/.agents`);
1167
+ console.log(chalk.green(`\nView: https://github.com/${username}/.agents`));
1168
+ }
1169
+ else {
1170
+ spinner.fail('Failed to push');
1171
+ console.log(chalk.red(result.error || 'Unknown error'));
1172
+ if (result.error?.includes('rejected')) {
1173
+ console.log(chalk.yellow('\nTry pulling first: agents pull'));
1174
+ }
1175
+ }
1176
+ }
1177
+ catch (err) {
1178
+ if (isPromptCancelled(err)) {
1179
+ console.log(chalk.yellow('\nCancelled'));
1180
+ process.exit(0);
1181
+ }
1182
+ console.error(chalk.red(err.message));
1183
+ process.exit(1);
1119
1184
  }
1120
- console.log(chalk.bold('\nNext steps:'));
1121
- console.log(chalk.gray(` cd ${localPath}`));
1122
- console.log(chalk.gray(' git add -A'));
1123
- console.log(chalk.gray(' git commit -m "Update agent configuration"'));
1124
- console.log(chalk.gray(' git push'));
1125
- console.log();
1126
- });
1127
- // =============================================================================
1128
- // SYNC COMMAND
1129
- // =============================================================================
1130
- program
1131
- .command('sync [source]')
1132
- .description('Bidirectional sync with remote .agents repo')
1133
- .option('-y, --yes', 'Skip interactive prompts')
1134
- .option('-f, --force', 'Overwrite local changes')
1135
- .action(async (source, options) => {
1136
- const args = ['pull'];
1137
- if (source)
1138
- args.push(source);
1139
- if (options.yes)
1140
- args.push('-y');
1141
- if (options.force)
1142
- args.push('-f');
1143
- await program.commands.find((c) => c.name() === 'pull')?.parseAsync(args, { from: 'user' });
1144
1185
  });
1145
1186
  // =============================================================================
1146
1187
  // COMMANDS COMMANDS
@@ -2448,37 +2489,6 @@ repoCmd
2448
2489
  console.log(chalk.yellow(`Failed to remove scope '${scopeName}'`));
2449
2490
  }
2450
2491
  });
2451
- repoCmd
2452
- .command('sync [scope]')
2453
- .description('Sync a specific scope or all scopes')
2454
- .option('-y, --yes', 'Skip confirmation prompts')
2455
- .action(async (scopeName, options) => {
2456
- const scopes = scopeName ? [{ name: scopeName, config: getScope(scopeName) }].filter(s => s.config) : getScopesByPriority();
2457
- if (scopes.length === 0) {
2458
- console.log(chalk.yellow('No scopes to sync.'));
2459
- return;
2460
- }
2461
- for (const { name, config } of scopes) {
2462
- if (!config)
2463
- continue;
2464
- console.log(chalk.bold(`\nSyncing scope: ${name}`));
2465
- const spinner = ora('Updating repository...').start();
2466
- try {
2467
- const { commit } = await cloneRepo(config.source);
2468
- spinner.succeed('Repository updated');
2469
- setScope(name, {
2470
- ...config,
2471
- commit,
2472
- lastSync: new Date().toISOString(),
2473
- });
2474
- }
2475
- catch (err) {
2476
- spinner.fail(`Failed to sync ${name}`);
2477
- console.error(chalk.gray(err.message));
2478
- }
2479
- }
2480
- console.log(chalk.green('\nSync complete.'));
2481
- });
2482
2492
  // =============================================================================
2483
2493
  // REGISTRY COMMANDS
2484
2494
  // =============================================================================