agent-switchboard 0.1.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/agents/adapter.d.ts +32 -0
  4. package/dist/agents/adapter.js +6 -0
  5. package/dist/agents/adapter.js.map +1 -0
  6. package/dist/agents/claude-code.d.ts +17 -0
  7. package/dist/agents/claude-code.js +27 -0
  8. package/dist/agents/claude-code.js.map +1 -0
  9. package/dist/agents/claude-desktop.d.ts +23 -0
  10. package/dist/agents/claude-desktop.js +44 -0
  11. package/dist/agents/claude-desktop.js.map +1 -0
  12. package/dist/agents/codex.d.ts +42 -0
  13. package/dist/agents/codex.js +135 -0
  14. package/dist/agents/codex.js.map +1 -0
  15. package/dist/agents/cursor.d.ts +20 -0
  16. package/dist/agents/cursor.js +31 -0
  17. package/dist/agents/cursor.js.map +1 -0
  18. package/dist/agents/gemini.d.ts +20 -0
  19. package/dist/agents/gemini.js +31 -0
  20. package/dist/agents/gemini.js.map +1 -0
  21. package/dist/agents/json-utils.d.ts +9 -0
  22. package/dist/agents/json-utils.js +26 -0
  23. package/dist/agents/json-utils.js.map +1 -0
  24. package/dist/agents/registry.d.ts +23 -0
  25. package/dist/agents/registry.js +54 -0
  26. package/dist/agents/registry.js.map +1 -0
  27. package/dist/config/abs-config.d.ts +21 -0
  28. package/dist/config/abs-config.js +67 -0
  29. package/dist/config/abs-config.js.map +1 -0
  30. package/dist/config/mcp-config.d.ts +31 -0
  31. package/dist/config/mcp-config.js +98 -0
  32. package/dist/config/mcp-config.js.map +1 -0
  33. package/dist/config/paths.d.ts +28 -0
  34. package/dist/config/paths.js +43 -0
  35. package/dist/config/paths.js.map +1 -0
  36. package/dist/config/schemas.d.ts +84 -0
  37. package/dist/config/schemas.js +31 -0
  38. package/dist/config/schemas.js.map +1 -0
  39. package/dist/config/switchboard-config.d.ts +21 -0
  40. package/dist/config/switchboard-config.js +67 -0
  41. package/dist/config/switchboard-config.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.js +116 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/types.d.ts +19 -0
  46. package/dist/types.js +6 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/ui/mcp-ui.d.ts +16 -0
  49. package/dist/ui/mcp-ui.js +65 -0
  50. package/dist/ui/mcp-ui.js.map +1 -0
  51. package/package.json +47 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Agent adapter registry
3
+ * Central registry for all supported agent adapters
4
+ */
5
+ import { ClaudeCodeAgent } from "./claude-code.js";
6
+ import { ClaudeDesktopAgent } from "./claude-desktop.js";
7
+ import { CodexAgent } from "./codex.js";
8
+ import { CursorAgent } from "./cursor.js";
9
+ import { GeminiAgent } from "./gemini.js";
10
+ /**
11
+ * Registry of all available agent adapters
12
+ * Add new adapters here when implemented
13
+ */
14
+ const agents = [
15
+ new ClaudeCodeAgent(),
16
+ new ClaudeDesktopAgent(),
17
+ new CodexAgent(),
18
+ new CursorAgent(),
19
+ new GeminiAgent(),
20
+ ];
21
+ /**
22
+ * Get an agent adapter by its ID
23
+ * @param id - Agent identifier (e.g., "claude-code", "codex", "cursor")
24
+ * @returns Agent adapter instance
25
+ * @throws {Error} If agent ID is not supported
26
+ */
27
+ export function getAgentById(id) {
28
+ const agent = agents.find((a) => a.id === id);
29
+ if (!agent) {
30
+ throw new Error(`Unsupported agent: ${JSON.stringify(id)}. Supported agents: ${supportedAgentIds().join(", ")}`);
31
+ }
32
+ return agent;
33
+ }
34
+ /**
35
+ * Get list of all supported agent IDs
36
+ * @returns Array of agent IDs
37
+ */
38
+ export function supportedAgentIds() {
39
+ return agents.map((a) => a.id);
40
+ }
41
+ /**
42
+ * Register a new agent adapter
43
+ * Used for dynamic registration or testing
44
+ * @param adapter - Agent adapter to register
45
+ */
46
+ export function registerAgent(adapter) {
47
+ // Check if already registered
48
+ const exists = agents.find((a) => a.id === adapter.id);
49
+ if (exists) {
50
+ throw new Error(`Agent ${adapter.id} is already registered`);
51
+ }
52
+ agents.push(adapter);
53
+ }
54
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/agents/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,GAAmB;IAC9B,IAAI,eAAe,EAAE;IACrB,IAAI,kBAAkB,EAAE;IACxB,IAAI,UAAU,EAAE;IAChB,IAAI,WAAW,EAAE;IACjB,IAAI,WAAW,EAAE;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACd,sBAAsB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,uBAAuB,iBAAiB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAChC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAqB;IAClD,8BAA8B;IAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,CAAC,EAAE,wBAAwB,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Agent Switchboard configuration loader and saver (TOML format)
3
+ * Manages the list of agents to apply MCP configs to
4
+ */
5
+ import { type AbsConfig } from "./schemas.js";
6
+ /**
7
+ * Loads the ABS configuration from ~/.agent-switchboard/config.toml
8
+ * Returns default empty agents list if file doesn't exist
9
+ *
10
+ * @returns {AbsConfig} Parsed and validated ABS configuration
11
+ * @throws {Error} If file exists but contains invalid TOML or fails schema validation
12
+ */
13
+ export declare function loadAbsConfig(): AbsConfig;
14
+ /**
15
+ * Saves the ABS configuration to ~/.agent-switchboard/config.toml
16
+ * Creates directory and file if they don't exist
17
+ *
18
+ * @param {AbsConfig} config - Configuration to save
19
+ * @throws {Error} If config fails schema validation or write operation fails
20
+ */
21
+ export declare function saveAbsConfig(config: AbsConfig): void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Agent Switchboard configuration loader and saver (TOML format)
3
+ * Manages the list of agents to apply MCP configs to
4
+ */
5
+ import fs from "node:fs";
6
+ import { parse, stringify } from "@iarna/toml";
7
+ import { absConfigSchema } from "./schemas.js";
8
+ import { getAbsConfigPath, getConfigDir } from "./paths.js";
9
+ /**
10
+ * Loads the ABS configuration from ~/.agent-switchboard/config.toml
11
+ * Returns default empty agents list if file doesn't exist
12
+ *
13
+ * @returns {AbsConfig} Parsed and validated ABS configuration
14
+ * @throws {Error} If file exists but contains invalid TOML or fails schema validation
15
+ */
16
+ export function loadAbsConfig() {
17
+ const configPath = getAbsConfigPath();
18
+ // Return default config if file doesn't exist
19
+ if (!fs.existsSync(configPath)) {
20
+ return { agents: [] };
21
+ }
22
+ try {
23
+ // Read file content
24
+ const content = fs.readFileSync(configPath, "utf-8");
25
+ // Parse TOML
26
+ const parsed = parse(content);
27
+ // Validate against Zod schema
28
+ const validated = absConfigSchema.parse(parsed);
29
+ return validated;
30
+ }
31
+ catch (error) {
32
+ if (error instanceof Error) {
33
+ throw new Error(`Failed to load ABS config from ${configPath}: ${error.message}`);
34
+ }
35
+ throw error;
36
+ }
37
+ }
38
+ /**
39
+ * Saves the ABS configuration to ~/.agent-switchboard/config.toml
40
+ * Creates directory and file if they don't exist
41
+ *
42
+ * @param {AbsConfig} config - Configuration to save
43
+ * @throws {Error} If config fails schema validation or write operation fails
44
+ */
45
+ export function saveAbsConfig(config) {
46
+ const configPath = getAbsConfigPath();
47
+ const configDir = getConfigDir();
48
+ try {
49
+ // Validate config against schema before saving
50
+ const validated = absConfigSchema.parse(config);
51
+ // Ensure directory exists
52
+ if (!fs.existsSync(configDir)) {
53
+ fs.mkdirSync(configDir, { recursive: true });
54
+ }
55
+ // Stringify to TOML format
56
+ const content = stringify(validated);
57
+ // Write to file
58
+ fs.writeFileSync(configPath, content, "utf-8");
59
+ }
60
+ catch (error) {
61
+ if (error instanceof Error) {
62
+ throw new Error(`Failed to save ABS config to ${configPath}: ${error.message}`);
63
+ }
64
+ throw error;
65
+ }
66
+ }
67
+ //# sourceMappingURL=abs-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abs-config.js","sourceRoot":"","sources":["../../src/config/abs-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAkB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,aAAa;IAC5B,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IAEtC,8CAA8C;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACJ,oBAAoB;QACpB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAErD,aAAa;QACb,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAE9B,8BAA8B;QAC9B,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEhD,OAAO,SAAS,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kCAAkC,UAAU,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC9C,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,IAAI,CAAC;QACJ,+CAA+C;QAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEhD,0BAA0B;QAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAErC,gBAAgB;QAChB,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,gCAAgC,UAAU,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * MCP configuration loader and saver with JSONC support
3
+ * Preserves comments and unknown fields when reading/writing mcp.json
4
+ */
5
+ import { type McpConfig } from "./schemas.js";
6
+ /**
7
+ * Loads the MCP configuration from ~/.agent-switchboard/mcp.json
8
+ * Parses JSONC (JSON with comments) format
9
+ * Returns default empty config if file doesn't exist
10
+ * Auto-adds missing enable flags and saves the file
11
+ *
12
+ * @returns {McpConfig} Parsed and validated MCP configuration
13
+ * @throws {Error} If file exists but contains invalid JSON or fails schema validation
14
+ */
15
+ export declare function loadMcpConfig(): McpConfig;
16
+ /**
17
+ * Saves the MCP configuration to ~/.agent-switchboard/mcp.json
18
+ * Preserves comments and formatting when modifying existing files
19
+ * Creates directory and file if they don't exist
20
+ *
21
+ * @param {McpConfig} config - Configuration to save
22
+ * @throws {Error} If config fails schema validation or write operation fails
23
+ */
24
+ export declare function saveMcpConfig(config: McpConfig): void;
25
+ /**
26
+ * Updates enable flags for MCP servers based on selection
27
+ * Preserves comments and unknown fields
28
+ *
29
+ * @param {string[]} enabledServerNames - Array of server names to enable
30
+ */
31
+ export declare function updateEnableFlags(enabledServerNames: string[]): void;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * MCP configuration loader and saver with JSONC support
3
+ * Preserves comments and unknown fields when reading/writing mcp.json
4
+ */
5
+ import fs from "node:fs";
6
+ import { parse } from "jsonc-parser";
7
+ import { getConfigDir, getMcpConfigPath } from "./paths.js";
8
+ import { mcpConfigSchema } from "./schemas.js";
9
+ /**
10
+ * Loads the MCP configuration from ~/.agent-switchboard/mcp.json
11
+ * Parses JSONC (JSON with comments) format
12
+ * Returns default empty config if file doesn't exist
13
+ * Auto-adds missing enable flags and saves the file
14
+ *
15
+ * @returns {McpConfig} Parsed and validated MCP configuration
16
+ * @throws {Error} If file exists but contains invalid JSON or fails schema validation
17
+ */
18
+ export function loadMcpConfig() {
19
+ const configPath = getMcpConfigPath();
20
+ // Return default config if file doesn't exist
21
+ if (!fs.existsSync(configPath)) {
22
+ return { mcpServers: {} };
23
+ }
24
+ try {
25
+ // Read file content
26
+ const content = fs.readFileSync(configPath, "utf-8");
27
+ // Parse JSONC (preserves comments in the parser's internal state)
28
+ const parsed = parse(content);
29
+ // Validate against Zod schema (adds default enable: true if missing)
30
+ const validated = mcpConfigSchema.parse(parsed);
31
+ // Check if any server was missing enable flag
32
+ let needsSave = false;
33
+ if (parsed.mcpServers) {
34
+ for (const [_, server] of Object.entries(parsed.mcpServers)) {
35
+ if (typeof server?.enable === "undefined") {
36
+ needsSave = true;
37
+ break;
38
+ }
39
+ }
40
+ }
41
+ // Save back if defaults were added
42
+ if (needsSave) {
43
+ saveMcpConfig(validated);
44
+ }
45
+ return validated;
46
+ }
47
+ catch (error) {
48
+ if (error instanceof Error) {
49
+ throw new Error(`Failed to load MCP config from ${configPath}: ${error.message}`);
50
+ }
51
+ throw error;
52
+ }
53
+ }
54
+ /**
55
+ * Saves the MCP configuration to ~/.agent-switchboard/mcp.json
56
+ * Preserves comments and formatting when modifying existing files
57
+ * Creates directory and file if they don't exist
58
+ *
59
+ * @param {McpConfig} config - Configuration to save
60
+ * @throws {Error} If config fails schema validation or write operation fails
61
+ */
62
+ export function saveMcpConfig(config) {
63
+ const configPath = getMcpConfigPath();
64
+ const configDir = getConfigDir();
65
+ try {
66
+ // Validate config against schema before saving
67
+ const validated = mcpConfigSchema.parse(config);
68
+ // Ensure directory exists
69
+ if (!fs.existsSync(configDir)) {
70
+ fs.mkdirSync(configDir, { recursive: true });
71
+ }
72
+ // Pretty print with 4 spaces; do not preserve comments; ensure trailing newline
73
+ const json = JSON.stringify(validated, null, 4) + "\n";
74
+ fs.writeFileSync(configPath, json, "utf-8");
75
+ }
76
+ catch (error) {
77
+ if (error instanceof Error) {
78
+ throw new Error(`Failed to save MCP config to ${configPath}: ${error.message}`);
79
+ }
80
+ throw error;
81
+ }
82
+ }
83
+ /**
84
+ * Updates enable flags for MCP servers based on selection
85
+ * Preserves comments and unknown fields
86
+ *
87
+ * @param {string[]} enabledServerNames - Array of server names to enable
88
+ */
89
+ export function updateEnableFlags(enabledServerNames) {
90
+ const config = loadMcpConfig();
91
+ const enabledSet = new Set(enabledServerNames);
92
+ // Update enable flag for each server
93
+ for (const [name, server] of Object.entries(config.mcpServers)) {
94
+ server.enable = enabledSet.has(name);
95
+ }
96
+ saveMcpConfig(config);
97
+ }
98
+ //# sourceMappingURL=mcp-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-config.js","sourceRoot":"","sources":["../../src/config/mcp-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Path utilities for Agent Switchboard configuration files
3
+ * Provides cross-platform path resolution for config files under ~/.agent-switchboard
4
+ */
5
+ /**
6
+ * Returns the absolute path to the Agent Switchboard config directory
7
+ * Cross-platform compatible: works on macOS, Linux, and Windows
8
+ *
9
+ * @returns {string} Absolute path to ~/.agent-switchboard
10
+ * @example
11
+ * // macOS/Linux: /Users/username/.agent-switchboard
12
+ * // Windows: C:\Users\username\.agent-switchboard
13
+ */
14
+ export declare function getConfigDir(): string;
15
+ /**
16
+ * Returns the absolute path to the MCP config file (mcp.json)
17
+ * This file stores all MCP server configurations with enable flags
18
+ *
19
+ * @returns {string} Absolute path to ~/.agent-switchboard/mcp.json
20
+ */
21
+ export declare function getMcpConfigPath(): string;
22
+ /**
23
+ * Returns the absolute path to the Agent Switchboard config file (config.toml)
24
+ * This file stores the list of agents to apply MCP configs to
25
+ *
26
+ * @returns {string} Absolute path to ~/.agent-switchboard/config.toml
27
+ */
28
+ export declare function getSwitchboardConfigPath(): string;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Path utilities for Agent Switchboard configuration files
3
+ * Provides cross-platform path resolution for config files under ~/.agent-switchboard
4
+ */
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ /**
8
+ * Returns the absolute path to the Agent Switchboard config directory
9
+ * Cross-platform compatible: works on macOS, Linux, and Windows
10
+ *
11
+ * @returns {string} Absolute path to ~/.agent-switchboard
12
+ * @example
13
+ * // macOS/Linux: /Users/username/.agent-switchboard
14
+ * // Windows: C:\Users\username\.agent-switchboard
15
+ */
16
+ export function getConfigDir() {
17
+ // Redesigned semantics:
18
+ // - ASB_HOME now points directly to the Switchboard config directory (i.e., replaces ~/.agent-switchboard)
19
+ // - If not set, default to os.homedir()/.agent-switchboard
20
+ const asbHome = process.env.ASB_HOME?.trim();
21
+ if (asbHome && asbHome.length > 0)
22
+ return asbHome;
23
+ return path.join(os.homedir(), ".agent-switchboard");
24
+ }
25
+ /**
26
+ * Returns the absolute path to the MCP config file (mcp.json)
27
+ * This file stores all MCP server configurations with enable flags
28
+ *
29
+ * @returns {string} Absolute path to ~/.agent-switchboard/mcp.json
30
+ */
31
+ export function getMcpConfigPath() {
32
+ return path.join(getConfigDir(), "mcp.json");
33
+ }
34
+ /**
35
+ * Returns the absolute path to the Agent Switchboard config file (config.toml)
36
+ * This file stores the list of agents to apply MCP configs to
37
+ *
38
+ * @returns {string} Absolute path to ~/.agent-switchboard/config.toml
39
+ */
40
+ export function getSwitchboardConfigPath() {
41
+ return path.join(getConfigDir(), "config.toml");
42
+ }
43
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IACxB,wBAAwB;IACxB,2GAA2G;IAC3G,2DAA2D;IAC3D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC7C,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Zod schemas for configuration validation
3
+ */
4
+ import { z } from "zod";
5
+ /**
6
+ * Schema for MCP server configuration
7
+ * Allows both command-based and URL-based servers
8
+ * Preserves unknown fields for forward compatibility
9
+ */
10
+ export declare const mcpServerSchema: z.ZodObject<{
11
+ command: z.ZodOptional<z.ZodString>;
12
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
13
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
14
+ url: z.ZodOptional<z.ZodString>;
15
+ enable: z.ZodDefault<z.ZodBoolean>;
16
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
17
+ command: z.ZodOptional<z.ZodString>;
18
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
19
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
20
+ url: z.ZodOptional<z.ZodString>;
21
+ enable: z.ZodDefault<z.ZodBoolean>;
22
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
23
+ command: z.ZodOptional<z.ZodString>;
24
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
26
+ url: z.ZodOptional<z.ZodString>;
27
+ enable: z.ZodDefault<z.ZodBoolean>;
28
+ }, z.ZodTypeAny, "passthrough">>;
29
+ /**
30
+ * Schema for MCP configuration file (~/.agent-switchboard/mcp.json)
31
+ */
32
+ export declare const mcpConfigSchema: z.ZodObject<{
33
+ mcpServers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
34
+ command: z.ZodOptional<z.ZodString>;
35
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
36
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
37
+ url: z.ZodOptional<z.ZodString>;
38
+ enable: z.ZodDefault<z.ZodBoolean>;
39
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
40
+ command: z.ZodOptional<z.ZodString>;
41
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
42
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
43
+ url: z.ZodOptional<z.ZodString>;
44
+ enable: z.ZodDefault<z.ZodBoolean>;
45
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
46
+ command: z.ZodOptional<z.ZodString>;
47
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
48
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
49
+ url: z.ZodOptional<z.ZodString>;
50
+ enable: z.ZodDefault<z.ZodBoolean>;
51
+ }, z.ZodTypeAny, "passthrough">>>>;
52
+ }, "strip", z.ZodTypeAny, {
53
+ mcpServers: Record<string, z.objectOutputType<{
54
+ command: z.ZodOptional<z.ZodString>;
55
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
56
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
57
+ url: z.ZodOptional<z.ZodString>;
58
+ enable: z.ZodDefault<z.ZodBoolean>;
59
+ }, z.ZodTypeAny, "passthrough">>;
60
+ }, {
61
+ mcpServers?: Record<string, z.objectInputType<{
62
+ command: z.ZodOptional<z.ZodString>;
63
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
64
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
65
+ url: z.ZodOptional<z.ZodString>;
66
+ enable: z.ZodDefault<z.ZodBoolean>;
67
+ }, z.ZodTypeAny, "passthrough">> | undefined;
68
+ }>;
69
+ /**
70
+ * Schema for Agent Switchboard configuration file (~/.agent-switchboard/config.toml)
71
+ */
72
+ export declare const switchboardConfigSchema: z.ZodObject<{
73
+ agents: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
74
+ }, "strip", z.ZodTypeAny, {
75
+ agents: string[];
76
+ }, {
77
+ agents?: string[] | undefined;
78
+ }>;
79
+ /**
80
+ * Infer TypeScript types from schemas
81
+ */
82
+ export type McpServer = z.infer<typeof mcpServerSchema>;
83
+ export type McpConfig = z.infer<typeof mcpConfigSchema>;
84
+ export type SwitchboardConfig = z.infer<typeof switchboardConfigSchema>;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Zod schemas for configuration validation
3
+ */
4
+ import { z } from "zod";
5
+ /**
6
+ * Schema for MCP server configuration
7
+ * Allows both command-based and URL-based servers
8
+ * Preserves unknown fields for forward compatibility
9
+ */
10
+ export const mcpServerSchema = z
11
+ .object({
12
+ command: z.string().optional(),
13
+ args: z.array(z.string()).optional(),
14
+ env: z.record(z.string()).optional(),
15
+ url: z.string().url().optional(),
16
+ enable: z.boolean().default(true),
17
+ })
18
+ .passthrough(); // Allow unknown fields
19
+ /**
20
+ * Schema for MCP configuration file (~/.agent-switchboard/mcp.json)
21
+ */
22
+ export const mcpConfigSchema = z.object({
23
+ mcpServers: z.record(z.string(), mcpServerSchema).default({}),
24
+ });
25
+ /**
26
+ * Schema for Agent Switchboard configuration file (~/.agent-switchboard/config.toml)
27
+ */
28
+ export const switchboardConfigSchema = z.object({
29
+ agents: z.array(z.string()).default([]),
30
+ });
31
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/config/schemas.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC;KAC9B,MAAM,CAAC;IACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACjC,CAAC;KACD,WAAW,EAAE,CAAC,CAAC,uBAAuB;AAExC;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC7D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACvC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Agent Switchboard configuration loader and saver (TOML format)
3
+ * Manages the list of agents to apply MCP configs to
4
+ */
5
+ import { type SwitchboardConfig } from "./schemas.js";
6
+ /**
7
+ * Loads the Agent Switchboard configuration from ~/.agent-switchboard/config.toml
8
+ * Returns default empty agents list if file doesn't exist
9
+ *
10
+ * @returns {SwitchboardConfig} Parsed and validated configuration
11
+ * @throws {Error} If file exists but contains invalid TOML or fails schema validation
12
+ */
13
+ export declare function loadSwitchboardConfig(): SwitchboardConfig;
14
+ /**
15
+ * Saves the Agent Switchboard configuration to ~/.agent-switchboard/config.toml
16
+ * Creates directory and file if they don't exist
17
+ *
18
+ * @param {SwitchboardConfig} config - Configuration to save
19
+ * @throws {Error} If config fails schema validation or write operation fails
20
+ */
21
+ export declare function saveSwitchboardConfig(config: SwitchboardConfig): void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Agent Switchboard configuration loader and saver (TOML format)
3
+ * Manages the list of agents to apply MCP configs to
4
+ */
5
+ import fs from "node:fs";
6
+ import { parse, stringify } from "@iarna/toml";
7
+ import { getConfigDir, getSwitchboardConfigPath } from "./paths.js";
8
+ import { switchboardConfigSchema } from "./schemas.js";
9
+ /**
10
+ * Loads the Agent Switchboard configuration from ~/.agent-switchboard/config.toml
11
+ * Returns default empty agents list if file doesn't exist
12
+ *
13
+ * @returns {SwitchboardConfig} Parsed and validated configuration
14
+ * @throws {Error} If file exists but contains invalid TOML or fails schema validation
15
+ */
16
+ export function loadSwitchboardConfig() {
17
+ const configPath = getSwitchboardConfigPath();
18
+ // Return default config if file doesn't exist
19
+ if (!fs.existsSync(configPath)) {
20
+ return { agents: [] };
21
+ }
22
+ try {
23
+ // Read file content
24
+ const content = fs.readFileSync(configPath, "utf-8");
25
+ // Parse TOML
26
+ const parsed = parse(content);
27
+ // Validate against Zod schema
28
+ const validated = switchboardConfigSchema.parse(parsed);
29
+ return validated;
30
+ }
31
+ catch (error) {
32
+ if (error instanceof Error) {
33
+ throw new Error(`Failed to load Agent Switchboard config from ${configPath}: ${error.message}`);
34
+ }
35
+ throw error;
36
+ }
37
+ }
38
+ /**
39
+ * Saves the Agent Switchboard configuration to ~/.agent-switchboard/config.toml
40
+ * Creates directory and file if they don't exist
41
+ *
42
+ * @param {SwitchboardConfig} config - Configuration to save
43
+ * @throws {Error} If config fails schema validation or write operation fails
44
+ */
45
+ export function saveSwitchboardConfig(config) {
46
+ const configPath = getSwitchboardConfigPath();
47
+ const configDir = getConfigDir();
48
+ try {
49
+ // Validate config against schema before saving
50
+ const validated = switchboardConfigSchema.parse(config);
51
+ // Ensure directory exists
52
+ if (!fs.existsSync(configDir)) {
53
+ fs.mkdirSync(configDir, { recursive: true });
54
+ }
55
+ // Stringify to TOML format
56
+ const content = stringify(validated);
57
+ // Write to file
58
+ fs.writeFileSync(configPath, content, "utf-8");
59
+ }
60
+ catch (error) {
61
+ if (error instanceof Error) {
62
+ throw new Error(`Failed to save Agent Switchboard config to ${configPath}: ${error.message}`);
63
+ }
64
+ throw error;
65
+ }
66
+ }
67
+ //# sourceMappingURL=switchboard-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switchboard-config.js","sourceRoot":"","sources":["../../src/config/switchboard-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAA0B,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB;IACpC,MAAM,UAAU,GAAG,wBAAwB,EAAE,CAAC;IAE9C,8CAA8C;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACJ,oBAAoB;QACpB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAErD,aAAa;QACb,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAE9B,8BAA8B;QAC9B,MAAM,SAAS,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAExD,OAAO,SAAS,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACd,gDAAgD,UAAU,KAAK,KAAK,CAAC,OAAO,EAAE,CAC9E,CAAC;QACH,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAyB;IAC9D,MAAM,UAAU,GAAG,wBAAwB,EAAE,CAAC;IAC9C,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,IAAI,CAAC;QACJ,+CAA+C;QAC/C,MAAM,SAAS,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAExD,0BAA0B;QAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAErC,gBAAgB;QAChB,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,8CAA8C,UAAU,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent Switchboard CLI Entry Point
4
+ * Unified MCP server manager for AI coding agents
5
+ */
6
+ export {};