rulesync 7.15.2 → 7.17.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 +1 -1
- package/dist/{chunk-WY325EI7.js → chunk-ZQUEAGJI.js} +164 -60
- package/dist/cli/index.cjs +331 -194
- package/dist/cli/index.js +177 -138
- package/dist/index.cjs +160 -61
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,8 @@ var RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path.join)(
|
|
|
60
60
|
RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
61
61
|
".curated"
|
|
62
62
|
);
|
|
63
|
+
var RULESYNC_MCP_FILE_NAME = "mcp.json";
|
|
64
|
+
var RULESYNC_MCP_SCHEMA_URL = "https://github.com/dyoshikawa/rulesync/releases/latest/download/mcp-schema.json";
|
|
63
65
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
64
66
|
|
|
65
67
|
// src/utils/error.ts
|
|
@@ -351,14 +353,21 @@ var ToolTargetSchema = import_mini2.z.enum(ALL_TOOL_TARGETS);
|
|
|
351
353
|
var ToolTargetsSchema = import_mini2.z.array(ToolTargetSchema);
|
|
352
354
|
var RulesyncTargetsSchema = import_mini2.z.array(import_mini2.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
|
|
353
355
|
|
|
354
|
-
// src/
|
|
355
|
-
function
|
|
356
|
+
// src/utils/validation.ts
|
|
357
|
+
function findControlCharacter(value) {
|
|
356
358
|
for (let i = 0; i < value.length; i++) {
|
|
357
359
|
const code = value.charCodeAt(i);
|
|
358
|
-
if (code >= 0 && code <= 31 || code === 127)
|
|
360
|
+
if (code >= 0 && code <= 31 || code === 127) {
|
|
361
|
+
return { position: i, hex: `0x${code.toString(16).padStart(2, "0")}` };
|
|
362
|
+
}
|
|
359
363
|
}
|
|
360
|
-
return
|
|
364
|
+
return null;
|
|
361
365
|
}
|
|
366
|
+
function hasControlCharacters(value) {
|
|
367
|
+
return findControlCharacter(value) !== null;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/config/config.ts
|
|
362
371
|
var SourceEntrySchema = import_mini3.z.object({
|
|
363
372
|
source: import_mini3.z.string().check((0, import_mini3.minLength)(1, "source must be a non-empty string")),
|
|
364
373
|
skills: (0, import_mini3.optional)(import_mini3.z.array(import_mini3.z.string())),
|
|
@@ -738,6 +747,7 @@ var import_node_path7 = require("path");
|
|
|
738
747
|
|
|
739
748
|
// src/utils/frontmatter.ts
|
|
740
749
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
750
|
+
var import_js_yaml = require("js-yaml");
|
|
741
751
|
function isPlainObject(value) {
|
|
742
752
|
if (value === null || typeof value !== "object") return false;
|
|
743
753
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -776,8 +786,55 @@ function deepRemoveNullishObject(obj) {
|
|
|
776
786
|
}
|
|
777
787
|
return result;
|
|
778
788
|
}
|
|
779
|
-
function
|
|
780
|
-
|
|
789
|
+
function deepFlattenStringsValue(value) {
|
|
790
|
+
if (value === null || value === void 0) {
|
|
791
|
+
return void 0;
|
|
792
|
+
}
|
|
793
|
+
if (typeof value === "string") {
|
|
794
|
+
return value.replace(/\n+/g, " ").trim();
|
|
795
|
+
}
|
|
796
|
+
if (Array.isArray(value)) {
|
|
797
|
+
const cleanedArray = value.map((item) => deepFlattenStringsValue(item)).filter((item) => item !== void 0);
|
|
798
|
+
return cleanedArray;
|
|
799
|
+
}
|
|
800
|
+
if (isPlainObject(value)) {
|
|
801
|
+
const result = {};
|
|
802
|
+
for (const [key, val] of Object.entries(value)) {
|
|
803
|
+
const cleaned = deepFlattenStringsValue(val);
|
|
804
|
+
if (cleaned !== void 0) {
|
|
805
|
+
result[key] = cleaned;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return result;
|
|
809
|
+
}
|
|
810
|
+
return value;
|
|
811
|
+
}
|
|
812
|
+
function deepFlattenStringsObject(obj) {
|
|
813
|
+
if (!obj || typeof obj !== "object") {
|
|
814
|
+
return {};
|
|
815
|
+
}
|
|
816
|
+
const result = {};
|
|
817
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
818
|
+
const cleaned = deepFlattenStringsValue(val);
|
|
819
|
+
if (cleaned !== void 0) {
|
|
820
|
+
result[key] = cleaned;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
return result;
|
|
824
|
+
}
|
|
825
|
+
function stringifyFrontmatter(body, frontmatter, options) {
|
|
826
|
+
const { avoidBlockScalars = false } = options ?? {};
|
|
827
|
+
const cleanFrontmatter = avoidBlockScalars ? deepFlattenStringsObject(frontmatter) : deepRemoveNullishObject(frontmatter);
|
|
828
|
+
if (avoidBlockScalars) {
|
|
829
|
+
return import_gray_matter.default.stringify(body, cleanFrontmatter, {
|
|
830
|
+
engines: {
|
|
831
|
+
yaml: {
|
|
832
|
+
parse: (input) => (0, import_js_yaml.load)(input) ?? {},
|
|
833
|
+
stringify: (data) => (0, import_js_yaml.dump)(data, { lineWidth: -1 })
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
781
838
|
return import_gray_matter.default.stringify(body, cleanFrontmatter);
|
|
782
839
|
}
|
|
783
840
|
function parseFrontmatter(content, filePath) {
|
|
@@ -1896,7 +1953,7 @@ var CursorCommand = class _CursorCommand extends ToolCommand {
|
|
|
1896
1953
|
}
|
|
1897
1954
|
super({
|
|
1898
1955
|
...rest,
|
|
1899
|
-
fileContent: stringifyFrontmatter(body, frontmatter)
|
|
1956
|
+
fileContent: stringifyFrontmatter(body, frontmatter, { avoidBlockScalars: true })
|
|
1900
1957
|
});
|
|
1901
1958
|
this.frontmatter = frontmatter;
|
|
1902
1959
|
this.body = body;
|
|
@@ -5694,7 +5751,7 @@ var import_mini20 = require("zod/mini");
|
|
|
5694
5751
|
|
|
5695
5752
|
// src/types/mcp.ts
|
|
5696
5753
|
var import_mini19 = require("zod/mini");
|
|
5697
|
-
var McpServerSchema = import_mini19.z.
|
|
5754
|
+
var McpServerSchema = import_mini19.z.looseObject({
|
|
5698
5755
|
type: import_mini19.z.optional(import_mini19.z.enum(["stdio", "sse", "http"])),
|
|
5699
5756
|
command: import_mini19.z.optional(import_mini19.z.union([import_mini19.z.string(), import_mini19.z.array(import_mini19.z.string())])),
|
|
5700
5757
|
args: import_mini19.z.optional(import_mini19.z.array(import_mini19.z.string())),
|
|
@@ -5726,6 +5783,10 @@ var RulesyncMcpServerSchema = import_mini20.z.extend(McpServerSchema, {
|
|
|
5726
5783
|
var RulesyncMcpConfigSchema = import_mini20.z.object({
|
|
5727
5784
|
mcpServers: import_mini20.z.record(import_mini20.z.string(), RulesyncMcpServerSchema)
|
|
5728
5785
|
});
|
|
5786
|
+
var RulesyncMcpFileSchema = import_mini20.z.looseObject({
|
|
5787
|
+
$schema: import_mini20.z.optional(import_mini20.z.string()),
|
|
5788
|
+
...RulesyncMcpConfigSchema.shape
|
|
5789
|
+
});
|
|
5729
5790
|
var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
|
|
5730
5791
|
json;
|
|
5731
5792
|
constructor(params) {
|
|
@@ -5751,7 +5812,7 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
|
|
|
5751
5812
|
};
|
|
5752
5813
|
}
|
|
5753
5814
|
validate() {
|
|
5754
|
-
const result =
|
|
5815
|
+
const result = RulesyncMcpFileSchema.safeParse(this.json);
|
|
5755
5816
|
if (!result.success) {
|
|
5756
5817
|
return { success: false, error: result.error };
|
|
5757
5818
|
}
|
|
@@ -5854,11 +5915,17 @@ var ToolMcp = class extends ToolFile {
|
|
|
5854
5915
|
toRulesyncMcpDefault({
|
|
5855
5916
|
fileContent = void 0
|
|
5856
5917
|
} = {}) {
|
|
5918
|
+
const content = fileContent ?? this.fileContent;
|
|
5919
|
+
const { $schema: _, ...json } = JSON.parse(content);
|
|
5920
|
+
const withSchema = {
|
|
5921
|
+
$schema: RULESYNC_MCP_SCHEMA_URL,
|
|
5922
|
+
...json
|
|
5923
|
+
};
|
|
5857
5924
|
return new RulesyncMcp({
|
|
5858
5925
|
baseDir: this.baseDir,
|
|
5859
5926
|
relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
|
|
5860
|
-
relativeFilePath:
|
|
5861
|
-
fileContent:
|
|
5927
|
+
relativeFilePath: RULESYNC_MCP_FILE_NAME,
|
|
5928
|
+
fileContent: JSON.stringify(withSchema, null, 2)
|
|
5862
5929
|
});
|
|
5863
5930
|
}
|
|
5864
5931
|
static async fromFile(_params) {
|
|
@@ -6161,10 +6228,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
|
|
|
6161
6228
|
toRulesyncMcp() {
|
|
6162
6229
|
const mcpServers = this.toml.mcp_servers ?? {};
|
|
6163
6230
|
const converted = convertFromCodexFormat(mcpServers);
|
|
6164
|
-
return
|
|
6165
|
-
baseDir: this.baseDir,
|
|
6166
|
-
relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
|
|
6167
|
-
relativeFilePath: ".mcp.json",
|
|
6231
|
+
return this.toRulesyncMcpDefault({
|
|
6168
6232
|
fileContent: JSON.stringify({ mcpServers: converted }, null, 2)
|
|
6169
6233
|
});
|
|
6170
6234
|
}
|
|
@@ -6322,12 +6386,26 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
6322
6386
|
json;
|
|
6323
6387
|
constructor(params) {
|
|
6324
6388
|
super(params);
|
|
6325
|
-
|
|
6389
|
+
if (this.fileContent !== void 0) {
|
|
6390
|
+
try {
|
|
6391
|
+
this.json = JSON.parse(this.fileContent);
|
|
6392
|
+
} catch (error) {
|
|
6393
|
+
throw new Error(
|
|
6394
|
+
`Failed to parse Cursor MCP config at ${(0, import_node_path48.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(error)}`,
|
|
6395
|
+
{ cause: error }
|
|
6396
|
+
);
|
|
6397
|
+
}
|
|
6398
|
+
} else {
|
|
6399
|
+
this.json = {};
|
|
6400
|
+
}
|
|
6326
6401
|
}
|
|
6327
6402
|
getJson() {
|
|
6328
6403
|
return this.json;
|
|
6329
6404
|
}
|
|
6330
|
-
|
|
6405
|
+
isDeletable() {
|
|
6406
|
+
return !this.global;
|
|
6407
|
+
}
|
|
6408
|
+
static getSettablePaths(_options) {
|
|
6331
6409
|
return {
|
|
6332
6410
|
relativeDirPath: ".cursor",
|
|
6333
6411
|
relativeFilePath: "mcp.json"
|
|
@@ -6335,41 +6413,62 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
6335
6413
|
}
|
|
6336
6414
|
static async fromFile({
|
|
6337
6415
|
baseDir = process.cwd(),
|
|
6338
|
-
validate = true
|
|
6416
|
+
validate = true,
|
|
6417
|
+
global = false
|
|
6339
6418
|
}) {
|
|
6340
|
-
const
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
)
|
|
6346
|
-
)
|
|
6419
|
+
const paths = this.getSettablePaths({ global });
|
|
6420
|
+
const filePath = (0, import_node_path48.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath);
|
|
6421
|
+
const fileContent = await readFileContentOrNull(filePath) ?? '{"mcpServers":{}}';
|
|
6422
|
+
let json;
|
|
6423
|
+
try {
|
|
6424
|
+
json = JSON.parse(fileContent);
|
|
6425
|
+
} catch (error) {
|
|
6426
|
+
throw new Error(
|
|
6427
|
+
`Failed to parse Cursor MCP config at ${(0, import_node_path48.join)(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError(error)}`,
|
|
6428
|
+
{ cause: error }
|
|
6429
|
+
);
|
|
6430
|
+
}
|
|
6431
|
+
const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
|
|
6347
6432
|
return new _CursorMcp({
|
|
6348
6433
|
baseDir,
|
|
6349
|
-
relativeDirPath:
|
|
6350
|
-
relativeFilePath:
|
|
6351
|
-
fileContent,
|
|
6352
|
-
validate
|
|
6434
|
+
relativeDirPath: paths.relativeDirPath,
|
|
6435
|
+
relativeFilePath: paths.relativeFilePath,
|
|
6436
|
+
fileContent: JSON.stringify(newJson, null, 2),
|
|
6437
|
+
validate,
|
|
6438
|
+
global
|
|
6353
6439
|
});
|
|
6354
6440
|
}
|
|
6355
|
-
static fromRulesyncMcp({
|
|
6441
|
+
static async fromRulesyncMcp({
|
|
6356
6442
|
baseDir = process.cwd(),
|
|
6357
6443
|
rulesyncMcp,
|
|
6358
|
-
validate = true
|
|
6444
|
+
validate = true,
|
|
6445
|
+
global = false
|
|
6359
6446
|
}) {
|
|
6360
|
-
const
|
|
6361
|
-
const
|
|
6447
|
+
const paths = this.getSettablePaths({ global });
|
|
6448
|
+
const fileContent = await readOrInitializeFileContent(
|
|
6449
|
+
(0, import_node_path48.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
6450
|
+
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
6451
|
+
);
|
|
6452
|
+
let json;
|
|
6453
|
+
try {
|
|
6454
|
+
json = JSON.parse(fileContent);
|
|
6455
|
+
} catch (error) {
|
|
6456
|
+
throw new Error(
|
|
6457
|
+
`Failed to parse Cursor MCP config at ${(0, import_node_path48.join)(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError(error)}`,
|
|
6458
|
+
{ cause: error }
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6461
|
+
const rulesyncJson = rulesyncMcp.getJson();
|
|
6462
|
+
const mcpServers = isMcpServers(rulesyncJson.mcpServers) ? rulesyncJson.mcpServers : {};
|
|
6362
6463
|
const transformedServers = convertEnvToCursorFormat(mcpServers);
|
|
6363
|
-
const cursorConfig = {
|
|
6364
|
-
mcpServers: transformedServers
|
|
6365
|
-
};
|
|
6366
|
-
const fileContent = JSON.stringify(cursorConfig, null, 2);
|
|
6464
|
+
const cursorConfig = { ...json, mcpServers: transformedServers };
|
|
6367
6465
|
return new _CursorMcp({
|
|
6368
6466
|
baseDir,
|
|
6369
|
-
relativeDirPath:
|
|
6370
|
-
relativeFilePath:
|
|
6371
|
-
fileContent,
|
|
6372
|
-
validate
|
|
6467
|
+
relativeDirPath: paths.relativeDirPath,
|
|
6468
|
+
relativeFilePath: paths.relativeFilePath,
|
|
6469
|
+
fileContent: JSON.stringify(cursorConfig, null, 2),
|
|
6470
|
+
validate,
|
|
6471
|
+
global
|
|
6373
6472
|
});
|
|
6374
6473
|
}
|
|
6375
6474
|
toRulesyncMcp() {
|
|
@@ -6379,12 +6478,8 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
6379
6478
|
...this.json,
|
|
6380
6479
|
mcpServers: transformedServers
|
|
6381
6480
|
};
|
|
6382
|
-
return
|
|
6383
|
-
|
|
6384
|
-
relativeDirPath: this.relativeDirPath,
|
|
6385
|
-
relativeFilePath: "rulesync.mcp.json",
|
|
6386
|
-
fileContent: JSON.stringify(transformedJson),
|
|
6387
|
-
validate: true
|
|
6481
|
+
return this.toRulesyncMcpDefault({
|
|
6482
|
+
fileContent: JSON.stringify(transformedJson, null, 2)
|
|
6388
6483
|
});
|
|
6389
6484
|
}
|
|
6390
6485
|
validate() {
|
|
@@ -6393,14 +6488,16 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
6393
6488
|
static forDeletion({
|
|
6394
6489
|
baseDir = process.cwd(),
|
|
6395
6490
|
relativeDirPath,
|
|
6396
|
-
relativeFilePath
|
|
6491
|
+
relativeFilePath,
|
|
6492
|
+
global = false
|
|
6397
6493
|
}) {
|
|
6398
6494
|
return new _CursorMcp({
|
|
6399
6495
|
baseDir,
|
|
6400
6496
|
relativeDirPath,
|
|
6401
6497
|
relativeFilePath,
|
|
6402
6498
|
fileContent: "{}",
|
|
6403
|
-
validate: false
|
|
6499
|
+
validate: false,
|
|
6500
|
+
global
|
|
6404
6501
|
});
|
|
6405
6502
|
}
|
|
6406
6503
|
};
|
|
@@ -6460,13 +6557,7 @@ var FactorydroidMcp = class _FactorydroidMcp extends ToolMcp {
|
|
|
6460
6557
|
});
|
|
6461
6558
|
}
|
|
6462
6559
|
toRulesyncMcp() {
|
|
6463
|
-
return
|
|
6464
|
-
baseDir: this.baseDir,
|
|
6465
|
-
relativeDirPath: this.relativeDirPath,
|
|
6466
|
-
relativeFilePath: "rulesync.mcp.json",
|
|
6467
|
-
fileContent: JSON.stringify(this.json),
|
|
6468
|
-
validate: true
|
|
6469
|
-
});
|
|
6560
|
+
return this.toRulesyncMcpDefault();
|
|
6470
6561
|
}
|
|
6471
6562
|
validate() {
|
|
6472
6563
|
return { success: true, error: null };
|
|
@@ -7229,7 +7320,7 @@ var toolMcpFactories = /* @__PURE__ */ new Map([
|
|
|
7229
7320
|
class: CursorMcp,
|
|
7230
7321
|
meta: {
|
|
7231
7322
|
supportsProject: true,
|
|
7232
|
-
supportsGlobal:
|
|
7323
|
+
supportsGlobal: true,
|
|
7233
7324
|
supportsEnabledTools: false,
|
|
7234
7325
|
supportsDisabledTools: false
|
|
7235
7326
|
}
|
|
@@ -7942,9 +8033,15 @@ var import_node_path61 = require("path");
|
|
|
7942
8033
|
var DirFeatureProcessor = class {
|
|
7943
8034
|
baseDir;
|
|
7944
8035
|
dryRun;
|
|
7945
|
-
|
|
8036
|
+
avoidBlockScalars;
|
|
8037
|
+
constructor({
|
|
8038
|
+
baseDir = process.cwd(),
|
|
8039
|
+
dryRun = false,
|
|
8040
|
+
avoidBlockScalars = false
|
|
8041
|
+
}) {
|
|
7946
8042
|
this.baseDir = baseDir;
|
|
7947
8043
|
this.dryRun = dryRun;
|
|
8044
|
+
this.avoidBlockScalars = avoidBlockScalars;
|
|
7948
8045
|
}
|
|
7949
8046
|
/**
|
|
7950
8047
|
* Return tool targets that this feature supports.
|
|
@@ -7970,7 +8067,9 @@ var DirFeatureProcessor = class {
|
|
|
7970
8067
|
let mainFileContent;
|
|
7971
8068
|
if (mainFile) {
|
|
7972
8069
|
const mainFilePath = (0, import_node_path61.join)(dirPath, mainFile.name);
|
|
7973
|
-
const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter
|
|
8070
|
+
const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter, {
|
|
8071
|
+
avoidBlockScalars: this.avoidBlockScalars
|
|
8072
|
+
});
|
|
7974
8073
|
mainFileContent = addTrailingNewline(content);
|
|
7975
8074
|
const existingContent = await readFileContentOrNull(mainFilePath);
|
|
7976
8075
|
if (existingContent !== mainFileContent) {
|
|
@@ -10709,7 +10808,7 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
10709
10808
|
getFactory = defaultGetFactory4,
|
|
10710
10809
|
dryRun = false
|
|
10711
10810
|
}) {
|
|
10712
|
-
super({ baseDir, dryRun });
|
|
10811
|
+
super({ baseDir, dryRun, avoidBlockScalars: toolTarget === "cursor" });
|
|
10713
10812
|
const result = SkillsProcessorToolTargetSchema.safeParse(toolTarget);
|
|
10714
10813
|
if (!result.success) {
|
|
10715
10814
|
throw new Error(
|
|
@@ -11790,7 +11889,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
11790
11889
|
...cursorSection
|
|
11791
11890
|
};
|
|
11792
11891
|
const body = rulesyncSubagent.getBody();
|
|
11793
|
-
const fileContent = stringifyFrontmatter(body, cursorFrontmatter);
|
|
11892
|
+
const fileContent = stringifyFrontmatter(body, cursorFrontmatter, { avoidBlockScalars: true });
|
|
11794
11893
|
const paths = this.getSettablePaths({ global });
|
|
11795
11894
|
return new _CursorSubagent({
|
|
11796
11895
|
baseDir,
|
package/dist/index.js
CHANGED