agent-switchboard 0.2.3 → 0.3.0
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 +9 -3
- package/dist/config/paths.js +24 -5
- 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 +59 -122
- 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 +10 -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 +54 -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 +36 -0
- package/dist/targets/registry.js +97 -0
- package/dist/targets/registry.js.map +1 -0
- package/dist/targets/types.d.ts +91 -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 { 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) {
|
|
@@ -110,26 +111,14 @@ program
|
|
|
110
111
|
console.log(chalk.blue('Inventory:'));
|
|
111
112
|
{
|
|
112
113
|
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
|
-
};
|
|
114
|
+
const sectionPlatforms = {};
|
|
115
|
+
for (const s of sections) {
|
|
116
|
+
let ids = getTargetsForSection(s).map((t) => t.id);
|
|
117
|
+
if (s === 'skills' && cursorSkillsDeduped) {
|
|
118
|
+
ids = ids.filter((id) => id !== 'cursor');
|
|
119
|
+
}
|
|
120
|
+
sectionPlatforms[s] = ids;
|
|
121
|
+
}
|
|
133
122
|
const termWidth = process.stdout.columns || 80;
|
|
134
123
|
const maxSectionLen = Math.max(...sections.map((s) => s.length));
|
|
135
124
|
const maxCountLen = Math.max(...sections.map((s) => `(${config[s].enabled.length})`.length));
|
|
@@ -194,9 +183,7 @@ program
|
|
|
194
183
|
// Show enabled plugins summary
|
|
195
184
|
{
|
|
196
185
|
const pluginIndex = buildPluginIndex();
|
|
197
|
-
const enabledPluginRefs =
|
|
198
|
-
.filter(([, v]) => v === true)
|
|
199
|
-
.map(([k]) => k);
|
|
186
|
+
const enabledPluginRefs = config.plugins.enabled;
|
|
200
187
|
if (enabledPluginRefs.length > 0) {
|
|
201
188
|
const names = enabledPluginRefs
|
|
202
189
|
.map((pid) => {
|
|
@@ -295,22 +282,6 @@ program
|
|
|
295
282
|
process.exit(1);
|
|
296
283
|
}
|
|
297
284
|
});
|
|
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
285
|
function resolveScope(input) {
|
|
315
286
|
if (!input)
|
|
316
287
|
return undefined;
|
|
@@ -377,26 +348,6 @@ function defaultSkillSourceDir(platform) {
|
|
|
377
348
|
return path.join(getCursorDir(), 'skills');
|
|
378
349
|
}
|
|
379
350
|
}
|
|
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
351
|
async function confirmOverwrite(filePath, force) {
|
|
401
352
|
if (!fs.existsSync(filePath))
|
|
402
353
|
return true;
|
|
@@ -404,29 +355,6 @@ async function confirmOverwrite(filePath, force) {
|
|
|
404
355
|
return true;
|
|
405
356
|
return await confirm({ message: `File exists: ${filePath}. Overwrite?`, default: false });
|
|
406
357
|
}
|
|
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
358
|
/**
|
|
431
359
|
* Extract hooks from Claude Code's ~/.claude/settings.json and import as a
|
|
432
360
|
* bundle into ~/.asb/hooks/. Copies referenced script files if they exist
|
|
@@ -662,7 +590,7 @@ ruleCommand
|
|
|
662
590
|
console.log();
|
|
663
591
|
printAgentSyncStatus({
|
|
664
592
|
agentSync: inventory.state.agentSync,
|
|
665
|
-
agents:
|
|
593
|
+
agents: getTargetsForSection('rules').map((t) => t.id),
|
|
666
594
|
});
|
|
667
595
|
const unsupportedAgents = listUnsupportedAgents();
|
|
668
596
|
if (unsupportedAgents.length > 0) {
|
|
@@ -689,6 +617,7 @@ ruleCommand.action(async (options) => {
|
|
|
689
617
|
try {
|
|
690
618
|
const scope = resolveScope(options);
|
|
691
619
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
620
|
+
await initTargets(config);
|
|
692
621
|
const selection = await showRuleSelector({ scope, pageSize: config.ui.page_size });
|
|
693
622
|
if (!selection) {
|
|
694
623
|
return;
|
|
@@ -777,6 +706,7 @@ commandRoot.action(async (options) => {
|
|
|
777
706
|
try {
|
|
778
707
|
const scope = resolveScope(options);
|
|
779
708
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
709
|
+
await initTargets(config);
|
|
780
710
|
const selection = await showCommandSelector({ scope, pageSize: config.ui.page_size });
|
|
781
711
|
if (!selection)
|
|
782
712
|
return;
|
|
@@ -926,6 +856,7 @@ agentRoot.action(async (options) => {
|
|
|
926
856
|
try {
|
|
927
857
|
const scope = resolveScope(options);
|
|
928
858
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
859
|
+
await initTargets(config);
|
|
929
860
|
const selection = await showSubagentSelector({ scope, pageSize: config.ui.page_size });
|
|
930
861
|
if (!selection)
|
|
931
862
|
return;
|
|
@@ -1073,6 +1004,7 @@ skillRoot.action(async (options) => {
|
|
|
1073
1004
|
try {
|
|
1074
1005
|
const scope = resolveScope(options);
|
|
1075
1006
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1007
|
+
await initTargets(config);
|
|
1076
1008
|
const selection = await showSkillSelector({ scope, pageSize: config.ui.page_size });
|
|
1077
1009
|
if (!selection)
|
|
1078
1010
|
return;
|
|
@@ -1374,6 +1306,7 @@ hookRoot
|
|
|
1374
1306
|
async function applyToAgents(scope, enabledServerNames, options) {
|
|
1375
1307
|
const mcpConfig = loadMcpConfigWithPlugins();
|
|
1376
1308
|
const switchboardConfig = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1309
|
+
await initTargets(switchboardConfig);
|
|
1377
1310
|
const useSpinner = options?.useSpinner ?? true;
|
|
1378
1311
|
const results = [];
|
|
1379
1312
|
if (switchboardConfig.applications.active.length === 0) {
|
|
@@ -1404,7 +1337,18 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1404
1337
|
const activeSet = new Set(agentActiveServers);
|
|
1405
1338
|
const enabledServers = Object.fromEntries(Object.entries(mcpConfig.mcpServers).filter(([name]) => activeSet.has(name)));
|
|
1406
1339
|
const configToApply = { mcpServers: enabledServers };
|
|
1407
|
-
const
|
|
1340
|
+
const target = getTargetById(agentId);
|
|
1341
|
+
if (!target?.mcp) {
|
|
1342
|
+
persist(chalk.yellow('⚠'), `${chalk.cyan(agentId)} - no MCP handler (skipped)`);
|
|
1343
|
+
results.push({
|
|
1344
|
+
application: agentId,
|
|
1345
|
+
filePath: '(unknown)',
|
|
1346
|
+
status: 'skipped',
|
|
1347
|
+
reason: 'no MCP handler',
|
|
1348
|
+
});
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
const mcpHandler = target.mcp;
|
|
1408
1352
|
const readFileSafe = (p) => {
|
|
1409
1353
|
try {
|
|
1410
1354
|
return fs.readFileSync(p, 'utf-8');
|
|
@@ -1413,11 +1357,10 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1413
1357
|
return null;
|
|
1414
1358
|
}
|
|
1415
1359
|
};
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
const projectPath = agent.projectConfigPath?.(scope.project) ?? 'project config';
|
|
1360
|
+
if (scope?.project && mcpHandler.applyProjectConfig) {
|
|
1361
|
+
const projectPath = mcpHandler.projectConfigPath?.(scope.project) ?? 'project config';
|
|
1419
1362
|
const before = readFileSafe(projectPath);
|
|
1420
|
-
|
|
1363
|
+
mcpHandler.applyProjectConfig(scope.project, configToApply);
|
|
1421
1364
|
const after = readFileSafe(projectPath);
|
|
1422
1365
|
const changed = before !== after;
|
|
1423
1366
|
persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(projectPath))}`);
|
|
@@ -1429,9 +1372,9 @@ async function applyToAgents(scope, enabledServerNames, options) {
|
|
|
1429
1372
|
});
|
|
1430
1373
|
}
|
|
1431
1374
|
else {
|
|
1432
|
-
const configPath =
|
|
1375
|
+
const configPath = mcpHandler.configPath();
|
|
1433
1376
|
const before = readFileSafe(configPath);
|
|
1434
|
-
|
|
1377
|
+
mcpHandler.applyConfig(configToApply);
|
|
1435
1378
|
const after = readFileSafe(configPath);
|
|
1436
1379
|
const changed = before !== after;
|
|
1437
1380
|
persist(chalk.green('✓'), `${chalk.cyan(agentId)} ${chalk.dim(shortenPath(configPath))}`);
|
|
@@ -1527,21 +1470,22 @@ pluginRoot
|
|
|
1527
1470
|
const index = buildPluginIndex();
|
|
1528
1471
|
const scope = resolveScope(options);
|
|
1529
1472
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1530
|
-
const
|
|
1473
|
+
const enabledList = config.plugins.enabled;
|
|
1474
|
+
const enabledSet = new Set(enabledList);
|
|
1531
1475
|
if (options.json) {
|
|
1532
1476
|
console.log(JSON.stringify(index.plugins.map((p) => {
|
|
1533
1477
|
const ref = p.meta.sourceKind === 'marketplace' ? `${p.id}@${p.meta.sourceName}` : p.id;
|
|
1534
1478
|
return {
|
|
1535
1479
|
id: p.id,
|
|
1536
1480
|
ref,
|
|
1537
|
-
enabled:
|
|
1481
|
+
enabled: enabledSet.has(ref),
|
|
1538
1482
|
...p.meta,
|
|
1539
1483
|
components: Object.fromEntries(Object.entries(p.components).map(([k, v]) => [k, v.length])),
|
|
1540
1484
|
};
|
|
1541
1485
|
}), null, 2));
|
|
1542
1486
|
return;
|
|
1543
1487
|
}
|
|
1544
|
-
printPluginList(index.plugins,
|
|
1488
|
+
printPluginList(index.plugins, enabledList);
|
|
1545
1489
|
}
|
|
1546
1490
|
catch (error) {
|
|
1547
1491
|
if (error instanceof Error) {
|
|
@@ -1578,7 +1522,7 @@ function pluginEnableAction(id, options) {
|
|
|
1578
1522
|
try {
|
|
1579
1523
|
const scope = resolveScope(options);
|
|
1580
1524
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1581
|
-
if (config.plugins.enabled
|
|
1525
|
+
if (config.plugins.enabled.includes(id)) {
|
|
1582
1526
|
console.log(chalk.yellow(`⚠ Plugin "${id}" is already enabled.`));
|
|
1583
1527
|
return;
|
|
1584
1528
|
}
|
|
@@ -1592,7 +1536,7 @@ function pluginEnableAction(id, options) {
|
|
|
1592
1536
|
...layer,
|
|
1593
1537
|
plugins: {
|
|
1594
1538
|
...(layer.plugins ?? {}),
|
|
1595
|
-
enabled:
|
|
1539
|
+
enabled: [...(layer.plugins?.enabled ?? []), id],
|
|
1596
1540
|
},
|
|
1597
1541
|
}), scopeToLoadOptions(scope));
|
|
1598
1542
|
console.log(chalk.green(`✓ Plugin "${id}" enabled.`));
|
|
@@ -1608,19 +1552,15 @@ function pluginDisableAction(id, options) {
|
|
|
1608
1552
|
try {
|
|
1609
1553
|
const scope = resolveScope(options);
|
|
1610
1554
|
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.`));
|
|
1555
|
+
if (!config.plugins.enabled.includes(id)) {
|
|
1556
|
+
console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
|
|
1617
1557
|
return;
|
|
1618
1558
|
}
|
|
1619
1559
|
updateConfigLayer((layer) => ({
|
|
1620
1560
|
...layer,
|
|
1621
1561
|
plugins: {
|
|
1622
1562
|
...(layer.plugins ?? {}),
|
|
1623
|
-
enabled:
|
|
1563
|
+
enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
|
|
1624
1564
|
},
|
|
1625
1565
|
}), scopeToLoadOptions(scope));
|
|
1626
1566
|
console.log(chalk.green(`✓ Plugin "${id}" disabled.`));
|
|
@@ -1636,18 +1576,17 @@ function pluginUninstallAction(id, options) {
|
|
|
1636
1576
|
try {
|
|
1637
1577
|
const scope = resolveScope(options);
|
|
1638
1578
|
const config = loadSwitchboardConfig(scopeToLoadOptions(scope));
|
|
1639
|
-
if (config.plugins.enabled
|
|
1640
|
-
console.log(chalk.yellow(`⚠ Plugin "${id}" is not
|
|
1579
|
+
if (!config.plugins.enabled.includes(id)) {
|
|
1580
|
+
console.log(chalk.yellow(`⚠ Plugin "${id}" is not enabled.`));
|
|
1641
1581
|
return;
|
|
1642
1582
|
}
|
|
1643
|
-
updateConfigLayer((layer) => {
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
}, scopeToLoadOptions(scope));
|
|
1583
|
+
updateConfigLayer((layer) => ({
|
|
1584
|
+
...layer,
|
|
1585
|
+
plugins: {
|
|
1586
|
+
...(layer.plugins ?? {}),
|
|
1587
|
+
enabled: (layer.plugins?.enabled ?? []).filter((x) => x !== id),
|
|
1588
|
+
},
|
|
1589
|
+
}), scopeToLoadOptions(scope));
|
|
1651
1590
|
console.log(chalk.green(`✓ Plugin "${id}" uninstalled.`));
|
|
1652
1591
|
}
|
|
1653
1592
|
catch (error) {
|
|
@@ -1661,27 +1600,25 @@ const pluginScopeOpts = [
|
|
|
1661
1600
|
['-p, --profile <name>', 'Profile configuration to use'],
|
|
1662
1601
|
['--project <path>', 'Project directory containing .asb.toml'],
|
|
1663
1602
|
];
|
|
1664
|
-
const enableCmd = pluginRoot
|
|
1665
|
-
.command('enable <id>')
|
|
1666
|
-
.description('Enable a plugin (set plugins.enabled to true)');
|
|
1603
|
+
const enableCmd = pluginRoot.command('enable <id>').description('Add a plugin to the enabled list');
|
|
1667
1604
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1668
1605
|
enableCmd.option(flag, desc);
|
|
1669
1606
|
enableCmd.action(pluginEnableAction);
|
|
1670
1607
|
const installCmd = pluginRoot
|
|
1671
1608
|
.command('install <id>')
|
|
1672
|
-
.description('
|
|
1609
|
+
.description('Add a plugin to the enabled list (alias for enable)');
|
|
1673
1610
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1674
1611
|
installCmd.option(flag, desc);
|
|
1675
1612
|
installCmd.action(pluginEnableAction);
|
|
1676
1613
|
const disableCmd = pluginRoot
|
|
1677
1614
|
.command('disable <id>')
|
|
1678
|
-
.description('
|
|
1615
|
+
.description('Remove a plugin from the enabled list');
|
|
1679
1616
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1680
1617
|
disableCmd.option(flag, desc);
|
|
1681
1618
|
disableCmd.action(pluginDisableAction);
|
|
1682
1619
|
const uninstallCmd = pluginRoot
|
|
1683
1620
|
.command('uninstall <id>')
|
|
1684
|
-
.description('Remove a plugin from
|
|
1621
|
+
.description('Remove a plugin from the enabled list (alias for disable)');
|
|
1685
1622
|
for (const [flag, desc] of pluginScopeOpts)
|
|
1686
1623
|
uninstallCmd.option(flag, desc);
|
|
1687
1624
|
uninstallCmd.action(pluginUninstallAction);
|
|
@@ -1915,7 +1852,7 @@ program
|
|
|
1915
1852
|
.action(() => {
|
|
1916
1853
|
console.error(chalk.red('✗ `asb source` has been removed.\n' +
|
|
1917
1854
|
' Sources are now managed under `asb plugin marketplace`.\n' +
|
|
1918
|
-
' Config has moved from [library.sources] to [plugins
|
|
1855
|
+
' Config has moved from [library.sources] to [plugins].\n' +
|
|
1919
1856
|
' Run `asb plugin marketplace --help` for usage.'));
|
|
1920
1857
|
process.exit(1);
|
|
1921
1858
|
});
|