skiller 0.4.3
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/LICENSE +21 -0
- package/README.md +989 -0
- package/dist/agents/AbstractAgent.js +92 -0
- package/dist/agents/AgentsMdAgent.js +85 -0
- package/dist/agents/AiderAgent.js +108 -0
- package/dist/agents/AmazonQCliAgent.js +103 -0
- package/dist/agents/AmpAgent.js +13 -0
- package/dist/agents/AugmentCodeAgent.js +70 -0
- package/dist/agents/ClaudeAgent.js +95 -0
- package/dist/agents/ClineAgent.js +53 -0
- package/dist/agents/CodexCliAgent.js +143 -0
- package/dist/agents/CopilotAgent.js +43 -0
- package/dist/agents/CrushAgent.js +128 -0
- package/dist/agents/CursorAgent.js +93 -0
- package/dist/agents/FirebaseAgent.js +61 -0
- package/dist/agents/FirebenderAgent.js +205 -0
- package/dist/agents/GeminiCliAgent.js +99 -0
- package/dist/agents/GooseAgent.js +58 -0
- package/dist/agents/IAgent.js +2 -0
- package/dist/agents/JulesAgent.js +14 -0
- package/dist/agents/JunieAgent.js +53 -0
- package/dist/agents/KiloCodeAgent.js +63 -0
- package/dist/agents/KiroAgent.js +50 -0
- package/dist/agents/OpenCodeAgent.js +99 -0
- package/dist/agents/OpenHandsAgent.js +56 -0
- package/dist/agents/QwenCodeAgent.js +82 -0
- package/dist/agents/RooCodeAgent.js +139 -0
- package/dist/agents/TraeAgent.js +54 -0
- package/dist/agents/WarpAgent.js +61 -0
- package/dist/agents/WindsurfAgent.js +27 -0
- package/dist/agents/ZedAgent.js +132 -0
- package/dist/agents/agent-utils.js +37 -0
- package/dist/agents/index.js +77 -0
- package/dist/cli/commands.js +136 -0
- package/dist/cli/handlers.js +221 -0
- package/dist/cli/index.js +5 -0
- package/dist/constants.js +58 -0
- package/dist/core/ConfigLoader.js +274 -0
- package/dist/core/FileSystemUtils.js +421 -0
- package/dist/core/FrontmatterParser.js +142 -0
- package/dist/core/GitignoreUtils.js +171 -0
- package/dist/core/RuleProcessor.js +60 -0
- package/dist/core/SkillsProcessor.js +528 -0
- package/dist/core/SkillsUtils.js +230 -0
- package/dist/core/UnifiedConfigLoader.js +432 -0
- package/dist/core/UnifiedConfigTypes.js +2 -0
- package/dist/core/agent-selection.js +52 -0
- package/dist/core/apply-engine.js +668 -0
- package/dist/core/config-utils.js +30 -0
- package/dist/core/hash.js +24 -0
- package/dist/core/revert-engine.js +413 -0
- package/dist/lib.js +196 -0
- package/dist/mcp/capabilities.js +65 -0
- package/dist/mcp/merge.js +39 -0
- package/dist/mcp/propagateOpenCodeMcp.js +116 -0
- package/dist/mcp/propagateOpenHandsMcp.js +169 -0
- package/dist/mcp/validate.js +17 -0
- package/dist/paths/mcp.js +120 -0
- package/dist/revert.js +186 -0
- package/dist/types.js +2 -0
- package/dist/vscode/settings.js +117 -0
- package/package.json +77 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.RooCodeAgent = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const fs_1 = require("fs");
|
|
39
|
+
const AgentsMdAgent_1 = require("./AgentsMdAgent");
|
|
40
|
+
const FileSystemUtils_1 = require("../core/FileSystemUtils");
|
|
41
|
+
/**
|
|
42
|
+
* Agent for RooCode that writes to AGENTS.md and generates .roo/mcp.json
|
|
43
|
+
* with project-level MCP server configuration.
|
|
44
|
+
*/
|
|
45
|
+
class RooCodeAgent {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.agentsMdAgent = new AgentsMdAgent_1.AgentsMdAgent();
|
|
48
|
+
}
|
|
49
|
+
getIdentifier() {
|
|
50
|
+
return 'roo';
|
|
51
|
+
}
|
|
52
|
+
getName() {
|
|
53
|
+
return 'RooCode';
|
|
54
|
+
}
|
|
55
|
+
getDefaultOutputPath(projectRoot) {
|
|
56
|
+
return {
|
|
57
|
+
instructions: path.join(projectRoot, 'AGENTS.md'),
|
|
58
|
+
mcp: path.join(projectRoot, '.roo', 'mcp.json'),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async applyRulerConfig(concatenatedRules, projectRoot, rulerMcpJson, agentConfig, backup = true) {
|
|
62
|
+
// First perform idempotent AGENTS.md write via composed AgentsMdAgent
|
|
63
|
+
await this.agentsMdAgent.applyRulerConfig(concatenatedRules, projectRoot, null, {
|
|
64
|
+
// Preserve explicit outputPath precedence semantics if provided.
|
|
65
|
+
outputPath: agentConfig?.outputPath ||
|
|
66
|
+
agentConfig?.outputPathInstructions ||
|
|
67
|
+
undefined,
|
|
68
|
+
}, backup);
|
|
69
|
+
// Now handle .roo/mcp.json configuration
|
|
70
|
+
const outputPaths = this.getDefaultOutputPath(projectRoot);
|
|
71
|
+
const mcpPath = path.resolve(projectRoot, agentConfig?.outputPathConfig ?? outputPaths['mcp']);
|
|
72
|
+
await (0, FileSystemUtils_1.ensureDirExists)(path.dirname(mcpPath));
|
|
73
|
+
// Create base structure with mcpServers
|
|
74
|
+
let finalMcpConfig = {
|
|
75
|
+
mcpServers: {},
|
|
76
|
+
};
|
|
77
|
+
// Try to read existing .roo/mcp.json
|
|
78
|
+
let existingConfig = {};
|
|
79
|
+
try {
|
|
80
|
+
const existingContent = await fs_1.promises.readFile(mcpPath, 'utf-8');
|
|
81
|
+
const parsed = JSON.parse(existingContent);
|
|
82
|
+
if (parsed && typeof parsed === 'object') {
|
|
83
|
+
existingConfig = parsed;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// File doesn't exist or invalid JSON - start fresh
|
|
88
|
+
existingConfig = {};
|
|
89
|
+
}
|
|
90
|
+
// Merge MCP servers if we have ruler config
|
|
91
|
+
if (rulerMcpJson?.mcpServers) {
|
|
92
|
+
const existingServers = existingConfig.mcpServers || {};
|
|
93
|
+
const newServers = rulerMcpJson.mcpServers;
|
|
94
|
+
// Shallow merge: new servers override existing with same name
|
|
95
|
+
finalMcpConfig = {
|
|
96
|
+
mcpServers: {
|
|
97
|
+
...existingServers,
|
|
98
|
+
...newServers,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
else if (existingConfig.mcpServers) {
|
|
103
|
+
// Keep existing servers if no new ones to add
|
|
104
|
+
finalMcpConfig = {
|
|
105
|
+
mcpServers: existingConfig.mcpServers,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// If neither condition is met, finalMcpConfig remains { mcpServers: {} }
|
|
109
|
+
// Write the config file with pretty JSON (2 spaces)
|
|
110
|
+
const newContent = JSON.stringify(finalMcpConfig, null, 2);
|
|
111
|
+
// Check if content has changed for idempotency
|
|
112
|
+
let existingContent = null;
|
|
113
|
+
try {
|
|
114
|
+
existingContent = await fs_1.promises.readFile(mcpPath, 'utf8');
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
existingContent = null;
|
|
118
|
+
}
|
|
119
|
+
if (existingContent !== null && existingContent === newContent) {
|
|
120
|
+
// No change; skip backup/write for idempotency
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Backup (only if file existed and backup is enabled) then write new content
|
|
124
|
+
if (backup) {
|
|
125
|
+
await (0, FileSystemUtils_1.backupFile)(mcpPath);
|
|
126
|
+
}
|
|
127
|
+
await (0, FileSystemUtils_1.writeGeneratedFile)(mcpPath, newContent);
|
|
128
|
+
}
|
|
129
|
+
supportsMcpStdio() {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
supportsMcpRemote() {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
getMcpServerKey() {
|
|
136
|
+
return 'mcpServers';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.RooCodeAgent = RooCodeAgent;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TraeAgent = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const AbstractAgent_1 = require("./AbstractAgent");
|
|
39
|
+
/**
|
|
40
|
+
* Trae AI agent adapter.
|
|
41
|
+
* Generates project_rules.md configuration file.
|
|
42
|
+
*/
|
|
43
|
+
class TraeAgent extends AbstractAgent_1.AbstractAgent {
|
|
44
|
+
getIdentifier() {
|
|
45
|
+
return 'trae';
|
|
46
|
+
}
|
|
47
|
+
getName() {
|
|
48
|
+
return 'Trae AI';
|
|
49
|
+
}
|
|
50
|
+
getDefaultOutputPath(projectRoot) {
|
|
51
|
+
return path.join(projectRoot, '.trae', 'rules', 'project_rules.md');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.TraeAgent = TraeAgent;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.WarpAgent = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const AbstractAgent_1 = require("./AbstractAgent");
|
|
39
|
+
/**
|
|
40
|
+
* Warp Agent Mode adapter.
|
|
41
|
+
* Generates WARP.md configuration file in the project root.
|
|
42
|
+
*/
|
|
43
|
+
class WarpAgent extends AbstractAgent_1.AbstractAgent {
|
|
44
|
+
getIdentifier() {
|
|
45
|
+
return 'warp';
|
|
46
|
+
}
|
|
47
|
+
getName() {
|
|
48
|
+
return 'Warp';
|
|
49
|
+
}
|
|
50
|
+
getDefaultOutputPath(projectRoot) {
|
|
51
|
+
return path.join(projectRoot, 'WARP.md');
|
|
52
|
+
}
|
|
53
|
+
// Warp does not support MCP servers
|
|
54
|
+
supportsMcpStdio() {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
supportsMcpRemote() {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.WarpAgent = WarpAgent;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WindsurfAgent = void 0;
|
|
4
|
+
const AgentsMdAgent_1 = require("./AgentsMdAgent");
|
|
5
|
+
/**
|
|
6
|
+
* Windsurf agent adapter.
|
|
7
|
+
* Now uses AGENTS.md format like other agents.
|
|
8
|
+
*/
|
|
9
|
+
class WindsurfAgent extends AgentsMdAgent_1.AgentsMdAgent {
|
|
10
|
+
getIdentifier() {
|
|
11
|
+
return 'windsurf';
|
|
12
|
+
}
|
|
13
|
+
getName() {
|
|
14
|
+
return 'Windsurf';
|
|
15
|
+
}
|
|
16
|
+
// Windsurf supports MCP configuration
|
|
17
|
+
getMcpServerKey() {
|
|
18
|
+
return 'mcpServers';
|
|
19
|
+
}
|
|
20
|
+
supportsMcpStdio() {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
supportsMcpRemote() {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.WindsurfAgent = WindsurfAgent;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ZedAgent = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const fs_1 = require("fs");
|
|
39
|
+
const AgentsMdAgent_1 = require("./AgentsMdAgent");
|
|
40
|
+
/**
|
|
41
|
+
* Zed editor agent adapter.
|
|
42
|
+
* Inherits from AgentsMdAgent to write instructions to AGENTS.md and handles
|
|
43
|
+
* MCP server configuration in .zed/settings.json at the project root.
|
|
44
|
+
*/
|
|
45
|
+
class ZedAgent extends AgentsMdAgent_1.AgentsMdAgent {
|
|
46
|
+
getIdentifier() {
|
|
47
|
+
return 'zed';
|
|
48
|
+
}
|
|
49
|
+
getName() {
|
|
50
|
+
return 'Zed';
|
|
51
|
+
}
|
|
52
|
+
async applyRulerConfig(concatenatedRules, projectRoot, rulerMcpJson, agentConfig) {
|
|
53
|
+
// First, perform idempotent AGENTS.md write via base class
|
|
54
|
+
await super.applyRulerConfig(concatenatedRules, projectRoot, null, {
|
|
55
|
+
outputPath: agentConfig?.outputPath,
|
|
56
|
+
});
|
|
57
|
+
// Handle MCP server configuration if enabled and provided
|
|
58
|
+
const mcpEnabled = agentConfig?.mcp?.enabled ?? true;
|
|
59
|
+
if (mcpEnabled && rulerMcpJson) {
|
|
60
|
+
const zedSettingsPath = path.join(projectRoot, '.zed', 'settings.json');
|
|
61
|
+
// Read existing settings
|
|
62
|
+
let existingSettings = {};
|
|
63
|
+
try {
|
|
64
|
+
const content = await fs_1.promises.readFile(zedSettingsPath, 'utf8');
|
|
65
|
+
existingSettings = JSON.parse(content);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error.code !== 'ENOENT') {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
// File doesn't exist, use empty settings
|
|
72
|
+
}
|
|
73
|
+
// Get the merge strategy
|
|
74
|
+
const strategy = agentConfig?.mcp?.strategy ?? 'merge';
|
|
75
|
+
// Handle merging based on strategy
|
|
76
|
+
let mergedSettings;
|
|
77
|
+
if (strategy === 'overwrite') {
|
|
78
|
+
// For overwrite, preserve all existing settings except MCP servers
|
|
79
|
+
mergedSettings = { ...existingSettings };
|
|
80
|
+
// Extract incoming MCP servers and transform them for Zed format
|
|
81
|
+
const incomingServers = rulerMcpJson.mcpServers || {};
|
|
82
|
+
const transformedServers = {};
|
|
83
|
+
for (const [serverName, serverConfig] of Object.entries(incomingServers)) {
|
|
84
|
+
transformedServers[serverName] = this.transformMcpServerForZed(serverConfig);
|
|
85
|
+
}
|
|
86
|
+
// Replace MCP servers completely
|
|
87
|
+
mergedSettings[this.getMcpServerKey()] = transformedServers;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// For merge strategy, preserve all existing settings
|
|
91
|
+
const baseServers = existingSettings[this.getMcpServerKey()] || {};
|
|
92
|
+
const incomingServers = rulerMcpJson.mcpServers || {};
|
|
93
|
+
// Transform incoming servers for Zed format
|
|
94
|
+
const transformedIncomingServers = {};
|
|
95
|
+
for (const [serverName, serverConfig] of Object.entries(incomingServers)) {
|
|
96
|
+
transformedIncomingServers[serverName] =
|
|
97
|
+
this.transformMcpServerForZed(serverConfig);
|
|
98
|
+
}
|
|
99
|
+
const mergedServers = { ...baseServers, ...transformedIncomingServers };
|
|
100
|
+
mergedSettings = {
|
|
101
|
+
...existingSettings,
|
|
102
|
+
[this.getMcpServerKey()]: mergedServers,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// Write updated settings
|
|
106
|
+
await fs_1.promises.mkdir(path.dirname(zedSettingsPath), { recursive: true });
|
|
107
|
+
await fs_1.promises.writeFile(zedSettingsPath, JSON.stringify(mergedSettings, null, 2));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
getMcpServerKey() {
|
|
111
|
+
return 'context_servers';
|
|
112
|
+
}
|
|
113
|
+
supportsMcpStdio() {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
supportsMcpRemote() {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Transform MCP server configuration from ruler format to Zed format.
|
|
121
|
+
* Converts "type": "stdio" to "source": "custom" and preserves other fields.
|
|
122
|
+
*/
|
|
123
|
+
transformMcpServerForZed(rulerServer) {
|
|
124
|
+
const transformedServer = { ...rulerServer };
|
|
125
|
+
// Remove "type" field if present
|
|
126
|
+
delete transformedServer.type;
|
|
127
|
+
// Add "source": "custom" as required by Zed
|
|
128
|
+
transformedServer.source = 'custom';
|
|
129
|
+
return transformedServer;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.ZedAgent = ZedAgent;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAgentOutputPaths = getAgentOutputPaths;
|
|
4
|
+
/**
|
|
5
|
+
* Gets all output paths for an agent, taking into account any config overrides.
|
|
6
|
+
*/
|
|
7
|
+
function getAgentOutputPaths(agent, projectRoot, agentConfig) {
|
|
8
|
+
const paths = [];
|
|
9
|
+
const defaults = agent.getDefaultOutputPath(projectRoot);
|
|
10
|
+
if (typeof defaults === 'string') {
|
|
11
|
+
// Single output path (most agents)
|
|
12
|
+
const actualPath = agentConfig?.outputPath ?? defaults;
|
|
13
|
+
paths.push(actualPath);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
// Multiple output paths (e.g., AiderAgent)
|
|
17
|
+
const defaultPaths = defaults;
|
|
18
|
+
// Handle instructions path
|
|
19
|
+
if ('instructions' in defaultPaths) {
|
|
20
|
+
const instructionsPath = agentConfig?.outputPathInstructions ?? defaultPaths.instructions;
|
|
21
|
+
paths.push(instructionsPath);
|
|
22
|
+
}
|
|
23
|
+
// Handle config path
|
|
24
|
+
if ('config' in defaultPaths) {
|
|
25
|
+
const configPath = agentConfig?.outputPathConfig ?? defaultPaths.config;
|
|
26
|
+
paths.push(configPath);
|
|
27
|
+
}
|
|
28
|
+
// Handle any other paths in the default paths record
|
|
29
|
+
for (const [key, defaultPath] of Object.entries(defaultPaths)) {
|
|
30
|
+
if (key !== 'instructions' && key !== 'config') {
|
|
31
|
+
// For unknown path types, use the default since we don't have specific config overrides
|
|
32
|
+
paths.push(defaultPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return paths;
|
|
37
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allAgents = exports.AbstractAgent = void 0;
|
|
4
|
+
exports.getAgentIdentifiersForCliHelp = getAgentIdentifiersForCliHelp;
|
|
5
|
+
const AbstractAgent_1 = require("./AbstractAgent");
|
|
6
|
+
Object.defineProperty(exports, "AbstractAgent", { enumerable: true, get: function () { return AbstractAgent_1.AbstractAgent; } });
|
|
7
|
+
const CopilotAgent_1 = require("./CopilotAgent");
|
|
8
|
+
const ClaudeAgent_1 = require("./ClaudeAgent");
|
|
9
|
+
const CodexCliAgent_1 = require("./CodexCliAgent");
|
|
10
|
+
const CursorAgent_1 = require("./CursorAgent");
|
|
11
|
+
const WindsurfAgent_1 = require("./WindsurfAgent");
|
|
12
|
+
const ClineAgent_1 = require("./ClineAgent");
|
|
13
|
+
const AiderAgent_1 = require("./AiderAgent");
|
|
14
|
+
const FirebaseAgent_1 = require("./FirebaseAgent");
|
|
15
|
+
const OpenHandsAgent_1 = require("./OpenHandsAgent");
|
|
16
|
+
const GeminiCliAgent_1 = require("./GeminiCliAgent");
|
|
17
|
+
const JulesAgent_1 = require("./JulesAgent");
|
|
18
|
+
const JunieAgent_1 = require("./JunieAgent");
|
|
19
|
+
const AugmentCodeAgent_1 = require("./AugmentCodeAgent");
|
|
20
|
+
const KiloCodeAgent_1 = require("./KiloCodeAgent");
|
|
21
|
+
const OpenCodeAgent_1 = require("./OpenCodeAgent");
|
|
22
|
+
const CrushAgent_1 = require("./CrushAgent");
|
|
23
|
+
const GooseAgent_1 = require("./GooseAgent");
|
|
24
|
+
const AmpAgent_1 = require("./AmpAgent");
|
|
25
|
+
const ZedAgent_1 = require("./ZedAgent");
|
|
26
|
+
const AgentsMdAgent_1 = require("./AgentsMdAgent");
|
|
27
|
+
const QwenCodeAgent_1 = require("./QwenCodeAgent");
|
|
28
|
+
const KiroAgent_1 = require("./KiroAgent");
|
|
29
|
+
const WarpAgent_1 = require("./WarpAgent");
|
|
30
|
+
const RooCodeAgent_1 = require("./RooCodeAgent");
|
|
31
|
+
const TraeAgent_1 = require("./TraeAgent");
|
|
32
|
+
const AmazonQCliAgent_1 = require("./AmazonQCliAgent");
|
|
33
|
+
const FirebenderAgent_1 = require("./FirebenderAgent");
|
|
34
|
+
exports.allAgents = [
|
|
35
|
+
new CopilotAgent_1.CopilotAgent(),
|
|
36
|
+
new ClaudeAgent_1.ClaudeAgent(),
|
|
37
|
+
new CodexCliAgent_1.CodexCliAgent(),
|
|
38
|
+
new CursorAgent_1.CursorAgent(),
|
|
39
|
+
new WindsurfAgent_1.WindsurfAgent(),
|
|
40
|
+
new ClineAgent_1.ClineAgent(),
|
|
41
|
+
new AiderAgent_1.AiderAgent(),
|
|
42
|
+
new FirebaseAgent_1.FirebaseAgent(),
|
|
43
|
+
new OpenHandsAgent_1.OpenHandsAgent(),
|
|
44
|
+
new GeminiCliAgent_1.GeminiCliAgent(),
|
|
45
|
+
new JulesAgent_1.JulesAgent(),
|
|
46
|
+
new JunieAgent_1.JunieAgent(),
|
|
47
|
+
new AugmentCodeAgent_1.AugmentCodeAgent(),
|
|
48
|
+
new KiloCodeAgent_1.KiloCodeAgent(),
|
|
49
|
+
new OpenCodeAgent_1.OpenCodeAgent(),
|
|
50
|
+
new GooseAgent_1.GooseAgent(),
|
|
51
|
+
new CrushAgent_1.CrushAgent(),
|
|
52
|
+
new AmpAgent_1.AmpAgent(),
|
|
53
|
+
new ZedAgent_1.ZedAgent(),
|
|
54
|
+
new QwenCodeAgent_1.QwenCodeAgent(),
|
|
55
|
+
new AgentsMdAgent_1.AgentsMdAgent(),
|
|
56
|
+
new KiroAgent_1.KiroAgent(),
|
|
57
|
+
new WarpAgent_1.WarpAgent(),
|
|
58
|
+
new RooCodeAgent_1.RooCodeAgent(),
|
|
59
|
+
new TraeAgent_1.TraeAgent(),
|
|
60
|
+
new AmazonQCliAgent_1.AmazonQCliAgent(),
|
|
61
|
+
new FirebenderAgent_1.FirebenderAgent(),
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Generates a comma-separated list of agent identifiers for CLI help text.
|
|
65
|
+
* Returns identifiers in alphabetical order, with 'agentsmd' always first.
|
|
66
|
+
*/
|
|
67
|
+
function getAgentIdentifiersForCliHelp() {
|
|
68
|
+
const identifiers = exports.allAgents.map((agent) => agent.getIdentifier());
|
|
69
|
+
const sorted = identifiers.sort();
|
|
70
|
+
// Ensure agentsmd is first (it should already be first alphabetically, but let's be explicit)
|
|
71
|
+
const agentsMdIndex = sorted.indexOf('agentsmd');
|
|
72
|
+
if (agentsMdIndex > 0) {
|
|
73
|
+
const agentsmd = sorted.splice(agentsMdIndex, 1)[0];
|
|
74
|
+
sorted.unshift(agentsmd);
|
|
75
|
+
}
|
|
76
|
+
return sorted.join(', ');
|
|
77
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.run = run;
|
|
7
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
8
|
+
const helpers_1 = require("yargs/helpers");
|
|
9
|
+
const handlers_1 = require("./handlers");
|
|
10
|
+
const index_1 = require("../agents/index");
|
|
11
|
+
/**
|
|
12
|
+
* Sets up and parses CLI commands.
|
|
13
|
+
*/
|
|
14
|
+
function run() {
|
|
15
|
+
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
16
|
+
.scriptName('ruler')
|
|
17
|
+
.usage('$0 <command> [options]')
|
|
18
|
+
.command('apply', 'Apply ruler configurations to supported AI agents', (y) => {
|
|
19
|
+
return y
|
|
20
|
+
.option('project-root', {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Project root directory',
|
|
23
|
+
default: process.cwd(),
|
|
24
|
+
})
|
|
25
|
+
.option('agents', {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
|
|
28
|
+
})
|
|
29
|
+
.option('config', {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'Path to TOML configuration file',
|
|
32
|
+
})
|
|
33
|
+
.option('mcp', {
|
|
34
|
+
type: 'boolean',
|
|
35
|
+
description: 'Enable or disable applying MCP server config',
|
|
36
|
+
default: true,
|
|
37
|
+
})
|
|
38
|
+
.alias('mcp', 'with-mcp')
|
|
39
|
+
.option('mcp-overwrite', {
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
description: 'Replace (not merge) the native MCP config(s)',
|
|
42
|
+
default: false,
|
|
43
|
+
})
|
|
44
|
+
.option('gitignore', {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
description: 'Enable/disable automatic .gitignore updates (default: enabled)',
|
|
47
|
+
})
|
|
48
|
+
.option('verbose', {
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
description: 'Enable verbose logging',
|
|
51
|
+
default: false,
|
|
52
|
+
})
|
|
53
|
+
.alias('verbose', 'v')
|
|
54
|
+
.option('dry-run', {
|
|
55
|
+
type: 'boolean',
|
|
56
|
+
description: 'Preview changes without writing files',
|
|
57
|
+
default: false,
|
|
58
|
+
})
|
|
59
|
+
.option('local-only', {
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
description: 'Only search for local .ruler directories, ignore global config',
|
|
62
|
+
default: false,
|
|
63
|
+
})
|
|
64
|
+
.option('nested', {
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
description: 'Enable nested rule loading from nested .ruler directories (default: from config or disabled)',
|
|
67
|
+
})
|
|
68
|
+
.option('backup', {
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
description: 'Enable/disable creation of .bak backup files (default: enabled)',
|
|
71
|
+
})
|
|
72
|
+
.option('skills', {
|
|
73
|
+
type: 'boolean',
|
|
74
|
+
description: 'Enable/disable skills support (experimental, default: enabled)',
|
|
75
|
+
});
|
|
76
|
+
}, handlers_1.applyHandler)
|
|
77
|
+
.command('init', 'Scaffold a .ruler directory with default files', (y) => {
|
|
78
|
+
return y
|
|
79
|
+
.option('project-root', {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'Project root directory',
|
|
82
|
+
default: process.cwd(),
|
|
83
|
+
})
|
|
84
|
+
.option('global', {
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
description: 'Initialize in global config directory (XDG_CONFIG_HOME/ruler)',
|
|
87
|
+
default: false,
|
|
88
|
+
})
|
|
89
|
+
.option('claude', {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
description: 'Use .claude directory instead of .ruler (for Claude Code users)',
|
|
92
|
+
default: false,
|
|
93
|
+
});
|
|
94
|
+
}, handlers_1.initHandler)
|
|
95
|
+
.command('revert', 'Revert ruler configurations from supported AI agents', (y) => {
|
|
96
|
+
return y
|
|
97
|
+
.option('project-root', {
|
|
98
|
+
type: 'string',
|
|
99
|
+
description: 'Project root directory',
|
|
100
|
+
default: process.cwd(),
|
|
101
|
+
})
|
|
102
|
+
.option('agents', {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
|
|
105
|
+
})
|
|
106
|
+
.option('config', {
|
|
107
|
+
type: 'string',
|
|
108
|
+
description: 'Path to TOML configuration file',
|
|
109
|
+
})
|
|
110
|
+
.option('keep-backups', {
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
description: 'Keep backup files after revert',
|
|
113
|
+
default: false,
|
|
114
|
+
})
|
|
115
|
+
.option('verbose', {
|
|
116
|
+
type: 'boolean',
|
|
117
|
+
description: 'Enable verbose logging',
|
|
118
|
+
default: false,
|
|
119
|
+
})
|
|
120
|
+
.alias('verbose', 'v')
|
|
121
|
+
.option('dry-run', {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
description: 'Preview changes without writing files',
|
|
124
|
+
default: false,
|
|
125
|
+
})
|
|
126
|
+
.option('local-only', {
|
|
127
|
+
type: 'boolean',
|
|
128
|
+
description: 'Only search for local .ruler directories, ignore global config',
|
|
129
|
+
default: false,
|
|
130
|
+
});
|
|
131
|
+
}, handlers_1.revertHandler)
|
|
132
|
+
.demandCommand(1, 'You need to specify a command')
|
|
133
|
+
.help()
|
|
134
|
+
.strict()
|
|
135
|
+
.parse();
|
|
136
|
+
}
|