@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 +132 -122
- package/dist/index.js.map +1 -1
- package/dist/lib/git.d.ts +28 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +95 -0
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/shims.d.ts.map +1 -1
- package/dist/lib/shims.js +7 -0
- package/dist/lib/shims.js.map +1 -1
- package/dist/lib/state.d.ts.map +1 -1
- package/dist/lib/state.js +5 -1
- package/dist/lib/state.js.map +1 -1
- package/package.json +1 -1
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('
|
|
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
|
|
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
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
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
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
for (const
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
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
|
// =============================================================================
|