rulesync 0.63.0 → 0.64.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 +15 -3
- package/dist/amazonqcli-WVGYACHI.js +9 -0
- package/dist/{augmentcode-HIZIQG2W.js → augmentcode-DTHPPXWO.js} +2 -2
- package/dist/{chunk-M7NL7G7A.js → chunk-4NAQ5HL4.js} +1 -1
- package/dist/{chunk-GQTMTBX4.js → chunk-6LSN7HSJ.js} +76 -4
- package/dist/chunk-DMTCLQ4T.js +17 -0
- package/dist/{chunk-YTU3SCQO.js → chunk-E2J3UBBK.js} +9 -3
- package/dist/{chunk-LXTA7DBA.js → chunk-EID75W45.js} +1 -1
- package/dist/{chunk-U4PLVMCG.js → chunk-FVPZQEWP.js} +1 -1
- package/dist/{chunk-NETSYSMD.js → chunk-HHJIL3YZ.js} +1 -1
- package/dist/{chunk-UEAYL4NT.js → chunk-JX55DU6Y.js} +1 -1
- package/dist/{chunk-KUGTKMNW.js → chunk-KKWJVA56.js} +5 -2
- package/dist/chunk-LURFNGH4.js +17 -0
- package/dist/{chunk-AUUSMVCT.js → chunk-LYVES5YR.js} +2 -0
- package/dist/{chunk-4PSTOKKD.js → chunk-TBXG53FV.js} +1 -1
- package/dist/{chunk-2CW2KFB3.js → chunk-TQOL7OKY.js} +1 -1
- package/dist/chunk-YPJW7Z5M.js +210 -0
- package/dist/{claudecode-YTEFACCT.js → claudecode-SSYLLUXX.js} +3 -3
- package/dist/{cline-CKNUDEA3.js → cline-5EUGKNZ6.js} +3 -3
- package/dist/{codexcli-7SDGYI7D.js → codexcli-IGM2ADYK.js} +3 -3
- package/dist/{copilot-MOR3HHJX.js → copilot-HSQO7ZCJ.js} +2 -2
- package/dist/{cursor-YJGH7W24.js → cursor-ZB3XNGBK.js} +3 -3
- package/dist/{geminicli-E7KZTZ2G.js → geminicli-FNRKH5GX.js} +3 -3
- package/dist/index.cjs +912 -504
- package/dist/index.js +647 -482
- package/dist/{junie-5LEQU4BO.js → junie-3YGOSOGF.js} +3 -3
- package/dist/{kiro-YDHXY2MA.js → kiro-B6WZNLY4.js} +2 -2
- package/dist/opencode-SZETJ62M.js +17 -0
- package/dist/{roo-L3QTTIPO.js → roo-KLTWVAKE.js} +3 -2
- package/dist/{windsurf-4P6HEUBV.js → windsurf-IZEKUAID.js} +3 -3
- package/package.json +2 -1
- package/dist/chunk-MDYDKNXQ.js +0 -61
- package/dist/chunk-PCATT4UZ.js +0 -78
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,7 @@ var init_tool_targets = __esm({
|
|
|
41
41
|
"use strict";
|
|
42
42
|
import_mini2 = require("zod/mini");
|
|
43
43
|
ALL_TOOL_TARGETS = [
|
|
44
|
+
"amazonqcli",
|
|
44
45
|
"augmentcode",
|
|
45
46
|
"augmentcode-legacy",
|
|
46
47
|
"copilot",
|
|
@@ -48,6 +49,7 @@ var init_tool_targets = __esm({
|
|
|
48
49
|
"cline",
|
|
49
50
|
"claudecode",
|
|
50
51
|
"codexcli",
|
|
52
|
+
"opencode",
|
|
51
53
|
"roo",
|
|
52
54
|
"geminicli",
|
|
53
55
|
"kiro",
|
|
@@ -61,6 +63,152 @@ var init_tool_targets = __esm({
|
|
|
61
63
|
}
|
|
62
64
|
});
|
|
63
65
|
|
|
66
|
+
// src/utils/logger.ts
|
|
67
|
+
var import_consola, Logger, logger;
|
|
68
|
+
var init_logger = __esm({
|
|
69
|
+
"src/utils/logger.ts"() {
|
|
70
|
+
"use strict";
|
|
71
|
+
import_consola = require("consola");
|
|
72
|
+
Logger = class {
|
|
73
|
+
_verbose = false;
|
|
74
|
+
console = import_consola.consola.withDefaults({
|
|
75
|
+
tag: "rulesync"
|
|
76
|
+
});
|
|
77
|
+
setVerbose(verbose) {
|
|
78
|
+
this._verbose = verbose;
|
|
79
|
+
}
|
|
80
|
+
get verbose() {
|
|
81
|
+
return this._verbose;
|
|
82
|
+
}
|
|
83
|
+
// Regular log (always shown, regardless of verbose)
|
|
84
|
+
log(message, ...args) {
|
|
85
|
+
this.console.log(message, ...args);
|
|
86
|
+
}
|
|
87
|
+
// Info level (shown only in verbose mode)
|
|
88
|
+
info(message, ...args) {
|
|
89
|
+
if (this._verbose) {
|
|
90
|
+
this.console.info(message, ...args);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Success (always shown)
|
|
94
|
+
success(message, ...args) {
|
|
95
|
+
this.console.success(message, ...args);
|
|
96
|
+
}
|
|
97
|
+
// Warning (always shown)
|
|
98
|
+
warn(message, ...args) {
|
|
99
|
+
this.console.warn(message, ...args);
|
|
100
|
+
}
|
|
101
|
+
// Error (always shown)
|
|
102
|
+
error(message, ...args) {
|
|
103
|
+
this.console.error(message, ...args);
|
|
104
|
+
}
|
|
105
|
+
// Debug level (shown only in verbose mode)
|
|
106
|
+
debug(message, ...args) {
|
|
107
|
+
if (this._verbose) {
|
|
108
|
+
this.console.debug(message, ...args);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
logger = new Logger();
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// src/utils/file.ts
|
|
117
|
+
async function ensureDir(dirPath) {
|
|
118
|
+
try {
|
|
119
|
+
await (0, import_promises2.stat)(dirPath);
|
|
120
|
+
} catch {
|
|
121
|
+
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function resolvePath(relativePath, baseDir) {
|
|
125
|
+
if (!baseDir) return relativePath;
|
|
126
|
+
const resolved = (0, import_node_path.resolve)(baseDir, relativePath);
|
|
127
|
+
const rel = (0, import_node_path.relative)(baseDir, resolved);
|
|
128
|
+
if (rel.startsWith("..") || (0, import_node_path.resolve)(resolved) !== resolved) {
|
|
129
|
+
throw new Error(`Path traversal detected: ${relativePath}`);
|
|
130
|
+
}
|
|
131
|
+
return resolved;
|
|
132
|
+
}
|
|
133
|
+
async function readFileContent(filepath) {
|
|
134
|
+
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
135
|
+
}
|
|
136
|
+
async function writeFileContent(filepath, content) {
|
|
137
|
+
await ensureDir((0, import_node_path.dirname)(filepath));
|
|
138
|
+
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
139
|
+
}
|
|
140
|
+
async function fileExists(filepath) {
|
|
141
|
+
try {
|
|
142
|
+
await (0, import_promises2.stat)(filepath);
|
|
143
|
+
return true;
|
|
144
|
+
} catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function findFiles(dir, extension = ".md") {
|
|
149
|
+
try {
|
|
150
|
+
const files = await (0, import_promises2.readdir)(dir);
|
|
151
|
+
return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path.join)(dir, file));
|
|
152
|
+
} catch {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function findRuleFiles(aiRulesDir) {
|
|
157
|
+
const rulesDir = (0, import_node_path.join)(aiRulesDir, "rules");
|
|
158
|
+
const newLocationFiles = await findFiles(rulesDir, ".md");
|
|
159
|
+
const legacyLocationFiles = await findFiles(aiRulesDir, ".md");
|
|
160
|
+
const newLocationBasenames = new Set(
|
|
161
|
+
newLocationFiles.map((file) => file.split("/").pop()?.replace(/\.md$/, ""))
|
|
162
|
+
);
|
|
163
|
+
const filteredLegacyFiles = legacyLocationFiles.filter((file) => {
|
|
164
|
+
const basename6 = file.split("/").pop()?.replace(/\.md$/, "");
|
|
165
|
+
return !newLocationBasenames.has(basename6);
|
|
166
|
+
});
|
|
167
|
+
return [...newLocationFiles, ...filteredLegacyFiles];
|
|
168
|
+
}
|
|
169
|
+
async function removeDirectory(dirPath) {
|
|
170
|
+
const dangerousPaths = [".", "/", "~", "src", "node_modules"];
|
|
171
|
+
if (dangerousPaths.includes(dirPath) || dirPath === "") {
|
|
172
|
+
logger.warn(`Skipping deletion of dangerous path: ${dirPath}`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
if (await fileExists(dirPath)) {
|
|
177
|
+
await (0, import_promises2.rm)(dirPath, { recursive: true, force: true });
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
logger.warn(`Failed to remove directory ${dirPath}:`, error);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function removeFile(filepath) {
|
|
184
|
+
try {
|
|
185
|
+
if (await fileExists(filepath)) {
|
|
186
|
+
await (0, import_promises2.rm)(filepath);
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
logger.warn(`Failed to remove file ${filepath}:`, error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function removeClaudeGeneratedFiles() {
|
|
193
|
+
const filesToRemove = ["CLAUDE.md", ".claude/memories"];
|
|
194
|
+
for (const fileOrDir of filesToRemove) {
|
|
195
|
+
if (fileOrDir.endsWith("/memories")) {
|
|
196
|
+
await removeDirectory(fileOrDir);
|
|
197
|
+
} else {
|
|
198
|
+
await removeFile(fileOrDir);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
var import_promises2, import_node_path;
|
|
203
|
+
var init_file = __esm({
|
|
204
|
+
"src/utils/file.ts"() {
|
|
205
|
+
"use strict";
|
|
206
|
+
import_promises2 = require("fs/promises");
|
|
207
|
+
import_node_path = require("path");
|
|
208
|
+
init_logger();
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
64
212
|
// src/utils/mcp-helpers.ts
|
|
65
213
|
function shouldIncludeServer(server, targetTool) {
|
|
66
214
|
if (!server.targets || server.targets.length === 0) {
|
|
@@ -85,6 +233,75 @@ var init_mcp_helpers = __esm({
|
|
|
85
233
|
}
|
|
86
234
|
});
|
|
87
235
|
|
|
236
|
+
// src/generators/mcp/amazonqcli.ts
|
|
237
|
+
var amazonqcli_exports = {};
|
|
238
|
+
__export(amazonqcli_exports, {
|
|
239
|
+
generateAmazonqcliMcp: () => generateAmazonqcliMcp,
|
|
240
|
+
generateAmazonqcliMcpString: () => generateAmazonqcliMcpString
|
|
241
|
+
});
|
|
242
|
+
async function generateAmazonqcliMcp(mcpServers, config, baseDir) {
|
|
243
|
+
const outputs = [];
|
|
244
|
+
const configPaths = [
|
|
245
|
+
".amazonq/mcp.json"
|
|
246
|
+
// Workspace configuration
|
|
247
|
+
// Note: Global configuration is ~/.aws/amazonq/mcp.json but is user-specific
|
|
248
|
+
// According to precautions.md, we should not create user-level files
|
|
249
|
+
];
|
|
250
|
+
for (const configPath of configPaths) {
|
|
251
|
+
const filepath = resolvePath(configPath, baseDir);
|
|
252
|
+
const content = generateAmazonqcliMcpConfig({ mcpServers });
|
|
253
|
+
outputs.push({
|
|
254
|
+
tool: "amazonqcli",
|
|
255
|
+
filepath,
|
|
256
|
+
content
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return outputs;
|
|
260
|
+
}
|
|
261
|
+
function generateAmazonqcliMcpString(config) {
|
|
262
|
+
return generateAmazonqcliMcpConfig(config);
|
|
263
|
+
}
|
|
264
|
+
function generateAmazonqcliMcpConfig(config) {
|
|
265
|
+
const servers = {};
|
|
266
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
267
|
+
if (!shouldIncludeServer(server, "amazonqcli")) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const amazonqServer = {};
|
|
271
|
+
if (server.command) {
|
|
272
|
+
amazonqServer.command = server.command;
|
|
273
|
+
if (server.args) {
|
|
274
|
+
amazonqServer.args = server.args;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (server.env) {
|
|
278
|
+
amazonqServer.env = server.env;
|
|
279
|
+
}
|
|
280
|
+
if (server.timeout !== void 0) {
|
|
281
|
+
amazonqServer.timeout = server.timeout;
|
|
282
|
+
}
|
|
283
|
+
if (server.disabled !== void 0) {
|
|
284
|
+
amazonqServer.disabled = server.disabled;
|
|
285
|
+
}
|
|
286
|
+
if (server.alwaysAllow) {
|
|
287
|
+
amazonqServer.autoApprove = server.alwaysAllow;
|
|
288
|
+
}
|
|
289
|
+
servers[serverName] = amazonqServer;
|
|
290
|
+
}
|
|
291
|
+
const finalConfig = {
|
|
292
|
+
mcpServers: servers
|
|
293
|
+
};
|
|
294
|
+
return `${JSON.stringify(finalConfig, null, 2)}
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
var init_amazonqcli = __esm({
|
|
298
|
+
"src/generators/mcp/amazonqcli.ts"() {
|
|
299
|
+
"use strict";
|
|
300
|
+
init_file();
|
|
301
|
+
init_mcp_helpers();
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
88
305
|
// src/generators/mcp/augmentcode.ts
|
|
89
306
|
var augmentcode_exports = {};
|
|
90
307
|
__export(augmentcode_exports, {
|
|
@@ -104,7 +321,10 @@ function generateAugmentcodeMcp(config) {
|
|
|
104
321
|
name: serverName
|
|
105
322
|
};
|
|
106
323
|
if (server.command) {
|
|
107
|
-
|
|
324
|
+
const command = Array.isArray(server.command) ? server.command[0] : server.command;
|
|
325
|
+
if (command) {
|
|
326
|
+
augmentServer.command = command;
|
|
327
|
+
}
|
|
108
328
|
if (server.args) {
|
|
109
329
|
augmentServer.args = server.args;
|
|
110
330
|
}
|
|
@@ -152,7 +372,10 @@ function generateAugmentcodeMcpConfiguration(mcpServers, baseDir = "") {
|
|
|
152
372
|
const { targets: _, ...serverConfig } = server;
|
|
153
373
|
const augmentServer = {};
|
|
154
374
|
if (serverConfig.command) {
|
|
155
|
-
|
|
375
|
+
const command = Array.isArray(serverConfig.command) ? serverConfig.command[0] : serverConfig.command;
|
|
376
|
+
if (command) {
|
|
377
|
+
augmentServer.command = command;
|
|
378
|
+
}
|
|
156
379
|
if (serverConfig.args) {
|
|
157
380
|
augmentServer.args = serverConfig.args;
|
|
158
381
|
}
|
|
@@ -199,6 +422,17 @@ var init_augmentcode = __esm({
|
|
|
199
422
|
}
|
|
200
423
|
});
|
|
201
424
|
|
|
425
|
+
// src/constants/schemas.ts
|
|
426
|
+
var SCHEMA_URLS;
|
|
427
|
+
var init_schemas = __esm({
|
|
428
|
+
"src/constants/schemas.ts"() {
|
|
429
|
+
"use strict";
|
|
430
|
+
SCHEMA_URLS = {
|
|
431
|
+
OPENCODE: "https://opencode.ai/config.json"
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
202
436
|
// src/generators/mcp/shared-factory.ts
|
|
203
437
|
function generateMcpConfig(config, toolConfig) {
|
|
204
438
|
const servers = {};
|
|
@@ -248,7 +482,7 @@ function generateMcpConfigurationFilesFromRegistry(tool, mcpServers, baseDir = "
|
|
|
248
482
|
if (tool === "junie") {
|
|
249
483
|
return generateJunieMcpConfigurationFiles(mcpServers, baseDir);
|
|
250
484
|
}
|
|
251
|
-
const customTools = ["copilot", "augmentcode", "
|
|
485
|
+
const customTools = ["copilot", "augmentcode", "codexcli", "kiro"];
|
|
252
486
|
if (customTools.includes(tool)) {
|
|
253
487
|
throw new Error(
|
|
254
488
|
`Tool ${tool} uses custom configuration logic - use its specific generator function instead`
|
|
@@ -297,6 +531,7 @@ var serverTransforms, configWrappers, MCP_GENERATOR_REGISTRY, cursorMcpGenerator
|
|
|
297
531
|
var init_shared_factory = __esm({
|
|
298
532
|
"src/generators/mcp/shared-factory.ts"() {
|
|
299
533
|
"use strict";
|
|
534
|
+
init_schemas();
|
|
300
535
|
init_mcp_helpers();
|
|
301
536
|
serverTransforms = {
|
|
302
537
|
/**
|
|
@@ -307,7 +542,8 @@ var init_shared_factory = __esm({
|
|
|
307
542
|
if (server.command) {
|
|
308
543
|
result.command = server.command;
|
|
309
544
|
if (server.args) result.args = server.args;
|
|
310
|
-
}
|
|
545
|
+
}
|
|
546
|
+
if (server.url || server.httpUrl) {
|
|
311
547
|
const url = server.httpUrl || server.url;
|
|
312
548
|
if (url) result.url = url;
|
|
313
549
|
}
|
|
@@ -316,6 +552,25 @@ var init_shared_factory = __esm({
|
|
|
316
552
|
}
|
|
317
553
|
return result;
|
|
318
554
|
},
|
|
555
|
+
/**
|
|
556
|
+
* Roo-specific server transformation (preserves httpUrl, transport, type, etc.)
|
|
557
|
+
*/
|
|
558
|
+
roo: (server) => {
|
|
559
|
+
const result = serverTransforms.extended(server);
|
|
560
|
+
if (server.httpUrl) {
|
|
561
|
+
if (!server.url) {
|
|
562
|
+
result.httpUrl = server.httpUrl;
|
|
563
|
+
delete result.url;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (server.transport) {
|
|
567
|
+
result.transport = server.transport;
|
|
568
|
+
}
|
|
569
|
+
if (server.type) {
|
|
570
|
+
result.type = server.type;
|
|
571
|
+
}
|
|
572
|
+
return result;
|
|
573
|
+
},
|
|
319
574
|
/**
|
|
320
575
|
* Extended server transformation (includes disabled, alwaysAllow, etc.)
|
|
321
576
|
*/
|
|
@@ -367,6 +622,12 @@ var init_shared_factory = __esm({
|
|
|
367
622
|
})
|
|
368
623
|
};
|
|
369
624
|
MCP_GENERATOR_REGISTRY = {
|
|
625
|
+
roo: {
|
|
626
|
+
target: "roo",
|
|
627
|
+
configPaths: [".roo/mcp.json"],
|
|
628
|
+
serverTransform: serverTransforms.roo,
|
|
629
|
+
configWrapper: configWrappers.mcpServers
|
|
630
|
+
},
|
|
370
631
|
claudecode: {
|
|
371
632
|
target: "claudecode",
|
|
372
633
|
configPaths: [".mcp.json"],
|
|
@@ -493,6 +754,48 @@ var init_shared_factory = __esm({
|
|
|
493
754
|
configPaths: [".cline/mcp.json"],
|
|
494
755
|
serverTransform: serverTransforms.extended,
|
|
495
756
|
configWrapper: configWrappers.mcpServers
|
|
757
|
+
},
|
|
758
|
+
geminicli: {
|
|
759
|
+
target: "geminicli",
|
|
760
|
+
configPaths: [".gemini/settings.json"],
|
|
761
|
+
serverTransform: (server) => {
|
|
762
|
+
const { targets: _, ...serverConfig } = server;
|
|
763
|
+
const geminiServer = { ...serverConfig };
|
|
764
|
+
if (server.env) {
|
|
765
|
+
geminiServer.env = server.env;
|
|
766
|
+
}
|
|
767
|
+
return geminiServer;
|
|
768
|
+
},
|
|
769
|
+
configWrapper: configWrappers.mcpServers
|
|
770
|
+
},
|
|
771
|
+
opencode: {
|
|
772
|
+
target: "opencode",
|
|
773
|
+
configPaths: ["opencode.json"],
|
|
774
|
+
serverTransform: (server) => {
|
|
775
|
+
const opencodeServer = {};
|
|
776
|
+
if (server.command) {
|
|
777
|
+
opencodeServer.type = "local";
|
|
778
|
+
opencodeServer.command = Array.isArray(server.command) ? server.command : [server.command];
|
|
779
|
+
if (server.args) opencodeServer.args = server.args;
|
|
780
|
+
if (server.env) opencodeServer.environment = server.env;
|
|
781
|
+
if (server.cwd) opencodeServer.cwd = server.cwd;
|
|
782
|
+
} else if (server.url || server.httpUrl) {
|
|
783
|
+
opencodeServer.type = "remote";
|
|
784
|
+
const url = server.httpUrl || server.url;
|
|
785
|
+
if (url) opencodeServer.url = url;
|
|
786
|
+
if (server.headers) opencodeServer.headers = server.headers;
|
|
787
|
+
}
|
|
788
|
+
if (server.disabled !== void 0) {
|
|
789
|
+
opencodeServer.enabled = !server.disabled;
|
|
790
|
+
} else {
|
|
791
|
+
opencodeServer.enabled = true;
|
|
792
|
+
}
|
|
793
|
+
return opencodeServer;
|
|
794
|
+
},
|
|
795
|
+
configWrapper: (servers) => ({
|
|
796
|
+
$schema: SCHEMA_URLS.OPENCODE,
|
|
797
|
+
mcp: servers
|
|
798
|
+
})
|
|
496
799
|
}
|
|
497
800
|
};
|
|
498
801
|
cursorMcpGenerator = createMcpGenerator("cursor");
|
|
@@ -696,7 +999,10 @@ function generateCopilotMcp(config, target) {
|
|
|
696
999
|
if (!shouldIncludeServer(server, "copilot")) continue;
|
|
697
1000
|
const copilotServer = {};
|
|
698
1001
|
if (server.command) {
|
|
699
|
-
|
|
1002
|
+
const command = Array.isArray(server.command) ? server.command[0] : server.command;
|
|
1003
|
+
if (command) {
|
|
1004
|
+
copilotServer.command = command;
|
|
1005
|
+
}
|
|
700
1006
|
if (server.args) copilotServer.args = server.args;
|
|
701
1007
|
} else if (server.url || server.httpUrl) {
|
|
702
1008
|
const url = server.httpUrl || server.url;
|
|
@@ -786,53 +1092,10 @@ __export(geminicli_exports, {
|
|
|
786
1092
|
generateGeminiCliMcpConfiguration: () => generateGeminiCliMcpConfiguration
|
|
787
1093
|
});
|
|
788
1094
|
function generateGeminiCliMcp(config) {
|
|
789
|
-
return
|
|
790
|
-
target: "geminicli",
|
|
791
|
-
configPaths: [".gemini/settings.json"],
|
|
792
|
-
serverTransform: (server) => {
|
|
793
|
-
const geminiServer = {};
|
|
794
|
-
if (server.command) {
|
|
795
|
-
geminiServer.command = server.command;
|
|
796
|
-
if (server.args) geminiServer.args = server.args;
|
|
797
|
-
} else if (server.url || server.httpUrl) {
|
|
798
|
-
if (server.httpUrl) {
|
|
799
|
-
geminiServer.httpUrl = server.httpUrl;
|
|
800
|
-
} else if (server.url) {
|
|
801
|
-
geminiServer.url = server.url;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
if (server.env) {
|
|
805
|
-
geminiServer.env = server.env;
|
|
806
|
-
}
|
|
807
|
-
if (server.timeout !== void 0) {
|
|
808
|
-
geminiServer.timeout = server.timeout;
|
|
809
|
-
}
|
|
810
|
-
if (server.trust !== void 0) {
|
|
811
|
-
geminiServer.trust = server.trust;
|
|
812
|
-
}
|
|
813
|
-
return geminiServer;
|
|
814
|
-
},
|
|
815
|
-
configWrapper: configWrappers.mcpServers
|
|
816
|
-
});
|
|
1095
|
+
return generateMcpFromRegistry("geminicli", config);
|
|
817
1096
|
}
|
|
818
1097
|
function generateGeminiCliMcpConfiguration(mcpServers, baseDir = "") {
|
|
819
|
-
return
|
|
820
|
-
mcpServers,
|
|
821
|
-
{
|
|
822
|
-
target: "geminicli",
|
|
823
|
-
configPaths: [".gemini/settings.json"],
|
|
824
|
-
serverTransform: (server) => {
|
|
825
|
-
const { targets: _, ...serverConfig } = server;
|
|
826
|
-
const geminiServer = { ...serverConfig };
|
|
827
|
-
if (server.env) {
|
|
828
|
-
geminiServer.env = server.env;
|
|
829
|
-
}
|
|
830
|
-
return geminiServer;
|
|
831
|
-
},
|
|
832
|
-
configWrapper: configWrappers.mcpServers
|
|
833
|
-
},
|
|
834
|
-
baseDir
|
|
835
|
-
);
|
|
1098
|
+
return generateMcpConfigurationFilesFromRegistry("geminicli", mcpServers, baseDir);
|
|
836
1099
|
}
|
|
837
1100
|
var init_geminicli = __esm({
|
|
838
1101
|
"src/generators/mcp/geminicli.ts"() {
|
|
@@ -956,77 +1219,15 @@ __export(roo_exports, {
|
|
|
956
1219
|
generateRooMcpConfiguration: () => generateRooMcpConfiguration
|
|
957
1220
|
});
|
|
958
1221
|
function generateRooMcp(config) {
|
|
959
|
-
|
|
960
|
-
mcpServers: {}
|
|
961
|
-
};
|
|
962
|
-
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
963
|
-
if (!shouldIncludeServer(server, "roo")) continue;
|
|
964
|
-
const rooServer = {};
|
|
965
|
-
if (server.command) {
|
|
966
|
-
rooServer.command = server.command;
|
|
967
|
-
if (server.args) rooServer.args = server.args;
|
|
968
|
-
} else if (server.url || server.httpUrl) {
|
|
969
|
-
const url = server.httpUrl || server.url;
|
|
970
|
-
if (url) {
|
|
971
|
-
rooServer.url = url;
|
|
972
|
-
}
|
|
973
|
-
if (server.httpUrl || server.transport === "http") {
|
|
974
|
-
rooServer.type = "streamable-http";
|
|
975
|
-
} else if (server.transport === "sse" || server.type === "sse") {
|
|
976
|
-
rooServer.type = "sse";
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
if (server.env) {
|
|
980
|
-
rooServer.env = {};
|
|
981
|
-
for (const [key, value] of Object.entries(server.env)) {
|
|
982
|
-
if (value.startsWith("${env:") && value.endsWith("}")) {
|
|
983
|
-
rooServer.env[key] = value;
|
|
984
|
-
} else {
|
|
985
|
-
rooServer.env[key] = `\${env:${value}}`;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
if (server.disabled !== void 0) {
|
|
990
|
-
rooServer.disabled = server.disabled;
|
|
991
|
-
}
|
|
992
|
-
if (server.alwaysAllow) {
|
|
993
|
-
rooServer.alwaysAllow = server.alwaysAllow;
|
|
994
|
-
}
|
|
995
|
-
if (server.networkTimeout !== void 0) {
|
|
996
|
-
rooServer.networkTimeout = Math.max(3e4, Math.min(3e5, server.networkTimeout));
|
|
997
|
-
}
|
|
998
|
-
rooConfig.mcpServers[serverName] = rooServer;
|
|
999
|
-
}
|
|
1000
|
-
return JSON.stringify(rooConfig, null, 2);
|
|
1222
|
+
return generateMcpFromRegistry("roo", config);
|
|
1001
1223
|
}
|
|
1002
1224
|
function generateRooMcpConfiguration(mcpServers, baseDir = "") {
|
|
1003
|
-
|
|
1004
|
-
const config = {
|
|
1005
|
-
mcpServers: {}
|
|
1006
|
-
};
|
|
1007
|
-
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
1008
|
-
if (!shouldIncludeServer(server, "roo")) {
|
|
1009
|
-
continue;
|
|
1010
|
-
}
|
|
1011
|
-
const { targets: _targets, ...serverConfig } = server;
|
|
1012
|
-
const rooServer = { ...serverConfig };
|
|
1013
|
-
if (serverConfig.httpUrl !== void 0 && serverConfig.url !== void 0) {
|
|
1014
|
-
rooServer.url = serverConfig.httpUrl;
|
|
1015
|
-
}
|
|
1016
|
-
config.mcpServers[serverName] = rooServer;
|
|
1017
|
-
}
|
|
1018
|
-
return [
|
|
1019
|
-
{
|
|
1020
|
-
filepath,
|
|
1021
|
-
content: `${JSON.stringify(config, null, 2)}
|
|
1022
|
-
`
|
|
1023
|
-
}
|
|
1024
|
-
];
|
|
1225
|
+
return generateMcpConfigurationFilesFromRegistry("roo", mcpServers, baseDir);
|
|
1025
1226
|
}
|
|
1026
1227
|
var init_roo = __esm({
|
|
1027
1228
|
"src/generators/mcp/roo.ts"() {
|
|
1028
1229
|
"use strict";
|
|
1029
|
-
|
|
1230
|
+
init_shared_factory();
|
|
1030
1231
|
}
|
|
1031
1232
|
});
|
|
1032
1233
|
|
|
@@ -1049,6 +1250,25 @@ var init_windsurf = __esm({
|
|
|
1049
1250
|
}
|
|
1050
1251
|
});
|
|
1051
1252
|
|
|
1253
|
+
// src/generators/mcp/opencode.ts
|
|
1254
|
+
var opencode_exports = {};
|
|
1255
|
+
__export(opencode_exports, {
|
|
1256
|
+
generateOpenCodeMcp: () => generateOpenCodeMcp,
|
|
1257
|
+
generateOpenCodeMcpConfiguration: () => generateOpenCodeMcpConfiguration
|
|
1258
|
+
});
|
|
1259
|
+
function generateOpenCodeMcp(config) {
|
|
1260
|
+
return generateMcpFromRegistry("opencode", config);
|
|
1261
|
+
}
|
|
1262
|
+
function generateOpenCodeMcpConfiguration(mcpServers, baseDir = "") {
|
|
1263
|
+
return generateMcpConfigurationFilesFromRegistry("opencode", mcpServers, baseDir);
|
|
1264
|
+
}
|
|
1265
|
+
var init_opencode = __esm({
|
|
1266
|
+
"src/generators/mcp/opencode.ts"() {
|
|
1267
|
+
"use strict";
|
|
1268
|
+
init_shared_factory();
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1052
1272
|
// src/cli/index.ts
|
|
1053
1273
|
var import_commander = require("commander");
|
|
1054
1274
|
|
|
@@ -1103,6 +1323,7 @@ var ConfigSchema = import_mini4.z.object({
|
|
|
1103
1323
|
var import_mini5 = require("zod/mini");
|
|
1104
1324
|
init_tool_targets();
|
|
1105
1325
|
var OutputPathsSchema = import_mini5.z.object({
|
|
1326
|
+
amazonqcli: import_mini5.z.optional(import_mini5.z.string()),
|
|
1106
1327
|
augmentcode: import_mini5.z.optional(import_mini5.z.string()),
|
|
1107
1328
|
"augmentcode-legacy": import_mini5.z.optional(import_mini5.z.string()),
|
|
1108
1329
|
copilot: import_mini5.z.optional(import_mini5.z.string()),
|
|
@@ -1110,6 +1331,7 @@ var OutputPathsSchema = import_mini5.z.object({
|
|
|
1110
1331
|
cline: import_mini5.z.optional(import_mini5.z.string()),
|
|
1111
1332
|
claudecode: import_mini5.z.optional(import_mini5.z.string()),
|
|
1112
1333
|
codexcli: import_mini5.z.optional(import_mini5.z.string()),
|
|
1334
|
+
opencode: import_mini5.z.optional(import_mini5.z.string()),
|
|
1113
1335
|
roo: import_mini5.z.optional(import_mini5.z.string()),
|
|
1114
1336
|
geminicli: import_mini5.z.optional(import_mini5.z.string()),
|
|
1115
1337
|
kiro: import_mini5.z.optional(import_mini5.z.string()),
|
|
@@ -1161,7 +1383,7 @@ var import_mini6 = require("zod/mini");
|
|
|
1161
1383
|
init_tool_targets();
|
|
1162
1384
|
var McpTransportTypeSchema = import_mini6.z.enum(["stdio", "sse", "http"]);
|
|
1163
1385
|
var McpServerBaseSchema = import_mini6.z.object({
|
|
1164
|
-
command: import_mini6.z.optional(import_mini6.z.string()),
|
|
1386
|
+
command: import_mini6.z.optional(import_mini6.z.union([import_mini6.z.string(), import_mini6.z.array(import_mini6.z.string())])),
|
|
1165
1387
|
args: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
|
|
1166
1388
|
url: import_mini6.z.optional(import_mini6.z.string()),
|
|
1167
1389
|
httpUrl: import_mini6.z.optional(import_mini6.z.string()),
|
|
@@ -1217,6 +1439,7 @@ function getDefaultConfig() {
|
|
|
1217
1439
|
return {
|
|
1218
1440
|
aiRulesDir: ".rulesync",
|
|
1219
1441
|
outputPaths: {
|
|
1442
|
+
amazonqcli: ".amazonq/rules",
|
|
1220
1443
|
augmentcode: ".",
|
|
1221
1444
|
"augmentcode-legacy": ".",
|
|
1222
1445
|
copilot: ".github/instructions",
|
|
@@ -1224,6 +1447,7 @@ function getDefaultConfig() {
|
|
|
1224
1447
|
cline: ".clinerules",
|
|
1225
1448
|
claudecode: ".",
|
|
1226
1449
|
codexcli: ".",
|
|
1450
|
+
opencode: ".",
|
|
1227
1451
|
roo: ".roo/rules",
|
|
1228
1452
|
geminicli: ".gemini/memories",
|
|
1229
1453
|
kiro: ".kiro/steering",
|
|
@@ -1430,51 +1654,8 @@ function mergeWithCliOptions(config, cliOptions) {
|
|
|
1430
1654
|
return merged;
|
|
1431
1655
|
}
|
|
1432
1656
|
|
|
1433
|
-
// src/utils/logger.ts
|
|
1434
|
-
var import_consola = require("consola");
|
|
1435
|
-
var Logger = class {
|
|
1436
|
-
_verbose = false;
|
|
1437
|
-
console = import_consola.consola.withDefaults({
|
|
1438
|
-
tag: "rulesync"
|
|
1439
|
-
});
|
|
1440
|
-
setVerbose(verbose) {
|
|
1441
|
-
this._verbose = verbose;
|
|
1442
|
-
}
|
|
1443
|
-
get verbose() {
|
|
1444
|
-
return this._verbose;
|
|
1445
|
-
}
|
|
1446
|
-
// Regular log (always shown, regardless of verbose)
|
|
1447
|
-
log(message, ...args) {
|
|
1448
|
-
this.console.log(message, ...args);
|
|
1449
|
-
}
|
|
1450
|
-
// Info level (shown only in verbose mode)
|
|
1451
|
-
info(message, ...args) {
|
|
1452
|
-
if (this._verbose) {
|
|
1453
|
-
this.console.info(message, ...args);
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
// Success (always shown)
|
|
1457
|
-
success(message, ...args) {
|
|
1458
|
-
this.console.success(message, ...args);
|
|
1459
|
-
}
|
|
1460
|
-
// Warning (always shown)
|
|
1461
|
-
warn(message, ...args) {
|
|
1462
|
-
this.console.warn(message, ...args);
|
|
1463
|
-
}
|
|
1464
|
-
// Error (always shown)
|
|
1465
|
-
error(message, ...args) {
|
|
1466
|
-
this.console.error(message, ...args);
|
|
1467
|
-
}
|
|
1468
|
-
// Debug level (shown only in verbose mode)
|
|
1469
|
-
debug(message, ...args) {
|
|
1470
|
-
if (this._verbose) {
|
|
1471
|
-
this.console.debug(message, ...args);
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
};
|
|
1475
|
-
var logger = new Logger();
|
|
1476
|
-
|
|
1477
1657
|
// src/cli/commands/add.ts
|
|
1658
|
+
init_logger();
|
|
1478
1659
|
function sanitizeFilename(filename) {
|
|
1479
1660
|
return filename.endsWith(".md") ? filename.slice(0, -3) : filename;
|
|
1480
1661
|
}
|
|
@@ -1518,6 +1699,7 @@ var import_node_fs = require("fs");
|
|
|
1518
1699
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
1519
1700
|
|
|
1520
1701
|
// src/utils/error.ts
|
|
1702
|
+
init_logger();
|
|
1521
1703
|
function getErrorMessage(error) {
|
|
1522
1704
|
return error instanceof Error ? error.message : String(error);
|
|
1523
1705
|
}
|
|
@@ -1547,90 +1729,11 @@ async function safeAsyncOperation(operation, errorContext) {
|
|
|
1547
1729
|
}
|
|
1548
1730
|
}
|
|
1549
1731
|
|
|
1550
|
-
// src/utils/
|
|
1551
|
-
|
|
1552
|
-
var import_node_path = require("path");
|
|
1553
|
-
async function ensureDir(dirPath) {
|
|
1554
|
-
try {
|
|
1555
|
-
await (0, import_promises2.stat)(dirPath);
|
|
1556
|
-
} catch {
|
|
1557
|
-
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
function resolvePath(relativePath, baseDir) {
|
|
1561
|
-
return baseDir ? (0, import_node_path.join)(baseDir, relativePath) : relativePath;
|
|
1562
|
-
}
|
|
1563
|
-
async function readFileContent(filepath) {
|
|
1564
|
-
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
1565
|
-
}
|
|
1566
|
-
async function writeFileContent(filepath, content) {
|
|
1567
|
-
await ensureDir((0, import_node_path.dirname)(filepath));
|
|
1568
|
-
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
1569
|
-
}
|
|
1570
|
-
async function fileExists(filepath) {
|
|
1571
|
-
try {
|
|
1572
|
-
await (0, import_promises2.stat)(filepath);
|
|
1573
|
-
return true;
|
|
1574
|
-
} catch {
|
|
1575
|
-
return false;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
async function findFiles(dir, extension = ".md") {
|
|
1579
|
-
try {
|
|
1580
|
-
const files = await (0, import_promises2.readdir)(dir);
|
|
1581
|
-
return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path.join)(dir, file));
|
|
1582
|
-
} catch {
|
|
1583
|
-
return [];
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
async function findRuleFiles(aiRulesDir) {
|
|
1587
|
-
const rulesDir = (0, import_node_path.join)(aiRulesDir, "rules");
|
|
1588
|
-
const newLocationFiles = await findFiles(rulesDir, ".md");
|
|
1589
|
-
const legacyLocationFiles = await findFiles(aiRulesDir, ".md");
|
|
1590
|
-
const newLocationBasenames = new Set(
|
|
1591
|
-
newLocationFiles.map((file) => file.split("/").pop()?.replace(/\.md$/, ""))
|
|
1592
|
-
);
|
|
1593
|
-
const filteredLegacyFiles = legacyLocationFiles.filter((file) => {
|
|
1594
|
-
const basename6 = file.split("/").pop()?.replace(/\.md$/, "");
|
|
1595
|
-
return !newLocationBasenames.has(basename6);
|
|
1596
|
-
});
|
|
1597
|
-
return [...newLocationFiles, ...filteredLegacyFiles];
|
|
1598
|
-
}
|
|
1599
|
-
async function removeDirectory(dirPath) {
|
|
1600
|
-
const dangerousPaths = [".", "/", "~", "src", "node_modules"];
|
|
1601
|
-
if (dangerousPaths.includes(dirPath) || dirPath === "") {
|
|
1602
|
-
logger.warn(`Skipping deletion of dangerous path: ${dirPath}`);
|
|
1603
|
-
return;
|
|
1604
|
-
}
|
|
1605
|
-
try {
|
|
1606
|
-
if (await fileExists(dirPath)) {
|
|
1607
|
-
await (0, import_promises2.rm)(dirPath, { recursive: true, force: true });
|
|
1608
|
-
}
|
|
1609
|
-
} catch (error) {
|
|
1610
|
-
logger.warn(`Failed to remove directory ${dirPath}:`, error);
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
async function removeFile(filepath) {
|
|
1614
|
-
try {
|
|
1615
|
-
if (await fileExists(filepath)) {
|
|
1616
|
-
await (0, import_promises2.rm)(filepath);
|
|
1617
|
-
}
|
|
1618
|
-
} catch (error) {
|
|
1619
|
-
logger.warn(`Failed to remove file ${filepath}:`, error);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
async function removeClaudeGeneratedFiles() {
|
|
1623
|
-
const filesToRemove = ["CLAUDE.md", ".claude/memories"];
|
|
1624
|
-
for (const fileOrDir of filesToRemove) {
|
|
1625
|
-
if (fileOrDir.endsWith("/memories")) {
|
|
1626
|
-
await removeDirectory(fileOrDir);
|
|
1627
|
-
} else {
|
|
1628
|
-
await removeFile(fileOrDir);
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1732
|
+
// src/utils/index.ts
|
|
1733
|
+
init_file();
|
|
1632
1734
|
|
|
1633
1735
|
// src/cli/commands/config.ts
|
|
1736
|
+
init_logger();
|
|
1634
1737
|
async function configCommand(options = {}) {
|
|
1635
1738
|
if (options.init) {
|
|
1636
1739
|
await initConfig(options);
|
|
@@ -1848,18 +1951,18 @@ var import_node_path5 = require("path");
|
|
|
1848
1951
|
|
|
1849
1952
|
// src/utils/command-generators.ts
|
|
1850
1953
|
var import_node_path3 = require("path");
|
|
1851
|
-
function generateYamlFrontmatter(command, options
|
|
1852
|
-
const
|
|
1853
|
-
if (options
|
|
1854
|
-
|
|
1954
|
+
function generateYamlFrontmatter(command, options) {
|
|
1955
|
+
const frontmatterLines = ["---"];
|
|
1956
|
+
if (options?.includeDescription && command.frontmatter.description) {
|
|
1957
|
+
frontmatterLines.push(`description: ${command.frontmatter.description}`);
|
|
1855
1958
|
}
|
|
1856
|
-
if (options
|
|
1959
|
+
if (options?.additionalFields) {
|
|
1857
1960
|
for (const field of options.additionalFields) {
|
|
1858
|
-
|
|
1961
|
+
frontmatterLines.push(`${field.key}: ${field.value}`);
|
|
1859
1962
|
}
|
|
1860
1963
|
}
|
|
1861
|
-
|
|
1862
|
-
return
|
|
1964
|
+
frontmatterLines.push("---");
|
|
1965
|
+
return frontmatterLines;
|
|
1863
1966
|
}
|
|
1864
1967
|
function buildCommandContent(command, frontmatterOptions) {
|
|
1865
1968
|
const frontmatter = generateYamlFrontmatter(command, frontmatterOptions);
|
|
@@ -1898,26 +2001,75 @@ var syntaxConverters = {
|
|
|
1898
2001
|
}
|
|
1899
2002
|
};
|
|
1900
2003
|
|
|
1901
|
-
// src/generators/commands/
|
|
1902
|
-
var
|
|
2004
|
+
// src/generators/commands/base.ts
|
|
2005
|
+
var BaseCommandGenerator = class {
|
|
2006
|
+
/**
|
|
2007
|
+
* Generate command output for the specified tool
|
|
2008
|
+
*/
|
|
1903
2009
|
generate(command, outputDir) {
|
|
1904
2010
|
const filepath = this.getOutputPath(command.filename, outputDir);
|
|
1905
|
-
const content =
|
|
2011
|
+
const content = this.processContent(command);
|
|
1906
2012
|
return {
|
|
1907
|
-
tool:
|
|
2013
|
+
tool: this.getToolName(),
|
|
1908
2014
|
filepath,
|
|
1909
2015
|
content
|
|
1910
2016
|
};
|
|
1911
2017
|
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Get the output path for the command file
|
|
2020
|
+
* Override this method if custom path logic is needed
|
|
2021
|
+
*/
|
|
1912
2022
|
getOutputPath(filename, baseDir) {
|
|
1913
|
-
|
|
2023
|
+
if (this.supportsHierarchy()) {
|
|
2024
|
+
return getHierarchicalCommandPath(
|
|
2025
|
+
filename,
|
|
2026
|
+
baseDir,
|
|
2027
|
+
this.getCommandsDirectory(),
|
|
2028
|
+
this.getFileExtension()
|
|
2029
|
+
);
|
|
2030
|
+
} else {
|
|
2031
|
+
return getFlattenedCommandPath(filename, baseDir, this.getCommandsDirectory());
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Whether this tool supports hierarchical directory structure
|
|
2036
|
+
* Override to return true for tools that support nested commands
|
|
2037
|
+
*/
|
|
2038
|
+
supportsHierarchy() {
|
|
2039
|
+
return false;
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Get file extension for the target tool
|
|
2043
|
+
* Override if tool uses different extension than .md
|
|
2044
|
+
*/
|
|
2045
|
+
getFileExtension() {
|
|
2046
|
+
return "md";
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
|
|
2050
|
+
// src/generators/commands/claudecode.ts
|
|
2051
|
+
var ClaudeCodeCommandGenerator = class extends BaseCommandGenerator {
|
|
2052
|
+
getToolName() {
|
|
2053
|
+
return "claudecode";
|
|
2054
|
+
}
|
|
2055
|
+
getCommandsDirectory() {
|
|
2056
|
+
return ".claude/commands";
|
|
1914
2057
|
}
|
|
2058
|
+
processContent(command) {
|
|
2059
|
+
return buildCommandContent(command, { includeDescription: true });
|
|
2060
|
+
}
|
|
2061
|
+
// Uses flattened structure by default (supportsHierarchy returns false)
|
|
1915
2062
|
};
|
|
1916
2063
|
|
|
1917
2064
|
// src/generators/commands/geminicli.ts
|
|
1918
|
-
var GeminiCliCommandGenerator = class {
|
|
1919
|
-
|
|
1920
|
-
|
|
2065
|
+
var GeminiCliCommandGenerator = class extends BaseCommandGenerator {
|
|
2066
|
+
getToolName() {
|
|
2067
|
+
return "geminicli";
|
|
2068
|
+
}
|
|
2069
|
+
getCommandsDirectory() {
|
|
2070
|
+
return ".gemini/commands";
|
|
2071
|
+
}
|
|
2072
|
+
processContent(command) {
|
|
1921
2073
|
const convertedContent = syntaxConverters.toGeminiCli(command.content);
|
|
1922
2074
|
const tomlLines = [];
|
|
1923
2075
|
if (command.frontmatter.description) {
|
|
@@ -1925,32 +2077,28 @@ var GeminiCliCommandGenerator = class {
|
|
|
1925
2077
|
tomlLines.push("");
|
|
1926
2078
|
}
|
|
1927
2079
|
tomlLines.push(`prompt = """${convertedContent}"""`);
|
|
1928
|
-
|
|
1929
|
-
return {
|
|
1930
|
-
tool: "geminicli",
|
|
1931
|
-
filepath,
|
|
1932
|
-
content
|
|
1933
|
-
};
|
|
2080
|
+
return tomlLines.join("\n") + "\n";
|
|
1934
2081
|
}
|
|
1935
|
-
|
|
1936
|
-
return
|
|
2082
|
+
supportsHierarchy() {
|
|
2083
|
+
return true;
|
|
2084
|
+
}
|
|
2085
|
+
getFileExtension() {
|
|
2086
|
+
return "toml";
|
|
1937
2087
|
}
|
|
1938
2088
|
};
|
|
1939
2089
|
|
|
1940
2090
|
// src/generators/commands/roo.ts
|
|
1941
|
-
var RooCommandGenerator = class {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
const content = buildCommandContent(command);
|
|
1945
|
-
return {
|
|
1946
|
-
tool: "roo",
|
|
1947
|
-
filepath,
|
|
1948
|
-
content
|
|
1949
|
-
};
|
|
2091
|
+
var RooCommandGenerator = class extends BaseCommandGenerator {
|
|
2092
|
+
getToolName() {
|
|
2093
|
+
return "roo";
|
|
1950
2094
|
}
|
|
1951
|
-
|
|
1952
|
-
return
|
|
2095
|
+
getCommandsDirectory() {
|
|
2096
|
+
return ".roo/commands";
|
|
2097
|
+
}
|
|
2098
|
+
processContent(command) {
|
|
2099
|
+
return buildCommandContent(command, { includeDescription: true });
|
|
1953
2100
|
}
|
|
2101
|
+
// Uses flattened structure by default (supportsHierarchy returns false)
|
|
1954
2102
|
};
|
|
1955
2103
|
|
|
1956
2104
|
// src/generators/commands/index.ts
|
|
@@ -1963,6 +2111,10 @@ function getCommandGenerator(tool) {
|
|
|
1963
2111
|
return commandGenerators[tool];
|
|
1964
2112
|
}
|
|
1965
2113
|
|
|
2114
|
+
// src/core/command-generator.ts
|
|
2115
|
+
init_file();
|
|
2116
|
+
init_logger();
|
|
2117
|
+
|
|
1966
2118
|
// src/core/command-parser.ts
|
|
1967
2119
|
var import_node_path4 = require("path");
|
|
1968
2120
|
|
|
@@ -1985,6 +2137,7 @@ function extractStringField(data, key, defaultValue) {
|
|
|
1985
2137
|
}
|
|
1986
2138
|
|
|
1987
2139
|
// src/core/command-parser.ts
|
|
2140
|
+
init_logger();
|
|
1988
2141
|
async function parseCommandsFromDirectory(commandsDir) {
|
|
1989
2142
|
const commandFiles = await findFiles(commandsDir, ".md");
|
|
1990
2143
|
const commands = [];
|
|
@@ -2771,15 +2924,15 @@ function generateWindsurfIgnore(rules, config, baseDir) {
|
|
|
2771
2924
|
return generateIgnoreFile(rules, config, ignoreConfigs.windsurf, baseDir);
|
|
2772
2925
|
}
|
|
2773
2926
|
|
|
2774
|
-
// src/generators/rules/augmentcode.ts
|
|
2775
|
-
var import_node_path9 = require("path");
|
|
2776
|
-
|
|
2777
2927
|
// src/generators/rules/shared-helpers.ts
|
|
2778
2928
|
var import_node_path8 = require("path");
|
|
2929
|
+
init_file();
|
|
2779
2930
|
|
|
2780
2931
|
// src/utils/ignore.ts
|
|
2781
2932
|
var import_node_path7 = require("path");
|
|
2782
2933
|
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
2934
|
+
init_file();
|
|
2935
|
+
init_logger();
|
|
2783
2936
|
var cachedIgnorePatterns = null;
|
|
2784
2937
|
async function loadIgnorePatterns(baseDir = process.cwd()) {
|
|
2785
2938
|
if (cachedIgnorePatterns) {
|
|
@@ -2930,7 +3083,61 @@ function generateIgnoreFile2(patterns, tool) {
|
|
|
2930
3083
|
return lines.join("\n");
|
|
2931
3084
|
}
|
|
2932
3085
|
|
|
3086
|
+
// src/generators/rules/amazonqcli.ts
|
|
3087
|
+
async function generateAmazonqcliConfig(rules, config, baseDir) {
|
|
3088
|
+
const generatorConfig = {
|
|
3089
|
+
tool: "amazonqcli",
|
|
3090
|
+
fileExtension: ".md",
|
|
3091
|
+
generateContent: generateRuleFile,
|
|
3092
|
+
generateRootContent: generateMainRulesFile,
|
|
3093
|
+
rootFilePath: ".amazonq/rules/main.md",
|
|
3094
|
+
generateDetailContent: generateRuleFile,
|
|
3095
|
+
detailSubDir: ".amazonq/rules"
|
|
3096
|
+
};
|
|
3097
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
3098
|
+
}
|
|
3099
|
+
function generateMainRulesFile(rootRule, detailRules) {
|
|
3100
|
+
const lines = [];
|
|
3101
|
+
if (detailRules.length > 0) {
|
|
3102
|
+
lines.push("# Amazon Q Developer CLI Project Rules");
|
|
3103
|
+
lines.push("");
|
|
3104
|
+
lines.push("This file contains the main project rules. See also:");
|
|
3105
|
+
lines.push("");
|
|
3106
|
+
for (const rule of detailRules) {
|
|
3107
|
+
lines.push(`- ${rule.filename}.md: ${rule.frontmatter.description}`);
|
|
3108
|
+
}
|
|
3109
|
+
lines.push("");
|
|
3110
|
+
}
|
|
3111
|
+
if (rootRule) {
|
|
3112
|
+
if (detailRules.length > 0) {
|
|
3113
|
+
lines.push("## Overview");
|
|
3114
|
+
lines.push("");
|
|
3115
|
+
}
|
|
3116
|
+
lines.push(rootRule.content);
|
|
3117
|
+
lines.push("");
|
|
3118
|
+
} else if (detailRules.length === 0) {
|
|
3119
|
+
lines.push("# Amazon Q Developer CLI Project Rules");
|
|
3120
|
+
lines.push("");
|
|
3121
|
+
lines.push("This file contains project-specific rules and context for Amazon Q Developer CLI.");
|
|
3122
|
+
lines.push("");
|
|
3123
|
+
lines.push("## Development Standards");
|
|
3124
|
+
lines.push("");
|
|
3125
|
+
lines.push("Add your project-specific development standards here.");
|
|
3126
|
+
lines.push("");
|
|
3127
|
+
}
|
|
3128
|
+
return lines.join("\n").trim() + "\n";
|
|
3129
|
+
}
|
|
3130
|
+
function generateRuleFile(rule) {
|
|
3131
|
+
const lines = [];
|
|
3132
|
+
lines.push(`# ${rule.frontmatter.description || rule.filename}`);
|
|
3133
|
+
lines.push("");
|
|
3134
|
+
lines.push(rule.content.trim());
|
|
3135
|
+
lines.push("");
|
|
3136
|
+
return lines.join("\n");
|
|
3137
|
+
}
|
|
3138
|
+
|
|
2933
3139
|
// src/generators/rules/augmentcode.ts
|
|
3140
|
+
var import_node_path9 = require("path");
|
|
2934
3141
|
async function generateAugmentcodeConfig(rules, config, baseDir) {
|
|
2935
3142
|
const outputs = createOutputsArray();
|
|
2936
3143
|
rules.forEach((rule) => {
|
|
@@ -2940,12 +3147,12 @@ async function generateAugmentcodeConfig(rules, config, baseDir) {
|
|
|
2940
3147
|
config,
|
|
2941
3148
|
baseDir,
|
|
2942
3149
|
(0, import_node_path9.join)(".augment", "rules", `${rule.filename}.md`),
|
|
2943
|
-
|
|
3150
|
+
generateRuleFile2(rule)
|
|
2944
3151
|
);
|
|
2945
3152
|
});
|
|
2946
3153
|
return outputs;
|
|
2947
3154
|
}
|
|
2948
|
-
function
|
|
3155
|
+
function generateRuleFile2(rule) {
|
|
2949
3156
|
const lines = [];
|
|
2950
3157
|
lines.push("---");
|
|
2951
3158
|
let ruleType = "manual";
|
|
@@ -2993,6 +3200,8 @@ function generateLegacyGuidelinesFile(allRules) {
|
|
|
2993
3200
|
|
|
2994
3201
|
// src/generators/rules/claudecode.ts
|
|
2995
3202
|
var import_node_path10 = require("path");
|
|
3203
|
+
init_file();
|
|
3204
|
+
init_logger();
|
|
2996
3205
|
async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
2997
3206
|
const generatorConfig = {
|
|
2998
3207
|
tool: "claudecode",
|
|
@@ -3092,6 +3301,22 @@ function determineCursorRuleType(frontmatter) {
|
|
|
3092
3301
|
}
|
|
3093
3302
|
var GENERATOR_REGISTRY = {
|
|
3094
3303
|
// Simple generators - generate one file per rule
|
|
3304
|
+
amazonqcli: {
|
|
3305
|
+
type: "complex",
|
|
3306
|
+
tool: "amazonqcli",
|
|
3307
|
+
fileExtension: ".md",
|
|
3308
|
+
// ignoreFileName omitted - Amazon Q CLI doesn't have native ignore file support yet
|
|
3309
|
+
generateContent: (rule) => {
|
|
3310
|
+
const lines = [];
|
|
3311
|
+
if (rule.frontmatter.description) {
|
|
3312
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
3313
|
+
`);
|
|
3314
|
+
}
|
|
3315
|
+
lines.push(rule.content.trim());
|
|
3316
|
+
return lines.join("\n");
|
|
3317
|
+
}
|
|
3318
|
+
// Complex generation handled by existing generator
|
|
3319
|
+
},
|
|
3095
3320
|
cline: {
|
|
3096
3321
|
type: "simple",
|
|
3097
3322
|
tool: "cline",
|
|
@@ -3258,6 +3483,22 @@ var GENERATOR_REGISTRY = {
|
|
|
3258
3483
|
const lines = [];
|
|
3259
3484
|
if (rule.frontmatter.description) {
|
|
3260
3485
|
lines.push(`# ${rule.frontmatter.description}
|
|
3486
|
+
`);
|
|
3487
|
+
}
|
|
3488
|
+
lines.push(rule.content.trim());
|
|
3489
|
+
return lines.join("\n");
|
|
3490
|
+
}
|
|
3491
|
+
// Complex generation handled by existing generator
|
|
3492
|
+
},
|
|
3493
|
+
opencode: {
|
|
3494
|
+
type: "complex",
|
|
3495
|
+
tool: "opencode",
|
|
3496
|
+
fileExtension: ".md",
|
|
3497
|
+
// ignoreFileName omitted - OpenCode doesn't use dedicated ignore files
|
|
3498
|
+
generateContent: (rule) => {
|
|
3499
|
+
const lines = [];
|
|
3500
|
+
if (rule.frontmatter.description) {
|
|
3501
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
3261
3502
|
`);
|
|
3262
3503
|
}
|
|
3263
3504
|
lines.push(rule.content.trim());
|
|
@@ -3300,8 +3541,8 @@ async function generateFromRegistry(tool, rules, config, baseDir) {
|
|
|
3300
3541
|
const enhancedConfig = {
|
|
3301
3542
|
tool: generatorConfig.tool,
|
|
3302
3543
|
fileExtension: generatorConfig.fileExtension,
|
|
3303
|
-
ignoreFileName: generatorConfig.ignoreFileName,
|
|
3304
3544
|
generateContent: generatorConfig.generateContent,
|
|
3545
|
+
...generatorConfig.ignoreFileName && { ignoreFileName: generatorConfig.ignoreFileName },
|
|
3305
3546
|
...generatorConfig.generateRootContent && {
|
|
3306
3547
|
generateRootContent: generatorConfig.generateRootContent
|
|
3307
3548
|
},
|
|
@@ -3332,48 +3573,91 @@ var generateKiroConfig = createSimpleGenerator("kiro");
|
|
|
3332
3573
|
var generateRooConfig = createSimpleGenerator("roo");
|
|
3333
3574
|
|
|
3334
3575
|
// src/generators/rules/codexcli.ts
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
const
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3576
|
+
init_file();
|
|
3577
|
+
|
|
3578
|
+
// src/utils/xml-document-generator.ts
|
|
3579
|
+
var import_fast_xml_parser = require("fast-xml-parser");
|
|
3580
|
+
function generateRootMarkdownWithXmlDocs(rootRule, memoryRules, config) {
|
|
3581
|
+
const lines = [];
|
|
3582
|
+
if (memoryRules.length > 0) {
|
|
3583
|
+
lines.push(
|
|
3584
|
+
"Please also reference the following documents as needed. In this case, `@` stands for the project root directory."
|
|
3585
|
+
);
|
|
3586
|
+
lines.push("");
|
|
3587
|
+
const documentsData = {
|
|
3588
|
+
Documents: {
|
|
3589
|
+
Document: memoryRules.map((rule) => {
|
|
3590
|
+
const relativePath = `@${config.memorySubDir}/${rule.filename}.md`;
|
|
3591
|
+
const document = {
|
|
3592
|
+
Path: relativePath,
|
|
3593
|
+
Description: rule.frontmatter.description
|
|
3594
|
+
};
|
|
3595
|
+
if (rule.frontmatter.globs.length > 0) {
|
|
3596
|
+
document.FilePatterns = rule.frontmatter.globs.join(", ");
|
|
3597
|
+
}
|
|
3598
|
+
return document;
|
|
3599
|
+
})
|
|
3600
|
+
}
|
|
3601
|
+
};
|
|
3602
|
+
const builder = new import_fast_xml_parser.XMLBuilder({
|
|
3603
|
+
format: true,
|
|
3604
|
+
ignoreAttributes: false,
|
|
3605
|
+
suppressEmptyNode: false
|
|
3353
3606
|
});
|
|
3607
|
+
const xmlContent = builder.build(documentsData);
|
|
3608
|
+
lines.push(xmlContent);
|
|
3609
|
+
lines.push("");
|
|
3610
|
+
lines.push("");
|
|
3354
3611
|
}
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
filepath: ignorePath,
|
|
3362
|
-
content: ignoreContent
|
|
3363
|
-
});
|
|
3612
|
+
if (rootRule) {
|
|
3613
|
+
lines.push(rootRule.content.trim());
|
|
3614
|
+
} else if (memoryRules.length === 0) {
|
|
3615
|
+
lines.push(`# ${config.fallbackTitle}`);
|
|
3616
|
+
lines.push("");
|
|
3617
|
+
lines.push("No configuration rules have been defined yet.");
|
|
3364
3618
|
}
|
|
3365
|
-
return
|
|
3619
|
+
return lines.join("\n");
|
|
3366
3620
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3621
|
+
|
|
3622
|
+
// src/generators/rules/codexcli.ts
|
|
3623
|
+
async function generateCodexConfig(rules, config, baseDir) {
|
|
3624
|
+
const outputs = [];
|
|
3625
|
+
const nonEmptyRules = rules.filter((rule) => rule.content.trim().length > 0);
|
|
3626
|
+
if (nonEmptyRules.length > 0) {
|
|
3627
|
+
const generatorConfig = {
|
|
3628
|
+
tool: "codexcli",
|
|
3629
|
+
fileExtension: ".md",
|
|
3630
|
+
ignoreFileName: ".codexignore",
|
|
3631
|
+
generateContent: generateCodexMemoryMarkdown,
|
|
3632
|
+
generateDetailContent: generateCodexMemoryMarkdown,
|
|
3633
|
+
generateRootContent: generateCodexRootMarkdown,
|
|
3634
|
+
rootFilePath: "AGENTS.md",
|
|
3635
|
+
detailSubDir: ".codex/memories"
|
|
3636
|
+
};
|
|
3637
|
+
const ruleOutputs = await generateComplexRules(nonEmptyRules, config, generatorConfig, baseDir);
|
|
3638
|
+
outputs.push(...ruleOutputs);
|
|
3639
|
+
} else {
|
|
3640
|
+
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
3641
|
+
if (ignorePatterns.patterns.length > 0) {
|
|
3642
|
+
const ignorePath = resolvePath(".codexignore", baseDir);
|
|
3643
|
+
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, "codexcli");
|
|
3644
|
+
outputs.push({
|
|
3645
|
+
tool: "codexcli",
|
|
3646
|
+
filepath: ignorePath,
|
|
3647
|
+
content: ignoreContent
|
|
3648
|
+
});
|
|
3373
3649
|
}
|
|
3374
|
-
sections.push(content);
|
|
3375
3650
|
}
|
|
3376
|
-
return
|
|
3651
|
+
return outputs;
|
|
3652
|
+
}
|
|
3653
|
+
function generateCodexMemoryMarkdown(rule) {
|
|
3654
|
+
return rule.content.trim();
|
|
3655
|
+
}
|
|
3656
|
+
function generateCodexRootMarkdown(rootRule, memoryRules, _baseDir) {
|
|
3657
|
+
return generateRootMarkdownWithXmlDocs(rootRule, memoryRules, {
|
|
3658
|
+
memorySubDir: ".codex/memories",
|
|
3659
|
+
fallbackTitle: "OpenAI Codex CLI Configuration"
|
|
3660
|
+
});
|
|
3377
3661
|
}
|
|
3378
3662
|
|
|
3379
3663
|
// src/generators/rules/geminicli.ts
|
|
@@ -3394,28 +3678,10 @@ function generateGeminiMemoryMarkdown(rule) {
|
|
|
3394
3678
|
return rule.content.trim();
|
|
3395
3679
|
}
|
|
3396
3680
|
function generateGeminiRootMarkdown(rootRule, memoryRules, _baseDir) {
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
lines.push("| Document | Description | File Patterns |");
|
|
3402
|
-
lines.push("|----------|-------------|---------------|");
|
|
3403
|
-
for (const rule of memoryRules) {
|
|
3404
|
-
const relativePath = `@.gemini/memories/${rule.filename}.md`;
|
|
3405
|
-
const filePatterns = rule.frontmatter.globs.length > 0 ? rule.frontmatter.globs.join(", ") : "-";
|
|
3406
|
-
lines.push(`| ${relativePath} | ${rule.frontmatter.description} | ${filePatterns} |`);
|
|
3407
|
-
}
|
|
3408
|
-
lines.push("");
|
|
3409
|
-
lines.push("");
|
|
3410
|
-
}
|
|
3411
|
-
if (rootRule) {
|
|
3412
|
-
lines.push(rootRule.content.trim());
|
|
3413
|
-
} else if (memoryRules.length === 0) {
|
|
3414
|
-
lines.push("# Gemini CLI Configuration");
|
|
3415
|
-
lines.push("");
|
|
3416
|
-
lines.push("No configuration rules have been defined yet.");
|
|
3417
|
-
}
|
|
3418
|
-
return lines.join("\n");
|
|
3681
|
+
return generateRootMarkdownWithXmlDocs(rootRule, memoryRules, {
|
|
3682
|
+
memorySubDir: ".gemini/memories",
|
|
3683
|
+
fallbackTitle: "Gemini CLI Configuration"
|
|
3684
|
+
});
|
|
3419
3685
|
}
|
|
3420
3686
|
|
|
3421
3687
|
// src/generators/rules/junie.ts
|
|
@@ -3445,8 +3711,33 @@ function generateGuidelinesMarkdown(rootRule, detailRules) {
|
|
|
3445
3711
|
return lines.join("\n").trim();
|
|
3446
3712
|
}
|
|
3447
3713
|
|
|
3448
|
-
// src/
|
|
3449
|
-
async function
|
|
3714
|
+
// src/generators/rules/opencode.ts
|
|
3715
|
+
async function generateOpenCodeConfig(rules, config, baseDir) {
|
|
3716
|
+
const generatorConfig = {
|
|
3717
|
+
tool: "opencode",
|
|
3718
|
+
fileExtension: ".md",
|
|
3719
|
+
// ignoreFileName omitted - OpenCode doesn't use dedicated ignore files
|
|
3720
|
+
generateContent: generateOpenCodeMarkdown,
|
|
3721
|
+
generateDetailContent: generateOpenCodeMarkdown,
|
|
3722
|
+
generateRootContent: generateOpenCodeRootMarkdown,
|
|
3723
|
+
rootFilePath: "AGENTS.md",
|
|
3724
|
+
detailSubDir: ".opencode/memories"
|
|
3725
|
+
};
|
|
3726
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
3727
|
+
}
|
|
3728
|
+
function generateOpenCodeMarkdown(rule) {
|
|
3729
|
+
return rule.content.trim();
|
|
3730
|
+
}
|
|
3731
|
+
function generateOpenCodeRootMarkdown(rootRule, memoryRules, _baseDir) {
|
|
3732
|
+
return generateRootMarkdownWithXmlDocs(rootRule, memoryRules, {
|
|
3733
|
+
memorySubDir: ".opencode/memories",
|
|
3734
|
+
fallbackTitle: "OpenCode Configuration"
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
// src/core/generator.ts
|
|
3739
|
+
init_logger();
|
|
3740
|
+
async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
3450
3741
|
const outputs = createOutputsArray();
|
|
3451
3742
|
const toolsToGenerate = targetTools || config.defaultTargets;
|
|
3452
3743
|
const rootFiles = rules.filter((rule) => rule.frontmatter.root === true);
|
|
@@ -3477,6 +3768,8 @@ function filterRulesForTool(rules, tool, config) {
|
|
|
3477
3768
|
}
|
|
3478
3769
|
async function generateForTool(tool, rules, config, baseDir) {
|
|
3479
3770
|
switch (tool) {
|
|
3771
|
+
case "amazonqcli":
|
|
3772
|
+
return await generateAmazonqcliConfig(rules, config, baseDir);
|
|
3480
3773
|
case "augmentcode": {
|
|
3481
3774
|
const augmentRulesOutputs = await generateAugmentcodeConfig(rules, config, baseDir);
|
|
3482
3775
|
const augmentIgnoreOutputs = await generateAugmentCodeIgnoreFiles(rules, config, baseDir);
|
|
@@ -3515,6 +3808,8 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
3515
3808
|
const kiroIgnoreOutputs = await generateKiroIgnoreFiles(rules, config, baseDir);
|
|
3516
3809
|
return [...kiroRulesOutputs, ...kiroIgnoreOutputs];
|
|
3517
3810
|
}
|
|
3811
|
+
case "opencode":
|
|
3812
|
+
return generateOpenCodeConfig(rules, config, baseDir);
|
|
3518
3813
|
case "windsurf": {
|
|
3519
3814
|
const windsurfRulesOutputs = await generateWindsurfConfig(rules, config, baseDir);
|
|
3520
3815
|
const windsurfIgnoreOutputs = await generateWindsurfIgnore(rules, config, baseDir);
|
|
@@ -3528,6 +3823,7 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
3528
3823
|
|
|
3529
3824
|
// src/core/parser.ts
|
|
3530
3825
|
var import_node_path12 = require("path");
|
|
3826
|
+
init_logger();
|
|
3531
3827
|
async function parseRulesFromDirectory(aiRulesDir) {
|
|
3532
3828
|
const ignorePatterns = await loadIgnorePatterns();
|
|
3533
3829
|
const allRuleFiles = await findRuleFiles(aiRulesDir);
|
|
@@ -3648,6 +3944,7 @@ async function validateRule(rule) {
|
|
|
3648
3944
|
var path4 = __toESM(require("path"), 1);
|
|
3649
3945
|
|
|
3650
3946
|
// src/generators/mcp/index.ts
|
|
3947
|
+
init_amazonqcli();
|
|
3651
3948
|
init_augmentcode();
|
|
3652
3949
|
init_claudecode();
|
|
3653
3950
|
init_cline();
|
|
@@ -3660,6 +3957,9 @@ init_kiro();
|
|
|
3660
3957
|
init_roo();
|
|
3661
3958
|
init_windsurf();
|
|
3662
3959
|
|
|
3960
|
+
// src/core/mcp-generator.ts
|
|
3961
|
+
init_file();
|
|
3962
|
+
|
|
3663
3963
|
// src/core/mcp-parser.ts
|
|
3664
3964
|
var fs = __toESM(require("fs"), 1);
|
|
3665
3965
|
var path3 = __toESM(require("path"), 1);
|
|
@@ -3691,6 +3991,35 @@ function parseMcpConfig(projectRoot) {
|
|
|
3691
3991
|
async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
|
|
3692
3992
|
const outputs = [];
|
|
3693
3993
|
const toolMap = {
|
|
3994
|
+
amazonqcli: async (servers, dir) => {
|
|
3995
|
+
const config = {
|
|
3996
|
+
aiRulesDir: ".rulesync",
|
|
3997
|
+
outputPaths: {
|
|
3998
|
+
amazonqcli: ".amazonq/rules",
|
|
3999
|
+
augmentcode: ".",
|
|
4000
|
+
"augmentcode-legacy": ".",
|
|
4001
|
+
copilot: ".github/instructions",
|
|
4002
|
+
cursor: ".cursor/rules",
|
|
4003
|
+
cline: ".clinerules",
|
|
4004
|
+
claudecode: ".",
|
|
4005
|
+
codexcli: ".",
|
|
4006
|
+
opencode: ".",
|
|
4007
|
+
roo: ".roo/rules",
|
|
4008
|
+
geminicli: ".gemini/memories",
|
|
4009
|
+
kiro: ".kiro/steering",
|
|
4010
|
+
junie: ".",
|
|
4011
|
+
windsurf: "."
|
|
4012
|
+
},
|
|
4013
|
+
watchEnabled: false,
|
|
4014
|
+
defaultTargets: []
|
|
4015
|
+
};
|
|
4016
|
+
const results = await (await Promise.resolve().then(() => (init_amazonqcli(), amazonqcli_exports))).generateAmazonqcliMcp(
|
|
4017
|
+
servers,
|
|
4018
|
+
config,
|
|
4019
|
+
dir
|
|
4020
|
+
);
|
|
4021
|
+
return results.map((result) => ({ filepath: result.filepath, content: result.content }));
|
|
4022
|
+
},
|
|
3694
4023
|
augmentcode: async (servers, dir) => (await Promise.resolve().then(() => (init_augmentcode(), augmentcode_exports))).generateAugmentcodeMcpConfiguration(
|
|
3695
4024
|
servers,
|
|
3696
4025
|
dir
|
|
@@ -3707,6 +4036,10 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
|
|
|
3707
4036
|
cursor: async (servers, dir) => (await Promise.resolve().then(() => (init_cursor(), cursor_exports))).generateCursorMcpConfiguration(servers, dir),
|
|
3708
4037
|
cline: async (servers, dir) => (await Promise.resolve().then(() => (init_cline(), cline_exports))).generateClineMcpConfiguration(servers, dir),
|
|
3709
4038
|
codexcli: async (servers, dir) => (await Promise.resolve().then(() => (init_codexcli(), codexcli_exports))).generateCodexMcpConfiguration(servers, dir),
|
|
4039
|
+
opencode: async (servers, dir) => (await Promise.resolve().then(() => (init_opencode(), opencode_exports))).generateOpenCodeMcpConfiguration(
|
|
4040
|
+
servers,
|
|
4041
|
+
dir
|
|
4042
|
+
),
|
|
3710
4043
|
roo: async (servers, dir) => (await Promise.resolve().then(() => (init_roo(), roo_exports))).generateRooMcpConfiguration(servers, dir),
|
|
3711
4044
|
geminicli: async (servers, dir) => (await Promise.resolve().then(() => (init_geminicli(), geminicli_exports))).generateGeminiCliMcpConfiguration(
|
|
3712
4045
|
servers,
|
|
@@ -3736,6 +4069,7 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
|
|
|
3736
4069
|
}
|
|
3737
4070
|
|
|
3738
4071
|
// src/cli/commands/generate.ts
|
|
4072
|
+
init_logger();
|
|
3739
4073
|
async function generateCommand(options = {}) {
|
|
3740
4074
|
const configLoaderOptions = {
|
|
3741
4075
|
...options.config !== void 0 && { configPath: options.config },
|
|
@@ -3851,6 +4185,9 @@ async function generateCommand(options = {}) {
|
|
|
3851
4185
|
case "kiro":
|
|
3852
4186
|
deleteTasks.push(removeDirectory(config.outputPaths.kiro));
|
|
3853
4187
|
break;
|
|
4188
|
+
case "opencode":
|
|
4189
|
+
deleteTasks.push(removeDirectory(config.outputPaths.opencode));
|
|
4190
|
+
break;
|
|
3854
4191
|
case "windsurf":
|
|
3855
4192
|
deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
|
|
3856
4193
|
break;
|
|
@@ -3945,10 +4282,13 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
3945
4282
|
// src/cli/commands/gitignore.ts
|
|
3946
4283
|
var import_node_fs2 = require("fs");
|
|
3947
4284
|
var import_node_path14 = require("path");
|
|
4285
|
+
init_logger();
|
|
3948
4286
|
var gitignoreCommand = async () => {
|
|
3949
4287
|
const gitignorePath = (0, import_node_path14.join)(process.cwd(), ".gitignore");
|
|
3950
4288
|
const rulesFilesToIgnore = [
|
|
3951
4289
|
"# Generated by rulesync - AI tool configuration files",
|
|
4290
|
+
"**/.amazonq/rules/",
|
|
4291
|
+
"**/.amazonq/mcp.json",
|
|
3952
4292
|
"**/.github/copilot-instructions.md",
|
|
3953
4293
|
"**/.github/instructions/",
|
|
3954
4294
|
"**/.cursor/rules/",
|
|
@@ -3974,6 +4314,9 @@ var gitignoreCommand = async () => {
|
|
|
3974
4314
|
"**/.augment-guidelines",
|
|
3975
4315
|
"**/.junie/guidelines.md",
|
|
3976
4316
|
"**/.noai",
|
|
4317
|
+
"**/.opencode/memories/",
|
|
4318
|
+
"**/.opencode/commands/",
|
|
4319
|
+
"**/opencode.json",
|
|
3977
4320
|
"**/.mcp.json",
|
|
3978
4321
|
"!.rulesync/.mcp.json",
|
|
3979
4322
|
"**/.cursor/mcp.json",
|
|
@@ -4015,159 +4358,9 @@ ${linesToAdd.join("\n")}
|
|
|
4015
4358
|
var import_node_path21 = require("path");
|
|
4016
4359
|
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
4017
4360
|
|
|
4018
|
-
// src/parsers/augmentcode.ts
|
|
4019
|
-
var import_node_path15 = require("path");
|
|
4020
|
-
|
|
4021
|
-
// src/utils/parser-helpers.ts
|
|
4022
|
-
function createParseResult() {
|
|
4023
|
-
return { rules: [], errors: [] };
|
|
4024
|
-
}
|
|
4025
|
-
function addError(result, error) {
|
|
4026
|
-
result.errors.push(error);
|
|
4027
|
-
}
|
|
4028
|
-
function addRule(result, rule) {
|
|
4029
|
-
if (!result.rules) {
|
|
4030
|
-
result.rules = [];
|
|
4031
|
-
}
|
|
4032
|
-
result.rules.push(rule);
|
|
4033
|
-
}
|
|
4034
|
-
function addRules(result, rules) {
|
|
4035
|
-
if (!result.rules) {
|
|
4036
|
-
result.rules = [];
|
|
4037
|
-
}
|
|
4038
|
-
result.rules.push(...rules);
|
|
4039
|
-
}
|
|
4040
|
-
async function safeReadFile(operation, errorContext) {
|
|
4041
|
-
try {
|
|
4042
|
-
const result = await operation();
|
|
4043
|
-
return createSuccessResult(result);
|
|
4044
|
-
} catch (error) {
|
|
4045
|
-
return createErrorResult(error, errorContext);
|
|
4046
|
-
}
|
|
4047
|
-
}
|
|
4048
|
-
|
|
4049
|
-
// src/parsers/augmentcode.ts
|
|
4050
|
-
async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
|
|
4051
|
-
return parseUnifiedAugmentcode(baseDir, {
|
|
4052
|
-
rulesDir: ".augment/rules",
|
|
4053
|
-
targetName: "augmentcode",
|
|
4054
|
-
filenamePrefix: "augmentcode"
|
|
4055
|
-
});
|
|
4056
|
-
}
|
|
4057
|
-
async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
4058
|
-
return parseUnifiedAugmentcode(baseDir, {
|
|
4059
|
-
legacyFilePath: ".augment-guidelines",
|
|
4060
|
-
targetName: "augmentcode-legacy",
|
|
4061
|
-
filenamePrefix: "augmentcode-legacy"
|
|
4062
|
-
});
|
|
4063
|
-
}
|
|
4064
|
-
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
4065
|
-
const result = createParseResult();
|
|
4066
|
-
if (config.rulesDir) {
|
|
4067
|
-
const rulesDir = (0, import_node_path15.join)(baseDir, config.rulesDir);
|
|
4068
|
-
if (await fileExists(rulesDir)) {
|
|
4069
|
-
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
4070
|
-
addRules(result, rulesResult.rules);
|
|
4071
|
-
result.errors.push(...rulesResult.errors);
|
|
4072
|
-
} else {
|
|
4073
|
-
addError(
|
|
4074
|
-
result,
|
|
4075
|
-
`No AugmentCode configuration found. Expected ${config.rulesDir} directory.`
|
|
4076
|
-
);
|
|
4077
|
-
}
|
|
4078
|
-
}
|
|
4079
|
-
if (config.legacyFilePath) {
|
|
4080
|
-
const legacyPath = (0, import_node_path15.join)(baseDir, config.legacyFilePath);
|
|
4081
|
-
if (await fileExists(legacyPath)) {
|
|
4082
|
-
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
4083
|
-
if (legacyResult.rule) {
|
|
4084
|
-
addRule(result, legacyResult.rule);
|
|
4085
|
-
}
|
|
4086
|
-
result.errors.push(...legacyResult.errors);
|
|
4087
|
-
} else {
|
|
4088
|
-
addError(
|
|
4089
|
-
result,
|
|
4090
|
-
`No AugmentCode legacy configuration found. Expected ${config.legacyFilePath} file.`
|
|
4091
|
-
);
|
|
4092
|
-
}
|
|
4093
|
-
}
|
|
4094
|
-
return { rules: result.rules || [], errors: result.errors };
|
|
4095
|
-
}
|
|
4096
|
-
async function parseAugmentRules(rulesDir, config) {
|
|
4097
|
-
const rules = [];
|
|
4098
|
-
const errors = [];
|
|
4099
|
-
try {
|
|
4100
|
-
const { readdir: readdir2 } = await import("fs/promises");
|
|
4101
|
-
const files = await readdir2(rulesDir);
|
|
4102
|
-
for (const file of files) {
|
|
4103
|
-
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
4104
|
-
const filePath = (0, import_node_path15.join)(rulesDir, file);
|
|
4105
|
-
try {
|
|
4106
|
-
const rawContent = await readFileContent(filePath);
|
|
4107
|
-
const parsed = parseFrontmatter(rawContent);
|
|
4108
|
-
const ruleType = extractStringField(parsed.data, "type", "manual");
|
|
4109
|
-
const description = extractStringField(parsed.data, "description", "");
|
|
4110
|
-
const tags = extractArrayField(parsed.data, "tags");
|
|
4111
|
-
const isRoot = ruleType === "always";
|
|
4112
|
-
const filename = (0, import_node_path15.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
|
|
4113
|
-
const frontmatter = {
|
|
4114
|
-
root: isRoot,
|
|
4115
|
-
targets: [config.targetName],
|
|
4116
|
-
description,
|
|
4117
|
-
globs: ["**/*"],
|
|
4118
|
-
// AugmentCode doesn't use specific globs in the same way
|
|
4119
|
-
...tags.length > 0 && { tags }
|
|
4120
|
-
};
|
|
4121
|
-
rules.push({
|
|
4122
|
-
frontmatter,
|
|
4123
|
-
content: parsed.content.trim(),
|
|
4124
|
-
filename: `${config.filenamePrefix}-${ruleType}-${filename}`,
|
|
4125
|
-
filepath: filePath
|
|
4126
|
-
});
|
|
4127
|
-
} catch (error) {
|
|
4128
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4129
|
-
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
4130
|
-
}
|
|
4131
|
-
}
|
|
4132
|
-
}
|
|
4133
|
-
} catch (error) {
|
|
4134
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4135
|
-
errors.push(`Failed to read ${config.rulesDir || rulesDir} directory: ${errorMessage}`);
|
|
4136
|
-
}
|
|
4137
|
-
return { rules, errors };
|
|
4138
|
-
}
|
|
4139
|
-
async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
4140
|
-
const parseResult = await safeReadFile(
|
|
4141
|
-
async () => {
|
|
4142
|
-
const content = await readFileContent(guidelinesPath);
|
|
4143
|
-
if (content.trim()) {
|
|
4144
|
-
const frontmatter = {
|
|
4145
|
-
root: true,
|
|
4146
|
-
// Legacy guidelines become root rules
|
|
4147
|
-
targets: [config.targetName],
|
|
4148
|
-
description: "Legacy AugmentCode guidelines",
|
|
4149
|
-
globs: ["**/*"]
|
|
4150
|
-
};
|
|
4151
|
-
return {
|
|
4152
|
-
frontmatter,
|
|
4153
|
-
content: content.trim(),
|
|
4154
|
-
filename: `${config.filenamePrefix}-guidelines`,
|
|
4155
|
-
filepath: guidelinesPath
|
|
4156
|
-
};
|
|
4157
|
-
}
|
|
4158
|
-
return null;
|
|
4159
|
-
},
|
|
4160
|
-
`Failed to parse ${config.legacyFilePath || guidelinesPath}`
|
|
4161
|
-
);
|
|
4162
|
-
if (parseResult.success) {
|
|
4163
|
-
return { rule: parseResult.result || null, errors: [] };
|
|
4164
|
-
} else {
|
|
4165
|
-
return { rule: null, errors: [parseResult.error || "Unknown error"] };
|
|
4166
|
-
}
|
|
4167
|
-
}
|
|
4168
|
-
|
|
4169
4361
|
// src/parsers/shared-helpers.ts
|
|
4170
|
-
var
|
|
4362
|
+
var import_node_path15 = require("path");
|
|
4363
|
+
init_file();
|
|
4171
4364
|
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
4172
4365
|
const errors = [];
|
|
4173
4366
|
const rules = [];
|
|
@@ -4224,7 +4417,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
4224
4417
|
const files = await readdir2(dirPath);
|
|
4225
4418
|
for (const file of files) {
|
|
4226
4419
|
if (file.endsWith(dirConfig.filePattern)) {
|
|
4227
|
-
const filePath = (0,
|
|
4420
|
+
const filePath = (0, import_node_path15.join)(dirPath, file);
|
|
4228
4421
|
const fileResult = await safeAsyncOperation(async () => {
|
|
4229
4422
|
const rawContent = await readFileContent(filePath);
|
|
4230
4423
|
let content;
|
|
@@ -4375,10 +4568,10 @@ async function parseMemoryFiles(memoryDir, config) {
|
|
|
4375
4568
|
const files = await readdir2(memoryDir);
|
|
4376
4569
|
for (const file of files) {
|
|
4377
4570
|
if (file.endsWith(".md")) {
|
|
4378
|
-
const filePath = (0,
|
|
4571
|
+
const filePath = (0, import_node_path15.join)(memoryDir, file);
|
|
4379
4572
|
const content = await readFileContent(filePath);
|
|
4380
4573
|
if (content.trim()) {
|
|
4381
|
-
const filename = (0,
|
|
4574
|
+
const filename = (0, import_node_path15.basename)(file, ".md");
|
|
4382
4575
|
const frontmatter = {
|
|
4383
4576
|
root: false,
|
|
4384
4577
|
targets: [config.tool],
|
|
@@ -4405,10 +4598,10 @@ async function parseCommandsFiles(commandsDir, config) {
|
|
|
4405
4598
|
const files = await readdir2(commandsDir);
|
|
4406
4599
|
for (const file of files) {
|
|
4407
4600
|
if (file.endsWith(".md")) {
|
|
4408
|
-
const filePath = (0,
|
|
4601
|
+
const filePath = (0, import_node_path15.join)(commandsDir, file);
|
|
4409
4602
|
const content = await readFileContent(filePath);
|
|
4410
4603
|
if (content.trim()) {
|
|
4411
|
-
const filename = (0,
|
|
4604
|
+
const filename = (0, import_node_path15.basename)(file, ".md");
|
|
4412
4605
|
let frontmatter;
|
|
4413
4606
|
let ruleContent;
|
|
4414
4607
|
try {
|
|
@@ -4483,6 +4676,170 @@ async function parseSettingsFile(settingsPath, tool) {
|
|
|
4483
4676
|
};
|
|
4484
4677
|
}
|
|
4485
4678
|
|
|
4679
|
+
// src/parsers/amazonqcli.ts
|
|
4680
|
+
async function parseAmazonqcliConfiguration(baseDir = process.cwd()) {
|
|
4681
|
+
return parseMemoryBasedConfiguration(baseDir, {
|
|
4682
|
+
tool: "amazonqcli",
|
|
4683
|
+
mainFileName: ".amazonq/rules/main.md",
|
|
4684
|
+
memoryDirPath: ".amazonq/rules",
|
|
4685
|
+
settingsPath: ".amazonq/mcp.json",
|
|
4686
|
+
mainDescription: "Main Amazon Q Developer CLI configuration",
|
|
4687
|
+
memoryDescription: "Amazon Q rule",
|
|
4688
|
+
filenamePrefix: "amazonq"
|
|
4689
|
+
});
|
|
4690
|
+
}
|
|
4691
|
+
|
|
4692
|
+
// src/parsers/augmentcode.ts
|
|
4693
|
+
var import_node_path16 = require("path");
|
|
4694
|
+
|
|
4695
|
+
// src/utils/parser-helpers.ts
|
|
4696
|
+
function createParseResult() {
|
|
4697
|
+
return { rules: [], errors: [] };
|
|
4698
|
+
}
|
|
4699
|
+
function addError(result, error) {
|
|
4700
|
+
result.errors.push(error);
|
|
4701
|
+
}
|
|
4702
|
+
function addRule(result, rule) {
|
|
4703
|
+
if (!result.rules) {
|
|
4704
|
+
result.rules = [];
|
|
4705
|
+
}
|
|
4706
|
+
result.rules.push(rule);
|
|
4707
|
+
}
|
|
4708
|
+
function addRules(result, rules) {
|
|
4709
|
+
if (!result.rules) {
|
|
4710
|
+
result.rules = [];
|
|
4711
|
+
}
|
|
4712
|
+
result.rules.push(...rules);
|
|
4713
|
+
}
|
|
4714
|
+
async function safeReadFile(operation, errorContext) {
|
|
4715
|
+
try {
|
|
4716
|
+
const result = await operation();
|
|
4717
|
+
return createSuccessResult(result);
|
|
4718
|
+
} catch (error) {
|
|
4719
|
+
return createErrorResult(error, errorContext);
|
|
4720
|
+
}
|
|
4721
|
+
}
|
|
4722
|
+
|
|
4723
|
+
// src/parsers/augmentcode.ts
|
|
4724
|
+
async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
|
|
4725
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
4726
|
+
rulesDir: ".augment/rules",
|
|
4727
|
+
targetName: "augmentcode",
|
|
4728
|
+
filenamePrefix: "augmentcode"
|
|
4729
|
+
});
|
|
4730
|
+
}
|
|
4731
|
+
async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
4732
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
4733
|
+
legacyFilePath: ".augment-guidelines",
|
|
4734
|
+
targetName: "augmentcode-legacy",
|
|
4735
|
+
filenamePrefix: "augmentcode-legacy"
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
4739
|
+
const result = createParseResult();
|
|
4740
|
+
if (config.rulesDir) {
|
|
4741
|
+
const rulesDir = (0, import_node_path16.join)(baseDir, config.rulesDir);
|
|
4742
|
+
if (await fileExists(rulesDir)) {
|
|
4743
|
+
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
4744
|
+
addRules(result, rulesResult.rules);
|
|
4745
|
+
result.errors.push(...rulesResult.errors);
|
|
4746
|
+
} else {
|
|
4747
|
+
addError(
|
|
4748
|
+
result,
|
|
4749
|
+
`No AugmentCode configuration found. Expected ${config.rulesDir} directory.`
|
|
4750
|
+
);
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
if (config.legacyFilePath) {
|
|
4754
|
+
const legacyPath = (0, import_node_path16.join)(baseDir, config.legacyFilePath);
|
|
4755
|
+
if (await fileExists(legacyPath)) {
|
|
4756
|
+
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
4757
|
+
if (legacyResult.rule) {
|
|
4758
|
+
addRule(result, legacyResult.rule);
|
|
4759
|
+
}
|
|
4760
|
+
result.errors.push(...legacyResult.errors);
|
|
4761
|
+
} else {
|
|
4762
|
+
addError(
|
|
4763
|
+
result,
|
|
4764
|
+
`No AugmentCode legacy configuration found. Expected ${config.legacyFilePath} file.`
|
|
4765
|
+
);
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
return { rules: result.rules || [], errors: result.errors };
|
|
4769
|
+
}
|
|
4770
|
+
async function parseAugmentRules(rulesDir, config) {
|
|
4771
|
+
const rules = [];
|
|
4772
|
+
const errors = [];
|
|
4773
|
+
try {
|
|
4774
|
+
const { readdir: readdir2 } = await import("fs/promises");
|
|
4775
|
+
const files = await readdir2(rulesDir);
|
|
4776
|
+
for (const file of files) {
|
|
4777
|
+
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
4778
|
+
const filePath = (0, import_node_path16.join)(rulesDir, file);
|
|
4779
|
+
try {
|
|
4780
|
+
const rawContent = await readFileContent(filePath);
|
|
4781
|
+
const parsed = parseFrontmatter(rawContent);
|
|
4782
|
+
const ruleType = extractStringField(parsed.data, "type", "manual");
|
|
4783
|
+
const description = extractStringField(parsed.data, "description", "");
|
|
4784
|
+
const tags = extractArrayField(parsed.data, "tags");
|
|
4785
|
+
const isRoot = ruleType === "always";
|
|
4786
|
+
const filename = (0, import_node_path16.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
|
|
4787
|
+
const frontmatter = {
|
|
4788
|
+
root: isRoot,
|
|
4789
|
+
targets: [config.targetName],
|
|
4790
|
+
description,
|
|
4791
|
+
globs: ["**/*"],
|
|
4792
|
+
// AugmentCode doesn't use specific globs in the same way
|
|
4793
|
+
...tags.length > 0 && { tags }
|
|
4794
|
+
};
|
|
4795
|
+
rules.push({
|
|
4796
|
+
frontmatter,
|
|
4797
|
+
content: parsed.content.trim(),
|
|
4798
|
+
filename: `${config.filenamePrefix}-${ruleType}-${filename}`,
|
|
4799
|
+
filepath: filePath
|
|
4800
|
+
});
|
|
4801
|
+
} catch (error) {
|
|
4802
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4803
|
+
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
4804
|
+
}
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
} catch (error) {
|
|
4808
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4809
|
+
errors.push(`Failed to read ${config.rulesDir || rulesDir} directory: ${errorMessage}`);
|
|
4810
|
+
}
|
|
4811
|
+
return { rules, errors };
|
|
4812
|
+
}
|
|
4813
|
+
async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
4814
|
+
const parseResult = await safeReadFile(
|
|
4815
|
+
async () => {
|
|
4816
|
+
const content = await readFileContent(guidelinesPath);
|
|
4817
|
+
if (content.trim()) {
|
|
4818
|
+
const frontmatter = {
|
|
4819
|
+
root: true,
|
|
4820
|
+
// Legacy guidelines become root rules
|
|
4821
|
+
targets: [config.targetName],
|
|
4822
|
+
description: "Legacy AugmentCode guidelines",
|
|
4823
|
+
globs: ["**/*"]
|
|
4824
|
+
};
|
|
4825
|
+
return {
|
|
4826
|
+
frontmatter,
|
|
4827
|
+
content: content.trim(),
|
|
4828
|
+
filename: `${config.filenamePrefix}-guidelines`,
|
|
4829
|
+
filepath: guidelinesPath
|
|
4830
|
+
};
|
|
4831
|
+
}
|
|
4832
|
+
return null;
|
|
4833
|
+
},
|
|
4834
|
+
`Failed to parse ${config.legacyFilePath || guidelinesPath}`
|
|
4835
|
+
);
|
|
4836
|
+
if (parseResult.success) {
|
|
4837
|
+
return { rule: parseResult.result || null, errors: [] };
|
|
4838
|
+
} else {
|
|
4839
|
+
return { rule: null, errors: [parseResult.error || "Unknown error"] };
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
|
|
4486
4843
|
// src/parsers/claudecode.ts
|
|
4487
4844
|
async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
4488
4845
|
return parseMemoryBasedConfiguration(baseDir, {
|
|
@@ -4820,6 +5177,32 @@ async function parseJunieConfiguration(baseDir = process.cwd()) {
|
|
|
4820
5177
|
return { rules, errors };
|
|
4821
5178
|
}
|
|
4822
5179
|
|
|
5180
|
+
// src/parsers/opencode.ts
|
|
5181
|
+
async function parseOpCodeIgnore(opcodeignorePath) {
|
|
5182
|
+
try {
|
|
5183
|
+
const content = await readFileContent(opcodeignorePath);
|
|
5184
|
+
const patterns = content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
5185
|
+
return patterns;
|
|
5186
|
+
} catch {
|
|
5187
|
+
return [];
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
async function parseOpenCodeConfiguration(baseDir = process.cwd()) {
|
|
5191
|
+
return parseMemoryBasedConfiguration(baseDir, {
|
|
5192
|
+
tool: "opencode",
|
|
5193
|
+
mainFileName: "AGENTS.md",
|
|
5194
|
+
memoryDirPath: ".opencode/memories",
|
|
5195
|
+
settingsPath: "opencode.json",
|
|
5196
|
+
mainDescription: "Main OpenCode configuration",
|
|
5197
|
+
memoryDescription: "Memory file",
|
|
5198
|
+
filenamePrefix: "opencode",
|
|
5199
|
+
additionalIgnoreFile: {
|
|
5200
|
+
path: ".opcodeignore",
|
|
5201
|
+
parser: parseOpCodeIgnore
|
|
5202
|
+
}
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
|
|
4823
5206
|
// src/parsers/roo.ts
|
|
4824
5207
|
async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
4825
5208
|
return parseConfigurationFiles(baseDir, {
|
|
@@ -4843,8 +5226,10 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
4843
5226
|
// src/parsers/windsurf.ts
|
|
4844
5227
|
var import_promises3 = require("fs/promises");
|
|
4845
5228
|
var import_node_path20 = require("path");
|
|
5229
|
+
init_logger();
|
|
4846
5230
|
|
|
4847
5231
|
// src/core/importer.ts
|
|
5232
|
+
init_logger();
|
|
4848
5233
|
async function importConfiguration(options) {
|
|
4849
5234
|
const {
|
|
4850
5235
|
tool,
|
|
@@ -4862,6 +5247,13 @@ async function importConfiguration(options) {
|
|
|
4862
5247
|
}
|
|
4863
5248
|
try {
|
|
4864
5249
|
switch (tool) {
|
|
5250
|
+
case "amazonqcli": {
|
|
5251
|
+
const amazonqResult = await parseAmazonqcliConfiguration(baseDir);
|
|
5252
|
+
rules = amazonqResult.rules;
|
|
5253
|
+
errors.push(...amazonqResult.errors);
|
|
5254
|
+
mcpServers = amazonqResult.mcpServers;
|
|
5255
|
+
break;
|
|
5256
|
+
}
|
|
4865
5257
|
case "augmentcode": {
|
|
4866
5258
|
const augmentResult = await parseAugmentcodeConfiguration(baseDir);
|
|
4867
5259
|
rules = augmentResult.rules;
|
|
@@ -4922,6 +5314,14 @@ async function importConfiguration(options) {
|
|
|
4922
5314
|
errors.push(...junieResult.errors);
|
|
4923
5315
|
break;
|
|
4924
5316
|
}
|
|
5317
|
+
case "opencode": {
|
|
5318
|
+
const opencodeResult = await parseOpenCodeConfiguration(baseDir);
|
|
5319
|
+
rules = opencodeResult.rules;
|
|
5320
|
+
errors.push(...opencodeResult.errors);
|
|
5321
|
+
ignorePatterns = opencodeResult.ignorePatterns;
|
|
5322
|
+
mcpServers = opencodeResult.mcpServers;
|
|
5323
|
+
break;
|
|
5324
|
+
}
|
|
4925
5325
|
default:
|
|
4926
5326
|
errors.push(`Unsupported tool: ${tool}`);
|
|
4927
5327
|
return { success: false, rulesCreated: 0, errors };
|
|
@@ -5025,9 +5425,11 @@ function generateRuleFileContent(rule) {
|
|
|
5025
5425
|
}
|
|
5026
5426
|
|
|
5027
5427
|
// src/cli/commands/import.ts
|
|
5428
|
+
init_logger();
|
|
5028
5429
|
async function importCommand(options = {}) {
|
|
5029
5430
|
logger.setVerbose(options.verbose || false);
|
|
5030
5431
|
const tools = [];
|
|
5432
|
+
if (options.amazonqcli) tools.push("amazonqcli");
|
|
5031
5433
|
if (options.augmentcode) tools.push("augmentcode");
|
|
5032
5434
|
if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
|
|
5033
5435
|
if (options.claudecode) tools.push("claudecode");
|
|
@@ -5036,9 +5438,10 @@ async function importCommand(options = {}) {
|
|
|
5036
5438
|
if (options.cline) tools.push("cline");
|
|
5037
5439
|
if (options.roo) tools.push("roo");
|
|
5038
5440
|
if (options.geminicli) tools.push("geminicli");
|
|
5441
|
+
if (options.opencode) tools.push("opencode");
|
|
5039
5442
|
if (tools.length === 0) {
|
|
5040
5443
|
logger.error(
|
|
5041
|
-
"\u274C Please specify one tool to import from (--augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli)"
|
|
5444
|
+
"\u274C Please specify one tool to import from (--amazonqcli, --augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli, --opencode)"
|
|
5042
5445
|
);
|
|
5043
5446
|
process.exit(1);
|
|
5044
5447
|
}
|
|
@@ -5087,6 +5490,7 @@ async function importCommand(options = {}) {
|
|
|
5087
5490
|
|
|
5088
5491
|
// src/cli/commands/init.ts
|
|
5089
5492
|
var import_node_path22 = require("path");
|
|
5493
|
+
init_logger();
|
|
5090
5494
|
async function initCommand(options = {}) {
|
|
5091
5495
|
const configResult = await loadConfig();
|
|
5092
5496
|
const config = configResult.config;
|
|
@@ -5150,6 +5554,7 @@ globs: ["**/*"]
|
|
|
5150
5554
|
}
|
|
5151
5555
|
|
|
5152
5556
|
// src/cli/commands/status.ts
|
|
5557
|
+
init_logger();
|
|
5153
5558
|
async function statusCommand() {
|
|
5154
5559
|
const config = getDefaultConfig();
|
|
5155
5560
|
logger.log("rulesync Status");
|
|
@@ -5202,6 +5607,7 @@ async function statusCommand() {
|
|
|
5202
5607
|
}
|
|
5203
5608
|
|
|
5204
5609
|
// src/cli/commands/validate.ts
|
|
5610
|
+
init_logger();
|
|
5205
5611
|
async function validateCommand() {
|
|
5206
5612
|
const config = getDefaultConfig();
|
|
5207
5613
|
logger.log("Validating rulesync configuration...");
|
|
@@ -5244,6 +5650,7 @@ Validation failed with ${validation.errors.length} error(s)`);
|
|
|
5244
5650
|
|
|
5245
5651
|
// src/cli/commands/watch.ts
|
|
5246
5652
|
var import_chokidar = require("chokidar");
|
|
5653
|
+
init_logger();
|
|
5247
5654
|
async function watchCommand() {
|
|
5248
5655
|
const config = getDefaultConfig();
|
|
5249
5656
|
logger.log("\u{1F440} Watching for changes in .rulesync directory...");
|
|
@@ -5284,12 +5691,12 @@ async function watchCommand() {
|
|
|
5284
5691
|
|
|
5285
5692
|
// src/cli/index.ts
|
|
5286
5693
|
var program = new import_commander.Command();
|
|
5287
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
5694
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.64.0");
|
|
5288
5695
|
program.command("init").description("Initialize rulesync in current directory").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(initCommand);
|
|
5289
5696
|
program.command("add <filename>").description("Add a new rule file").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(addCommand);
|
|
5290
5697
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
5291
|
-
program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcode-legacy", "Import from AugmentCode legacy format (.augment-guidelines)").option("--claudecode", "Import from Claude Code (CLAUDE.md)").option("--cursor", "Import from Cursor (.cursorrules)").option("--copilot", "Import from GitHub Copilot (.github/copilot-instructions.md)").option("--cline", "Import from Cline (.cline/instructions.md)").option("--roo", "Import from Roo Code (.roo/instructions.md)").option("--geminicli", "Import from Gemini CLI (GEMINI.md)").option("--junie", "Import from JetBrains Junie (.junie/guidelines.md)").option("-v, --verbose", "Verbose output").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(importCommand);
|
|
5292
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "Generate only for AugmentCode legacy format").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--codexcli", "Generate only for OpenAI Codex CLI").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--kiro", "Generate only for Kiro IDE").option("--windsurf", "Generate only for Windsurf").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
5698
|
+
program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcode-legacy", "Import from AugmentCode legacy format (.augment-guidelines)").option("--claudecode", "Import from Claude Code (CLAUDE.md)").option("--cursor", "Import from Cursor (.cursorrules)").option("--copilot", "Import from GitHub Copilot (.github/copilot-instructions.md)").option("--cline", "Import from Cline (.cline/instructions.md)").option("--roo", "Import from Roo Code (.roo/instructions.md)").option("--geminicli", "Import from Gemini CLI (GEMINI.md)").option("--junie", "Import from JetBrains Junie (.junie/guidelines.md)").option("--opencode", "Import from OpenCode (AGENTS.md)").option("-v, --verbose", "Verbose output").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(importCommand);
|
|
5699
|
+
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "Generate only for AugmentCode legacy format").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--codexcli", "Generate only for OpenAI Codex CLI").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--kiro", "Generate only for Kiro IDE").option("--opencode", "Generate only for OpenCode").option("--windsurf", "Generate only for Windsurf").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
5293
5700
|
"-b, --base-dir <paths>",
|
|
5294
5701
|
"Base directories to generate files (comma-separated for multiple paths)"
|
|
5295
5702
|
).option("-v, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("--no-config", "Disable configuration file loading").action(async (options) => {
|
|
@@ -5305,6 +5712,7 @@ program.command("generate").description("Generate configuration files for AI too
|
|
|
5305
5712
|
if (options.geminicli) tools.push("geminicli");
|
|
5306
5713
|
if (options.junie) tools.push("junie");
|
|
5307
5714
|
if (options.kiro) tools.push("kiro");
|
|
5715
|
+
if (options.opencode) tools.push("opencode");
|
|
5308
5716
|
if (options.windsurf) tools.push("windsurf");
|
|
5309
5717
|
const generateOptions = {
|
|
5310
5718
|
verbose: options.verbose,
|