rulesync 0.54.0 → 0.56.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.ja.md +67 -5
- package/README.md +77 -6
- package/dist/{augmentcode-MJYD2Y4S.js → augmentcode-HIZIQG2W.js} +2 -2
- package/dist/chunk-7E4U4YAB.js +17 -0
- package/dist/{chunk-D7XQ4OHK.js → chunk-7UBF4OLN.js} +1 -1
- package/dist/{chunk-VI6SBYFB.js → chunk-AUUSMVCT.js} +2 -1
- package/dist/chunk-J3TBR5EP.js +292 -0
- package/dist/{chunk-OXKDEZJK.js → chunk-KUGTKMNW.js} +1 -1
- package/dist/{chunk-QVPD6ENS.js → chunk-LXTA7DBA.js} +1 -1
- package/dist/chunk-OA473EXZ.js +17 -0
- package/dist/{chunk-BEPSWIZC.js → chunk-PCATT4UZ.js} +1 -1
- package/dist/chunk-VKNCBVZF.js +17 -0
- package/dist/chunk-VNT6AHHO.js +17 -0
- package/dist/chunk-W2WU253H.js +17 -0
- package/dist/chunk-WAX2UANS.js +61 -0
- package/dist/{chunk-ORNO5MOO.js → chunk-YTU3SCQO.js} +1 -1
- package/dist/{claudecode-CKGUHLRR.js → claudecode-VVI2PTKI.js} +3 -3
- package/dist/{cline-Z5C656VR.js → cline-BJLFSLEB.js} +3 -3
- package/dist/{codexcli-VFUJKSIJ.js → codexcli-LKWQB3V3.js} +3 -3
- package/dist/{copilot-4WQS5TA7.js → copilot-MOR3HHJX.js} +2 -2
- package/dist/{cursor-HOB2F2V2.js → cursor-2BVUO64T.js} +3 -2
- package/dist/{geminicli-XTMQTIU2.js → geminicli-5YFMKRFL.js} +3 -2
- package/dist/index.cjs +898 -493
- package/dist/index.js +669 -337
- package/dist/{junie-AN6CR7DD.js → junie-5TDJPUXX.js} +3 -2
- package/dist/{kiro-PTUZOHQ2.js → kiro-YDHXY2MA.js} +2 -2
- package/dist/{roo-WOMS36KU.js → roo-L3QTTIPO.js} +2 -2
- package/dist/windsurf-PXDRIQ76.js +10 -0
- package/package.json +1 -1
- package/dist/chunk-3PHMFVXP.js +0 -66
- package/dist/chunk-OY6BYYIX.js +0 -63
- package/dist/chunk-PPAQWVXX.js +0 -94
- package/dist/chunk-TJKD6LEW.js +0 -90
- package/dist/chunk-UHANRG2O.js +0 -54
- package/dist/chunk-UZCJNUXO.js +0 -67
package/dist/index.cjs
CHANGED
|
@@ -47,7 +47,8 @@ var init_tool_targets = __esm({
|
|
|
47
47
|
"roo",
|
|
48
48
|
"geminicli",
|
|
49
49
|
"kiro",
|
|
50
|
-
"junie"
|
|
50
|
+
"junie",
|
|
51
|
+
"windsurf"
|
|
51
52
|
];
|
|
52
53
|
ToolTargetSchema = import_mini.z.enum(ALL_TOOL_TARGETS);
|
|
53
54
|
ToolTargetsSchema = import_mini.z.array(ToolTargetSchema);
|
|
@@ -147,11 +148,72 @@ function generateMcpConfig(config, toolConfig) {
|
|
|
147
148
|
const finalConfig = toolConfig.configWrapper(servers);
|
|
148
149
|
return JSON.stringify(finalConfig, null, 2);
|
|
149
150
|
}
|
|
150
|
-
|
|
151
|
+
function generateMcpFromRegistry(tool, config) {
|
|
152
|
+
const generatorConfig = MCP_GENERATOR_REGISTRY[tool];
|
|
153
|
+
if (!generatorConfig) {
|
|
154
|
+
throw new Error(`No MCP generator configuration found for tool: ${tool}`);
|
|
155
|
+
}
|
|
156
|
+
return generateMcpConfig(config, generatorConfig);
|
|
157
|
+
}
|
|
158
|
+
var serverTransforms, configWrappers, MCP_GENERATOR_REGISTRY;
|
|
151
159
|
var init_shared_factory = __esm({
|
|
152
160
|
"src/generators/mcp/shared-factory.ts"() {
|
|
153
161
|
"use strict";
|
|
154
162
|
init_mcp_helpers();
|
|
163
|
+
serverTransforms = {
|
|
164
|
+
/**
|
|
165
|
+
* Basic server transformation (command, args, env, url handling)
|
|
166
|
+
*/
|
|
167
|
+
basic: (server) => {
|
|
168
|
+
const result = {};
|
|
169
|
+
if (server.command) {
|
|
170
|
+
result.command = server.command;
|
|
171
|
+
if (server.args) result.args = server.args;
|
|
172
|
+
} else if (server.url || server.httpUrl) {
|
|
173
|
+
const url = server.httpUrl || server.url;
|
|
174
|
+
if (url) result.url = url;
|
|
175
|
+
}
|
|
176
|
+
if (server.env) {
|
|
177
|
+
result.env = server.env;
|
|
178
|
+
}
|
|
179
|
+
return result;
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Extended server transformation (includes disabled, alwaysAllow, etc.)
|
|
183
|
+
*/
|
|
184
|
+
extended: (server) => {
|
|
185
|
+
const result = serverTransforms.basic(server);
|
|
186
|
+
if (server.disabled !== void 0) {
|
|
187
|
+
result.disabled = server.disabled;
|
|
188
|
+
}
|
|
189
|
+
if (server.alwaysAllow) {
|
|
190
|
+
result.alwaysAllow = server.alwaysAllow;
|
|
191
|
+
}
|
|
192
|
+
if (server.networkTimeout !== void 0) {
|
|
193
|
+
result.networkTimeout = server.networkTimeout;
|
|
194
|
+
}
|
|
195
|
+
if (server.tools) {
|
|
196
|
+
result.tools = server.tools;
|
|
197
|
+
}
|
|
198
|
+
if (server.timeout !== void 0) {
|
|
199
|
+
result.timeout = server.timeout;
|
|
200
|
+
}
|
|
201
|
+
if (server.trust !== void 0) {
|
|
202
|
+
result.trust = server.trust;
|
|
203
|
+
}
|
|
204
|
+
if (server.headers) {
|
|
205
|
+
result.headers = server.headers;
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* Remove rulesync-specific properties from server config
|
|
211
|
+
*/
|
|
212
|
+
cleanRulesyncProps: (server) => {
|
|
213
|
+
const { targets: _, transport: _transport, ...cleanServer } = server;
|
|
214
|
+
return { ...cleanServer };
|
|
215
|
+
}
|
|
216
|
+
};
|
|
155
217
|
configWrappers = {
|
|
156
218
|
/**
|
|
157
219
|
* Standard mcpServers wrapper
|
|
@@ -166,37 +228,141 @@ var init_shared_factory = __esm({
|
|
|
166
228
|
servers
|
|
167
229
|
})
|
|
168
230
|
};
|
|
231
|
+
MCP_GENERATOR_REGISTRY = {
|
|
232
|
+
claudecode: {
|
|
233
|
+
target: "claudecode",
|
|
234
|
+
configPaths: [".claude/settings.json"],
|
|
235
|
+
serverTransform: (server) => {
|
|
236
|
+
const claudeServer = {};
|
|
237
|
+
if (server.command) {
|
|
238
|
+
claudeServer.command = server.command;
|
|
239
|
+
if (server.args) claudeServer.args = server.args;
|
|
240
|
+
} else if (server.url || server.httpUrl) {
|
|
241
|
+
const url = server.httpUrl || server.url;
|
|
242
|
+
if (url) {
|
|
243
|
+
claudeServer.url = url;
|
|
244
|
+
}
|
|
245
|
+
if (server.httpUrl) {
|
|
246
|
+
claudeServer.transport = "http";
|
|
247
|
+
} else if (server.transport === "sse") {
|
|
248
|
+
claudeServer.transport = "sse";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (server.env) {
|
|
252
|
+
claudeServer.env = server.env;
|
|
253
|
+
}
|
|
254
|
+
return claudeServer;
|
|
255
|
+
},
|
|
256
|
+
configWrapper: configWrappers.mcpServers
|
|
257
|
+
},
|
|
258
|
+
cursor: {
|
|
259
|
+
target: "cursor",
|
|
260
|
+
configPaths: [".cursor/mcp.json"],
|
|
261
|
+
serverTransform: (server) => {
|
|
262
|
+
const cursorServer = {};
|
|
263
|
+
if (server.command) {
|
|
264
|
+
cursorServer.command = server.command;
|
|
265
|
+
if (server.args) cursorServer.args = server.args;
|
|
266
|
+
} else if (server.url || server.httpUrl) {
|
|
267
|
+
const url = server.httpUrl || server.url;
|
|
268
|
+
if (url) {
|
|
269
|
+
cursorServer.url = url;
|
|
270
|
+
}
|
|
271
|
+
if (server.httpUrl || server.transport === "http") {
|
|
272
|
+
cursorServer.type = "streamable-http";
|
|
273
|
+
} else if (server.transport === "sse" || server.type === "sse") {
|
|
274
|
+
cursorServer.type = "sse";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (server.env) {
|
|
278
|
+
cursorServer.env = server.env;
|
|
279
|
+
}
|
|
280
|
+
if (server.cwd) {
|
|
281
|
+
cursorServer.cwd = server.cwd;
|
|
282
|
+
}
|
|
283
|
+
return cursorServer;
|
|
284
|
+
},
|
|
285
|
+
configWrapper: configWrappers.mcpServers
|
|
286
|
+
},
|
|
287
|
+
windsurf: {
|
|
288
|
+
target: "windsurf",
|
|
289
|
+
configPaths: ["mcp_config.json"],
|
|
290
|
+
serverTransform: (server) => {
|
|
291
|
+
const windsurfServer = {};
|
|
292
|
+
if (server.command) {
|
|
293
|
+
windsurfServer.command = server.command;
|
|
294
|
+
if (server.args) windsurfServer.args = server.args;
|
|
295
|
+
} else if (server.url || server.httpUrl) {
|
|
296
|
+
const url = server.httpUrl || server.url;
|
|
297
|
+
if (url) {
|
|
298
|
+
windsurfServer.serverUrl = url;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (server.env) {
|
|
302
|
+
windsurfServer.env = server.env;
|
|
303
|
+
}
|
|
304
|
+
if (server.cwd) {
|
|
305
|
+
windsurfServer.cwd = server.cwd;
|
|
306
|
+
}
|
|
307
|
+
return windsurfServer;
|
|
308
|
+
},
|
|
309
|
+
configWrapper: configWrappers.mcpServers
|
|
310
|
+
},
|
|
311
|
+
junie: {
|
|
312
|
+
target: "junie",
|
|
313
|
+
configPaths: [".junie/mcp-config.json"],
|
|
314
|
+
serverTransform: (server, serverName) => {
|
|
315
|
+
const junieServer = {
|
|
316
|
+
name: serverName
|
|
317
|
+
};
|
|
318
|
+
if (server.command) {
|
|
319
|
+
junieServer.command = server.command;
|
|
320
|
+
if (server.args) junieServer.args = server.args;
|
|
321
|
+
} else if (server.url || server.httpUrl) {
|
|
322
|
+
if (server.httpUrl) {
|
|
323
|
+
junieServer.httpUrl = server.httpUrl;
|
|
324
|
+
} else if (server.url) {
|
|
325
|
+
junieServer.url = server.url;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (server.env) {
|
|
329
|
+
junieServer.env = server.env;
|
|
330
|
+
}
|
|
331
|
+
if (server.cwd) {
|
|
332
|
+
junieServer.workingDirectory = server.cwd;
|
|
333
|
+
}
|
|
334
|
+
if (server.timeout !== void 0) {
|
|
335
|
+
junieServer.timeout = server.timeout;
|
|
336
|
+
}
|
|
337
|
+
if (server.trust !== void 0) {
|
|
338
|
+
junieServer.trust = server.trust;
|
|
339
|
+
}
|
|
340
|
+
if (server.transport) {
|
|
341
|
+
if (String(server.transport) === "streamable-http") {
|
|
342
|
+
junieServer.transport = "http";
|
|
343
|
+
} else if (server.transport === "stdio" || server.transport === "http" || server.transport === "sse") {
|
|
344
|
+
junieServer.transport = server.transport;
|
|
345
|
+
}
|
|
346
|
+
} else if (server.command) {
|
|
347
|
+
junieServer.transport = "stdio";
|
|
348
|
+
}
|
|
349
|
+
return junieServer;
|
|
350
|
+
},
|
|
351
|
+
configWrapper: configWrappers.mcpServers
|
|
352
|
+
},
|
|
353
|
+
cline: {
|
|
354
|
+
target: "cline",
|
|
355
|
+
configPaths: [".cline/mcp.json"],
|
|
356
|
+
serverTransform: serverTransforms.extended,
|
|
357
|
+
configWrapper: configWrappers.mcpServers
|
|
358
|
+
}
|
|
359
|
+
};
|
|
169
360
|
}
|
|
170
361
|
});
|
|
171
362
|
|
|
172
363
|
// src/generators/mcp/claudecode.ts
|
|
173
364
|
function generateClaudeMcp(config) {
|
|
174
|
-
return
|
|
175
|
-
target: "claudecode",
|
|
176
|
-
configPaths: [".claude/settings.json"],
|
|
177
|
-
serverTransform: (server) => {
|
|
178
|
-
const claudeServer = {};
|
|
179
|
-
if (server.command) {
|
|
180
|
-
claudeServer.command = server.command;
|
|
181
|
-
if (server.args) claudeServer.args = server.args;
|
|
182
|
-
} else if (server.url || server.httpUrl) {
|
|
183
|
-
const url = server.httpUrl || server.url;
|
|
184
|
-
if (url) {
|
|
185
|
-
claudeServer.url = url;
|
|
186
|
-
}
|
|
187
|
-
if (server.httpUrl) {
|
|
188
|
-
claudeServer.transport = "http";
|
|
189
|
-
} else if (server.transport === "sse") {
|
|
190
|
-
claudeServer.transport = "sse";
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
if (server.env) {
|
|
194
|
-
claudeServer.env = server.env;
|
|
195
|
-
}
|
|
196
|
-
return claudeServer;
|
|
197
|
-
},
|
|
198
|
-
configWrapper: configWrappers.mcpServers
|
|
199
|
-
});
|
|
365
|
+
return generateMcpFromRegistry("claudecode", config);
|
|
200
366
|
}
|
|
201
367
|
var init_claudecode = __esm({
|
|
202
368
|
"src/generators/mcp/claudecode.ts"() {
|
|
@@ -207,33 +373,7 @@ var init_claudecode = __esm({
|
|
|
207
373
|
|
|
208
374
|
// src/generators/mcp/cline.ts
|
|
209
375
|
function generateClineMcp(config) {
|
|
210
|
-
return
|
|
211
|
-
target: "cline",
|
|
212
|
-
configPaths: [".cline/mcp.json"],
|
|
213
|
-
serverTransform: (server) => {
|
|
214
|
-
const clineServer = {};
|
|
215
|
-
if (server.command) {
|
|
216
|
-
clineServer.command = server.command;
|
|
217
|
-
if (server.args) clineServer.args = server.args;
|
|
218
|
-
} else if (server.url) {
|
|
219
|
-
clineServer.url = server.url;
|
|
220
|
-
}
|
|
221
|
-
if (server.env) {
|
|
222
|
-
clineServer.env = server.env;
|
|
223
|
-
}
|
|
224
|
-
if (server.disabled !== void 0) {
|
|
225
|
-
clineServer.disabled = server.disabled;
|
|
226
|
-
}
|
|
227
|
-
if (server.alwaysAllow) {
|
|
228
|
-
clineServer.alwaysAllow = server.alwaysAllow;
|
|
229
|
-
}
|
|
230
|
-
if (server.networkTimeout !== void 0) {
|
|
231
|
-
clineServer.networkTimeout = server.networkTimeout;
|
|
232
|
-
}
|
|
233
|
-
return clineServer;
|
|
234
|
-
},
|
|
235
|
-
configWrapper: configWrappers.mcpServers
|
|
236
|
-
});
|
|
376
|
+
return generateMcpFromRegistry("cline", config);
|
|
237
377
|
}
|
|
238
378
|
var init_cline = __esm({
|
|
239
379
|
"src/generators/mcp/cline.ts"() {
|
|
@@ -370,137 +510,61 @@ var init_copilot = __esm({
|
|
|
370
510
|
|
|
371
511
|
// src/generators/mcp/cursor.ts
|
|
372
512
|
function generateCursorMcp(config) {
|
|
373
|
-
|
|
374
|
-
mcpServers: {}
|
|
375
|
-
};
|
|
376
|
-
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
377
|
-
if (!shouldIncludeServer(server, "cursor")) continue;
|
|
378
|
-
const cursorServer = {};
|
|
379
|
-
if (server.command) {
|
|
380
|
-
cursorServer.command = server.command;
|
|
381
|
-
if (server.args) cursorServer.args = server.args;
|
|
382
|
-
} else if (server.url || server.httpUrl) {
|
|
383
|
-
const url = server.httpUrl || server.url;
|
|
384
|
-
if (url) {
|
|
385
|
-
cursorServer.url = url;
|
|
386
|
-
}
|
|
387
|
-
if (server.httpUrl || server.transport === "http") {
|
|
388
|
-
cursorServer.type = "streamable-http";
|
|
389
|
-
} else if (server.transport === "sse" || server.type === "sse") {
|
|
390
|
-
cursorServer.type = "sse";
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
if (server.env) {
|
|
394
|
-
cursorServer.env = server.env;
|
|
395
|
-
}
|
|
396
|
-
if (server.cwd) {
|
|
397
|
-
cursorServer.cwd = server.cwd;
|
|
398
|
-
}
|
|
399
|
-
cursorConfig.mcpServers[serverName] = cursorServer;
|
|
400
|
-
}
|
|
401
|
-
return JSON.stringify(cursorConfig, null, 2);
|
|
513
|
+
return generateMcpFromRegistry("cursor", config);
|
|
402
514
|
}
|
|
403
515
|
var init_cursor = __esm({
|
|
404
516
|
"src/generators/mcp/cursor.ts"() {
|
|
405
517
|
"use strict";
|
|
406
|
-
|
|
518
|
+
init_shared_factory();
|
|
407
519
|
}
|
|
408
520
|
});
|
|
409
521
|
|
|
410
522
|
// src/generators/mcp/geminicli.ts
|
|
411
523
|
function generateGeminiCliMcp(config) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (server.
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
geminiServer.url = server.url;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
if (server.env) {
|
|
429
|
-
geminiServer.env = {};
|
|
430
|
-
for (const [key, value] of Object.entries(server.env)) {
|
|
431
|
-
if (value.startsWith("${") && value.endsWith("}")) {
|
|
432
|
-
geminiServer.env[key] = value;
|
|
433
|
-
} else {
|
|
434
|
-
geminiServer.env[key] = `\${${value}}`;
|
|
524
|
+
return generateMcpConfig(config, {
|
|
525
|
+
target: "geminicli",
|
|
526
|
+
configPaths: [".gemini/settings.json"],
|
|
527
|
+
serverTransform: (server) => {
|
|
528
|
+
const geminiServer = {};
|
|
529
|
+
if (server.command) {
|
|
530
|
+
geminiServer.command = server.command;
|
|
531
|
+
if (server.args) geminiServer.args = server.args;
|
|
532
|
+
} else if (server.url || server.httpUrl) {
|
|
533
|
+
if (server.httpUrl) {
|
|
534
|
+
geminiServer.httpUrl = server.httpUrl;
|
|
535
|
+
} else if (server.url) {
|
|
536
|
+
geminiServer.url = server.url;
|
|
435
537
|
}
|
|
436
538
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
539
|
+
if (server.env) {
|
|
540
|
+
geminiServer.env = server.env;
|
|
541
|
+
}
|
|
542
|
+
if (server.timeout !== void 0) {
|
|
543
|
+
geminiServer.timeout = server.timeout;
|
|
544
|
+
}
|
|
545
|
+
if (server.trust !== void 0) {
|
|
546
|
+
geminiServer.trust = server.trust;
|
|
547
|
+
}
|
|
548
|
+
return geminiServer;
|
|
549
|
+
},
|
|
550
|
+
configWrapper: configWrappers.mcpServers
|
|
551
|
+
});
|
|
447
552
|
}
|
|
448
553
|
var init_geminicli = __esm({
|
|
449
554
|
"src/generators/mcp/geminicli.ts"() {
|
|
450
555
|
"use strict";
|
|
451
|
-
|
|
556
|
+
init_shared_factory();
|
|
452
557
|
}
|
|
453
558
|
});
|
|
454
559
|
|
|
455
560
|
// src/generators/mcp/junie.ts
|
|
456
561
|
function generateJunieMcp(config) {
|
|
457
|
-
|
|
458
|
-
mcpServers: {}
|
|
459
|
-
};
|
|
460
|
-
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
461
|
-
if (!shouldIncludeServer(server, "junie")) continue;
|
|
462
|
-
const junieServer = {
|
|
463
|
-
name: serverName
|
|
464
|
-
};
|
|
465
|
-
if (server.command) {
|
|
466
|
-
junieServer.command = server.command;
|
|
467
|
-
if (server.args) junieServer.args = server.args;
|
|
468
|
-
} else if (server.url || server.httpUrl) {
|
|
469
|
-
if (server.httpUrl) {
|
|
470
|
-
junieServer.httpUrl = server.httpUrl;
|
|
471
|
-
} else if (server.url) {
|
|
472
|
-
junieServer.url = server.url;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
if (server.env) {
|
|
476
|
-
junieServer.env = server.env;
|
|
477
|
-
}
|
|
478
|
-
if (server.cwd) {
|
|
479
|
-
junieServer.workingDirectory = server.cwd;
|
|
480
|
-
}
|
|
481
|
-
if (server.timeout !== void 0) {
|
|
482
|
-
junieServer.timeout = server.timeout;
|
|
483
|
-
}
|
|
484
|
-
if (server.trust !== void 0) {
|
|
485
|
-
junieServer.trust = server.trust;
|
|
486
|
-
}
|
|
487
|
-
if (server.transport) {
|
|
488
|
-
if (String(server.transport) === "streamable-http") {
|
|
489
|
-
junieServer.transport = "http";
|
|
490
|
-
} else if (server.transport === "stdio" || server.transport === "http" || server.transport === "sse") {
|
|
491
|
-
junieServer.transport = server.transport;
|
|
492
|
-
}
|
|
493
|
-
} else if (server.command) {
|
|
494
|
-
junieServer.transport = "stdio";
|
|
495
|
-
}
|
|
496
|
-
junieConfig.mcpServers[serverName] = junieServer;
|
|
497
|
-
}
|
|
498
|
-
return JSON.stringify(junieConfig, null, 2);
|
|
562
|
+
return generateMcpFromRegistry("junie", config);
|
|
499
563
|
}
|
|
500
564
|
var init_junie = __esm({
|
|
501
565
|
"src/generators/mcp/junie.ts"() {
|
|
502
566
|
"use strict";
|
|
503
|
-
|
|
567
|
+
init_shared_factory();
|
|
504
568
|
}
|
|
505
569
|
});
|
|
506
570
|
|
|
@@ -607,6 +671,17 @@ var init_roo = __esm({
|
|
|
607
671
|
}
|
|
608
672
|
});
|
|
609
673
|
|
|
674
|
+
// src/generators/mcp/windsurf.ts
|
|
675
|
+
function generateWindsurfMcp(config) {
|
|
676
|
+
return generateMcpFromRegistry("windsurf", config);
|
|
677
|
+
}
|
|
678
|
+
var init_windsurf = __esm({
|
|
679
|
+
"src/generators/mcp/windsurf.ts"() {
|
|
680
|
+
"use strict";
|
|
681
|
+
init_shared_factory();
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
|
|
610
685
|
// src/cli/index.ts
|
|
611
686
|
var import_commander = require("commander");
|
|
612
687
|
|
|
@@ -630,7 +705,8 @@ function getDefaultConfig() {
|
|
|
630
705
|
roo: ".roo/rules",
|
|
631
706
|
geminicli: ".gemini/memories",
|
|
632
707
|
kiro: ".kiro/steering",
|
|
633
|
-
junie: "."
|
|
708
|
+
junie: ".",
|
|
709
|
+
windsurf: "."
|
|
634
710
|
},
|
|
635
711
|
watchEnabled: false,
|
|
636
712
|
defaultTargets: ALL_TOOL_TARGETS.filter((tool) => tool !== "augmentcode-legacy")
|
|
@@ -719,7 +795,8 @@ var OutputPathsSchema = import_mini4.z.object({
|
|
|
719
795
|
roo: import_mini4.z.optional(import_mini4.z.string()),
|
|
720
796
|
geminicli: import_mini4.z.optional(import_mini4.z.string()),
|
|
721
797
|
kiro: import_mini4.z.optional(import_mini4.z.string()),
|
|
722
|
-
junie: import_mini4.z.optional(import_mini4.z.string())
|
|
798
|
+
junie: import_mini4.z.optional(import_mini4.z.string()),
|
|
799
|
+
windsurf: import_mini4.z.optional(import_mini4.z.string())
|
|
723
800
|
});
|
|
724
801
|
var ConfigOptionsSchema = import_mini4.z.object({
|
|
725
802
|
aiRulesDir: import_mini4.z.optional(import_mini4.z.string()),
|
|
@@ -801,6 +878,8 @@ var RuleFrontmatterSchema = import_mini6.z.object({
|
|
|
801
878
|
description: import_mini6.z.string(),
|
|
802
879
|
globs: import_mini6.z.array(import_mini6.z.string()),
|
|
803
880
|
cursorRuleType: import_mini6.z.optional(import_mini6.z.enum(["always", "manual", "specificFiles", "intelligently"])),
|
|
881
|
+
windsurfActivationMode: import_mini6.z.optional(import_mini6.z.enum(["always", "manual", "model-decision", "glob"])),
|
|
882
|
+
windsurfOutputFormat: import_mini6.z.optional(import_mini6.z.enum(["single-file", "directory"])),
|
|
804
883
|
tags: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string()))
|
|
805
884
|
});
|
|
806
885
|
var ParsedRuleSchema = import_mini6.z.object({
|
|
@@ -1012,6 +1091,36 @@ function mergeWithCliOptions(config, cliOptions) {
|
|
|
1012
1091
|
return merged;
|
|
1013
1092
|
}
|
|
1014
1093
|
|
|
1094
|
+
// src/utils/error.ts
|
|
1095
|
+
function getErrorMessage(error) {
|
|
1096
|
+
return error instanceof Error ? error.message : String(error);
|
|
1097
|
+
}
|
|
1098
|
+
function formatErrorWithContext(error, context) {
|
|
1099
|
+
const errorMessage = getErrorMessage(error);
|
|
1100
|
+
return `${context}: ${errorMessage}`;
|
|
1101
|
+
}
|
|
1102
|
+
function createErrorResult(error, context) {
|
|
1103
|
+
const errorMessage = context ? formatErrorWithContext(error, context) : getErrorMessage(error);
|
|
1104
|
+
return {
|
|
1105
|
+
success: false,
|
|
1106
|
+
error: errorMessage
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
function createSuccessResult(result) {
|
|
1110
|
+
return {
|
|
1111
|
+
success: true,
|
|
1112
|
+
result
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
async function safeAsyncOperation(operation, errorContext) {
|
|
1116
|
+
try {
|
|
1117
|
+
const result = await operation();
|
|
1118
|
+
return createSuccessResult(result);
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
return createErrorResult(error, errorContext);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1015
1124
|
// src/utils/file.ts
|
|
1016
1125
|
var import_promises2 = require("fs/promises");
|
|
1017
1126
|
var import_node_path = require("path");
|
|
@@ -1022,6 +1131,9 @@ async function ensureDir(dirPath) {
|
|
|
1022
1131
|
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
1023
1132
|
}
|
|
1024
1133
|
}
|
|
1134
|
+
function resolvePath(relativePath, baseDir) {
|
|
1135
|
+
return baseDir ? (0, import_node_path.join)(baseDir, relativePath) : relativePath;
|
|
1136
|
+
}
|
|
1025
1137
|
async function readFileContent(filepath) {
|
|
1026
1138
|
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
1027
1139
|
}
|
|
@@ -1312,7 +1424,7 @@ export default config;
|
|
|
1312
1424
|
}
|
|
1313
1425
|
|
|
1314
1426
|
// src/cli/commands/generate.ts
|
|
1315
|
-
var
|
|
1427
|
+
var import_node_path10 = require("path");
|
|
1316
1428
|
|
|
1317
1429
|
// src/generators/ignore/shared-factory.ts
|
|
1318
1430
|
var import_node_path3 = require("path");
|
|
@@ -1872,6 +1984,131 @@ var ignoreConfigs = {
|
|
|
1872
1984
|
],
|
|
1873
1985
|
includeCommonPatterns: false,
|
|
1874
1986
|
projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
|
|
1987
|
+
},
|
|
1988
|
+
windsurf: {
|
|
1989
|
+
tool: "windsurf",
|
|
1990
|
+
filename: ".codeiumignore",
|
|
1991
|
+
header: [
|
|
1992
|
+
"# Generated by rulesync - Windsurf AI Code Editor ignore file",
|
|
1993
|
+
"# This file controls which files are excluded from Cascade AI analysis and context",
|
|
1994
|
+
"# Uses same syntax as .gitignore patterns",
|
|
1995
|
+
"# Note: Git-ignored files are automatically excluded by Windsurf"
|
|
1996
|
+
],
|
|
1997
|
+
corePatterns: [
|
|
1998
|
+
"# \u2500\u2500\u2500\u2500\u2500 Security & Credentials (Critical) \u2500\u2500\u2500\u2500\u2500",
|
|
1999
|
+
"# Environment files",
|
|
2000
|
+
".env*",
|
|
2001
|
+
"!.env.example",
|
|
2002
|
+
"",
|
|
2003
|
+
"# Private keys and certificates",
|
|
2004
|
+
"*.pem",
|
|
2005
|
+
"*.key",
|
|
2006
|
+
"*.crt",
|
|
2007
|
+
"*.p12",
|
|
2008
|
+
"*.pfx",
|
|
2009
|
+
"*.der",
|
|
2010
|
+
"",
|
|
2011
|
+
"# SSH keys",
|
|
2012
|
+
"id_rsa*",
|
|
2013
|
+
"id_dsa*",
|
|
2014
|
+
"*.ppk",
|
|
2015
|
+
"",
|
|
2016
|
+
"# API keys and tokens",
|
|
2017
|
+
"**/apikeys/",
|
|
2018
|
+
"**/*_token*",
|
|
2019
|
+
"**/*_secret*",
|
|
2020
|
+
"**/*api_key*",
|
|
2021
|
+
"",
|
|
2022
|
+
"# Cloud provider credentials",
|
|
2023
|
+
"aws-credentials.json",
|
|
2024
|
+
"gcp-service-account*.json",
|
|
2025
|
+
"azure-credentials.json",
|
|
2026
|
+
"",
|
|
2027
|
+
"# \u2500\u2500\u2500\u2500\u2500 Database & Configuration Files \u2500\u2500\u2500\u2500\u2500",
|
|
2028
|
+
"# Database files",
|
|
2029
|
+
"*.db",
|
|
2030
|
+
"*.sqlite",
|
|
2031
|
+
"*.sqlite3",
|
|
2032
|
+
"",
|
|
2033
|
+
"# Configuration files with secrets",
|
|
2034
|
+
"config/secrets/",
|
|
2035
|
+
"**/database.yml",
|
|
2036
|
+
"",
|
|
2037
|
+
"# \u2500\u2500\u2500\u2500\u2500 Build Artifacts & Dependencies \u2500\u2500\u2500\u2500\u2500",
|
|
2038
|
+
"# Build outputs",
|
|
2039
|
+
"dist/",
|
|
2040
|
+
"build/",
|
|
2041
|
+
"out/",
|
|
2042
|
+
"target/",
|
|
2043
|
+
"",
|
|
2044
|
+
"# Dependencies (already auto-excluded but reinforced)",
|
|
2045
|
+
"node_modules/",
|
|
2046
|
+
".pnpm-store/",
|
|
2047
|
+
".yarn/",
|
|
2048
|
+
"vendor/",
|
|
2049
|
+
"",
|
|
2050
|
+
"# \u2500\u2500\u2500\u2500\u2500 Cache & Temporary Files \u2500\u2500\u2500\u2500\u2500",
|
|
2051
|
+
"# Cache directories",
|
|
2052
|
+
".cache/",
|
|
2053
|
+
".parcel-cache/",
|
|
2054
|
+
".next/cache/",
|
|
2055
|
+
"",
|
|
2056
|
+
"# Temporary files",
|
|
2057
|
+
"*.tmp",
|
|
2058
|
+
"*.swp",
|
|
2059
|
+
"*.swo",
|
|
2060
|
+
"*~",
|
|
2061
|
+
"",
|
|
2062
|
+
"# \u2500\u2500\u2500\u2500\u2500 Large Data Files \u2500\u2500\u2500\u2500\u2500",
|
|
2063
|
+
"# Data files",
|
|
2064
|
+
"*.csv",
|
|
2065
|
+
"*.xlsx",
|
|
2066
|
+
"*.json",
|
|
2067
|
+
"data/",
|
|
2068
|
+
"datasets/",
|
|
2069
|
+
"",
|
|
2070
|
+
"# Media files",
|
|
2071
|
+
"*.mp4",
|
|
2072
|
+
"*.avi",
|
|
2073
|
+
"*.mov",
|
|
2074
|
+
"*.png",
|
|
2075
|
+
"*.jpg",
|
|
2076
|
+
"*.jpeg",
|
|
2077
|
+
"*.gif",
|
|
2078
|
+
"",
|
|
2079
|
+
"# Archives",
|
|
2080
|
+
"*.zip",
|
|
2081
|
+
"*.tar.gz",
|
|
2082
|
+
"*.rar",
|
|
2083
|
+
"",
|
|
2084
|
+
"# \u2500\u2500\u2500\u2500\u2500 IDE & Editor Files \u2500\u2500\u2500\u2500\u2500",
|
|
2085
|
+
"# IDE settings (personal)",
|
|
2086
|
+
".vscode/settings.json",
|
|
2087
|
+
".idea/",
|
|
2088
|
+
"",
|
|
2089
|
+
"# Editor temporary files",
|
|
2090
|
+
"*.swp",
|
|
2091
|
+
"*.swo",
|
|
2092
|
+
"",
|
|
2093
|
+
"# \u2500\u2500\u2500\u2500\u2500 Test Coverage & Logs \u2500\u2500\u2500\u2500\u2500",
|
|
2094
|
+
"# Test coverage reports",
|
|
2095
|
+
"coverage/",
|
|
2096
|
+
".nyc_output/",
|
|
2097
|
+
"",
|
|
2098
|
+
"# Logs",
|
|
2099
|
+
"*.log",
|
|
2100
|
+
"",
|
|
2101
|
+
"# \u2500\u2500\u2500\u2500\u2500 Re-include Important Files \u2500\u2500\u2500\u2500\u2500",
|
|
2102
|
+
"# Allow configuration examples",
|
|
2103
|
+
"!.env.example",
|
|
2104
|
+
"!config/*.example.*",
|
|
2105
|
+
"",
|
|
2106
|
+
"# Allow documentation",
|
|
2107
|
+
"!docs/**/*.md",
|
|
2108
|
+
"!README.md"
|
|
2109
|
+
],
|
|
2110
|
+
includeCommonPatterns: false,
|
|
2111
|
+
projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
|
|
1875
2112
|
}
|
|
1876
2113
|
};
|
|
1877
2114
|
|
|
@@ -1890,7 +2127,12 @@ async function generateKiroIgnoreFiles(rules, config, baseDir) {
|
|
|
1890
2127
|
return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
|
|
1891
2128
|
}
|
|
1892
2129
|
|
|
1893
|
-
// src/generators/
|
|
2130
|
+
// src/generators/ignore/windsurf.ts
|
|
2131
|
+
function generateWindsurfIgnore(rules, config, baseDir) {
|
|
2132
|
+
return generateIgnoreFile(rules, config, ignoreConfigs.windsurf, baseDir);
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
// src/generators/rules/augmentcode.ts
|
|
1894
2136
|
var import_node_path6 = require("path");
|
|
1895
2137
|
|
|
1896
2138
|
// src/generators/rules/shared-helpers.ts
|
|
@@ -1949,7 +2191,7 @@ function filterIgnoredFiles(files, ignorePatterns) {
|
|
|
1949
2191
|
|
|
1950
2192
|
// src/generators/rules/shared-helpers.ts
|
|
1951
2193
|
function resolveOutputDir(config, tool, baseDir) {
|
|
1952
|
-
return
|
|
2194
|
+
return resolvePath(config.outputPaths[tool], baseDir);
|
|
1953
2195
|
}
|
|
1954
2196
|
function createOutputsArray() {
|
|
1955
2197
|
return [];
|
|
@@ -1976,7 +2218,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
|
1976
2218
|
}
|
|
1977
2219
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1978
2220
|
if (ignorePatterns.patterns.length > 0) {
|
|
1979
|
-
const ignorePath =
|
|
2221
|
+
const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
|
|
1980
2222
|
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
1981
2223
|
outputs.push({
|
|
1982
2224
|
tool: generatorConfig.tool,
|
|
@@ -1994,7 +2236,10 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
1994
2236
|
if (generatorConfig.generateDetailContent && generatorConfig.detailSubDir) {
|
|
1995
2237
|
for (const rule of detailRules) {
|
|
1996
2238
|
const content = generatorConfig.generateDetailContent(rule);
|
|
1997
|
-
const filepath =
|
|
2239
|
+
const filepath = resolvePath(
|
|
2240
|
+
(0, import_node_path5.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
|
|
2241
|
+
baseDir
|
|
2242
|
+
);
|
|
1998
2243
|
outputs.push({
|
|
1999
2244
|
tool: generatorConfig.tool,
|
|
2000
2245
|
filepath,
|
|
@@ -2004,7 +2249,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
2004
2249
|
}
|
|
2005
2250
|
if (generatorConfig.generateRootContent && generatorConfig.rootFilePath) {
|
|
2006
2251
|
const rootContent = generatorConfig.generateRootContent(rootRule, detailRules, baseDir);
|
|
2007
|
-
const rootFilepath =
|
|
2252
|
+
const rootFilepath = resolvePath(generatorConfig.rootFilePath, baseDir);
|
|
2008
2253
|
outputs.push({
|
|
2009
2254
|
tool: generatorConfig.tool,
|
|
2010
2255
|
filepath: rootFilepath,
|
|
@@ -2013,7 +2258,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
2013
2258
|
}
|
|
2014
2259
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
2015
2260
|
if (ignorePatterns.patterns.length > 0) {
|
|
2016
|
-
const ignorePath =
|
|
2261
|
+
const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
|
|
2017
2262
|
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
2018
2263
|
outputs.push({
|
|
2019
2264
|
tool: generatorConfig.tool,
|
|
@@ -2043,16 +2288,6 @@ function generateIgnoreFile2(patterns, tool) {
|
|
|
2043
2288
|
lines.push(...patterns);
|
|
2044
2289
|
return lines.join("\n");
|
|
2045
2290
|
}
|
|
2046
|
-
async function generateComplexRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
2047
|
-
const unifiedConfig = {
|
|
2048
|
-
tool: generatorConfig.tool,
|
|
2049
|
-
fileExtension: generatorConfig.fileExtension,
|
|
2050
|
-
ignoreFileName: generatorConfig.ignoreFileName,
|
|
2051
|
-
generateContent: generatorConfig.generateContent,
|
|
2052
|
-
pathResolver: generatorConfig.getOutputPath
|
|
2053
|
-
};
|
|
2054
|
-
return generateRulesConfig(rules, config, unifiedConfig, baseDir);
|
|
2055
|
-
}
|
|
2056
2291
|
|
|
2057
2292
|
// src/generators/rules/augmentcode.ts
|
|
2058
2293
|
async function generateAugmentcodeConfig(rules, config, baseDir) {
|
|
@@ -2118,32 +2353,24 @@ function generateLegacyGuidelinesFile(allRules) {
|
|
|
2118
2353
|
// src/generators/rules/claudecode.ts
|
|
2119
2354
|
var import_node_path7 = require("path");
|
|
2120
2355
|
async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
2121
|
-
const
|
|
2122
|
-
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
2123
|
-
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
2124
|
-
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
2125
|
-
const claudeOutputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
|
|
2126
|
-
outputs.push({
|
|
2356
|
+
const generatorConfig = {
|
|
2127
2357
|
tool: "claudecode",
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
|
|
2143
|
-
}
|
|
2144
|
-
return outputs;
|
|
2358
|
+
fileExtension: ".md",
|
|
2359
|
+
ignoreFileName: ".aiignore",
|
|
2360
|
+
generateContent: generateMemoryFile,
|
|
2361
|
+
generateRootContent: generateClaudeMarkdown,
|
|
2362
|
+
rootFilePath: "CLAUDE.md",
|
|
2363
|
+
generateDetailContent: generateMemoryFile,
|
|
2364
|
+
detailSubDir: ".claude/memories",
|
|
2365
|
+
updateAdditionalConfig: async (ignorePatterns, baseDir2) => {
|
|
2366
|
+
const settingsPath = resolvePath((0, import_node_path7.join)(".claude", "settings.json"), baseDir2);
|
|
2367
|
+
await updateClaudeSettings(settingsPath, ignorePatterns);
|
|
2368
|
+
return [];
|
|
2369
|
+
}
|
|
2370
|
+
};
|
|
2371
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
2145
2372
|
}
|
|
2146
|
-
function generateClaudeMarkdown(
|
|
2373
|
+
function generateClaudeMarkdown(rootRule, detailRules) {
|
|
2147
2374
|
const lines = [];
|
|
2148
2375
|
if (detailRules.length > 0) {
|
|
2149
2376
|
lines.push("Please also reference the following documents as needed:");
|
|
@@ -2157,11 +2384,9 @@ function generateClaudeMarkdown(rootRules, detailRules) {
|
|
|
2157
2384
|
}
|
|
2158
2385
|
lines.push("");
|
|
2159
2386
|
}
|
|
2160
|
-
if (
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
lines.push("");
|
|
2164
|
-
}
|
|
2387
|
+
if (rootRule) {
|
|
2388
|
+
lines.push(rootRule.content);
|
|
2389
|
+
lines.push("");
|
|
2165
2390
|
}
|
|
2166
2391
|
return lines.join("\n");
|
|
2167
2392
|
}
|
|
@@ -2201,134 +2426,8 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
|
2201
2426
|
console.log(`\u2705 Updated Claude Code settings: ${settingsPath}`);
|
|
2202
2427
|
}
|
|
2203
2428
|
|
|
2204
|
-
// src/generators/rules/
|
|
2205
|
-
async function generateClineConfig(rules, config, baseDir) {
|
|
2206
|
-
return generateRulesConfig(
|
|
2207
|
-
rules,
|
|
2208
|
-
config,
|
|
2209
|
-
{
|
|
2210
|
-
tool: "cline",
|
|
2211
|
-
fileExtension: ".md",
|
|
2212
|
-
ignoreFileName: ".clineignore",
|
|
2213
|
-
generateContent: (rule) => rule.content.trim()
|
|
2214
|
-
},
|
|
2215
|
-
baseDir
|
|
2216
|
-
);
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
// src/generators/rules/codexcli.ts
|
|
2220
|
-
async function generateCodexConfig(rules, config, baseDir) {
|
|
2221
|
-
const generatorConfig = {
|
|
2222
|
-
tool: "codexcli",
|
|
2223
|
-
fileExtension: ".md",
|
|
2224
|
-
ignoreFileName: ".codexignore",
|
|
2225
|
-
generateContent: generateCodexInstructionsMarkdown,
|
|
2226
|
-
pathResolver: (rule, outputDir) => {
|
|
2227
|
-
if (rule.frontmatter.root === true) {
|
|
2228
|
-
return `${outputDir}/codex.md`;
|
|
2229
|
-
}
|
|
2230
|
-
return `${outputDir}/${rule.filename}.md`;
|
|
2231
|
-
}
|
|
2232
|
-
};
|
|
2233
|
-
return generateRulesConfig(rules, config, generatorConfig, baseDir);
|
|
2234
|
-
}
|
|
2235
|
-
function generateCodexInstructionsMarkdown(rule) {
|
|
2236
|
-
const lines = [];
|
|
2237
|
-
if (rule.frontmatter.root === false && rule.frontmatter.description && rule.frontmatter.description !== "Main instructions" && !rule.frontmatter.description.includes("Project-level Codex CLI instructions")) {
|
|
2238
|
-
lines.push(`<!-- ${rule.frontmatter.description} -->`);
|
|
2239
|
-
if (rule.content.trim()) {
|
|
2240
|
-
lines.push("");
|
|
2241
|
-
}
|
|
2242
|
-
}
|
|
2243
|
-
const content = rule.content.trim();
|
|
2244
|
-
if (content) {
|
|
2245
|
-
lines.push(content);
|
|
2246
|
-
}
|
|
2247
|
-
return lines.join("\n");
|
|
2248
|
-
}
|
|
2249
|
-
|
|
2250
|
-
// src/generators/rules/copilot.ts
|
|
2429
|
+
// src/generators/rules/generator-registry.ts
|
|
2251
2430
|
var import_node_path8 = require("path");
|
|
2252
|
-
async function generateCopilotConfig(rules, config, baseDir) {
|
|
2253
|
-
return generateComplexRulesConfig(
|
|
2254
|
-
rules,
|
|
2255
|
-
config,
|
|
2256
|
-
{
|
|
2257
|
-
tool: "copilot",
|
|
2258
|
-
fileExtension: ".instructions.md",
|
|
2259
|
-
ignoreFileName: ".copilotignore",
|
|
2260
|
-
generateContent: generateCopilotMarkdown,
|
|
2261
|
-
getOutputPath: (rule, outputDir) => {
|
|
2262
|
-
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
2263
|
-
return (0, import_node_path8.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
2264
|
-
}
|
|
2265
|
-
},
|
|
2266
|
-
baseDir
|
|
2267
|
-
);
|
|
2268
|
-
}
|
|
2269
|
-
function generateCopilotMarkdown(rule) {
|
|
2270
|
-
const lines = [];
|
|
2271
|
-
lines.push("---");
|
|
2272
|
-
lines.push(`description: "${rule.frontmatter.description}"`);
|
|
2273
|
-
if (rule.frontmatter.globs.length > 0) {
|
|
2274
|
-
lines.push(`applyTo: "${rule.frontmatter.globs.join(", ")}"`);
|
|
2275
|
-
} else {
|
|
2276
|
-
lines.push('applyTo: "**"');
|
|
2277
|
-
}
|
|
2278
|
-
lines.push("---");
|
|
2279
|
-
lines.push(rule.content);
|
|
2280
|
-
return lines.join("\n");
|
|
2281
|
-
}
|
|
2282
|
-
|
|
2283
|
-
// src/generators/rules/cursor.ts
|
|
2284
|
-
var import_node_path9 = require("path");
|
|
2285
|
-
async function generateCursorConfig(rules, config, baseDir) {
|
|
2286
|
-
return generateComplexRulesConfig(
|
|
2287
|
-
rules,
|
|
2288
|
-
config,
|
|
2289
|
-
{
|
|
2290
|
-
tool: "cursor",
|
|
2291
|
-
fileExtension: ".mdc",
|
|
2292
|
-
ignoreFileName: ".cursorignore",
|
|
2293
|
-
generateContent: generateCursorMarkdown,
|
|
2294
|
-
getOutputPath: (rule, outputDir) => {
|
|
2295
|
-
return (0, import_node_path9.join)(outputDir, `${rule.filename}.mdc`);
|
|
2296
|
-
}
|
|
2297
|
-
},
|
|
2298
|
-
baseDir
|
|
2299
|
-
);
|
|
2300
|
-
}
|
|
2301
|
-
function generateCursorMarkdown(rule) {
|
|
2302
|
-
const lines = [];
|
|
2303
|
-
const ruleType = determineCursorRuleType(rule.frontmatter);
|
|
2304
|
-
lines.push("---");
|
|
2305
|
-
switch (ruleType) {
|
|
2306
|
-
case "always":
|
|
2307
|
-
lines.push("description:");
|
|
2308
|
-
lines.push("globs:");
|
|
2309
|
-
lines.push("alwaysApply: true");
|
|
2310
|
-
break;
|
|
2311
|
-
case "manual":
|
|
2312
|
-
lines.push("description:");
|
|
2313
|
-
lines.push("globs:");
|
|
2314
|
-
lines.push("alwaysApply: false");
|
|
2315
|
-
break;
|
|
2316
|
-
case "specificFiles":
|
|
2317
|
-
lines.push("description:");
|
|
2318
|
-
lines.push(`globs: ${rule.frontmatter.globs.join(",")}`);
|
|
2319
|
-
lines.push("alwaysApply: false");
|
|
2320
|
-
break;
|
|
2321
|
-
case "intelligently":
|
|
2322
|
-
lines.push(`description: ${rule.frontmatter.description}`);
|
|
2323
|
-
lines.push("globs:");
|
|
2324
|
-
lines.push("alwaysApply: false");
|
|
2325
|
-
break;
|
|
2326
|
-
}
|
|
2327
|
-
lines.push("---");
|
|
2328
|
-
lines.push("");
|
|
2329
|
-
lines.push(rule.content);
|
|
2330
|
-
return lines.join("\n");
|
|
2331
|
-
}
|
|
2332
2431
|
function determineCursorRuleType(frontmatter) {
|
|
2333
2432
|
if (frontmatter.cursorRuleType) {
|
|
2334
2433
|
return frontmatter.cursorRuleType;
|
|
@@ -2350,6 +2449,293 @@ function determineCursorRuleType(frontmatter) {
|
|
|
2350
2449
|
}
|
|
2351
2450
|
return "intelligently";
|
|
2352
2451
|
}
|
|
2452
|
+
var GENERATOR_REGISTRY = {
|
|
2453
|
+
// Simple generators - generate one file per rule
|
|
2454
|
+
cline: {
|
|
2455
|
+
type: "simple",
|
|
2456
|
+
tool: "cline",
|
|
2457
|
+
fileExtension: ".md",
|
|
2458
|
+
ignoreFileName: ".clineignore",
|
|
2459
|
+
generateContent: (rule) => rule.content.trim()
|
|
2460
|
+
},
|
|
2461
|
+
roo: {
|
|
2462
|
+
type: "simple",
|
|
2463
|
+
tool: "roo",
|
|
2464
|
+
fileExtension: ".md",
|
|
2465
|
+
ignoreFileName: ".rooignore",
|
|
2466
|
+
generateContent: (rule) => rule.content.trim()
|
|
2467
|
+
},
|
|
2468
|
+
kiro: {
|
|
2469
|
+
type: "simple",
|
|
2470
|
+
tool: "kiro",
|
|
2471
|
+
fileExtension: ".md",
|
|
2472
|
+
ignoreFileName: ".kiroignore",
|
|
2473
|
+
generateContent: (rule) => rule.content.trim()
|
|
2474
|
+
},
|
|
2475
|
+
augmentcode: {
|
|
2476
|
+
type: "simple",
|
|
2477
|
+
tool: "augmentcode",
|
|
2478
|
+
fileExtension: ".md",
|
|
2479
|
+
ignoreFileName: ".aiignore",
|
|
2480
|
+
generateContent: (rule) => rule.content.trim()
|
|
2481
|
+
},
|
|
2482
|
+
"augmentcode-legacy": {
|
|
2483
|
+
type: "simple",
|
|
2484
|
+
tool: "augmentcode-legacy",
|
|
2485
|
+
fileExtension: ".md",
|
|
2486
|
+
ignoreFileName: ".aiignore",
|
|
2487
|
+
generateContent: (rule) => rule.content.trim()
|
|
2488
|
+
},
|
|
2489
|
+
// Complex generators with custom content formatting
|
|
2490
|
+
copilot: {
|
|
2491
|
+
type: "simple",
|
|
2492
|
+
tool: "copilot",
|
|
2493
|
+
fileExtension: ".instructions.md",
|
|
2494
|
+
ignoreFileName: ".copilotignore",
|
|
2495
|
+
generateContent: (rule) => {
|
|
2496
|
+
const lines = [];
|
|
2497
|
+
lines.push("---");
|
|
2498
|
+
lines.push(`description: "${rule.frontmatter.description}"`);
|
|
2499
|
+
if (rule.frontmatter.globs.length > 0) {
|
|
2500
|
+
lines.push(`applyTo: "${rule.frontmatter.globs.join(", ")}"`);
|
|
2501
|
+
} else {
|
|
2502
|
+
lines.push('applyTo: "**"');
|
|
2503
|
+
}
|
|
2504
|
+
lines.push("---");
|
|
2505
|
+
lines.push(rule.content);
|
|
2506
|
+
return lines.join("\n");
|
|
2507
|
+
},
|
|
2508
|
+
pathResolver: (rule, outputDir) => {
|
|
2509
|
+
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
2510
|
+
return (0, import_node_path8.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
2511
|
+
}
|
|
2512
|
+
},
|
|
2513
|
+
cursor: {
|
|
2514
|
+
type: "simple",
|
|
2515
|
+
tool: "cursor",
|
|
2516
|
+
fileExtension: ".mdc",
|
|
2517
|
+
ignoreFileName: ".cursorignore",
|
|
2518
|
+
generateContent: (rule) => {
|
|
2519
|
+
const lines = [];
|
|
2520
|
+
const ruleType = determineCursorRuleType(rule.frontmatter);
|
|
2521
|
+
lines.push("---");
|
|
2522
|
+
switch (ruleType) {
|
|
2523
|
+
case "always":
|
|
2524
|
+
lines.push("description:");
|
|
2525
|
+
lines.push("globs:");
|
|
2526
|
+
lines.push("alwaysApply: true");
|
|
2527
|
+
break;
|
|
2528
|
+
case "manual":
|
|
2529
|
+
lines.push("description:");
|
|
2530
|
+
lines.push("globs:");
|
|
2531
|
+
lines.push("alwaysApply: false");
|
|
2532
|
+
break;
|
|
2533
|
+
case "specificFiles":
|
|
2534
|
+
lines.push("description:");
|
|
2535
|
+
lines.push(`globs: ${rule.frontmatter.globs.join(",")}`);
|
|
2536
|
+
lines.push("alwaysApply: false");
|
|
2537
|
+
break;
|
|
2538
|
+
case "intelligently":
|
|
2539
|
+
lines.push(`description: ${rule.frontmatter.description}`);
|
|
2540
|
+
lines.push("globs:");
|
|
2541
|
+
lines.push("alwaysApply: false");
|
|
2542
|
+
break;
|
|
2543
|
+
}
|
|
2544
|
+
lines.push("---");
|
|
2545
|
+
lines.push("");
|
|
2546
|
+
lines.push(rule.content);
|
|
2547
|
+
return lines.join("\n");
|
|
2548
|
+
},
|
|
2549
|
+
pathResolver: (rule, outputDir) => {
|
|
2550
|
+
return (0, import_node_path8.join)(outputDir, `${rule.filename}.mdc`);
|
|
2551
|
+
}
|
|
2552
|
+
},
|
|
2553
|
+
codexcli: {
|
|
2554
|
+
type: "simple",
|
|
2555
|
+
tool: "codexcli",
|
|
2556
|
+
fileExtension: ".md",
|
|
2557
|
+
ignoreFileName: ".codexignore",
|
|
2558
|
+
generateContent: (rule) => rule.content.trim()
|
|
2559
|
+
},
|
|
2560
|
+
windsurf: {
|
|
2561
|
+
type: "simple",
|
|
2562
|
+
tool: "windsurf",
|
|
2563
|
+
fileExtension: ".md",
|
|
2564
|
+
ignoreFileName: ".codeiumignore",
|
|
2565
|
+
generateContent: (rule) => {
|
|
2566
|
+
const lines = [];
|
|
2567
|
+
const activationMode = rule.frontmatter.windsurfActivationMode;
|
|
2568
|
+
const globPattern = rule.frontmatter.globs?.[0];
|
|
2569
|
+
if (activationMode || globPattern) {
|
|
2570
|
+
lines.push("---");
|
|
2571
|
+
if (activationMode) {
|
|
2572
|
+
lines.push(`activation: ${activationMode}`);
|
|
2573
|
+
}
|
|
2574
|
+
if (globPattern && activationMode === "glob") {
|
|
2575
|
+
lines.push(`pattern: "${globPattern}"`);
|
|
2576
|
+
}
|
|
2577
|
+
lines.push("---");
|
|
2578
|
+
lines.push("");
|
|
2579
|
+
}
|
|
2580
|
+
lines.push(rule.content.trim());
|
|
2581
|
+
return lines.join("\n");
|
|
2582
|
+
},
|
|
2583
|
+
pathResolver: (rule, outputDir) => {
|
|
2584
|
+
const outputFormat = rule.frontmatter.windsurfOutputFormat || "directory";
|
|
2585
|
+
if (outputFormat === "single-file") {
|
|
2586
|
+
return (0, import_node_path8.join)(outputDir, ".windsurf-rules");
|
|
2587
|
+
} else {
|
|
2588
|
+
const rulesDir = (0, import_node_path8.join)(outputDir, ".windsurf", "rules");
|
|
2589
|
+
return (0, import_node_path8.join)(rulesDir, `${rule.filename}.md`);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
},
|
|
2593
|
+
// Complex generators with root + detail pattern
|
|
2594
|
+
claudecode: {
|
|
2595
|
+
type: "complex",
|
|
2596
|
+
tool: "claudecode",
|
|
2597
|
+
fileExtension: ".md",
|
|
2598
|
+
ignoreFileName: ".aiignore",
|
|
2599
|
+
generateContent: (rule) => {
|
|
2600
|
+
const lines = [];
|
|
2601
|
+
if (rule.frontmatter.description) {
|
|
2602
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2603
|
+
`);
|
|
2604
|
+
}
|
|
2605
|
+
lines.push(rule.content.trim());
|
|
2606
|
+
return lines.join("\n");
|
|
2607
|
+
}
|
|
2608
|
+
// NOTE: Claude Code specific logic is handled in the actual generator file
|
|
2609
|
+
// due to complex settings.json manipulation requirements
|
|
2610
|
+
},
|
|
2611
|
+
geminicli: {
|
|
2612
|
+
type: "complex",
|
|
2613
|
+
tool: "geminicli",
|
|
2614
|
+
fileExtension: ".md",
|
|
2615
|
+
ignoreFileName: ".aiexclude",
|
|
2616
|
+
generateContent: (rule) => {
|
|
2617
|
+
const lines = [];
|
|
2618
|
+
if (rule.frontmatter.description) {
|
|
2619
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2620
|
+
`);
|
|
2621
|
+
}
|
|
2622
|
+
lines.push(rule.content.trim());
|
|
2623
|
+
return lines.join("\n");
|
|
2624
|
+
}
|
|
2625
|
+
// Complex generation handled by existing generator
|
|
2626
|
+
},
|
|
2627
|
+
junie: {
|
|
2628
|
+
type: "complex",
|
|
2629
|
+
tool: "junie",
|
|
2630
|
+
fileExtension: ".md",
|
|
2631
|
+
ignoreFileName: ".aiignore",
|
|
2632
|
+
generateContent: (rule) => {
|
|
2633
|
+
const lines = [];
|
|
2634
|
+
if (rule.frontmatter.description) {
|
|
2635
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2636
|
+
`);
|
|
2637
|
+
}
|
|
2638
|
+
lines.push(rule.content.trim());
|
|
2639
|
+
return lines.join("\n");
|
|
2640
|
+
}
|
|
2641
|
+
// Complex generation handled by existing generator
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
async function generateFromRegistry(tool, rules, config, baseDir) {
|
|
2645
|
+
const generatorConfig = GENERATOR_REGISTRY[tool];
|
|
2646
|
+
if (!generatorConfig) {
|
|
2647
|
+
throw new Error(`No generator configuration found for tool: ${tool}`);
|
|
2648
|
+
}
|
|
2649
|
+
if (generatorConfig.type === "simple") {
|
|
2650
|
+
const ruleConfig = {
|
|
2651
|
+
tool: generatorConfig.tool,
|
|
2652
|
+
fileExtension: generatorConfig.fileExtension,
|
|
2653
|
+
ignoreFileName: generatorConfig.ignoreFileName,
|
|
2654
|
+
generateContent: generatorConfig.generateContent,
|
|
2655
|
+
...generatorConfig.pathResolver && { pathResolver: generatorConfig.pathResolver }
|
|
2656
|
+
};
|
|
2657
|
+
return generateRulesConfig(rules, config, ruleConfig, baseDir);
|
|
2658
|
+
} else {
|
|
2659
|
+
const enhancedConfig = {
|
|
2660
|
+
tool: generatorConfig.tool,
|
|
2661
|
+
fileExtension: generatorConfig.fileExtension,
|
|
2662
|
+
ignoreFileName: generatorConfig.ignoreFileName,
|
|
2663
|
+
generateContent: generatorConfig.generateContent,
|
|
2664
|
+
...generatorConfig.generateRootContent && {
|
|
2665
|
+
generateRootContent: generatorConfig.generateRootContent
|
|
2666
|
+
},
|
|
2667
|
+
...generatorConfig.rootFilePath && { rootFilePath: generatorConfig.rootFilePath },
|
|
2668
|
+
...generatorConfig.generateDetailContent && {
|
|
2669
|
+
generateDetailContent: generatorConfig.generateDetailContent
|
|
2670
|
+
},
|
|
2671
|
+
...generatorConfig.detailSubDir && { detailSubDir: generatorConfig.detailSubDir },
|
|
2672
|
+
...generatorConfig.updateAdditionalConfig && {
|
|
2673
|
+
updateAdditionalConfig: generatorConfig.updateAdditionalConfig
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
return generateComplexRules(rules, config, enhancedConfig, baseDir);
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
// src/generators/rules/cline.ts
|
|
2681
|
+
async function generateClineConfig(rules, config, baseDir) {
|
|
2682
|
+
return generateFromRegistry("cline", rules, config, baseDir);
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
// src/generators/rules/codexcli.ts
|
|
2686
|
+
async function generateCodexConfig(rules, config, baseDir) {
|
|
2687
|
+
const outputs = [];
|
|
2688
|
+
if (rules.length === 0) {
|
|
2689
|
+
return outputs;
|
|
2690
|
+
}
|
|
2691
|
+
const sortedRules = [...rules].sort((a, b) => {
|
|
2692
|
+
if (a.frontmatter.root === true && b.frontmatter.root !== true) return -1;
|
|
2693
|
+
if (a.frontmatter.root !== true && b.frontmatter.root === true) return 1;
|
|
2694
|
+
return 0;
|
|
2695
|
+
});
|
|
2696
|
+
const concatenatedContent = generateConcatenatedCodexContent(sortedRules);
|
|
2697
|
+
if (concatenatedContent.trim()) {
|
|
2698
|
+
const outputDir = resolveOutputDir(config, "codexcli", baseDir);
|
|
2699
|
+
const filepath = `${outputDir}/codex.md`;
|
|
2700
|
+
outputs.push({
|
|
2701
|
+
tool: "codexcli",
|
|
2702
|
+
filepath,
|
|
2703
|
+
content: concatenatedContent
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
2707
|
+
if (ignorePatterns.patterns.length > 0) {
|
|
2708
|
+
const ignorePath = resolvePath(".codexignore", baseDir);
|
|
2709
|
+
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, "codexcli");
|
|
2710
|
+
outputs.push({
|
|
2711
|
+
tool: "codexcli",
|
|
2712
|
+
filepath: ignorePath,
|
|
2713
|
+
content: ignoreContent
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2716
|
+
return outputs;
|
|
2717
|
+
}
|
|
2718
|
+
function generateConcatenatedCodexContent(rules) {
|
|
2719
|
+
const sections = [];
|
|
2720
|
+
for (const rule of rules) {
|
|
2721
|
+
const content = rule.content.trim();
|
|
2722
|
+
if (!content) {
|
|
2723
|
+
continue;
|
|
2724
|
+
}
|
|
2725
|
+
sections.push(content);
|
|
2726
|
+
}
|
|
2727
|
+
return sections.join("\n\n---\n\n");
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
// src/generators/rules/copilot.ts
|
|
2731
|
+
async function generateCopilotConfig(rules, config, baseDir) {
|
|
2732
|
+
return generateFromRegistry("copilot", rules, config, baseDir);
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
// src/generators/rules/cursor.ts
|
|
2736
|
+
async function generateCursorConfig(rules, config, baseDir) {
|
|
2737
|
+
return generateFromRegistry("cursor", rules, config, baseDir);
|
|
2738
|
+
}
|
|
2353
2739
|
|
|
2354
2740
|
// src/generators/rules/geminicli.ts
|
|
2355
2741
|
async function generateGeminiConfig(rules, config, baseDir) {
|
|
@@ -2421,38 +2807,18 @@ function generateGuidelinesMarkdown(rootRule, detailRules) {
|
|
|
2421
2807
|
}
|
|
2422
2808
|
|
|
2423
2809
|
// src/generators/rules/kiro.ts
|
|
2424
|
-
var import_node_path10 = require("path");
|
|
2425
2810
|
async function generateKiroConfig(rules, config, baseDir) {
|
|
2426
|
-
|
|
2427
|
-
for (const rule of rules) {
|
|
2428
|
-
const content = generateKiroMarkdown(rule);
|
|
2429
|
-
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
|
|
2430
|
-
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
2431
|
-
outputs.push({
|
|
2432
|
-
tool: "kiro",
|
|
2433
|
-
filepath,
|
|
2434
|
-
content
|
|
2435
|
-
});
|
|
2436
|
-
}
|
|
2437
|
-
return outputs;
|
|
2438
|
-
}
|
|
2439
|
-
function generateKiroMarkdown(rule) {
|
|
2440
|
-
return rule.content.trim();
|
|
2811
|
+
return generateFromRegistry("kiro", rules, config, baseDir);
|
|
2441
2812
|
}
|
|
2442
2813
|
|
|
2443
2814
|
// src/generators/rules/roo.ts
|
|
2444
2815
|
async function generateRooConfig(rules, config, baseDir) {
|
|
2445
|
-
return
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
ignoreFileName: ".rooignore",
|
|
2452
|
-
generateContent: (rule) => rule.content.trim()
|
|
2453
|
-
},
|
|
2454
|
-
baseDir
|
|
2455
|
-
);
|
|
2816
|
+
return generateFromRegistry("roo", rules, config, baseDir);
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
// src/generators/rules/windsurf.ts
|
|
2820
|
+
async function generateWindsurfConfig(rules, config, baseDir) {
|
|
2821
|
+
return generateFromRegistry("windsurf", rules, config, baseDir);
|
|
2456
2822
|
}
|
|
2457
2823
|
|
|
2458
2824
|
// src/core/generator.ts
|
|
@@ -2527,6 +2893,11 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
2527
2893
|
const kiroIgnoreOutputs = await generateKiroIgnoreFiles(rules, config, baseDir);
|
|
2528
2894
|
return [...kiroRulesOutputs, ...kiroIgnoreOutputs];
|
|
2529
2895
|
}
|
|
2896
|
+
case "windsurf": {
|
|
2897
|
+
const windsurfRulesOutputs = await generateWindsurfConfig(rules, config, baseDir);
|
|
2898
|
+
const windsurfIgnoreOutputs = await generateWindsurfIgnore(rules, config, baseDir);
|
|
2899
|
+
return [...windsurfRulesOutputs, ...windsurfIgnoreOutputs];
|
|
2900
|
+
}
|
|
2530
2901
|
default:
|
|
2531
2902
|
console.warn(`Unknown tool: ${tool}`);
|
|
2532
2903
|
return null;
|
|
@@ -2534,7 +2905,7 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
2534
2905
|
}
|
|
2535
2906
|
|
|
2536
2907
|
// src/core/parser.ts
|
|
2537
|
-
var
|
|
2908
|
+
var import_node_path9 = require("path");
|
|
2538
2909
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
2539
2910
|
async function parseRulesFromDirectory(aiRulesDir) {
|
|
2540
2911
|
const ignorePatterns = await loadIgnorePatterns();
|
|
@@ -2572,7 +2943,7 @@ async function parseRuleFile(filepath) {
|
|
|
2572
2943
|
const parsed = (0, import_gray_matter.default)(content);
|
|
2573
2944
|
try {
|
|
2574
2945
|
const frontmatter = RuleFrontmatterSchema.parse(parsed.data);
|
|
2575
|
-
const filename = (0,
|
|
2946
|
+
const filename = (0, import_node_path9.basename)(filepath, ".md");
|
|
2576
2947
|
return {
|
|
2577
2948
|
frontmatter,
|
|
2578
2949
|
content: parsed.content,
|
|
@@ -2650,6 +3021,7 @@ init_geminicli();
|
|
|
2650
3021
|
init_junie();
|
|
2651
3022
|
init_kiro();
|
|
2652
3023
|
init_roo();
|
|
3024
|
+
init_windsurf();
|
|
2653
3025
|
|
|
2654
3026
|
// src/core/mcp-parser.ts
|
|
2655
3027
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -2741,6 +3113,11 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2741
3113
|
tool: "roo-project",
|
|
2742
3114
|
path: path4.join(targetRoot, ".roo", "mcp.json"),
|
|
2743
3115
|
generate: () => generateRooMcp(config)
|
|
3116
|
+
},
|
|
3117
|
+
{
|
|
3118
|
+
tool: "windsurf-project",
|
|
3119
|
+
path: path4.join(targetRoot, "mcp_config.json"),
|
|
3120
|
+
generate: () => generateWindsurfMcp(config)
|
|
2744
3121
|
}
|
|
2745
3122
|
];
|
|
2746
3123
|
const filteredGenerators = targetTools ? generators.filter((g) => {
|
|
@@ -2757,7 +3134,7 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2757
3134
|
try {
|
|
2758
3135
|
const content = generator.generate();
|
|
2759
3136
|
const parsed = JSON.parse(content);
|
|
2760
|
-
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
3137
|
+
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo") || generator.tool.includes("windsurf")) {
|
|
2761
3138
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
2762
3139
|
results.push({
|
|
2763
3140
|
tool: generator.tool,
|
|
@@ -2869,12 +3246,12 @@ async function generateCommand(options = {}) {
|
|
|
2869
3246
|
for (const tool of targetTools) {
|
|
2870
3247
|
switch (tool) {
|
|
2871
3248
|
case "augmentcode":
|
|
2872
|
-
deleteTasks.push(removeDirectory((0,
|
|
2873
|
-
deleteTasks.push(removeDirectory((0,
|
|
3249
|
+
deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "rules")));
|
|
3250
|
+
deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "ignore")));
|
|
2874
3251
|
break;
|
|
2875
3252
|
case "augmentcode-legacy":
|
|
2876
3253
|
deleteTasks.push(removeClaudeGeneratedFiles());
|
|
2877
|
-
deleteTasks.push(removeDirectory((0,
|
|
3254
|
+
deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "ignore")));
|
|
2878
3255
|
break;
|
|
2879
3256
|
case "copilot":
|
|
2880
3257
|
deleteTasks.push(removeDirectory(config.outputPaths.copilot));
|
|
@@ -2897,6 +3274,9 @@ async function generateCommand(options = {}) {
|
|
|
2897
3274
|
case "kiro":
|
|
2898
3275
|
deleteTasks.push(removeDirectory(config.outputPaths.kiro));
|
|
2899
3276
|
break;
|
|
3277
|
+
case "windsurf":
|
|
3278
|
+
deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
|
|
3279
|
+
break;
|
|
2900
3280
|
}
|
|
2901
3281
|
}
|
|
2902
3282
|
await Promise.all(deleteTasks);
|
|
@@ -2969,9 +3349,9 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
2969
3349
|
|
|
2970
3350
|
// src/cli/commands/gitignore.ts
|
|
2971
3351
|
var import_node_fs2 = require("fs");
|
|
2972
|
-
var
|
|
3352
|
+
var import_node_path11 = require("path");
|
|
2973
3353
|
var gitignoreCommand = async () => {
|
|
2974
|
-
const gitignorePath = (0,
|
|
3354
|
+
const gitignorePath = (0, import_node_path11.join)(process.cwd(), ".gitignore");
|
|
2975
3355
|
const rulesFilesToIgnore = [
|
|
2976
3356
|
"# Generated by rulesync - AI tool configuration files",
|
|
2977
3357
|
"**/.github/copilot-instructions.md",
|
|
@@ -3035,11 +3415,11 @@ ${linesToAdd.join("\n")}
|
|
|
3035
3415
|
};
|
|
3036
3416
|
|
|
3037
3417
|
// src/core/importer.ts
|
|
3038
|
-
var
|
|
3039
|
-
var
|
|
3418
|
+
var import_node_path18 = require("path");
|
|
3419
|
+
var import_gray_matter6 = __toESM(require("gray-matter"), 1);
|
|
3040
3420
|
|
|
3041
3421
|
// src/parsers/augmentcode.ts
|
|
3042
|
-
var
|
|
3422
|
+
var import_node_path12 = require("path");
|
|
3043
3423
|
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
3044
3424
|
|
|
3045
3425
|
// src/utils/parser-helpers.ts
|
|
@@ -3061,36 +3441,63 @@ function addRules(result, rules) {
|
|
|
3061
3441
|
}
|
|
3062
3442
|
result.rules.push(...rules);
|
|
3063
3443
|
}
|
|
3064
|
-
function handleParseError(error, context) {
|
|
3065
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3066
|
-
return `${context}: ${errorMessage}`;
|
|
3067
|
-
}
|
|
3068
3444
|
async function safeReadFile(operation, errorContext) {
|
|
3069
3445
|
try {
|
|
3070
3446
|
const result = await operation();
|
|
3071
|
-
return
|
|
3447
|
+
return createSuccessResult(result);
|
|
3072
3448
|
} catch (error) {
|
|
3073
|
-
return
|
|
3074
|
-
success: false,
|
|
3075
|
-
error: handleParseError(error, errorContext)
|
|
3076
|
-
};
|
|
3449
|
+
return createErrorResult(error, errorContext);
|
|
3077
3450
|
}
|
|
3078
3451
|
}
|
|
3079
3452
|
|
|
3080
3453
|
// src/parsers/augmentcode.ts
|
|
3081
3454
|
async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
|
|
3455
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
3456
|
+
rulesDir: ".augment/rules",
|
|
3457
|
+
targetName: "augmentcode",
|
|
3458
|
+
filenamePrefix: "augmentcode"
|
|
3459
|
+
});
|
|
3460
|
+
}
|
|
3461
|
+
async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
3462
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
3463
|
+
legacyFilePath: ".augment-guidelines",
|
|
3464
|
+
targetName: "augmentcode-legacy",
|
|
3465
|
+
filenamePrefix: "augmentcode-legacy"
|
|
3466
|
+
});
|
|
3467
|
+
}
|
|
3468
|
+
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
3082
3469
|
const result = createParseResult();
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3470
|
+
if (config.rulesDir) {
|
|
3471
|
+
const rulesDir = (0, import_node_path12.join)(baseDir, config.rulesDir);
|
|
3472
|
+
if (await fileExists(rulesDir)) {
|
|
3473
|
+
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
3474
|
+
addRules(result, rulesResult.rules);
|
|
3475
|
+
result.errors.push(...rulesResult.errors);
|
|
3476
|
+
} else {
|
|
3477
|
+
addError(
|
|
3478
|
+
result,
|
|
3479
|
+
`No AugmentCode configuration found. Expected ${config.rulesDir} directory.`
|
|
3480
|
+
);
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
if (config.legacyFilePath) {
|
|
3484
|
+
const legacyPath = (0, import_node_path12.join)(baseDir, config.legacyFilePath);
|
|
3485
|
+
if (await fileExists(legacyPath)) {
|
|
3486
|
+
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
3487
|
+
if (legacyResult.rule) {
|
|
3488
|
+
addRule(result, legacyResult.rule);
|
|
3489
|
+
}
|
|
3490
|
+
result.errors.push(...legacyResult.errors);
|
|
3491
|
+
} else {
|
|
3492
|
+
addError(
|
|
3493
|
+
result,
|
|
3494
|
+
`No AugmentCode legacy configuration found. Expected ${config.legacyFilePath} file.`
|
|
3495
|
+
);
|
|
3496
|
+
}
|
|
3090
3497
|
}
|
|
3091
3498
|
return { rules: result.rules || [], errors: result.errors };
|
|
3092
3499
|
}
|
|
3093
|
-
async function parseAugmentRules(rulesDir) {
|
|
3500
|
+
async function parseAugmentRules(rulesDir, config) {
|
|
3094
3501
|
const rules = [];
|
|
3095
3502
|
const errors = [];
|
|
3096
3503
|
try {
|
|
@@ -3098,7 +3505,7 @@ async function parseAugmentRules(rulesDir) {
|
|
|
3098
3505
|
const files = await readdir2(rulesDir);
|
|
3099
3506
|
for (const file of files) {
|
|
3100
3507
|
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
3101
|
-
const filePath = (0,
|
|
3508
|
+
const filePath = (0, import_node_path12.join)(rulesDir, file);
|
|
3102
3509
|
try {
|
|
3103
3510
|
const rawContent = await readFileContent(filePath);
|
|
3104
3511
|
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
@@ -3107,10 +3514,10 @@ async function parseAugmentRules(rulesDir) {
|
|
|
3107
3514
|
const description = frontmatterData.description || "";
|
|
3108
3515
|
const tags = Array.isArray(frontmatterData.tags) ? frontmatterData.tags : void 0;
|
|
3109
3516
|
const isRoot = ruleType === "always";
|
|
3110
|
-
const filename = (0,
|
|
3517
|
+
const filename = (0, import_node_path12.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
|
|
3111
3518
|
const frontmatter = {
|
|
3112
3519
|
root: isRoot,
|
|
3113
|
-
targets: [
|
|
3520
|
+
targets: [config.targetName],
|
|
3114
3521
|
description,
|
|
3115
3522
|
globs: ["**/*"],
|
|
3116
3523
|
// AugmentCode doesn't use specific globs in the same way
|
|
@@ -3119,7 +3526,7 @@ async function parseAugmentRules(rulesDir) {
|
|
|
3119
3526
|
rules.push({
|
|
3120
3527
|
frontmatter,
|
|
3121
3528
|
content: parsed.content.trim(),
|
|
3122
|
-
filename:
|
|
3529
|
+
filename: `${config.filenamePrefix}-${ruleType}-${filename}`,
|
|
3123
3530
|
filepath: filePath
|
|
3124
3531
|
});
|
|
3125
3532
|
} catch (error) {
|
|
@@ -3130,50 +3537,33 @@ async function parseAugmentRules(rulesDir) {
|
|
|
3130
3537
|
}
|
|
3131
3538
|
} catch (error) {
|
|
3132
3539
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3133
|
-
errors.push(`Failed to read .
|
|
3540
|
+
errors.push(`Failed to read ${config.rulesDir || rulesDir} directory: ${errorMessage}`);
|
|
3134
3541
|
}
|
|
3135
3542
|
return { rules, errors };
|
|
3136
3543
|
}
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
if (content.trim()) {
|
|
3161
|
-
const frontmatter = {
|
|
3162
|
-
root: true,
|
|
3163
|
-
// Legacy guidelines become root rules
|
|
3164
|
-
targets: ["augmentcode-legacy"],
|
|
3165
|
-
description: "Legacy AugmentCode guidelines",
|
|
3166
|
-
globs: ["**/*"]
|
|
3167
|
-
};
|
|
3168
|
-
return {
|
|
3169
|
-
frontmatter,
|
|
3170
|
-
content: content.trim(),
|
|
3171
|
-
filename: "augmentcode-legacy-guidelines",
|
|
3172
|
-
filepath: guidelinesPath
|
|
3173
|
-
};
|
|
3174
|
-
}
|
|
3175
|
-
return null;
|
|
3176
|
-
}, "Failed to parse .augment-guidelines");
|
|
3544
|
+
async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
3545
|
+
const parseResult = await safeReadFile(
|
|
3546
|
+
async () => {
|
|
3547
|
+
const content = await readFileContent(guidelinesPath);
|
|
3548
|
+
if (content.trim()) {
|
|
3549
|
+
const frontmatter = {
|
|
3550
|
+
root: true,
|
|
3551
|
+
// Legacy guidelines become root rules
|
|
3552
|
+
targets: [config.targetName],
|
|
3553
|
+
description: "Legacy AugmentCode guidelines",
|
|
3554
|
+
globs: ["**/*"]
|
|
3555
|
+
};
|
|
3556
|
+
return {
|
|
3557
|
+
frontmatter,
|
|
3558
|
+
content: content.trim(),
|
|
3559
|
+
filename: `${config.filenamePrefix}-guidelines`,
|
|
3560
|
+
filepath: guidelinesPath
|
|
3561
|
+
};
|
|
3562
|
+
}
|
|
3563
|
+
return null;
|
|
3564
|
+
},
|
|
3565
|
+
`Failed to parse ${config.legacyFilePath || guidelinesPath}`
|
|
3566
|
+
);
|
|
3177
3567
|
if (parseResult.success) {
|
|
3178
3568
|
return { rule: parseResult.result || null, errors: [] };
|
|
3179
3569
|
} else {
|
|
@@ -3182,33 +3572,36 @@ async function parseAugmentGuidelines(guidelinesPath) {
|
|
|
3182
3572
|
}
|
|
3183
3573
|
|
|
3184
3574
|
// src/parsers/shared-helpers.ts
|
|
3185
|
-
var
|
|
3575
|
+
var import_node_path13 = require("path");
|
|
3186
3576
|
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
3187
3577
|
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
3188
3578
|
const errors = [];
|
|
3189
3579
|
const rules = [];
|
|
3190
3580
|
if (config.mainFile) {
|
|
3191
|
-
const
|
|
3581
|
+
const mainFile = config.mainFile;
|
|
3582
|
+
const mainFilePath = resolvePath(mainFile.path, baseDir);
|
|
3192
3583
|
if (await fileExists(mainFilePath)) {
|
|
3193
|
-
|
|
3584
|
+
const result = await safeAsyncOperation(async () => {
|
|
3194
3585
|
const rawContent = await readFileContent(mainFilePath);
|
|
3195
3586
|
let content;
|
|
3196
3587
|
let frontmatter;
|
|
3197
|
-
if (
|
|
3588
|
+
if (mainFile.useFrontmatter) {
|
|
3198
3589
|
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
3199
3590
|
content = parsed.content.trim();
|
|
3591
|
+
const parsedFrontmatter = parsed.data;
|
|
3200
3592
|
frontmatter = {
|
|
3201
|
-
root: false,
|
|
3593
|
+
root: mainFile.isRoot ?? false,
|
|
3202
3594
|
targets: [config.tool],
|
|
3203
|
-
description:
|
|
3204
|
-
globs: ["**/*"]
|
|
3595
|
+
description: parsedFrontmatter.description || mainFile.description,
|
|
3596
|
+
globs: Array.isArray(parsedFrontmatter.globs) ? parsedFrontmatter.globs : ["**/*"],
|
|
3597
|
+
...parsedFrontmatter.tags && { tags: parsedFrontmatter.tags }
|
|
3205
3598
|
};
|
|
3206
3599
|
} else {
|
|
3207
3600
|
content = rawContent.trim();
|
|
3208
3601
|
frontmatter = {
|
|
3209
|
-
root: false,
|
|
3602
|
+
root: mainFile.isRoot ?? false,
|
|
3210
3603
|
targets: [config.tool],
|
|
3211
|
-
description:
|
|
3604
|
+
description: mainFile.description,
|
|
3212
3605
|
globs: ["**/*"]
|
|
3213
3606
|
};
|
|
3214
3607
|
}
|
|
@@ -3216,43 +3609,52 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
3216
3609
|
rules.push({
|
|
3217
3610
|
frontmatter,
|
|
3218
3611
|
content,
|
|
3219
|
-
filename: "instructions",
|
|
3612
|
+
filename: mainFile.filenameOverride || "instructions",
|
|
3220
3613
|
filepath: mainFilePath
|
|
3221
3614
|
});
|
|
3222
3615
|
}
|
|
3223
|
-
}
|
|
3224
|
-
|
|
3225
|
-
errors.push(
|
|
3616
|
+
}, `Failed to parse ${mainFile.path}`);
|
|
3617
|
+
if (!result.success) {
|
|
3618
|
+
errors.push(result.error);
|
|
3226
3619
|
}
|
|
3227
3620
|
}
|
|
3228
3621
|
}
|
|
3229
3622
|
if (config.directories) {
|
|
3230
3623
|
for (const dirConfig of config.directories) {
|
|
3231
|
-
const dirPath = (
|
|
3624
|
+
const dirPath = resolvePath(dirConfig.directory, baseDir);
|
|
3232
3625
|
if (await fileExists(dirPath)) {
|
|
3233
|
-
|
|
3626
|
+
const result = await safeAsyncOperation(async () => {
|
|
3234
3627
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3235
3628
|
const files = await readdir2(dirPath);
|
|
3236
3629
|
for (const file of files) {
|
|
3237
3630
|
if (file.endsWith(dirConfig.filePattern)) {
|
|
3238
|
-
const filePath = (0,
|
|
3239
|
-
|
|
3631
|
+
const filePath = (0, import_node_path13.join)(dirPath, file);
|
|
3632
|
+
const fileResult = await safeAsyncOperation(async () => {
|
|
3240
3633
|
const rawContent = await readFileContent(filePath);
|
|
3241
3634
|
let content;
|
|
3635
|
+
let frontmatter;
|
|
3636
|
+
const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
|
|
3242
3637
|
if (dirConfig.filePattern === ".instructions.md") {
|
|
3243
3638
|
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
3244
3639
|
content = parsed.content.trim();
|
|
3640
|
+
const parsedFrontmatter = parsed.data;
|
|
3641
|
+
frontmatter = {
|
|
3642
|
+
root: false,
|
|
3643
|
+
targets: [config.tool],
|
|
3644
|
+
description: parsedFrontmatter.description || `${dirConfig.description}: ${filename}`,
|
|
3645
|
+
globs: Array.isArray(parsedFrontmatter.globs) ? parsedFrontmatter.globs : ["**/*"],
|
|
3646
|
+
...parsedFrontmatter.tags && { tags: parsedFrontmatter.tags }
|
|
3647
|
+
};
|
|
3245
3648
|
} else {
|
|
3246
3649
|
content = rawContent.trim();
|
|
3247
|
-
|
|
3248
|
-
if (content) {
|
|
3249
|
-
const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
|
|
3250
|
-
const frontmatter = {
|
|
3650
|
+
frontmatter = {
|
|
3251
3651
|
root: false,
|
|
3252
3652
|
targets: [config.tool],
|
|
3253
3653
|
description: `${dirConfig.description}: ${filename}`,
|
|
3254
3654
|
globs: ["**/*"]
|
|
3255
3655
|
};
|
|
3656
|
+
}
|
|
3657
|
+
if (content) {
|
|
3256
3658
|
rules.push({
|
|
3257
3659
|
frontmatter,
|
|
3258
3660
|
content,
|
|
@@ -3260,15 +3662,15 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
3260
3662
|
filepath: filePath
|
|
3261
3663
|
});
|
|
3262
3664
|
}
|
|
3263
|
-
}
|
|
3264
|
-
|
|
3265
|
-
errors.push(
|
|
3665
|
+
}, `Failed to parse ${filePath}`);
|
|
3666
|
+
if (!fileResult.success) {
|
|
3667
|
+
errors.push(fileResult.error);
|
|
3266
3668
|
}
|
|
3267
3669
|
}
|
|
3268
3670
|
}
|
|
3269
|
-
}
|
|
3270
|
-
|
|
3271
|
-
errors.push(
|
|
3671
|
+
}, `Failed to parse ${dirConfig.directory} files`);
|
|
3672
|
+
if (!result.success) {
|
|
3673
|
+
errors.push(result.error);
|
|
3272
3674
|
}
|
|
3273
3675
|
}
|
|
3274
3676
|
}
|
|
@@ -3283,7 +3685,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3283
3685
|
const rules = [];
|
|
3284
3686
|
let ignorePatterns;
|
|
3285
3687
|
let mcpServers;
|
|
3286
|
-
const mainFilePath = (
|
|
3688
|
+
const mainFilePath = resolvePath(config.mainFileName, baseDir);
|
|
3287
3689
|
if (!await fileExists(mainFilePath)) {
|
|
3288
3690
|
errors.push(`${config.mainFileName} file not found`);
|
|
3289
3691
|
return { rules, errors };
|
|
@@ -3294,12 +3696,12 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3294
3696
|
if (mainRule) {
|
|
3295
3697
|
rules.push(mainRule);
|
|
3296
3698
|
}
|
|
3297
|
-
const memoryDir = (
|
|
3699
|
+
const memoryDir = resolvePath(config.memoryDirPath, baseDir);
|
|
3298
3700
|
if (await fileExists(memoryDir)) {
|
|
3299
3701
|
const memoryRules = await parseMemoryFiles(memoryDir, config);
|
|
3300
3702
|
rules.push(...memoryRules);
|
|
3301
3703
|
}
|
|
3302
|
-
const settingsPath = (
|
|
3704
|
+
const settingsPath = resolvePath(config.settingsPath, baseDir);
|
|
3303
3705
|
if (await fileExists(settingsPath)) {
|
|
3304
3706
|
const settingsResult = await parseSettingsFile(settingsPath, config.tool);
|
|
3305
3707
|
if (settingsResult.ignorePatterns) {
|
|
@@ -3311,7 +3713,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3311
3713
|
errors.push(...settingsResult.errors);
|
|
3312
3714
|
}
|
|
3313
3715
|
if (config.additionalIgnoreFile) {
|
|
3314
|
-
const additionalIgnorePath = (
|
|
3716
|
+
const additionalIgnorePath = resolvePath(config.additionalIgnoreFile.path, baseDir);
|
|
3315
3717
|
if (await fileExists(additionalIgnorePath)) {
|
|
3316
3718
|
const additionalPatterns = await config.additionalIgnoreFile.parser(additionalIgnorePath);
|
|
3317
3719
|
if (additionalPatterns.length > 0) {
|
|
@@ -3320,8 +3722,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3320
3722
|
}
|
|
3321
3723
|
}
|
|
3322
3724
|
} catch (error) {
|
|
3323
|
-
|
|
3324
|
-
errors.push(`Failed to parse ${config.tool} configuration: ${errorMessage}`);
|
|
3725
|
+
errors.push(`Failed to parse ${config.tool} configuration: ${getErrorMessage(error)}`);
|
|
3325
3726
|
}
|
|
3326
3727
|
return {
|
|
3327
3728
|
rules,
|
|
@@ -3365,10 +3766,10 @@ async function parseMemoryFiles(memoryDir, config) {
|
|
|
3365
3766
|
const files = await readdir2(memoryDir);
|
|
3366
3767
|
for (const file of files) {
|
|
3367
3768
|
if (file.endsWith(".md")) {
|
|
3368
|
-
const filePath = (0,
|
|
3769
|
+
const filePath = (0, import_node_path13.join)(memoryDir, file);
|
|
3369
3770
|
const content = await readFileContent(filePath);
|
|
3370
3771
|
if (content.trim()) {
|
|
3371
|
-
const filename = (0,
|
|
3772
|
+
const filename = (0, import_node_path13.basename)(file, ".md");
|
|
3372
3773
|
const frontmatter = {
|
|
3373
3774
|
root: false,
|
|
3374
3775
|
targets: [config.tool],
|
|
@@ -3417,8 +3818,7 @@ async function parseSettingsFile(settingsPath, tool) {
|
|
|
3417
3818
|
mcpServers = parseResult.data.mcpServers;
|
|
3418
3819
|
}
|
|
3419
3820
|
} catch (error) {
|
|
3420
|
-
|
|
3421
|
-
errors.push(`Failed to parse settings.json: ${errorMessage}`);
|
|
3821
|
+
errors.push(`Failed to parse settings.json: ${getErrorMessage(error)}`);
|
|
3422
3822
|
}
|
|
3423
3823
|
return {
|
|
3424
3824
|
errors,
|
|
@@ -3461,7 +3861,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
3461
3861
|
}
|
|
3462
3862
|
|
|
3463
3863
|
// src/parsers/codexcli.ts
|
|
3464
|
-
var
|
|
3864
|
+
var import_node_path14 = require("path");
|
|
3465
3865
|
|
|
3466
3866
|
// src/parsers/copilot.ts
|
|
3467
3867
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
@@ -3484,7 +3884,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
3484
3884
|
}
|
|
3485
3885
|
|
|
3486
3886
|
// src/parsers/cursor.ts
|
|
3487
|
-
var
|
|
3887
|
+
var import_node_path15 = require("path");
|
|
3488
3888
|
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
3489
3889
|
var import_js_yaml = require("js-yaml");
|
|
3490
3890
|
var import_mini7 = require("zod/mini");
|
|
@@ -3609,7 +4009,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3609
4009
|
const rules = [];
|
|
3610
4010
|
let ignorePatterns;
|
|
3611
4011
|
let mcpServers;
|
|
3612
|
-
const cursorFilePath = (0,
|
|
4012
|
+
const cursorFilePath = (0, import_node_path15.join)(baseDir, ".cursorrules");
|
|
3613
4013
|
if (await fileExists(cursorFilePath)) {
|
|
3614
4014
|
try {
|
|
3615
4015
|
const rawContent = await readFileContent(cursorFilePath);
|
|
@@ -3630,20 +4030,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3630
4030
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
3631
4031
|
}
|
|
3632
4032
|
}
|
|
3633
|
-
const cursorRulesDir = (0,
|
|
4033
|
+
const cursorRulesDir = (0, import_node_path15.join)(baseDir, ".cursor", "rules");
|
|
3634
4034
|
if (await fileExists(cursorRulesDir)) {
|
|
3635
4035
|
try {
|
|
3636
4036
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3637
4037
|
const files = await readdir2(cursorRulesDir);
|
|
3638
4038
|
for (const file of files) {
|
|
3639
4039
|
if (file.endsWith(".mdc")) {
|
|
3640
|
-
const filePath = (0,
|
|
4040
|
+
const filePath = (0, import_node_path15.join)(cursorRulesDir, file);
|
|
3641
4041
|
try {
|
|
3642
4042
|
const rawContent = await readFileContent(filePath);
|
|
3643
4043
|
const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
|
|
3644
4044
|
const content = parsed.content.trim();
|
|
3645
4045
|
if (content) {
|
|
3646
|
-
const filename = (0,
|
|
4046
|
+
const filename = (0, import_node_path15.basename)(file, ".mdc");
|
|
3647
4047
|
const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
|
|
3648
4048
|
rules.push({
|
|
3649
4049
|
frontmatter,
|
|
@@ -3666,7 +4066,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3666
4066
|
if (rules.length === 0) {
|
|
3667
4067
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
3668
4068
|
}
|
|
3669
|
-
const cursorIgnorePath = (0,
|
|
4069
|
+
const cursorIgnorePath = (0, import_node_path15.join)(baseDir, ".cursorignore");
|
|
3670
4070
|
if (await fileExists(cursorIgnorePath)) {
|
|
3671
4071
|
try {
|
|
3672
4072
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -3679,7 +4079,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3679
4079
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
3680
4080
|
}
|
|
3681
4081
|
}
|
|
3682
|
-
const cursorMcpPath = (0,
|
|
4082
|
+
const cursorMcpPath = (0, import_node_path15.join)(baseDir, ".cursor", "mcp.json");
|
|
3683
4083
|
if (await fileExists(cursorMcpPath)) {
|
|
3684
4084
|
try {
|
|
3685
4085
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -3728,11 +4128,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
3728
4128
|
}
|
|
3729
4129
|
|
|
3730
4130
|
// src/parsers/junie.ts
|
|
3731
|
-
var
|
|
4131
|
+
var import_node_path16 = require("path");
|
|
3732
4132
|
async function parseJunieConfiguration(baseDir = process.cwd()) {
|
|
3733
4133
|
const errors = [];
|
|
3734
4134
|
const rules = [];
|
|
3735
|
-
const guidelinesPath = (0,
|
|
4135
|
+
const guidelinesPath = (0, import_node_path16.join)(baseDir, ".junie", "guidelines.md");
|
|
3736
4136
|
if (!await fileExists(guidelinesPath)) {
|
|
3737
4137
|
errors.push(".junie/guidelines.md file not found");
|
|
3738
4138
|
return { rules, errors };
|
|
@@ -3783,6 +4183,11 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
3783
4183
|
});
|
|
3784
4184
|
}
|
|
3785
4185
|
|
|
4186
|
+
// src/parsers/windsurf.ts
|
|
4187
|
+
var import_promises3 = require("fs/promises");
|
|
4188
|
+
var import_node_path17 = require("path");
|
|
4189
|
+
var import_gray_matter5 = __toESM(require("gray-matter"), 1);
|
|
4190
|
+
|
|
3786
4191
|
// src/core/importer.ts
|
|
3787
4192
|
async function importConfiguration(options) {
|
|
3788
4193
|
const { tool, baseDir = process.cwd(), rulesDir = ".rulesync", verbose = false } = options;
|
|
@@ -3867,7 +4272,7 @@ async function importConfiguration(options) {
|
|
|
3867
4272
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
3868
4273
|
return { success: false, rulesCreated: 0, errors };
|
|
3869
4274
|
}
|
|
3870
|
-
const rulesDirPath = (0,
|
|
4275
|
+
const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
|
|
3871
4276
|
try {
|
|
3872
4277
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
3873
4278
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -3881,7 +4286,7 @@ async function importConfiguration(options) {
|
|
|
3881
4286
|
try {
|
|
3882
4287
|
const baseFilename = rule.filename;
|
|
3883
4288
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
3884
|
-
const filePath = (0,
|
|
4289
|
+
const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
|
|
3885
4290
|
const content = generateRuleFileContent(rule);
|
|
3886
4291
|
await writeFileContent(filePath, content);
|
|
3887
4292
|
rulesCreated++;
|
|
@@ -3896,7 +4301,7 @@ async function importConfiguration(options) {
|
|
|
3896
4301
|
let ignoreFileCreated = false;
|
|
3897
4302
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
3898
4303
|
try {
|
|
3899
|
-
const rulesyncignorePath = (0,
|
|
4304
|
+
const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
|
|
3900
4305
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
3901
4306
|
`;
|
|
3902
4307
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -3912,7 +4317,7 @@ async function importConfiguration(options) {
|
|
|
3912
4317
|
let mcpFileCreated = false;
|
|
3913
4318
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
3914
4319
|
try {
|
|
3915
|
-
const mcpPath = (0,
|
|
4320
|
+
const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
|
|
3916
4321
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
3917
4322
|
`;
|
|
3918
4323
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -3934,13 +4339,13 @@ async function importConfiguration(options) {
|
|
|
3934
4339
|
};
|
|
3935
4340
|
}
|
|
3936
4341
|
function generateRuleFileContent(rule) {
|
|
3937
|
-
const frontmatter =
|
|
4342
|
+
const frontmatter = import_gray_matter6.default.stringify("", rule.frontmatter);
|
|
3938
4343
|
return frontmatter + rule.content;
|
|
3939
4344
|
}
|
|
3940
4345
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
3941
4346
|
let filename = baseFilename;
|
|
3942
4347
|
let counter = 1;
|
|
3943
|
-
while (await fileExists((0,
|
|
4348
|
+
while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
|
|
3944
4349
|
filename = `${baseFilename}-${counter}`;
|
|
3945
4350
|
counter++;
|
|
3946
4351
|
}
|
|
@@ -4007,7 +4412,7 @@ async function importCommand(options = {}) {
|
|
|
4007
4412
|
}
|
|
4008
4413
|
|
|
4009
4414
|
// src/cli/commands/init.ts
|
|
4010
|
-
var
|
|
4415
|
+
var import_node_path19 = require("path");
|
|
4011
4416
|
async function initCommand() {
|
|
4012
4417
|
const aiRulesDir = ".rulesync";
|
|
4013
4418
|
console.log("Initializing rulesync...");
|
|
@@ -4054,7 +4459,7 @@ globs: ["**/*"]
|
|
|
4054
4459
|
- Follow single responsibility principle
|
|
4055
4460
|
`
|
|
4056
4461
|
};
|
|
4057
|
-
const filepath = (0,
|
|
4462
|
+
const filepath = (0, import_node_path19.join)(aiRulesDir, sampleFile.filename);
|
|
4058
4463
|
if (!await fileExists(filepath)) {
|
|
4059
4464
|
await writeFileContent(filepath, sampleFile.content);
|
|
4060
4465
|
console.log(`Created ${filepath}`);
|
|
@@ -4198,7 +4603,7 @@ async function watchCommand() {
|
|
|
4198
4603
|
|
|
4199
4604
|
// src/cli/index.ts
|
|
4200
4605
|
var program = new import_commander.Command();
|
|
4201
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
4606
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.56.0");
|
|
4202
4607
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
4203
4608
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
4204
4609
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|