rulesync 11.0.0 → 13.0.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 +39 -39
- package/dist/cli/index.cjs +251 -12
- package/dist/cli/index.js +251 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-AKytnIKl.js → import-CMSHVMqU.js} +1767 -469
- package/dist/import-CMSHVMqU.js.map +1 -0
- package/dist/{import-ESr9cSFw.cjs → import-nbmxtKYi.cjs} +1809 -481
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-AKytnIKl.js.map +0 -1
|
@@ -37,6 +37,7 @@ let gray_matter = require("gray-matter");
|
|
|
37
37
|
gray_matter = __toESM(gray_matter, 1);
|
|
38
38
|
let js_yaml = require("js-yaml");
|
|
39
39
|
let es_toolkit_object = require("es-toolkit/object");
|
|
40
|
+
let node_crypto = require("node:crypto");
|
|
40
41
|
let _toon_format_toon = require("@toon-format/toon");
|
|
41
42
|
//#region src/types/features.ts
|
|
42
43
|
const ALL_FEATURES = [
|
|
@@ -47,7 +48,8 @@ const ALL_FEATURES = [
|
|
|
47
48
|
"commands",
|
|
48
49
|
"skills",
|
|
49
50
|
"hooks",
|
|
50
|
-
"permissions"
|
|
51
|
+
"permissions",
|
|
52
|
+
"checks"
|
|
51
53
|
];
|
|
52
54
|
const ALL_FEATURES_WITH_WILDCARD = [...ALL_FEATURES, "*"];
|
|
53
55
|
const FeatureSchema = zod_mini.z.enum(ALL_FEATURES);
|
|
@@ -114,25 +116,26 @@ function formatError(error) {
|
|
|
114
116
|
}
|
|
115
117
|
//#endregion
|
|
116
118
|
//#region src/constants/rulesync-paths.ts
|
|
117
|
-
const { join: join$
|
|
119
|
+
const { join: join$256 } = node_path.posix;
|
|
118
120
|
const RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
|
|
119
121
|
const RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH = "rulesync.local.jsonc";
|
|
120
122
|
const RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
|
|
121
|
-
const RULESYNC_RULES_RELATIVE_DIR_PATH = join$
|
|
122
|
-
const RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join$
|
|
123
|
-
const RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join$
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const
|
|
123
|
+
const RULESYNC_RULES_RELATIVE_DIR_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "rules");
|
|
124
|
+
const RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "commands");
|
|
125
|
+
const RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "subagents");
|
|
126
|
+
const RULESYNC_CHECKS_RELATIVE_DIR_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "checks");
|
|
127
|
+
const RULESYNC_MCP_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
|
|
128
|
+
const RULESYNC_HOOKS_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "hooks.json");
|
|
129
|
+
const RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "permissions.json");
|
|
130
|
+
const RULESYNC_MCP_JSONC_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "mcp.jsonc");
|
|
131
|
+
const RULESYNC_HOOKS_JSONC_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "hooks.jsonc");
|
|
132
|
+
const RULESYNC_PERMISSIONS_JSONC_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "permissions.jsonc");
|
|
130
133
|
const RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
|
|
131
|
-
const RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join$
|
|
134
|
+
const RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
|
|
132
135
|
const RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
133
136
|
const RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
134
|
-
const RULESYNC_SKILLS_RELATIVE_DIR_PATH = join$
|
|
135
|
-
const RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = join$
|
|
137
|
+
const RULESYNC_SKILLS_RELATIVE_DIR_PATH = join$256(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
138
|
+
const RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = join$256(RULESYNC_SKILLS_RELATIVE_DIR_PATH, ".curated");
|
|
136
139
|
const RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH = "rulesync.lock";
|
|
137
140
|
const RULESYNC_MCP_FILE_NAME = "mcp.json";
|
|
138
141
|
const RULESYNC_HOOKS_FILE_NAME = "hooks.json";
|
|
@@ -289,6 +292,7 @@ const subagentsProcessorToolTargetTuple = [
|
|
|
289
292
|
"kiro-ide",
|
|
290
293
|
"opencode",
|
|
291
294
|
"qwencode",
|
|
295
|
+
"reasonix",
|
|
292
296
|
"roo",
|
|
293
297
|
"rovodev",
|
|
294
298
|
"takt",
|
|
@@ -385,6 +389,7 @@ const permissionsProcessorToolTargetTuple = [
|
|
|
385
389
|
"warp",
|
|
386
390
|
"zed"
|
|
387
391
|
];
|
|
392
|
+
const checksProcessorToolTargetTuple = ["amp"];
|
|
388
393
|
//#endregion
|
|
389
394
|
//#region src/types/tool-targets.ts
|
|
390
395
|
const ALL_TOOL_TARGETS = [...new Set([
|
|
@@ -395,7 +400,8 @@ const ALL_TOOL_TARGETS = [...new Set([
|
|
|
395
400
|
subagentsProcessorToolTargetTuple,
|
|
396
401
|
skillsProcessorToolTargetTuple,
|
|
397
402
|
hooksProcessorToolTargetTuple,
|
|
398
|
-
permissionsProcessorToolTargetTuple
|
|
403
|
+
permissionsProcessorToolTargetTuple,
|
|
404
|
+
checksProcessorToolTargetTuple
|
|
399
405
|
].flat())];
|
|
400
406
|
const ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
|
|
401
407
|
const ToolTargetSchema = zod_mini.z.enum(ALL_TOOL_TARGETS);
|
|
@@ -1469,7 +1475,7 @@ function isPlainObject$1(value) {
|
|
|
1469
1475
|
/**
|
|
1470
1476
|
* Type guard to check if a value is an array of strings.
|
|
1471
1477
|
*/
|
|
1472
|
-
function isStringArray(value) {
|
|
1478
|
+
function isStringArray$1(value) {
|
|
1473
1479
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
1474
1480
|
}
|
|
1475
1481
|
//#endregion
|
|
@@ -1717,13 +1723,17 @@ var FeatureProcessor = class {
|
|
|
1717
1723
|
}
|
|
1718
1724
|
};
|
|
1719
1725
|
//#endregion
|
|
1720
|
-
//#region src/constants/
|
|
1721
|
-
const
|
|
1722
|
-
const
|
|
1723
|
-
const
|
|
1724
|
-
const
|
|
1725
|
-
const
|
|
1726
|
-
const
|
|
1726
|
+
//#region src/constants/amp-paths.ts
|
|
1727
|
+
const AMP_DIR = ".amp";
|
|
1728
|
+
const AMP_GLOBAL_DIR = (0, node_path.join)(".config", "amp");
|
|
1729
|
+
const AMP_AGENTS_DIR = ".agents";
|
|
1730
|
+
const AMP_SKILLS_PROJECT_DIR = (0, node_path.join)(AMP_AGENTS_DIR, "skills");
|
|
1731
|
+
const AMP_SKILLS_GLOBAL_DIR = (0, node_path.join)(".config", "agents", "skills");
|
|
1732
|
+
const AMP_CHECKS_PROJECT_DIR = (0, node_path.join)(AMP_AGENTS_DIR, "checks");
|
|
1733
|
+
const AMP_CHECKS_GLOBAL_DIR = (0, node_path.join)(AMP_GLOBAL_DIR, "checks");
|
|
1734
|
+
const AMP_RULE_FILE_NAME = "AGENTS.md";
|
|
1735
|
+
const AMP_SETTINGS_FILE_NAME = "settings.json";
|
|
1736
|
+
const AMP_SETTINGS_JSONC_FILE_NAME = "settings.jsonc";
|
|
1727
1737
|
//#endregion
|
|
1728
1738
|
//#region src/types/ai-file.ts
|
|
1729
1739
|
var AiFile = class {
|
|
@@ -1797,6 +1807,414 @@ var AiFile = class {
|
|
|
1797
1807
|
}
|
|
1798
1808
|
};
|
|
1799
1809
|
//#endregion
|
|
1810
|
+
//#region src/types/rulesync-file.ts
|
|
1811
|
+
var RulesyncFile = class extends AiFile {
|
|
1812
|
+
static async fromFile(_params) {
|
|
1813
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1814
|
+
}
|
|
1815
|
+
};
|
|
1816
|
+
//#endregion
|
|
1817
|
+
//#region src/features/checks/rulesync-check.ts
|
|
1818
|
+
const RulesyncCheckFrontmatterSchema = zod_mini.z.looseObject({
|
|
1819
|
+
targets: zod_mini.z._default(RulesyncTargetsSchema, ["*"]),
|
|
1820
|
+
description: zod_mini.z.optional(zod_mini.z.string()),
|
|
1821
|
+
severity: zod_mini.z.optional(zod_mini.z.enum([
|
|
1822
|
+
"low",
|
|
1823
|
+
"medium",
|
|
1824
|
+
"high",
|
|
1825
|
+
"critical"
|
|
1826
|
+
])),
|
|
1827
|
+
tools: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string()))
|
|
1828
|
+
});
|
|
1829
|
+
var RulesyncCheck = class RulesyncCheck extends RulesyncFile {
|
|
1830
|
+
frontmatter;
|
|
1831
|
+
body;
|
|
1832
|
+
constructor({ frontmatter, body, ...rest }) {
|
|
1833
|
+
const parseResult = RulesyncCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1834
|
+
if (!parseResult.success && rest.validate !== false) throw new Error(`Invalid frontmatter in ${(0, node_path.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`);
|
|
1835
|
+
const parsedFrontmatter = parseResult.success ? {
|
|
1836
|
+
...frontmatter,
|
|
1837
|
+
...parseResult.data
|
|
1838
|
+
} : {
|
|
1839
|
+
...frontmatter,
|
|
1840
|
+
targets: frontmatter?.targets ?? ["*"]
|
|
1841
|
+
};
|
|
1842
|
+
super({
|
|
1843
|
+
...rest,
|
|
1844
|
+
fileContent: stringifyFrontmatter(body, parsedFrontmatter)
|
|
1845
|
+
});
|
|
1846
|
+
this.frontmatter = parsedFrontmatter;
|
|
1847
|
+
this.body = body;
|
|
1848
|
+
}
|
|
1849
|
+
static getSettablePaths() {
|
|
1850
|
+
return { relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH };
|
|
1851
|
+
}
|
|
1852
|
+
getFrontmatter() {
|
|
1853
|
+
return this.frontmatter;
|
|
1854
|
+
}
|
|
1855
|
+
getBody() {
|
|
1856
|
+
return this.body;
|
|
1857
|
+
}
|
|
1858
|
+
validate() {
|
|
1859
|
+
if (!this.frontmatter) return {
|
|
1860
|
+
success: true,
|
|
1861
|
+
error: null
|
|
1862
|
+
};
|
|
1863
|
+
const result = RulesyncCheckFrontmatterSchema.safeParse(this.frontmatter);
|
|
1864
|
+
if (result.success) return {
|
|
1865
|
+
success: true,
|
|
1866
|
+
error: null
|
|
1867
|
+
};
|
|
1868
|
+
else return {
|
|
1869
|
+
success: false,
|
|
1870
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${(0, node_path.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath }) {
|
|
1874
|
+
const filePath = (0, node_path.join)(outputRoot, RULESYNC_CHECKS_RELATIVE_DIR_PATH, relativeFilePath);
|
|
1875
|
+
const { frontmatter, body: content, hasFrontmatter } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
1876
|
+
if (!hasFrontmatter) throw new Error(`Missing frontmatter in ${filePath}. Rulesync files must begin with a YAML frontmatter block delimited by '---'.`);
|
|
1877
|
+
const result = RulesyncCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1878
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
1879
|
+
const filename = (0, node_path.basename)(relativeFilePath);
|
|
1880
|
+
return new RulesyncCheck({
|
|
1881
|
+
outputRoot,
|
|
1882
|
+
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
1883
|
+
relativeFilePath: filename,
|
|
1884
|
+
frontmatter: result.data,
|
|
1885
|
+
body: content.trim()
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
//#endregion
|
|
1890
|
+
//#region src/types/tool-file.ts
|
|
1891
|
+
var ToolFile = class extends AiFile {};
|
|
1892
|
+
//#endregion
|
|
1893
|
+
//#region src/features/checks/tool-check.ts
|
|
1894
|
+
var ToolCheck = class extends ToolFile {
|
|
1895
|
+
static getSettablePaths(_options = {}) {
|
|
1896
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1897
|
+
}
|
|
1898
|
+
static async fromFile(_params) {
|
|
1899
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1900
|
+
}
|
|
1901
|
+
/**
|
|
1902
|
+
* Create a minimal instance for deletion purposes.
|
|
1903
|
+
* This method does not read or parse file content, making it safe to use
|
|
1904
|
+
* even when files have old/incompatible formats.
|
|
1905
|
+
*/
|
|
1906
|
+
static forDeletion(_params) {
|
|
1907
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1908
|
+
}
|
|
1909
|
+
static fromRulesyncCheck(_params) {
|
|
1910
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1911
|
+
}
|
|
1912
|
+
static isTargetedByRulesyncCheck(_rulesyncCheck) {
|
|
1913
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1914
|
+
}
|
|
1915
|
+
static isTargetedByRulesyncCheckDefault({ rulesyncCheck, toolTarget }) {
|
|
1916
|
+
const targets = rulesyncCheck.getFrontmatter().targets;
|
|
1917
|
+
if (!targets) return true;
|
|
1918
|
+
if (targets.includes("*")) return true;
|
|
1919
|
+
if (targets.includes(toolTarget)) return true;
|
|
1920
|
+
return false;
|
|
1921
|
+
}
|
|
1922
|
+
static filterToolSpecificSection(rawSection, excludeFields) {
|
|
1923
|
+
const filtered = {};
|
|
1924
|
+
for (const [key, value] of Object.entries(rawSection)) if (!excludeFields.includes(key)) filtered[key] = value;
|
|
1925
|
+
return filtered;
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
//#endregion
|
|
1929
|
+
//#region src/features/checks/amp-check.ts
|
|
1930
|
+
const AmpCheckFrontmatterSchema = zod_mini.z.looseObject({
|
|
1931
|
+
name: zod_mini.z.string(),
|
|
1932
|
+
description: zod_mini.z.optional(zod_mini.z.string()),
|
|
1933
|
+
"severity-default": zod_mini.z.optional(zod_mini.z.enum([
|
|
1934
|
+
"low",
|
|
1935
|
+
"medium",
|
|
1936
|
+
"high",
|
|
1937
|
+
"critical"
|
|
1938
|
+
])),
|
|
1939
|
+
tools: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string()))
|
|
1940
|
+
});
|
|
1941
|
+
/**
|
|
1942
|
+
* Represents an Amp code review check.
|
|
1943
|
+
*
|
|
1944
|
+
* Amp natively reads code review checks as Markdown files with YAML frontmatter,
|
|
1945
|
+
* scoped to the project (`.agents/checks/`) and user-wide (`~/.config/amp/checks/`).
|
|
1946
|
+
* Each check runs as a per-check subagent during code review.
|
|
1947
|
+
* @see https://ampcode.com/manual
|
|
1948
|
+
*/
|
|
1949
|
+
var AmpCheck = class AmpCheck extends ToolCheck {
|
|
1950
|
+
frontmatter;
|
|
1951
|
+
body;
|
|
1952
|
+
constructor({ frontmatter, body, fileContent, ...rest }) {
|
|
1953
|
+
if (rest.validate !== false) {
|
|
1954
|
+
const result = AmpCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1955
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${(0, node_path.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
1956
|
+
}
|
|
1957
|
+
super({
|
|
1958
|
+
...rest,
|
|
1959
|
+
fileContent: fileContent ?? stringifyFrontmatter(body, frontmatter)
|
|
1960
|
+
});
|
|
1961
|
+
this.frontmatter = frontmatter;
|
|
1962
|
+
this.body = body;
|
|
1963
|
+
}
|
|
1964
|
+
static getSettablePaths({ global = false } = {}) {
|
|
1965
|
+
return { relativeDirPath: global ? AMP_CHECKS_GLOBAL_DIR : AMP_CHECKS_PROJECT_DIR };
|
|
1966
|
+
}
|
|
1967
|
+
getFrontmatter() {
|
|
1968
|
+
return this.frontmatter;
|
|
1969
|
+
}
|
|
1970
|
+
getBody() {
|
|
1971
|
+
return this.body;
|
|
1972
|
+
}
|
|
1973
|
+
toRulesyncCheck() {
|
|
1974
|
+
const { name: _name, description, "severity-default": severityDefault, tools, ...restFields } = this.frontmatter;
|
|
1975
|
+
return new RulesyncCheck({
|
|
1976
|
+
outputRoot: ".",
|
|
1977
|
+
frontmatter: {
|
|
1978
|
+
targets: ["*"],
|
|
1979
|
+
...description !== void 0 && { description },
|
|
1980
|
+
...severityDefault !== void 0 && { severity: severityDefault },
|
|
1981
|
+
...tools !== void 0 && { tools },
|
|
1982
|
+
...restFields
|
|
1983
|
+
},
|
|
1984
|
+
body: this.body,
|
|
1985
|
+
relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH,
|
|
1986
|
+
relativeFilePath: this.getRelativeFilePath(),
|
|
1987
|
+
validate: true
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
static fromRulesyncCheck({ outputRoot = process.cwd(), rulesyncCheck, validate = true, global = false }) {
|
|
1991
|
+
const rulesyncFrontmatter = rulesyncCheck.getFrontmatter();
|
|
1992
|
+
const relativeFilePath = rulesyncCheck.getRelativeFilePath();
|
|
1993
|
+
const name = (0, node_path.basename)(relativeFilePath, ".md");
|
|
1994
|
+
const { targets: _targets, description, severity, tools, ...restFields } = rulesyncFrontmatter;
|
|
1995
|
+
const toolTargetKeys = new Set(ALL_TOOL_TARGETS);
|
|
1996
|
+
const passthroughFields = Object.fromEntries(Object.entries(restFields).filter(([key]) => !toolTargetKeys.has(key) && key !== "name"));
|
|
1997
|
+
const ampSection = this.filterToolSpecificSection(rulesyncFrontmatter.amp ?? {}, ["name"]);
|
|
1998
|
+
const rawAmpFrontmatter = {
|
|
1999
|
+
name,
|
|
2000
|
+
...description !== void 0 && { description },
|
|
2001
|
+
...severity !== void 0 && { "severity-default": severity },
|
|
2002
|
+
...tools !== void 0 && { tools },
|
|
2003
|
+
...passthroughFields,
|
|
2004
|
+
...ampSection
|
|
2005
|
+
};
|
|
2006
|
+
const result = AmpCheckFrontmatterSchema.safeParse(rawAmpFrontmatter);
|
|
2007
|
+
if (!result.success) throw new Error(`Invalid amp check frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
2008
|
+
const ampFrontmatter = result.data;
|
|
2009
|
+
const body = rulesyncCheck.getBody();
|
|
2010
|
+
const fileContent = stringifyFrontmatter(body, ampFrontmatter);
|
|
2011
|
+
const paths = this.getSettablePaths({ global });
|
|
2012
|
+
return new AmpCheck({
|
|
2013
|
+
outputRoot,
|
|
2014
|
+
frontmatter: ampFrontmatter,
|
|
2015
|
+
body,
|
|
2016
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2017
|
+
relativeFilePath,
|
|
2018
|
+
fileContent,
|
|
2019
|
+
validate
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
2022
|
+
validate() {
|
|
2023
|
+
if (!this.frontmatter) return {
|
|
2024
|
+
success: true,
|
|
2025
|
+
error: null
|
|
2026
|
+
};
|
|
2027
|
+
const result = AmpCheckFrontmatterSchema.safeParse(this.frontmatter);
|
|
2028
|
+
if (result.success) return {
|
|
2029
|
+
success: true,
|
|
2030
|
+
error: null
|
|
2031
|
+
};
|
|
2032
|
+
else return {
|
|
2033
|
+
success: false,
|
|
2034
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${(0, node_path.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
static isTargetedByRulesyncCheck(rulesyncCheck) {
|
|
2038
|
+
return this.isTargetedByRulesyncCheckDefault({
|
|
2039
|
+
rulesyncCheck,
|
|
2040
|
+
toolTarget: "amp"
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
2044
|
+
const paths = this.getSettablePaths({ global });
|
|
2045
|
+
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
2046
|
+
const fileContent = await readFileContent(filePath);
|
|
2047
|
+
const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
|
|
2048
|
+
const result = AmpCheckFrontmatterSchema.safeParse(frontmatter);
|
|
2049
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
2050
|
+
return new AmpCheck({
|
|
2051
|
+
outputRoot,
|
|
2052
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2053
|
+
relativeFilePath,
|
|
2054
|
+
frontmatter: result.data,
|
|
2055
|
+
body: content.trim(),
|
|
2056
|
+
fileContent,
|
|
2057
|
+
validate
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
2061
|
+
return new AmpCheck({
|
|
2062
|
+
outputRoot,
|
|
2063
|
+
relativeDirPath,
|
|
2064
|
+
relativeFilePath,
|
|
2065
|
+
frontmatter: { name: "" },
|
|
2066
|
+
body: "",
|
|
2067
|
+
fileContent: "",
|
|
2068
|
+
validate: false
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
//#endregion
|
|
2073
|
+
//#region src/features/checks/checks-processor.ts
|
|
2074
|
+
const ChecksProcessorToolTargetSchema = zod_mini.z.enum(checksProcessorToolTargetTuple);
|
|
2075
|
+
/**
|
|
2076
|
+
* Factory Map mapping tool targets to their check factories.
|
|
2077
|
+
* Using Map to preserve insertion order for consistent iteration.
|
|
2078
|
+
*/
|
|
2079
|
+
const toolCheckFactories = /* @__PURE__ */ new Map([["amp", {
|
|
2080
|
+
class: AmpCheck,
|
|
2081
|
+
meta: {
|
|
2082
|
+
supportsGlobal: true,
|
|
2083
|
+
filePattern: "*.md"
|
|
2084
|
+
}
|
|
2085
|
+
}]]);
|
|
2086
|
+
const defaultGetFactory$6 = (target) => {
|
|
2087
|
+
const factory = toolCheckFactories.get(target);
|
|
2088
|
+
if (!factory) throw new Error(`Unsupported tool target: ${target}`);
|
|
2089
|
+
return factory;
|
|
2090
|
+
};
|
|
2091
|
+
const allToolTargetKeys$5 = [...toolCheckFactories.keys()];
|
|
2092
|
+
const checksProcessorToolTargets = allToolTargetKeys$5;
|
|
2093
|
+
const checksProcessorToolTargetsGlobal = allToolTargetKeys$5.filter((target) => {
|
|
2094
|
+
return toolCheckFactories.get(target)?.meta.supportsGlobal ?? false;
|
|
2095
|
+
});
|
|
2096
|
+
var ChecksProcessor = class extends FeatureProcessor {
|
|
2097
|
+
toolTarget;
|
|
2098
|
+
global;
|
|
2099
|
+
getFactory;
|
|
2100
|
+
constructor({ outputRoot = process.cwd(), inputRoot = process.cwd(), toolTarget, global = false, getFactory = defaultGetFactory$6, dryRun = false, logger }) {
|
|
2101
|
+
super({
|
|
2102
|
+
outputRoot,
|
|
2103
|
+
inputRoot,
|
|
2104
|
+
dryRun,
|
|
2105
|
+
logger
|
|
2106
|
+
});
|
|
2107
|
+
const result = ChecksProcessorToolTargetSchema.safeParse(toolTarget);
|
|
2108
|
+
if (!result.success) throw new Error(`Invalid tool target for ChecksProcessor: ${toolTarget}. ${formatError(result.error)}`);
|
|
2109
|
+
this.toolTarget = result.data;
|
|
2110
|
+
this.global = global;
|
|
2111
|
+
this.getFactory = getFactory;
|
|
2112
|
+
}
|
|
2113
|
+
async convertRulesyncFilesToToolFiles(rulesyncFiles) {
|
|
2114
|
+
const rulesyncChecks = rulesyncFiles.filter((file) => file instanceof RulesyncCheck);
|
|
2115
|
+
const factory = this.getFactory(this.toolTarget);
|
|
2116
|
+
return rulesyncChecks.filter((rulesyncCheck) => factory.class.isTargetedByRulesyncCheck(rulesyncCheck)).map((rulesyncCheck) => factory.class.fromRulesyncCheck({
|
|
2117
|
+
outputRoot: this.outputRoot,
|
|
2118
|
+
relativeDirPath: RulesyncCheck.getSettablePaths().relativeDirPath,
|
|
2119
|
+
rulesyncCheck,
|
|
2120
|
+
global: this.global
|
|
2121
|
+
}));
|
|
2122
|
+
}
|
|
2123
|
+
async convertToolFilesToRulesyncFiles(toolFiles) {
|
|
2124
|
+
return toolFiles.filter((file) => file instanceof ToolCheck).map((toolCheck) => toolCheck.toRulesyncCheck());
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* Implementation of abstract method from Processor
|
|
2128
|
+
* Load and parse rulesync check files from .rulesync/checks/ directory
|
|
2129
|
+
*/
|
|
2130
|
+
async loadRulesyncFiles() {
|
|
2131
|
+
const checksDir = (0, node_path.join)(this.inputRoot, RulesyncCheck.getSettablePaths().relativeDirPath);
|
|
2132
|
+
if (!await directoryExists(checksDir)) {
|
|
2133
|
+
this.logger.debug(`Rulesync checks directory not found: ${checksDir}`);
|
|
2134
|
+
return [];
|
|
2135
|
+
}
|
|
2136
|
+
const mdFiles = (await listDirectoryFiles(checksDir)).filter((file) => file.endsWith(".md"));
|
|
2137
|
+
if (mdFiles.length === 0) {
|
|
2138
|
+
this.logger.debug(`No markdown files found in rulesync checks directory: ${checksDir}`);
|
|
2139
|
+
return [];
|
|
2140
|
+
}
|
|
2141
|
+
this.logger.debug(`Found ${mdFiles.length} check files in ${checksDir}`);
|
|
2142
|
+
const rulesyncChecks = [];
|
|
2143
|
+
for (const mdFile of mdFiles) {
|
|
2144
|
+
const filepath = (0, node_path.join)(checksDir, mdFile);
|
|
2145
|
+
try {
|
|
2146
|
+
const rulesyncCheck = await RulesyncCheck.fromFile({
|
|
2147
|
+
outputRoot: this.inputRoot,
|
|
2148
|
+
relativeFilePath: mdFile,
|
|
2149
|
+
validate: true
|
|
2150
|
+
});
|
|
2151
|
+
rulesyncChecks.push(rulesyncCheck);
|
|
2152
|
+
this.logger.debug(`Successfully loaded check: ${mdFile}`);
|
|
2153
|
+
} catch (error) {
|
|
2154
|
+
this.logger.warn(`Failed to load check file ${filepath}: ${formatError(error)}`);
|
|
2155
|
+
continue;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
this.logger.debug(`Successfully loaded ${rulesyncChecks.length} rulesync checks`);
|
|
2159
|
+
return rulesyncChecks;
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Implementation of abstract method from Processor
|
|
2163
|
+
* Load tool-specific check files and parse them into ToolCheck instances
|
|
2164
|
+
*/
|
|
2165
|
+
async loadToolFiles({ forDeletion = false } = {}) {
|
|
2166
|
+
const factory = this.getFactory(this.toolTarget);
|
|
2167
|
+
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
2168
|
+
const baseDir = (0, node_path.join)(this.outputRoot, paths.relativeDirPath);
|
|
2169
|
+
const checkFilePaths = await findFilesByGlobs((0, node_path.join)(baseDir, factory.meta.filePattern));
|
|
2170
|
+
const toRelativeFilePath = (path) => (0, node_path.relative)(baseDir, path);
|
|
2171
|
+
if (forDeletion) return checkFilePaths.map((path) => factory.class.forDeletion({
|
|
2172
|
+
outputRoot: this.outputRoot,
|
|
2173
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2174
|
+
relativeFilePath: toRelativeFilePath(path),
|
|
2175
|
+
global: this.global
|
|
2176
|
+
})).filter((check) => check.isDeletable());
|
|
2177
|
+
const loaded = await Promise.all(checkFilePaths.map((path) => factory.class.fromFile({
|
|
2178
|
+
outputRoot: this.outputRoot,
|
|
2179
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2180
|
+
relativeFilePath: toRelativeFilePath(path),
|
|
2181
|
+
global: this.global
|
|
2182
|
+
})));
|
|
2183
|
+
this.logger.debug(`Successfully loaded ${loaded.length} ${this.toolTarget} checks from ${paths.relativeDirPath}`);
|
|
2184
|
+
return loaded;
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Implementation of abstract method from FeatureProcessor
|
|
2188
|
+
* Return the tool targets that this processor supports
|
|
2189
|
+
*/
|
|
2190
|
+
static getToolTargets({ global = false } = {}) {
|
|
2191
|
+
if (global) return [...checksProcessorToolTargetsGlobal];
|
|
2192
|
+
return [...checksProcessorToolTargets];
|
|
2193
|
+
}
|
|
2194
|
+
static getToolTargetsSimulated() {
|
|
2195
|
+
return [];
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Get the factory for a specific tool target.
|
|
2199
|
+
* This is a static version of the internal getFactory for external use.
|
|
2200
|
+
* @param target - The tool target. Must be a valid ChecksProcessorToolTarget.
|
|
2201
|
+
* @returns The factory for the target, or undefined if not found.
|
|
2202
|
+
*/
|
|
2203
|
+
static getFactory(target) {
|
|
2204
|
+
const result = ChecksProcessorToolTargetSchema.safeParse(target);
|
|
2205
|
+
if (!result.success) return;
|
|
2206
|
+
return toolCheckFactories.get(result.data);
|
|
2207
|
+
}
|
|
2208
|
+
};
|
|
2209
|
+
//#endregion
|
|
2210
|
+
//#region src/constants/agentsmd-paths.ts
|
|
2211
|
+
const AGENTSMD_DIR = ".agents";
|
|
2212
|
+
const AGENTSMD_MEMORIES_DIR_PATH = (0, node_path.join)(AGENTSMD_DIR, "memories");
|
|
2213
|
+
const AGENTSMD_COMMANDS_DIR_PATH = (0, node_path.join)(AGENTSMD_DIR, "commands");
|
|
2214
|
+
const AGENTSMD_SKILLS_DIR_PATH = (0, node_path.join)(AGENTSMD_DIR, "skills");
|
|
2215
|
+
const AGENTSMD_SUBAGENTS_DIR_PATH = (0, node_path.join)(AGENTSMD_DIR, "subagents");
|
|
2216
|
+
const AGENTSMD_RULE_FILE_NAME = "AGENTS.md";
|
|
2217
|
+
//#endregion
|
|
1800
2218
|
//#region src/features/commands/tool-command.ts
|
|
1801
2219
|
/**
|
|
1802
2220
|
* Abstract base class for AI development tool-specific command formats.
|
|
@@ -2044,13 +2462,6 @@ const AntigravityCommandFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
2044
2462
|
...AntigravityWorkflowFrontmatterSchema.shape
|
|
2045
2463
|
});
|
|
2046
2464
|
//#endregion
|
|
2047
|
-
//#region src/types/rulesync-file.ts
|
|
2048
|
-
var RulesyncFile = class extends AiFile {
|
|
2049
|
-
static async fromFile(_params) {
|
|
2050
|
-
throw new Error("Please implement this method in the subclass.");
|
|
2051
|
-
}
|
|
2052
|
-
};
|
|
2053
|
-
//#endregion
|
|
2054
2465
|
//#region src/features/commands/rulesync-command.ts
|
|
2055
2466
|
const RulesyncCommandFrontmatterSchema = zod_mini.z.looseObject({
|
|
2056
2467
|
targets: zod_mini.z._default(RulesyncTargetsSchema, ["*"]),
|
|
@@ -3111,135 +3522,118 @@ var CursorCommand = class CursorCommand extends ToolCommand {
|
|
|
3111
3522
|
//#endregion
|
|
3112
3523
|
//#region src/constants/devin-paths.ts
|
|
3113
3524
|
const DEVIN_DIR = ".devin";
|
|
3114
|
-
const CODEIUM_WINDSURF_DIR = (0, node_path.join)(".codeium", "windsurf");
|
|
3115
|
-
const DEVIN_WORKFLOWS_DIR_PATH = (0, node_path.join)(DEVIN_DIR, "workflows");
|
|
3116
3525
|
const DEVIN_SKILLS_DIR_PATH = (0, node_path.join)(DEVIN_DIR, "skills");
|
|
3117
3526
|
const DEVIN_AGENTS_DIR_PATH = (0, node_path.join)(DEVIN_DIR, "agents");
|
|
3118
3527
|
const DEVIN_GLOBAL_CONFIG_DIR_PATH = (0, node_path.join)(".config", "devin");
|
|
3119
3528
|
const DEVIN_GLOBAL_AGENTS_DIR_PATH = (0, node_path.join)(DEVIN_GLOBAL_CONFIG_DIR_PATH, "agents");
|
|
3120
3529
|
const DEVIN_GLOBAL_SKILLS_DIR_PATH = (0, node_path.join)(DEVIN_GLOBAL_CONFIG_DIR_PATH, "skills");
|
|
3121
|
-
const CODEIUM_WINDSURF_GLOBAL_WORKFLOWS_DIR_PATH = (0, node_path.join)(CODEIUM_WINDSURF_DIR, "global_workflows");
|
|
3122
3530
|
const DEVIN_CONFIG_FILE_NAME = "config.json";
|
|
3123
3531
|
const DEVIN_HOOKS_V1_FILE_NAME = "hooks.v1.json";
|
|
3124
3532
|
const DEVIN_GLOBAL_AGENTS_FILE_NAME = "AGENTS.md";
|
|
3125
3533
|
const DEVIN_IGNORE_FILE_NAME = ".devinignore";
|
|
3126
3534
|
const DEVIN_LEGACY_IGNORE_FILE_NAME = ".codeiumignore";
|
|
3127
3535
|
//#endregion
|
|
3536
|
+
//#region src/constants/general.ts
|
|
3537
|
+
const SKILL_FILE_NAME$1 = "SKILL.md";
|
|
3538
|
+
//#endregion
|
|
3539
|
+
//#region src/features/commands/command-skill-ownership.ts
|
|
3540
|
+
/**
|
|
3541
|
+
* Slug used for the per-command `<slug>/SKILL.md` directory when a tool's
|
|
3542
|
+
* commands are emitted onto its skills surface (Devin, Hermes Agent).
|
|
3543
|
+
*/
|
|
3544
|
+
function commandSlug(relativeFilePath) {
|
|
3545
|
+
return (0, node_path.basename)(relativeFilePath, ".md").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
3546
|
+
}
|
|
3547
|
+
/**
|
|
3548
|
+
* Whether a rulesync command exists whose slug matches `dirName`.
|
|
3549
|
+
*
|
|
3550
|
+
* Used by the skills-surface `isDirOwned` hooks of tools whose commands are
|
|
3551
|
+
* emitted as `<slug>/SKILL.md` into the skills tree: a directory matching a
|
|
3552
|
+
* current command slug is owned by the commands feature, so the skills
|
|
3553
|
+
* feature must neither import it as a skill nor delete it as an orphan
|
|
3554
|
+
* skill. Once the command is removed from `.rulesync/commands/`, the
|
|
3555
|
+
* directory stops matching and the skills feature cleans it up as a regular
|
|
3556
|
+
* orphan.
|
|
3557
|
+
*/
|
|
3558
|
+
async function rulesyncCommandSlugExists({ inputRoot, dirName }) {
|
|
3559
|
+
return (await findFilesByGlobs((0, node_path.join)(inputRoot, RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "**", "*.md"))).some((filePath) => commandSlug((0, node_path.basename)(filePath)) === dirName);
|
|
3560
|
+
}
|
|
3561
|
+
//#endregion
|
|
3128
3562
|
//#region src/features/commands/devin-command.ts
|
|
3129
|
-
|
|
3563
|
+
function commandSkillContent$1(rulesyncCommand) {
|
|
3564
|
+
const slug = commandSlug(rulesyncCommand.getRelativeFilePath());
|
|
3565
|
+
const description = rulesyncCommand.getFrontmatter().description ?? `${slug} command`;
|
|
3566
|
+
return stringifyFrontmatter(rulesyncCommand.getBody().trim(), {
|
|
3567
|
+
name: slug,
|
|
3568
|
+
description
|
|
3569
|
+
});
|
|
3570
|
+
}
|
|
3130
3571
|
/**
|
|
3131
|
-
* Represents a Devin
|
|
3132
|
-
*
|
|
3133
|
-
*
|
|
3134
|
-
*
|
|
3135
|
-
*
|
|
3572
|
+
* Represents a Devin slash command, emitted as a Devin Skill.
|
|
3573
|
+
*
|
|
3574
|
+
* Devin's extensibility docs no longer document a standalone
|
|
3575
|
+
* workflows/commands component — reusable prompts invoked as slash commands
|
|
3576
|
+
* are Skills (`/name`). Commands are therefore emitted onto the native skills
|
|
3577
|
+
* surface, one `SKILL.md` per command: `.devin/skills/<slug>/SKILL.md`
|
|
3578
|
+
* (project) and `~/.config/devin/skills/<slug>/SKILL.md` (global). The legacy
|
|
3579
|
+
* Windsurf/Cascade-era `.devin/workflows/` and
|
|
3580
|
+
* `~/.codeium/windsurf/global_workflows/` locations are no longer emitted.
|
|
3581
|
+
*
|
|
3582
|
+
* Import and deletion are intentionally no-ops for this target: the skills
|
|
3583
|
+
* feature owns the `.devin/skills/` tree, so importing it as commands would
|
|
3584
|
+
* double-import every skill (mirrors the Hermes Agent commands target).
|
|
3585
|
+
*
|
|
3586
|
+
* @see https://docs.devin.ai/cli/extensibility
|
|
3587
|
+
* @see https://docs.devin.ai/cli/extensibility/skills/overview
|
|
3136
3588
|
*/
|
|
3137
3589
|
var DevinCommand = class DevinCommand extends ToolCommand {
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
const result = DevinCommandFrontmatterSchema.safeParse(frontmatter);
|
|
3143
|
-
if (!result.success) throw new Error(`Invalid frontmatter in ${(0, node_path.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
3144
|
-
}
|
|
3145
|
-
super({
|
|
3146
|
-
...rest,
|
|
3147
|
-
fileContent: stringifyFrontmatter(body, frontmatter)
|
|
3590
|
+
static isTargetedByRulesyncCommand(rulesyncCommand) {
|
|
3591
|
+
return this.isTargetedByRulesyncCommandDefault({
|
|
3592
|
+
rulesyncCommand,
|
|
3593
|
+
toolTarget: "devin"
|
|
3148
3594
|
});
|
|
3149
|
-
this.frontmatter = frontmatter;
|
|
3150
|
-
this.body = body;
|
|
3151
3595
|
}
|
|
3152
3596
|
static getSettablePaths({ global = false } = {}) {
|
|
3153
|
-
|
|
3154
|
-
return { relativeDirPath: DEVIN_WORKFLOWS_DIR_PATH };
|
|
3155
|
-
}
|
|
3156
|
-
getBody() {
|
|
3157
|
-
return this.body;
|
|
3158
|
-
}
|
|
3159
|
-
getFrontmatter() {
|
|
3160
|
-
return this.frontmatter;
|
|
3597
|
+
return { relativeDirPath: global ? DEVIN_GLOBAL_SKILLS_DIR_PATH : DEVIN_SKILLS_DIR_PATH };
|
|
3161
3598
|
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
|
|
3170
|
-
return new RulesyncCommand({
|
|
3171
|
-
outputRoot: process.cwd(),
|
|
3172
|
-
frontmatter: rulesyncFrontmatter,
|
|
3173
|
-
body: this.body,
|
|
3174
|
-
relativeDirPath: RulesyncCommand.getSettablePaths().relativeDirPath,
|
|
3175
|
-
relativeFilePath: this.relativeFilePath,
|
|
3176
|
-
fileContent,
|
|
3177
|
-
validate: true
|
|
3178
|
-
});
|
|
3179
|
-
}
|
|
3180
|
-
static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
|
|
3181
|
-
const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
|
|
3182
|
-
const devinFields = rulesyncFrontmatter.devin ?? {};
|
|
3183
|
-
const devinFrontmatter = {
|
|
3184
|
-
description: rulesyncFrontmatter.description,
|
|
3185
|
-
...devinFields
|
|
3186
|
-
};
|
|
3187
|
-
const body = rulesyncCommand.getBody();
|
|
3188
|
-
const paths = this.getSettablePaths({ global });
|
|
3189
|
-
return new DevinCommand({
|
|
3190
|
-
outputRoot,
|
|
3191
|
-
frontmatter: devinFrontmatter,
|
|
3192
|
-
body,
|
|
3193
|
-
relativeDirPath: paths.relativeDirPath,
|
|
3194
|
-
relativeFilePath: rulesyncCommand.getRelativeFilePath(),
|
|
3195
|
-
validate
|
|
3599
|
+
constructor({ slug, ...params }) {
|
|
3600
|
+
super({
|
|
3601
|
+
...params,
|
|
3602
|
+
...slug !== void 0 && {
|
|
3603
|
+
relativeDirPath: (0, node_path.join)(params.relativeDirPath, slug),
|
|
3604
|
+
relativeFilePath: "SKILL.md"
|
|
3605
|
+
}
|
|
3196
3606
|
});
|
|
3197
3607
|
}
|
|
3198
3608
|
validate() {
|
|
3199
|
-
|
|
3200
|
-
success: true,
|
|
3201
|
-
error: null
|
|
3202
|
-
};
|
|
3203
|
-
const result = DevinCommandFrontmatterSchema.safeParse(this.frontmatter);
|
|
3204
|
-
if (result.success) return {
|
|
3609
|
+
return {
|
|
3205
3610
|
success: true,
|
|
3206
3611
|
error: null
|
|
3207
3612
|
};
|
|
3208
|
-
else return {
|
|
3209
|
-
success: false,
|
|
3210
|
-
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${(0, node_path.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
3211
|
-
};
|
|
3212
3613
|
}
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3614
|
+
toRulesyncCommand() {
|
|
3615
|
+
const slug = (0, node_path.basename)((0, node_path.dirname)(this.getRelativePathFromCwd()));
|
|
3616
|
+
const { frontmatter, body } = parseFrontmatter(this.getFileContent(), this.getFilePath());
|
|
3617
|
+
const description = typeof frontmatter.description === "string" ? frontmatter.description : void 0;
|
|
3618
|
+
return new RulesyncCommand({
|
|
3619
|
+
relativeDirPath: RULESYNC_COMMANDS_RELATIVE_DIR_PATH,
|
|
3620
|
+
relativeFilePath: `${slug}.md`,
|
|
3621
|
+
frontmatter: { description },
|
|
3622
|
+
body: body.trimStart()
|
|
3217
3623
|
});
|
|
3218
3624
|
}
|
|
3219
|
-
static
|
|
3220
|
-
const paths =
|
|
3221
|
-
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
3222
|
-
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
3223
|
-
const result = DevinCommandFrontmatterSchema.safeParse(frontmatter);
|
|
3224
|
-
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
3625
|
+
static fromRulesyncCommand({ outputRoot, rulesyncCommand, global = false }) {
|
|
3626
|
+
const paths = DevinCommand.getSettablePaths({ global });
|
|
3225
3627
|
return new DevinCommand({
|
|
3226
3628
|
outputRoot,
|
|
3227
3629
|
relativeDirPath: paths.relativeDirPath,
|
|
3228
|
-
relativeFilePath,
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
validate
|
|
3630
|
+
relativeFilePath: SKILL_FILE_NAME$1,
|
|
3631
|
+
slug: commandSlug(rulesyncCommand.getRelativeFilePath()),
|
|
3632
|
+
fileContent: commandSkillContent$1(rulesyncCommand)
|
|
3232
3633
|
});
|
|
3233
3634
|
}
|
|
3234
|
-
|
|
3235
|
-
return
|
|
3236
|
-
outputRoot,
|
|
3237
|
-
relativeDirPath,
|
|
3238
|
-
relativeFilePath,
|
|
3239
|
-
frontmatter: { description: "" },
|
|
3240
|
-
body: "",
|
|
3241
|
-
validate: false
|
|
3242
|
-
});
|
|
3635
|
+
getFileContent() {
|
|
3636
|
+
return this.fileContent;
|
|
3243
3637
|
}
|
|
3244
3638
|
};
|
|
3245
3639
|
//#endregion
|
|
@@ -3568,10 +3962,7 @@ const HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_MANIFEST_PATH = (0, node_path.join)(
|
|
|
3568
3962
|
const HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_INIT_PATH = (0, node_path.join)(HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_DIR_PATH, "__init__.py");
|
|
3569
3963
|
//#endregion
|
|
3570
3964
|
//#region src/features/commands/hermesagent-command.ts
|
|
3571
|
-
const SKILL_FILE_NAME
|
|
3572
|
-
function commandSlug(relativeFilePath) {
|
|
3573
|
-
return (0, node_path.basename)(relativeFilePath, ".md").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
3574
|
-
}
|
|
3965
|
+
const SKILL_FILE_NAME = "SKILL.md";
|
|
3575
3966
|
function commandSkillContent(rulesyncCommand) {
|
|
3576
3967
|
const slug = commandSlug(rulesyncCommand.getRelativeFilePath());
|
|
3577
3968
|
const description = rulesyncCommand.getFrontmatter().description ?? `${slug} command`;
|
|
@@ -3588,7 +3979,7 @@ var HermesagentCommand = class HermesagentCommand extends ToolCommand {
|
|
|
3588
3979
|
static getSettablePaths({ slug = "command" } = {}) {
|
|
3589
3980
|
return {
|
|
3590
3981
|
relativeDirPath: (0, node_path.join)(HERMESAGENT_SKILLS_DIR_PATH, slug),
|
|
3591
|
-
relativeFilePath: SKILL_FILE_NAME
|
|
3982
|
+
relativeFilePath: SKILL_FILE_NAME
|
|
3592
3983
|
};
|
|
3593
3984
|
}
|
|
3594
3985
|
constructor({ slug, ...params }) {
|
|
@@ -3619,7 +4010,7 @@ var HermesagentCommand = class HermesagentCommand extends ToolCommand {
|
|
|
3619
4010
|
return new HermesagentCommand({
|
|
3620
4011
|
outputRoot,
|
|
3621
4012
|
relativeDirPath: "",
|
|
3622
|
-
relativeFilePath: SKILL_FILE_NAME
|
|
4013
|
+
relativeFilePath: SKILL_FILE_NAME,
|
|
3623
4014
|
slug: commandSlug(rulesyncCommand.getRelativeFilePath()),
|
|
3624
4015
|
fileContent: commandSkillContent(rulesyncCommand)
|
|
3625
4016
|
});
|
|
@@ -4854,6 +5245,7 @@ const PI_AGENT_SKILLS_DIR_PATH = (0, node_path.join)(PI_AGENT_DIR, "skills");
|
|
|
4854
5245
|
const PI_PROMPTS_DIR_PATH = (0, node_path.join)(".pi", "prompts");
|
|
4855
5246
|
const PI_SKILLS_DIR_PATH = (0, node_path.join)(".pi", "skills");
|
|
4856
5247
|
const PI_RULE_FILE_NAME = "AGENTS.md";
|
|
5248
|
+
const PI_APPEND_SYSTEM_FILE_NAME = "APPEND_SYSTEM.md";
|
|
4857
5249
|
//#endregion
|
|
4858
5250
|
//#region src/features/commands/pi-command.ts
|
|
4859
5251
|
/**
|
|
@@ -5118,6 +5510,9 @@ const REASONIX_SETTINGS_FILE_NAME = "settings.json";
|
|
|
5118
5510
|
const REASONIX_COMMANDS_DIR_PATH = (0, node_path.join)(REASONIX_DIR, "commands");
|
|
5119
5511
|
const REASONIX_RULE_FILE_NAME = "REASONIX.md";
|
|
5120
5512
|
const REASONIX_SKILLS_DIR_PATH = (0, node_path.join)(REASONIX_DIR, "skills");
|
|
5513
|
+
const REASONIX_SUBAGENTS_DIR_PATH = REASONIX_SKILLS_DIR_PATH;
|
|
5514
|
+
const REASONIX_SUBAGENT_INVOCATION = "manual";
|
|
5515
|
+
const REASONIX_SUBAGENT_RUN_AS = "subagent";
|
|
5121
5516
|
//#endregion
|
|
5122
5517
|
//#region src/features/commands/reasonix-command.ts
|
|
5123
5518
|
/**
|
|
@@ -5385,9 +5780,6 @@ const ROVODEV_AGENTS_SKILLS_DIR_PATH = (0, node_path.join)(".agents", "skills");
|
|
|
5385
5780
|
const ROVODEV_PROMPTS_FILE_NAME = "prompts.yml";
|
|
5386
5781
|
const ROVODEV_PROMPTS_DIR_PATH = (0, node_path.join)(ROVODEV_DIR, "prompts");
|
|
5387
5782
|
//#endregion
|
|
5388
|
-
//#region src/types/tool-file.ts
|
|
5389
|
-
var ToolFile = class extends AiFile {};
|
|
5390
|
-
//#endregion
|
|
5391
5783
|
//#region src/features/commands/rovodev-command.ts
|
|
5392
5784
|
/**
|
|
5393
5785
|
* Rovo Dev CLI "saved prompts": a file-based custom-command surface made of a
|
|
@@ -5876,7 +6268,8 @@ const toolCommandFactories = /* @__PURE__ */ new Map([
|
|
|
5876
6268
|
supportsProject: false,
|
|
5877
6269
|
supportsGlobal: true,
|
|
5878
6270
|
isSimulated: false,
|
|
5879
|
-
supportsSubdirectory: true
|
|
6271
|
+
supportsSubdirectory: true,
|
|
6272
|
+
skipToolFileScan: true
|
|
5880
6273
|
}
|
|
5881
6274
|
}],
|
|
5882
6275
|
["junie", {
|
|
@@ -6006,7 +6399,8 @@ const toolCommandFactories = /* @__PURE__ */ new Map([
|
|
|
6006
6399
|
supportsProject: true,
|
|
6007
6400
|
supportsGlobal: true,
|
|
6008
6401
|
isSimulated: false,
|
|
6009
|
-
supportsSubdirectory: false
|
|
6402
|
+
supportsSubdirectory: false,
|
|
6403
|
+
skipToolFileScan: true
|
|
6010
6404
|
}
|
|
6011
6405
|
}]
|
|
6012
6406
|
]);
|
|
@@ -6109,6 +6503,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
6109
6503
|
*/
|
|
6110
6504
|
async loadToolFiles({ forDeletion = false } = {}) {
|
|
6111
6505
|
const factory = this.getFactory(this.toolTarget);
|
|
6506
|
+
if (factory.meta.skipToolFileScan) return [];
|
|
6112
6507
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
6113
6508
|
const outputRootFull = (0, node_path.join)(this.outputRoot, paths.relativeDirPath);
|
|
6114
6509
|
const commandFilePaths = await findFilesByGlobs(factory.meta.supportsSubdirectory ? (0, node_path.join)(outputRootFull, "**", `*.${factory.meta.extension}`) : (0, node_path.join)(outputRootFull, `*.${factory.meta.extension}`));
|
|
@@ -6218,7 +6613,10 @@ const HookDefinitionSchema = zod_mini.z.looseObject({
|
|
|
6218
6613
|
type: zod_mini.z.optional(zod_mini.z.enum([
|
|
6219
6614
|
"command",
|
|
6220
6615
|
"prompt",
|
|
6221
|
-
"http"
|
|
6616
|
+
"http",
|
|
6617
|
+
"agent",
|
|
6618
|
+
"mcp_tool",
|
|
6619
|
+
"function"
|
|
6222
6620
|
])),
|
|
6223
6621
|
url: zod_mini.z.optional(safeString),
|
|
6224
6622
|
timeout: zod_mini.z.optional(zod_mini.z.number()),
|
|
@@ -6231,12 +6629,71 @@ const HookDefinitionSchema = zod_mini.z.looseObject({
|
|
|
6231
6629
|
sequential: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
6232
6630
|
async: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
6233
6631
|
env: zod_mini.z.optional(zod_mini.z.record(zod_mini.z.string(), safeString)),
|
|
6234
|
-
shell: zod_mini.z.optional(
|
|
6632
|
+
shell: zod_mini.z.optional(zod_mini.z.enum(["bash", "powershell"])),
|
|
6235
6633
|
statusMessage: zod_mini.z.optional(safeString),
|
|
6236
6634
|
headers: zod_mini.z.optional(zod_mini.z.record(zod_mini.z.string(), safeString)),
|
|
6237
6635
|
allowedEnvVars: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())),
|
|
6238
|
-
once: zod_mini.z.optional(zod_mini.z.boolean())
|
|
6636
|
+
once: zod_mini.z.optional(zod_mini.z.boolean()),
|
|
6637
|
+
server: zod_mini.z.optional(safeString),
|
|
6638
|
+
tool: zod_mini.z.optional(safeString),
|
|
6639
|
+
input: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
6640
|
+
model: zod_mini.z.optional(safeString)
|
|
6239
6641
|
});
|
|
6642
|
+
/**
|
|
6643
|
+
* All canonical hook event names.
|
|
6644
|
+
* Each tool supports a subset of these events.
|
|
6645
|
+
*/
|
|
6646
|
+
const HOOK_EVENTS = [
|
|
6647
|
+
"sessionStart",
|
|
6648
|
+
"sessionEnd",
|
|
6649
|
+
"preToolUse",
|
|
6650
|
+
"postToolUse",
|
|
6651
|
+
"preModelInvocation",
|
|
6652
|
+
"postModelInvocation",
|
|
6653
|
+
"beforeSubmitPrompt",
|
|
6654
|
+
"stop",
|
|
6655
|
+
"subagentStop",
|
|
6656
|
+
"preCompact",
|
|
6657
|
+
"postCompact",
|
|
6658
|
+
"contextOffload",
|
|
6659
|
+
"postToolUseFailure",
|
|
6660
|
+
"subagentStart",
|
|
6661
|
+
"beforeShellExecution",
|
|
6662
|
+
"afterShellExecution",
|
|
6663
|
+
"beforeMCPExecution",
|
|
6664
|
+
"afterMCPExecution",
|
|
6665
|
+
"beforeReadFile",
|
|
6666
|
+
"afterFileEdit",
|
|
6667
|
+
"beforeAgentResponse",
|
|
6668
|
+
"afterAgentResponse",
|
|
6669
|
+
"afterAgentThought",
|
|
6670
|
+
"beforeTabFileRead",
|
|
6671
|
+
"afterTabFileEdit",
|
|
6672
|
+
"permissionRequest",
|
|
6673
|
+
"notification",
|
|
6674
|
+
"setup",
|
|
6675
|
+
"afterError",
|
|
6676
|
+
"beforeToolSelection",
|
|
6677
|
+
"worktreeCreate",
|
|
6678
|
+
"worktreeRemove",
|
|
6679
|
+
"workspaceOpen",
|
|
6680
|
+
"messageDisplay",
|
|
6681
|
+
"todoCreated",
|
|
6682
|
+
"todoCompleted",
|
|
6683
|
+
"stopFailure",
|
|
6684
|
+
"instructionsLoaded",
|
|
6685
|
+
"userPromptExpansion",
|
|
6686
|
+
"postToolBatch",
|
|
6687
|
+
"permissionDenied",
|
|
6688
|
+
"taskCreated",
|
|
6689
|
+
"taskCompleted",
|
|
6690
|
+
"teammateIdle",
|
|
6691
|
+
"configChange",
|
|
6692
|
+
"cwdChanged",
|
|
6693
|
+
"fileChanged",
|
|
6694
|
+
"elicitation",
|
|
6695
|
+
"elicitationResult"
|
|
6696
|
+
];
|
|
6240
6697
|
/** Hook events supported by Cursor. */
|
|
6241
6698
|
const CURSOR_HOOK_EVENTS = [
|
|
6242
6699
|
"sessionStart",
|
|
@@ -6711,12 +7168,28 @@ const CANONICAL_TO_HERMESAGENT_EVENT_NAMES = {
|
|
|
6711
7168
|
*/
|
|
6712
7169
|
const HERMESAGENT_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_HERMESAGENT_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
6713
7170
|
const hooksRecordSchema = zod_mini.z.record(zod_mini.z.string(), zod_mini.z.array(HookDefinitionSchema));
|
|
7171
|
+
const HOOK_EVENT_SET = new Set(HOOK_EVENTS);
|
|
7172
|
+
/** Whether `value` is a canonical hook event name. */
|
|
7173
|
+
const isHookEvent = (value) => HOOK_EVENT_SET.has(value);
|
|
7174
|
+
/**
|
|
7175
|
+
* Top-level `hooks` record whose keys must be canonical event names, so typos
|
|
7176
|
+
* are rejected at parse time. Keys are validated with a refinement (instead of
|
|
7177
|
+
* an enum key schema) to keep the inferred type a plain string record.
|
|
7178
|
+
*
|
|
7179
|
+
* The per-tool override blocks below deliberately keep the lenient
|
|
7180
|
+
* `hooksRecordSchema`: some are documented to pass tool-native event keys
|
|
7181
|
+
* through verbatim (e.g. kiro-ide's IDE-only `PostFileSave`/`PreTaskExec`
|
|
7182
|
+
* triggers), which the canonical enum would reject.
|
|
7183
|
+
*/
|
|
7184
|
+
const canonicalHooksRecordSchema = zod_mini.z.record(zod_mini.z.string(), zod_mini.z.array(HookDefinitionSchema)).check(zod_mini.z.refine((record) => Object.keys(record).every((key) => HOOK_EVENT_SET.has(key)), { error: (issue) => {
|
|
7185
|
+
return `unknown hook event name(s): ${Object.keys(issue.input ?? {}).filter((key) => !HOOK_EVENT_SET.has(key)).join(", ")}`;
|
|
7186
|
+
} }));
|
|
6714
7187
|
/**
|
|
6715
7188
|
* Canonical hooks config (canonical event names in camelCase).
|
|
6716
7189
|
*/
|
|
6717
7190
|
const HooksConfigSchema = zod_mini.z.looseObject({
|
|
6718
7191
|
version: zod_mini.z.optional(zod_mini.z.number()),
|
|
6719
|
-
hooks:
|
|
7192
|
+
hooks: canonicalHooksRecordSchema,
|
|
6720
7193
|
cursor: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6721
7194
|
claudecode: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
6722
7195
|
copilot: zod_mini.z.optional(zod_mini.z.looseObject({ hooks: zod_mini.z.optional(hooksRecordSchema) })),
|
|
@@ -7153,6 +7626,20 @@ const CANONICAL_TO_GROKCLI_EVENT_NAMES = {
|
|
|
7153
7626
|
*/
|
|
7154
7627
|
const GROKCLI_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_GROKCLI_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
7155
7628
|
//#endregion
|
|
7629
|
+
//#region src/utils/object.ts
|
|
7630
|
+
/**
|
|
7631
|
+
* Return a shallow copy of `obj` keeping only the entries whose value is
|
|
7632
|
+
* neither `undefined` nor `null`.
|
|
7633
|
+
*
|
|
7634
|
+
* Used to assemble generated config objects without one conditional spread per
|
|
7635
|
+
* optional field (which would otherwise exceed the lint complexity budget).
|
|
7636
|
+
*/
|
|
7637
|
+
function compact(obj) {
|
|
7638
|
+
const result = {};
|
|
7639
|
+
for (const [key, value] of Object.entries(obj)) if (value !== void 0 && value !== null) result[key] = value;
|
|
7640
|
+
return result;
|
|
7641
|
+
}
|
|
7642
|
+
//#endregion
|
|
7156
7643
|
//#region src/features/hooks/tool-hooks-converter.ts
|
|
7157
7644
|
function isToolMatcherEntry(x) {
|
|
7158
7645
|
if (x === null || typeof x !== "object") return false;
|
|
@@ -7210,6 +7697,25 @@ function importBooleanPassthroughFields({ h, converterConfig }) {
|
|
|
7210
7697
|
return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ tool }) => typeof h[tool] === "boolean").map(({ canonical, tool }) => [canonical, h[tool]]));
|
|
7211
7698
|
}
|
|
7212
7699
|
/**
|
|
7700
|
+
* Emit the payload fields specific to a hook type — `url`/`headers`/
|
|
7701
|
+
* `allowedEnvVars` for http, `server`/`tool`/`input` for mcp_tool, `model`
|
|
7702
|
+
* for prompt/agent. https://code.claude.com/docs/en/hooks
|
|
7703
|
+
*/
|
|
7704
|
+
function emitTypePayloadFields({ def, hookType, converterConfig }) {
|
|
7705
|
+
if (hookType === "http") return compact({
|
|
7706
|
+
url: def.url,
|
|
7707
|
+
headers: def.headers,
|
|
7708
|
+
allowedEnvVars: def.allowedEnvVars
|
|
7709
|
+
});
|
|
7710
|
+
if (hookType === "mcp_tool") return compact({
|
|
7711
|
+
server: def.server,
|
|
7712
|
+
tool: def.tool,
|
|
7713
|
+
input: def.input
|
|
7714
|
+
});
|
|
7715
|
+
if ((hookType === "prompt" || hookType === "agent") && converterConfig.emitsPromptModel) return compact({ model: def.model });
|
|
7716
|
+
return {};
|
|
7717
|
+
}
|
|
7718
|
+
/**
|
|
7213
7719
|
* Convert the definitions of a single matcher group into tool hook entries,
|
|
7214
7720
|
* honoring supported hook types and passthrough fields.
|
|
7215
7721
|
*/
|
|
@@ -7231,6 +7737,11 @@ function buildToolHooks({ defs, converterConfig }) {
|
|
|
7231
7737
|
...command !== void 0 && command !== null && { command },
|
|
7232
7738
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
|
|
7233
7739
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt },
|
|
7740
|
+
...emitTypePayloadFields({
|
|
7741
|
+
def,
|
|
7742
|
+
hookType,
|
|
7743
|
+
converterConfig
|
|
7744
|
+
}),
|
|
7234
7745
|
...converterConfig.passthroughFields?.includes("name") && def.name !== void 0 && def.name !== null && { name: def.name },
|
|
7235
7746
|
...converterConfig.passthroughFields?.includes("description") && def.description !== void 0 && def.description !== null && { description: def.description }
|
|
7236
7747
|
});
|
|
@@ -7297,6 +7808,46 @@ function stripCommandPrefix({ command, converterConfig }) {
|
|
|
7297
7808
|
return cmd;
|
|
7298
7809
|
}
|
|
7299
7810
|
/**
|
|
7811
|
+
* Hook types preserved verbatim on import — Claude Code's five documented
|
|
7812
|
+
* handler types. Anything else is coerced to `command` as before.
|
|
7813
|
+
* https://code.claude.com/docs/en/hooks
|
|
7814
|
+
*/
|
|
7815
|
+
const IMPORTED_HOOK_TYPES = /* @__PURE__ */ new Set([
|
|
7816
|
+
"command",
|
|
7817
|
+
"prompt",
|
|
7818
|
+
"http",
|
|
7819
|
+
"mcp_tool",
|
|
7820
|
+
"agent"
|
|
7821
|
+
]);
|
|
7822
|
+
function isImportedHookType(value) {
|
|
7823
|
+
return typeof value === "string" && IMPORTED_HOOK_TYPES.has(value);
|
|
7824
|
+
}
|
|
7825
|
+
function isStringRecord(value) {
|
|
7826
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
7827
|
+
return Object.values(value).every((v) => typeof v === "string");
|
|
7828
|
+
}
|
|
7829
|
+
function isStringArray(value) {
|
|
7830
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
7831
|
+
}
|
|
7832
|
+
/**
|
|
7833
|
+
* Import the payload fields specific to a hook type, type-checking each raw
|
|
7834
|
+
* value before it enters the canonical definition.
|
|
7835
|
+
*/
|
|
7836
|
+
function importTypePayloadFields({ h, hookType }) {
|
|
7837
|
+
if (hookType === "http") return {
|
|
7838
|
+
...typeof h.url === "string" && { url: h.url },
|
|
7839
|
+
...isStringRecord(h.headers) && { headers: h.headers },
|
|
7840
|
+
...isStringArray(h.allowedEnvVars) && { allowedEnvVars: h.allowedEnvVars }
|
|
7841
|
+
};
|
|
7842
|
+
if (hookType === "mcp_tool") return {
|
|
7843
|
+
...typeof h.server === "string" && { server: h.server },
|
|
7844
|
+
...typeof h.tool === "string" && { tool: h.tool },
|
|
7845
|
+
...h.input !== null && typeof h.input === "object" && !Array.isArray(h.input) && { input: h.input }
|
|
7846
|
+
};
|
|
7847
|
+
if (hookType === "prompt" || hookType === "agent") return typeof h.model === "string" ? { model: h.model } : {};
|
|
7848
|
+
return {};
|
|
7849
|
+
}
|
|
7850
|
+
/**
|
|
7300
7851
|
* Convert a single tool hook record into a canonical hook definition.
|
|
7301
7852
|
*/
|
|
7302
7853
|
function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
@@ -7304,7 +7855,7 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
|
7304
7855
|
command: h.command,
|
|
7305
7856
|
converterConfig
|
|
7306
7857
|
});
|
|
7307
|
-
const hookType = h.type
|
|
7858
|
+
const hookType = isImportedHookType(h.type) ? h.type : "command";
|
|
7308
7859
|
const timeout = typeof h.timeout === "number" ? h.timeout : void 0;
|
|
7309
7860
|
const prompt = typeof h.prompt === "string" ? h.prompt : void 0;
|
|
7310
7861
|
return {
|
|
@@ -7312,6 +7863,10 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
|
7312
7863
|
...command !== void 0 && command !== null && { command },
|
|
7313
7864
|
...timeout !== void 0 && timeout !== null && { timeout },
|
|
7314
7865
|
...prompt !== void 0 && prompt !== null && { prompt },
|
|
7866
|
+
...importTypePayloadFields({
|
|
7867
|
+
h,
|
|
7868
|
+
hookType
|
|
7869
|
+
}),
|
|
7315
7870
|
...converterConfig.passthroughFields?.includes("name") && typeof h.name === "string" && { name: h.name },
|
|
7316
7871
|
...converterConfig.passthroughFields?.includes("description") && typeof h.description === "string" && { description: h.description },
|
|
7317
7872
|
...importBooleanPassthroughFields({
|
|
@@ -7331,6 +7886,32 @@ function toolMatcherEntryToCanonical({ rawEntry, converterConfig }) {
|
|
|
7331
7886
|
converterConfig
|
|
7332
7887
|
}));
|
|
7333
7888
|
}
|
|
7889
|
+
/**
|
|
7890
|
+
* Assemble the canonical hooks config a tool importer writes to
|
|
7891
|
+
* `.rulesync/hooks.json`.
|
|
7892
|
+
*
|
|
7893
|
+
* The top-level `hooks` record only accepts canonical event names, so any
|
|
7894
|
+
* imported native event key without a canonical mapping is moved under the
|
|
7895
|
+
* importing tool's own override block (`<overrideKey>.hooks`), whose keys stay
|
|
7896
|
+
* lenient. This mirrors the generate direction — override blocks pass
|
|
7897
|
+
* tool-native keys through verbatim — so documented native triggers (e.g.
|
|
7898
|
+
* kiro-ide's `PostFileSave`) survive an import → generate round-trip instead
|
|
7899
|
+
* of failing canonical validation.
|
|
7900
|
+
*/
|
|
7901
|
+
function buildImportedHooksConfig({ hooks, overrideKey, version = 1, extraOverride }) {
|
|
7902
|
+
const canonical = {};
|
|
7903
|
+
const native = {};
|
|
7904
|
+
for (const [event, defs] of Object.entries(hooks)) if (isHookEvent(event)) canonical[event] = defs;
|
|
7905
|
+
else native[event] = defs;
|
|
7906
|
+
const override = { ...extraOverride };
|
|
7907
|
+
if (Object.keys(native).length > 0) override.hooks = native;
|
|
7908
|
+
const config = {
|
|
7909
|
+
version,
|
|
7910
|
+
hooks: canonical
|
|
7911
|
+
};
|
|
7912
|
+
if (Object.keys(override).length > 0) config[overrideKey] = override;
|
|
7913
|
+
return config;
|
|
7914
|
+
}
|
|
7334
7915
|
function toolHooksToCanonical({ hooks, converterConfig }) {
|
|
7335
7916
|
if (hooks === null || hooks === void 0 || typeof hooks !== "object") return {};
|
|
7336
7917
|
const canonical = {};
|
|
@@ -7501,7 +8082,8 @@ const ANTIGRAVITY_CONVERTER_CONFIG = {
|
|
|
7501
8082
|
"preModelInvocation",
|
|
7502
8083
|
"postModelInvocation",
|
|
7503
8084
|
"stop"
|
|
7504
|
-
])
|
|
8085
|
+
]),
|
|
8086
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"])
|
|
7505
8087
|
};
|
|
7506
8088
|
/**
|
|
7507
8089
|
* Antigravity's `hooks.json` is keyed by a named hook whose value holds the
|
|
@@ -7608,10 +8190,11 @@ var AntigravityHooks = class extends ToolHooks {
|
|
|
7608
8190
|
hooks: flattenAntigravityHooks(parsed),
|
|
7609
8191
|
converterConfig: ANTIGRAVITY_CONVERTER_CONFIG
|
|
7610
8192
|
});
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
hooks
|
|
7614
|
-
|
|
8193
|
+
const overrideKey = this.constructor.getOverrideKey();
|
|
8194
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8195
|
+
hooks,
|
|
8196
|
+
overrideKey
|
|
8197
|
+
}), null, 2) });
|
|
7615
8198
|
}
|
|
7616
8199
|
validate() {
|
|
7617
8200
|
return {
|
|
@@ -7732,7 +8315,8 @@ const AUGMENTCODE_CONVERTER_CONFIG = {
|
|
|
7732
8315
|
"sessionEnd",
|
|
7733
8316
|
"stop",
|
|
7734
8317
|
"notification"
|
|
7735
|
-
])
|
|
8318
|
+
]),
|
|
8319
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"])
|
|
7736
8320
|
};
|
|
7737
8321
|
/**
|
|
7738
8322
|
* AugmentCode (Auggie CLI) lifecycle hooks.
|
|
@@ -7814,10 +8398,10 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
7814
8398
|
hooks: settings.hooks,
|
|
7815
8399
|
converterConfig: AUGMENTCODE_CONVERTER_CONFIG
|
|
7816
8400
|
});
|
|
7817
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
}, null, 2) });
|
|
8401
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8402
|
+
hooks,
|
|
8403
|
+
overrideKey: "augmentcode"
|
|
8404
|
+
}), null, 2) });
|
|
7821
8405
|
}
|
|
7822
8406
|
validate() {
|
|
7823
8407
|
return {
|
|
@@ -7852,7 +8436,15 @@ const CLAUDE_CONVERTER_CONFIG = {
|
|
|
7852
8436
|
"taskCompleted",
|
|
7853
8437
|
"teammateIdle",
|
|
7854
8438
|
"cwdChanged"
|
|
7855
|
-
])
|
|
8439
|
+
]),
|
|
8440
|
+
supportedHookTypes: /* @__PURE__ */ new Set([
|
|
8441
|
+
"command",
|
|
8442
|
+
"prompt",
|
|
8443
|
+
"http",
|
|
8444
|
+
"mcp_tool",
|
|
8445
|
+
"agent"
|
|
8446
|
+
]),
|
|
8447
|
+
emitsPromptModel: true
|
|
7856
8448
|
};
|
|
7857
8449
|
var ClaudecodeHooks = class ClaudecodeHooks extends ToolHooks {
|
|
7858
8450
|
constructor(params) {
|
|
@@ -7917,10 +8509,10 @@ var ClaudecodeHooks = class ClaudecodeHooks extends ToolHooks {
|
|
|
7917
8509
|
hooks: settings.hooks,
|
|
7918
8510
|
converterConfig: CLAUDE_CONVERTER_CONFIG
|
|
7919
8511
|
});
|
|
7920
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
}, null, 2) });
|
|
8512
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8513
|
+
hooks,
|
|
8514
|
+
overrideKey: "claudecode"
|
|
8515
|
+
}), null, 2) });
|
|
7924
8516
|
}
|
|
7925
8517
|
validate() {
|
|
7926
8518
|
return {
|
|
@@ -8063,10 +8655,10 @@ var CodexcliHooks = class CodexcliHooks extends ToolHooks {
|
|
|
8063
8655
|
hooks: parsed.hooks,
|
|
8064
8656
|
converterConfig: CODEXCLI_CONVERTER_CONFIG
|
|
8065
8657
|
});
|
|
8066
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
}, null, 2) });
|
|
8658
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8659
|
+
hooks,
|
|
8660
|
+
overrideKey: "codexcli"
|
|
8661
|
+
}), null, 2) });
|
|
8070
8662
|
}
|
|
8071
8663
|
validate() {
|
|
8072
8664
|
return {
|
|
@@ -8234,10 +8826,10 @@ var CopilotHooks = class CopilotHooks extends ToolHooks {
|
|
|
8234
8826
|
throw new Error(`Failed to parse Copilot hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8235
8827
|
}
|
|
8236
8828
|
const hooks = copilotHooksToCanonical(parsed.hooks, options?.logger);
|
|
8237
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
}, null, 2) });
|
|
8829
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8830
|
+
hooks,
|
|
8831
|
+
overrideKey: "copilot"
|
|
8832
|
+
}), null, 2) });
|
|
8241
8833
|
}
|
|
8242
8834
|
validate() {
|
|
8243
8835
|
return {
|
|
@@ -8256,20 +8848,6 @@ var CopilotHooks = class CopilotHooks extends ToolHooks {
|
|
|
8256
8848
|
}
|
|
8257
8849
|
};
|
|
8258
8850
|
//#endregion
|
|
8259
|
-
//#region src/utils/object.ts
|
|
8260
|
-
/**
|
|
8261
|
-
* Return a shallow copy of `obj` keeping only the entries whose value is
|
|
8262
|
-
* neither `undefined` nor `null`.
|
|
8263
|
-
*
|
|
8264
|
-
* Used to assemble generated config objects without one conditional spread per
|
|
8265
|
-
* optional field (which would otherwise exceed the lint complexity budget).
|
|
8266
|
-
*/
|
|
8267
|
-
function compact(obj) {
|
|
8268
|
-
const result = {};
|
|
8269
|
-
for (const [key, value] of Object.entries(obj)) if (value !== void 0 && value !== null) result[key] = value;
|
|
8270
|
-
return result;
|
|
8271
|
-
}
|
|
8272
|
-
//#endregion
|
|
8273
8851
|
//#region src/features/hooks/copilotcli-hooks.ts
|
|
8274
8852
|
/**
|
|
8275
8853
|
* GitHub Copilot CLI hooks.
|
|
@@ -8402,7 +8980,7 @@ function buildCopilotCliEntriesForEvent({ eventName, definitions, canonicalSchem
|
|
|
8402
8980
|
...timeoutPart,
|
|
8403
8981
|
...rest
|
|
8404
8982
|
});
|
|
8405
|
-
else entries.push({
|
|
8983
|
+
else if (hookType === "command") entries.push({
|
|
8406
8984
|
type: "command",
|
|
8407
8985
|
...matcherPart,
|
|
8408
8986
|
...compact({
|
|
@@ -8554,10 +9132,10 @@ var CopilotcliHooks = class CopilotcliHooks extends ToolHooks {
|
|
|
8554
9132
|
throw new Error(`Failed to parse Copilot CLI hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8555
9133
|
}
|
|
8556
9134
|
const hooks = copilotCliHooksToCanonical(parsed.hooks, options?.logger);
|
|
8557
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
}, null, 2) });
|
|
9135
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9136
|
+
hooks,
|
|
9137
|
+
overrideKey: "copilotcli"
|
|
9138
|
+
}), null, 2) });
|
|
8561
9139
|
}
|
|
8562
9140
|
validate() {
|
|
8563
9141
|
return {
|
|
@@ -8612,9 +9190,10 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8612
9190
|
...config.cursor?.hooks
|
|
8613
9191
|
};
|
|
8614
9192
|
const mappedHooks = {};
|
|
9193
|
+
const cursorSupportedTypes = /* @__PURE__ */ new Set(["command", "prompt"]);
|
|
8615
9194
|
for (const [eventName, defs] of Object.entries(mergedHooks)) {
|
|
8616
9195
|
const cursorEventName = CANONICAL_TO_CURSOR_EVENT_NAMES[eventName] ?? eventName;
|
|
8617
|
-
|
|
9196
|
+
const mappedDefs = defs.filter((def) => cursorSupportedTypes.has(def.type ?? "command")).map((def) => ({
|
|
8618
9197
|
...def.type !== void 0 && def.type !== null && { type: def.type },
|
|
8619
9198
|
...def.command !== void 0 && def.command !== null && { command: def.command },
|
|
8620
9199
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
|
|
@@ -8623,6 +9202,7 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8623
9202
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt },
|
|
8624
9203
|
...def.failClosed !== void 0 && def.failClosed !== null && { failClosed: def.failClosed }
|
|
8625
9204
|
}));
|
|
9205
|
+
if (mappedDefs.length > 0) mappedHooks[cursorEventName] = mappedDefs;
|
|
8626
9206
|
}
|
|
8627
9207
|
const cursorConfig = {
|
|
8628
9208
|
version: config.version ?? 1,
|
|
@@ -8649,10 +9229,11 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8649
9229
|
canonicalHooks[eventName] = defs;
|
|
8650
9230
|
}
|
|
8651
9231
|
const version = parsed.version ?? 1;
|
|
8652
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
9232
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9233
|
+
hooks: canonicalHooks,
|
|
9234
|
+
overrideKey: "cursor",
|
|
9235
|
+
version
|
|
9236
|
+
}), null, 2) });
|
|
8656
9237
|
}
|
|
8657
9238
|
validate() {
|
|
8658
9239
|
return {
|
|
@@ -8707,7 +9288,7 @@ function canonicalToDeepagentsHooks(config) {
|
|
|
8707
9288
|
const deepagentsEvent = CANONICAL_TO_DEEPAGENTS_EVENT_NAMES[canonicalEvent];
|
|
8708
9289
|
if (!deepagentsEvent) continue;
|
|
8709
9290
|
for (const def of definitions) {
|
|
8710
|
-
if (def.type
|
|
9291
|
+
if ((def.type ?? "command") !== "command") continue;
|
|
8711
9292
|
if (!def.command) continue;
|
|
8712
9293
|
if (def.matcher) continue;
|
|
8713
9294
|
entries.push({
|
|
@@ -8797,10 +9378,10 @@ var DeepagentsHooks = class DeepagentsHooks extends ToolHooks {
|
|
|
8797
9378
|
throw new Error(`Failed to parse deepagents hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8798
9379
|
}
|
|
8799
9380
|
const hooks = deepagentsToCanonicalHooks(isDeepagentsHooksFile(parsed) ? parsed.hooks : []);
|
|
8800
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
}, null, 2) });
|
|
9381
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9382
|
+
hooks,
|
|
9383
|
+
overrideKey: "deepagents"
|
|
9384
|
+
}), null, 2) });
|
|
8804
9385
|
}
|
|
8805
9386
|
validate() {
|
|
8806
9387
|
return {
|
|
@@ -8929,10 +9510,10 @@ var DevinHooks = class DevinHooks extends ToolHooks {
|
|
|
8929
9510
|
hooks: this.getRelativeFilePath() === "config.json" ? isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {} : parsed,
|
|
8930
9511
|
converterConfig: DEVIN_CONVERTER_CONFIG
|
|
8931
9512
|
});
|
|
8932
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
}, null, 2) });
|
|
9513
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9514
|
+
hooks,
|
|
9515
|
+
overrideKey: "devin"
|
|
9516
|
+
}), null, 2) });
|
|
8936
9517
|
}
|
|
8937
9518
|
validate() {
|
|
8938
9519
|
return {
|
|
@@ -8956,7 +9537,8 @@ const FACTORYDROID_CONVERTER_CONFIG = {
|
|
|
8956
9537
|
supportedEvents: FACTORYDROID_HOOK_EVENTS,
|
|
8957
9538
|
canonicalToToolEventNames: CANONICAL_TO_FACTORYDROID_EVENT_NAMES,
|
|
8958
9539
|
toolToCanonicalEventNames: FACTORYDROID_TO_CANONICAL_EVENT_NAMES,
|
|
8959
|
-
projectDirVar: "$FACTORY_PROJECT_DIR"
|
|
9540
|
+
projectDirVar: "$FACTORY_PROJECT_DIR",
|
|
9541
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command", "prompt"])
|
|
8960
9542
|
};
|
|
8961
9543
|
var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
8962
9544
|
constructor(params) {
|
|
@@ -9024,10 +9606,10 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
9024
9606
|
hooks: settings.hooks,
|
|
9025
9607
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG
|
|
9026
9608
|
});
|
|
9027
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
}, null, 2) });
|
|
9609
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9610
|
+
hooks,
|
|
9611
|
+
overrideKey: "factorydroid"
|
|
9612
|
+
}), null, 2) });
|
|
9031
9613
|
}
|
|
9032
9614
|
validate() {
|
|
9033
9615
|
return {
|
|
@@ -9118,10 +9700,10 @@ var GooseHooks = class GooseHooks extends ToolHooks {
|
|
|
9118
9700
|
hooks: parsed.hooks && typeof parsed.hooks === "object" && !Array.isArray(parsed.hooks) ? Object.fromEntries(Object.entries(parsed.hooks).filter(([eventName]) => Object.hasOwn(GOOSE_TO_CANONICAL_EVENT_NAMES, eventName))) : parsed.hooks,
|
|
9119
9701
|
converterConfig: GOOSE_CONVERTER_CONFIG
|
|
9120
9702
|
});
|
|
9121
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
}, null, 2) });
|
|
9703
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9704
|
+
hooks,
|
|
9705
|
+
overrideKey: "goose"
|
|
9706
|
+
}), null, 2) });
|
|
9125
9707
|
}
|
|
9126
9708
|
validate() {
|
|
9127
9709
|
return {
|
|
@@ -9279,10 +9861,10 @@ var GrokcliHooks = class GrokcliHooks extends ToolHooks {
|
|
|
9279
9861
|
hooks: isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {},
|
|
9280
9862
|
converterConfig: GROKCLI_CONVERTER_CONFIG
|
|
9281
9863
|
});
|
|
9282
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
}, null, 2) });
|
|
9864
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9865
|
+
hooks,
|
|
9866
|
+
overrideKey: "grokcli"
|
|
9867
|
+
}), null, 2) });
|
|
9286
9868
|
}
|
|
9287
9869
|
validate() {
|
|
9288
9870
|
return {
|
|
@@ -9443,10 +10025,10 @@ var HermesagentHooks = class HermesagentHooks extends ToolHooks {
|
|
|
9443
10025
|
format: "yaml",
|
|
9444
10026
|
fileContent: this.getFileContent()
|
|
9445
10027
|
}).hooks);
|
|
9446
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
}, null, 2) });
|
|
10028
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10029
|
+
hooks,
|
|
10030
|
+
overrideKey: "hermesagent"
|
|
10031
|
+
}), null, 2) });
|
|
9450
10032
|
}
|
|
9451
10033
|
static fromRulesyncHooks({ outputRoot, rulesyncHooks, logger }) {
|
|
9452
10034
|
const config = rulesyncHooks.getJson();
|
|
@@ -9549,10 +10131,10 @@ var JunieHooks = class JunieHooks extends ToolHooks {
|
|
|
9549
10131
|
hooks: settings.hooks,
|
|
9550
10132
|
converterConfig: JUNIE_CONVERTER_CONFIG
|
|
9551
10133
|
});
|
|
9552
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
}, null, 2) });
|
|
10134
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10135
|
+
hooks,
|
|
10136
|
+
overrideKey: "junie"
|
|
10137
|
+
}), null, 2) });
|
|
9556
10138
|
}
|
|
9557
10139
|
validate() {
|
|
9558
10140
|
return {
|
|
@@ -9597,7 +10179,7 @@ function collectOpencodeStyleHandlers({ effectiveHooks, eventMap, namedEventHand
|
|
|
9597
10179
|
if (!toolEvent) continue;
|
|
9598
10180
|
const handlers = [];
|
|
9599
10181
|
for (const def of definitions) {
|
|
9600
|
-
if (def.type
|
|
10182
|
+
if ((def.type ?? "command") !== "command") continue;
|
|
9601
10183
|
if (!def.command) continue;
|
|
9602
10184
|
handlers.push({
|
|
9603
10185
|
command: def.command,
|
|
@@ -9902,10 +10484,11 @@ var KiroHooks = class KiroHooks extends ToolHooks {
|
|
|
9902
10484
|
throw new Error(`Failed to parse Kiro hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
9903
10485
|
}
|
|
9904
10486
|
const hooks = kiroHooksToCanonical(agentConfig.hooks);
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
hooks
|
|
9908
|
-
|
|
10487
|
+
const overrideKey = this.constructor.getOverrideKey();
|
|
10488
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10489
|
+
hooks,
|
|
10490
|
+
overrideKey
|
|
10491
|
+
}), null, 2) });
|
|
9909
10492
|
}
|
|
9910
10493
|
validate() {
|
|
9911
10494
|
return {
|
|
@@ -10114,10 +10697,10 @@ var KiroIdeHooks = class KiroIdeHooks extends ToolHooks {
|
|
|
10114
10697
|
throw new Error(`Failed to parse Kiro IDE hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10115
10698
|
}
|
|
10116
10699
|
const hooks = kiroIdeHooksToCanonical(parsed.hooks ?? []);
|
|
10117
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
}, null, 2) });
|
|
10700
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10701
|
+
hooks,
|
|
10702
|
+
overrideKey: "kiro-ide"
|
|
10703
|
+
}), null, 2) });
|
|
10121
10704
|
}
|
|
10122
10705
|
validate() {
|
|
10123
10706
|
return {
|
|
@@ -10241,11 +10824,18 @@ function canonicalToQwencodeHooks(config) {
|
|
|
10241
10824
|
...sharedHooks,
|
|
10242
10825
|
...config.qwencode?.hooks
|
|
10243
10826
|
};
|
|
10827
|
+
const qwencodeSupportedTypes = /* @__PURE__ */ new Set([
|
|
10828
|
+
"command",
|
|
10829
|
+
"prompt",
|
|
10830
|
+
"http",
|
|
10831
|
+
"function"
|
|
10832
|
+
]);
|
|
10244
10833
|
const qwencode = {};
|
|
10245
10834
|
for (const [eventName, definitions] of Object.entries(effectiveHooks)) {
|
|
10246
10835
|
const qwencodeEventName = CANONICAL_TO_QWENCODE_EVENT_NAMES[eventName] ?? eventName;
|
|
10247
10836
|
const byMatcher = /* @__PURE__ */ new Map();
|
|
10248
10837
|
for (const def of definitions) {
|
|
10838
|
+
if (!qwencodeSupportedTypes.has(def.type ?? "command")) continue;
|
|
10249
10839
|
const key = def.matcher ?? "";
|
|
10250
10840
|
const list = byMatcher.get(key);
|
|
10251
10841
|
if (list) list.push(def);
|
|
@@ -10305,9 +10895,10 @@ function qwencodeMatcherEntryToCanonical(entry) {
|
|
|
10305
10895
|
const sequential = entry.sequential === true;
|
|
10306
10896
|
const matcher = entry.matcher !== void 0 && entry.matcher !== null && entry.matcher !== "" ? entry.matcher : void 0;
|
|
10307
10897
|
for (const h of hooks) {
|
|
10308
|
-
const hookType = h.type === "command" || h.type === "prompt" || h.type === "http" ? h.type : "command";
|
|
10898
|
+
const hookType = h.type === "command" || h.type === "prompt" || h.type === "http" || h.type === "function" ? h.type : "command";
|
|
10309
10899
|
const isHttp = hookType === "http";
|
|
10310
10900
|
const isCommand = hookType === "command";
|
|
10901
|
+
const shell = h.shell === "bash" || h.shell === "powershell" ? h.shell : void 0;
|
|
10311
10902
|
defs.push({
|
|
10312
10903
|
type: hookType,
|
|
10313
10904
|
...compact({
|
|
@@ -10319,7 +10910,7 @@ function qwencodeMatcherEntryToCanonical(entry) {
|
|
|
10319
10910
|
statusMessage: h.statusMessage,
|
|
10320
10911
|
async: isCommand ? h.async : void 0,
|
|
10321
10912
|
env: isCommand ? h.env : void 0,
|
|
10322
|
-
shell: isCommand ?
|
|
10913
|
+
shell: isCommand ? shell : void 0,
|
|
10323
10914
|
headers: isHttp ? h.headers : void 0,
|
|
10324
10915
|
allowedEnvVars: isHttp ? h.allowedEnvVars : void 0,
|
|
10325
10916
|
once: isHttp ? h.once : void 0,
|
|
@@ -10406,15 +10997,11 @@ var QwencodeHooks = class QwencodeHooks extends ToolHooks {
|
|
|
10406
10997
|
} catch (error) {
|
|
10407
10998
|
throw new Error(`Failed to parse Qwen Code hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10408
10999
|
}
|
|
10409
|
-
const
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
} : {
|
|
10415
|
-
version: 1,
|
|
10416
|
-
hooks
|
|
10417
|
-
};
|
|
11000
|
+
const canonical = buildImportedHooksConfig({
|
|
11001
|
+
hooks: qwencodeHooksToCanonical(settings.hooks),
|
|
11002
|
+
overrideKey: "qwencode",
|
|
11003
|
+
...typeof settings.disableAllHooks === "boolean" && { extraOverride: { disableAllHooks: settings.disableAllHooks } }
|
|
11004
|
+
});
|
|
10418
11005
|
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(canonical, null, 2) });
|
|
10419
11006
|
}
|
|
10420
11007
|
validate() {
|
|
@@ -10576,10 +11163,10 @@ var ReasonixHooks = class ReasonixHooks extends ToolHooks {
|
|
|
10576
11163
|
throw new Error(`Failed to parse Reasonix hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10577
11164
|
}
|
|
10578
11165
|
const hooks = reasonixHooksToCanonical(settings.hooks);
|
|
10579
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
}, null, 2) });
|
|
11166
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
11167
|
+
hooks,
|
|
11168
|
+
overrideKey: "reasonix"
|
|
11169
|
+
}), null, 2) });
|
|
10583
11170
|
}
|
|
10584
11171
|
validate() {
|
|
10585
11172
|
return {
|
|
@@ -10802,10 +11389,10 @@ var VibeHooks = class VibeHooks extends ToolHooks {
|
|
|
10802
11389
|
throw new Error(`Failed to parse Vibe hooks content in ${(0, node_path.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10803
11390
|
}
|
|
10804
11391
|
const hooks = vibeHooksToCanonical(parsed);
|
|
10805
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
}, null, 2) });
|
|
11392
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
11393
|
+
hooks,
|
|
11394
|
+
overrideKey: "vibe"
|
|
11395
|
+
}), null, 2) });
|
|
10809
11396
|
}
|
|
10810
11397
|
validate() {
|
|
10811
11398
|
try {
|
|
@@ -10892,7 +11479,13 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
10892
11479
|
supportsImport: true
|
|
10893
11480
|
},
|
|
10894
11481
|
supportedEvents: CLAUDE_HOOK_EVENTS,
|
|
10895
|
-
supportedHookTypes: [
|
|
11482
|
+
supportedHookTypes: [
|
|
11483
|
+
"command",
|
|
11484
|
+
"prompt",
|
|
11485
|
+
"http",
|
|
11486
|
+
"mcp_tool",
|
|
11487
|
+
"agent"
|
|
11488
|
+
],
|
|
10896
11489
|
supportsMatcher: true
|
|
10897
11490
|
}],
|
|
10898
11491
|
["codexcli", {
|
|
@@ -11084,7 +11677,12 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
11084
11677
|
supportsImport: true
|
|
11085
11678
|
},
|
|
11086
11679
|
supportedEvents: QWENCODE_HOOK_EVENTS,
|
|
11087
|
-
supportedHookTypes: [
|
|
11680
|
+
supportedHookTypes: [
|
|
11681
|
+
"command",
|
|
11682
|
+
"prompt",
|
|
11683
|
+
"http",
|
|
11684
|
+
"function"
|
|
11685
|
+
],
|
|
11088
11686
|
supportsMatcher: true
|
|
11089
11687
|
}],
|
|
11090
11688
|
["reasonix", {
|
|
@@ -12386,16 +12984,6 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
12386
12984
|
}
|
|
12387
12985
|
};
|
|
12388
12986
|
//#endregion
|
|
12389
|
-
//#region src/constants/amp-paths.ts
|
|
12390
|
-
const AMP_DIR = ".amp";
|
|
12391
|
-
const AMP_GLOBAL_DIR = (0, node_path.join)(".config", "amp");
|
|
12392
|
-
const AMP_AGENTS_DIR = ".agents";
|
|
12393
|
-
const AMP_SKILLS_PROJECT_DIR = (0, node_path.join)(AMP_AGENTS_DIR, "skills");
|
|
12394
|
-
const AMP_SKILLS_GLOBAL_DIR = (0, node_path.join)(".config", "agents", "skills");
|
|
12395
|
-
const AMP_RULE_FILE_NAME = "AGENTS.md";
|
|
12396
|
-
const AMP_SETTINGS_FILE_NAME = "settings.json";
|
|
12397
|
-
const AMP_SETTINGS_JSONC_FILE_NAME = "settings.jsonc";
|
|
12398
|
-
//#endregion
|
|
12399
12987
|
//#region src/types/mcp.ts
|
|
12400
12988
|
const EnvVarNameSchema = zod_mini.z.string().check((0, zod_mini.refine)((value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value), "envVars entries must be valid environment variable names"));
|
|
12401
12989
|
const McpServerSchema = zod_mini.z.looseObject({
|
|
@@ -13487,10 +14075,19 @@ function mapOauthFromCodex(oauth) {
|
|
|
13487
14075
|
}
|
|
13488
14076
|
const CODEX_MCP_SERVER_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
13489
14077
|
function normalizeCodexMcpServerName(name) {
|
|
13490
|
-
if (PROTOTYPE_POLLUTION_KEYS.has(name)) return
|
|
13491
|
-
|
|
14078
|
+
if (!PROTOTYPE_POLLUTION_KEYS.has(name) && CODEX_MCP_SERVER_NAME_PATTERN.test(name)) return {
|
|
14079
|
+
codexName: name,
|
|
14080
|
+
usedFallback: false
|
|
14081
|
+
};
|
|
13492
14082
|
const normalizedName = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
13493
|
-
|
|
14083
|
+
if (normalizedName && !PROTOTYPE_POLLUTION_KEYS.has(normalizedName)) return {
|
|
14084
|
+
codexName: normalizedName,
|
|
14085
|
+
usedFallback: false
|
|
14086
|
+
};
|
|
14087
|
+
return {
|
|
14088
|
+
codexName: `mcp_${(0, node_crypto.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`,
|
|
14089
|
+
usedFallback: true
|
|
14090
|
+
};
|
|
13494
14091
|
}
|
|
13495
14092
|
function convertFromCodexFormat(codexMcp) {
|
|
13496
14093
|
const result = {};
|
|
@@ -13504,7 +14101,7 @@ function convertFromCodexFormat(codexMcp) {
|
|
|
13504
14101
|
} else if (key === "oauth" && isRecord(value)) converted[key] = mapOauthFromCodex(value);
|
|
13505
14102
|
else if (Object.hasOwn(CODEX_TO_RULESYNC_FIELD_MAP, key)) {
|
|
13506
14103
|
const mappedKey = CODEX_TO_RULESYNC_FIELD_MAP[key];
|
|
13507
|
-
if (mappedKey) if (isStringArray(value)) converted[mappedKey] = value;
|
|
14104
|
+
if (mappedKey) if (isStringArray$1(value)) converted[mappedKey] = value;
|
|
13508
14105
|
else warnWithFallback(void 0, `Ignored malformed array for ${key} in MCP server ${name}`);
|
|
13509
14106
|
} else converted[key] = value;
|
|
13510
14107
|
}
|
|
@@ -13516,12 +14113,9 @@ function convertToCodexFormat(mcpServers) {
|
|
|
13516
14113
|
const result = {};
|
|
13517
14114
|
const originalNames = /* @__PURE__ */ new Map();
|
|
13518
14115
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
13519
|
-
const codexName = normalizeCodexMcpServerName(name);
|
|
13520
|
-
if (codexName === null) {
|
|
13521
|
-
warnWithFallback(void 0, `MCP server "${name}" could not be normalized to a valid Codex MCP server name and was skipped.`);
|
|
13522
|
-
continue;
|
|
13523
|
-
}
|
|
13524
14116
|
if (!isRecord(config)) continue;
|
|
14117
|
+
const { codexName, usedFallback } = normalizeCodexMcpServerName(name);
|
|
14118
|
+
if (usedFallback) warnWithFallback(void 0, `MCP server "${name}" cannot be represented as a Codex MCP server name (ASCII [a-zA-Z0-9_-] only), so the stable fallback name "${codexName}" was used. Rename the server in .rulesync/mcp.json to choose a readable Codex name.`);
|
|
13525
14119
|
const converted = {};
|
|
13526
14120
|
for (const [key, value] of Object.entries(config)) {
|
|
13527
14121
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
@@ -13530,12 +14124,12 @@ function convertToCodexFormat(mcpServers) {
|
|
|
13530
14124
|
} else if (key === "oauth" && isRecord(value)) converted[key] = mapOauthToCodex(value);
|
|
13531
14125
|
else if (Object.hasOwn(RULESYNC_TO_CODEX_FIELD_MAP, key)) {
|
|
13532
14126
|
const mappedKey = RULESYNC_TO_CODEX_FIELD_MAP[key];
|
|
13533
|
-
if (mappedKey) if (isStringArray(value)) converted[mappedKey] = value;
|
|
14127
|
+
if (mappedKey) if (isStringArray$1(value)) converted[mappedKey] = value;
|
|
13534
14128
|
else warnWithFallback(void 0, `[CodexCliMcp] Skipping invalid value type for mapped key '${key}': expected string array, got ${typeof value}`);
|
|
13535
14129
|
} else converted[key] = value;
|
|
13536
14130
|
}
|
|
13537
14131
|
const previousName = originalNames.get(codexName);
|
|
13538
|
-
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}"
|
|
14132
|
+
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}"; "${name}" (processed last) overwrites "${previousName}".`);
|
|
13539
14133
|
originalNames.set(codexName, name);
|
|
13540
14134
|
result[codexName] = converted;
|
|
13541
14135
|
}
|
|
@@ -13602,7 +14196,7 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
13602
14196
|
const rawServer = isRecord(rawMcpServers) ? rawMcpServers[serverName] : void 0;
|
|
13603
14197
|
return [serverName, {
|
|
13604
14198
|
...serverConfig,
|
|
13605
|
-
...isRecord(rawServer) && isStringArray(rawServer.envVars) ? { envVars: rawServer.envVars } : {}
|
|
14199
|
+
...isRecord(rawServer) && isStringArray$1(rawServer.envVars) ? { envVars: rawServer.envVars } : {}
|
|
13606
14200
|
}];
|
|
13607
14201
|
})));
|
|
13608
14202
|
const filteredMcpServers = this.removeEmptyEntries(converted);
|
|
@@ -14339,11 +14933,11 @@ function applyGooseStdioFields(ext, config) {
|
|
|
14339
14933
|
if (Array.isArray(command)) {
|
|
14340
14934
|
if (typeof command[0] === "string") ext.cmd = command[0];
|
|
14341
14935
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14342
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
14936
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14343
14937
|
if (rest.length > 0 || args.length > 0) ext.args = [...rest, ...args];
|
|
14344
14938
|
} else if (typeof command === "string") {
|
|
14345
14939
|
ext.cmd = command;
|
|
14346
|
-
if (isStringArray(config.args)) ext.args = config.args;
|
|
14940
|
+
if (isStringArray$1(config.args)) ext.args = config.args;
|
|
14347
14941
|
}
|
|
14348
14942
|
if (isPlainObject$1(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
|
|
14349
14943
|
}
|
|
@@ -14401,7 +14995,7 @@ function convertFromGooseFormat(extensions) {
|
|
|
14401
14995
|
else if (type === "streamable_http") server.type = "http";
|
|
14402
14996
|
else if (type === "stdio") server.type = "stdio";
|
|
14403
14997
|
if (typeof ext.cmd === "string") server.command = ext.cmd;
|
|
14404
|
-
if (isStringArray(ext.args)) server.args = ext.args;
|
|
14998
|
+
if (isStringArray$1(ext.args)) server.args = ext.args;
|
|
14405
14999
|
if (isPlainObject$1(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
|
|
14406
15000
|
if (typeof ext.uri === "string") server.url = ext.uri;
|
|
14407
15001
|
if (isPlainObject$1(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
|
|
@@ -14421,11 +15015,11 @@ function buildGoosePluginStdioServer(config) {
|
|
|
14421
15015
|
if (Array.isArray(command)) {
|
|
14422
15016
|
if (typeof command[0] === "string") server.command = command[0];
|
|
14423
15017
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14424
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
15018
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14425
15019
|
if (rest.length > 0 || args.length > 0) server.args = [...rest, ...args];
|
|
14426
15020
|
} else if (typeof command === "string") {
|
|
14427
15021
|
server.command = command;
|
|
14428
|
-
if (isStringArray(config.args)) server.args = config.args;
|
|
15022
|
+
if (isStringArray$1(config.args)) server.args = config.args;
|
|
14429
15023
|
}
|
|
14430
15024
|
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
14431
15025
|
if (typeof config.cwd === "string") server.cwd = config.cwd;
|
|
@@ -14738,7 +15332,7 @@ function resolveHermesTimeout(config) {
|
|
|
14738
15332
|
*/
|
|
14739
15333
|
function copyHermesAdvancedFields(source, target) {
|
|
14740
15334
|
if (typeof source.auth === "string") target.auth = source.auth;
|
|
14741
|
-
if (typeof source.client_cert === "string" || isStringArray(source.client_cert)) target.client_cert = source.client_cert;
|
|
15335
|
+
if (typeof source.client_cert === "string" || isStringArray$1(source.client_cert)) target.client_cert = source.client_cert;
|
|
14742
15336
|
if (typeof source.client_key === "string") target.client_key = source.client_key;
|
|
14743
15337
|
if (typeof source.connect_timeout === "number") target.connect_timeout = source.connect_timeout;
|
|
14744
15338
|
if (typeof source.supports_parallel_tool_calls === "boolean") target.supports_parallel_tool_calls = source.supports_parallel_tool_calls;
|
|
@@ -14757,8 +15351,8 @@ function copyHermesAdvancedFields(source, target) {
|
|
|
14757
15351
|
*/
|
|
14758
15352
|
function buildHermesToolsBlock(config) {
|
|
14759
15353
|
const tools = {};
|
|
14760
|
-
if (isStringArray(config.enabledTools)) tools.include = config.enabledTools;
|
|
14761
|
-
if (isStringArray(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
15354
|
+
if (isStringArray$1(config.enabledTools)) tools.include = config.enabledTools;
|
|
15355
|
+
if (isStringArray$1(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
14762
15356
|
if (typeof config.promptsEnabled === "boolean") tools.prompts = config.promptsEnabled;
|
|
14763
15357
|
if (typeof config.resourcesEnabled === "boolean") tools.resources = config.resourcesEnabled;
|
|
14764
15358
|
return tools;
|
|
@@ -14770,8 +15364,8 @@ function buildHermesToolsBlock(config) {
|
|
|
14770
15364
|
* `promptsEnabled`/`resourcesEnabled` top-level toggles.
|
|
14771
15365
|
*/
|
|
14772
15366
|
function applyHermesToolsBlock(hermesTools, server) {
|
|
14773
|
-
if (isStringArray(hermesTools.include)) server.enabledTools = hermesTools.include;
|
|
14774
|
-
if (isStringArray(hermesTools.exclude)) server.disabledTools = hermesTools.exclude;
|
|
15367
|
+
if (isStringArray$1(hermesTools.include)) server.enabledTools = hermesTools.include;
|
|
15368
|
+
if (isStringArray$1(hermesTools.exclude)) server.disabledTools = hermesTools.exclude;
|
|
14775
15369
|
if (typeof hermesTools.prompts === "boolean") server.promptsEnabled = hermesTools.prompts;
|
|
14776
15370
|
if (typeof hermesTools.resources === "boolean") server.resourcesEnabled = hermesTools.resources;
|
|
14777
15371
|
}
|
|
@@ -14795,11 +15389,11 @@ function convertServerToHermes(config) {
|
|
|
14795
15389
|
if (Array.isArray(command)) {
|
|
14796
15390
|
if (typeof command[0] === "string") out.command = command[0];
|
|
14797
15391
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14798
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
15392
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14799
15393
|
if (rest.length > 0 || args.length > 0) out.args = [...rest, ...args];
|
|
14800
15394
|
} else if (typeof command === "string") {
|
|
14801
15395
|
out.command = command;
|
|
14802
|
-
if (isStringArray(config.args)) out.args = config.args;
|
|
15396
|
+
if (isStringArray$1(config.args)) out.args = config.args;
|
|
14803
15397
|
}
|
|
14804
15398
|
if (isPlainObject$1(config.env)) out.env = omitPrototypePollutionKeys(config.env);
|
|
14805
15399
|
} else if (url !== void 0) {
|
|
@@ -14847,7 +15441,7 @@ function convertFromHermesFormat(mcpServers) {
|
|
|
14847
15441
|
if (PROTOTYPE_POLLUTION_KEYS.has(name) || !isRecord(config)) continue;
|
|
14848
15442
|
const server = {};
|
|
14849
15443
|
if (typeof config.command === "string") server.command = config.command;
|
|
14850
|
-
if (isStringArray(config.args)) server.args = config.args;
|
|
15444
|
+
if (isStringArray$1(config.args)) server.args = config.args;
|
|
14851
15445
|
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
14852
15446
|
if (typeof config.url === "string") server.url = config.url;
|
|
14853
15447
|
if (isPlainObject$1(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
|
|
@@ -17172,7 +17766,11 @@ const VibePermissionsOverrideSchema = zod_mini.z.looseObject({ permission: zod_m
|
|
|
17172
17766
|
*/
|
|
17173
17767
|
const CursorPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
17174
17768
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17175
|
-
approvalMode: zod_mini.z.optional(zod_mini.z.
|
|
17769
|
+
approvalMode: zod_mini.z.optional(zod_mini.z.enum([
|
|
17770
|
+
"allowlist",
|
|
17771
|
+
"auto-review",
|
|
17772
|
+
"unrestricted"
|
|
17773
|
+
])),
|
|
17176
17774
|
sandbox: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
17177
17775
|
});
|
|
17178
17776
|
/**
|
|
@@ -17260,7 +17858,11 @@ const FactorydroidPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17260
17858
|
*/
|
|
17261
17859
|
const WarpPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
17262
17860
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17263
|
-
agent_mode_coding_permissions: zod_mini.z.optional(zod_mini.z.
|
|
17861
|
+
agent_mode_coding_permissions: zod_mini.z.optional(zod_mini.z.enum([
|
|
17862
|
+
"always_ask_before_reading",
|
|
17863
|
+
"always_allow_reading",
|
|
17864
|
+
"allow_reading_specific_files"
|
|
17865
|
+
])),
|
|
17264
17866
|
agent_mode_coding_file_read_allowlist: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())),
|
|
17265
17867
|
agent_mode_execute_readonly_commands: zod_mini.z.optional(zod_mini.z.boolean())
|
|
17266
17868
|
});
|
|
@@ -17306,7 +17908,11 @@ const JuniePermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17306
17908
|
*/
|
|
17307
17909
|
const TaktPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
17308
17910
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17309
|
-
step_permission_overrides: zod_mini.z.optional(zod_mini.z.record(zod_mini.z.string(), zod_mini.z.
|
|
17911
|
+
step_permission_overrides: zod_mini.z.optional(zod_mini.z.record(zod_mini.z.string(), zod_mini.z.enum([
|
|
17912
|
+
"readonly",
|
|
17913
|
+
"edit",
|
|
17914
|
+
"full"
|
|
17915
|
+
]))),
|
|
17310
17916
|
provider_options: zod_mini.z.optional(zod_mini.z.looseObject({}))
|
|
17311
17917
|
});
|
|
17312
17918
|
/**
|
|
@@ -17336,9 +17942,15 @@ const AmpPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17336
17942
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17337
17943
|
permissions: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.looseObject({
|
|
17338
17944
|
tool: zod_mini.z.string(),
|
|
17339
|
-
action: zod_mini.z.
|
|
17945
|
+
action: zod_mini.z.enum([
|
|
17946
|
+
"allow",
|
|
17947
|
+
"ask",
|
|
17948
|
+
"reject",
|
|
17949
|
+
"delegate"
|
|
17950
|
+
]),
|
|
17951
|
+
context: zod_mini.z.optional(zod_mini.z.enum(["thread", "subagent"]))
|
|
17340
17952
|
}))),
|
|
17341
|
-
mcpPermissions: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.looseObject({}))),
|
|
17953
|
+
mcpPermissions: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.looseObject({ action: zod_mini.z.enum(["allow", "reject"]) }))),
|
|
17342
17954
|
guardedFiles: zod_mini.z.optional(zod_mini.z.looseObject({ allowlist: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())) })),
|
|
17343
17955
|
dangerouslyAllowAll: zod_mini.z.optional(zod_mini.z.boolean())
|
|
17344
17956
|
});
|
|
@@ -17363,7 +17975,12 @@ const AmpPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17363
17975
|
*/
|
|
17364
17976
|
const AntigravityCliPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
17365
17977
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17366
|
-
toolPermission: zod_mini.z.optional(zod_mini.z.
|
|
17978
|
+
toolPermission: zod_mini.z.optional(zod_mini.z.enum([
|
|
17979
|
+
"request-review",
|
|
17980
|
+
"proceed-in-sandbox",
|
|
17981
|
+
"always-proceed",
|
|
17982
|
+
"strict"
|
|
17983
|
+
])),
|
|
17367
17984
|
enableTerminalSandbox: zod_mini.z.optional(zod_mini.z.boolean())
|
|
17368
17985
|
});
|
|
17369
17986
|
/**
|
|
@@ -17392,7 +18009,14 @@ const AugmentcodePermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17392
18009
|
permission: zod_mini.z.optional(ToolScopedPermissionSchema),
|
|
17393
18010
|
toolPermissions: zod_mini.z.optional(zod_mini.z.array(zod_mini.z.looseObject({
|
|
17394
18011
|
toolName: zod_mini.z.string(),
|
|
17395
|
-
|
|
18012
|
+
eventType: zod_mini.z.optional(zod_mini.z.enum(["tool-call", "tool-response"])),
|
|
18013
|
+
permission: zod_mini.z.looseObject({ type: zod_mini.z.enum([
|
|
18014
|
+
"allow",
|
|
18015
|
+
"deny",
|
|
18016
|
+
"ask-user",
|
|
18017
|
+
"webhook-policy",
|
|
18018
|
+
"script-policy"
|
|
18019
|
+
]) })
|
|
17396
18020
|
})))
|
|
17397
18021
|
});
|
|
17398
18022
|
/**
|
|
@@ -17482,12 +18106,20 @@ const CodexApprovalsReviewerSchema = zod_mini.z.enum([
|
|
|
17482
18106
|
* `[permissions.rulesync]` profile may extend. Codex ships three built-in
|
|
17483
18107
|
* profiles (`:read-only`, `:workspace`, `:danger-full-access`; the leading
|
|
17484
18108
|
* colon is reserved for built-ins), but `extends` rejects
|
|
17485
|
-
* `:danger-full-access` at config load time, so only
|
|
17486
|
-
*
|
|
17487
|
-
*
|
|
18109
|
+
* `:danger-full-access` at config load time, so only these two are valid
|
|
18110
|
+
* `extends` parents. The value list is exported so the Codex CLI translator
|
|
18111
|
+
* derives its import-side baseline check from the same source.
|
|
17488
18112
|
* @see https://learn.chatgpt.com/docs/permissions
|
|
17489
18113
|
*/
|
|
17490
|
-
const
|
|
18114
|
+
const CODEX_EXTENDABLE_BASELINE_PROFILES = [":read-only", ":workspace"];
|
|
18115
|
+
/**
|
|
18116
|
+
* All accepted `codexcli.base_permission_profile` values. `:danger-full-access`
|
|
18117
|
+
* cannot be an `extends` parent, so selecting it makes rulesync emit
|
|
18118
|
+
* `default_permissions = ":danger-full-access"` directly and skip the managed
|
|
18119
|
+
* `[permissions.rulesync]` profile entirely (there is no sandbox for
|
|
18120
|
+
* filesystem/network rules to refine in that mode).
|
|
18121
|
+
*/
|
|
18122
|
+
const CODEX_BASE_PERMISSION_PROFILES = [...CODEX_EXTENDABLE_BASELINE_PROFILES, ":danger-full-access"];
|
|
17491
18123
|
const CodexBasePermissionProfileSchema = zod_mini.z.enum(CODEX_BASE_PERMISSION_PROFILES);
|
|
17492
18124
|
/**
|
|
17493
18125
|
* Codex CLI-scoped permission override.
|
|
@@ -17498,10 +18130,14 @@ const CodexBasePermissionProfileSchema = zod_mini.z.enum(CODEX_BASE_PERMISSION_P
|
|
|
17498
18130
|
* override whose fields are written verbatim as top-level `.codex/config.toml`
|
|
17499
18131
|
* keys (the override wins per key; existing sibling keys the user set directly
|
|
17500
18132
|
* are preserved):
|
|
17501
|
-
* - `base_permission_profile` — the built-in profile
|
|
17502
|
-
*
|
|
17503
|
-
*
|
|
17504
|
-
*
|
|
18133
|
+
* - `base_permission_profile` — the built-in baseline profile (`:read-only` |
|
|
18134
|
+
* `:workspace` | `:danger-full-access`). Unlike the other keys it is not a
|
|
18135
|
+
* top-level config key: the extendable baselines are emitted as the managed
|
|
18136
|
+
* `[permissions.rulesync]` profile's `extends` value, while
|
|
18137
|
+
* `:danger-full-access` (which Codex rejects as an `extends` parent) is
|
|
18138
|
+
* selected directly via `default_permissions` and skips the managed profile
|
|
18139
|
+
* entirely — canonical filesystem/network rules are ignored in that mode.
|
|
18140
|
+
* Defaults to `:workspace` when unspecified.
|
|
17505
18141
|
* - `approval_policy` — `untrusted` | `on-request` (legacy alias `on-failure`) |
|
|
17506
18142
|
* `never`, or a `{ granular = { … } }` table (kept verbatim; the granular
|
|
17507
18143
|
* schema has required fields that are brittle to model as typed keys).
|
|
@@ -17521,6 +18157,15 @@ const CodexBasePermissionProfileSchema = zod_mini.z.enum(CODEX_BASE_PERMISSION_P
|
|
|
17521
18157
|
* | `guardian_subagent`), or a table for the richer reviewer config.
|
|
17522
18158
|
* Defaults to `auto_review` when neither the override nor the existing
|
|
17523
18159
|
* config sets it.
|
|
18160
|
+
* - `git_write_rules` — whether the managed profile's `:workspace_roots` table
|
|
18161
|
+
* emits the default `.git` carve-out (`".git/**" = "write"`). Codex's
|
|
18162
|
+
* `:workspace` baseline makes `.git` read-only, which denies basic git
|
|
18163
|
+
* workflows (commit/stage writes to `.git/index`, `.git/objects`, refs,
|
|
18164
|
+
* logs; everyday commands like `git remote add` or `git push -u` write to
|
|
18165
|
+
* `.git/config`), so the carve-out is emitted by default. Defaults to
|
|
18166
|
+
* `true`; only an explicit `false` suppresses it. Like
|
|
18167
|
+
* `base_permission_profile` it is consumed by the profile builder, not
|
|
18168
|
+
* written as a top-level config key.
|
|
17524
18169
|
*
|
|
17525
18170
|
* Two surfaces are deliberately NOT authorable here so the override can never
|
|
17526
18171
|
* clobber a feature-owned key: `mcp_servers.*` per-MCP gating is owned by the
|
|
@@ -17546,7 +18191,8 @@ const CodexcliPermissionsOverrideSchema = zod_mini.z.looseObject({
|
|
|
17546
18191
|
/** @deprecated Superseded by `base_permission_profile` (permission profiles). */
|
|
17547
18192
|
sandbox_workspace_write: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
17548
18193
|
apps: zod_mini.z.optional(zod_mini.z.looseObject({})),
|
|
17549
|
-
approvals_reviewer: zod_mini.z.optional(zod_mini.z.union([CodexApprovalsReviewerSchema, zod_mini.z.looseObject({})]))
|
|
18194
|
+
approvals_reviewer: zod_mini.z.optional(zod_mini.z.union([CodexApprovalsReviewerSchema, zod_mini.z.looseObject({})])),
|
|
18195
|
+
git_write_rules: zod_mini.z.optional(zod_mini.z.boolean())
|
|
17550
18196
|
});
|
|
17551
18197
|
/**
|
|
17552
18198
|
* Permissions configuration.
|
|
@@ -19515,11 +20161,14 @@ var ClinePermissions = class ClinePermissions extends ToolPermissions {
|
|
|
19515
20161
|
const RULESYNC_PROFILE_NAME = "rulesync";
|
|
19516
20162
|
const CODEX_WORKSPACE_ROOTS_KEY = ":workspace_roots";
|
|
19517
20163
|
const CODEX_WORKSPACE_BASELINE = ":workspace";
|
|
19518
|
-
const
|
|
20164
|
+
const CODEX_READ_ONLY_BASELINE = ":read-only";
|
|
20165
|
+
const CODEX_DANGER_FULL_ACCESS_BASELINE = ":danger-full-access";
|
|
20166
|
+
const CODEX_EXTENDABLE_BASELINES = new Set(CODEX_EXTENDABLE_BASELINE_PROFILES);
|
|
19519
20167
|
const CODEX_DEFAULT_APPROVAL_POLICY = "on-request";
|
|
19520
20168
|
const CODEX_DEFAULT_APPROVALS_REVIEWER = "auto_review";
|
|
19521
20169
|
const CODEX_GLOB_SCAN_MAX_DEPTH = 8;
|
|
19522
20170
|
const CODEX_MINIMAL_KEY = ":minimal";
|
|
20171
|
+
const CODEX_GIT_WRITE_RULES = { ".git/**": "write" };
|
|
19523
20172
|
const GLOBAL_WILDCARD_DOMAIN = "*";
|
|
19524
20173
|
var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
19525
20174
|
static getSettablePaths(_options = {}) {
|
|
@@ -19547,8 +20196,40 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
19547
20196
|
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
19548
20197
|
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
19549
20198
|
const existing = toMutableTable(smol_toml.parse(existingContent || smol_toml.stringify({})));
|
|
20199
|
+
const canonicalConfig = rulesyncPermissions.getJson();
|
|
20200
|
+
if (canonicalConfig.codexcli?.base_permission_profile === CODEX_DANGER_FULL_ACCESS_BASELINE) {
|
|
20201
|
+
const ignoredCategories = Object.entries(canonicalConfig.permission).filter(([category, rules]) => category !== "bash" && Object.keys(rules).length > 0).map(([category]) => category);
|
|
20202
|
+
if (ignoredCategories.length > 0) logger?.warn(`Codex CLI baseline ":danger-full-access" removes the sandbox, so canonical ${ignoredCategories.join("/")} rules are not representable and are ignored for Codex CLI.`);
|
|
20203
|
+
const permissionsTable = toMutableTable(existing.permissions);
|
|
20204
|
+
if (permissionsTable[RULESYNC_PROFILE_NAME] !== void 0) {
|
|
20205
|
+
logger?.warn(`Codex CLI baseline ":danger-full-access" prunes the managed "[permissions.${RULESYNC_PROFILE_NAME}]" profile; any hand-written keys inside it (e.g. network settings) are removed. Move them to a sibling profile or re-add them after switching baselines.`);
|
|
20206
|
+
delete permissionsTable[RULESYNC_PROFILE_NAME];
|
|
20207
|
+
}
|
|
20208
|
+
const overridePatch = computeCodexcliOverridePatch({
|
|
20209
|
+
existing,
|
|
20210
|
+
override: canonicalConfig.codexcli,
|
|
20211
|
+
logger
|
|
20212
|
+
});
|
|
20213
|
+
return new CodexcliPermissions({
|
|
20214
|
+
outputRoot,
|
|
20215
|
+
relativeDirPath: paths.relativeDirPath,
|
|
20216
|
+
relativeFilePath: paths.relativeFilePath,
|
|
20217
|
+
fileContent: applySharedConfigPatch({
|
|
20218
|
+
fileKey: sharedConfigFileKey(paths),
|
|
20219
|
+
feature: "permissions",
|
|
20220
|
+
existingContent,
|
|
20221
|
+
patch: {
|
|
20222
|
+
permissions: Object.keys(permissionsTable).length > 0 ? permissionsTable : void 0,
|
|
20223
|
+
default_permissions: CODEX_DANGER_FULL_ACCESS_BASELINE,
|
|
20224
|
+
...overridePatch
|
|
20225
|
+
},
|
|
20226
|
+
filePath
|
|
20227
|
+
}),
|
|
20228
|
+
validate
|
|
20229
|
+
});
|
|
20230
|
+
}
|
|
19550
20231
|
const newProfile = convertRulesyncToCodexProfile({
|
|
19551
|
-
config:
|
|
20232
|
+
config: canonicalConfig,
|
|
19552
20233
|
logger
|
|
19553
20234
|
});
|
|
19554
20235
|
const permissionsTable = toMutableTable(existing.permissions);
|
|
@@ -19609,6 +20290,7 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
19609
20290
|
});
|
|
19610
20291
|
const override = extractCodexcliOverride(table);
|
|
19611
20292
|
if (typeof profile?.extends === "string" && CODEX_EXTENDABLE_BASELINES.has(profile.extends)) override.base_permission_profile = profile.extends;
|
|
20293
|
+
if (defaultProfile === CODEX_DANGER_FULL_ACCESS_BASELINE) override.base_permission_profile = CODEX_DANGER_FULL_ACCESS_BASELINE;
|
|
19612
20294
|
const result = Object.keys(override).length > 0 ? {
|
|
19613
20295
|
...config,
|
|
19614
20296
|
codexcli: override
|
|
@@ -19664,16 +20346,10 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19664
20346
|
const filesystem = { [CODEX_MINIMAL_KEY]: "read" };
|
|
19665
20347
|
const workspaceRootFilesystem = {};
|
|
19666
20348
|
const domains = {};
|
|
20349
|
+
const filesystemCategoryRules = {};
|
|
19667
20350
|
for (const [toolName, rules] of Object.entries(config.permission)) {
|
|
19668
20351
|
if (toolName === "read" || toolName === "edit" || toolName === "write") {
|
|
19669
|
-
|
|
19670
|
-
for (const [pattern, action] of Object.entries(rules)) addFilesystemRule({
|
|
19671
|
-
filesystem,
|
|
19672
|
-
workspaceRootFilesystem,
|
|
19673
|
-
pattern,
|
|
19674
|
-
access: mapAction(action),
|
|
19675
|
-
logger
|
|
19676
|
-
});
|
|
20352
|
+
filesystemCategoryRules[toolName] = rules;
|
|
19677
20353
|
continue;
|
|
19678
20354
|
}
|
|
19679
20355
|
if (toolName === "webfetch") {
|
|
@@ -19686,6 +20362,21 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19686
20362
|
}
|
|
19687
20363
|
logger?.warn(`Codex CLI permissions support only read/edit/write/webfetch categories. Skipping: ${toolName}`);
|
|
19688
20364
|
}
|
|
20365
|
+
for (const [pattern, access] of mergeFilesystemCategoryRules({
|
|
20366
|
+
categoryRules: filesystemCategoryRules,
|
|
20367
|
+
logger
|
|
20368
|
+
})) addFilesystemRule({
|
|
20369
|
+
filesystem,
|
|
20370
|
+
workspaceRootFilesystem,
|
|
20371
|
+
pattern,
|
|
20372
|
+
access,
|
|
20373
|
+
logger
|
|
20374
|
+
});
|
|
20375
|
+
applyDefaultGitWriteRules({
|
|
20376
|
+
config,
|
|
20377
|
+
filesystem,
|
|
20378
|
+
workspaceRootFilesystem
|
|
20379
|
+
});
|
|
19689
20380
|
if (Object.keys(workspaceRootFilesystem).length > 0) {
|
|
19690
20381
|
if (typeof filesystem[CODEX_WORKSPACE_ROOTS_KEY] === "string") logger?.warn(`"${CODEX_WORKSPACE_ROOTS_KEY}" is set as a direct filesystem access rule in the permissions, but it will be overwritten by workspace-root rules. Consider removing the direct "${CODEX_WORKSPACE_ROOTS_KEY}" entry.`);
|
|
19691
20382
|
if (Object.keys(workspaceRootFilesystem).some((pattern) => pattern.includes("**"))) filesystem.glob_scan_max_depth = CODEX_GLOB_SCAN_MAX_DEPTH;
|
|
@@ -19703,6 +20394,12 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19703
20394
|
...network ? { network } : {}
|
|
19704
20395
|
};
|
|
19705
20396
|
}
|
|
20397
|
+
function applyDefaultGitWriteRules({ config, filesystem, workspaceRootFilesystem }) {
|
|
20398
|
+
if (config.codexcli?.git_write_rules === false) return;
|
|
20399
|
+
if (config.codexcli?.base_permission_profile === CODEX_READ_ONLY_BASELINE) return;
|
|
20400
|
+
if (typeof filesystem[CODEX_WORKSPACE_ROOTS_KEY] === "string") return;
|
|
20401
|
+
for (const [pattern, access] of Object.entries(CODEX_GIT_WRITE_RULES)) workspaceRootFilesystem[pattern] ??= access;
|
|
20402
|
+
}
|
|
19706
20403
|
function convertCodexProfileToRulesync({ profile, domainsHadUnknown }) {
|
|
19707
20404
|
const permission = {};
|
|
19708
20405
|
if (profile?.filesystem) {
|
|
@@ -19714,7 +20411,10 @@ function convertCodexProfileToRulesync({ profile, domainsHadUnknown }) {
|
|
|
19714
20411
|
addRulesyncFilesystemRule(permission, pattern, access);
|
|
19715
20412
|
continue;
|
|
19716
20413
|
}
|
|
19717
|
-
if (isCodexFilesystemRuleTable(access)) for (const [nestedPattern, nestedAccess] of Object.entries(access))
|
|
20414
|
+
if (isCodexFilesystemRuleTable(access)) for (const [nestedPattern, nestedAccess] of Object.entries(access)) {
|
|
20415
|
+
if (pattern === CODEX_WORKSPACE_ROOTS_KEY && CODEX_GIT_WRITE_RULES[nestedPattern] === nestedAccess) continue;
|
|
20416
|
+
addRulesyncFilesystemRule(permission, nestedPattern, nestedAccess);
|
|
20417
|
+
}
|
|
19718
20418
|
}
|
|
19719
20419
|
}
|
|
19720
20420
|
if (profile?.network && profile.network.enabled !== false) {
|
|
@@ -19756,9 +20456,28 @@ function toCodexProfile(value) {
|
|
|
19756
20456
|
}
|
|
19757
20457
|
function warnAboutPreservedProfileState({ existingProfile, newProfile, existingDomainsHadUnknown, logger }) {
|
|
19758
20458
|
if (existingProfile !== void 0 && existingProfile.extends !== newProfile.extends) logger?.warn(`Existing "extends" value "${existingProfile.extends ?? "(none)"}" will be replaced by Rulesync-managed "${newProfile.extends ?? "(none)"}".`);
|
|
20459
|
+
warnAboutPreservedNetworkState({
|
|
20460
|
+
existingProfile,
|
|
20461
|
+
newProfile,
|
|
20462
|
+
logger
|
|
20463
|
+
});
|
|
20464
|
+
if (existingDomainsHadUnknown) logger?.warn(`Existing "network.domains" contained unrecognized values. These entries were skipped and will not be imported.`);
|
|
20465
|
+
}
|
|
20466
|
+
function networkHasAllowDomain(network) {
|
|
20467
|
+
return Object.values(network?.domains ?? {}).some((action) => action === "allow");
|
|
20468
|
+
}
|
|
20469
|
+
function warnAboutNetworkEnabledState({ existingProfile, newProfile, logger }) {
|
|
20470
|
+
if (existingProfile?.network?.enabled !== void 0 && newProfile.network?.enabled === void 0 && !networkHasAllowDomain(existingProfile.network)) logger?.warn(`Preserving existing "network.enabled" from config. Review this value manually as it may enable network access beyond the Rulesync-managed domain rules.`);
|
|
20471
|
+
if (existingProfile?.network?.enabled === false && newProfile.network?.enabled === true) logger?.warn(`Existing "network.enabled = false" will be replaced by Rulesync-managed "enabled = true" because the canonical model contains an allow domain.`);
|
|
20472
|
+
}
|
|
20473
|
+
function warnAboutPreservedNetworkState({ existingProfile, newProfile, logger }) {
|
|
19759
20474
|
if (existingProfile?.network?.unix_sockets !== void 0) logger?.warn(`Preserving existing "network.unix_sockets" from config. Review these entries manually as they may grant broad system access.`);
|
|
20475
|
+
warnAboutNetworkEnabledState({
|
|
20476
|
+
existingProfile,
|
|
20477
|
+
newProfile,
|
|
20478
|
+
logger
|
|
20479
|
+
});
|
|
19760
20480
|
if (existingProfile?.network?.mode !== void 0) logger?.warn(`Preserving existing "network.mode" from config. Review this value manually as it may grant broader network access than the Rulesync-managed domain rules.`);
|
|
19761
|
-
if (existingDomainsHadUnknown) logger?.warn(`Existing "network.domains" contained unrecognized values. These entries were skipped and will not be imported.`);
|
|
19762
20481
|
}
|
|
19763
20482
|
const MANAGED_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
19764
20483
|
"description",
|
|
@@ -19800,6 +20519,7 @@ function preserveUnmanagedProfileKeys({ rawExistingProfile, profile, logger }) {
|
|
|
19800
20519
|
function mergeWithExistingProfile({ newProfile, existingProfile }) {
|
|
19801
20520
|
if (!existingProfile) return newProfile;
|
|
19802
20521
|
const mergedNetwork = { ...newProfile.network };
|
|
20522
|
+
if (existingProfile.network?.enabled !== void 0 && mergedNetwork.enabled === void 0 && !networkHasAllowDomain(existingProfile.network)) mergedNetwork.enabled = existingProfile.network.enabled;
|
|
19803
20523
|
if (existingProfile.network?.mode !== void 0 && mergedNetwork.mode === void 0) mergedNetwork.mode = existingProfile.network.mode;
|
|
19804
20524
|
if (existingProfile.network?.unix_sockets !== void 0 && mergedNetwork.unix_sockets === void 0) mergedNetwork.unix_sockets = existingProfile.network.unix_sockets;
|
|
19805
20525
|
const hasNetwork = Object.keys(mergedNetwork).length > 0;
|
|
@@ -19851,7 +20571,7 @@ function computeCodexcliOverridePatch({ existing, override, logger }) {
|
|
|
19851
20571
|
const patch = {};
|
|
19852
20572
|
const allowed = new Set(CODEXCLI_OVERRIDE_KEYS);
|
|
19853
20573
|
for (const [key, value] of Object.entries(override ?? {})) {
|
|
19854
|
-
if (key === "base_permission_profile") continue;
|
|
20574
|
+
if (key === "base_permission_profile" || key === "git_write_rules") continue;
|
|
19855
20575
|
if (!allowed.has(key)) {
|
|
19856
20576
|
logger?.warn(`Codex CLI permission override key "${key}" is not managed and was skipped. "permissions"/"default_permissions" are owned by the canonical permission model and "mcp_servers" gating by the MCP feature.`);
|
|
19857
20577
|
continue;
|
|
@@ -19932,6 +20652,67 @@ function mapReadAction(action) {
|
|
|
19932
20652
|
function mapWriteAction(action) {
|
|
19933
20653
|
return action === "allow" ? "write" : "deny";
|
|
19934
20654
|
}
|
|
20655
|
+
/**
|
|
20656
|
+
* Merge the canonical read/edit/write category rules into one Codex access
|
|
20657
|
+
* level per path pattern (Codex models a single `deny` < `read` < `write`
|
|
20658
|
+
* level, with no `ask`).
|
|
20659
|
+
*
|
|
20660
|
+
* - `edit` and `write` collapse onto Codex's write side; when both carry the
|
|
20661
|
+
* same pattern, the more restrictive action wins (`deny` > `ask` > `allow`).
|
|
20662
|
+
* - `read: allow` + write-side `allow` → `"write"`.
|
|
20663
|
+
* - `read: allow` + write-side non-allow → `"read"` (readable but not
|
|
20664
|
+
* writable — exactly what Codex's `"read"` level expresses).
|
|
20665
|
+
* - `read` non-allow → `"deny"` regardless of the write side; a contradictory
|
|
20666
|
+
* write-side `allow` (unreadable but writable is not expressible in Codex)
|
|
20667
|
+
* is warned about.
|
|
20668
|
+
* - Single-category patterns keep the existing mapReadAction/mapWriteAction
|
|
20669
|
+
* mappings.
|
|
20670
|
+
*
|
|
20671
|
+
* Iteration order is read → edit → write with first-seen pattern order, so
|
|
20672
|
+
* the emitted table is stable regardless of the authored category order.
|
|
20673
|
+
* Note the merge is one-way: `"{path}" = "read"` imports back as
|
|
20674
|
+
* `read: allow` only (the explicit write-side deny is implied by Codex's
|
|
20675
|
+
* access level and not re-materialized).
|
|
20676
|
+
*/
|
|
20677
|
+
function mergeFilesystemCategoryRules({ categoryRules, logger }) {
|
|
20678
|
+
const readRules = categoryRules.read ?? {};
|
|
20679
|
+
const writeSideRestrictiveness = {
|
|
20680
|
+
deny: 2,
|
|
20681
|
+
ask: 1,
|
|
20682
|
+
allow: 0
|
|
20683
|
+
};
|
|
20684
|
+
const writeSideRules = {};
|
|
20685
|
+
for (const category of ["edit", "write"]) for (const [pattern, action] of Object.entries(categoryRules[category] ?? {})) {
|
|
20686
|
+
const existing = writeSideRules[pattern];
|
|
20687
|
+
if (existing === void 0 || writeSideRestrictiveness[action] > writeSideRestrictiveness[existing]) writeSideRules[pattern] = action;
|
|
20688
|
+
}
|
|
20689
|
+
const patterns = [];
|
|
20690
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20691
|
+
for (const pattern of [...Object.keys(readRules), ...Object.keys(writeSideRules)]) if (!seen.has(pattern)) {
|
|
20692
|
+
seen.add(pattern);
|
|
20693
|
+
patterns.push(pattern);
|
|
20694
|
+
}
|
|
20695
|
+
const merged = [];
|
|
20696
|
+
for (const pattern of patterns) {
|
|
20697
|
+
const readAction = readRules[pattern];
|
|
20698
|
+
const writeAction = writeSideRules[pattern];
|
|
20699
|
+
if (readAction === void 0) {
|
|
20700
|
+
merged.push([pattern, mapWriteAction(writeAction)]);
|
|
20701
|
+
continue;
|
|
20702
|
+
}
|
|
20703
|
+
if (writeAction === void 0) {
|
|
20704
|
+
merged.push([pattern, mapReadAction(readAction)]);
|
|
20705
|
+
continue;
|
|
20706
|
+
}
|
|
20707
|
+
if (readAction === "allow") {
|
|
20708
|
+
merged.push([pattern, writeAction === "allow" ? "write" : "read"]);
|
|
20709
|
+
continue;
|
|
20710
|
+
}
|
|
20711
|
+
if (writeAction === "allow") logger?.warn(`Codex CLI cannot express "writable but not readable": pattern "${pattern}" has read: ${readAction} and a write-side allow. Emitting "deny".`);
|
|
20712
|
+
merged.push([pattern, "deny"]);
|
|
20713
|
+
}
|
|
20714
|
+
return merged;
|
|
20715
|
+
}
|
|
19935
20716
|
function buildCodexBashRulesContent(config) {
|
|
19936
20717
|
const bashRules = config.permission.bash ?? {};
|
|
19937
20718
|
const entries = Object.entries(bashRules);
|
|
@@ -20883,7 +21664,7 @@ function convertRulesyncToGoosePermissionConfig({ config, logger }) {
|
|
|
20883
21664
|
function convertGoosePermissionConfigToRulesync(userPermission) {
|
|
20884
21665
|
const permission = {};
|
|
20885
21666
|
for (const key of GOOSE_PERMISSION_LIST_KEYS) {
|
|
20886
|
-
const toolNames = isStringArray(userPermission[key]) ? userPermission[key] : [];
|
|
21667
|
+
const toolNames = isStringArray$1(userPermission[key]) ? userPermission[key] : [];
|
|
20887
21668
|
const action = GOOSE_LIST_TO_ACTION[key];
|
|
20888
21669
|
for (const toolName of toolNames) {
|
|
20889
21670
|
const category = GOOSE_TO_RULESYNC_TOOL_NAME[toolName] ?? toolName;
|
|
@@ -21123,7 +21904,7 @@ const ACTION_RANK = {
|
|
|
21123
21904
|
* (mirrors the Cursor adapter's preservation of unmanaged types).
|
|
21124
21905
|
*/
|
|
21125
21906
|
function unmanagedEntries(existingPermission, key) {
|
|
21126
|
-
return (isStringArray(existingPermission[key]) ? existingPermission[key] : []).filter((entry) => parseGrokEntry(entry) === null);
|
|
21907
|
+
return (isStringArray$1(existingPermission[key]) ? existingPermission[key] : []).filter((entry) => parseGrokEntry(entry) === null);
|
|
21127
21908
|
}
|
|
21128
21909
|
/**
|
|
21129
21910
|
* Bucket canonical rules into Grok's `[permission]` allow/deny/ask arrays of
|
|
@@ -21164,9 +21945,9 @@ function buildGrokPermissionArrays(config, existingPermission, logger) {
|
|
|
21164
21945
|
* arrays resolves to the strictest action.
|
|
21165
21946
|
*/
|
|
21166
21947
|
function parseGrokPermissionArrays(permission) {
|
|
21167
|
-
const allow = isStringArray(permission.allow) ? permission.allow : void 0;
|
|
21168
|
-
const deny = isStringArray(permission.deny) ? permission.deny : void 0;
|
|
21169
|
-
const ask = isStringArray(permission.ask) ? permission.ask : void 0;
|
|
21948
|
+
const allow = isStringArray$1(permission.allow) ? permission.allow : void 0;
|
|
21949
|
+
const deny = isStringArray$1(permission.deny) ? permission.deny : void 0;
|
|
21950
|
+
const ask = isStringArray$1(permission.ask) ? permission.ask : void 0;
|
|
21170
21951
|
if ((allow?.length ?? 0) + (deny?.length ?? 0) + (ask?.length ?? 0) === 0) return null;
|
|
21171
21952
|
const result = {};
|
|
21172
21953
|
const apply = (entries, action) => {
|
|
@@ -22947,7 +23728,7 @@ function convertRovodevToolPermissionsToRulesync(toolPermissions) {
|
|
|
22947
23728
|
permission[category][CATCH_ALL_PATTERN$1] = value;
|
|
22948
23729
|
}
|
|
22949
23730
|
}
|
|
22950
|
-
if (isStringArray(toolPermissions.allowedExternalPaths)) for (const path of toolPermissions.allowedExternalPaths) {
|
|
23731
|
+
if (isStringArray$1(toolPermissions.allowedExternalPaths)) for (const path of toolPermissions.allowedExternalPaths) {
|
|
22951
23732
|
permission.read ??= {};
|
|
22952
23733
|
permission.read[path] = "allow";
|
|
22953
23734
|
}
|
|
@@ -23507,8 +24288,8 @@ var WarpPermissions = class WarpPermissions extends ToolPermissions {
|
|
|
23507
24288
|
const agents = isRecord(settings.agents) ? settings.agents : {};
|
|
23508
24289
|
const profiles = isRecord(agents.profiles) ? agents.profiles : {};
|
|
23509
24290
|
const config = convertWarpToRulesyncPermissions({
|
|
23510
|
-
allow: isStringArray(profiles[ALLOWLIST_KEY]) ? profiles[ALLOWLIST_KEY] : [],
|
|
23511
|
-
deny: isStringArray(profiles[DENYLIST_KEY]) ? profiles[DENYLIST_KEY] : []
|
|
24291
|
+
allow: isStringArray$1(profiles[ALLOWLIST_KEY]) ? profiles[ALLOWLIST_KEY] : [],
|
|
24292
|
+
deny: isStringArray$1(profiles[DENYLIST_KEY]) ? profiles[DENYLIST_KEY] : []
|
|
23512
24293
|
});
|
|
23513
24294
|
const warpOverride = {};
|
|
23514
24295
|
for (const key of WARP_OVERRIDE_KEYS) if (profiles[key] !== void 0) warpOverride[key] = profiles[key];
|
|
@@ -24088,9 +24869,6 @@ var PermissionsProcessor = class extends FeatureProcessor {
|
|
|
24088
24869
|
}
|
|
24089
24870
|
};
|
|
24090
24871
|
//#endregion
|
|
24091
|
-
//#region src/constants/general.ts
|
|
24092
|
-
const SKILL_FILE_NAME = "SKILL.md";
|
|
24093
|
-
//#endregion
|
|
24094
24872
|
//#region src/types/ai-dir.ts
|
|
24095
24873
|
var AiDir = class {
|
|
24096
24874
|
/**
|
|
@@ -24291,10 +25069,10 @@ var ToolSkill = class extends AiDir {
|
|
|
24291
25069
|
const settablePaths = getSettablePaths({ global });
|
|
24292
25070
|
const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
|
|
24293
25071
|
const skillDirPath = (0, node_path.join)(outputRoot, actualRelativeDirPath, dirName);
|
|
24294
|
-
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME);
|
|
24295
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25072
|
+
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1);
|
|
25073
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24296
25074
|
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24297
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25075
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24298
25076
|
return {
|
|
24299
25077
|
outputRoot,
|
|
24300
25078
|
relativeDirPath: actualRelativeDirPath,
|
|
@@ -24336,7 +25114,7 @@ var SimulatedSkill = class extends ToolSkill {
|
|
|
24336
25114
|
relativeDirPath,
|
|
24337
25115
|
dirName,
|
|
24338
25116
|
mainFile: {
|
|
24339
|
-
name: SKILL_FILE_NAME,
|
|
25117
|
+
name: SKILL_FILE_NAME$1,
|
|
24340
25118
|
body,
|
|
24341
25119
|
frontmatter: { ...frontmatter }
|
|
24342
25120
|
},
|
|
@@ -24394,12 +25172,12 @@ var SimulatedSkill = class extends ToolSkill {
|
|
|
24394
25172
|
const settablePaths = this.getSettablePaths();
|
|
24395
25173
|
const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
|
|
24396
25174
|
const skillDirPath = (0, node_path.join)(outputRoot, actualRelativeDirPath, dirName);
|
|
24397
|
-
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME);
|
|
24398
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25175
|
+
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1);
|
|
25176
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24399
25177
|
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24400
25178
|
const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
|
|
24401
25179
|
if (!result.success) throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
|
|
24402
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25180
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24403
25181
|
return {
|
|
24404
25182
|
outputRoot,
|
|
24405
25183
|
relativeDirPath: actualRelativeDirPath,
|
|
@@ -24609,7 +25387,7 @@ var RulesyncSkill = class RulesyncSkill extends AiDir {
|
|
|
24609
25387
|
relativeDirPath,
|
|
24610
25388
|
dirName,
|
|
24611
25389
|
mainFile: {
|
|
24612
|
-
name: SKILL_FILE_NAME,
|
|
25390
|
+
name: SKILL_FILE_NAME$1,
|
|
24613
25391
|
body,
|
|
24614
25392
|
frontmatter: { ...frontmatter }
|
|
24615
25393
|
},
|
|
@@ -24644,13 +25422,13 @@ var RulesyncSkill = class RulesyncSkill extends AiDir {
|
|
|
24644
25422
|
}
|
|
24645
25423
|
static async fromDir({ outputRoot = process.cwd(), relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName, global = false }) {
|
|
24646
25424
|
const skillDirPath = (0, node_path.join)(outputRoot, relativeDirPath, dirName);
|
|
24647
|
-
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME);
|
|
24648
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25425
|
+
const skillFilePath = (0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1);
|
|
25426
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24649
25427
|
const { frontmatter, body: content, hasFrontmatter } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24650
25428
|
if (!hasFrontmatter) throw new Error(`Missing frontmatter in ${skillFilePath}. Rulesync files must begin with a YAML frontmatter block delimited by '---'.`);
|
|
24651
25429
|
const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
|
|
24652
25430
|
if (!result.success) throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
|
|
24653
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25431
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24654
25432
|
return new RulesyncSkill({
|
|
24655
25433
|
outputRoot,
|
|
24656
25434
|
relativeDirPath,
|
|
@@ -24690,7 +25468,7 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24690
25468
|
relativeDirPath,
|
|
24691
25469
|
dirName,
|
|
24692
25470
|
mainFile: {
|
|
24693
|
-
name: SKILL_FILE_NAME,
|
|
25471
|
+
name: SKILL_FILE_NAME$1,
|
|
24694
25472
|
body,
|
|
24695
25473
|
frontmatter: { ...frontmatter }
|
|
24696
25474
|
},
|
|
@@ -24717,7 +25495,7 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24717
25495
|
validate() {
|
|
24718
25496
|
if (!this.mainFile) return {
|
|
24719
25497
|
success: false,
|
|
24720
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25498
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
24721
25499
|
};
|
|
24722
25500
|
const result = RovodevSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
24723
25501
|
if (!result.success) return {
|
|
@@ -24793,10 +25571,10 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24793
25571
|
const result = RovodevSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
24794
25572
|
if (!result.success) {
|
|
24795
25573
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
24796
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25574
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
24797
25575
|
}
|
|
24798
25576
|
if (result.data.name !== loaded.dirName) {
|
|
24799
|
-
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
25577
|
+
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
24800
25578
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
24801
25579
|
}
|
|
24802
25580
|
return new RovodevSkill({
|
|
@@ -24961,7 +25739,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
24961
25739
|
relativeDirPath,
|
|
24962
25740
|
dirName,
|
|
24963
25741
|
mainFile: {
|
|
24964
|
-
name: SKILL_FILE_NAME,
|
|
25742
|
+
name: SKILL_FILE_NAME$1,
|
|
24965
25743
|
body,
|
|
24966
25744
|
frontmatter: { ...frontmatter }
|
|
24967
25745
|
},
|
|
@@ -24985,7 +25763,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
24985
25763
|
validate() {
|
|
24986
25764
|
if (!this.mainFile) return {
|
|
24987
25765
|
success: false,
|
|
24988
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25766
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
24989
25767
|
};
|
|
24990
25768
|
const result = AgentsSkillsSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
24991
25769
|
if (!result.success) return {
|
|
@@ -25057,7 +25835,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
25057
25835
|
const result = AgentsSkillsSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25058
25836
|
if (!result.success) {
|
|
25059
25837
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25060
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25838
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25061
25839
|
}
|
|
25062
25840
|
return new this({
|
|
25063
25841
|
outputRoot: loaded.outputRoot,
|
|
@@ -25114,7 +25892,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25114
25892
|
relativeDirPath,
|
|
25115
25893
|
dirName,
|
|
25116
25894
|
mainFile: {
|
|
25117
|
-
name: SKILL_FILE_NAME,
|
|
25895
|
+
name: SKILL_FILE_NAME$1,
|
|
25118
25896
|
body,
|
|
25119
25897
|
frontmatter: { ...frontmatter }
|
|
25120
25898
|
},
|
|
@@ -25139,7 +25917,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25139
25917
|
validate() {
|
|
25140
25918
|
if (!this.mainFile) return {
|
|
25141
25919
|
success: false,
|
|
25142
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25920
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25143
25921
|
};
|
|
25144
25922
|
const result = AiassistantSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25145
25923
|
if (!result.success) return {
|
|
@@ -25199,7 +25977,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25199
25977
|
const result = AiassistantSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25200
25978
|
if (!result.success) {
|
|
25201
25979
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25202
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25980
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25203
25981
|
}
|
|
25204
25982
|
return new AiassistantSkill({
|
|
25205
25983
|
outputRoot: loaded.outputRoot,
|
|
@@ -25250,7 +26028,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25250
26028
|
relativeDirPath,
|
|
25251
26029
|
dirName,
|
|
25252
26030
|
mainFile: {
|
|
25253
|
-
name: SKILL_FILE_NAME,
|
|
26031
|
+
name: SKILL_FILE_NAME$1,
|
|
25254
26032
|
body,
|
|
25255
26033
|
frontmatter: { ...frontmatter }
|
|
25256
26034
|
},
|
|
@@ -25274,7 +26052,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25274
26052
|
validate() {
|
|
25275
26053
|
if (!this.mainFile) return {
|
|
25276
26054
|
success: false,
|
|
25277
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26055
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25278
26056
|
};
|
|
25279
26057
|
const result = AmpSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25280
26058
|
if (!result.success) return {
|
|
@@ -25334,7 +26112,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25334
26112
|
const result = AmpSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25335
26113
|
if (!result.success) {
|
|
25336
26114
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25337
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26115
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25338
26116
|
}
|
|
25339
26117
|
return new AmpSkill({
|
|
25340
26118
|
outputRoot: loaded.outputRoot,
|
|
@@ -25390,7 +26168,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25390
26168
|
relativeDirPath,
|
|
25391
26169
|
dirName,
|
|
25392
26170
|
mainFile: {
|
|
25393
|
-
name: SKILL_FILE_NAME,
|
|
26171
|
+
name: SKILL_FILE_NAME$1,
|
|
25394
26172
|
body,
|
|
25395
26173
|
frontmatter: { ...frontmatter }
|
|
25396
26174
|
},
|
|
@@ -25423,7 +26201,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25423
26201
|
validate() {
|
|
25424
26202
|
if (this.mainFile === void 0) return {
|
|
25425
26203
|
success: false,
|
|
25426
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26204
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25427
26205
|
};
|
|
25428
26206
|
const result = AntigravitySkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25429
26207
|
if (!result.success) return {
|
|
@@ -25483,7 +26261,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25483
26261
|
const result = AntigravitySkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25484
26262
|
if (!result.success) {
|
|
25485
26263
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25486
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26264
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25487
26265
|
}
|
|
25488
26266
|
return new this({
|
|
25489
26267
|
outputRoot: loaded.outputRoot,
|
|
@@ -25567,7 +26345,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25567
26345
|
relativeDirPath,
|
|
25568
26346
|
dirName,
|
|
25569
26347
|
mainFile: {
|
|
25570
|
-
name: SKILL_FILE_NAME,
|
|
26348
|
+
name: SKILL_FILE_NAME$1,
|
|
25571
26349
|
body,
|
|
25572
26350
|
frontmatter: { ...frontmatter }
|
|
25573
26351
|
},
|
|
@@ -25594,7 +26372,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25594
26372
|
validate() {
|
|
25595
26373
|
if (this.mainFile === void 0) return {
|
|
25596
26374
|
success: false,
|
|
25597
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26375
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25598
26376
|
};
|
|
25599
26377
|
const result = AugmentcodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25600
26378
|
if (!result.success) return {
|
|
@@ -25654,7 +26432,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25654
26432
|
const result = AugmentcodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25655
26433
|
if (!result.success) {
|
|
25656
26434
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25657
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26435
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25658
26436
|
}
|
|
25659
26437
|
return new AugmentcodeSkill({
|
|
25660
26438
|
outputRoot: loaded.outputRoot,
|
|
@@ -25795,7 +26573,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25795
26573
|
relativeDirPath,
|
|
25796
26574
|
dirName,
|
|
25797
26575
|
mainFile: {
|
|
25798
|
-
name: SKILL_FILE_NAME,
|
|
26576
|
+
name: SKILL_FILE_NAME$1,
|
|
25799
26577
|
body,
|
|
25800
26578
|
frontmatter: { ...frontmatter }
|
|
25801
26579
|
},
|
|
@@ -25822,7 +26600,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25822
26600
|
validate() {
|
|
25823
26601
|
if (this.mainFile === void 0) return {
|
|
25824
26602
|
success: false,
|
|
25825
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26603
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25826
26604
|
};
|
|
25827
26605
|
const result = ClaudecodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25828
26606
|
if (!result.success) return {
|
|
@@ -25910,7 +26688,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25910
26688
|
const result = ClaudecodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25911
26689
|
if (!result.success) {
|
|
25912
26690
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25913
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26691
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25914
26692
|
}
|
|
25915
26693
|
return new ClaudecodeSkill({
|
|
25916
26694
|
outputRoot: loaded.outputRoot,
|
|
@@ -25956,7 +26734,7 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
25956
26734
|
relativeDirPath,
|
|
25957
26735
|
dirName,
|
|
25958
26736
|
mainFile: {
|
|
25959
|
-
name: SKILL_FILE_NAME,
|
|
26737
|
+
name: SKILL_FILE_NAME$1,
|
|
25960
26738
|
body,
|
|
25961
26739
|
frontmatter: { ...frontmatter }
|
|
25962
26740
|
},
|
|
@@ -25980,7 +26758,7 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
25980
26758
|
validate() {
|
|
25981
26759
|
if (!this.mainFile) return {
|
|
25982
26760
|
success: false,
|
|
25983
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26761
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25984
26762
|
};
|
|
25985
26763
|
const result = ClineSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25986
26764
|
if (!result.success) return {
|
|
@@ -26044,10 +26822,10 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
26044
26822
|
const result = ClineSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26045
26823
|
if (!result.success) {
|
|
26046
26824
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26047
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26825
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26048
26826
|
}
|
|
26049
26827
|
if (result.data.name !== loaded.dirName) {
|
|
26050
|
-
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
26828
|
+
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
26051
26829
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
26052
26830
|
}
|
|
26053
26831
|
return new ClineSkill({
|
|
@@ -26161,7 +26939,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26161
26939
|
relativeDirPath,
|
|
26162
26940
|
dirName,
|
|
26163
26941
|
mainFile: {
|
|
26164
|
-
name: SKILL_FILE_NAME,
|
|
26942
|
+
name: SKILL_FILE_NAME$1,
|
|
26165
26943
|
body,
|
|
26166
26944
|
frontmatter: { ...frontmatter }
|
|
26167
26945
|
},
|
|
@@ -26185,7 +26963,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26185
26963
|
validate() {
|
|
26186
26964
|
if (!this.mainFile) return {
|
|
26187
26965
|
success: false,
|
|
26188
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26966
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26189
26967
|
};
|
|
26190
26968
|
const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26191
26969
|
if (!result.success) return {
|
|
@@ -26263,7 +27041,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26263
27041
|
const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26264
27042
|
if (!result.success) {
|
|
26265
27043
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26266
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27044
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26267
27045
|
}
|
|
26268
27046
|
return new CodexCliSkill({
|
|
26269
27047
|
outputRoot: loaded.outputRoot,
|
|
@@ -26315,7 +27093,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26315
27093
|
relativeDirPath,
|
|
26316
27094
|
dirName,
|
|
26317
27095
|
mainFile: {
|
|
26318
|
-
name: SKILL_FILE_NAME,
|
|
27096
|
+
name: SKILL_FILE_NAME$1,
|
|
26319
27097
|
body,
|
|
26320
27098
|
frontmatter: { ...frontmatter }
|
|
26321
27099
|
},
|
|
@@ -26340,7 +27118,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26340
27118
|
validate() {
|
|
26341
27119
|
if (!this.mainFile) return {
|
|
26342
27120
|
success: false,
|
|
26343
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27121
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26344
27122
|
};
|
|
26345
27123
|
const result = CopilotSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26346
27124
|
if (!result.success) return {
|
|
@@ -26407,7 +27185,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26407
27185
|
const result = CopilotSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26408
27186
|
if (!result.success) {
|
|
26409
27187
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26410
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27188
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26411
27189
|
}
|
|
26412
27190
|
return new CopilotSkill({
|
|
26413
27191
|
outputRoot: loaded.outputRoot,
|
|
@@ -26461,7 +27239,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26461
27239
|
relativeDirPath,
|
|
26462
27240
|
dirName,
|
|
26463
27241
|
mainFile: {
|
|
26464
|
-
name: SKILL_FILE_NAME,
|
|
27242
|
+
name: SKILL_FILE_NAME$1,
|
|
26465
27243
|
body,
|
|
26466
27244
|
frontmatter: { ...frontmatter }
|
|
26467
27245
|
},
|
|
@@ -26486,7 +27264,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26486
27264
|
validate() {
|
|
26487
27265
|
if (!this.mainFile) return {
|
|
26488
27266
|
success: false,
|
|
26489
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27267
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26490
27268
|
};
|
|
26491
27269
|
const result = CopilotcliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26492
27270
|
if (!result.success) return {
|
|
@@ -26555,7 +27333,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26555
27333
|
const result = CopilotcliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26556
27334
|
if (!result.success) {
|
|
26557
27335
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26558
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27336
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26559
27337
|
}
|
|
26560
27338
|
return new CopilotcliSkill({
|
|
26561
27339
|
outputRoot: loaded.outputRoot,
|
|
@@ -26605,7 +27383,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26605
27383
|
relativeDirPath,
|
|
26606
27384
|
dirName,
|
|
26607
27385
|
mainFile: {
|
|
26608
|
-
name: SKILL_FILE_NAME,
|
|
27386
|
+
name: SKILL_FILE_NAME$1,
|
|
26609
27387
|
body,
|
|
26610
27388
|
frontmatter: { ...frontmatter }
|
|
26611
27389
|
},
|
|
@@ -26629,7 +27407,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26629
27407
|
validate() {
|
|
26630
27408
|
if (!this.mainFile) return {
|
|
26631
27409
|
success: false,
|
|
26632
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27410
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26633
27411
|
};
|
|
26634
27412
|
const result = CursorSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26635
27413
|
if (!result.success) return {
|
|
@@ -26703,7 +27481,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26703
27481
|
const result = CursorSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26704
27482
|
if (!result.success) {
|
|
26705
27483
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26706
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27484
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26707
27485
|
}
|
|
26708
27486
|
return new CursorSkill({
|
|
26709
27487
|
outputRoot: loaded.outputRoot,
|
|
@@ -26750,7 +27528,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26750
27528
|
relativeDirPath,
|
|
26751
27529
|
dirName,
|
|
26752
27530
|
mainFile: {
|
|
26753
|
-
name: SKILL_FILE_NAME,
|
|
27531
|
+
name: SKILL_FILE_NAME$1,
|
|
26754
27532
|
body,
|
|
26755
27533
|
frontmatter: { ...frontmatter }
|
|
26756
27534
|
},
|
|
@@ -26774,7 +27552,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26774
27552
|
validate() {
|
|
26775
27553
|
if (!this.mainFile) return {
|
|
26776
27554
|
success: false,
|
|
26777
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27555
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26778
27556
|
};
|
|
26779
27557
|
const result = DeepagentsSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26780
27558
|
if (!result.success) return {
|
|
@@ -26850,7 +27628,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26850
27628
|
const result = DeepagentsSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26851
27629
|
if (!result.success) {
|
|
26852
27630
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26853
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27631
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26854
27632
|
}
|
|
26855
27633
|
return new DeepagentsSkill({
|
|
26856
27634
|
outputRoot: loaded.outputRoot,
|
|
@@ -26901,7 +27679,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26901
27679
|
relativeDirPath,
|
|
26902
27680
|
dirName,
|
|
26903
27681
|
mainFile: {
|
|
26904
|
-
name: SKILL_FILE_NAME,
|
|
27682
|
+
name: SKILL_FILE_NAME$1,
|
|
26905
27683
|
body,
|
|
26906
27684
|
frontmatter: { ...frontmatter }
|
|
26907
27685
|
},
|
|
@@ -26926,7 +27704,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26926
27704
|
validate() {
|
|
26927
27705
|
if (!this.mainFile) return {
|
|
26928
27706
|
success: false,
|
|
26929
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27707
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26930
27708
|
};
|
|
26931
27709
|
const result = DevinSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26932
27710
|
if (!result.success) return {
|
|
@@ -26978,6 +27756,18 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26978
27756
|
const targets = rulesyncSkill.getFrontmatter().targets;
|
|
26979
27757
|
return targets.includes("*") || targets.includes("devin");
|
|
26980
27758
|
}
|
|
27759
|
+
/**
|
|
27760
|
+
* Commands are emitted into this same skills tree as `<slug>/SKILL.md`
|
|
27761
|
+
* (see `DevinCommand`), so a directory matching a current rulesync command
|
|
27762
|
+
* slug is owned by the commands feature: it must not be imported as a
|
|
27763
|
+
* skill nor deleted as an orphan skill.
|
|
27764
|
+
*/
|
|
27765
|
+
static async isDirOwned({ dirName, inputRoot }) {
|
|
27766
|
+
return !await rulesyncCommandSlugExists({
|
|
27767
|
+
inputRoot,
|
|
27768
|
+
dirName
|
|
27769
|
+
});
|
|
27770
|
+
}
|
|
26981
27771
|
static async fromDir(params) {
|
|
26982
27772
|
const loaded = await this.loadSkillDirContent({
|
|
26983
27773
|
...params,
|
|
@@ -26986,7 +27776,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26986
27776
|
const result = DevinSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26987
27777
|
if (!result.success) {
|
|
26988
27778
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26989
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27779
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26990
27780
|
}
|
|
26991
27781
|
return new DevinSkill({
|
|
26992
27782
|
outputRoot: loaded.outputRoot,
|
|
@@ -27038,7 +27828,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27038
27828
|
relativeDirPath,
|
|
27039
27829
|
dirName,
|
|
27040
27830
|
mainFile: {
|
|
27041
|
-
name: SKILL_FILE_NAME,
|
|
27831
|
+
name: SKILL_FILE_NAME$1,
|
|
27042
27832
|
body,
|
|
27043
27833
|
frontmatter: { ...frontmatter }
|
|
27044
27834
|
},
|
|
@@ -27062,7 +27852,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27062
27852
|
validate() {
|
|
27063
27853
|
if (this.mainFile === void 0) return {
|
|
27064
27854
|
success: false,
|
|
27065
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27855
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27066
27856
|
};
|
|
27067
27857
|
const result = FactorydroidSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27068
27858
|
if (!result.success) return {
|
|
@@ -27137,7 +27927,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27137
27927
|
const result = FactorydroidSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27138
27928
|
if (!result.success) {
|
|
27139
27929
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27140
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27930
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27141
27931
|
}
|
|
27142
27932
|
return new FactorydroidSkill({
|
|
27143
27933
|
outputRoot: loaded.outputRoot,
|
|
@@ -27184,7 +27974,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27184
27974
|
relativeDirPath,
|
|
27185
27975
|
dirName,
|
|
27186
27976
|
mainFile: {
|
|
27187
|
-
name: SKILL_FILE_NAME,
|
|
27977
|
+
name: SKILL_FILE_NAME$1,
|
|
27188
27978
|
body,
|
|
27189
27979
|
frontmatter: { ...frontmatter }
|
|
27190
27980
|
},
|
|
@@ -27209,7 +27999,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27209
27999
|
validate() {
|
|
27210
28000
|
if (!this.mainFile) return {
|
|
27211
28001
|
success: false,
|
|
27212
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28002
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27213
28003
|
};
|
|
27214
28004
|
const result = GooseSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27215
28005
|
if (!result.success) return {
|
|
@@ -27269,7 +28059,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27269
28059
|
const result = GooseSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27270
28060
|
if (!result.success) {
|
|
27271
28061
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27272
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28062
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27273
28063
|
}
|
|
27274
28064
|
return new GooseSkill({
|
|
27275
28065
|
outputRoot: loaded.outputRoot,
|
|
@@ -27322,7 +28112,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27322
28112
|
relativeDirPath,
|
|
27323
28113
|
dirName,
|
|
27324
28114
|
mainFile: {
|
|
27325
|
-
name: SKILL_FILE_NAME,
|
|
28115
|
+
name: SKILL_FILE_NAME$1,
|
|
27326
28116
|
body,
|
|
27327
28117
|
frontmatter: { ...frontmatter }
|
|
27328
28118
|
},
|
|
@@ -27346,7 +28136,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27346
28136
|
validate() {
|
|
27347
28137
|
if (this.mainFile === void 0) return {
|
|
27348
28138
|
success: false,
|
|
27349
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28139
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27350
28140
|
};
|
|
27351
28141
|
const result = GrokcliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27352
28142
|
if (!result.success) return {
|
|
@@ -27406,7 +28196,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27406
28196
|
const result = GrokcliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27407
28197
|
if (!result.success) {
|
|
27408
28198
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27409
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28199
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27410
28200
|
}
|
|
27411
28201
|
return new GrokcliSkill({
|
|
27412
28202
|
outputRoot: loaded.outputRoot,
|
|
@@ -27441,6 +28231,18 @@ var HermesagentSkill = class extends AgentsSkillsSkill {
|
|
|
27441
28231
|
static getSettablePaths() {
|
|
27442
28232
|
return { relativeDirPath: HERMESAGENT_SKILLS_DIR_PATH };
|
|
27443
28233
|
}
|
|
28234
|
+
/**
|
|
28235
|
+
* Commands are emitted into this same skills tree as `<slug>/SKILL.md`
|
|
28236
|
+
* (see `HermesagentCommand`), so a directory matching a current rulesync
|
|
28237
|
+
* command slug is owned by the commands feature: it must not be imported
|
|
28238
|
+
* as a skill nor deleted as an orphan skill.
|
|
28239
|
+
*/
|
|
28240
|
+
static async isDirOwned({ dirName, inputRoot }) {
|
|
28241
|
+
return !await rulesyncCommandSlugExists({
|
|
28242
|
+
inputRoot,
|
|
28243
|
+
dirName
|
|
28244
|
+
});
|
|
28245
|
+
}
|
|
27444
28246
|
constructor(params) {
|
|
27445
28247
|
super({
|
|
27446
28248
|
...params,
|
|
@@ -27465,7 +28267,7 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27465
28267
|
relativeDirPath,
|
|
27466
28268
|
dirName,
|
|
27467
28269
|
mainFile: {
|
|
27468
|
-
name: SKILL_FILE_NAME,
|
|
28270
|
+
name: SKILL_FILE_NAME$1,
|
|
27469
28271
|
body,
|
|
27470
28272
|
frontmatter: { ...frontmatter }
|
|
27471
28273
|
},
|
|
@@ -27489,7 +28291,7 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27489
28291
|
validate() {
|
|
27490
28292
|
if (!this.mainFile) return {
|
|
27491
28293
|
success: false,
|
|
27492
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28294
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27493
28295
|
};
|
|
27494
28296
|
const result = JunieSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27495
28297
|
if (!result.success) return {
|
|
@@ -27553,10 +28355,10 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27553
28355
|
const result = JunieSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27554
28356
|
if (!result.success) {
|
|
27555
28357
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27556
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28358
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27557
28359
|
}
|
|
27558
28360
|
if (result.data.name !== loaded.dirName) {
|
|
27559
|
-
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
28361
|
+
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
27560
28362
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
27561
28363
|
}
|
|
27562
28364
|
return new JunieSkill({
|
|
@@ -27604,7 +28406,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27604
28406
|
relativeDirPath,
|
|
27605
28407
|
dirName,
|
|
27606
28408
|
mainFile: {
|
|
27607
|
-
name: SKILL_FILE_NAME,
|
|
28409
|
+
name: SKILL_FILE_NAME$1,
|
|
27608
28410
|
body,
|
|
27609
28411
|
frontmatter: { ...frontmatter }
|
|
27610
28412
|
},
|
|
@@ -27628,7 +28430,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27628
28430
|
validate() {
|
|
27629
28431
|
if (this.mainFile === void 0) return {
|
|
27630
28432
|
success: false,
|
|
27631
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28433
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27632
28434
|
};
|
|
27633
28435
|
const result = KiloSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27634
28436
|
if (!result.success) return {
|
|
@@ -27700,7 +28502,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27700
28502
|
const result = KiloSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27701
28503
|
if (!result.success) {
|
|
27702
28504
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27703
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28505
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27704
28506
|
}
|
|
27705
28507
|
return new KiloSkill({
|
|
27706
28508
|
outputRoot: loaded.outputRoot,
|
|
@@ -27746,7 +28548,7 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27746
28548
|
relativeDirPath,
|
|
27747
28549
|
dirName,
|
|
27748
28550
|
mainFile: {
|
|
27749
|
-
name: SKILL_FILE_NAME,
|
|
28551
|
+
name: SKILL_FILE_NAME$1,
|
|
27750
28552
|
body,
|
|
27751
28553
|
frontmatter: { ...frontmatter }
|
|
27752
28554
|
},
|
|
@@ -27770,7 +28572,7 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27770
28572
|
validate() {
|
|
27771
28573
|
if (!this.mainFile) return {
|
|
27772
28574
|
success: false,
|
|
27773
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28575
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27774
28576
|
};
|
|
27775
28577
|
const result = KiroSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27776
28578
|
if (!result.success) return {
|
|
@@ -27834,10 +28636,10 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27834
28636
|
const result = KiroSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27835
28637
|
if (!result.success) {
|
|
27836
28638
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27837
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28639
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27838
28640
|
}
|
|
27839
28641
|
if (result.data.name !== loaded.dirName) {
|
|
27840
|
-
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
28642
|
+
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
27841
28643
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
27842
28644
|
}
|
|
27843
28645
|
return new KiroSkill({
|
|
@@ -27920,7 +28722,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
27920
28722
|
relativeDirPath,
|
|
27921
28723
|
dirName,
|
|
27922
28724
|
mainFile: {
|
|
27923
|
-
name: SKILL_FILE_NAME,
|
|
28725
|
+
name: SKILL_FILE_NAME$1,
|
|
27924
28726
|
body,
|
|
27925
28727
|
frontmatter: { ...frontmatter }
|
|
27926
28728
|
},
|
|
@@ -27947,7 +28749,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
27947
28749
|
validate() {
|
|
27948
28750
|
if (this.mainFile === void 0) return {
|
|
27949
28751
|
success: false,
|
|
27950
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28752
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27951
28753
|
};
|
|
27952
28754
|
const result = OpenCodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27953
28755
|
if (!result.success) return {
|
|
@@ -28026,7 +28828,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
28026
28828
|
const result = OpenCodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28027
28829
|
if (!result.success) {
|
|
28028
28830
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28029
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28831
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28030
28832
|
}
|
|
28031
28833
|
return new OpenCodeSkill({
|
|
28032
28834
|
outputRoot: loaded.outputRoot,
|
|
@@ -28087,7 +28889,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28087
28889
|
relativeDirPath: resolvedDirPath,
|
|
28088
28890
|
dirName,
|
|
28089
28891
|
mainFile: {
|
|
28090
|
-
name: SKILL_FILE_NAME,
|
|
28892
|
+
name: SKILL_FILE_NAME$1,
|
|
28091
28893
|
body,
|
|
28092
28894
|
frontmatter: { ...frontmatter }
|
|
28093
28895
|
},
|
|
@@ -28112,7 +28914,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28112
28914
|
validate() {
|
|
28113
28915
|
if (!this.mainFile) return {
|
|
28114
28916
|
success: false,
|
|
28115
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28917
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28116
28918
|
};
|
|
28117
28919
|
const result = PiSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28118
28920
|
if (!result.success) return {
|
|
@@ -28187,7 +28989,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28187
28989
|
const result = PiSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28188
28990
|
if (!result.success) {
|
|
28189
28991
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28190
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28992
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28191
28993
|
}
|
|
28192
28994
|
return new PiSkill({
|
|
28193
28995
|
outputRoot: loaded.outputRoot,
|
|
@@ -28240,7 +29042,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28240
29042
|
relativeDirPath,
|
|
28241
29043
|
dirName,
|
|
28242
29044
|
mainFile: {
|
|
28243
|
-
name: SKILL_FILE_NAME,
|
|
29045
|
+
name: SKILL_FILE_NAME$1,
|
|
28244
29046
|
body,
|
|
28245
29047
|
frontmatter: { ...frontmatter }
|
|
28246
29048
|
},
|
|
@@ -28264,7 +29066,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28264
29066
|
validate() {
|
|
28265
29067
|
if (this.mainFile === void 0) return {
|
|
28266
29068
|
success: false,
|
|
28267
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29069
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28268
29070
|
};
|
|
28269
29071
|
const result = QwencodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28270
29072
|
if (!result.success) return {
|
|
@@ -28344,7 +29146,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28344
29146
|
const result = QwencodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28345
29147
|
if (!result.success) {
|
|
28346
29148
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28347
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29149
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28348
29150
|
}
|
|
28349
29151
|
return new QwencodeSkill({
|
|
28350
29152
|
outputRoot: loaded.outputRoot,
|
|
@@ -28394,7 +29196,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28394
29196
|
relativeDirPath,
|
|
28395
29197
|
dirName,
|
|
28396
29198
|
mainFile: {
|
|
28397
|
-
name: SKILL_FILE_NAME,
|
|
29199
|
+
name: SKILL_FILE_NAME$1,
|
|
28398
29200
|
body,
|
|
28399
29201
|
frontmatter: { ...frontmatter }
|
|
28400
29202
|
},
|
|
@@ -28418,7 +29220,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28418
29220
|
validate() {
|
|
28419
29221
|
if (this.mainFile === void 0) return {
|
|
28420
29222
|
success: false,
|
|
28421
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29223
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28422
29224
|
};
|
|
28423
29225
|
const result = ReasonixSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28424
29226
|
if (!result.success) return {
|
|
@@ -28478,7 +29280,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28478
29280
|
const result = ReasonixSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28479
29281
|
if (!result.success) {
|
|
28480
29282
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28481
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29283
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28482
29284
|
}
|
|
28483
29285
|
return new ReasonixSkill({
|
|
28484
29286
|
outputRoot: loaded.outputRoot,
|
|
@@ -28491,6 +29293,24 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28491
29293
|
global: loaded.global
|
|
28492
29294
|
});
|
|
28493
29295
|
}
|
|
29296
|
+
/**
|
|
29297
|
+
* Whether the skill directory belongs to the skills feature.
|
|
29298
|
+
*
|
|
29299
|
+
* `.reasonix/skills/` is shared with the subagents feature: a directory whose
|
|
29300
|
+
* SKILL.md declares `runAs: subagent` is a subagent profile, not a regular
|
|
29301
|
+
* skill, so it must be neither imported as a skill nor deleted as an orphan
|
|
29302
|
+
* skill. Directories without a readable/parsable SKILL.md keep the default
|
|
29303
|
+
* skills-feature ownership, matching the previous behavior for such dirs.
|
|
29304
|
+
*/
|
|
29305
|
+
static async isDirOwned({ outputRoot, relativeDirPath, dirName }) {
|
|
29306
|
+
const skillFilePath = (0, node_path.join)(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
29307
|
+
try {
|
|
29308
|
+
const { frontmatter } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
29309
|
+
return frontmatter["runAs"] !== REASONIX_SUBAGENT_RUN_AS;
|
|
29310
|
+
} catch {
|
|
29311
|
+
return true;
|
|
29312
|
+
}
|
|
29313
|
+
}
|
|
28494
29314
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, dirName, global = false }) {
|
|
28495
29315
|
return new ReasonixSkill({
|
|
28496
29316
|
outputRoot,
|
|
@@ -28533,7 +29353,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28533
29353
|
relativeDirPath,
|
|
28534
29354
|
dirName,
|
|
28535
29355
|
mainFile: {
|
|
28536
|
-
name: SKILL_FILE_NAME,
|
|
29356
|
+
name: SKILL_FILE_NAME$1,
|
|
28537
29357
|
body,
|
|
28538
29358
|
frontmatter: { ...frontmatter }
|
|
28539
29359
|
},
|
|
@@ -28557,7 +29377,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28557
29377
|
validate() {
|
|
28558
29378
|
if (!this.mainFile) return {
|
|
28559
29379
|
success: false,
|
|
28560
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29380
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28561
29381
|
};
|
|
28562
29382
|
const result = ReplitSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28563
29383
|
if (!result.success) return {
|
|
@@ -28625,7 +29445,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28625
29445
|
const result = ReplitSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28626
29446
|
if (!result.success) {
|
|
28627
29447
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28628
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29448
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28629
29449
|
}
|
|
28630
29450
|
return new ReplitSkill({
|
|
28631
29451
|
outputRoot: loaded.outputRoot,
|
|
@@ -28672,7 +29492,7 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28672
29492
|
relativeDirPath,
|
|
28673
29493
|
dirName,
|
|
28674
29494
|
mainFile: {
|
|
28675
|
-
name: SKILL_FILE_NAME,
|
|
29495
|
+
name: SKILL_FILE_NAME$1,
|
|
28676
29496
|
body,
|
|
28677
29497
|
frontmatter: { ...frontmatter }
|
|
28678
29498
|
},
|
|
@@ -28696,7 +29516,7 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28696
29516
|
validate() {
|
|
28697
29517
|
if (!this.mainFile) return {
|
|
28698
29518
|
success: false,
|
|
28699
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29519
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28700
29520
|
};
|
|
28701
29521
|
const result = RooSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28702
29522
|
if (!result.success) return {
|
|
@@ -28760,10 +29580,10 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28760
29580
|
const result = RooSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28761
29581
|
if (!result.success) {
|
|
28762
29582
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28763
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29583
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28764
29584
|
}
|
|
28765
29585
|
if (result.data.name !== loaded.dirName) {
|
|
28766
|
-
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
29586
|
+
const skillFilePath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
28767
29587
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
28768
29588
|
}
|
|
28769
29589
|
return new RooSkill({
|
|
@@ -28980,7 +29800,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
28980
29800
|
relativeDirPath,
|
|
28981
29801
|
dirName,
|
|
28982
29802
|
mainFile: {
|
|
28983
|
-
name: SKILL_FILE_NAME,
|
|
29803
|
+
name: SKILL_FILE_NAME$1,
|
|
28984
29804
|
body,
|
|
28985
29805
|
frontmatter: { ...frontmatter }
|
|
28986
29806
|
},
|
|
@@ -29007,7 +29827,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
29007
29827
|
validate() {
|
|
29008
29828
|
if (!this.mainFile) return {
|
|
29009
29829
|
success: false,
|
|
29010
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29830
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
29011
29831
|
};
|
|
29012
29832
|
const result = VibeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
29013
29833
|
if (!result.success) return {
|
|
@@ -29071,7 +29891,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
29071
29891
|
const result = VibeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29072
29892
|
if (!result.success) {
|
|
29073
29893
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29074
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29894
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29075
29895
|
}
|
|
29076
29896
|
return new VibeSkill({
|
|
29077
29897
|
outputRoot: loaded.outputRoot,
|
|
@@ -29127,7 +29947,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29127
29947
|
relativeDirPath,
|
|
29128
29948
|
dirName,
|
|
29129
29949
|
mainFile: {
|
|
29130
|
-
name: SKILL_FILE_NAME,
|
|
29950
|
+
name: SKILL_FILE_NAME$1,
|
|
29131
29951
|
body,
|
|
29132
29952
|
frontmatter: { ...frontmatter }
|
|
29133
29953
|
},
|
|
@@ -29151,7 +29971,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29151
29971
|
validate() {
|
|
29152
29972
|
if (this.mainFile === void 0) return {
|
|
29153
29973
|
success: false,
|
|
29154
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29974
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
29155
29975
|
};
|
|
29156
29976
|
const result = WarpSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
29157
29977
|
if (!result.success) return {
|
|
@@ -29211,7 +30031,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29211
30031
|
const result = WarpSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29212
30032
|
if (!result.success) {
|
|
29213
30033
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29214
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
30034
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29215
30035
|
}
|
|
29216
30036
|
return new WarpSkill({
|
|
29217
30037
|
outputRoot: loaded.outputRoot,
|
|
@@ -29259,7 +30079,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29259
30079
|
relativeDirPath,
|
|
29260
30080
|
dirName,
|
|
29261
30081
|
mainFile: {
|
|
29262
|
-
name: SKILL_FILE_NAME,
|
|
30082
|
+
name: SKILL_FILE_NAME$1,
|
|
29263
30083
|
body,
|
|
29264
30084
|
frontmatter: { ...frontmatter }
|
|
29265
30085
|
},
|
|
@@ -29283,7 +30103,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29283
30103
|
validate() {
|
|
29284
30104
|
if (!this.mainFile) return {
|
|
29285
30105
|
success: false,
|
|
29286
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
30106
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
29287
30107
|
};
|
|
29288
30108
|
const result = ZedSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
29289
30109
|
if (!result.success) return {
|
|
@@ -29352,7 +30172,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29352
30172
|
const result = ZedSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29353
30173
|
if (!result.success) {
|
|
29354
30174
|
const skillDirPath = (0, node_path.join)(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29355
|
-
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
30175
|
+
throw new Error(`Invalid frontmatter in ${(0, node_path.join)(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29356
30176
|
}
|
|
29357
30177
|
return new ZedSkill({
|
|
29358
30178
|
outputRoot: loaded.outputRoot,
|
|
@@ -29789,6 +30609,12 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
29789
30609
|
for (const dirPath of dirPaths) {
|
|
29790
30610
|
const dirName = (0, node_path.basename)(dirPath);
|
|
29791
30611
|
if (seenDirNames.has(dirName)) continue;
|
|
30612
|
+
if (factory.class.isDirOwned && !await factory.class.isDirOwned({
|
|
30613
|
+
outputRoot: this.outputRoot,
|
|
30614
|
+
relativeDirPath: root,
|
|
30615
|
+
dirName,
|
|
30616
|
+
inputRoot: this.inputRoot
|
|
30617
|
+
})) continue;
|
|
29792
30618
|
seenDirNames.add(dirName);
|
|
29793
30619
|
loadEntries.push({
|
|
29794
30620
|
root,
|
|
@@ -29815,6 +30641,12 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
29815
30641
|
const dirPaths = await findFilesByGlobs((0, node_path.join)(skillsDirPath, "*"), { type: "dir" });
|
|
29816
30642
|
for (const dirPath of dirPaths) {
|
|
29817
30643
|
const dirName = (0, node_path.basename)(dirPath);
|
|
30644
|
+
if (factory.class.isDirOwned && !await factory.class.isDirOwned({
|
|
30645
|
+
outputRoot: this.outputRoot,
|
|
30646
|
+
relativeDirPath: root,
|
|
30647
|
+
dirName,
|
|
30648
|
+
inputRoot: this.inputRoot
|
|
30649
|
+
})) continue;
|
|
29818
30650
|
const toolSkill = factory.class.forDeletion({
|
|
29819
30651
|
outputRoot: this.outputRoot,
|
|
29820
30652
|
relativeDirPath: root,
|
|
@@ -33114,6 +33946,188 @@ var OpenCodeSubagent = class OpenCodeSubagent extends OpenCodeStyleSubagent {
|
|
|
33114
33946
|
}
|
|
33115
33947
|
};
|
|
33116
33948
|
//#endregion
|
|
33949
|
+
//#region src/features/subagents/reasonix-subagent.ts
|
|
33950
|
+
const ReasonixSubagentFrontmatterSchema = zod_mini.z.looseObject({
|
|
33951
|
+
name: zod_mini.z.string(),
|
|
33952
|
+
description: zod_mini.z.optional(zod_mini.z.string()),
|
|
33953
|
+
invocation: zod_mini.z.optional(zod_mini.z.string()),
|
|
33954
|
+
runAs: zod_mini.z.optional(zod_mini.z.string()),
|
|
33955
|
+
model: zod_mini.z.optional(zod_mini.z.string()),
|
|
33956
|
+
effort: zod_mini.z.optional(zod_mini.z.string()),
|
|
33957
|
+
"allowed-tools": zod_mini.z.optional(zod_mini.z.array(zod_mini.z.string())),
|
|
33958
|
+
color: zod_mini.z.optional(zod_mini.z.string())
|
|
33959
|
+
});
|
|
33960
|
+
/**
|
|
33961
|
+
* Represents a DeepSeek-Reasonix subagent profile.
|
|
33962
|
+
*
|
|
33963
|
+
* Reasonix discovers subagents as directory-layout Skills (`<name>/SKILL.md`)
|
|
33964
|
+
* under `.reasonix/skills/` (project) and `~/.reasonix/skills/` (global); the
|
|
33965
|
+
* global scope is served by the processor supplying the home directory as
|
|
33966
|
+
* outputRoot, so the relative directory path is identical for both scopes. A
|
|
33967
|
+
* subagent is a Skill whose frontmatter declares `invocation: manual` and
|
|
33968
|
+
* `runAs: subagent`.
|
|
33969
|
+
*
|
|
33970
|
+
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/SUBAGENT_PROFILES.md
|
|
33971
|
+
*/
|
|
33972
|
+
var ReasonixSubagent = class ReasonixSubagent extends ToolSubagent {
|
|
33973
|
+
frontmatter;
|
|
33974
|
+
body;
|
|
33975
|
+
constructor({ frontmatter, body, fileContent, ...rest }) {
|
|
33976
|
+
if (rest.validate !== false) {
|
|
33977
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
33978
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${(0, node_path.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
33979
|
+
}
|
|
33980
|
+
super({
|
|
33981
|
+
...rest,
|
|
33982
|
+
fileContent: fileContent ?? stringifyFrontmatter(body, frontmatter)
|
|
33983
|
+
});
|
|
33984
|
+
this.frontmatter = frontmatter;
|
|
33985
|
+
this.body = body;
|
|
33986
|
+
}
|
|
33987
|
+
static getSettablePaths({ global: _global = false } = {}) {
|
|
33988
|
+
return { relativeDirPath: REASONIX_SUBAGENTS_DIR_PATH };
|
|
33989
|
+
}
|
|
33990
|
+
getFrontmatter() {
|
|
33991
|
+
return this.frontmatter;
|
|
33992
|
+
}
|
|
33993
|
+
getBody() {
|
|
33994
|
+
return this.body;
|
|
33995
|
+
}
|
|
33996
|
+
toRulesyncSubagent() {
|
|
33997
|
+
const { name, description, invocation: _invocation, runAs: _runAs, ...restFields } = this.frontmatter;
|
|
33998
|
+
const reasonixSection = { ...restFields };
|
|
33999
|
+
const rulesyncFrontmatter = {
|
|
34000
|
+
targets: ["*"],
|
|
34001
|
+
name,
|
|
34002
|
+
description,
|
|
34003
|
+
...Object.keys(reasonixSection).length > 0 && { reasonix: reasonixSection }
|
|
34004
|
+
};
|
|
34005
|
+
return new RulesyncSubagent({
|
|
34006
|
+
outputRoot: this.getOutputRoot(),
|
|
34007
|
+
frontmatter: rulesyncFrontmatter,
|
|
34008
|
+
body: this.body,
|
|
34009
|
+
relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
|
|
34010
|
+
relativeFilePath: `${this.getSubagentName()}.md`,
|
|
34011
|
+
validate: true
|
|
34012
|
+
});
|
|
34013
|
+
}
|
|
34014
|
+
/**
|
|
34015
|
+
* Derive the subagent name from this instance's relative file path.
|
|
34016
|
+
*
|
|
34017
|
+
* The tool-side layout is `<name>/SKILL.md`, so the name is the parent
|
|
34018
|
+
* directory of the file. If the path is unexpectedly flat (e.g. a legacy
|
|
34019
|
+
* `<name>.md`), fall back to the basename without extension.
|
|
34020
|
+
*/
|
|
34021
|
+
getSubagentName() {
|
|
34022
|
+
const relativeFilePath = this.getRelativeFilePath();
|
|
34023
|
+
const dir = (0, node_path.dirname)(relativeFilePath);
|
|
34024
|
+
if (dir && dir !== ".") return (0, node_path.basename)(dir);
|
|
34025
|
+
return (0, node_path.basename)(relativeFilePath, (0, node_path.extname)(relativeFilePath));
|
|
34026
|
+
}
|
|
34027
|
+
static fromRulesyncSubagent({ outputRoot = process.cwd(), rulesyncSubagent, validate = true, global = false }) {
|
|
34028
|
+
const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
|
|
34029
|
+
const reasonixSection = this.filterToolSpecificSection(rulesyncFrontmatter.reasonix ?? {}, ["name", "description"]);
|
|
34030
|
+
const rawReasonixFrontmatter = {
|
|
34031
|
+
name: rulesyncFrontmatter.name,
|
|
34032
|
+
description: rulesyncFrontmatter.description,
|
|
34033
|
+
...reasonixSection,
|
|
34034
|
+
invocation: REASONIX_SUBAGENT_INVOCATION,
|
|
34035
|
+
runAs: REASONIX_SUBAGENT_RUN_AS
|
|
34036
|
+
};
|
|
34037
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(rawReasonixFrontmatter);
|
|
34038
|
+
if (!result.success) throw new Error(`Invalid reasonix subagent frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(result.error)}`);
|
|
34039
|
+
const reasonixFrontmatter = result.data;
|
|
34040
|
+
const body = rulesyncSubagent.getBody();
|
|
34041
|
+
const fileContent = stringifyFrontmatter(body, reasonixFrontmatter);
|
|
34042
|
+
const paths = this.getSettablePaths({ global });
|
|
34043
|
+
const subagentName = (0, node_path.basename)(rulesyncSubagent.getRelativeFilePath(), (0, node_path.extname)(rulesyncSubagent.getRelativeFilePath()));
|
|
34044
|
+
return new ReasonixSubagent({
|
|
34045
|
+
outputRoot,
|
|
34046
|
+
frontmatter: reasonixFrontmatter,
|
|
34047
|
+
body,
|
|
34048
|
+
relativeDirPath: paths.relativeDirPath,
|
|
34049
|
+
relativeFilePath: (0, node_path.join)(subagentName, SKILL_FILE_NAME$1),
|
|
34050
|
+
fileContent,
|
|
34051
|
+
validate,
|
|
34052
|
+
global
|
|
34053
|
+
});
|
|
34054
|
+
}
|
|
34055
|
+
validate() {
|
|
34056
|
+
if (!this.frontmatter) return {
|
|
34057
|
+
success: true,
|
|
34058
|
+
error: null
|
|
34059
|
+
};
|
|
34060
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(this.frontmatter);
|
|
34061
|
+
if (result.success) return {
|
|
34062
|
+
success: true,
|
|
34063
|
+
error: null
|
|
34064
|
+
};
|
|
34065
|
+
else return {
|
|
34066
|
+
success: false,
|
|
34067
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${(0, node_path.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
34068
|
+
};
|
|
34069
|
+
}
|
|
34070
|
+
static isTargetedByRulesyncSubagent(rulesyncSubagent) {
|
|
34071
|
+
return this.isTargetedByRulesyncSubagentDefault({
|
|
34072
|
+
rulesyncSubagent,
|
|
34073
|
+
toolTarget: "reasonix"
|
|
34074
|
+
});
|
|
34075
|
+
}
|
|
34076
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
34077
|
+
const paths = this.getSettablePaths({ global });
|
|
34078
|
+
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
34079
|
+
const fileContent = await readFileContent(filePath);
|
|
34080
|
+
const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
|
|
34081
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
34082
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
34083
|
+
return new ReasonixSubagent({
|
|
34084
|
+
outputRoot,
|
|
34085
|
+
relativeDirPath: paths.relativeDirPath,
|
|
34086
|
+
relativeFilePath,
|
|
34087
|
+
frontmatter: result.data,
|
|
34088
|
+
body: content.trim(),
|
|
34089
|
+
fileContent,
|
|
34090
|
+
validate,
|
|
34091
|
+
global
|
|
34092
|
+
});
|
|
34093
|
+
}
|
|
34094
|
+
/**
|
|
34095
|
+
* Whether the SKILL.md at the given path is a subagent profile.
|
|
34096
|
+
*
|
|
34097
|
+
* `.reasonix/skills/` is shared with the skills feature: a regular skill and
|
|
34098
|
+
* a subagent profile differ only by their frontmatter markers. Only files
|
|
34099
|
+
* carrying `runAs: subagent` belong to this feature, so regular skills are
|
|
34100
|
+
* neither imported as subagents nor deleted as orphans by the subagents
|
|
34101
|
+
* feature. `runAs` alone is checked (not `invocation`) because it is the
|
|
34102
|
+
* marker that switches the execution mode; generation always emits both.
|
|
34103
|
+
* Unreadable or unparsable files are treated as not owned, erring on the
|
|
34104
|
+
* side of leaving foreign files untouched.
|
|
34105
|
+
*/
|
|
34106
|
+
static async isFileOwned({ outputRoot, relativeDirPath, relativeFilePath }) {
|
|
34107
|
+
const filePath = (0, node_path.join)(outputRoot, relativeDirPath, relativeFilePath);
|
|
34108
|
+
try {
|
|
34109
|
+
const { frontmatter } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
34110
|
+
return frontmatter["runAs"] === REASONIX_SUBAGENT_RUN_AS;
|
|
34111
|
+
} catch {
|
|
34112
|
+
return false;
|
|
34113
|
+
}
|
|
34114
|
+
}
|
|
34115
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
34116
|
+
return new ReasonixSubagent({
|
|
34117
|
+
outputRoot,
|
|
34118
|
+
relativeDirPath,
|
|
34119
|
+
relativeFilePath,
|
|
34120
|
+
frontmatter: {
|
|
34121
|
+
name: "",
|
|
34122
|
+
description: ""
|
|
34123
|
+
},
|
|
34124
|
+
body: "",
|
|
34125
|
+
fileContent: "",
|
|
34126
|
+
validate: false
|
|
34127
|
+
});
|
|
34128
|
+
}
|
|
34129
|
+
};
|
|
34130
|
+
//#endregion
|
|
33117
34131
|
//#region src/features/subagents/roo-subagent.ts
|
|
33118
34132
|
/**
|
|
33119
34133
|
* Default tool groups assigned to a generated mode when the rulesync source
|
|
@@ -33748,6 +34762,14 @@ const toolSubagentFactories = /* @__PURE__ */ new Map([
|
|
|
33748
34762
|
filePattern: "*.md"
|
|
33749
34763
|
}
|
|
33750
34764
|
}],
|
|
34765
|
+
["reasonix", {
|
|
34766
|
+
class: ReasonixSubagent,
|
|
34767
|
+
meta: {
|
|
34768
|
+
supportsSimulated: false,
|
|
34769
|
+
supportsGlobal: true,
|
|
34770
|
+
filePattern: (0, node_path.join)("*", "SKILL.md")
|
|
34771
|
+
}
|
|
34772
|
+
}],
|
|
33751
34773
|
["roo", {
|
|
33752
34774
|
class: RooSubagent,
|
|
33753
34775
|
meta: {
|
|
@@ -33900,8 +34922,17 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
33900
34922
|
const baseDir = (0, node_path.join)(this.outputRoot, dirPath);
|
|
33901
34923
|
const subagentFilePaths = await findFilesByGlobs((0, node_path.join)(baseDir, factory.meta.filePattern));
|
|
33902
34924
|
const toRelativeFilePath = (path) => (0, node_path.relative)(baseDir, path);
|
|
34925
|
+
let ownedFilePaths = subagentFilePaths;
|
|
34926
|
+
if (factory.class.isFileOwned) {
|
|
34927
|
+
const ownership = await Promise.all(subagentFilePaths.map((path) => factory.class.isFileOwned({
|
|
34928
|
+
outputRoot: this.outputRoot,
|
|
34929
|
+
relativeDirPath: dirPath,
|
|
34930
|
+
relativeFilePath: toRelativeFilePath(path)
|
|
34931
|
+
})));
|
|
34932
|
+
ownedFilePaths = subagentFilePaths.filter((_, index) => ownership[index]);
|
|
34933
|
+
}
|
|
33903
34934
|
if (forDeletion) {
|
|
33904
|
-
toolSubagents.push(...
|
|
34935
|
+
toolSubagents.push(...ownedFilePaths.map((path) => factory.class.forDeletion({
|
|
33905
34936
|
outputRoot: this.outputRoot,
|
|
33906
34937
|
relativeDirPath: dirPath,
|
|
33907
34938
|
relativeFilePath: toRelativeFilePath(path),
|
|
@@ -33909,7 +34940,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
33909
34940
|
})).filter((subagent) => subagent.isDeletable()));
|
|
33910
34941
|
continue;
|
|
33911
34942
|
}
|
|
33912
|
-
const loaded = await Promise.all(
|
|
34943
|
+
const loaded = await Promise.all(ownedFilePaths.map((path) => factory.class.fromFile({
|
|
33913
34944
|
outputRoot: this.outputRoot,
|
|
33914
34945
|
relativeDirPath: dirPath,
|
|
33915
34946
|
relativeFilePath: toRelativeFilePath(path),
|
|
@@ -34021,6 +35052,7 @@ const RulesyncRuleFrontmatterSchema = zod_mini.z.object({
|
|
|
34021
35052
|
name: zod_mini.z.optional(zod_mini.z.string()),
|
|
34022
35053
|
description: zod_mini.z.optional(zod_mini.z.string())
|
|
34023
35054
|
})),
|
|
35055
|
+
pi: zod_mini.z.optional(zod_mini.z.looseObject({ systemPrompt: zod_mini.z.optional(zod_mini.z.enum(["append"])) })),
|
|
34024
35056
|
takt: zod_mini.z.optional(zod_mini.z.looseObject({
|
|
34025
35057
|
name: zod_mini.z.optional(zod_mini.z.string()),
|
|
34026
35058
|
extends: zod_mini.z.optional(zod_mini.z.string()),
|
|
@@ -34184,6 +35216,16 @@ var ToolRule = class extends ToolFile {
|
|
|
34184
35216
|
isRoot() {
|
|
34185
35217
|
return this.root;
|
|
34186
35218
|
}
|
|
35219
|
+
/**
|
|
35220
|
+
* Whether this rule must be left out of the root rule's reference/MCP
|
|
35221
|
+
* instruction listings even though it is a non-root survivor. Used by files
|
|
35222
|
+
* the tool loads through its own mechanism (e.g. Pi's `APPEND_SYSTEM.md`,
|
|
35223
|
+
* which Pi appends to the system prompt itself — referencing it from
|
|
35224
|
+
* `AGENTS.md` would double-load the content).
|
|
35225
|
+
*/
|
|
35226
|
+
isExcludedFromRootReferences() {
|
|
35227
|
+
return false;
|
|
35228
|
+
}
|
|
34187
35229
|
getDescription() {
|
|
34188
35230
|
return this.description;
|
|
34189
35231
|
}
|
|
@@ -36530,6 +37572,15 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
36530
37572
|
* is `undefined`). This mirrors the grokcli, warp, and deepagents targets.
|
|
36531
37573
|
*
|
|
36532
37574
|
* Goose uses plain markdown files (.goosehints) without frontmatter.
|
|
37575
|
+
*
|
|
37576
|
+
* Global scope emits only `~/.config/goose/.goosehints`. Goose v1.41.0 (PR
|
|
37577
|
+
* block/goose#9736) additionally loads the vendor-neutral
|
|
37578
|
+
* `~/.agents/AGENTS.md` alongside the config-dir hints, but rulesync
|
|
37579
|
+
* deliberately does not emit that shared path from the goose target: the
|
|
37580
|
+
* config-dir hints remain fully loaded (no capability loss), and the
|
|
37581
|
+
* cross-tool `~/.agents/AGENTS.md` is already written by targets that own it
|
|
37582
|
+
* (e.g. cline in global mode) — a second writer would need cross-target
|
|
37583
|
+
* shared-file coordination for zero gain (decision recorded in issue #2207).
|
|
36533
37584
|
*/
|
|
36534
37585
|
var GooseRule = class GooseRule extends ToolRule {
|
|
36535
37586
|
static getSettablePaths({ global } = {}) {
|
|
@@ -36731,14 +37782,21 @@ var HermesagentRule = class HermesagentRule extends ToolRule {
|
|
|
36731
37782
|
/**
|
|
36732
37783
|
* Rule generator for JetBrains Junie AI coding agent
|
|
36733
37784
|
*
|
|
36734
|
-
* Generates `.junie/AGENTS.md` files based on rulesync rule content.
|
|
36735
|
-
*
|
|
36736
|
-
*
|
|
36737
|
-
*
|
|
36738
|
-
*
|
|
36739
|
-
*
|
|
36740
|
-
*
|
|
36741
|
-
*
|
|
37785
|
+
* Generates `.junie/AGENTS.md` files based on rulesync rule content. Junie CLI
|
|
37786
|
+
* resolves project guidelines **first-match-wins**: `.junie/AGENTS.md` → root
|
|
37787
|
+
* `AGENTS.md` → legacy `.junie/guidelines.md` / `.junie/guidelines/`. Only the
|
|
37788
|
+
* first match is loaded, it documents no `@`-reference or file-inclusion
|
|
37789
|
+
* mechanism, and no `.junie/memories/` read path exists — so non-root rules
|
|
37790
|
+
* are folded into the single root `.junie/AGENTS.md` by the RulesProcessor
|
|
37791
|
+
* (`nonRoot` is `undefined`, mirroring the grokcli / warp / deepagents
|
|
37792
|
+
* targets; decision recorded in issue #2211). The legacy
|
|
37793
|
+
* `.junie/guidelines.md` is still accepted as an import fallback, but
|
|
37794
|
+
* generation always targets `.junie/AGENTS.md`. Junie uses plain markdown
|
|
37795
|
+
* without frontmatter requirements.
|
|
37796
|
+
*
|
|
37797
|
+
* Global (user) scope writes a single `~/.junie/AGENTS.md` file. Junie merges
|
|
37798
|
+
* these user-scope guidelines with the project guidelines (both are included
|
|
37799
|
+
* and marked clearly).
|
|
36742
37800
|
*
|
|
36743
37801
|
* @see https://junie.jetbrains.com/docs/junie-ide-plugin.html
|
|
36744
37802
|
* @see https://junie.jetbrains.com/docs/guidelines-and-memory.html
|
|
@@ -36757,15 +37815,12 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36757
37815
|
alternativeRoots: [{
|
|
36758
37816
|
relativeDirPath: buildToolPath(JUNIE_DIR, ".", excludeToolDir),
|
|
36759
37817
|
relativeFilePath: JUNIE_LEGACY_RULE_FILE_NAME
|
|
36760
|
-
}]
|
|
36761
|
-
nonRoot: { relativeDirPath: buildToolPath(JUNIE_DIR, "memories", excludeToolDir) }
|
|
37818
|
+
}]
|
|
36762
37819
|
};
|
|
36763
37820
|
}
|
|
36764
37821
|
/**
|
|
36765
37822
|
* Determines whether a given relative file path refers to a root guideline file.
|
|
36766
37823
|
* The preferred file is `AGENTS.md`; the legacy `guidelines.md` is still accepted.
|
|
36767
|
-
* Memory files live under `.junie/memories/` and are passed in as bare filenames
|
|
36768
|
-
* (e.g. `memo.md`), so a top-level `AGENTS.md`/`guidelines.md` is the root entry.
|
|
36769
37824
|
*/
|
|
36770
37825
|
static isRootRelativeFilePath(relativeFilePath) {
|
|
36771
37826
|
return relativeFilePath === "AGENTS.md" || relativeFilePath === "guidelines.md";
|
|
@@ -36784,10 +37839,7 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36784
37839
|
root: true
|
|
36785
37840
|
});
|
|
36786
37841
|
}
|
|
36787
|
-
const
|
|
36788
|
-
const settablePaths = this.getSettablePaths();
|
|
36789
|
-
if (!settablePaths.nonRoot) throw new Error("JunieRule project settable paths must include a nonRoot path");
|
|
36790
|
-
const relativeDirPath = isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath;
|
|
37842
|
+
const relativeDirPath = this.getSettablePaths().root.relativeDirPath;
|
|
36791
37843
|
const fileContent = await readFileContent((0, node_path.join)(outputRoot, (0, node_path.join)(relativeDirPath, relativeFilePath)));
|
|
36792
37844
|
return new JunieRule({
|
|
36793
37845
|
outputRoot,
|
|
@@ -36795,7 +37847,7 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36795
37847
|
relativeFilePath,
|
|
36796
37848
|
fileContent,
|
|
36797
37849
|
validate,
|
|
36798
|
-
root:
|
|
37850
|
+
root: JunieRule.isRootRelativeFilePath(relativeFilePath)
|
|
36799
37851
|
});
|
|
36800
37852
|
}
|
|
36801
37853
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
@@ -36810,13 +37862,15 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36810
37862
|
rootPath: paths.root
|
|
36811
37863
|
}));
|
|
36812
37864
|
}
|
|
36813
|
-
|
|
37865
|
+
const { root } = this.getSettablePaths();
|
|
37866
|
+
return new JunieRule({
|
|
36814
37867
|
outputRoot,
|
|
36815
|
-
|
|
37868
|
+
relativeDirPath: root.relativeDirPath,
|
|
37869
|
+
relativeFilePath: root.relativeFilePath,
|
|
37870
|
+
fileContent: rulesyncRule.getBody(),
|
|
36816
37871
|
validate,
|
|
36817
|
-
|
|
36818
|
-
|
|
36819
|
-
}));
|
|
37872
|
+
root: rulesyncRule.getFrontmatter().root ?? false
|
|
37873
|
+
});
|
|
36820
37874
|
}
|
|
36821
37875
|
toRulesyncRule() {
|
|
36822
37876
|
return this.toRulesyncRuleDefault();
|
|
@@ -37219,31 +38273,68 @@ var OpenCodeRule = class OpenCodeRule extends ToolRule {
|
|
|
37219
38273
|
* RulesProcessor (there is no separate non-root output location — `nonRoot` is
|
|
37220
38274
|
* `undefined`). This mirrors the codexcli, grokcli, warp, and deepagents targets.
|
|
37221
38275
|
*
|
|
37222
|
-
* Pi also loads two system-prompt instruction files
|
|
38276
|
+
* Pi also loads two system-prompt instruction files. `.pi/APPEND_SYSTEM.md`
|
|
38277
|
+
* (global `~/.pi/agent/APPEND_SYSTEM.md`) *appends* to the default system prompt,
|
|
38278
|
+
* and rulesync emits it from any rule that opts in via the `pi.systemPrompt:
|
|
38279
|
+
* append` frontmatter block: those bodies are routed here instead of being folded
|
|
38280
|
+
* into `AGENTS.md`, and multiple opted-in rules concatenate in source order.
|
|
37223
38281
|
* `.pi/SYSTEM.md` (global `~/.pi/agent/SYSTEM.md`) *replaces* the default system
|
|
37224
|
-
* prompt entirely
|
|
37225
|
-
*
|
|
37226
|
-
*
|
|
37227
|
-
* for marking a rule as "replace" vs "append" the system prompt, so these
|
|
37228
|
-
* surfaces are documented in docs/reference/file-formats.md and left to be
|
|
37229
|
-
* authored by hand rather than mapped to a speculative new frontmatter flag.
|
|
38282
|
+
* prompt entirely — which silently disables Pi's built-in tool instructions — so
|
|
38283
|
+
* rulesync deliberately never emits it and leaves it to be authored by hand.
|
|
38284
|
+
* See docs/reference/file-formats.md.
|
|
37230
38285
|
*/
|
|
37231
38286
|
var PiRule = class PiRule extends ToolRule {
|
|
37232
|
-
|
|
38287
|
+
appendSystemPrompt;
|
|
38288
|
+
constructor({ fileContent, root, appendSystemPrompt = false, ...rest }) {
|
|
37233
38289
|
super({
|
|
37234
38290
|
...rest,
|
|
37235
38291
|
fileContent,
|
|
37236
38292
|
root: root ?? false
|
|
37237
38293
|
});
|
|
38294
|
+
this.appendSystemPrompt = appendSystemPrompt;
|
|
37238
38295
|
}
|
|
37239
38296
|
static getSettablePaths({ global = false, excludeToolDir } = {}) {
|
|
37240
|
-
return {
|
|
37241
|
-
|
|
37242
|
-
|
|
37243
|
-
|
|
38297
|
+
return {
|
|
38298
|
+
root: {
|
|
38299
|
+
relativeDirPath: global ? buildToolPath(".pi", "agent", excludeToolDir) : ".",
|
|
38300
|
+
relativeFilePath: PI_RULE_FILE_NAME
|
|
38301
|
+
},
|
|
38302
|
+
appendSystemPrompt: {
|
|
38303
|
+
relativeDirPath: global ? buildToolPath(".pi", "agent", excludeToolDir) : ".pi",
|
|
38304
|
+
relativeFilePath: PI_APPEND_SYSTEM_FILE_NAME
|
|
38305
|
+
}
|
|
38306
|
+
};
|
|
37244
38307
|
}
|
|
37245
|
-
|
|
37246
|
-
|
|
38308
|
+
/**
|
|
38309
|
+
* Extra fixed files this tool manages beyond the root rule. The
|
|
38310
|
+
* RulesProcessor enumerates these for import and deletion so a stale
|
|
38311
|
+
* `APPEND_SYSTEM.md` is cleaned up once no rule opts in anymore.
|
|
38312
|
+
*/
|
|
38313
|
+
static getExtraFixedFiles({ global = false } = {}) {
|
|
38314
|
+
return [this.getSettablePaths({ global }).appendSystemPrompt];
|
|
38315
|
+
}
|
|
38316
|
+
/**
|
|
38317
|
+
* Pi appends `APPEND_SYSTEM.md` to the system prompt itself, so listing it in
|
|
38318
|
+
* the root rule's reference section (toon/explicit discovery modes) would
|
|
38319
|
+
* double-load the content.
|
|
38320
|
+
*/
|
|
38321
|
+
isExcludedFromRootReferences() {
|
|
38322
|
+
return this.appendSystemPrompt;
|
|
38323
|
+
}
|
|
38324
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
38325
|
+
const { root, appendSystemPrompt } = this.getSettablePaths({ global });
|
|
38326
|
+
if (relativeFilePath === "APPEND_SYSTEM.md") {
|
|
38327
|
+
const fileContent = await readFileContent((0, node_path.join)(outputRoot, (0, node_path.join)(appendSystemPrompt.relativeDirPath, appendSystemPrompt.relativeFilePath)));
|
|
38328
|
+
return new PiRule({
|
|
38329
|
+
outputRoot,
|
|
38330
|
+
relativeDirPath: appendSystemPrompt.relativeDirPath,
|
|
38331
|
+
relativeFilePath: appendSystemPrompt.relativeFilePath,
|
|
38332
|
+
fileContent,
|
|
38333
|
+
validate,
|
|
38334
|
+
root: false,
|
|
38335
|
+
appendSystemPrompt: true
|
|
38336
|
+
});
|
|
38337
|
+
}
|
|
37247
38338
|
const fileContent = await readFileContent((0, node_path.join)(outputRoot, (0, node_path.join)(root.relativeDirPath, root.relativeFilePath)));
|
|
37248
38339
|
return new PiRule({
|
|
37249
38340
|
outputRoot,
|
|
@@ -37255,8 +38346,18 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37255
38346
|
});
|
|
37256
38347
|
}
|
|
37257
38348
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
37258
|
-
const { root } = this.getSettablePaths({ global });
|
|
37259
|
-
const
|
|
38349
|
+
const { root, appendSystemPrompt } = this.getSettablePaths({ global });
|
|
38350
|
+
const frontmatter = rulesyncRule.getFrontmatter();
|
|
38351
|
+
if (!frontmatter.root && frontmatter.pi?.systemPrompt === "append") return new PiRule({
|
|
38352
|
+
outputRoot,
|
|
38353
|
+
relativeDirPath: appendSystemPrompt.relativeDirPath,
|
|
38354
|
+
relativeFilePath: appendSystemPrompt.relativeFilePath,
|
|
38355
|
+
fileContent: rulesyncRule.getBody(),
|
|
38356
|
+
validate,
|
|
38357
|
+
root: false,
|
|
38358
|
+
appendSystemPrompt: true
|
|
38359
|
+
});
|
|
38360
|
+
const isRoot = frontmatter.root ?? false;
|
|
37260
38361
|
return new PiRule({
|
|
37261
38362
|
outputRoot,
|
|
37262
38363
|
relativeDirPath: root.relativeDirPath,
|
|
@@ -37267,6 +38368,17 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37267
38368
|
});
|
|
37268
38369
|
}
|
|
37269
38370
|
toRulesyncRule() {
|
|
38371
|
+
if (this.appendSystemPrompt) return new RulesyncRule({
|
|
38372
|
+
outputRoot: process.cwd(),
|
|
38373
|
+
relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
|
|
38374
|
+
relativeFilePath: PI_APPEND_SYSTEM_FILE_NAME,
|
|
38375
|
+
frontmatter: {
|
|
38376
|
+
root: false,
|
|
38377
|
+
targets: ["pi"],
|
|
38378
|
+
pi: { systemPrompt: "append" }
|
|
38379
|
+
},
|
|
38380
|
+
body: this.getFileContent()
|
|
38381
|
+
});
|
|
37270
38382
|
return this.toRulesyncRuleDefault();
|
|
37271
38383
|
}
|
|
37272
38384
|
validate() {
|
|
@@ -37277,6 +38389,15 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37277
38389
|
}
|
|
37278
38390
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
|
|
37279
38391
|
const { root } = this.getSettablePaths({ global });
|
|
38392
|
+
if (relativeFilePath === "APPEND_SYSTEM.md") return new PiRule({
|
|
38393
|
+
outputRoot,
|
|
38394
|
+
relativeDirPath,
|
|
38395
|
+
relativeFilePath,
|
|
38396
|
+
fileContent: "",
|
|
38397
|
+
validate: false,
|
|
38398
|
+
root: false,
|
|
38399
|
+
appendSystemPrompt: true
|
|
38400
|
+
});
|
|
37280
38401
|
const isRoot = relativeFilePath === "AGENTS.md" && (relativeDirPath === "." || relativeDirPath === root.relativeDirPath);
|
|
37281
38402
|
return new PiRule({
|
|
37282
38403
|
outputRoot,
|
|
@@ -38436,7 +39557,8 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
38436
39557
|
meta: {
|
|
38437
39558
|
extension: "md",
|
|
38438
39559
|
supportsGlobal: true,
|
|
38439
|
-
ruleDiscoveryMode: "
|
|
39560
|
+
ruleDiscoveryMode: "auto",
|
|
39561
|
+
foldsNonRootIntoRoot: true
|
|
38440
39562
|
}
|
|
38441
39563
|
}],
|
|
38442
39564
|
["kilo", {
|
|
@@ -38702,7 +39824,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38702
39824
|
*/
|
|
38703
39825
|
async buildMcpInstructionFiles({ toolRules, meta }) {
|
|
38704
39826
|
if (!meta.mcpInstructionsRegistrar || this.global) return [];
|
|
38705
|
-
const instructionPaths = toolRules.filter((rule) => !rule.isRoot()).map((rule) => toPosixPath((0, node_path.join)(rule.getRelativeDirPath(), rule.getRelativeFilePath())));
|
|
39827
|
+
const instructionPaths = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences()).map((rule) => toPosixPath((0, node_path.join)(rule.getRelativeDirPath(), rule.getRelativeFilePath())));
|
|
38706
39828
|
if (instructionPaths.length === 0) return [];
|
|
38707
39829
|
return [await meta.mcpInstructionsRegistrar.fromInstructions({
|
|
38708
39830
|
outputRoot: this.outputRoot,
|
|
@@ -38734,7 +39856,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38734
39856
|
const toolRelativeDirPath = skillClass.getSettablePaths({ global: this.global }).relativeDirPath;
|
|
38735
39857
|
return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
|
|
38736
39858
|
const frontmatter = skill.getFrontmatter();
|
|
38737
|
-
const relativePath = (0, node_path.join)(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
|
|
39859
|
+
const relativePath = (0, node_path.join)(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME$1);
|
|
38738
39860
|
return {
|
|
38739
39861
|
name: frontmatter.name,
|
|
38740
39862
|
description: frontmatter.description,
|
|
@@ -38758,11 +39880,25 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38758
39880
|
*/
|
|
38759
39881
|
foldNonRootRulesIntoRootRule(toolRules) {
|
|
38760
39882
|
if (toolRules.length <= 1) return;
|
|
38761
|
-
const
|
|
38762
|
-
|
|
38763
|
-
|
|
38764
|
-
|
|
38765
|
-
|
|
39883
|
+
const groups = /* @__PURE__ */ new Map();
|
|
39884
|
+
for (const rule of toolRules) {
|
|
39885
|
+
const path = (0, node_path.join)(rule.getRelativeDirPath(), rule.getRelativeFilePath());
|
|
39886
|
+
const group = groups.get(path);
|
|
39887
|
+
if (group) group.push(rule);
|
|
39888
|
+
else groups.set(path, [rule]);
|
|
39889
|
+
}
|
|
39890
|
+
const survivors = /* @__PURE__ */ new Set();
|
|
39891
|
+
for (const group of groups.values()) {
|
|
39892
|
+
const target = group.find((rule) => rule.isRoot()) ?? group[0];
|
|
39893
|
+
if (!target) continue;
|
|
39894
|
+
const mergedContent = [target, ...group.filter((rule) => rule !== target)].map((rule) => rule.getFileContent().trim()).filter((content) => content.length > 0).join("\n\n");
|
|
39895
|
+
target.setFileContent(mergedContent);
|
|
39896
|
+
survivors.add(target);
|
|
39897
|
+
}
|
|
39898
|
+
for (let i = toolRules.length - 1; i >= 0; i--) {
|
|
39899
|
+
const rule = toolRules[i];
|
|
39900
|
+
if (rule && !survivors.has(rule)) toolRules.splice(i, 1);
|
|
39901
|
+
}
|
|
38766
39902
|
}
|
|
38767
39903
|
/**
|
|
38768
39904
|
* Handle localRoot rule generation based on tool target.
|
|
@@ -38972,6 +40108,27 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
38972
40108
|
const mirrorPaths = await findFilesByGlobs(mirrorGlob);
|
|
38973
40109
|
return buildDeletionRulesFromPaths(mirrorPaths);
|
|
38974
40110
|
})();
|
|
40111
|
+
const extraFixedToolRules = await (async () => {
|
|
40112
|
+
const extraFiles = factory.class.getExtraFixedFiles?.({ global: this.global });
|
|
40113
|
+
if (!extraFiles || extraFiles.length === 0) return [];
|
|
40114
|
+
const filePaths = await findFilesByGlobs(extraFiles.map((file) => (0, node_path.join)(this.outputRoot, file.relativeDirPath, file.relativeFilePath)));
|
|
40115
|
+
if (filePaths.length === 0) return [];
|
|
40116
|
+
if (forDeletion) return buildDeletionRulesFromPaths(filePaths);
|
|
40117
|
+
return await Promise.all(filePaths.map((filePath) => {
|
|
40118
|
+
const relativeDirPath = resolveRelativeDirPath(filePath);
|
|
40119
|
+
checkPathTraversal({
|
|
40120
|
+
relativePath: relativeDirPath,
|
|
40121
|
+
intendedRootDir: this.outputRoot
|
|
40122
|
+
});
|
|
40123
|
+
return factory.class.fromFile({
|
|
40124
|
+
outputRoot: this.outputRoot,
|
|
40125
|
+
relativeDirPath,
|
|
40126
|
+
relativeFilePath: (0, node_path.basename)(filePath),
|
|
40127
|
+
global: this.global
|
|
40128
|
+
});
|
|
40129
|
+
}));
|
|
40130
|
+
})();
|
|
40131
|
+
this.logger.debug(`Found ${extraFixedToolRules.length} extra fixed tool rule files`);
|
|
38975
40132
|
const nonRootToolRules = await (async () => {
|
|
38976
40133
|
if (!settablePaths.nonRoot) return [];
|
|
38977
40134
|
const nonRootOutputRoot = (0, node_path.join)(this.outputRoot, settablePaths.nonRoot.relativeDirPath);
|
|
@@ -39007,6 +40164,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39007
40164
|
...rootToolRules,
|
|
39008
40165
|
...localRootToolRules,
|
|
39009
40166
|
...rootMirrorDeletionRules,
|
|
40167
|
+
...extraFixedToolRules,
|
|
39010
40168
|
...nonRootToolRules
|
|
39011
40169
|
];
|
|
39012
40170
|
} catch (error) {
|
|
@@ -39034,7 +40192,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39034
40192
|
return toolRuleFactories.get(result.data);
|
|
39035
40193
|
}
|
|
39036
40194
|
generateToonReferencesSection(toolRules) {
|
|
39037
|
-
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
|
|
40195
|
+
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences());
|
|
39038
40196
|
if (toolRulesWithoutRoot.length === 0) return "";
|
|
39039
40197
|
const lines = [];
|
|
39040
40198
|
lines.push("Please also reference the following rules as needed. The list below is provided in TOON format, and `@` stands for the project root directory.");
|
|
@@ -39050,7 +40208,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39050
40208
|
return lines.join("\n") + "\n\n";
|
|
39051
40209
|
}
|
|
39052
40210
|
generateReferencesSection(toolRules) {
|
|
39053
|
-
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
|
|
40211
|
+
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences());
|
|
39054
40212
|
if (toolRulesWithoutRoot.length === 0) return "";
|
|
39055
40213
|
const lines = [];
|
|
39056
40214
|
lines.push("Please also reference the following rules as needed:");
|
|
@@ -39071,7 +40229,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39071
40229
|
*/
|
|
39072
40230
|
async function convertFromTool(params) {
|
|
39073
40231
|
const ctx = params;
|
|
39074
|
-
const [rulesCount, ignoreCount, mcpCount, commandsCount, subagentsCount, skillsCount, hooksCount, permissionsCount] = [
|
|
40232
|
+
const [rulesCount, ignoreCount, mcpCount, commandsCount, subagentsCount, skillsCount, hooksCount, permissionsCount, checksCount] = [
|
|
39075
40233
|
await runFeatureConvert(ctx, buildRulesStrategy(ctx)),
|
|
39076
40234
|
await runFeatureConvert(ctx, buildIgnoreStrategy(ctx)),
|
|
39077
40235
|
await runFeatureConvert(ctx, buildMcpStrategy(ctx)),
|
|
@@ -39079,7 +40237,8 @@ async function convertFromTool(params) {
|
|
|
39079
40237
|
await runFeatureConvert(ctx, buildSubagentsStrategy(ctx)),
|
|
39080
40238
|
await runFeatureConvert(ctx, buildSkillsStrategy(ctx)),
|
|
39081
40239
|
await runFeatureConvert(ctx, buildHooksStrategy(ctx)),
|
|
39082
|
-
await runFeatureConvert(ctx, buildPermissionsStrategy(ctx))
|
|
40240
|
+
await runFeatureConvert(ctx, buildPermissionsStrategy(ctx)),
|
|
40241
|
+
await runFeatureConvert(ctx, buildChecksStrategy(ctx))
|
|
39083
40242
|
];
|
|
39084
40243
|
return {
|
|
39085
40244
|
rulesCount,
|
|
@@ -39089,7 +40248,8 @@ async function convertFromTool(params) {
|
|
|
39089
40248
|
subagentsCount,
|
|
39090
40249
|
skillsCount,
|
|
39091
40250
|
hooksCount,
|
|
39092
|
-
permissionsCount
|
|
40251
|
+
permissionsCount,
|
|
40252
|
+
checksCount
|
|
39093
40253
|
};
|
|
39094
40254
|
}
|
|
39095
40255
|
async function runFeatureConvert(ctx, strategy) {
|
|
@@ -39322,6 +40482,27 @@ function buildPermissionsStrategy(ctx) {
|
|
|
39322
40482
|
write: (p, files) => p.writeAiFiles(files)
|
|
39323
40483
|
};
|
|
39324
40484
|
}
|
|
40485
|
+
function buildChecksStrategy(ctx) {
|
|
40486
|
+
const { config, logger } = ctx;
|
|
40487
|
+
const global = config.getGlobal();
|
|
40488
|
+
const outputRoot = getOutputRoot(config);
|
|
40489
|
+
return {
|
|
40490
|
+
feature: "checks",
|
|
40491
|
+
itemLabel: "check file(s)",
|
|
40492
|
+
allTargets: ChecksProcessor.getToolTargets({ global }),
|
|
40493
|
+
createProcessor: ({ toolTarget, dryRun }) => new ChecksProcessor({
|
|
40494
|
+
outputRoot,
|
|
40495
|
+
toolTarget,
|
|
40496
|
+
global,
|
|
40497
|
+
dryRun,
|
|
40498
|
+
logger
|
|
40499
|
+
}),
|
|
40500
|
+
loadSource: (p) => p.loadToolFiles(),
|
|
40501
|
+
toRulesync: (p, files) => p.convertToolFilesToRulesyncFiles(files),
|
|
40502
|
+
fromRulesync: (p, files) => p.convertRulesyncFilesToToolFiles(files),
|
|
40503
|
+
write: (p, files) => p.writeAiFiles(files)
|
|
40504
|
+
};
|
|
40505
|
+
}
|
|
39325
40506
|
//#endregion
|
|
39326
40507
|
//#region src/types/processor-registry.ts
|
|
39327
40508
|
const PROCESSOR_REGISTRY = [
|
|
@@ -39372,6 +40553,12 @@ const PROCESSOR_REGISTRY = [
|
|
|
39372
40553
|
processor: PermissionsProcessor,
|
|
39373
40554
|
schema: PermissionsProcessorToolTargetSchema,
|
|
39374
40555
|
factory: toolPermissionsFactories
|
|
40556
|
+
},
|
|
40557
|
+
{
|
|
40558
|
+
feature: "checks",
|
|
40559
|
+
processor: ChecksProcessor,
|
|
40560
|
+
schema: ChecksProcessorToolTargetSchema,
|
|
40561
|
+
factory: toolCheckFactories
|
|
39375
40562
|
}
|
|
39376
40563
|
];
|
|
39377
40564
|
const getProcessorRegistryEntry = (feature) => {
|
|
@@ -39721,6 +40908,7 @@ const GENERATION_STEP_GRAPH = [
|
|
|
39721
40908
|
id: "permissions",
|
|
39722
40909
|
...sharedWriteMeta("permissions")
|
|
39723
40910
|
},
|
|
40911
|
+
{ id: "checks" },
|
|
39724
40912
|
{
|
|
39725
40913
|
id: "rules",
|
|
39726
40914
|
...sharedWriteMeta("rules"),
|
|
@@ -39728,11 +40916,51 @@ const GENERATION_STEP_GRAPH = [
|
|
|
39728
40916
|
}
|
|
39729
40917
|
];
|
|
39730
40918
|
/**
|
|
40919
|
+
* Warn when a rulesync skill and a rulesync subagent share a name for a tool
|
|
40920
|
+
* that emits both features into the same directory (e.g. Reasonix, where both
|
|
40921
|
+
* write `<name>/SKILL.md` under `.reasonix/skills/`). The colliding outputs
|
|
40922
|
+
* target the same on-disk file, so whichever generation step runs later
|
|
40923
|
+
* silently overwrites the other's file.
|
|
40924
|
+
*/
|
|
40925
|
+
async function warnSkillSubagentNameCollisions(params) {
|
|
40926
|
+
const { config, logger } = params;
|
|
40927
|
+
const global = config.getGlobal();
|
|
40928
|
+
for (const toolTarget of config.getTargets()) {
|
|
40929
|
+
const features = config.getFeatures(toolTarget);
|
|
40930
|
+
if (!features.includes("skills") || !features.includes("subagents")) continue;
|
|
40931
|
+
if (!SubagentsProcessor.getToolTargets({ global }).includes(toolTarget) || !SkillsProcessor.getToolTargets({ global }).includes(toolTarget)) continue;
|
|
40932
|
+
const subagentFactory = SubagentsProcessor.getFactory(toolTarget);
|
|
40933
|
+
const skillFactory = SkillsProcessor.getFactory(toolTarget);
|
|
40934
|
+
if (!subagentFactory || !skillFactory) continue;
|
|
40935
|
+
const subagentsDirPath = subagentFactory.class.getSettablePaths({ global }).relativeDirPath;
|
|
40936
|
+
if (subagentsDirPath !== skillFactory.class.getSettablePaths({ global }).relativeDirPath) continue;
|
|
40937
|
+
const subagentsProcessor = new SubagentsProcessor({
|
|
40938
|
+
inputRoot: config.getInputRoot(),
|
|
40939
|
+
toolTarget,
|
|
40940
|
+
global,
|
|
40941
|
+
logger
|
|
40942
|
+
});
|
|
40943
|
+
const subagentNames = new Set((await subagentsProcessor.loadRulesyncFiles()).filter((file) => file instanceof RulesyncSubagent).filter((file) => subagentFactory.class.isTargetedByRulesyncSubagent(file)).map((file) => (0, node_path.basename)(file.getRelativeFilePath(), (0, node_path.extname)(file.getRelativeFilePath()))));
|
|
40944
|
+
if (subagentNames.size === 0) continue;
|
|
40945
|
+
const skillNames = (await new SkillsProcessor({
|
|
40946
|
+
inputRoot: config.getInputRoot(),
|
|
40947
|
+
toolTarget,
|
|
40948
|
+
global,
|
|
40949
|
+
logger
|
|
40950
|
+
}).loadRulesyncDirs()).filter((dir) => dir instanceof RulesyncSkill).filter((skill) => skillFactory.class.isTargetedByRulesyncSkill(skill)).map((skill) => skill.getDirName());
|
|
40951
|
+
for (const name of skillNames) if (subagentNames.has(name)) logger.warn(`Skill "${name}" and subagent "${name}" both target '${toolTarget}' and write the same path '${(0, node_path.join)(subagentsDirPath, name)}'; the later generation step overwrites the other's output. Rename one of them or narrow their targets.`);
|
|
40952
|
+
}
|
|
40953
|
+
}
|
|
40954
|
+
/**
|
|
39731
40955
|
* Generate configuration files for AI tools.
|
|
39732
40956
|
* @throws Error if generation fails
|
|
39733
40957
|
*/
|
|
39734
40958
|
async function generate(params) {
|
|
39735
40959
|
const { config, logger } = params;
|
|
40960
|
+
await warnSkillSubagentNameCollisions({
|
|
40961
|
+
config,
|
|
40962
|
+
logger
|
|
40963
|
+
});
|
|
39736
40964
|
let skillsResult;
|
|
39737
40965
|
const runners = {
|
|
39738
40966
|
ignore: () => generateIgnoreCore({
|
|
@@ -39766,6 +40994,10 @@ async function generate(params) {
|
|
|
39766
40994
|
config,
|
|
39767
40995
|
logger
|
|
39768
40996
|
}),
|
|
40997
|
+
checks: () => generateChecksCore({
|
|
40998
|
+
config,
|
|
40999
|
+
logger
|
|
41000
|
+
}),
|
|
39769
41001
|
rules: () => generateRulesCore({
|
|
39770
41002
|
config,
|
|
39771
41003
|
logger,
|
|
@@ -39802,6 +41034,8 @@ async function generate(params) {
|
|
|
39802
41034
|
hooksPaths: get("hooks").paths,
|
|
39803
41035
|
permissionsCount: get("permissions").count,
|
|
39804
41036
|
permissionsPaths: get("permissions").paths,
|
|
41037
|
+
checksCount: get("checks").count,
|
|
41038
|
+
checksPaths: get("checks").paths,
|
|
39805
41039
|
skills: skillsResult.skills,
|
|
39806
41040
|
hasDiff
|
|
39807
41041
|
};
|
|
@@ -40170,6 +41404,44 @@ async function generatePermissionsCore(params) {
|
|
|
40170
41404
|
hasDiff
|
|
40171
41405
|
};
|
|
40172
41406
|
}
|
|
41407
|
+
async function generateChecksCore(params) {
|
|
41408
|
+
const { config, logger } = params;
|
|
41409
|
+
let totalCount = 0;
|
|
41410
|
+
const allPaths = [];
|
|
41411
|
+
let hasDiff = false;
|
|
41412
|
+
const supportedChecksTargets = ChecksProcessor.getToolTargets({ global: config.getGlobal() });
|
|
41413
|
+
const toolTargets = (0, es_toolkit.intersection)(config.getTargets(), supportedChecksTargets);
|
|
41414
|
+
warnUnsupportedTargets({
|
|
41415
|
+
config,
|
|
41416
|
+
supportedTargets: supportedChecksTargets,
|
|
41417
|
+
featureName: "checks",
|
|
41418
|
+
logger
|
|
41419
|
+
});
|
|
41420
|
+
for (const toolTarget of toolTargets) for (const outputRoot of config.getOutputRoots(toolTarget)) {
|
|
41421
|
+
if (!config.getFeatures(toolTarget).includes("checks")) continue;
|
|
41422
|
+
const processor = new ChecksProcessor({
|
|
41423
|
+
outputRoot,
|
|
41424
|
+
inputRoot: config.getInputRoot(),
|
|
41425
|
+
toolTarget,
|
|
41426
|
+
global: config.getGlobal(),
|
|
41427
|
+
dryRun: config.isPreviewMode(),
|
|
41428
|
+
logger
|
|
41429
|
+
});
|
|
41430
|
+
const result = await processFeatureWithRulesyncFiles({
|
|
41431
|
+
config,
|
|
41432
|
+
processor,
|
|
41433
|
+
rulesyncFiles: await processor.loadRulesyncFiles()
|
|
41434
|
+
});
|
|
41435
|
+
totalCount += result.count;
|
|
41436
|
+
allPaths.push(...result.paths);
|
|
41437
|
+
if (result.hasDiff) hasDiff = true;
|
|
41438
|
+
}
|
|
41439
|
+
return {
|
|
41440
|
+
count: totalCount,
|
|
41441
|
+
paths: allPaths,
|
|
41442
|
+
hasDiff
|
|
41443
|
+
};
|
|
41444
|
+
}
|
|
40173
41445
|
//#endregion
|
|
40174
41446
|
//#region src/lib/import.ts
|
|
40175
41447
|
/**
|
|
@@ -40227,6 +41499,11 @@ async function importFromTool(params) {
|
|
|
40227
41499
|
config,
|
|
40228
41500
|
tool,
|
|
40229
41501
|
logger
|
|
41502
|
+
}),
|
|
41503
|
+
checksCount: await importChecksCore({
|
|
41504
|
+
config,
|
|
41505
|
+
tool,
|
|
41506
|
+
logger
|
|
40230
41507
|
})
|
|
40231
41508
|
};
|
|
40232
41509
|
}
|
|
@@ -40443,6 +41720,27 @@ async function importPermissionsCore(params) {
|
|
|
40443
41720
|
if (config.getVerbose() && writtenCount > 0) logger.success(`Created ${writtenCount} permissions file(s)`);
|
|
40444
41721
|
return writtenCount;
|
|
40445
41722
|
}
|
|
41723
|
+
async function importChecksCore(params) {
|
|
41724
|
+
const { config, tool, logger } = params;
|
|
41725
|
+
if (!config.getFeatures(tool).includes("checks")) return 0;
|
|
41726
|
+
const global = config.getGlobal();
|
|
41727
|
+
if (!ChecksProcessor.getToolTargets({ global }).includes(tool)) return 0;
|
|
41728
|
+
const checksProcessor = new ChecksProcessor({
|
|
41729
|
+
outputRoot: config.getOutputRoots()[0] ?? ".",
|
|
41730
|
+
toolTarget: tool,
|
|
41731
|
+
global,
|
|
41732
|
+
logger
|
|
41733
|
+
});
|
|
41734
|
+
const toolFiles = await checksProcessor.loadToolFiles();
|
|
41735
|
+
if (toolFiles.length === 0) {
|
|
41736
|
+
logger.warn(`No check files found for ${tool}. Skipping import.`);
|
|
41737
|
+
return 0;
|
|
41738
|
+
}
|
|
41739
|
+
const rulesyncFiles = await checksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
41740
|
+
const { count: writtenCount } = await checksProcessor.writeAiFiles(rulesyncFiles);
|
|
41741
|
+
if (config.getVerbose() && writtenCount > 0) logger.success(`Created ${writtenCount} check files`);
|
|
41742
|
+
return writtenCount;
|
|
41743
|
+
}
|
|
40446
41744
|
//#endregion
|
|
40447
41745
|
Object.defineProperty(exports, "ALL_FEATURES", {
|
|
40448
41746
|
enumerable: true,
|
|
@@ -40504,12 +41802,24 @@ Object.defineProperty(exports, "CLIError", {
|
|
|
40504
41802
|
return CLIError;
|
|
40505
41803
|
}
|
|
40506
41804
|
});
|
|
41805
|
+
Object.defineProperty(exports, "CODEXCLI_BASH_RULES_FILE_NAME", {
|
|
41806
|
+
enumerable: true,
|
|
41807
|
+
get: function() {
|
|
41808
|
+
return CODEXCLI_BASH_RULES_FILE_NAME;
|
|
41809
|
+
}
|
|
41810
|
+
});
|
|
40507
41811
|
Object.defineProperty(exports, "CODEXCLI_DIR", {
|
|
40508
41812
|
enumerable: true,
|
|
40509
41813
|
get: function() {
|
|
40510
41814
|
return CODEXCLI_DIR;
|
|
40511
41815
|
}
|
|
40512
41816
|
});
|
|
41817
|
+
Object.defineProperty(exports, "ChecksProcessor", {
|
|
41818
|
+
enumerable: true,
|
|
41819
|
+
get: function() {
|
|
41820
|
+
return ChecksProcessor;
|
|
41821
|
+
}
|
|
41822
|
+
});
|
|
40513
41823
|
Object.defineProperty(exports, "CommandsProcessor", {
|
|
40514
41824
|
enumerable: true,
|
|
40515
41825
|
get: function() {
|
|
@@ -40576,6 +41886,12 @@ Object.defineProperty(exports, "RULESYNC_AIIGNORE_RELATIVE_FILE_PATH", {
|
|
|
40576
41886
|
return RULESYNC_AIIGNORE_RELATIVE_FILE_PATH;
|
|
40577
41887
|
}
|
|
40578
41888
|
});
|
|
41889
|
+
Object.defineProperty(exports, "RULESYNC_CHECKS_RELATIVE_DIR_PATH", {
|
|
41890
|
+
enumerable: true,
|
|
41891
|
+
get: function() {
|
|
41892
|
+
return RULESYNC_CHECKS_RELATIVE_DIR_PATH;
|
|
41893
|
+
}
|
|
41894
|
+
});
|
|
40579
41895
|
Object.defineProperty(exports, "RULESYNC_COMMANDS_RELATIVE_DIR_PATH", {
|
|
40580
41896
|
enumerable: true,
|
|
40581
41897
|
get: function() {
|
|
@@ -40720,6 +42036,18 @@ Object.defineProperty(exports, "RulesProcessor", {
|
|
|
40720
42036
|
return RulesProcessor;
|
|
40721
42037
|
}
|
|
40722
42038
|
});
|
|
42039
|
+
Object.defineProperty(exports, "RulesyncCheck", {
|
|
42040
|
+
enumerable: true,
|
|
42041
|
+
get: function() {
|
|
42042
|
+
return RulesyncCheck;
|
|
42043
|
+
}
|
|
42044
|
+
});
|
|
42045
|
+
Object.defineProperty(exports, "RulesyncCheckFrontmatterSchema", {
|
|
42046
|
+
enumerable: true,
|
|
42047
|
+
get: function() {
|
|
42048
|
+
return RulesyncCheckFrontmatterSchema;
|
|
42049
|
+
}
|
|
42050
|
+
});
|
|
40723
42051
|
Object.defineProperty(exports, "RulesyncCommand", {
|
|
40724
42052
|
enumerable: true,
|
|
40725
42053
|
get: function() {
|
|
@@ -40795,7 +42123,7 @@ Object.defineProperty(exports, "RulesyncSubagentFrontmatterSchema", {
|
|
|
40795
42123
|
Object.defineProperty(exports, "SKILL_FILE_NAME", {
|
|
40796
42124
|
enumerable: true,
|
|
40797
42125
|
get: function() {
|
|
40798
|
-
return SKILL_FILE_NAME;
|
|
42126
|
+
return SKILL_FILE_NAME$1;
|
|
40799
42127
|
}
|
|
40800
42128
|
});
|
|
40801
42129
|
Object.defineProperty(exports, "SkillsProcessor", {
|