agent-switchboard 0.2.3 → 0.3.1
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/README.md +29 -28
- package/dist/agents/registry.d.ts +0 -6
- package/dist/agents/registry.js +0 -13
- package/dist/agents/registry.js.map +1 -1
- package/dist/commands/distribution.d.ts +3 -4
- package/dist/commands/distribution.js +18 -116
- package/dist/commands/distribution.js.map +1 -1
- package/dist/config/application-config.d.ts +1 -1
- package/dist/config/application-config.js +2 -10
- package/dist/config/application-config.js.map +1 -1
- package/dist/config/mcp-config.js +1 -3
- package/dist/config/mcp-config.js.map +1 -1
- package/dist/config/paths.d.ts +11 -7
- package/dist/config/paths.js +29 -9
- package/dist/config/paths.js.map +1 -1
- package/dist/config/schemas.d.ts +331 -43
- package/dist/config/schemas.js +109 -15
- package/dist/config/schemas.js.map +1 -1
- package/dist/config/switchboard-config.js +0 -1
- package/dist/config/switchboard-config.js.map +1 -1
- package/dist/extensions/api.d.ts +49 -0
- package/dist/extensions/api.js +41 -0
- package/dist/extensions/api.js.map +1 -0
- package/dist/extensions/loader.d.ts +17 -0
- package/dist/extensions/loader.js +73 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/hooks/distribution.js +1 -16
- package/dist/hooks/distribution.js.map +1 -1
- package/dist/index.js +77 -123
- package/dist/index.js.map +1 -1
- package/dist/library/distribute-bundle.js +1 -19
- package/dist/library/distribute-bundle.js.map +1 -1
- package/dist/library/fs.d.ts +12 -0
- package/dist/library/fs.js +81 -0
- package/dist/library/fs.js.map +1 -1
- package/dist/library/sources.d.ts +6 -1
- package/dist/library/sources.js +73 -16
- package/dist/library/sources.js.map +1 -1
- package/dist/rules/agents.d.ts +0 -4
- package/dist/rules/agents.js +0 -10
- package/dist/rules/agents.js.map +1 -1
- package/dist/rules/distribution.d.ts +1 -2
- package/dist/rules/distribution.js +20 -79
- package/dist/rules/distribution.js.map +1 -1
- package/dist/skills/distribution.d.ts +0 -22
- package/dist/skills/distribution.js +70 -185
- package/dist/skills/distribution.js.map +1 -1
- package/dist/skills/importer.js +2 -33
- package/dist/skills/importer.js.map +1 -1
- package/dist/subagents/codex-distribute.d.ts +13 -0
- package/dist/subagents/codex-distribute.js +273 -0
- package/dist/subagents/codex-distribute.js.map +1 -0
- package/dist/subagents/distribution.d.ts +3 -4
- package/dist/subagents/distribution.js +30 -410
- package/dist/subagents/distribution.js.map +1 -1
- package/dist/targets/builtin/claude-code.d.ts +2 -0
- package/dist/targets/builtin/claude-code.js +73 -0
- package/dist/targets/builtin/claude-code.js.map +1 -0
- package/dist/targets/builtin/claude-desktop.d.ts +2 -0
- package/dist/targets/builtin/claude-desktop.js +14 -0
- package/dist/targets/builtin/claude-desktop.js.map +1 -0
- package/dist/targets/builtin/codex.d.ts +3 -0
- package/dist/targets/builtin/codex.js +57 -0
- package/dist/targets/builtin/codex.js.map +1 -0
- package/dist/targets/builtin/common.d.ts +22 -0
- package/dist/targets/builtin/common.js +55 -0
- package/dist/targets/builtin/common.js.map +1 -0
- package/dist/targets/builtin/cursor.d.ts +2 -0
- package/dist/targets/builtin/cursor.js +95 -0
- package/dist/targets/builtin/cursor.js.map +1 -0
- package/dist/targets/builtin/gemini.d.ts +2 -0
- package/dist/targets/builtin/gemini.js +62 -0
- package/dist/targets/builtin/gemini.js.map +1 -0
- package/dist/targets/builtin/index.d.ts +10 -0
- package/dist/targets/builtin/index.js +19 -0
- package/dist/targets/builtin/index.js.map +1 -0
- package/dist/targets/builtin/opencode.d.ts +2 -0
- package/dist/targets/builtin/opencode.js +67 -0
- package/dist/targets/builtin/opencode.js.map +1 -0
- package/dist/targets/builtin/trae.d.ts +3 -0
- package/dist/targets/builtin/trae.js +56 -0
- package/dist/targets/builtin/trae.js.map +1 -0
- package/dist/targets/dsl/compiler.d.ts +13 -0
- package/dist/targets/dsl/compiler.js +215 -0
- package/dist/targets/dsl/compiler.js.map +1 -0
- package/dist/targets/dsl/index.d.ts +2 -0
- package/dist/targets/dsl/index.js +3 -0
- package/dist/targets/dsl/index.js.map +1 -0
- package/dist/targets/dsl/transforms.d.ts +77 -0
- package/dist/targets/dsl/transforms.js +159 -0
- package/dist/targets/dsl/transforms.js.map +1 -0
- package/dist/targets/init.d.ts +14 -0
- package/dist/targets/init.js +28 -0
- package/dist/targets/init.js.map +1 -0
- package/dist/targets/registry.d.ts +38 -0
- package/dist/targets/registry.js +101 -0
- package/dist/targets/registry.js.map +1 -0
- package/dist/targets/types.d.ts +93 -0
- package/dist/targets/types.js +28 -0
- package/dist/targets/types.js.map +1 -0
- package/dist/ui/plugin-ui.d.ts +1 -1
- package/dist/ui/plugin-ui.js +5 -12
- package/dist/ui/plugin-ui.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import { confirm } from '@inquirer/prompts';
|
|
|
10
10
|
import chalk from 'chalk';
|
|
11
11
|
import { Command } from 'commander';
|
|
12
12
|
import ora from 'ora';
|
|
13
|
-
import { getAgentById } from './agents/registry.js';
|
|
14
13
|
import { distributeCommands } from './commands/distribution.js';
|
|
15
14
|
import { importCommandFromFile } from './commands/importer.js';
|
|
16
15
|
import { buildCommandInventory } from './commands/inventory.js';
|
|
@@ -21,12 +20,11 @@ import { getAgentsDir, getAgentsHome, getClaudeDir, getCodexDir, getCommandsDir,
|
|
|
21
20
|
import { loadSwitchboardConfig, loadSwitchboardConfigWithLayers, } from './config/switchboard-config.js';
|
|
22
21
|
import { distributeHooks } from './hooks/distribution.js';
|
|
23
22
|
import { loadHookLibrary } from './hooks/library.js';
|
|
24
|
-
import { ensureLibraryDirectories, writeFileSecure } from './library/fs.js';
|
|
23
|
+
import { copyDirRecursive, ensureLibraryDirectories, isDir, isFile, listFilesRecursively, writeFileSecure, } from './library/fs.js';
|
|
25
24
|
import { addLocalSource, addRemoteSource, getSources, inferSourceName, isGitUrl, parseGitUrl, removeSource, updateRemoteSources, validateSourcePath, } from './library/sources.js';
|
|
26
25
|
import { loadLibraryStateSection, loadMcpEnabledState, saveMcpEnabledState, } from './library/state.js';
|
|
27
26
|
import { readMarketplace } from './marketplace/reader.js';
|
|
28
27
|
import { buildPluginIndex } from './plugins/index.js';
|
|
29
|
-
import { RULE_SUPPORTED_AGENTS } from './rules/agents.js';
|
|
30
28
|
import { composeActiveRules } from './rules/composer.js';
|
|
31
29
|
import { distributeRules, listIndirectAgents, listPerFileAgents, listUnsupportedAgents, } from './rules/distribution.js';
|
|
32
30
|
import { buildRuleInventory } from './rules/inventory.js';
|
|
@@ -38,6 +36,8 @@ import { buildSkillInventory } from './skills/inventory.js';
|
|
|
38
36
|
import { distributeSubagents } from './subagents/distribution.js';
|
|
39
37
|
import { importSubagentFromFile } from './subagents/importer.js';
|
|
40
38
|
import { buildSubagentInventory } from './subagents/inventory.js';
|
|
39
|
+
import { initTargets } from './targets/init.js';
|
|
40
|
+
import { filterInstalled, getTargetById, getTargetsForSection } from './targets/registry.js';
|
|
41
41
|
import { showCommandSelector } from './ui/command-ui.js';
|
|
42
42
|
import { showHookSelector } from './ui/hook-ui.js';
|
|
43
43
|
import { showMcpServerUI } from './ui/mcp-ui.js';
|
|
@@ -75,6 +75,7 @@ program
|
|
|
75
75
|
const scope = resolveScope(options);
|
|
76
76
|
const loadOptions = scopeToLoadOptions(scope);
|
|
77
77
|
const { config, layers } = loadSwitchboardConfigWithLayers(loadOptions);
|
|
78
|
+
await initTargets(config);
|
|
78
79
|
console.log(chalk.yellow('⚠ Sync overwrites agent config without diff.'));
|
|
79
80
|
console.log();
|
|
80
81
|
if (options.update !== false) {
|
|
@@ -101,7 +102,14 @@ program
|
|
|
101
102
|
activeLayers.push(shortenPath(layers.project.path));
|
|
102
103
|
console.log(`${chalk.blue('Config:')} ${activeLayers.length > 0 ? chalk.dim(activeLayers.join(' + ')) : chalk.gray('no config files')}`);
|
|
103
104
|
const appsLabel = config.applications.active.length > 0
|
|
104
|
-
?
|
|
105
|
+
? config.applications.active
|
|
106
|
+
.map((id) => {
|
|
107
|
+
const t = getTargetById(id);
|
|
108
|
+
if (t?.isInstalled?.() === false)
|
|
109
|
+
return chalk.gray(`${id} (not installed)`);
|
|
110
|
+
return chalk.cyan(id);
|
|
111
|
+
})
|
|
112
|
+
.join(', ')
|
|
105
113
|
: chalk.gray('none configured');
|
|
106
114
|
console.log(`${chalk.blue('Apps:')} ${appsLabel}`);
|
|
107
115
|
console.log();
|
|
@@ -110,26 +118,14 @@ program
|
|
|
110
118
|
console.log(chalk.blue('Inventory:'));
|
|
111
119
|
{
|
|
112
120
|
const sections = ['mcp', 'rules', 'commands', 'agents', 'skills', 'hooks'];
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
'opencode',
|
|
122
|
-
'trae',
|
|
123
|
-
'trae-cn',
|
|
124
|
-
],
|
|
125
|
-
rules: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode', 'trae', 'trae-cn'],
|
|
126
|
-
commands: ['claude-code', 'codex', 'cursor', 'gemini', 'opencode'],
|
|
127
|
-
agents: ['claude-code', 'opencode', 'cursor'],
|
|
128
|
-
skills: cursorSkillsDeduped
|
|
129
|
-
? ['claude-code', 'codex', 'gemini', 'opencode', 'trae', 'trae-cn']
|
|
130
|
-
: ['claude-code', 'codex', 'gemini', 'opencode', 'cursor', 'trae', 'trae-cn'],
|
|
131
|
-
hooks: ['claude-code'],
|
|
132
|
-
};
|
|
121
|
+
const sectionPlatforms = {};
|
|
122
|
+
for (const s of sections) {
|
|
123
|
+
let ids = filterInstalled(getTargetsForSection(s)).map((t) => t.id);
|
|
124
|
+
if (s === 'skills' && cursorSkillsDeduped) {
|
|
125
|
+
ids = ids.filter((id) => id !== 'cursor');
|
|
126
|
+
}
|
|
127
|
+
sectionPlatforms[s] = ids;
|
|
128
|
+
}
|
|
133
129
|
const termWidth = process.stdout.columns || 80;
|
|
134
130
|
const maxSectionLen = Math.max(...sections.map((s) => s.length));
|
|
135
131
|
const maxCountLen = Math.max(...sections.map((s) => `(${config[s].enabled.length})`.length));
|
|
@@ -194,9 +190,7 @@ program
|
|
|
194
190
|
// Show enabled plugins summary
|
|
195
191
|
{
|
|
196
192
|
const pluginIndex = buildPluginIndex();
|
|
197
|
-
const enabledPluginRefs =
|
|
198
|
-
.filter(([, v]) => v === true)
|
|
199
|
-
.map(([k]) => k);
|
|
193
|
+
const enabledPluginRefs = config.plugins.enabled;
|
|
200
194
|
if (enabledPluginRefs.length > 0) {
|
|
201
195
|
const names = enabledPluginRefs
|
|
202
196
|
.map((pid) => {
|
|
@@ -295,22 +289,6 @@ program
|
|
|
295
289
|
process.exit(1);
|
|
296
290
|
}
|
|
297
291
|
});
|
|
298
|
-
function isDir(p) {
|
|
299
|
-
try {
|
|
300
|
-
return fs.existsSync(p) && fs.statSync(p).isDirectory();
|
|
301
|
-
}
|
|
302
|
-
catch {
|
|
303
|
-
return false;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
function isFile(p) {
|
|
307
|
-
try {
|
|
308
|
-
return fs.existsSync(p) && fs.statSync(p).isFile();
|
|
309
|
-
}
|
|
310
|
-
catch {
|
|
311
|
-
return false;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
292
|
function resolveScope(input) {
|
|
315
293
|
if (!input)
|
|
316
294
|
return undefined;
|
|
@@ -377,26 +355,6 @@ function defaultSkillSourceDir(platform) {
|
|
|
377
355
|
return path.join(getCursorDir(), 'skills');
|
|
378
356
|
}
|
|
379
357
|
}
|
|
380
|
-
function listFilesRecursively(root, filterExts) {
|
|
381
|
-
const out = [];
|
|
382
|
-
const exts = new Set(filterExts.map((e) => e.toLowerCase()));
|
|
383
|
-
const walk = (dir) => {
|
|
384
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
385
|
-
for (const entry of entries) {
|
|
386
|
-
const abs = path.join(dir, entry.name);
|
|
387
|
-
if (entry.isDirectory()) {
|
|
388
|
-
walk(abs);
|
|
389
|
-
}
|
|
390
|
-
else if (entry.isFile()) {
|
|
391
|
-
const ext = path.extname(entry.name).toLowerCase();
|
|
392
|
-
if (exts.has(ext))
|
|
393
|
-
out.push(abs);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
walk(root);
|
|
398
|
-
return out;
|
|
399
|
-
}
|
|
400
358
|
async function confirmOverwrite(filePath, force) {
|
|
401
359
|
if (!fs.existsSync(filePath))
|
|
402
360
|
return true;
|
|
@@ -404,29 +362,6 @@ async function confirmOverwrite(filePath, force) {
|
|
|
404
362
|
return true;
|
|
405
363
|
return await confirm({ message: `File exists: ${filePath}. Overwrite?`, default: false });
|
|
406
364
|
}
|
|
407
|
-
function copyDirRecursive(src, dest) {
|
|
408
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
409
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
410
|
-
for (const entry of entries) {
|
|
411
|
-
const srcPath = path.join(src, entry.name);
|
|
412
|
-
const destPath = path.join(dest, entry.name);
|
|
413
|
-
if (entry.isDirectory()) {
|
|
414
|
-
copyDirRecursive(srcPath, destPath);
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
fs.copyFileSync(srcPath, destPath);
|
|
418
|
-
// Preserve executable permissions
|
|
419
|
-
try {
|
|
420
|
-
const mode = fs.statSync(srcPath).mode;
|
|
421
|
-
if (mode & 0o111)
|
|
422
|
-
fs.chmodSync(destPath, mode & 0o777);
|
|
423
|
-
}
|
|
424
|
-
catch {
|
|
425
|
-
// Ignore
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
365
|
/**
|
|
431
366
|
* Extract hooks from Claude Code's ~/.claude/settings.json and import as a
|
|
432
367
|
* bundle into ~/.asb/hooks/. Copies referenced script files if they exist
|
|
@@ -662,7 +597,7 @@ ruleCommand
|
|
|
662
597
|
console.log();
|
|
663
598
|
printAgentSyncStatus({
|
|
664
599
|
agentSync: inventory.state.agentSync,
|
|
665
|
-
agents:
|
|
600
|
+
agents: getTargetsForSection('rules').map((t) => t.id),
|
|
666
601
|
});
|
|
667
602
|
const unsupportedAgents = listUnsupportedAgents();
|
|
668
603
|
if (unsupportedAgents.length > 0) {
|
|
@@ -689,6 +624,7 @@ ruleCommand.action(async (options) => {
|
|
|
689
624
|
try {
|
|
690
625
|
const scope = resolveScope(options);
|
|
691
626
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
627
|
+
await initTargets(config);
|
|
692
628
|
const selection = await showRuleSelector({ scope, pageSize: config.ui.page_size });
|
|
693
629
|
if (!selection) {
|
|
694
630
|
return;
|
|
@@ -777,6 +713,7 @@ commandRoot.action(async (options) => {
|
|
|
777
713
|
try {
|
|
778
714
|
const scope = resolveScope(options);
|
|
779
715
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
716
|
+
await initTargets(config);
|
|
780
717
|
const selection = await showCommandSelector({ scope, pageSize: config.ui.page_size });
|
|
781
718
|
if (!selection)
|
|
782
719
|
return;
|
|
@@ -926,6 +863,7 @@ agentRoot.action(async (options) => {
|
|
|
926
863
|
try {
|
|
927
864
|
const scope = resolveScope(options);
|
|
928
865
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
866
|
+
await initTargets(config);
|
|
929
867
|
const selection = await showSubagentSelector({ scope, pageSize: config.ui.page_size });
|
|
930
868
|
if (!selection)
|
|
931
869
|
return;
|
|
@@ -1073,6 +1011,7 @@ skillRoot.action(async (options) => {
|
|
|
1073
1011
|
try {
|
|
1074
1012
|
const scope = resolveScope(options);
|
|
1075
1013
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1014
|
+
await initTargets(config);
|
|
1076
1015
|
const selection = await showSkillSelector({ scope, pageSize: config.ui.page_size });
|
|
1077
1016
|
if (!selection)
|
|
1078
1017
|
return;
|
|
@@ -1374,6 +1313,7 @@ hookRoot
|
|
|
1374
1313
|
async function applyToAgents(scope, enabledServerNames, options) {
|
|
1375
1314
|
const mcpConfig = loadMcpConfigWithPlugins();
|
|
1376
1315
|
const switchboardConfig = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1316
|
+
await initTargets(switchboardConfig);
|
|
1377
1317
|
const useSpinner = options?.useSpinner ?? true;
|
|
1378
1318
|
const results = [];
|
|
1379
1319
|
if (switchboardConfig.applications.active.length === 0) {
|
|
@@ -1404,7 +1344,28 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1404
1344
|
const activeSet = new Set(agentActiveServers);
|
|
1405
1345
|
const enabledServers = Object.fromEntries(Object.entries(mcpConfig.mcpServers).filter(([name]) => activeSet.has(name)));
|
|
1406
1346
|
const configToApply = { mcpServers: enabledServers };
|
|
1407
|
-
const
|
|
1347
|
+
const target = getTargetById(agentId);
|
|
1348
|
+
if (target?.isInstalled?.() === false) {
|
|
1349
|
+
persist(chalk.gray('○'), `${chalk.cyan(agentId)} ${chalk.gray('(not installed, skipped)')}`);
|
|
1350
|
+
results.push({
|
|
1351
|
+
application: agentId,
|
|
1352
|
+
filePath: '(not installed)',
|
|
1353
|
+
status: 'skipped',
|
|
1354
|
+
reason: 'not installed',
|
|
1355
|
+
});
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
if (!target?.mcp) {
|
|
1359
|
+
persist(chalk.yellow('⚠'), `${chalk.cyan(agentId)} - no MCP handler (skipped)`);
|
|
1360
|
+
results.push({
|
|
1361
|
+
application: agentId,
|
|
1362
|
+
filePath: '(unknown)',
|
|
1363
|
+
status: 'skipped',
|
|
1364
|
+
reason: 'no MCP handler',
|
|
1365
|
+
});
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
const mcpHandler = target.mcp;
|
|
1408
1369
|
const readFileSafe = (p) => {
|
|
1409
1370
|
try {
|
|
1410
1371
|
return fs.readFileSync(p, 'utf-8');
|
|
@@ -1413,11 +1374,10 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1413
1374
|
return null;
|
|
1414
1375
|
}
|
|
1415
1376
|
};
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
const projectPath = agent.projectConfigPath?.(scope.project) ?? 'project config';
|
|
1377
|
+
if (scope?.project && mcpHandler.applyProjectConfig) {
|
|
1378
|
+
const projectPath = mcpHandler.projectConfigPath?.(scope.project) ?? 'project config';
|
|
1419
1379
|
const before = readFileSafe(projectPath);
|
|
1420
|
-
|
|
1380
|
+
mcpHandler.applyProjectConfig(scope.project, configToApply);
|
|
1421
1381
|
const after = readFileSafe(projectPath);
|
|
1422
1382
|
const changed = before !== after;
|
|
1423
1383
|
persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(projectPath))}`);
|
|
@@ -1429,9 +1389,9 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1429
1389
|
});
|
|
1430
1390
|
}
|
|
1431
1391
|
else {
|
|
1432
|
-
const configPath =
|
|
1392
|
+
const configPath = mcpHandler.configPath();
|
|
1433
1393
|
const before = readFileSafe(configPath);
|
|
1434
|
-
|
|
1394
|
+
mcpHandler.applyConfig(configToApply);
|
|
1435
1395
|
const after = readFileSafe(configPath);
|
|
1436
1396
|
const changed = before !== after;
|
|
1437
1397
|
persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(configPath))}`);
|
|
@@ -1527,21 +1487,22 @@ pluginRoot
|
|
|
1527
1487
|
const index = buildPluginIndex();
|
|
1528
1488
|
const scope = resolveScope(options);
|
|
1529
1489
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1530
|
-
const
|
|
1490
|
+
const enabledList = config.plugins.enabled;
|
|
1491
|
+
const enabledSet = new Set(enabledList);
|
|
1531
1492
|
if (options.json) {
|
|
1532
1493
|
console.log(JSON.stringify(index.plugins.map((p) => {
|
|
1533
1494
|
const ref = p.meta.sourceKind === 'marketplace' ? `${p.id}@${p.meta.sourceName}` : p.id;
|
|
1534
1495
|
return {
|
|
1535
1496
|
id: p.id,
|
|
1536
1497
|
ref,
|
|
1537
|
-
enabled:
|
|
1498
|
+
enabled: enabledSet.has(ref),
|
|
1538
1499
|
...p.meta,
|
|
1539
1500
|
components: Object.fromEntries(Object.entries(p.components).map(([k, v]) => [k, v.length])),
|
|
1540
1501
|
};
|
|
1541
1502
|
}), null, 2));
|
|
1542
1503
|
return;
|
|
1543
1504
|
}
|
|
1544
|
-
printPluginList(index.plugins,
|
|
1505
|
+
printPluginList(index.plugins, enabledList);
|
|
1545
1506
|
}
|
|
1546
1507
|
catch (error) {
|
|
1547
1508
|
if (error instanceof Error) {
|
|
@@ -1578,7 +1539,7 @@ function pluginEnableAction(id, options) {
|
|
|
1578
1539
|
try {
|
|
1579
1540
|
const scope = resolveScope(options);
|
|
1580
1541
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1581
|
-
if (config.plugins.enabled
|
|
1542
|
+
if (config.plugins.enabled.includes(id)) {
|
|
1582
1543
|
console.log(chalk.yellow(`⚠ Plugin "${id}" is already enabled.`));
|
|
1583
1544
|
return;
|
|
1584
1545
|
}
|
|
@@ -1592,7 +1553,7 @@ function pluginEnableAction(id, options) {
|
|
|
1592
1553
|
...layer,
|
|
1593
1554
|
plugins: {
|
|
1594
1555
|
...(layer.plugins ?? {}),
|
|
1595
|
-
enabled:
|
|
1556
|
+
enabled: [...(layer.plugins?.enabled ?? []), id],
|
|
1596
1557
|
},
|
|
1597
1558
|
}), scopeToLoadOptions(scope));
|
|
1598
1559
|
console.log(chalk.green(`✓ Plugin "${id}" enabled.`));
|
|
@@ -1608,19 +1569,15 @@ function pluginDisableAction(id, options) {
|
|
|
1608
1569
|
try {
|
|
1609
1570
|
const scope = resolveScope(options);
|
|
1610
1571
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1611
|
-
if (config.plugins.enabled
|
|
1612
|
-
console.log(chalk.yellow(`⚠ Plugin "${id}" is not
|
|
1613
|
-
return;
|
|
1614
|
-
}
|
|
1615
|
-
if (config.plugins.enabled[id] === false) {
|
|
1616
|
-
console.log(chalk.yellow(`⚠ Plugin "${id}" is already disabled.`));
|
|
1572
|
+
if (!config.plugins.enabled.includes(id)) {
|
|
1573
|
+
console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
|
|
1617
1574
|
return;
|
|
1618
1575
|
}
|
|
1619
1576
|
updateConfigLayer((layer) => ({
|
|
1620
1577
|
...layer,
|
|
1621
1578
|
plugins: {
|
|
1622
1579
|
...(layer.plugins ?? {}),
|
|
1623
|
-
enabled:
|
|
1580
|
+
enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
|
|
1624
1581
|
},
|
|
1625
1582
|
}), scopeToLoadOptions(scope));
|
|
1626
1583
|
console.log(chalk.green(`✓ Plugin "${id}" disabled.`));
|
|
@@ -1636,18 +1593,17 @@ function pluginUninstallAction(id, options) {
|
|
|
1636
1593
|
try {
|
|
1637
1594
|
const scope = resolveScope(options);
|
|
1638
1595
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1639
|
-
if (config.plugins.enabled
|
|
1640
|
-
console.log(chalk.yellow(`⚠ Plugin "${id}" is not
|
|
1596
|
+
if (!config.plugins.enabled.includes(id)) {
|
|
1597
|
+
console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
|
|
1641
1598
|
return;
|
|
1642
1599
|
}
|
|
1643
|
-
updateConfigLayer((layer) => {
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
}, scopeToLoadOptions(scope));
|
|
1600
|
+
updateConfigLayer((layer) => ({
|
|
1601
|
+
...layer,
|
|
1602
|
+
plugins: {
|
|
1603
|
+
...(layer.plugins ?? {}),
|
|
1604
|
+
enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
|
|
1605
|
+
},
|
|
1606
|
+
}), scopeToLoadOptions(scope));
|
|
1651
1607
|
console.log(chalk.green(`✓ Plugin "${id}" uninstalled.`));
|
|
1652
1608
|
}
|
|
1653
1609
|
catch (error) {
|
|
@@ -1661,27 +1617,25 @@ const pluginScopeOpts = [
|
|
|
1661
1617
|
['-p, --profile <name>', 'Profile configuration to use'],
|
|
1662
1618
|
['--project <path>', 'Project directory containing .asb.toml'],
|
|
1663
1619
|
];
|
|
1664
|
-
const enableCmd = pluginRoot
|
|
1665
|
-
.command('enable <id>')
|
|
1666
|
-
.description('Enable a plugin (set plugins.enabled to true)');
|
|
1620
|
+
const enableCmd = pluginRoot.command('enable <id>').description('Add a plugin to the enabled list');
|
|
1667
1621
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1668
1622
|
enableCmd.option(flag, desc);
|
|
1669
1623
|
enableCmd.action(pluginEnableAction);
|
|
1670
1624
|
const installCmd = pluginRoot
|
|
1671
1625
|
.command('install <id>')
|
|
1672
|
-
.description('
|
|
1626
|
+
.description('Add a plugin to the enabled list (alias for enable)');
|
|
1673
1627
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1674
1628
|
installCmd.option(flag, desc);
|
|
1675
1629
|
installCmd.action(pluginEnableAction);
|
|
1676
1630
|
const disableCmd = pluginRoot
|
|
1677
1631
|
.command('disable <id>')
|
|
1678
|
-
.description('
|
|
1632
|
+
.description('Remove a plugin from the enabled list');
|
|
1679
1633
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1680
1634
|
disableCmd.option(flag, desc);
|
|
1681
1635
|
disableCmd.action(pluginDisableAction);
|
|
1682
1636
|
const uninstallCmd = pluginRoot
|
|
1683
1637
|
.command('uninstall <id>')
|
|
1684
|
-
.description('Remove a plugin from
|
|
1638
|
+
.description('Remove a plugin from the enabled list (alias for disable)');
|
|
1685
1639
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1686
1640
|
uninstallCmd.option(flag, desc);
|
|
1687
1641
|
uninstallCmd.action(pluginUninstallAction);
|
|
@@ -1915,7 +1869,7 @@ program
|
|
|
1915
1869
|
.action(() => {
|
|
1916
1870
|
console.error(chalk.red('✗ `asb source` has been removed.\n' +
|
|
1917
1871
|
' Sources are now managed under `asb plugin marketplace`.\n' +
|
|
1918
|
-
' Config has moved from [library.sources] to [plugins
|
|
1872
|
+
' Config has moved from [library.sources] to [plugins].\n' +
|
|
1919
1873
|
' Run `asb plugin marketplace --help` for usage.'));
|
|
1920
1874
|
process.exit(1);
|
|
1921
1875
|
});
|