agent-switchboard 0.1.27 → 0.1.28

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.
Files changed (88) hide show
  1. package/README.md +26 -1
  2. package/dist/commands/distribution.js +2 -2
  3. package/dist/commands/distribution.js.map +1 -1
  4. package/dist/commands/library.d.ts +1 -1
  5. package/dist/commands/library.js +5 -5
  6. package/dist/commands/library.js.map +1 -1
  7. package/dist/config/application-config.d.ts +37 -0
  8. package/dist/config/application-config.js +83 -0
  9. package/dist/config/application-config.js.map +1 -0
  10. package/dist/config/layered-config.js +43 -2
  11. package/dist/config/layered-config.js.map +1 -1
  12. package/dist/config/paths.d.ts +7 -2
  13. package/dist/config/paths.js +12 -3
  14. package/dist/config/paths.js.map +1 -1
  15. package/dist/config/schemas.d.ts +103 -22
  16. package/dist/config/schemas.js +22 -18
  17. package/dist/config/schemas.js.map +1 -1
  18. package/dist/config/switchboard-config.d.ts +3 -6
  19. package/dist/config/switchboard-config.js +3 -6
  20. package/dist/config/switchboard-config.js.map +1 -1
  21. package/dist/hooks/distribution.d.ts +27 -0
  22. package/dist/hooks/distribution.js +235 -0
  23. package/dist/hooks/distribution.js.map +1 -0
  24. package/dist/hooks/library.d.ts +40 -0
  25. package/dist/hooks/library.js +143 -0
  26. package/dist/hooks/library.js.map +1 -0
  27. package/dist/hooks/schema.d.ts +542 -0
  28. package/dist/hooks/schema.js +49 -0
  29. package/dist/hooks/schema.js.map +1 -0
  30. package/dist/index.js +608 -146
  31. package/dist/index.js.map +1 -1
  32. package/dist/library/fs.d.ts +1 -3
  33. package/dist/library/fs.js +24 -7
  34. package/dist/library/fs.js.map +1 -1
  35. package/dist/library/schema.d.ts +1 -1
  36. package/dist/library/schema.js +1 -1
  37. package/dist/library/sources.d.ts +3 -0
  38. package/dist/library/sources.js +8 -2
  39. package/dist/library/sources.js.map +1 -1
  40. package/dist/library/state.d.ts +4 -5
  41. package/dist/library/state.js +15 -31
  42. package/dist/library/state.js.map +1 -1
  43. package/dist/marketplace/plugin-loader.d.ts +30 -0
  44. package/dist/marketplace/plugin-loader.js +178 -0
  45. package/dist/marketplace/plugin-loader.js.map +1 -0
  46. package/dist/marketplace/reader.d.ts +36 -0
  47. package/dist/marketplace/reader.js +90 -0
  48. package/dist/marketplace/reader.js.map +1 -0
  49. package/dist/marketplace/schemas.d.ts +467 -0
  50. package/dist/marketplace/schemas.js +57 -0
  51. package/dist/marketplace/schemas.js.map +1 -0
  52. package/dist/marketplace/source-loader.d.ts +32 -0
  53. package/dist/marketplace/source-loader.js +45 -0
  54. package/dist/marketplace/source-loader.js.map +1 -0
  55. package/dist/rules/composer.d.ts +2 -2
  56. package/dist/rules/composer.js +5 -5
  57. package/dist/rules/composer.js.map +1 -1
  58. package/dist/rules/distribution.js +2 -2
  59. package/dist/rules/distribution.js.map +1 -1
  60. package/dist/skills/distribution.js +6 -6
  61. package/dist/skills/distribution.js.map +1 -1
  62. package/dist/skills/library.d.ts +1 -2
  63. package/dist/skills/library.js +6 -6
  64. package/dist/skills/library.js.map +1 -1
  65. package/dist/subagents/distribution.d.ts +1 -1
  66. package/dist/subagents/distribution.js +319 -20
  67. package/dist/subagents/distribution.js.map +1 -1
  68. package/dist/subagents/importer.d.ts +1 -1
  69. package/dist/subagents/importer.js +61 -1
  70. package/dist/subagents/importer.js.map +1 -1
  71. package/dist/subagents/inventory.js +3 -3
  72. package/dist/subagents/inventory.js.map +1 -1
  73. package/dist/subagents/library.d.ts +2 -2
  74. package/dist/subagents/library.js +14 -19
  75. package/dist/subagents/library.js.map +1 -1
  76. package/dist/ui/hook-ui.d.ts +8 -0
  77. package/dist/ui/hook-ui.js +17 -0
  78. package/dist/ui/hook-ui.js.map +1 -0
  79. package/dist/ui/library-selector.d.ts +1 -1
  80. package/dist/ui/subagent-ui.js +3 -3
  81. package/dist/ui/subagent-ui.js.map +1 -1
  82. package/dist/util/cli.d.ts +20 -0
  83. package/dist/util/cli.js +107 -14
  84. package/dist/util/cli.js.map +1 -1
  85. package/package.json +3 -2
  86. package/dist/config/agent-config.d.ts +0 -35
  87. package/dist/config/agent-config.js +0 -88
  88. package/dist/config/agent-config.js.map +0 -1
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Plugin component loader: extracts commands, agents, skills, and hooks from a
3
+ * resolved plugin directory and maps them to ASB library entry formats.
4
+ */
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { hookFileSchema } from '../hooks/schema.js';
8
+ import { parseLibraryMarkdown } from '../library/parser.js';
9
+ import { parseSkillMarkdown } from '../skills/parser.js';
10
+ const SKILL_FILE = 'SKILL.md';
11
+ function isMarkdownFile(name) {
12
+ const ext = path.extname(name).toLowerCase();
13
+ return ext === '.md' || ext === '.markdown';
14
+ }
15
+ function toId(fileName) {
16
+ return path.basename(fileName, path.extname(fileName));
17
+ }
18
+ /**
19
+ * Load all components (commands, agents, skills) from a single plugin directory.
20
+ * The namespace is the plugin name, producing IDs like "plugin-name:component-id".
21
+ */
22
+ export function loadPluginComponents(plugin) {
23
+ const namespace = plugin.name;
24
+ const result = { commands: [], agents: [], skills: [], hooks: [] };
25
+ result.commands = loadMarkdownEntries(path.join(plugin.localPath, 'commands'), namespace, 'command');
26
+ result.agents = loadMarkdownEntries(path.join(plugin.localPath, 'agents'), namespace, 'agent');
27
+ result.skills = loadSkillEntries(plugin.localPath, namespace);
28
+ result.hooks = loadHookEntries(plugin.localPath, namespace);
29
+ return result;
30
+ }
31
+ /**
32
+ * Load markdown-based library entries (commands or agents) from a directory.
33
+ */
34
+ function loadMarkdownEntries(directory, namespace, kind) {
35
+ if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory()) {
36
+ return [];
37
+ }
38
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
39
+ const result = [];
40
+ for (const entry of entries) {
41
+ if (!entry.isFile() || !isMarkdownFile(entry.name))
42
+ continue;
43
+ const absolutePath = path.join(directory, entry.name);
44
+ const rawContent = fs.readFileSync(absolutePath, 'utf-8');
45
+ try {
46
+ const parsed = parseLibraryMarkdown(rawContent);
47
+ const bareId = toId(entry.name);
48
+ const id = `${namespace}:${bareId}`;
49
+ result.push({
50
+ id,
51
+ bareId,
52
+ namespace,
53
+ source: directory,
54
+ filePath: absolutePath,
55
+ metadata: parsed.metadata,
56
+ content: parsed.content,
57
+ });
58
+ }
59
+ catch (error) {
60
+ const msg = error instanceof Error ? error.message : String(error);
61
+ throw new Error(`Failed to parse plugin ${kind} "${entry.name}": ${msg}`);
62
+ }
63
+ }
64
+ return result;
65
+ }
66
+ /**
67
+ * Load skill entries from a plugin's skills/ directory.
68
+ * Each subdirectory containing SKILL.md is a skill bundle.
69
+ */
70
+ function loadSkillEntries(pluginDir, namespace) {
71
+ const skillsDir = path.join(pluginDir, 'skills');
72
+ if (!fs.existsSync(skillsDir) || !fs.statSync(skillsDir).isDirectory()) {
73
+ return [];
74
+ }
75
+ const result = [];
76
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
77
+ for (const entry of entries) {
78
+ if (!entry.isDirectory())
79
+ continue;
80
+ const skillDir = path.join(skillsDir, entry.name);
81
+ const skillPath = path.join(skillDir, SKILL_FILE);
82
+ if (!fs.existsSync(skillPath))
83
+ continue;
84
+ try {
85
+ const rawContent = fs.readFileSync(skillPath, 'utf-8');
86
+ const parsed = parseSkillMarkdown(rawContent);
87
+ const bareId = entry.name;
88
+ const id = `${namespace}:${bareId}`;
89
+ result.push({
90
+ id,
91
+ bareId,
92
+ namespace,
93
+ source: skillsDir,
94
+ dirPath: skillDir,
95
+ skillPath,
96
+ metadata: parsed.metadata,
97
+ content: parsed.content,
98
+ });
99
+ }
100
+ catch (error) {
101
+ const msg = error instanceof Error ? error.message : String(error);
102
+ throw new Error(`Failed to parse plugin skill "${entry.name}": ${msg}`);
103
+ }
104
+ }
105
+ return result;
106
+ }
107
+ /**
108
+ * Load hook entries from a plugin's hooks/ directory.
109
+ * Supports both single-file hooks (*.json) and bundle hooks (subdirs with hook.json).
110
+ * Claude Code plugins typically have hooks/hooks.json + script files at the same level.
111
+ */
112
+ function loadHookEntries(pluginDir, namespace) {
113
+ const hooksDir = path.join(pluginDir, 'hooks');
114
+ if (!fs.existsSync(hooksDir) || !fs.statSync(hooksDir).isDirectory()) {
115
+ return [];
116
+ }
117
+ const result = [];
118
+ const entries = fs.readdirSync(hooksDir, { withFileTypes: true });
119
+ for (const entry of entries) {
120
+ if (entry.isFile() && path.extname(entry.name).toLowerCase() === '.json') {
121
+ const absolutePath = path.join(hooksDir, entry.name);
122
+ const rawContent = fs.readFileSync(absolutePath, 'utf-8');
123
+ try {
124
+ const parsed = hookFileSchema.parse(JSON.parse(rawContent));
125
+ const bareId = path.basename(entry.name, '.json');
126
+ const id = `${namespace}:${bareId}`;
127
+ // Detect if script files exist alongside the JSON (bundle-like plugin layout)
128
+ const hasScripts = entries.some((e) => e.isFile() && !e.name.endsWith('.json'));
129
+ result.push({
130
+ id,
131
+ bareId,
132
+ namespace,
133
+ source: hooksDir,
134
+ filePath: absolutePath,
135
+ name: parsed.name,
136
+ description: parsed.description,
137
+ hooks: parsed.hooks,
138
+ isBundle: hasScripts,
139
+ dirPath: hasScripts ? hooksDir : undefined,
140
+ });
141
+ }
142
+ catch (error) {
143
+ const msg = error instanceof Error ? error.message : String(error);
144
+ throw new Error(`Failed to parse plugin hook "${entry.name}": ${msg}`);
145
+ }
146
+ }
147
+ else if (entry.isDirectory()) {
148
+ const hookJsonPath = path.join(hooksDir, entry.name, 'hook.json');
149
+ if (!fs.existsSync(hookJsonPath))
150
+ continue;
151
+ try {
152
+ const rawContent = fs.readFileSync(hookJsonPath, 'utf-8');
153
+ const parsed = hookFileSchema.parse(JSON.parse(rawContent));
154
+ const bareId = entry.name;
155
+ const id = `${namespace}:${bareId}`;
156
+ const bundleDir = path.join(hooksDir, entry.name);
157
+ result.push({
158
+ id,
159
+ bareId,
160
+ namespace,
161
+ source: hooksDir,
162
+ filePath: hookJsonPath,
163
+ name: parsed.name,
164
+ description: parsed.description,
165
+ hooks: parsed.hooks,
166
+ isBundle: true,
167
+ dirPath: bundleDir,
168
+ });
169
+ }
170
+ catch (error) {
171
+ const msg = error instanceof Error ? error.message : String(error);
172
+ throw new Error(`Failed to parse plugin hook bundle "${entry.name}": ${msg}`);
173
+ }
174
+ }
175
+ }
176
+ return result;
177
+ }
178
+ //# sourceMappingURL=plugin-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/marketplace/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Marketplace reader: detects and parses Claude Code marketplace repositories.
3
+ *
4
+ * A marketplace is a repository containing `.claude-plugin/marketplace.json`.
5
+ * Each plugin is either a relative path within the same repo or a standalone
6
+ * directory with `.claude-plugin/plugin.json`.
7
+ */
8
+ import { type PluginManifest } from './schemas.js';
9
+ export interface ResolvedPlugin {
10
+ name: string;
11
+ description?: string;
12
+ version?: string;
13
+ /** Absolute path to the plugin root directory */
14
+ localPath: string;
15
+ /** Plugin manifest if `.claude-plugin/plugin.json` exists */
16
+ manifest?: PluginManifest;
17
+ /** Whether plugin is in strict mode */
18
+ strict: boolean;
19
+ }
20
+ export interface MarketplaceReadResult {
21
+ name: string;
22
+ owner: {
23
+ name: string;
24
+ email?: string;
25
+ };
26
+ plugins: ResolvedPlugin[];
27
+ warnings: string[];
28
+ }
29
+ /**
30
+ * Check whether a local path is a Claude Code marketplace (has .claude-plugin/marketplace.json).
31
+ */
32
+ export declare function isMarketplace(localPath: string): boolean;
33
+ /**
34
+ * Read and resolve a marketplace, returning all resolvable plugins with metadata.
35
+ */
36
+ export declare function readMarketplace(localPath: string): MarketplaceReadResult;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Marketplace reader: detects and parses Claude Code marketplace repositories.
3
+ *
4
+ * A marketplace is a repository containing `.claude-plugin/marketplace.json`.
5
+ * Each plugin is either a relative path within the same repo or a standalone
6
+ * directory with `.claude-plugin/plugin.json`.
7
+ */
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import { marketplaceManifestSchema, pluginManifestSchema, } from './schemas.js';
11
+ const MARKETPLACE_MANIFEST = '.claude-plugin/marketplace.json';
12
+ const PLUGIN_MANIFEST = '.claude-plugin/plugin.json';
13
+ /**
14
+ * Check whether a local path is a Claude Code marketplace (has .claude-plugin/marketplace.json).
15
+ */
16
+ export function isMarketplace(localPath) {
17
+ const manifestPath = path.join(localPath, MARKETPLACE_MANIFEST);
18
+ return fs.existsSync(manifestPath);
19
+ }
20
+ /**
21
+ * Read and resolve a marketplace, returning all resolvable plugins with metadata.
22
+ */
23
+ export function readMarketplace(localPath) {
24
+ const manifestPath = path.join(localPath, MARKETPLACE_MANIFEST);
25
+ const warnings = [];
26
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
27
+ const manifest = marketplaceManifestSchema.parse(raw);
28
+ const pluginRoot = manifest.metadata?.pluginRoot ?? '';
29
+ const plugins = [];
30
+ for (const entry of manifest.plugins) {
31
+ const resolved = resolvePluginDir(localPath, pluginRoot, entry.name, entry.source);
32
+ if (!resolved) {
33
+ warnings.push(`Plugin "${entry.name}": unsupported source type, skipped`);
34
+ continue;
35
+ }
36
+ if (!fs.existsSync(resolved)) {
37
+ warnings.push(`Plugin "${entry.name}": directory not found at ${resolved}`);
38
+ continue;
39
+ }
40
+ const pluginManifest = readPluginManifest(resolved);
41
+ plugins.push({
42
+ name: entry.name,
43
+ description: entry.description ?? pluginManifest?.description,
44
+ version: entry.version ?? pluginManifest?.version,
45
+ localPath: resolved,
46
+ manifest: pluginManifest ?? undefined,
47
+ strict: entry.strict,
48
+ });
49
+ }
50
+ return {
51
+ name: manifest.name,
52
+ owner: manifest.owner,
53
+ plugins,
54
+ warnings,
55
+ };
56
+ }
57
+ /**
58
+ * Resolve a plugin source to a local absolute path.
59
+ * Only supports relative paths and local `path` sources for MVP.
60
+ * GitHub/git/npm/pip sources return null with a warning.
61
+ */
62
+ function resolvePluginDir(marketplaceRoot, pluginRoot, _pluginName, source) {
63
+ if (typeof source === 'string') {
64
+ if (source.startsWith('./') || source.startsWith('../') || !source.includes(':')) {
65
+ return path.resolve(marketplaceRoot, pluginRoot, source);
66
+ }
67
+ return null;
68
+ }
69
+ if (source.path && typeof source.path === 'string') {
70
+ return path.resolve(marketplaceRoot, pluginRoot, source.path);
71
+ }
72
+ // npm, pip, github, git sources are not supported in MVP
73
+ return null;
74
+ }
75
+ /**
76
+ * Read optional `.claude-plugin/plugin.json` from a plugin directory.
77
+ */
78
+ function readPluginManifest(pluginDir) {
79
+ const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST);
80
+ if (!fs.existsSync(manifestPath))
81
+ return null;
82
+ try {
83
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
84
+ return pluginManifestSchema.parse(raw);
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ //# sourceMappingURL=reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/marketplace/reader.ts"],"names":[],"mappings":"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"}