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
|
@@ -12,6 +12,7 @@ import { parse as parse$1, stringify } from "smol-toml";
|
|
|
12
12
|
import matter from "gray-matter";
|
|
13
13
|
import { YAMLException, dump, load } from "js-yaml";
|
|
14
14
|
import { omit } from "es-toolkit/object";
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
15
16
|
import { encode } from "@toon-format/toon";
|
|
16
17
|
//#region src/types/features.ts
|
|
17
18
|
const ALL_FEATURES = [
|
|
@@ -22,7 +23,8 @@ const ALL_FEATURES = [
|
|
|
22
23
|
"commands",
|
|
23
24
|
"skills",
|
|
24
25
|
"hooks",
|
|
25
|
-
"permissions"
|
|
26
|
+
"permissions",
|
|
27
|
+
"checks"
|
|
26
28
|
];
|
|
27
29
|
const ALL_FEATURES_WITH_WILDCARD = [...ALL_FEATURES, "*"];
|
|
28
30
|
const FeatureSchema = z.enum(ALL_FEATURES);
|
|
@@ -96,6 +98,7 @@ const RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
|
|
|
96
98
|
const RULESYNC_RULES_RELATIVE_DIR_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "rules");
|
|
97
99
|
const RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "commands");
|
|
98
100
|
const RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "subagents");
|
|
101
|
+
const RULESYNC_CHECKS_RELATIVE_DIR_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "checks");
|
|
99
102
|
const RULESYNC_MCP_RELATIVE_FILE_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
|
|
100
103
|
const RULESYNC_HOOKS_RELATIVE_FILE_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "hooks.json");
|
|
101
104
|
const RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH = join$1(RULESYNC_RELATIVE_DIR_PATH, "permissions.json");
|
|
@@ -264,6 +267,7 @@ const subagentsProcessorToolTargetTuple = [
|
|
|
264
267
|
"kiro-ide",
|
|
265
268
|
"opencode",
|
|
266
269
|
"qwencode",
|
|
270
|
+
"reasonix",
|
|
267
271
|
"roo",
|
|
268
272
|
"rovodev",
|
|
269
273
|
"takt",
|
|
@@ -360,6 +364,7 @@ const permissionsProcessorToolTargetTuple = [
|
|
|
360
364
|
"warp",
|
|
361
365
|
"zed"
|
|
362
366
|
];
|
|
367
|
+
const checksProcessorToolTargetTuple = ["amp"];
|
|
363
368
|
//#endregion
|
|
364
369
|
//#region src/types/tool-targets.ts
|
|
365
370
|
const ALL_TOOL_TARGETS = [...new Set([
|
|
@@ -370,7 +375,8 @@ const ALL_TOOL_TARGETS = [...new Set([
|
|
|
370
375
|
subagentsProcessorToolTargetTuple,
|
|
371
376
|
skillsProcessorToolTargetTuple,
|
|
372
377
|
hooksProcessorToolTargetTuple,
|
|
373
|
-
permissionsProcessorToolTargetTuple
|
|
378
|
+
permissionsProcessorToolTargetTuple,
|
|
379
|
+
checksProcessorToolTargetTuple
|
|
374
380
|
].flat())];
|
|
375
381
|
const ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
|
|
376
382
|
const ToolTargetSchema = z.enum(ALL_TOOL_TARGETS);
|
|
@@ -1444,7 +1450,7 @@ function isPlainObject$1(value) {
|
|
|
1444
1450
|
/**
|
|
1445
1451
|
* Type guard to check if a value is an array of strings.
|
|
1446
1452
|
*/
|
|
1447
|
-
function isStringArray(value) {
|
|
1453
|
+
function isStringArray$1(value) {
|
|
1448
1454
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
1449
1455
|
}
|
|
1450
1456
|
//#endregion
|
|
@@ -1692,13 +1698,17 @@ var FeatureProcessor = class {
|
|
|
1692
1698
|
}
|
|
1693
1699
|
};
|
|
1694
1700
|
//#endregion
|
|
1695
|
-
//#region src/constants/
|
|
1696
|
-
const
|
|
1697
|
-
const
|
|
1698
|
-
const
|
|
1699
|
-
const
|
|
1700
|
-
const
|
|
1701
|
-
const
|
|
1701
|
+
//#region src/constants/amp-paths.ts
|
|
1702
|
+
const AMP_DIR = ".amp";
|
|
1703
|
+
const AMP_GLOBAL_DIR = join(".config", "amp");
|
|
1704
|
+
const AMP_AGENTS_DIR = ".agents";
|
|
1705
|
+
const AMP_SKILLS_PROJECT_DIR = join(AMP_AGENTS_DIR, "skills");
|
|
1706
|
+
const AMP_SKILLS_GLOBAL_DIR = join(".config", "agents", "skills");
|
|
1707
|
+
const AMP_CHECKS_PROJECT_DIR = join(AMP_AGENTS_DIR, "checks");
|
|
1708
|
+
const AMP_CHECKS_GLOBAL_DIR = join(AMP_GLOBAL_DIR, "checks");
|
|
1709
|
+
const AMP_RULE_FILE_NAME = "AGENTS.md";
|
|
1710
|
+
const AMP_SETTINGS_FILE_NAME = "settings.json";
|
|
1711
|
+
const AMP_SETTINGS_JSONC_FILE_NAME = "settings.jsonc";
|
|
1702
1712
|
//#endregion
|
|
1703
1713
|
//#region src/types/ai-file.ts
|
|
1704
1714
|
var AiFile = class {
|
|
@@ -1772,6 +1782,414 @@ var AiFile = class {
|
|
|
1772
1782
|
}
|
|
1773
1783
|
};
|
|
1774
1784
|
//#endregion
|
|
1785
|
+
//#region src/types/rulesync-file.ts
|
|
1786
|
+
var RulesyncFile = class extends AiFile {
|
|
1787
|
+
static async fromFile(_params) {
|
|
1788
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
//#endregion
|
|
1792
|
+
//#region src/features/checks/rulesync-check.ts
|
|
1793
|
+
const RulesyncCheckFrontmatterSchema = z.looseObject({
|
|
1794
|
+
targets: z._default(RulesyncTargetsSchema, ["*"]),
|
|
1795
|
+
description: z.optional(z.string()),
|
|
1796
|
+
severity: z.optional(z.enum([
|
|
1797
|
+
"low",
|
|
1798
|
+
"medium",
|
|
1799
|
+
"high",
|
|
1800
|
+
"critical"
|
|
1801
|
+
])),
|
|
1802
|
+
tools: z.optional(z.array(z.string()))
|
|
1803
|
+
});
|
|
1804
|
+
var RulesyncCheck = class RulesyncCheck extends RulesyncFile {
|
|
1805
|
+
frontmatter;
|
|
1806
|
+
body;
|
|
1807
|
+
constructor({ frontmatter, body, ...rest }) {
|
|
1808
|
+
const parseResult = RulesyncCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1809
|
+
if (!parseResult.success && rest.validate !== false) throw new Error(`Invalid frontmatter in ${join(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`);
|
|
1810
|
+
const parsedFrontmatter = parseResult.success ? {
|
|
1811
|
+
...frontmatter,
|
|
1812
|
+
...parseResult.data
|
|
1813
|
+
} : {
|
|
1814
|
+
...frontmatter,
|
|
1815
|
+
targets: frontmatter?.targets ?? ["*"]
|
|
1816
|
+
};
|
|
1817
|
+
super({
|
|
1818
|
+
...rest,
|
|
1819
|
+
fileContent: stringifyFrontmatter(body, parsedFrontmatter)
|
|
1820
|
+
});
|
|
1821
|
+
this.frontmatter = parsedFrontmatter;
|
|
1822
|
+
this.body = body;
|
|
1823
|
+
}
|
|
1824
|
+
static getSettablePaths() {
|
|
1825
|
+
return { relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH };
|
|
1826
|
+
}
|
|
1827
|
+
getFrontmatter() {
|
|
1828
|
+
return this.frontmatter;
|
|
1829
|
+
}
|
|
1830
|
+
getBody() {
|
|
1831
|
+
return this.body;
|
|
1832
|
+
}
|
|
1833
|
+
validate() {
|
|
1834
|
+
if (!this.frontmatter) return {
|
|
1835
|
+
success: true,
|
|
1836
|
+
error: null
|
|
1837
|
+
};
|
|
1838
|
+
const result = RulesyncCheckFrontmatterSchema.safeParse(this.frontmatter);
|
|
1839
|
+
if (result.success) return {
|
|
1840
|
+
success: true,
|
|
1841
|
+
error: null
|
|
1842
|
+
};
|
|
1843
|
+
else return {
|
|
1844
|
+
success: false,
|
|
1845
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${join(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath }) {
|
|
1849
|
+
const filePath = join(outputRoot, RULESYNC_CHECKS_RELATIVE_DIR_PATH, relativeFilePath);
|
|
1850
|
+
const { frontmatter, body: content, hasFrontmatter } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
1851
|
+
if (!hasFrontmatter) throw new Error(`Missing frontmatter in ${filePath}. Rulesync files must begin with a YAML frontmatter block delimited by '---'.`);
|
|
1852
|
+
const result = RulesyncCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1853
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
1854
|
+
const filename = basename(relativeFilePath);
|
|
1855
|
+
return new RulesyncCheck({
|
|
1856
|
+
outputRoot,
|
|
1857
|
+
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
1858
|
+
relativeFilePath: filename,
|
|
1859
|
+
frontmatter: result.data,
|
|
1860
|
+
body: content.trim()
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
};
|
|
1864
|
+
//#endregion
|
|
1865
|
+
//#region src/types/tool-file.ts
|
|
1866
|
+
var ToolFile = class extends AiFile {};
|
|
1867
|
+
//#endregion
|
|
1868
|
+
//#region src/features/checks/tool-check.ts
|
|
1869
|
+
var ToolCheck = class extends ToolFile {
|
|
1870
|
+
static getSettablePaths(_options = {}) {
|
|
1871
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1872
|
+
}
|
|
1873
|
+
static async fromFile(_params) {
|
|
1874
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Create a minimal instance for deletion purposes.
|
|
1878
|
+
* This method does not read or parse file content, making it safe to use
|
|
1879
|
+
* even when files have old/incompatible formats.
|
|
1880
|
+
*/
|
|
1881
|
+
static forDeletion(_params) {
|
|
1882
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1883
|
+
}
|
|
1884
|
+
static fromRulesyncCheck(_params) {
|
|
1885
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1886
|
+
}
|
|
1887
|
+
static isTargetedByRulesyncCheck(_rulesyncCheck) {
|
|
1888
|
+
throw new Error("Please implement this method in the subclass.");
|
|
1889
|
+
}
|
|
1890
|
+
static isTargetedByRulesyncCheckDefault({ rulesyncCheck, toolTarget }) {
|
|
1891
|
+
const targets = rulesyncCheck.getFrontmatter().targets;
|
|
1892
|
+
if (!targets) return true;
|
|
1893
|
+
if (targets.includes("*")) return true;
|
|
1894
|
+
if (targets.includes(toolTarget)) return true;
|
|
1895
|
+
return false;
|
|
1896
|
+
}
|
|
1897
|
+
static filterToolSpecificSection(rawSection, excludeFields) {
|
|
1898
|
+
const filtered = {};
|
|
1899
|
+
for (const [key, value] of Object.entries(rawSection)) if (!excludeFields.includes(key)) filtered[key] = value;
|
|
1900
|
+
return filtered;
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
//#endregion
|
|
1904
|
+
//#region src/features/checks/amp-check.ts
|
|
1905
|
+
const AmpCheckFrontmatterSchema = z.looseObject({
|
|
1906
|
+
name: z.string(),
|
|
1907
|
+
description: z.optional(z.string()),
|
|
1908
|
+
"severity-default": z.optional(z.enum([
|
|
1909
|
+
"low",
|
|
1910
|
+
"medium",
|
|
1911
|
+
"high",
|
|
1912
|
+
"critical"
|
|
1913
|
+
])),
|
|
1914
|
+
tools: z.optional(z.array(z.string()))
|
|
1915
|
+
});
|
|
1916
|
+
/**
|
|
1917
|
+
* Represents an Amp code review check.
|
|
1918
|
+
*
|
|
1919
|
+
* Amp natively reads code review checks as Markdown files with YAML frontmatter,
|
|
1920
|
+
* scoped to the project (`.agents/checks/`) and user-wide (`~/.config/amp/checks/`).
|
|
1921
|
+
* Each check runs as a per-check subagent during code review.
|
|
1922
|
+
* @see https://ampcode.com/manual
|
|
1923
|
+
*/
|
|
1924
|
+
var AmpCheck = class AmpCheck extends ToolCheck {
|
|
1925
|
+
frontmatter;
|
|
1926
|
+
body;
|
|
1927
|
+
constructor({ frontmatter, body, fileContent, ...rest }) {
|
|
1928
|
+
if (rest.validate !== false) {
|
|
1929
|
+
const result = AmpCheckFrontmatterSchema.safeParse(frontmatter);
|
|
1930
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${join(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
1931
|
+
}
|
|
1932
|
+
super({
|
|
1933
|
+
...rest,
|
|
1934
|
+
fileContent: fileContent ?? stringifyFrontmatter(body, frontmatter)
|
|
1935
|
+
});
|
|
1936
|
+
this.frontmatter = frontmatter;
|
|
1937
|
+
this.body = body;
|
|
1938
|
+
}
|
|
1939
|
+
static getSettablePaths({ global = false } = {}) {
|
|
1940
|
+
return { relativeDirPath: global ? AMP_CHECKS_GLOBAL_DIR : AMP_CHECKS_PROJECT_DIR };
|
|
1941
|
+
}
|
|
1942
|
+
getFrontmatter() {
|
|
1943
|
+
return this.frontmatter;
|
|
1944
|
+
}
|
|
1945
|
+
getBody() {
|
|
1946
|
+
return this.body;
|
|
1947
|
+
}
|
|
1948
|
+
toRulesyncCheck() {
|
|
1949
|
+
const { name: _name, description, "severity-default": severityDefault, tools, ...restFields } = this.frontmatter;
|
|
1950
|
+
return new RulesyncCheck({
|
|
1951
|
+
outputRoot: ".",
|
|
1952
|
+
frontmatter: {
|
|
1953
|
+
targets: ["*"],
|
|
1954
|
+
...description !== void 0 && { description },
|
|
1955
|
+
...severityDefault !== void 0 && { severity: severityDefault },
|
|
1956
|
+
...tools !== void 0 && { tools },
|
|
1957
|
+
...restFields
|
|
1958
|
+
},
|
|
1959
|
+
body: this.body,
|
|
1960
|
+
relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH,
|
|
1961
|
+
relativeFilePath: this.getRelativeFilePath(),
|
|
1962
|
+
validate: true
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
static fromRulesyncCheck({ outputRoot = process.cwd(), rulesyncCheck, validate = true, global = false }) {
|
|
1966
|
+
const rulesyncFrontmatter = rulesyncCheck.getFrontmatter();
|
|
1967
|
+
const relativeFilePath = rulesyncCheck.getRelativeFilePath();
|
|
1968
|
+
const name = basename(relativeFilePath, ".md");
|
|
1969
|
+
const { targets: _targets, description, severity, tools, ...restFields } = rulesyncFrontmatter;
|
|
1970
|
+
const toolTargetKeys = new Set(ALL_TOOL_TARGETS);
|
|
1971
|
+
const passthroughFields = Object.fromEntries(Object.entries(restFields).filter(([key]) => !toolTargetKeys.has(key) && key !== "name"));
|
|
1972
|
+
const ampSection = this.filterToolSpecificSection(rulesyncFrontmatter.amp ?? {}, ["name"]);
|
|
1973
|
+
const rawAmpFrontmatter = {
|
|
1974
|
+
name,
|
|
1975
|
+
...description !== void 0 && { description },
|
|
1976
|
+
...severity !== void 0 && { "severity-default": severity },
|
|
1977
|
+
...tools !== void 0 && { tools },
|
|
1978
|
+
...passthroughFields,
|
|
1979
|
+
...ampSection
|
|
1980
|
+
};
|
|
1981
|
+
const result = AmpCheckFrontmatterSchema.safeParse(rawAmpFrontmatter);
|
|
1982
|
+
if (!result.success) throw new Error(`Invalid amp check frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
1983
|
+
const ampFrontmatter = result.data;
|
|
1984
|
+
const body = rulesyncCheck.getBody();
|
|
1985
|
+
const fileContent = stringifyFrontmatter(body, ampFrontmatter);
|
|
1986
|
+
const paths = this.getSettablePaths({ global });
|
|
1987
|
+
return new AmpCheck({
|
|
1988
|
+
outputRoot,
|
|
1989
|
+
frontmatter: ampFrontmatter,
|
|
1990
|
+
body,
|
|
1991
|
+
relativeDirPath: paths.relativeDirPath,
|
|
1992
|
+
relativeFilePath,
|
|
1993
|
+
fileContent,
|
|
1994
|
+
validate
|
|
1995
|
+
});
|
|
1996
|
+
}
|
|
1997
|
+
validate() {
|
|
1998
|
+
if (!this.frontmatter) return {
|
|
1999
|
+
success: true,
|
|
2000
|
+
error: null
|
|
2001
|
+
};
|
|
2002
|
+
const result = AmpCheckFrontmatterSchema.safeParse(this.frontmatter);
|
|
2003
|
+
if (result.success) return {
|
|
2004
|
+
success: true,
|
|
2005
|
+
error: null
|
|
2006
|
+
};
|
|
2007
|
+
else return {
|
|
2008
|
+
success: false,
|
|
2009
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${join(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
static isTargetedByRulesyncCheck(rulesyncCheck) {
|
|
2013
|
+
return this.isTargetedByRulesyncCheckDefault({
|
|
2014
|
+
rulesyncCheck,
|
|
2015
|
+
toolTarget: "amp"
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
2019
|
+
const paths = this.getSettablePaths({ global });
|
|
2020
|
+
const filePath = join(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
2021
|
+
const fileContent = await readFileContent(filePath);
|
|
2022
|
+
const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
|
|
2023
|
+
const result = AmpCheckFrontmatterSchema.safeParse(frontmatter);
|
|
2024
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
2025
|
+
return new AmpCheck({
|
|
2026
|
+
outputRoot,
|
|
2027
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2028
|
+
relativeFilePath,
|
|
2029
|
+
frontmatter: result.data,
|
|
2030
|
+
body: content.trim(),
|
|
2031
|
+
fileContent,
|
|
2032
|
+
validate
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
2036
|
+
return new AmpCheck({
|
|
2037
|
+
outputRoot,
|
|
2038
|
+
relativeDirPath,
|
|
2039
|
+
relativeFilePath,
|
|
2040
|
+
frontmatter: { name: "" },
|
|
2041
|
+
body: "",
|
|
2042
|
+
fileContent: "",
|
|
2043
|
+
validate: false
|
|
2044
|
+
});
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
2047
|
+
//#endregion
|
|
2048
|
+
//#region src/features/checks/checks-processor.ts
|
|
2049
|
+
const ChecksProcessorToolTargetSchema = z.enum(checksProcessorToolTargetTuple);
|
|
2050
|
+
/**
|
|
2051
|
+
* Factory Map mapping tool targets to their check factories.
|
|
2052
|
+
* Using Map to preserve insertion order for consistent iteration.
|
|
2053
|
+
*/
|
|
2054
|
+
const toolCheckFactories = /* @__PURE__ */ new Map([["amp", {
|
|
2055
|
+
class: AmpCheck,
|
|
2056
|
+
meta: {
|
|
2057
|
+
supportsGlobal: true,
|
|
2058
|
+
filePattern: "*.md"
|
|
2059
|
+
}
|
|
2060
|
+
}]]);
|
|
2061
|
+
const defaultGetFactory$6 = (target) => {
|
|
2062
|
+
const factory = toolCheckFactories.get(target);
|
|
2063
|
+
if (!factory) throw new Error(`Unsupported tool target: ${target}`);
|
|
2064
|
+
return factory;
|
|
2065
|
+
};
|
|
2066
|
+
const allToolTargetKeys$5 = [...toolCheckFactories.keys()];
|
|
2067
|
+
const checksProcessorToolTargets = allToolTargetKeys$5;
|
|
2068
|
+
const checksProcessorToolTargetsGlobal = allToolTargetKeys$5.filter((target) => {
|
|
2069
|
+
return toolCheckFactories.get(target)?.meta.supportsGlobal ?? false;
|
|
2070
|
+
});
|
|
2071
|
+
var ChecksProcessor = class extends FeatureProcessor {
|
|
2072
|
+
toolTarget;
|
|
2073
|
+
global;
|
|
2074
|
+
getFactory;
|
|
2075
|
+
constructor({ outputRoot = process.cwd(), inputRoot = process.cwd(), toolTarget, global = false, getFactory = defaultGetFactory$6, dryRun = false, logger }) {
|
|
2076
|
+
super({
|
|
2077
|
+
outputRoot,
|
|
2078
|
+
inputRoot,
|
|
2079
|
+
dryRun,
|
|
2080
|
+
logger
|
|
2081
|
+
});
|
|
2082
|
+
const result = ChecksProcessorToolTargetSchema.safeParse(toolTarget);
|
|
2083
|
+
if (!result.success) throw new Error(`Invalid tool target for ChecksProcessor: ${toolTarget}. ${formatError(result.error)}`);
|
|
2084
|
+
this.toolTarget = result.data;
|
|
2085
|
+
this.global = global;
|
|
2086
|
+
this.getFactory = getFactory;
|
|
2087
|
+
}
|
|
2088
|
+
async convertRulesyncFilesToToolFiles(rulesyncFiles) {
|
|
2089
|
+
const rulesyncChecks = rulesyncFiles.filter((file) => file instanceof RulesyncCheck);
|
|
2090
|
+
const factory = this.getFactory(this.toolTarget);
|
|
2091
|
+
return rulesyncChecks.filter((rulesyncCheck) => factory.class.isTargetedByRulesyncCheck(rulesyncCheck)).map((rulesyncCheck) => factory.class.fromRulesyncCheck({
|
|
2092
|
+
outputRoot: this.outputRoot,
|
|
2093
|
+
relativeDirPath: RulesyncCheck.getSettablePaths().relativeDirPath,
|
|
2094
|
+
rulesyncCheck,
|
|
2095
|
+
global: this.global
|
|
2096
|
+
}));
|
|
2097
|
+
}
|
|
2098
|
+
async convertToolFilesToRulesyncFiles(toolFiles) {
|
|
2099
|
+
return toolFiles.filter((file) => file instanceof ToolCheck).map((toolCheck) => toolCheck.toRulesyncCheck());
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Implementation of abstract method from Processor
|
|
2103
|
+
* Load and parse rulesync check files from .rulesync/checks/ directory
|
|
2104
|
+
*/
|
|
2105
|
+
async loadRulesyncFiles() {
|
|
2106
|
+
const checksDir = join(this.inputRoot, RulesyncCheck.getSettablePaths().relativeDirPath);
|
|
2107
|
+
if (!await directoryExists(checksDir)) {
|
|
2108
|
+
this.logger.debug(`Rulesync checks directory not found: ${checksDir}`);
|
|
2109
|
+
return [];
|
|
2110
|
+
}
|
|
2111
|
+
const mdFiles = (await listDirectoryFiles(checksDir)).filter((file) => file.endsWith(".md"));
|
|
2112
|
+
if (mdFiles.length === 0) {
|
|
2113
|
+
this.logger.debug(`No markdown files found in rulesync checks directory: ${checksDir}`);
|
|
2114
|
+
return [];
|
|
2115
|
+
}
|
|
2116
|
+
this.logger.debug(`Found ${mdFiles.length} check files in ${checksDir}`);
|
|
2117
|
+
const rulesyncChecks = [];
|
|
2118
|
+
for (const mdFile of mdFiles) {
|
|
2119
|
+
const filepath = join(checksDir, mdFile);
|
|
2120
|
+
try {
|
|
2121
|
+
const rulesyncCheck = await RulesyncCheck.fromFile({
|
|
2122
|
+
outputRoot: this.inputRoot,
|
|
2123
|
+
relativeFilePath: mdFile,
|
|
2124
|
+
validate: true
|
|
2125
|
+
});
|
|
2126
|
+
rulesyncChecks.push(rulesyncCheck);
|
|
2127
|
+
this.logger.debug(`Successfully loaded check: ${mdFile}`);
|
|
2128
|
+
} catch (error) {
|
|
2129
|
+
this.logger.warn(`Failed to load check file ${filepath}: ${formatError(error)}`);
|
|
2130
|
+
continue;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
this.logger.debug(`Successfully loaded ${rulesyncChecks.length} rulesync checks`);
|
|
2134
|
+
return rulesyncChecks;
|
|
2135
|
+
}
|
|
2136
|
+
/**
|
|
2137
|
+
* Implementation of abstract method from Processor
|
|
2138
|
+
* Load tool-specific check files and parse them into ToolCheck instances
|
|
2139
|
+
*/
|
|
2140
|
+
async loadToolFiles({ forDeletion = false } = {}) {
|
|
2141
|
+
const factory = this.getFactory(this.toolTarget);
|
|
2142
|
+
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
2143
|
+
const baseDir = join(this.outputRoot, paths.relativeDirPath);
|
|
2144
|
+
const checkFilePaths = await findFilesByGlobs(join(baseDir, factory.meta.filePattern));
|
|
2145
|
+
const toRelativeFilePath = (path) => relative(baseDir, path);
|
|
2146
|
+
if (forDeletion) return checkFilePaths.map((path) => factory.class.forDeletion({
|
|
2147
|
+
outputRoot: this.outputRoot,
|
|
2148
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2149
|
+
relativeFilePath: toRelativeFilePath(path),
|
|
2150
|
+
global: this.global
|
|
2151
|
+
})).filter((check) => check.isDeletable());
|
|
2152
|
+
const loaded = await Promise.all(checkFilePaths.map((path) => factory.class.fromFile({
|
|
2153
|
+
outputRoot: this.outputRoot,
|
|
2154
|
+
relativeDirPath: paths.relativeDirPath,
|
|
2155
|
+
relativeFilePath: toRelativeFilePath(path),
|
|
2156
|
+
global: this.global
|
|
2157
|
+
})));
|
|
2158
|
+
this.logger.debug(`Successfully loaded ${loaded.length} ${this.toolTarget} checks from ${paths.relativeDirPath}`);
|
|
2159
|
+
return loaded;
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Implementation of abstract method from FeatureProcessor
|
|
2163
|
+
* Return the tool targets that this processor supports
|
|
2164
|
+
*/
|
|
2165
|
+
static getToolTargets({ global = false } = {}) {
|
|
2166
|
+
if (global) return [...checksProcessorToolTargetsGlobal];
|
|
2167
|
+
return [...checksProcessorToolTargets];
|
|
2168
|
+
}
|
|
2169
|
+
static getToolTargetsSimulated() {
|
|
2170
|
+
return [];
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Get the factory for a specific tool target.
|
|
2174
|
+
* This is a static version of the internal getFactory for external use.
|
|
2175
|
+
* @param target - The tool target. Must be a valid ChecksProcessorToolTarget.
|
|
2176
|
+
* @returns The factory for the target, or undefined if not found.
|
|
2177
|
+
*/
|
|
2178
|
+
static getFactory(target) {
|
|
2179
|
+
const result = ChecksProcessorToolTargetSchema.safeParse(target);
|
|
2180
|
+
if (!result.success) return;
|
|
2181
|
+
return toolCheckFactories.get(result.data);
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
//#endregion
|
|
2185
|
+
//#region src/constants/agentsmd-paths.ts
|
|
2186
|
+
const AGENTSMD_DIR = ".agents";
|
|
2187
|
+
const AGENTSMD_MEMORIES_DIR_PATH = join(AGENTSMD_DIR, "memories");
|
|
2188
|
+
const AGENTSMD_COMMANDS_DIR_PATH = join(AGENTSMD_DIR, "commands");
|
|
2189
|
+
const AGENTSMD_SKILLS_DIR_PATH = join(AGENTSMD_DIR, "skills");
|
|
2190
|
+
const AGENTSMD_SUBAGENTS_DIR_PATH = join(AGENTSMD_DIR, "subagents");
|
|
2191
|
+
const AGENTSMD_RULE_FILE_NAME = "AGENTS.md";
|
|
2192
|
+
//#endregion
|
|
1775
2193
|
//#region src/features/commands/tool-command.ts
|
|
1776
2194
|
/**
|
|
1777
2195
|
* Abstract base class for AI development tool-specific command formats.
|
|
@@ -2019,13 +2437,6 @@ const AntigravityCommandFrontmatterSchema = z.looseObject({
|
|
|
2019
2437
|
...AntigravityWorkflowFrontmatterSchema.shape
|
|
2020
2438
|
});
|
|
2021
2439
|
//#endregion
|
|
2022
|
-
//#region src/types/rulesync-file.ts
|
|
2023
|
-
var RulesyncFile = class extends AiFile {
|
|
2024
|
-
static async fromFile(_params) {
|
|
2025
|
-
throw new Error("Please implement this method in the subclass.");
|
|
2026
|
-
}
|
|
2027
|
-
};
|
|
2028
|
-
//#endregion
|
|
2029
2440
|
//#region src/features/commands/rulesync-command.ts
|
|
2030
2441
|
const RulesyncCommandFrontmatterSchema = z.looseObject({
|
|
2031
2442
|
targets: z._default(RulesyncTargetsSchema, ["*"]),
|
|
@@ -3086,135 +3497,118 @@ var CursorCommand = class CursorCommand extends ToolCommand {
|
|
|
3086
3497
|
//#endregion
|
|
3087
3498
|
//#region src/constants/devin-paths.ts
|
|
3088
3499
|
const DEVIN_DIR = ".devin";
|
|
3089
|
-
const CODEIUM_WINDSURF_DIR = join(".codeium", "windsurf");
|
|
3090
|
-
const DEVIN_WORKFLOWS_DIR_PATH = join(DEVIN_DIR, "workflows");
|
|
3091
3500
|
const DEVIN_SKILLS_DIR_PATH = join(DEVIN_DIR, "skills");
|
|
3092
3501
|
const DEVIN_AGENTS_DIR_PATH = join(DEVIN_DIR, "agents");
|
|
3093
3502
|
const DEVIN_GLOBAL_CONFIG_DIR_PATH = join(".config", "devin");
|
|
3094
3503
|
const DEVIN_GLOBAL_AGENTS_DIR_PATH = join(DEVIN_GLOBAL_CONFIG_DIR_PATH, "agents");
|
|
3095
3504
|
const DEVIN_GLOBAL_SKILLS_DIR_PATH = join(DEVIN_GLOBAL_CONFIG_DIR_PATH, "skills");
|
|
3096
|
-
const CODEIUM_WINDSURF_GLOBAL_WORKFLOWS_DIR_PATH = join(CODEIUM_WINDSURF_DIR, "global_workflows");
|
|
3097
3505
|
const DEVIN_CONFIG_FILE_NAME = "config.json";
|
|
3098
3506
|
const DEVIN_HOOKS_V1_FILE_NAME = "hooks.v1.json";
|
|
3099
3507
|
const DEVIN_GLOBAL_AGENTS_FILE_NAME = "AGENTS.md";
|
|
3100
3508
|
const DEVIN_IGNORE_FILE_NAME = ".devinignore";
|
|
3101
3509
|
const DEVIN_LEGACY_IGNORE_FILE_NAME = ".codeiumignore";
|
|
3102
3510
|
//#endregion
|
|
3511
|
+
//#region src/constants/general.ts
|
|
3512
|
+
const SKILL_FILE_NAME$1 = "SKILL.md";
|
|
3513
|
+
//#endregion
|
|
3514
|
+
//#region src/features/commands/command-skill-ownership.ts
|
|
3515
|
+
/**
|
|
3516
|
+
* Slug used for the per-command `<slug>/SKILL.md` directory when a tool's
|
|
3517
|
+
* commands are emitted onto its skills surface (Devin, Hermes Agent).
|
|
3518
|
+
*/
|
|
3519
|
+
function commandSlug(relativeFilePath) {
|
|
3520
|
+
return basename(relativeFilePath, ".md").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
3521
|
+
}
|
|
3522
|
+
/**
|
|
3523
|
+
* Whether a rulesync command exists whose slug matches `dirName`.
|
|
3524
|
+
*
|
|
3525
|
+
* Used by the skills-surface `isDirOwned` hooks of tools whose commands are
|
|
3526
|
+
* emitted as `<slug>/SKILL.md` into the skills tree: a directory matching a
|
|
3527
|
+
* current command slug is owned by the commands feature, so the skills
|
|
3528
|
+
* feature must neither import it as a skill nor delete it as an orphan
|
|
3529
|
+
* skill. Once the command is removed from `.rulesync/commands/`, the
|
|
3530
|
+
* directory stops matching and the skills feature cleans it up as a regular
|
|
3531
|
+
* orphan.
|
|
3532
|
+
*/
|
|
3533
|
+
async function rulesyncCommandSlugExists({ inputRoot, dirName }) {
|
|
3534
|
+
return (await findFilesByGlobs(join(inputRoot, RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "**", "*.md"))).some((filePath) => commandSlug(basename(filePath)) === dirName);
|
|
3535
|
+
}
|
|
3536
|
+
//#endregion
|
|
3103
3537
|
//#region src/features/commands/devin-command.ts
|
|
3104
|
-
|
|
3538
|
+
function commandSkillContent$1(rulesyncCommand) {
|
|
3539
|
+
const slug = commandSlug(rulesyncCommand.getRelativeFilePath());
|
|
3540
|
+
const description = rulesyncCommand.getFrontmatter().description ?? `${slug} command`;
|
|
3541
|
+
return stringifyFrontmatter(rulesyncCommand.getBody().trim(), {
|
|
3542
|
+
name: slug,
|
|
3543
|
+
description
|
|
3544
|
+
});
|
|
3545
|
+
}
|
|
3105
3546
|
/**
|
|
3106
|
-
* Represents a Devin
|
|
3107
|
-
*
|
|
3108
|
-
*
|
|
3109
|
-
*
|
|
3110
|
-
*
|
|
3547
|
+
* Represents a Devin slash command, emitted as a Devin Skill.
|
|
3548
|
+
*
|
|
3549
|
+
* Devin's extensibility docs no longer document a standalone
|
|
3550
|
+
* workflows/commands component — reusable prompts invoked as slash commands
|
|
3551
|
+
* are Skills (`/name`). Commands are therefore emitted onto the native skills
|
|
3552
|
+
* surface, one `SKILL.md` per command: `.devin/skills/<slug>/SKILL.md`
|
|
3553
|
+
* (project) and `~/.config/devin/skills/<slug>/SKILL.md` (global). The legacy
|
|
3554
|
+
* Windsurf/Cascade-era `.devin/workflows/` and
|
|
3555
|
+
* `~/.codeium/windsurf/global_workflows/` locations are no longer emitted.
|
|
3556
|
+
*
|
|
3557
|
+
* Import and deletion are intentionally no-ops for this target: the skills
|
|
3558
|
+
* feature owns the `.devin/skills/` tree, so importing it as commands would
|
|
3559
|
+
* double-import every skill (mirrors the Hermes Agent commands target).
|
|
3560
|
+
*
|
|
3561
|
+
* @see https://docs.devin.ai/cli/extensibility
|
|
3562
|
+
* @see https://docs.devin.ai/cli/extensibility/skills/overview
|
|
3111
3563
|
*/
|
|
3112
3564
|
var DevinCommand = class DevinCommand extends ToolCommand {
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
const result = DevinCommandFrontmatterSchema.safeParse(frontmatter);
|
|
3118
|
-
if (!result.success) throw new Error(`Invalid frontmatter in ${join(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
3119
|
-
}
|
|
3120
|
-
super({
|
|
3121
|
-
...rest,
|
|
3122
|
-
fileContent: stringifyFrontmatter(body, frontmatter)
|
|
3565
|
+
static isTargetedByRulesyncCommand(rulesyncCommand) {
|
|
3566
|
+
return this.isTargetedByRulesyncCommandDefault({
|
|
3567
|
+
rulesyncCommand,
|
|
3568
|
+
toolTarget: "devin"
|
|
3123
3569
|
});
|
|
3124
|
-
this.frontmatter = frontmatter;
|
|
3125
|
-
this.body = body;
|
|
3126
3570
|
}
|
|
3127
3571
|
static getSettablePaths({ global = false } = {}) {
|
|
3128
|
-
|
|
3129
|
-
return { relativeDirPath: DEVIN_WORKFLOWS_DIR_PATH };
|
|
3130
|
-
}
|
|
3131
|
-
getBody() {
|
|
3132
|
-
return this.body;
|
|
3133
|
-
}
|
|
3134
|
-
getFrontmatter() {
|
|
3135
|
-
return this.frontmatter;
|
|
3572
|
+
return { relativeDirPath: global ? DEVIN_GLOBAL_SKILLS_DIR_PATH : DEVIN_SKILLS_DIR_PATH };
|
|
3136
3573
|
}
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
|
|
3145
|
-
return new RulesyncCommand({
|
|
3146
|
-
outputRoot: process.cwd(),
|
|
3147
|
-
frontmatter: rulesyncFrontmatter,
|
|
3148
|
-
body: this.body,
|
|
3149
|
-
relativeDirPath: RulesyncCommand.getSettablePaths().relativeDirPath,
|
|
3150
|
-
relativeFilePath: this.relativeFilePath,
|
|
3151
|
-
fileContent,
|
|
3152
|
-
validate: true
|
|
3153
|
-
});
|
|
3154
|
-
}
|
|
3155
|
-
static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
|
|
3156
|
-
const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
|
|
3157
|
-
const devinFields = rulesyncFrontmatter.devin ?? {};
|
|
3158
|
-
const devinFrontmatter = {
|
|
3159
|
-
description: rulesyncFrontmatter.description,
|
|
3160
|
-
...devinFields
|
|
3161
|
-
};
|
|
3162
|
-
const body = rulesyncCommand.getBody();
|
|
3163
|
-
const paths = this.getSettablePaths({ global });
|
|
3164
|
-
return new DevinCommand({
|
|
3165
|
-
outputRoot,
|
|
3166
|
-
frontmatter: devinFrontmatter,
|
|
3167
|
-
body,
|
|
3168
|
-
relativeDirPath: paths.relativeDirPath,
|
|
3169
|
-
relativeFilePath: rulesyncCommand.getRelativeFilePath(),
|
|
3170
|
-
validate
|
|
3574
|
+
constructor({ slug, ...params }) {
|
|
3575
|
+
super({
|
|
3576
|
+
...params,
|
|
3577
|
+
...slug !== void 0 && {
|
|
3578
|
+
relativeDirPath: join(params.relativeDirPath, slug),
|
|
3579
|
+
relativeFilePath: "SKILL.md"
|
|
3580
|
+
}
|
|
3171
3581
|
});
|
|
3172
3582
|
}
|
|
3173
3583
|
validate() {
|
|
3174
|
-
|
|
3175
|
-
success: true,
|
|
3176
|
-
error: null
|
|
3177
|
-
};
|
|
3178
|
-
const result = DevinCommandFrontmatterSchema.safeParse(this.frontmatter);
|
|
3179
|
-
if (result.success) return {
|
|
3584
|
+
return {
|
|
3180
3585
|
success: true,
|
|
3181
3586
|
error: null
|
|
3182
3587
|
};
|
|
3183
|
-
else return {
|
|
3184
|
-
success: false,
|
|
3185
|
-
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${join(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
3186
|
-
};
|
|
3187
3588
|
}
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3589
|
+
toRulesyncCommand() {
|
|
3590
|
+
const slug = basename(dirname(this.getRelativePathFromCwd()));
|
|
3591
|
+
const { frontmatter, body } = parseFrontmatter(this.getFileContent(), this.getFilePath());
|
|
3592
|
+
const description = typeof frontmatter.description === "string" ? frontmatter.description : void 0;
|
|
3593
|
+
return new RulesyncCommand({
|
|
3594
|
+
relativeDirPath: RULESYNC_COMMANDS_RELATIVE_DIR_PATH,
|
|
3595
|
+
relativeFilePath: `${slug}.md`,
|
|
3596
|
+
frontmatter: { description },
|
|
3597
|
+
body: body.trimStart()
|
|
3192
3598
|
});
|
|
3193
3599
|
}
|
|
3194
|
-
static
|
|
3195
|
-
const paths =
|
|
3196
|
-
const filePath = join(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
3197
|
-
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
3198
|
-
const result = DevinCommandFrontmatterSchema.safeParse(frontmatter);
|
|
3199
|
-
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
3600
|
+
static fromRulesyncCommand({ outputRoot, rulesyncCommand, global = false }) {
|
|
3601
|
+
const paths = DevinCommand.getSettablePaths({ global });
|
|
3200
3602
|
return new DevinCommand({
|
|
3201
3603
|
outputRoot,
|
|
3202
3604
|
relativeDirPath: paths.relativeDirPath,
|
|
3203
|
-
relativeFilePath,
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
validate
|
|
3605
|
+
relativeFilePath: SKILL_FILE_NAME$1,
|
|
3606
|
+
slug: commandSlug(rulesyncCommand.getRelativeFilePath()),
|
|
3607
|
+
fileContent: commandSkillContent$1(rulesyncCommand)
|
|
3207
3608
|
});
|
|
3208
3609
|
}
|
|
3209
|
-
|
|
3210
|
-
return
|
|
3211
|
-
outputRoot,
|
|
3212
|
-
relativeDirPath,
|
|
3213
|
-
relativeFilePath,
|
|
3214
|
-
frontmatter: { description: "" },
|
|
3215
|
-
body: "",
|
|
3216
|
-
validate: false
|
|
3217
|
-
});
|
|
3610
|
+
getFileContent() {
|
|
3611
|
+
return this.fileContent;
|
|
3218
3612
|
}
|
|
3219
3613
|
};
|
|
3220
3614
|
//#endregion
|
|
@@ -3542,10 +3936,7 @@ const HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_MANIFEST_PATH = join(HERMESAGENT_RUL
|
|
|
3542
3936
|
const HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_INIT_PATH = join(HERMESAGENT_RULESYNC_SUBAGENTS_PLUGIN_DIR_PATH, "__init__.py");
|
|
3543
3937
|
//#endregion
|
|
3544
3938
|
//#region src/features/commands/hermesagent-command.ts
|
|
3545
|
-
const SKILL_FILE_NAME
|
|
3546
|
-
function commandSlug(relativeFilePath) {
|
|
3547
|
-
return basename(relativeFilePath, ".md").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
3548
|
-
}
|
|
3939
|
+
const SKILL_FILE_NAME = "SKILL.md";
|
|
3549
3940
|
function commandSkillContent(rulesyncCommand) {
|
|
3550
3941
|
const slug = commandSlug(rulesyncCommand.getRelativeFilePath());
|
|
3551
3942
|
const description = rulesyncCommand.getFrontmatter().description ?? `${slug} command`;
|
|
@@ -3562,7 +3953,7 @@ var HermesagentCommand = class HermesagentCommand extends ToolCommand {
|
|
|
3562
3953
|
static getSettablePaths({ slug = "command" } = {}) {
|
|
3563
3954
|
return {
|
|
3564
3955
|
relativeDirPath: join(HERMESAGENT_SKILLS_DIR_PATH, slug),
|
|
3565
|
-
relativeFilePath: SKILL_FILE_NAME
|
|
3956
|
+
relativeFilePath: SKILL_FILE_NAME
|
|
3566
3957
|
};
|
|
3567
3958
|
}
|
|
3568
3959
|
constructor({ slug, ...params }) {
|
|
@@ -3593,7 +3984,7 @@ var HermesagentCommand = class HermesagentCommand extends ToolCommand {
|
|
|
3593
3984
|
return new HermesagentCommand({
|
|
3594
3985
|
outputRoot,
|
|
3595
3986
|
relativeDirPath: "",
|
|
3596
|
-
relativeFilePath: SKILL_FILE_NAME
|
|
3987
|
+
relativeFilePath: SKILL_FILE_NAME,
|
|
3597
3988
|
slug: commandSlug(rulesyncCommand.getRelativeFilePath()),
|
|
3598
3989
|
fileContent: commandSkillContent(rulesyncCommand)
|
|
3599
3990
|
});
|
|
@@ -4828,6 +5219,7 @@ const PI_AGENT_SKILLS_DIR_PATH = join(PI_AGENT_DIR, "skills");
|
|
|
4828
5219
|
const PI_PROMPTS_DIR_PATH = join(".pi", "prompts");
|
|
4829
5220
|
const PI_SKILLS_DIR_PATH = join(".pi", "skills");
|
|
4830
5221
|
const PI_RULE_FILE_NAME = "AGENTS.md";
|
|
5222
|
+
const PI_APPEND_SYSTEM_FILE_NAME = "APPEND_SYSTEM.md";
|
|
4831
5223
|
//#endregion
|
|
4832
5224
|
//#region src/features/commands/pi-command.ts
|
|
4833
5225
|
/**
|
|
@@ -5092,6 +5484,9 @@ const REASONIX_SETTINGS_FILE_NAME = "settings.json";
|
|
|
5092
5484
|
const REASONIX_COMMANDS_DIR_PATH = join(REASONIX_DIR, "commands");
|
|
5093
5485
|
const REASONIX_RULE_FILE_NAME = "REASONIX.md";
|
|
5094
5486
|
const REASONIX_SKILLS_DIR_PATH = join(REASONIX_DIR, "skills");
|
|
5487
|
+
const REASONIX_SUBAGENTS_DIR_PATH = REASONIX_SKILLS_DIR_PATH;
|
|
5488
|
+
const REASONIX_SUBAGENT_INVOCATION = "manual";
|
|
5489
|
+
const REASONIX_SUBAGENT_RUN_AS = "subagent";
|
|
5095
5490
|
//#endregion
|
|
5096
5491
|
//#region src/features/commands/reasonix-command.ts
|
|
5097
5492
|
/**
|
|
@@ -5359,9 +5754,6 @@ const ROVODEV_AGENTS_SKILLS_DIR_PATH = join(".agents", "skills");
|
|
|
5359
5754
|
const ROVODEV_PROMPTS_FILE_NAME = "prompts.yml";
|
|
5360
5755
|
const ROVODEV_PROMPTS_DIR_PATH = join(ROVODEV_DIR, "prompts");
|
|
5361
5756
|
//#endregion
|
|
5362
|
-
//#region src/types/tool-file.ts
|
|
5363
|
-
var ToolFile = class extends AiFile {};
|
|
5364
|
-
//#endregion
|
|
5365
5757
|
//#region src/features/commands/rovodev-command.ts
|
|
5366
5758
|
/**
|
|
5367
5759
|
* Rovo Dev CLI "saved prompts": a file-based custom-command surface made of a
|
|
@@ -5850,7 +6242,8 @@ const toolCommandFactories = /* @__PURE__ */ new Map([
|
|
|
5850
6242
|
supportsProject: false,
|
|
5851
6243
|
supportsGlobal: true,
|
|
5852
6244
|
isSimulated: false,
|
|
5853
|
-
supportsSubdirectory: true
|
|
6245
|
+
supportsSubdirectory: true,
|
|
6246
|
+
skipToolFileScan: true
|
|
5854
6247
|
}
|
|
5855
6248
|
}],
|
|
5856
6249
|
["junie", {
|
|
@@ -5980,7 +6373,8 @@ const toolCommandFactories = /* @__PURE__ */ new Map([
|
|
|
5980
6373
|
supportsProject: true,
|
|
5981
6374
|
supportsGlobal: true,
|
|
5982
6375
|
isSimulated: false,
|
|
5983
|
-
supportsSubdirectory: false
|
|
6376
|
+
supportsSubdirectory: false,
|
|
6377
|
+
skipToolFileScan: true
|
|
5984
6378
|
}
|
|
5985
6379
|
}]
|
|
5986
6380
|
]);
|
|
@@ -6083,6 +6477,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
6083
6477
|
*/
|
|
6084
6478
|
async loadToolFiles({ forDeletion = false } = {}) {
|
|
6085
6479
|
const factory = this.getFactory(this.toolTarget);
|
|
6480
|
+
if (factory.meta.skipToolFileScan) return [];
|
|
6086
6481
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
6087
6482
|
const outputRootFull = join(this.outputRoot, paths.relativeDirPath);
|
|
6088
6483
|
const commandFilePaths = await findFilesByGlobs(factory.meta.supportsSubdirectory ? join(outputRootFull, "**", `*.${factory.meta.extension}`) : join(outputRootFull, `*.${factory.meta.extension}`));
|
|
@@ -6192,7 +6587,10 @@ const HookDefinitionSchema = z.looseObject({
|
|
|
6192
6587
|
type: z.optional(z.enum([
|
|
6193
6588
|
"command",
|
|
6194
6589
|
"prompt",
|
|
6195
|
-
"http"
|
|
6590
|
+
"http",
|
|
6591
|
+
"agent",
|
|
6592
|
+
"mcp_tool",
|
|
6593
|
+
"function"
|
|
6196
6594
|
])),
|
|
6197
6595
|
url: z.optional(safeString),
|
|
6198
6596
|
timeout: z.optional(z.number()),
|
|
@@ -6205,12 +6603,71 @@ const HookDefinitionSchema = z.looseObject({
|
|
|
6205
6603
|
sequential: z.optional(z.boolean()),
|
|
6206
6604
|
async: z.optional(z.boolean()),
|
|
6207
6605
|
env: z.optional(z.record(z.string(), safeString)),
|
|
6208
|
-
shell: z.optional(
|
|
6606
|
+
shell: z.optional(z.enum(["bash", "powershell"])),
|
|
6209
6607
|
statusMessage: z.optional(safeString),
|
|
6210
6608
|
headers: z.optional(z.record(z.string(), safeString)),
|
|
6211
6609
|
allowedEnvVars: z.optional(z.array(z.string())),
|
|
6212
|
-
once: z.optional(z.boolean())
|
|
6610
|
+
once: z.optional(z.boolean()),
|
|
6611
|
+
server: z.optional(safeString),
|
|
6612
|
+
tool: z.optional(safeString),
|
|
6613
|
+
input: z.optional(z.looseObject({})),
|
|
6614
|
+
model: z.optional(safeString)
|
|
6213
6615
|
});
|
|
6616
|
+
/**
|
|
6617
|
+
* All canonical hook event names.
|
|
6618
|
+
* Each tool supports a subset of these events.
|
|
6619
|
+
*/
|
|
6620
|
+
const HOOK_EVENTS = [
|
|
6621
|
+
"sessionStart",
|
|
6622
|
+
"sessionEnd",
|
|
6623
|
+
"preToolUse",
|
|
6624
|
+
"postToolUse",
|
|
6625
|
+
"preModelInvocation",
|
|
6626
|
+
"postModelInvocation",
|
|
6627
|
+
"beforeSubmitPrompt",
|
|
6628
|
+
"stop",
|
|
6629
|
+
"subagentStop",
|
|
6630
|
+
"preCompact",
|
|
6631
|
+
"postCompact",
|
|
6632
|
+
"contextOffload",
|
|
6633
|
+
"postToolUseFailure",
|
|
6634
|
+
"subagentStart",
|
|
6635
|
+
"beforeShellExecution",
|
|
6636
|
+
"afterShellExecution",
|
|
6637
|
+
"beforeMCPExecution",
|
|
6638
|
+
"afterMCPExecution",
|
|
6639
|
+
"beforeReadFile",
|
|
6640
|
+
"afterFileEdit",
|
|
6641
|
+
"beforeAgentResponse",
|
|
6642
|
+
"afterAgentResponse",
|
|
6643
|
+
"afterAgentThought",
|
|
6644
|
+
"beforeTabFileRead",
|
|
6645
|
+
"afterTabFileEdit",
|
|
6646
|
+
"permissionRequest",
|
|
6647
|
+
"notification",
|
|
6648
|
+
"setup",
|
|
6649
|
+
"afterError",
|
|
6650
|
+
"beforeToolSelection",
|
|
6651
|
+
"worktreeCreate",
|
|
6652
|
+
"worktreeRemove",
|
|
6653
|
+
"workspaceOpen",
|
|
6654
|
+
"messageDisplay",
|
|
6655
|
+
"todoCreated",
|
|
6656
|
+
"todoCompleted",
|
|
6657
|
+
"stopFailure",
|
|
6658
|
+
"instructionsLoaded",
|
|
6659
|
+
"userPromptExpansion",
|
|
6660
|
+
"postToolBatch",
|
|
6661
|
+
"permissionDenied",
|
|
6662
|
+
"taskCreated",
|
|
6663
|
+
"taskCompleted",
|
|
6664
|
+
"teammateIdle",
|
|
6665
|
+
"configChange",
|
|
6666
|
+
"cwdChanged",
|
|
6667
|
+
"fileChanged",
|
|
6668
|
+
"elicitation",
|
|
6669
|
+
"elicitationResult"
|
|
6670
|
+
];
|
|
6214
6671
|
/** Hook events supported by Cursor. */
|
|
6215
6672
|
const CURSOR_HOOK_EVENTS = [
|
|
6216
6673
|
"sessionStart",
|
|
@@ -6685,12 +7142,28 @@ const CANONICAL_TO_HERMESAGENT_EVENT_NAMES = {
|
|
|
6685
7142
|
*/
|
|
6686
7143
|
const HERMESAGENT_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_HERMESAGENT_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
6687
7144
|
const hooksRecordSchema = z.record(z.string(), z.array(HookDefinitionSchema));
|
|
7145
|
+
const HOOK_EVENT_SET = new Set(HOOK_EVENTS);
|
|
7146
|
+
/** Whether `value` is a canonical hook event name. */
|
|
7147
|
+
const isHookEvent = (value) => HOOK_EVENT_SET.has(value);
|
|
7148
|
+
/**
|
|
7149
|
+
* Top-level `hooks` record whose keys must be canonical event names, so typos
|
|
7150
|
+
* are rejected at parse time. Keys are validated with a refinement (instead of
|
|
7151
|
+
* an enum key schema) to keep the inferred type a plain string record.
|
|
7152
|
+
*
|
|
7153
|
+
* The per-tool override blocks below deliberately keep the lenient
|
|
7154
|
+
* `hooksRecordSchema`: some are documented to pass tool-native event keys
|
|
7155
|
+
* through verbatim (e.g. kiro-ide's IDE-only `PostFileSave`/`PreTaskExec`
|
|
7156
|
+
* triggers), which the canonical enum would reject.
|
|
7157
|
+
*/
|
|
7158
|
+
const canonicalHooksRecordSchema = z.record(z.string(), z.array(HookDefinitionSchema)).check(z.refine((record) => Object.keys(record).every((key) => HOOK_EVENT_SET.has(key)), { error: (issue) => {
|
|
7159
|
+
return `unknown hook event name(s): ${Object.keys(issue.input ?? {}).filter((key) => !HOOK_EVENT_SET.has(key)).join(", ")}`;
|
|
7160
|
+
} }));
|
|
6688
7161
|
/**
|
|
6689
7162
|
* Canonical hooks config (canonical event names in camelCase).
|
|
6690
7163
|
*/
|
|
6691
7164
|
const HooksConfigSchema = z.looseObject({
|
|
6692
7165
|
version: z.optional(z.number()),
|
|
6693
|
-
hooks:
|
|
7166
|
+
hooks: canonicalHooksRecordSchema,
|
|
6694
7167
|
cursor: z.optional(z.looseObject({ hooks: z.optional(hooksRecordSchema) })),
|
|
6695
7168
|
claudecode: z.optional(z.looseObject({ hooks: z.optional(hooksRecordSchema) })),
|
|
6696
7169
|
copilot: z.optional(z.looseObject({ hooks: z.optional(hooksRecordSchema) })),
|
|
@@ -7127,6 +7600,20 @@ const CANONICAL_TO_GROKCLI_EVENT_NAMES = {
|
|
|
7127
7600
|
*/
|
|
7128
7601
|
const GROKCLI_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANONICAL_TO_GROKCLI_EVENT_NAMES).map(([k, v]) => [v, k]));
|
|
7129
7602
|
//#endregion
|
|
7603
|
+
//#region src/utils/object.ts
|
|
7604
|
+
/**
|
|
7605
|
+
* Return a shallow copy of `obj` keeping only the entries whose value is
|
|
7606
|
+
* neither `undefined` nor `null`.
|
|
7607
|
+
*
|
|
7608
|
+
* Used to assemble generated config objects without one conditional spread per
|
|
7609
|
+
* optional field (which would otherwise exceed the lint complexity budget).
|
|
7610
|
+
*/
|
|
7611
|
+
function compact(obj) {
|
|
7612
|
+
const result = {};
|
|
7613
|
+
for (const [key, value] of Object.entries(obj)) if (value !== void 0 && value !== null) result[key] = value;
|
|
7614
|
+
return result;
|
|
7615
|
+
}
|
|
7616
|
+
//#endregion
|
|
7130
7617
|
//#region src/features/hooks/tool-hooks-converter.ts
|
|
7131
7618
|
function isToolMatcherEntry(x) {
|
|
7132
7619
|
if (x === null || typeof x !== "object") return false;
|
|
@@ -7184,6 +7671,25 @@ function importBooleanPassthroughFields({ h, converterConfig }) {
|
|
|
7184
7671
|
return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ tool }) => typeof h[tool] === "boolean").map(({ canonical, tool }) => [canonical, h[tool]]));
|
|
7185
7672
|
}
|
|
7186
7673
|
/**
|
|
7674
|
+
* Emit the payload fields specific to a hook type — `url`/`headers`/
|
|
7675
|
+
* `allowedEnvVars` for http, `server`/`tool`/`input` for mcp_tool, `model`
|
|
7676
|
+
* for prompt/agent. https://code.claude.com/docs/en/hooks
|
|
7677
|
+
*/
|
|
7678
|
+
function emitTypePayloadFields({ def, hookType, converterConfig }) {
|
|
7679
|
+
if (hookType === "http") return compact({
|
|
7680
|
+
url: def.url,
|
|
7681
|
+
headers: def.headers,
|
|
7682
|
+
allowedEnvVars: def.allowedEnvVars
|
|
7683
|
+
});
|
|
7684
|
+
if (hookType === "mcp_tool") return compact({
|
|
7685
|
+
server: def.server,
|
|
7686
|
+
tool: def.tool,
|
|
7687
|
+
input: def.input
|
|
7688
|
+
});
|
|
7689
|
+
if ((hookType === "prompt" || hookType === "agent") && converterConfig.emitsPromptModel) return compact({ model: def.model });
|
|
7690
|
+
return {};
|
|
7691
|
+
}
|
|
7692
|
+
/**
|
|
7187
7693
|
* Convert the definitions of a single matcher group into tool hook entries,
|
|
7188
7694
|
* honoring supported hook types and passthrough fields.
|
|
7189
7695
|
*/
|
|
@@ -7205,6 +7711,11 @@ function buildToolHooks({ defs, converterConfig }) {
|
|
|
7205
7711
|
...command !== void 0 && command !== null && { command },
|
|
7206
7712
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
|
|
7207
7713
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt },
|
|
7714
|
+
...emitTypePayloadFields({
|
|
7715
|
+
def,
|
|
7716
|
+
hookType,
|
|
7717
|
+
converterConfig
|
|
7718
|
+
}),
|
|
7208
7719
|
...converterConfig.passthroughFields?.includes("name") && def.name !== void 0 && def.name !== null && { name: def.name },
|
|
7209
7720
|
...converterConfig.passthroughFields?.includes("description") && def.description !== void 0 && def.description !== null && { description: def.description }
|
|
7210
7721
|
});
|
|
@@ -7271,6 +7782,46 @@ function stripCommandPrefix({ command, converterConfig }) {
|
|
|
7271
7782
|
return cmd;
|
|
7272
7783
|
}
|
|
7273
7784
|
/**
|
|
7785
|
+
* Hook types preserved verbatim on import — Claude Code's five documented
|
|
7786
|
+
* handler types. Anything else is coerced to `command` as before.
|
|
7787
|
+
* https://code.claude.com/docs/en/hooks
|
|
7788
|
+
*/
|
|
7789
|
+
const IMPORTED_HOOK_TYPES = /* @__PURE__ */ new Set([
|
|
7790
|
+
"command",
|
|
7791
|
+
"prompt",
|
|
7792
|
+
"http",
|
|
7793
|
+
"mcp_tool",
|
|
7794
|
+
"agent"
|
|
7795
|
+
]);
|
|
7796
|
+
function isImportedHookType(value) {
|
|
7797
|
+
return typeof value === "string" && IMPORTED_HOOK_TYPES.has(value);
|
|
7798
|
+
}
|
|
7799
|
+
function isStringRecord(value) {
|
|
7800
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
7801
|
+
return Object.values(value).every((v) => typeof v === "string");
|
|
7802
|
+
}
|
|
7803
|
+
function isStringArray(value) {
|
|
7804
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
7805
|
+
}
|
|
7806
|
+
/**
|
|
7807
|
+
* Import the payload fields specific to a hook type, type-checking each raw
|
|
7808
|
+
* value before it enters the canonical definition.
|
|
7809
|
+
*/
|
|
7810
|
+
function importTypePayloadFields({ h, hookType }) {
|
|
7811
|
+
if (hookType === "http") return {
|
|
7812
|
+
...typeof h.url === "string" && { url: h.url },
|
|
7813
|
+
...isStringRecord(h.headers) && { headers: h.headers },
|
|
7814
|
+
...isStringArray(h.allowedEnvVars) && { allowedEnvVars: h.allowedEnvVars }
|
|
7815
|
+
};
|
|
7816
|
+
if (hookType === "mcp_tool") return {
|
|
7817
|
+
...typeof h.server === "string" && { server: h.server },
|
|
7818
|
+
...typeof h.tool === "string" && { tool: h.tool },
|
|
7819
|
+
...h.input !== null && typeof h.input === "object" && !Array.isArray(h.input) && { input: h.input }
|
|
7820
|
+
};
|
|
7821
|
+
if (hookType === "prompt" || hookType === "agent") return typeof h.model === "string" ? { model: h.model } : {};
|
|
7822
|
+
return {};
|
|
7823
|
+
}
|
|
7824
|
+
/**
|
|
7274
7825
|
* Convert a single tool hook record into a canonical hook definition.
|
|
7275
7826
|
*/
|
|
7276
7827
|
function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
@@ -7278,7 +7829,7 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
|
7278
7829
|
command: h.command,
|
|
7279
7830
|
converterConfig
|
|
7280
7831
|
});
|
|
7281
|
-
const hookType = h.type
|
|
7832
|
+
const hookType = isImportedHookType(h.type) ? h.type : "command";
|
|
7282
7833
|
const timeout = typeof h.timeout === "number" ? h.timeout : void 0;
|
|
7283
7834
|
const prompt = typeof h.prompt === "string" ? h.prompt : void 0;
|
|
7284
7835
|
return {
|
|
@@ -7286,6 +7837,10 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
|
|
|
7286
7837
|
...command !== void 0 && command !== null && { command },
|
|
7287
7838
|
...timeout !== void 0 && timeout !== null && { timeout },
|
|
7288
7839
|
...prompt !== void 0 && prompt !== null && { prompt },
|
|
7840
|
+
...importTypePayloadFields({
|
|
7841
|
+
h,
|
|
7842
|
+
hookType
|
|
7843
|
+
}),
|
|
7289
7844
|
...converterConfig.passthroughFields?.includes("name") && typeof h.name === "string" && { name: h.name },
|
|
7290
7845
|
...converterConfig.passthroughFields?.includes("description") && typeof h.description === "string" && { description: h.description },
|
|
7291
7846
|
...importBooleanPassthroughFields({
|
|
@@ -7305,6 +7860,32 @@ function toolMatcherEntryToCanonical({ rawEntry, converterConfig }) {
|
|
|
7305
7860
|
converterConfig
|
|
7306
7861
|
}));
|
|
7307
7862
|
}
|
|
7863
|
+
/**
|
|
7864
|
+
* Assemble the canonical hooks config a tool importer writes to
|
|
7865
|
+
* `.rulesync/hooks.json`.
|
|
7866
|
+
*
|
|
7867
|
+
* The top-level `hooks` record only accepts canonical event names, so any
|
|
7868
|
+
* imported native event key without a canonical mapping is moved under the
|
|
7869
|
+
* importing tool's own override block (`<overrideKey>.hooks`), whose keys stay
|
|
7870
|
+
* lenient. This mirrors the generate direction — override blocks pass
|
|
7871
|
+
* tool-native keys through verbatim — so documented native triggers (e.g.
|
|
7872
|
+
* kiro-ide's `PostFileSave`) survive an import → generate round-trip instead
|
|
7873
|
+
* of failing canonical validation.
|
|
7874
|
+
*/
|
|
7875
|
+
function buildImportedHooksConfig({ hooks, overrideKey, version = 1, extraOverride }) {
|
|
7876
|
+
const canonical = {};
|
|
7877
|
+
const native = {};
|
|
7878
|
+
for (const [event, defs] of Object.entries(hooks)) if (isHookEvent(event)) canonical[event] = defs;
|
|
7879
|
+
else native[event] = defs;
|
|
7880
|
+
const override = { ...extraOverride };
|
|
7881
|
+
if (Object.keys(native).length > 0) override.hooks = native;
|
|
7882
|
+
const config = {
|
|
7883
|
+
version,
|
|
7884
|
+
hooks: canonical
|
|
7885
|
+
};
|
|
7886
|
+
if (Object.keys(override).length > 0) config[overrideKey] = override;
|
|
7887
|
+
return config;
|
|
7888
|
+
}
|
|
7308
7889
|
function toolHooksToCanonical({ hooks, converterConfig }) {
|
|
7309
7890
|
if (hooks === null || hooks === void 0 || typeof hooks !== "object") return {};
|
|
7310
7891
|
const canonical = {};
|
|
@@ -7475,7 +8056,8 @@ const ANTIGRAVITY_CONVERTER_CONFIG = {
|
|
|
7475
8056
|
"preModelInvocation",
|
|
7476
8057
|
"postModelInvocation",
|
|
7477
8058
|
"stop"
|
|
7478
|
-
])
|
|
8059
|
+
]),
|
|
8060
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"])
|
|
7479
8061
|
};
|
|
7480
8062
|
/**
|
|
7481
8063
|
* Antigravity's `hooks.json` is keyed by a named hook whose value holds the
|
|
@@ -7582,10 +8164,11 @@ var AntigravityHooks = class extends ToolHooks {
|
|
|
7582
8164
|
hooks: flattenAntigravityHooks(parsed),
|
|
7583
8165
|
converterConfig: ANTIGRAVITY_CONVERTER_CONFIG
|
|
7584
8166
|
});
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
hooks
|
|
7588
|
-
|
|
8167
|
+
const overrideKey = this.constructor.getOverrideKey();
|
|
8168
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8169
|
+
hooks,
|
|
8170
|
+
overrideKey
|
|
8171
|
+
}), null, 2) });
|
|
7589
8172
|
}
|
|
7590
8173
|
validate() {
|
|
7591
8174
|
return {
|
|
@@ -7706,7 +8289,8 @@ const AUGMENTCODE_CONVERTER_CONFIG = {
|
|
|
7706
8289
|
"sessionEnd",
|
|
7707
8290
|
"stop",
|
|
7708
8291
|
"notification"
|
|
7709
|
-
])
|
|
8292
|
+
]),
|
|
8293
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command"])
|
|
7710
8294
|
};
|
|
7711
8295
|
/**
|
|
7712
8296
|
* AugmentCode (Auggie CLI) lifecycle hooks.
|
|
@@ -7788,10 +8372,10 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
7788
8372
|
hooks: settings.hooks,
|
|
7789
8373
|
converterConfig: AUGMENTCODE_CONVERTER_CONFIG
|
|
7790
8374
|
});
|
|
7791
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
}, null, 2) });
|
|
8375
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8376
|
+
hooks,
|
|
8377
|
+
overrideKey: "augmentcode"
|
|
8378
|
+
}), null, 2) });
|
|
7795
8379
|
}
|
|
7796
8380
|
validate() {
|
|
7797
8381
|
return {
|
|
@@ -7826,7 +8410,15 @@ const CLAUDE_CONVERTER_CONFIG = {
|
|
|
7826
8410
|
"taskCompleted",
|
|
7827
8411
|
"teammateIdle",
|
|
7828
8412
|
"cwdChanged"
|
|
7829
|
-
])
|
|
8413
|
+
]),
|
|
8414
|
+
supportedHookTypes: /* @__PURE__ */ new Set([
|
|
8415
|
+
"command",
|
|
8416
|
+
"prompt",
|
|
8417
|
+
"http",
|
|
8418
|
+
"mcp_tool",
|
|
8419
|
+
"agent"
|
|
8420
|
+
]),
|
|
8421
|
+
emitsPromptModel: true
|
|
7830
8422
|
};
|
|
7831
8423
|
var ClaudecodeHooks = class ClaudecodeHooks extends ToolHooks {
|
|
7832
8424
|
constructor(params) {
|
|
@@ -7891,10 +8483,10 @@ var ClaudecodeHooks = class ClaudecodeHooks extends ToolHooks {
|
|
|
7891
8483
|
hooks: settings.hooks,
|
|
7892
8484
|
converterConfig: CLAUDE_CONVERTER_CONFIG
|
|
7893
8485
|
});
|
|
7894
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
}, null, 2) });
|
|
8486
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8487
|
+
hooks,
|
|
8488
|
+
overrideKey: "claudecode"
|
|
8489
|
+
}), null, 2) });
|
|
7898
8490
|
}
|
|
7899
8491
|
validate() {
|
|
7900
8492
|
return {
|
|
@@ -8037,10 +8629,10 @@ var CodexcliHooks = class CodexcliHooks extends ToolHooks {
|
|
|
8037
8629
|
hooks: parsed.hooks,
|
|
8038
8630
|
converterConfig: CODEXCLI_CONVERTER_CONFIG
|
|
8039
8631
|
});
|
|
8040
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
}, null, 2) });
|
|
8632
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8633
|
+
hooks,
|
|
8634
|
+
overrideKey: "codexcli"
|
|
8635
|
+
}), null, 2) });
|
|
8044
8636
|
}
|
|
8045
8637
|
validate() {
|
|
8046
8638
|
return {
|
|
@@ -8208,10 +8800,10 @@ var CopilotHooks = class CopilotHooks extends ToolHooks {
|
|
|
8208
8800
|
throw new Error(`Failed to parse Copilot hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8209
8801
|
}
|
|
8210
8802
|
const hooks = copilotHooksToCanonical(parsed.hooks, options?.logger);
|
|
8211
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
}, null, 2) });
|
|
8803
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
8804
|
+
hooks,
|
|
8805
|
+
overrideKey: "copilot"
|
|
8806
|
+
}), null, 2) });
|
|
8215
8807
|
}
|
|
8216
8808
|
validate() {
|
|
8217
8809
|
return {
|
|
@@ -8230,20 +8822,6 @@ var CopilotHooks = class CopilotHooks extends ToolHooks {
|
|
|
8230
8822
|
}
|
|
8231
8823
|
};
|
|
8232
8824
|
//#endregion
|
|
8233
|
-
//#region src/utils/object.ts
|
|
8234
|
-
/**
|
|
8235
|
-
* Return a shallow copy of `obj` keeping only the entries whose value is
|
|
8236
|
-
* neither `undefined` nor `null`.
|
|
8237
|
-
*
|
|
8238
|
-
* Used to assemble generated config objects without one conditional spread per
|
|
8239
|
-
* optional field (which would otherwise exceed the lint complexity budget).
|
|
8240
|
-
*/
|
|
8241
|
-
function compact(obj) {
|
|
8242
|
-
const result = {};
|
|
8243
|
-
for (const [key, value] of Object.entries(obj)) if (value !== void 0 && value !== null) result[key] = value;
|
|
8244
|
-
return result;
|
|
8245
|
-
}
|
|
8246
|
-
//#endregion
|
|
8247
8825
|
//#region src/features/hooks/copilotcli-hooks.ts
|
|
8248
8826
|
/**
|
|
8249
8827
|
* GitHub Copilot CLI hooks.
|
|
@@ -8376,7 +8954,7 @@ function buildCopilotCliEntriesForEvent({ eventName, definitions, canonicalSchem
|
|
|
8376
8954
|
...timeoutPart,
|
|
8377
8955
|
...rest
|
|
8378
8956
|
});
|
|
8379
|
-
else entries.push({
|
|
8957
|
+
else if (hookType === "command") entries.push({
|
|
8380
8958
|
type: "command",
|
|
8381
8959
|
...matcherPart,
|
|
8382
8960
|
...compact({
|
|
@@ -8528,10 +9106,10 @@ var CopilotcliHooks = class CopilotcliHooks extends ToolHooks {
|
|
|
8528
9106
|
throw new Error(`Failed to parse Copilot CLI hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8529
9107
|
}
|
|
8530
9108
|
const hooks = copilotCliHooksToCanonical(parsed.hooks, options?.logger);
|
|
8531
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
}, null, 2) });
|
|
9109
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9110
|
+
hooks,
|
|
9111
|
+
overrideKey: "copilotcli"
|
|
9112
|
+
}), null, 2) });
|
|
8535
9113
|
}
|
|
8536
9114
|
validate() {
|
|
8537
9115
|
return {
|
|
@@ -8586,9 +9164,10 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8586
9164
|
...config.cursor?.hooks
|
|
8587
9165
|
};
|
|
8588
9166
|
const mappedHooks = {};
|
|
9167
|
+
const cursorSupportedTypes = /* @__PURE__ */ new Set(["command", "prompt"]);
|
|
8589
9168
|
for (const [eventName, defs] of Object.entries(mergedHooks)) {
|
|
8590
9169
|
const cursorEventName = CANONICAL_TO_CURSOR_EVENT_NAMES[eventName] ?? eventName;
|
|
8591
|
-
|
|
9170
|
+
const mappedDefs = defs.filter((def) => cursorSupportedTypes.has(def.type ?? "command")).map((def) => ({
|
|
8592
9171
|
...def.type !== void 0 && def.type !== null && { type: def.type },
|
|
8593
9172
|
...def.command !== void 0 && def.command !== null && { command: def.command },
|
|
8594
9173
|
...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
|
|
@@ -8597,6 +9176,7 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8597
9176
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt },
|
|
8598
9177
|
...def.failClosed !== void 0 && def.failClosed !== null && { failClosed: def.failClosed }
|
|
8599
9178
|
}));
|
|
9179
|
+
if (mappedDefs.length > 0) mappedHooks[cursorEventName] = mappedDefs;
|
|
8600
9180
|
}
|
|
8601
9181
|
const cursorConfig = {
|
|
8602
9182
|
version: config.version ?? 1,
|
|
@@ -8623,10 +9203,11 @@ var CursorHooks = class CursorHooks extends ToolHooks {
|
|
|
8623
9203
|
canonicalHooks[eventName] = defs;
|
|
8624
9204
|
}
|
|
8625
9205
|
const version = parsed.version ?? 1;
|
|
8626
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
9206
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9207
|
+
hooks: canonicalHooks,
|
|
9208
|
+
overrideKey: "cursor",
|
|
9209
|
+
version
|
|
9210
|
+
}), null, 2) });
|
|
8630
9211
|
}
|
|
8631
9212
|
validate() {
|
|
8632
9213
|
return {
|
|
@@ -8681,7 +9262,7 @@ function canonicalToDeepagentsHooks(config) {
|
|
|
8681
9262
|
const deepagentsEvent = CANONICAL_TO_DEEPAGENTS_EVENT_NAMES[canonicalEvent];
|
|
8682
9263
|
if (!deepagentsEvent) continue;
|
|
8683
9264
|
for (const def of definitions) {
|
|
8684
|
-
if (def.type
|
|
9265
|
+
if ((def.type ?? "command") !== "command") continue;
|
|
8685
9266
|
if (!def.command) continue;
|
|
8686
9267
|
if (def.matcher) continue;
|
|
8687
9268
|
entries.push({
|
|
@@ -8771,10 +9352,10 @@ var DeepagentsHooks = class DeepagentsHooks extends ToolHooks {
|
|
|
8771
9352
|
throw new Error(`Failed to parse deepagents hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
8772
9353
|
}
|
|
8773
9354
|
const hooks = deepagentsToCanonicalHooks(isDeepagentsHooksFile(parsed) ? parsed.hooks : []);
|
|
8774
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
}, null, 2) });
|
|
9355
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9356
|
+
hooks,
|
|
9357
|
+
overrideKey: "deepagents"
|
|
9358
|
+
}), null, 2) });
|
|
8778
9359
|
}
|
|
8779
9360
|
validate() {
|
|
8780
9361
|
return {
|
|
@@ -8903,10 +9484,10 @@ var DevinHooks = class DevinHooks extends ToolHooks {
|
|
|
8903
9484
|
hooks: this.getRelativeFilePath() === "config.json" ? isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {} : parsed,
|
|
8904
9485
|
converterConfig: DEVIN_CONVERTER_CONFIG
|
|
8905
9486
|
});
|
|
8906
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
}, null, 2) });
|
|
9487
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9488
|
+
hooks,
|
|
9489
|
+
overrideKey: "devin"
|
|
9490
|
+
}), null, 2) });
|
|
8910
9491
|
}
|
|
8911
9492
|
validate() {
|
|
8912
9493
|
return {
|
|
@@ -8930,7 +9511,8 @@ const FACTORYDROID_CONVERTER_CONFIG = {
|
|
|
8930
9511
|
supportedEvents: FACTORYDROID_HOOK_EVENTS,
|
|
8931
9512
|
canonicalToToolEventNames: CANONICAL_TO_FACTORYDROID_EVENT_NAMES,
|
|
8932
9513
|
toolToCanonicalEventNames: FACTORYDROID_TO_CANONICAL_EVENT_NAMES,
|
|
8933
|
-
projectDirVar: "$FACTORY_PROJECT_DIR"
|
|
9514
|
+
projectDirVar: "$FACTORY_PROJECT_DIR",
|
|
9515
|
+
supportedHookTypes: /* @__PURE__ */ new Set(["command", "prompt"])
|
|
8934
9516
|
};
|
|
8935
9517
|
var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
8936
9518
|
constructor(params) {
|
|
@@ -8998,10 +9580,10 @@ var FactorydroidHooks = class FactorydroidHooks extends ToolHooks {
|
|
|
8998
9580
|
hooks: settings.hooks,
|
|
8999
9581
|
converterConfig: FACTORYDROID_CONVERTER_CONFIG
|
|
9000
9582
|
});
|
|
9001
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
}, null, 2) });
|
|
9583
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9584
|
+
hooks,
|
|
9585
|
+
overrideKey: "factorydroid"
|
|
9586
|
+
}), null, 2) });
|
|
9005
9587
|
}
|
|
9006
9588
|
validate() {
|
|
9007
9589
|
return {
|
|
@@ -9092,10 +9674,10 @@ var GooseHooks = class GooseHooks extends ToolHooks {
|
|
|
9092
9674
|
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,
|
|
9093
9675
|
converterConfig: GOOSE_CONVERTER_CONFIG
|
|
9094
9676
|
});
|
|
9095
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
}, null, 2) });
|
|
9677
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9678
|
+
hooks,
|
|
9679
|
+
overrideKey: "goose"
|
|
9680
|
+
}), null, 2) });
|
|
9099
9681
|
}
|
|
9100
9682
|
validate() {
|
|
9101
9683
|
return {
|
|
@@ -9253,10 +9835,10 @@ var GrokcliHooks = class GrokcliHooks extends ToolHooks {
|
|
|
9253
9835
|
hooks: isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {},
|
|
9254
9836
|
converterConfig: GROKCLI_CONVERTER_CONFIG
|
|
9255
9837
|
});
|
|
9256
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
}, null, 2) });
|
|
9838
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
9839
|
+
hooks,
|
|
9840
|
+
overrideKey: "grokcli"
|
|
9841
|
+
}), null, 2) });
|
|
9260
9842
|
}
|
|
9261
9843
|
validate() {
|
|
9262
9844
|
return {
|
|
@@ -9417,10 +9999,10 @@ var HermesagentHooks = class HermesagentHooks extends ToolHooks {
|
|
|
9417
9999
|
format: "yaml",
|
|
9418
10000
|
fileContent: this.getFileContent()
|
|
9419
10001
|
}).hooks);
|
|
9420
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
}, null, 2) });
|
|
10002
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10003
|
+
hooks,
|
|
10004
|
+
overrideKey: "hermesagent"
|
|
10005
|
+
}), null, 2) });
|
|
9424
10006
|
}
|
|
9425
10007
|
static fromRulesyncHooks({ outputRoot, rulesyncHooks, logger }) {
|
|
9426
10008
|
const config = rulesyncHooks.getJson();
|
|
@@ -9523,10 +10105,10 @@ var JunieHooks = class JunieHooks extends ToolHooks {
|
|
|
9523
10105
|
hooks: settings.hooks,
|
|
9524
10106
|
converterConfig: JUNIE_CONVERTER_CONFIG
|
|
9525
10107
|
});
|
|
9526
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
}, null, 2) });
|
|
10108
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10109
|
+
hooks,
|
|
10110
|
+
overrideKey: "junie"
|
|
10111
|
+
}), null, 2) });
|
|
9530
10112
|
}
|
|
9531
10113
|
validate() {
|
|
9532
10114
|
return {
|
|
@@ -9571,7 +10153,7 @@ function collectOpencodeStyleHandlers({ effectiveHooks, eventMap, namedEventHand
|
|
|
9571
10153
|
if (!toolEvent) continue;
|
|
9572
10154
|
const handlers = [];
|
|
9573
10155
|
for (const def of definitions) {
|
|
9574
|
-
if (def.type
|
|
10156
|
+
if ((def.type ?? "command") !== "command") continue;
|
|
9575
10157
|
if (!def.command) continue;
|
|
9576
10158
|
handlers.push({
|
|
9577
10159
|
command: def.command,
|
|
@@ -9876,10 +10458,11 @@ var KiroHooks = class KiroHooks extends ToolHooks {
|
|
|
9876
10458
|
throw new Error(`Failed to parse Kiro hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
9877
10459
|
}
|
|
9878
10460
|
const hooks = kiroHooksToCanonical(agentConfig.hooks);
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
hooks
|
|
9882
|
-
|
|
10461
|
+
const overrideKey = this.constructor.getOverrideKey();
|
|
10462
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10463
|
+
hooks,
|
|
10464
|
+
overrideKey
|
|
10465
|
+
}), null, 2) });
|
|
9883
10466
|
}
|
|
9884
10467
|
validate() {
|
|
9885
10468
|
return {
|
|
@@ -10088,10 +10671,10 @@ var KiroIdeHooks = class KiroIdeHooks extends ToolHooks {
|
|
|
10088
10671
|
throw new Error(`Failed to parse Kiro IDE hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10089
10672
|
}
|
|
10090
10673
|
const hooks = kiroIdeHooksToCanonical(parsed.hooks ?? []);
|
|
10091
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
}, null, 2) });
|
|
10674
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
10675
|
+
hooks,
|
|
10676
|
+
overrideKey: "kiro-ide"
|
|
10677
|
+
}), null, 2) });
|
|
10095
10678
|
}
|
|
10096
10679
|
validate() {
|
|
10097
10680
|
return {
|
|
@@ -10215,11 +10798,18 @@ function canonicalToQwencodeHooks(config) {
|
|
|
10215
10798
|
...sharedHooks,
|
|
10216
10799
|
...config.qwencode?.hooks
|
|
10217
10800
|
};
|
|
10801
|
+
const qwencodeSupportedTypes = /* @__PURE__ */ new Set([
|
|
10802
|
+
"command",
|
|
10803
|
+
"prompt",
|
|
10804
|
+
"http",
|
|
10805
|
+
"function"
|
|
10806
|
+
]);
|
|
10218
10807
|
const qwencode = {};
|
|
10219
10808
|
for (const [eventName, definitions] of Object.entries(effectiveHooks)) {
|
|
10220
10809
|
const qwencodeEventName = CANONICAL_TO_QWENCODE_EVENT_NAMES[eventName] ?? eventName;
|
|
10221
10810
|
const byMatcher = /* @__PURE__ */ new Map();
|
|
10222
10811
|
for (const def of definitions) {
|
|
10812
|
+
if (!qwencodeSupportedTypes.has(def.type ?? "command")) continue;
|
|
10223
10813
|
const key = def.matcher ?? "";
|
|
10224
10814
|
const list = byMatcher.get(key);
|
|
10225
10815
|
if (list) list.push(def);
|
|
@@ -10279,9 +10869,10 @@ function qwencodeMatcherEntryToCanonical(entry) {
|
|
|
10279
10869
|
const sequential = entry.sequential === true;
|
|
10280
10870
|
const matcher = entry.matcher !== void 0 && entry.matcher !== null && entry.matcher !== "" ? entry.matcher : void 0;
|
|
10281
10871
|
for (const h of hooks) {
|
|
10282
|
-
const hookType = h.type === "command" || h.type === "prompt" || h.type === "http" ? h.type : "command";
|
|
10872
|
+
const hookType = h.type === "command" || h.type === "prompt" || h.type === "http" || h.type === "function" ? h.type : "command";
|
|
10283
10873
|
const isHttp = hookType === "http";
|
|
10284
10874
|
const isCommand = hookType === "command";
|
|
10875
|
+
const shell = h.shell === "bash" || h.shell === "powershell" ? h.shell : void 0;
|
|
10285
10876
|
defs.push({
|
|
10286
10877
|
type: hookType,
|
|
10287
10878
|
...compact({
|
|
@@ -10293,7 +10884,7 @@ function qwencodeMatcherEntryToCanonical(entry) {
|
|
|
10293
10884
|
statusMessage: h.statusMessage,
|
|
10294
10885
|
async: isCommand ? h.async : void 0,
|
|
10295
10886
|
env: isCommand ? h.env : void 0,
|
|
10296
|
-
shell: isCommand ?
|
|
10887
|
+
shell: isCommand ? shell : void 0,
|
|
10297
10888
|
headers: isHttp ? h.headers : void 0,
|
|
10298
10889
|
allowedEnvVars: isHttp ? h.allowedEnvVars : void 0,
|
|
10299
10890
|
once: isHttp ? h.once : void 0,
|
|
@@ -10380,15 +10971,11 @@ var QwencodeHooks = class QwencodeHooks extends ToolHooks {
|
|
|
10380
10971
|
} catch (error) {
|
|
10381
10972
|
throw new Error(`Failed to parse Qwen Code hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10382
10973
|
}
|
|
10383
|
-
const
|
|
10384
|
-
|
|
10385
|
-
|
|
10386
|
-
|
|
10387
|
-
|
|
10388
|
-
} : {
|
|
10389
|
-
version: 1,
|
|
10390
|
-
hooks
|
|
10391
|
-
};
|
|
10974
|
+
const canonical = buildImportedHooksConfig({
|
|
10975
|
+
hooks: qwencodeHooksToCanonical(settings.hooks),
|
|
10976
|
+
overrideKey: "qwencode",
|
|
10977
|
+
...typeof settings.disableAllHooks === "boolean" && { extraOverride: { disableAllHooks: settings.disableAllHooks } }
|
|
10978
|
+
});
|
|
10392
10979
|
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(canonical, null, 2) });
|
|
10393
10980
|
}
|
|
10394
10981
|
validate() {
|
|
@@ -10550,10 +11137,10 @@ var ReasonixHooks = class ReasonixHooks extends ToolHooks {
|
|
|
10550
11137
|
throw new Error(`Failed to parse Reasonix hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10551
11138
|
}
|
|
10552
11139
|
const hooks = reasonixHooksToCanonical(settings.hooks);
|
|
10553
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10554
|
-
|
|
10555
|
-
|
|
10556
|
-
}, null, 2) });
|
|
11140
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
11141
|
+
hooks,
|
|
11142
|
+
overrideKey: "reasonix"
|
|
11143
|
+
}), null, 2) });
|
|
10557
11144
|
}
|
|
10558
11145
|
validate() {
|
|
10559
11146
|
return {
|
|
@@ -10776,10 +11363,10 @@ var VibeHooks = class VibeHooks extends ToolHooks {
|
|
|
10776
11363
|
throw new Error(`Failed to parse Vibe hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
10777
11364
|
}
|
|
10778
11365
|
const hooks = vibeHooksToCanonical(parsed);
|
|
10779
|
-
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify({
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
}, null, 2) });
|
|
11366
|
+
return this.toRulesyncHooksDefault({ fileContent: JSON.stringify(buildImportedHooksConfig({
|
|
11367
|
+
hooks,
|
|
11368
|
+
overrideKey: "vibe"
|
|
11369
|
+
}), null, 2) });
|
|
10783
11370
|
}
|
|
10784
11371
|
validate() {
|
|
10785
11372
|
try {
|
|
@@ -10866,7 +11453,13 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
10866
11453
|
supportsImport: true
|
|
10867
11454
|
},
|
|
10868
11455
|
supportedEvents: CLAUDE_HOOK_EVENTS,
|
|
10869
|
-
supportedHookTypes: [
|
|
11456
|
+
supportedHookTypes: [
|
|
11457
|
+
"command",
|
|
11458
|
+
"prompt",
|
|
11459
|
+
"http",
|
|
11460
|
+
"mcp_tool",
|
|
11461
|
+
"agent"
|
|
11462
|
+
],
|
|
10870
11463
|
supportsMatcher: true
|
|
10871
11464
|
}],
|
|
10872
11465
|
["codexcli", {
|
|
@@ -11058,7 +11651,12 @@ const toolHooksFactories = /* @__PURE__ */ new Map([
|
|
|
11058
11651
|
supportsImport: true
|
|
11059
11652
|
},
|
|
11060
11653
|
supportedEvents: QWENCODE_HOOK_EVENTS,
|
|
11061
|
-
supportedHookTypes: [
|
|
11654
|
+
supportedHookTypes: [
|
|
11655
|
+
"command",
|
|
11656
|
+
"prompt",
|
|
11657
|
+
"http",
|
|
11658
|
+
"function"
|
|
11659
|
+
],
|
|
11062
11660
|
supportsMatcher: true
|
|
11063
11661
|
}],
|
|
11064
11662
|
["reasonix", {
|
|
@@ -12360,16 +12958,6 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
12360
12958
|
}
|
|
12361
12959
|
};
|
|
12362
12960
|
//#endregion
|
|
12363
|
-
//#region src/constants/amp-paths.ts
|
|
12364
|
-
const AMP_DIR = ".amp";
|
|
12365
|
-
const AMP_GLOBAL_DIR = join(".config", "amp");
|
|
12366
|
-
const AMP_AGENTS_DIR = ".agents";
|
|
12367
|
-
const AMP_SKILLS_PROJECT_DIR = join(AMP_AGENTS_DIR, "skills");
|
|
12368
|
-
const AMP_SKILLS_GLOBAL_DIR = join(".config", "agents", "skills");
|
|
12369
|
-
const AMP_RULE_FILE_NAME = "AGENTS.md";
|
|
12370
|
-
const AMP_SETTINGS_FILE_NAME = "settings.json";
|
|
12371
|
-
const AMP_SETTINGS_JSONC_FILE_NAME = "settings.jsonc";
|
|
12372
|
-
//#endregion
|
|
12373
12961
|
//#region src/types/mcp.ts
|
|
12374
12962
|
const EnvVarNameSchema = z.string().check(refine((value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value), "envVars entries must be valid environment variable names"));
|
|
12375
12963
|
const McpServerSchema = z.looseObject({
|
|
@@ -13461,10 +14049,19 @@ function mapOauthFromCodex(oauth) {
|
|
|
13461
14049
|
}
|
|
13462
14050
|
const CODEX_MCP_SERVER_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
13463
14051
|
function normalizeCodexMcpServerName(name) {
|
|
13464
|
-
if (PROTOTYPE_POLLUTION_KEYS.has(name)) return
|
|
13465
|
-
|
|
14052
|
+
if (!PROTOTYPE_POLLUTION_KEYS.has(name) && CODEX_MCP_SERVER_NAME_PATTERN.test(name)) return {
|
|
14053
|
+
codexName: name,
|
|
14054
|
+
usedFallback: false
|
|
14055
|
+
};
|
|
13466
14056
|
const normalizedName = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
13467
|
-
|
|
14057
|
+
if (normalizedName && !PROTOTYPE_POLLUTION_KEYS.has(normalizedName)) return {
|
|
14058
|
+
codexName: normalizedName,
|
|
14059
|
+
usedFallback: false
|
|
14060
|
+
};
|
|
14061
|
+
return {
|
|
14062
|
+
codexName: `mcp_${createHash("sha256").update(name).digest("hex").slice(0, 8)}`,
|
|
14063
|
+
usedFallback: true
|
|
14064
|
+
};
|
|
13468
14065
|
}
|
|
13469
14066
|
function convertFromCodexFormat(codexMcp) {
|
|
13470
14067
|
const result = {};
|
|
@@ -13478,7 +14075,7 @@ function convertFromCodexFormat(codexMcp) {
|
|
|
13478
14075
|
} else if (key === "oauth" && isRecord(value)) converted[key] = mapOauthFromCodex(value);
|
|
13479
14076
|
else if (Object.hasOwn(CODEX_TO_RULESYNC_FIELD_MAP, key)) {
|
|
13480
14077
|
const mappedKey = CODEX_TO_RULESYNC_FIELD_MAP[key];
|
|
13481
|
-
if (mappedKey) if (isStringArray(value)) converted[mappedKey] = value;
|
|
14078
|
+
if (mappedKey) if (isStringArray$1(value)) converted[mappedKey] = value;
|
|
13482
14079
|
else warnWithFallback(void 0, `Ignored malformed array for ${key} in MCP server ${name}`);
|
|
13483
14080
|
} else converted[key] = value;
|
|
13484
14081
|
}
|
|
@@ -13490,12 +14087,9 @@ function convertToCodexFormat(mcpServers) {
|
|
|
13490
14087
|
const result = {};
|
|
13491
14088
|
const originalNames = /* @__PURE__ */ new Map();
|
|
13492
14089
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
13493
|
-
const codexName = normalizeCodexMcpServerName(name);
|
|
13494
|
-
if (codexName === null) {
|
|
13495
|
-
warnWithFallback(void 0, `MCP server "${name}" could not be normalized to a valid Codex MCP server name and was skipped.`);
|
|
13496
|
-
continue;
|
|
13497
|
-
}
|
|
13498
14090
|
if (!isRecord(config)) continue;
|
|
14091
|
+
const { codexName, usedFallback } = normalizeCodexMcpServerName(name);
|
|
14092
|
+
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.`);
|
|
13499
14093
|
const converted = {};
|
|
13500
14094
|
for (const [key, value] of Object.entries(config)) {
|
|
13501
14095
|
if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
|
|
@@ -13504,12 +14098,12 @@ function convertToCodexFormat(mcpServers) {
|
|
|
13504
14098
|
} else if (key === "oauth" && isRecord(value)) converted[key] = mapOauthToCodex(value);
|
|
13505
14099
|
else if (Object.hasOwn(RULESYNC_TO_CODEX_FIELD_MAP, key)) {
|
|
13506
14100
|
const mappedKey = RULESYNC_TO_CODEX_FIELD_MAP[key];
|
|
13507
|
-
if (mappedKey) if (isStringArray(value)) converted[mappedKey] = value;
|
|
14101
|
+
if (mappedKey) if (isStringArray$1(value)) converted[mappedKey] = value;
|
|
13508
14102
|
else warnWithFallback(void 0, `[CodexCliMcp] Skipping invalid value type for mapped key '${key}': expected string array, got ${typeof value}`);
|
|
13509
14103
|
} else converted[key] = value;
|
|
13510
14104
|
}
|
|
13511
14105
|
const previousName = originalNames.get(codexName);
|
|
13512
|
-
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}"
|
|
14106
|
+
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}"; "${name}" (processed last) overwrites "${previousName}".`);
|
|
13513
14107
|
originalNames.set(codexName, name);
|
|
13514
14108
|
result[codexName] = converted;
|
|
13515
14109
|
}
|
|
@@ -13576,7 +14170,7 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
13576
14170
|
const rawServer = isRecord(rawMcpServers) ? rawMcpServers[serverName] : void 0;
|
|
13577
14171
|
return [serverName, {
|
|
13578
14172
|
...serverConfig,
|
|
13579
|
-
...isRecord(rawServer) && isStringArray(rawServer.envVars) ? { envVars: rawServer.envVars } : {}
|
|
14173
|
+
...isRecord(rawServer) && isStringArray$1(rawServer.envVars) ? { envVars: rawServer.envVars } : {}
|
|
13580
14174
|
}];
|
|
13581
14175
|
})));
|
|
13582
14176
|
const filteredMcpServers = this.removeEmptyEntries(converted);
|
|
@@ -14313,11 +14907,11 @@ function applyGooseStdioFields(ext, config) {
|
|
|
14313
14907
|
if (Array.isArray(command)) {
|
|
14314
14908
|
if (typeof command[0] === "string") ext.cmd = command[0];
|
|
14315
14909
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14316
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
14910
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14317
14911
|
if (rest.length > 0 || args.length > 0) ext.args = [...rest, ...args];
|
|
14318
14912
|
} else if (typeof command === "string") {
|
|
14319
14913
|
ext.cmd = command;
|
|
14320
|
-
if (isStringArray(config.args)) ext.args = config.args;
|
|
14914
|
+
if (isStringArray$1(config.args)) ext.args = config.args;
|
|
14321
14915
|
}
|
|
14322
14916
|
if (isPlainObject$1(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
|
|
14323
14917
|
}
|
|
@@ -14375,7 +14969,7 @@ function convertFromGooseFormat(extensions) {
|
|
|
14375
14969
|
else if (type === "streamable_http") server.type = "http";
|
|
14376
14970
|
else if (type === "stdio") server.type = "stdio";
|
|
14377
14971
|
if (typeof ext.cmd === "string") server.command = ext.cmd;
|
|
14378
|
-
if (isStringArray(ext.args)) server.args = ext.args;
|
|
14972
|
+
if (isStringArray$1(ext.args)) server.args = ext.args;
|
|
14379
14973
|
if (isPlainObject$1(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
|
|
14380
14974
|
if (typeof ext.uri === "string") server.url = ext.uri;
|
|
14381
14975
|
if (isPlainObject$1(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
|
|
@@ -14395,11 +14989,11 @@ function buildGoosePluginStdioServer(config) {
|
|
|
14395
14989
|
if (Array.isArray(command)) {
|
|
14396
14990
|
if (typeof command[0] === "string") server.command = command[0];
|
|
14397
14991
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14398
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
14992
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14399
14993
|
if (rest.length > 0 || args.length > 0) server.args = [...rest, ...args];
|
|
14400
14994
|
} else if (typeof command === "string") {
|
|
14401
14995
|
server.command = command;
|
|
14402
|
-
if (isStringArray(config.args)) server.args = config.args;
|
|
14996
|
+
if (isStringArray$1(config.args)) server.args = config.args;
|
|
14403
14997
|
}
|
|
14404
14998
|
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
14405
14999
|
if (typeof config.cwd === "string") server.cwd = config.cwd;
|
|
@@ -14712,7 +15306,7 @@ function resolveHermesTimeout(config) {
|
|
|
14712
15306
|
*/
|
|
14713
15307
|
function copyHermesAdvancedFields(source, target) {
|
|
14714
15308
|
if (typeof source.auth === "string") target.auth = source.auth;
|
|
14715
|
-
if (typeof source.client_cert === "string" || isStringArray(source.client_cert)) target.client_cert = source.client_cert;
|
|
15309
|
+
if (typeof source.client_cert === "string" || isStringArray$1(source.client_cert)) target.client_cert = source.client_cert;
|
|
14716
15310
|
if (typeof source.client_key === "string") target.client_key = source.client_key;
|
|
14717
15311
|
if (typeof source.connect_timeout === "number") target.connect_timeout = source.connect_timeout;
|
|
14718
15312
|
if (typeof source.supports_parallel_tool_calls === "boolean") target.supports_parallel_tool_calls = source.supports_parallel_tool_calls;
|
|
@@ -14731,8 +15325,8 @@ function copyHermesAdvancedFields(source, target) {
|
|
|
14731
15325
|
*/
|
|
14732
15326
|
function buildHermesToolsBlock(config) {
|
|
14733
15327
|
const tools = {};
|
|
14734
|
-
if (isStringArray(config.enabledTools)) tools.include = config.enabledTools;
|
|
14735
|
-
if (isStringArray(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
15328
|
+
if (isStringArray$1(config.enabledTools)) tools.include = config.enabledTools;
|
|
15329
|
+
if (isStringArray$1(config.disabledTools)) tools.exclude = config.disabledTools;
|
|
14736
15330
|
if (typeof config.promptsEnabled === "boolean") tools.prompts = config.promptsEnabled;
|
|
14737
15331
|
if (typeof config.resourcesEnabled === "boolean") tools.resources = config.resourcesEnabled;
|
|
14738
15332
|
return tools;
|
|
@@ -14744,8 +15338,8 @@ function buildHermesToolsBlock(config) {
|
|
|
14744
15338
|
* `promptsEnabled`/`resourcesEnabled` top-level toggles.
|
|
14745
15339
|
*/
|
|
14746
15340
|
function applyHermesToolsBlock(hermesTools, server) {
|
|
14747
|
-
if (isStringArray(hermesTools.include)) server.enabledTools = hermesTools.include;
|
|
14748
|
-
if (isStringArray(hermesTools.exclude)) server.disabledTools = hermesTools.exclude;
|
|
15341
|
+
if (isStringArray$1(hermesTools.include)) server.enabledTools = hermesTools.include;
|
|
15342
|
+
if (isStringArray$1(hermesTools.exclude)) server.disabledTools = hermesTools.exclude;
|
|
14749
15343
|
if (typeof hermesTools.prompts === "boolean") server.promptsEnabled = hermesTools.prompts;
|
|
14750
15344
|
if (typeof hermesTools.resources === "boolean") server.resourcesEnabled = hermesTools.resources;
|
|
14751
15345
|
}
|
|
@@ -14769,11 +15363,11 @@ function convertServerToHermes(config) {
|
|
|
14769
15363
|
if (Array.isArray(command)) {
|
|
14770
15364
|
if (typeof command[0] === "string") out.command = command[0];
|
|
14771
15365
|
const rest = command.slice(1).filter((c) => typeof c === "string");
|
|
14772
|
-
const args = isStringArray(config.args) ? config.args : [];
|
|
15366
|
+
const args = isStringArray$1(config.args) ? config.args : [];
|
|
14773
15367
|
if (rest.length > 0 || args.length > 0) out.args = [...rest, ...args];
|
|
14774
15368
|
} else if (typeof command === "string") {
|
|
14775
15369
|
out.command = command;
|
|
14776
|
-
if (isStringArray(config.args)) out.args = config.args;
|
|
15370
|
+
if (isStringArray$1(config.args)) out.args = config.args;
|
|
14777
15371
|
}
|
|
14778
15372
|
if (isPlainObject$1(config.env)) out.env = omitPrototypePollutionKeys(config.env);
|
|
14779
15373
|
} else if (url !== void 0) {
|
|
@@ -14821,7 +15415,7 @@ function convertFromHermesFormat(mcpServers) {
|
|
|
14821
15415
|
if (PROTOTYPE_POLLUTION_KEYS.has(name) || !isRecord(config)) continue;
|
|
14822
15416
|
const server = {};
|
|
14823
15417
|
if (typeof config.command === "string") server.command = config.command;
|
|
14824
|
-
if (isStringArray(config.args)) server.args = config.args;
|
|
15418
|
+
if (isStringArray$1(config.args)) server.args = config.args;
|
|
14825
15419
|
if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
|
|
14826
15420
|
if (typeof config.url === "string") server.url = config.url;
|
|
14827
15421
|
if (isPlainObject$1(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
|
|
@@ -17146,7 +17740,11 @@ const VibePermissionsOverrideSchema = z.looseObject({ permission: z.optional(z.r
|
|
|
17146
17740
|
*/
|
|
17147
17741
|
const CursorPermissionsOverrideSchema = z.looseObject({
|
|
17148
17742
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17149
|
-
approvalMode: z.optional(z.
|
|
17743
|
+
approvalMode: z.optional(z.enum([
|
|
17744
|
+
"allowlist",
|
|
17745
|
+
"auto-review",
|
|
17746
|
+
"unrestricted"
|
|
17747
|
+
])),
|
|
17150
17748
|
sandbox: z.optional(z.looseObject({}))
|
|
17151
17749
|
});
|
|
17152
17750
|
/**
|
|
@@ -17234,7 +17832,11 @@ const FactorydroidPermissionsOverrideSchema = z.looseObject({
|
|
|
17234
17832
|
*/
|
|
17235
17833
|
const WarpPermissionsOverrideSchema = z.looseObject({
|
|
17236
17834
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17237
|
-
agent_mode_coding_permissions: z.optional(z.
|
|
17835
|
+
agent_mode_coding_permissions: z.optional(z.enum([
|
|
17836
|
+
"always_ask_before_reading",
|
|
17837
|
+
"always_allow_reading",
|
|
17838
|
+
"allow_reading_specific_files"
|
|
17839
|
+
])),
|
|
17238
17840
|
agent_mode_coding_file_read_allowlist: z.optional(z.array(z.string())),
|
|
17239
17841
|
agent_mode_execute_readonly_commands: z.optional(z.boolean())
|
|
17240
17842
|
});
|
|
@@ -17280,7 +17882,11 @@ const JuniePermissionsOverrideSchema = z.looseObject({
|
|
|
17280
17882
|
*/
|
|
17281
17883
|
const TaktPermissionsOverrideSchema = z.looseObject({
|
|
17282
17884
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17283
|
-
step_permission_overrides: z.optional(z.record(z.string(), z.
|
|
17885
|
+
step_permission_overrides: z.optional(z.record(z.string(), z.enum([
|
|
17886
|
+
"readonly",
|
|
17887
|
+
"edit",
|
|
17888
|
+
"full"
|
|
17889
|
+
]))),
|
|
17284
17890
|
provider_options: z.optional(z.looseObject({}))
|
|
17285
17891
|
});
|
|
17286
17892
|
/**
|
|
@@ -17310,9 +17916,15 @@ const AmpPermissionsOverrideSchema = z.looseObject({
|
|
|
17310
17916
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17311
17917
|
permissions: z.optional(z.array(z.looseObject({
|
|
17312
17918
|
tool: z.string(),
|
|
17313
|
-
action: z.
|
|
17919
|
+
action: z.enum([
|
|
17920
|
+
"allow",
|
|
17921
|
+
"ask",
|
|
17922
|
+
"reject",
|
|
17923
|
+
"delegate"
|
|
17924
|
+
]),
|
|
17925
|
+
context: z.optional(z.enum(["thread", "subagent"]))
|
|
17314
17926
|
}))),
|
|
17315
|
-
mcpPermissions: z.optional(z.array(z.looseObject({}))),
|
|
17927
|
+
mcpPermissions: z.optional(z.array(z.looseObject({ action: z.enum(["allow", "reject"]) }))),
|
|
17316
17928
|
guardedFiles: z.optional(z.looseObject({ allowlist: z.optional(z.array(z.string())) })),
|
|
17317
17929
|
dangerouslyAllowAll: z.optional(z.boolean())
|
|
17318
17930
|
});
|
|
@@ -17337,7 +17949,12 @@ const AmpPermissionsOverrideSchema = z.looseObject({
|
|
|
17337
17949
|
*/
|
|
17338
17950
|
const AntigravityCliPermissionsOverrideSchema = z.looseObject({
|
|
17339
17951
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17340
|
-
toolPermission: z.optional(z.
|
|
17952
|
+
toolPermission: z.optional(z.enum([
|
|
17953
|
+
"request-review",
|
|
17954
|
+
"proceed-in-sandbox",
|
|
17955
|
+
"always-proceed",
|
|
17956
|
+
"strict"
|
|
17957
|
+
])),
|
|
17341
17958
|
enableTerminalSandbox: z.optional(z.boolean())
|
|
17342
17959
|
});
|
|
17343
17960
|
/**
|
|
@@ -17366,7 +17983,14 @@ const AugmentcodePermissionsOverrideSchema = z.looseObject({
|
|
|
17366
17983
|
permission: z.optional(ToolScopedPermissionSchema),
|
|
17367
17984
|
toolPermissions: z.optional(z.array(z.looseObject({
|
|
17368
17985
|
toolName: z.string(),
|
|
17369
|
-
|
|
17986
|
+
eventType: z.optional(z.enum(["tool-call", "tool-response"])),
|
|
17987
|
+
permission: z.looseObject({ type: z.enum([
|
|
17988
|
+
"allow",
|
|
17989
|
+
"deny",
|
|
17990
|
+
"ask-user",
|
|
17991
|
+
"webhook-policy",
|
|
17992
|
+
"script-policy"
|
|
17993
|
+
]) })
|
|
17370
17994
|
})))
|
|
17371
17995
|
});
|
|
17372
17996
|
/**
|
|
@@ -17456,12 +18080,20 @@ const CodexApprovalsReviewerSchema = z.enum([
|
|
|
17456
18080
|
* `[permissions.rulesync]` profile may extend. Codex ships three built-in
|
|
17457
18081
|
* profiles (`:read-only`, `:workspace`, `:danger-full-access`; the leading
|
|
17458
18082
|
* colon is reserved for built-ins), but `extends` rejects
|
|
17459
|
-
* `:danger-full-access` at config load time, so only
|
|
17460
|
-
*
|
|
17461
|
-
*
|
|
18083
|
+
* `:danger-full-access` at config load time, so only these two are valid
|
|
18084
|
+
* `extends` parents. The value list is exported so the Codex CLI translator
|
|
18085
|
+
* derives its import-side baseline check from the same source.
|
|
17462
18086
|
* @see https://learn.chatgpt.com/docs/permissions
|
|
17463
18087
|
*/
|
|
17464
|
-
const
|
|
18088
|
+
const CODEX_EXTENDABLE_BASELINE_PROFILES = [":read-only", ":workspace"];
|
|
18089
|
+
/**
|
|
18090
|
+
* All accepted `codexcli.base_permission_profile` values. `:danger-full-access`
|
|
18091
|
+
* cannot be an `extends` parent, so selecting it makes rulesync emit
|
|
18092
|
+
* `default_permissions = ":danger-full-access"` directly and skip the managed
|
|
18093
|
+
* `[permissions.rulesync]` profile entirely (there is no sandbox for
|
|
18094
|
+
* filesystem/network rules to refine in that mode).
|
|
18095
|
+
*/
|
|
18096
|
+
const CODEX_BASE_PERMISSION_PROFILES = [...CODEX_EXTENDABLE_BASELINE_PROFILES, ":danger-full-access"];
|
|
17465
18097
|
const CodexBasePermissionProfileSchema = z.enum(CODEX_BASE_PERMISSION_PROFILES);
|
|
17466
18098
|
/**
|
|
17467
18099
|
* Codex CLI-scoped permission override.
|
|
@@ -17472,10 +18104,14 @@ const CodexBasePermissionProfileSchema = z.enum(CODEX_BASE_PERMISSION_PROFILES);
|
|
|
17472
18104
|
* override whose fields are written verbatim as top-level `.codex/config.toml`
|
|
17473
18105
|
* keys (the override wins per key; existing sibling keys the user set directly
|
|
17474
18106
|
* are preserved):
|
|
17475
|
-
* - `base_permission_profile` — the built-in profile
|
|
17476
|
-
*
|
|
17477
|
-
*
|
|
17478
|
-
*
|
|
18107
|
+
* - `base_permission_profile` — the built-in baseline profile (`:read-only` |
|
|
18108
|
+
* `:workspace` | `:danger-full-access`). Unlike the other keys it is not a
|
|
18109
|
+
* top-level config key: the extendable baselines are emitted as the managed
|
|
18110
|
+
* `[permissions.rulesync]` profile's `extends` value, while
|
|
18111
|
+
* `:danger-full-access` (which Codex rejects as an `extends` parent) is
|
|
18112
|
+
* selected directly via `default_permissions` and skips the managed profile
|
|
18113
|
+
* entirely — canonical filesystem/network rules are ignored in that mode.
|
|
18114
|
+
* Defaults to `:workspace` when unspecified.
|
|
17479
18115
|
* - `approval_policy` — `untrusted` | `on-request` (legacy alias `on-failure`) |
|
|
17480
18116
|
* `never`, or a `{ granular = { … } }` table (kept verbatim; the granular
|
|
17481
18117
|
* schema has required fields that are brittle to model as typed keys).
|
|
@@ -17495,6 +18131,15 @@ const CodexBasePermissionProfileSchema = z.enum(CODEX_BASE_PERMISSION_PROFILES);
|
|
|
17495
18131
|
* | `guardian_subagent`), or a table for the richer reviewer config.
|
|
17496
18132
|
* Defaults to `auto_review` when neither the override nor the existing
|
|
17497
18133
|
* config sets it.
|
|
18134
|
+
* - `git_write_rules` — whether the managed profile's `:workspace_roots` table
|
|
18135
|
+
* emits the default `.git` carve-out (`".git/**" = "write"`). Codex's
|
|
18136
|
+
* `:workspace` baseline makes `.git` read-only, which denies basic git
|
|
18137
|
+
* workflows (commit/stage writes to `.git/index`, `.git/objects`, refs,
|
|
18138
|
+
* logs; everyday commands like `git remote add` or `git push -u` write to
|
|
18139
|
+
* `.git/config`), so the carve-out is emitted by default. Defaults to
|
|
18140
|
+
* `true`; only an explicit `false` suppresses it. Like
|
|
18141
|
+
* `base_permission_profile` it is consumed by the profile builder, not
|
|
18142
|
+
* written as a top-level config key.
|
|
17498
18143
|
*
|
|
17499
18144
|
* Two surfaces are deliberately NOT authorable here so the override can never
|
|
17500
18145
|
* clobber a feature-owned key: `mcp_servers.*` per-MCP gating is owned by the
|
|
@@ -17520,7 +18165,8 @@ const CodexcliPermissionsOverrideSchema = z.looseObject({
|
|
|
17520
18165
|
/** @deprecated Superseded by `base_permission_profile` (permission profiles). */
|
|
17521
18166
|
sandbox_workspace_write: z.optional(z.looseObject({})),
|
|
17522
18167
|
apps: z.optional(z.looseObject({})),
|
|
17523
|
-
approvals_reviewer: z.optional(z.union([CodexApprovalsReviewerSchema, z.looseObject({})]))
|
|
18168
|
+
approvals_reviewer: z.optional(z.union([CodexApprovalsReviewerSchema, z.looseObject({})])),
|
|
18169
|
+
git_write_rules: z.optional(z.boolean())
|
|
17524
18170
|
});
|
|
17525
18171
|
/**
|
|
17526
18172
|
* Permissions configuration.
|
|
@@ -19489,11 +20135,14 @@ var ClinePermissions = class ClinePermissions extends ToolPermissions {
|
|
|
19489
20135
|
const RULESYNC_PROFILE_NAME = "rulesync";
|
|
19490
20136
|
const CODEX_WORKSPACE_ROOTS_KEY = ":workspace_roots";
|
|
19491
20137
|
const CODEX_WORKSPACE_BASELINE = ":workspace";
|
|
19492
|
-
const
|
|
20138
|
+
const CODEX_READ_ONLY_BASELINE = ":read-only";
|
|
20139
|
+
const CODEX_DANGER_FULL_ACCESS_BASELINE = ":danger-full-access";
|
|
20140
|
+
const CODEX_EXTENDABLE_BASELINES = new Set(CODEX_EXTENDABLE_BASELINE_PROFILES);
|
|
19493
20141
|
const CODEX_DEFAULT_APPROVAL_POLICY = "on-request";
|
|
19494
20142
|
const CODEX_DEFAULT_APPROVALS_REVIEWER = "auto_review";
|
|
19495
20143
|
const CODEX_GLOB_SCAN_MAX_DEPTH = 8;
|
|
19496
20144
|
const CODEX_MINIMAL_KEY = ":minimal";
|
|
20145
|
+
const CODEX_GIT_WRITE_RULES = { ".git/**": "write" };
|
|
19497
20146
|
const GLOBAL_WILDCARD_DOMAIN = "*";
|
|
19498
20147
|
var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
19499
20148
|
static getSettablePaths(_options = {}) {
|
|
@@ -19521,8 +20170,40 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
19521
20170
|
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
19522
20171
|
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
19523
20172
|
const existing = toMutableTable(smolToml.parse(existingContent || smolToml.stringify({})));
|
|
20173
|
+
const canonicalConfig = rulesyncPermissions.getJson();
|
|
20174
|
+
if (canonicalConfig.codexcli?.base_permission_profile === CODEX_DANGER_FULL_ACCESS_BASELINE) {
|
|
20175
|
+
const ignoredCategories = Object.entries(canonicalConfig.permission).filter(([category, rules]) => category !== "bash" && Object.keys(rules).length > 0).map(([category]) => category);
|
|
20176
|
+
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.`);
|
|
20177
|
+
const permissionsTable = toMutableTable(existing.permissions);
|
|
20178
|
+
if (permissionsTable[RULESYNC_PROFILE_NAME] !== void 0) {
|
|
20179
|
+
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.`);
|
|
20180
|
+
delete permissionsTable[RULESYNC_PROFILE_NAME];
|
|
20181
|
+
}
|
|
20182
|
+
const overridePatch = computeCodexcliOverridePatch({
|
|
20183
|
+
existing,
|
|
20184
|
+
override: canonicalConfig.codexcli,
|
|
20185
|
+
logger
|
|
20186
|
+
});
|
|
20187
|
+
return new CodexcliPermissions({
|
|
20188
|
+
outputRoot,
|
|
20189
|
+
relativeDirPath: paths.relativeDirPath,
|
|
20190
|
+
relativeFilePath: paths.relativeFilePath,
|
|
20191
|
+
fileContent: applySharedConfigPatch({
|
|
20192
|
+
fileKey: sharedConfigFileKey(paths),
|
|
20193
|
+
feature: "permissions",
|
|
20194
|
+
existingContent,
|
|
20195
|
+
patch: {
|
|
20196
|
+
permissions: Object.keys(permissionsTable).length > 0 ? permissionsTable : void 0,
|
|
20197
|
+
default_permissions: CODEX_DANGER_FULL_ACCESS_BASELINE,
|
|
20198
|
+
...overridePatch
|
|
20199
|
+
},
|
|
20200
|
+
filePath
|
|
20201
|
+
}),
|
|
20202
|
+
validate
|
|
20203
|
+
});
|
|
20204
|
+
}
|
|
19524
20205
|
const newProfile = convertRulesyncToCodexProfile({
|
|
19525
|
-
config:
|
|
20206
|
+
config: canonicalConfig,
|
|
19526
20207
|
logger
|
|
19527
20208
|
});
|
|
19528
20209
|
const permissionsTable = toMutableTable(existing.permissions);
|
|
@@ -19583,6 +20264,7 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
19583
20264
|
});
|
|
19584
20265
|
const override = extractCodexcliOverride(table);
|
|
19585
20266
|
if (typeof profile?.extends === "string" && CODEX_EXTENDABLE_BASELINES.has(profile.extends)) override.base_permission_profile = profile.extends;
|
|
20267
|
+
if (defaultProfile === CODEX_DANGER_FULL_ACCESS_BASELINE) override.base_permission_profile = CODEX_DANGER_FULL_ACCESS_BASELINE;
|
|
19586
20268
|
const result = Object.keys(override).length > 0 ? {
|
|
19587
20269
|
...config,
|
|
19588
20270
|
codexcli: override
|
|
@@ -19638,16 +20320,10 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19638
20320
|
const filesystem = { [CODEX_MINIMAL_KEY]: "read" };
|
|
19639
20321
|
const workspaceRootFilesystem = {};
|
|
19640
20322
|
const domains = {};
|
|
20323
|
+
const filesystemCategoryRules = {};
|
|
19641
20324
|
for (const [toolName, rules] of Object.entries(config.permission)) {
|
|
19642
20325
|
if (toolName === "read" || toolName === "edit" || toolName === "write") {
|
|
19643
|
-
|
|
19644
|
-
for (const [pattern, action] of Object.entries(rules)) addFilesystemRule({
|
|
19645
|
-
filesystem,
|
|
19646
|
-
workspaceRootFilesystem,
|
|
19647
|
-
pattern,
|
|
19648
|
-
access: mapAction(action),
|
|
19649
|
-
logger
|
|
19650
|
-
});
|
|
20326
|
+
filesystemCategoryRules[toolName] = rules;
|
|
19651
20327
|
continue;
|
|
19652
20328
|
}
|
|
19653
20329
|
if (toolName === "webfetch") {
|
|
@@ -19660,6 +20336,21 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19660
20336
|
}
|
|
19661
20337
|
logger?.warn(`Codex CLI permissions support only read/edit/write/webfetch categories. Skipping: ${toolName}`);
|
|
19662
20338
|
}
|
|
20339
|
+
for (const [pattern, access] of mergeFilesystemCategoryRules({
|
|
20340
|
+
categoryRules: filesystemCategoryRules,
|
|
20341
|
+
logger
|
|
20342
|
+
})) addFilesystemRule({
|
|
20343
|
+
filesystem,
|
|
20344
|
+
workspaceRootFilesystem,
|
|
20345
|
+
pattern,
|
|
20346
|
+
access,
|
|
20347
|
+
logger
|
|
20348
|
+
});
|
|
20349
|
+
applyDefaultGitWriteRules({
|
|
20350
|
+
config,
|
|
20351
|
+
filesystem,
|
|
20352
|
+
workspaceRootFilesystem
|
|
20353
|
+
});
|
|
19663
20354
|
if (Object.keys(workspaceRootFilesystem).length > 0) {
|
|
19664
20355
|
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.`);
|
|
19665
20356
|
if (Object.keys(workspaceRootFilesystem).some((pattern) => pattern.includes("**"))) filesystem.glob_scan_max_depth = CODEX_GLOB_SCAN_MAX_DEPTH;
|
|
@@ -19677,6 +20368,12 @@ function convertRulesyncToCodexProfile({ config, logger }) {
|
|
|
19677
20368
|
...network ? { network } : {}
|
|
19678
20369
|
};
|
|
19679
20370
|
}
|
|
20371
|
+
function applyDefaultGitWriteRules({ config, filesystem, workspaceRootFilesystem }) {
|
|
20372
|
+
if (config.codexcli?.git_write_rules === false) return;
|
|
20373
|
+
if (config.codexcli?.base_permission_profile === CODEX_READ_ONLY_BASELINE) return;
|
|
20374
|
+
if (typeof filesystem[CODEX_WORKSPACE_ROOTS_KEY] === "string") return;
|
|
20375
|
+
for (const [pattern, access] of Object.entries(CODEX_GIT_WRITE_RULES)) workspaceRootFilesystem[pattern] ??= access;
|
|
20376
|
+
}
|
|
19680
20377
|
function convertCodexProfileToRulesync({ profile, domainsHadUnknown }) {
|
|
19681
20378
|
const permission = {};
|
|
19682
20379
|
if (profile?.filesystem) {
|
|
@@ -19688,7 +20385,10 @@ function convertCodexProfileToRulesync({ profile, domainsHadUnknown }) {
|
|
|
19688
20385
|
addRulesyncFilesystemRule(permission, pattern, access);
|
|
19689
20386
|
continue;
|
|
19690
20387
|
}
|
|
19691
|
-
if (isCodexFilesystemRuleTable(access)) for (const [nestedPattern, nestedAccess] of Object.entries(access))
|
|
20388
|
+
if (isCodexFilesystemRuleTable(access)) for (const [nestedPattern, nestedAccess] of Object.entries(access)) {
|
|
20389
|
+
if (pattern === CODEX_WORKSPACE_ROOTS_KEY && CODEX_GIT_WRITE_RULES[nestedPattern] === nestedAccess) continue;
|
|
20390
|
+
addRulesyncFilesystemRule(permission, nestedPattern, nestedAccess);
|
|
20391
|
+
}
|
|
19692
20392
|
}
|
|
19693
20393
|
}
|
|
19694
20394
|
if (profile?.network && profile.network.enabled !== false) {
|
|
@@ -19730,9 +20430,28 @@ function toCodexProfile(value) {
|
|
|
19730
20430
|
}
|
|
19731
20431
|
function warnAboutPreservedProfileState({ existingProfile, newProfile, existingDomainsHadUnknown, logger }) {
|
|
19732
20432
|
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)"}".`);
|
|
20433
|
+
warnAboutPreservedNetworkState({
|
|
20434
|
+
existingProfile,
|
|
20435
|
+
newProfile,
|
|
20436
|
+
logger
|
|
20437
|
+
});
|
|
20438
|
+
if (existingDomainsHadUnknown) logger?.warn(`Existing "network.domains" contained unrecognized values. These entries were skipped and will not be imported.`);
|
|
20439
|
+
}
|
|
20440
|
+
function networkHasAllowDomain(network) {
|
|
20441
|
+
return Object.values(network?.domains ?? {}).some((action) => action === "allow");
|
|
20442
|
+
}
|
|
20443
|
+
function warnAboutNetworkEnabledState({ existingProfile, newProfile, logger }) {
|
|
20444
|
+
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.`);
|
|
20445
|
+
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.`);
|
|
20446
|
+
}
|
|
20447
|
+
function warnAboutPreservedNetworkState({ existingProfile, newProfile, logger }) {
|
|
19733
20448
|
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.`);
|
|
20449
|
+
warnAboutNetworkEnabledState({
|
|
20450
|
+
existingProfile,
|
|
20451
|
+
newProfile,
|
|
20452
|
+
logger
|
|
20453
|
+
});
|
|
19734
20454
|
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.`);
|
|
19735
|
-
if (existingDomainsHadUnknown) logger?.warn(`Existing "network.domains" contained unrecognized values. These entries were skipped and will not be imported.`);
|
|
19736
20455
|
}
|
|
19737
20456
|
const MANAGED_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
19738
20457
|
"description",
|
|
@@ -19774,6 +20493,7 @@ function preserveUnmanagedProfileKeys({ rawExistingProfile, profile, logger }) {
|
|
|
19774
20493
|
function mergeWithExistingProfile({ newProfile, existingProfile }) {
|
|
19775
20494
|
if (!existingProfile) return newProfile;
|
|
19776
20495
|
const mergedNetwork = { ...newProfile.network };
|
|
20496
|
+
if (existingProfile.network?.enabled !== void 0 && mergedNetwork.enabled === void 0 && !networkHasAllowDomain(existingProfile.network)) mergedNetwork.enabled = existingProfile.network.enabled;
|
|
19777
20497
|
if (existingProfile.network?.mode !== void 0 && mergedNetwork.mode === void 0) mergedNetwork.mode = existingProfile.network.mode;
|
|
19778
20498
|
if (existingProfile.network?.unix_sockets !== void 0 && mergedNetwork.unix_sockets === void 0) mergedNetwork.unix_sockets = existingProfile.network.unix_sockets;
|
|
19779
20499
|
const hasNetwork = Object.keys(mergedNetwork).length > 0;
|
|
@@ -19825,7 +20545,7 @@ function computeCodexcliOverridePatch({ existing, override, logger }) {
|
|
|
19825
20545
|
const patch = {};
|
|
19826
20546
|
const allowed = new Set(CODEXCLI_OVERRIDE_KEYS);
|
|
19827
20547
|
for (const [key, value] of Object.entries(override ?? {})) {
|
|
19828
|
-
if (key === "base_permission_profile") continue;
|
|
20548
|
+
if (key === "base_permission_profile" || key === "git_write_rules") continue;
|
|
19829
20549
|
if (!allowed.has(key)) {
|
|
19830
20550
|
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.`);
|
|
19831
20551
|
continue;
|
|
@@ -19906,6 +20626,67 @@ function mapReadAction(action) {
|
|
|
19906
20626
|
function mapWriteAction(action) {
|
|
19907
20627
|
return action === "allow" ? "write" : "deny";
|
|
19908
20628
|
}
|
|
20629
|
+
/**
|
|
20630
|
+
* Merge the canonical read/edit/write category rules into one Codex access
|
|
20631
|
+
* level per path pattern (Codex models a single `deny` < `read` < `write`
|
|
20632
|
+
* level, with no `ask`).
|
|
20633
|
+
*
|
|
20634
|
+
* - `edit` and `write` collapse onto Codex's write side; when both carry the
|
|
20635
|
+
* same pattern, the more restrictive action wins (`deny` > `ask` > `allow`).
|
|
20636
|
+
* - `read: allow` + write-side `allow` → `"write"`.
|
|
20637
|
+
* - `read: allow` + write-side non-allow → `"read"` (readable but not
|
|
20638
|
+
* writable — exactly what Codex's `"read"` level expresses).
|
|
20639
|
+
* - `read` non-allow → `"deny"` regardless of the write side; a contradictory
|
|
20640
|
+
* write-side `allow` (unreadable but writable is not expressible in Codex)
|
|
20641
|
+
* is warned about.
|
|
20642
|
+
* - Single-category patterns keep the existing mapReadAction/mapWriteAction
|
|
20643
|
+
* mappings.
|
|
20644
|
+
*
|
|
20645
|
+
* Iteration order is read → edit → write with first-seen pattern order, so
|
|
20646
|
+
* the emitted table is stable regardless of the authored category order.
|
|
20647
|
+
* Note the merge is one-way: `"{path}" = "read"` imports back as
|
|
20648
|
+
* `read: allow` only (the explicit write-side deny is implied by Codex's
|
|
20649
|
+
* access level and not re-materialized).
|
|
20650
|
+
*/
|
|
20651
|
+
function mergeFilesystemCategoryRules({ categoryRules, logger }) {
|
|
20652
|
+
const readRules = categoryRules.read ?? {};
|
|
20653
|
+
const writeSideRestrictiveness = {
|
|
20654
|
+
deny: 2,
|
|
20655
|
+
ask: 1,
|
|
20656
|
+
allow: 0
|
|
20657
|
+
};
|
|
20658
|
+
const writeSideRules = {};
|
|
20659
|
+
for (const category of ["edit", "write"]) for (const [pattern, action] of Object.entries(categoryRules[category] ?? {})) {
|
|
20660
|
+
const existing = writeSideRules[pattern];
|
|
20661
|
+
if (existing === void 0 || writeSideRestrictiveness[action] > writeSideRestrictiveness[existing]) writeSideRules[pattern] = action;
|
|
20662
|
+
}
|
|
20663
|
+
const patterns = [];
|
|
20664
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20665
|
+
for (const pattern of [...Object.keys(readRules), ...Object.keys(writeSideRules)]) if (!seen.has(pattern)) {
|
|
20666
|
+
seen.add(pattern);
|
|
20667
|
+
patterns.push(pattern);
|
|
20668
|
+
}
|
|
20669
|
+
const merged = [];
|
|
20670
|
+
for (const pattern of patterns) {
|
|
20671
|
+
const readAction = readRules[pattern];
|
|
20672
|
+
const writeAction = writeSideRules[pattern];
|
|
20673
|
+
if (readAction === void 0) {
|
|
20674
|
+
merged.push([pattern, mapWriteAction(writeAction)]);
|
|
20675
|
+
continue;
|
|
20676
|
+
}
|
|
20677
|
+
if (writeAction === void 0) {
|
|
20678
|
+
merged.push([pattern, mapReadAction(readAction)]);
|
|
20679
|
+
continue;
|
|
20680
|
+
}
|
|
20681
|
+
if (readAction === "allow") {
|
|
20682
|
+
merged.push([pattern, writeAction === "allow" ? "write" : "read"]);
|
|
20683
|
+
continue;
|
|
20684
|
+
}
|
|
20685
|
+
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".`);
|
|
20686
|
+
merged.push([pattern, "deny"]);
|
|
20687
|
+
}
|
|
20688
|
+
return merged;
|
|
20689
|
+
}
|
|
19909
20690
|
function buildCodexBashRulesContent(config) {
|
|
19910
20691
|
const bashRules = config.permission.bash ?? {};
|
|
19911
20692
|
const entries = Object.entries(bashRules);
|
|
@@ -20857,7 +21638,7 @@ function convertRulesyncToGoosePermissionConfig({ config, logger }) {
|
|
|
20857
21638
|
function convertGoosePermissionConfigToRulesync(userPermission) {
|
|
20858
21639
|
const permission = {};
|
|
20859
21640
|
for (const key of GOOSE_PERMISSION_LIST_KEYS) {
|
|
20860
|
-
const toolNames = isStringArray(userPermission[key]) ? userPermission[key] : [];
|
|
21641
|
+
const toolNames = isStringArray$1(userPermission[key]) ? userPermission[key] : [];
|
|
20861
21642
|
const action = GOOSE_LIST_TO_ACTION[key];
|
|
20862
21643
|
for (const toolName of toolNames) {
|
|
20863
21644
|
const category = GOOSE_TO_RULESYNC_TOOL_NAME[toolName] ?? toolName;
|
|
@@ -21097,7 +21878,7 @@ const ACTION_RANK = {
|
|
|
21097
21878
|
* (mirrors the Cursor adapter's preservation of unmanaged types).
|
|
21098
21879
|
*/
|
|
21099
21880
|
function unmanagedEntries(existingPermission, key) {
|
|
21100
|
-
return (isStringArray(existingPermission[key]) ? existingPermission[key] : []).filter((entry) => parseGrokEntry(entry) === null);
|
|
21881
|
+
return (isStringArray$1(existingPermission[key]) ? existingPermission[key] : []).filter((entry) => parseGrokEntry(entry) === null);
|
|
21101
21882
|
}
|
|
21102
21883
|
/**
|
|
21103
21884
|
* Bucket canonical rules into Grok's `[permission]` allow/deny/ask arrays of
|
|
@@ -21138,9 +21919,9 @@ function buildGrokPermissionArrays(config, existingPermission, logger) {
|
|
|
21138
21919
|
* arrays resolves to the strictest action.
|
|
21139
21920
|
*/
|
|
21140
21921
|
function parseGrokPermissionArrays(permission) {
|
|
21141
|
-
const allow = isStringArray(permission.allow) ? permission.allow : void 0;
|
|
21142
|
-
const deny = isStringArray(permission.deny) ? permission.deny : void 0;
|
|
21143
|
-
const ask = isStringArray(permission.ask) ? permission.ask : void 0;
|
|
21922
|
+
const allow = isStringArray$1(permission.allow) ? permission.allow : void 0;
|
|
21923
|
+
const deny = isStringArray$1(permission.deny) ? permission.deny : void 0;
|
|
21924
|
+
const ask = isStringArray$1(permission.ask) ? permission.ask : void 0;
|
|
21144
21925
|
if ((allow?.length ?? 0) + (deny?.length ?? 0) + (ask?.length ?? 0) === 0) return null;
|
|
21145
21926
|
const result = {};
|
|
21146
21927
|
const apply = (entries, action) => {
|
|
@@ -22921,7 +23702,7 @@ function convertRovodevToolPermissionsToRulesync(toolPermissions) {
|
|
|
22921
23702
|
permission[category][CATCH_ALL_PATTERN$1] = value;
|
|
22922
23703
|
}
|
|
22923
23704
|
}
|
|
22924
|
-
if (isStringArray(toolPermissions.allowedExternalPaths)) for (const path of toolPermissions.allowedExternalPaths) {
|
|
23705
|
+
if (isStringArray$1(toolPermissions.allowedExternalPaths)) for (const path of toolPermissions.allowedExternalPaths) {
|
|
22925
23706
|
permission.read ??= {};
|
|
22926
23707
|
permission.read[path] = "allow";
|
|
22927
23708
|
}
|
|
@@ -23481,8 +24262,8 @@ var WarpPermissions = class WarpPermissions extends ToolPermissions {
|
|
|
23481
24262
|
const agents = isRecord(settings.agents) ? settings.agents : {};
|
|
23482
24263
|
const profiles = isRecord(agents.profiles) ? agents.profiles : {};
|
|
23483
24264
|
const config = convertWarpToRulesyncPermissions({
|
|
23484
|
-
allow: isStringArray(profiles[ALLOWLIST_KEY]) ? profiles[ALLOWLIST_KEY] : [],
|
|
23485
|
-
deny: isStringArray(profiles[DENYLIST_KEY]) ? profiles[DENYLIST_KEY] : []
|
|
24265
|
+
allow: isStringArray$1(profiles[ALLOWLIST_KEY]) ? profiles[ALLOWLIST_KEY] : [],
|
|
24266
|
+
deny: isStringArray$1(profiles[DENYLIST_KEY]) ? profiles[DENYLIST_KEY] : []
|
|
23486
24267
|
});
|
|
23487
24268
|
const warpOverride = {};
|
|
23488
24269
|
for (const key of WARP_OVERRIDE_KEYS) if (profiles[key] !== void 0) warpOverride[key] = profiles[key];
|
|
@@ -24062,9 +24843,6 @@ var PermissionsProcessor = class extends FeatureProcessor {
|
|
|
24062
24843
|
}
|
|
24063
24844
|
};
|
|
24064
24845
|
//#endregion
|
|
24065
|
-
//#region src/constants/general.ts
|
|
24066
|
-
const SKILL_FILE_NAME = "SKILL.md";
|
|
24067
|
-
//#endregion
|
|
24068
24846
|
//#region src/types/ai-dir.ts
|
|
24069
24847
|
var AiDir = class {
|
|
24070
24848
|
/**
|
|
@@ -24265,10 +25043,10 @@ var ToolSkill = class extends AiDir {
|
|
|
24265
25043
|
const settablePaths = getSettablePaths({ global });
|
|
24266
25044
|
const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
|
|
24267
25045
|
const skillDirPath = join(outputRoot, actualRelativeDirPath, dirName);
|
|
24268
|
-
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME);
|
|
24269
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25046
|
+
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME$1);
|
|
25047
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24270
25048
|
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24271
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25049
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24272
25050
|
return {
|
|
24273
25051
|
outputRoot,
|
|
24274
25052
|
relativeDirPath: actualRelativeDirPath,
|
|
@@ -24310,7 +25088,7 @@ var SimulatedSkill = class extends ToolSkill {
|
|
|
24310
25088
|
relativeDirPath,
|
|
24311
25089
|
dirName,
|
|
24312
25090
|
mainFile: {
|
|
24313
|
-
name: SKILL_FILE_NAME,
|
|
25091
|
+
name: SKILL_FILE_NAME$1,
|
|
24314
25092
|
body,
|
|
24315
25093
|
frontmatter: { ...frontmatter }
|
|
24316
25094
|
},
|
|
@@ -24368,12 +25146,12 @@ var SimulatedSkill = class extends ToolSkill {
|
|
|
24368
25146
|
const settablePaths = this.getSettablePaths();
|
|
24369
25147
|
const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
|
|
24370
25148
|
const skillDirPath = join(outputRoot, actualRelativeDirPath, dirName);
|
|
24371
|
-
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME);
|
|
24372
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25149
|
+
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME$1);
|
|
25150
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24373
25151
|
const { frontmatter, body: content } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24374
25152
|
const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
|
|
24375
25153
|
if (!result.success) throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
|
|
24376
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25154
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, actualRelativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24377
25155
|
return {
|
|
24378
25156
|
outputRoot,
|
|
24379
25157
|
relativeDirPath: actualRelativeDirPath,
|
|
@@ -24583,7 +25361,7 @@ var RulesyncSkill = class RulesyncSkill extends AiDir {
|
|
|
24583
25361
|
relativeDirPath,
|
|
24584
25362
|
dirName,
|
|
24585
25363
|
mainFile: {
|
|
24586
|
-
name: SKILL_FILE_NAME,
|
|
25364
|
+
name: SKILL_FILE_NAME$1,
|
|
24587
25365
|
body,
|
|
24588
25366
|
frontmatter: { ...frontmatter }
|
|
24589
25367
|
},
|
|
@@ -24618,13 +25396,13 @@ var RulesyncSkill = class RulesyncSkill extends AiDir {
|
|
|
24618
25396
|
}
|
|
24619
25397
|
static async fromDir({ outputRoot = process.cwd(), relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName, global = false }) {
|
|
24620
25398
|
const skillDirPath = join(outputRoot, relativeDirPath, dirName);
|
|
24621
|
-
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME);
|
|
24622
|
-
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
|
|
25399
|
+
const skillFilePath = join(skillDirPath, SKILL_FILE_NAME$1);
|
|
25400
|
+
if (!await fileExists(skillFilePath)) throw new Error(`${SKILL_FILE_NAME$1} not found in ${skillDirPath}`);
|
|
24623
25401
|
const { frontmatter, body: content, hasFrontmatter } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
24624
25402
|
if (!hasFrontmatter) throw new Error(`Missing frontmatter in ${skillFilePath}. Rulesync files must begin with a YAML frontmatter block delimited by '---'.`);
|
|
24625
25403
|
const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
|
|
24626
25404
|
if (!result.success) throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
|
|
24627
|
-
const otherFiles = await this.collectOtherFiles(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME);
|
|
25405
|
+
const otherFiles = await this.collectOtherFiles(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
24628
25406
|
return new RulesyncSkill({
|
|
24629
25407
|
outputRoot,
|
|
24630
25408
|
relativeDirPath,
|
|
@@ -24664,7 +25442,7 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24664
25442
|
relativeDirPath,
|
|
24665
25443
|
dirName,
|
|
24666
25444
|
mainFile: {
|
|
24667
|
-
name: SKILL_FILE_NAME,
|
|
25445
|
+
name: SKILL_FILE_NAME$1,
|
|
24668
25446
|
body,
|
|
24669
25447
|
frontmatter: { ...frontmatter }
|
|
24670
25448
|
},
|
|
@@ -24691,7 +25469,7 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24691
25469
|
validate() {
|
|
24692
25470
|
if (!this.mainFile) return {
|
|
24693
25471
|
success: false,
|
|
24694
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25472
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
24695
25473
|
};
|
|
24696
25474
|
const result = RovodevSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
24697
25475
|
if (!result.success) return {
|
|
@@ -24767,10 +25545,10 @@ var RovodevSkill = class RovodevSkill extends ToolSkill {
|
|
|
24767
25545
|
const result = RovodevSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
24768
25546
|
if (!result.success) {
|
|
24769
25547
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
24770
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25548
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
24771
25549
|
}
|
|
24772
25550
|
if (result.data.name !== loaded.dirName) {
|
|
24773
|
-
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
25551
|
+
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
24774
25552
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
24775
25553
|
}
|
|
24776
25554
|
return new RovodevSkill({
|
|
@@ -24935,7 +25713,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
24935
25713
|
relativeDirPath,
|
|
24936
25714
|
dirName,
|
|
24937
25715
|
mainFile: {
|
|
24938
|
-
name: SKILL_FILE_NAME,
|
|
25716
|
+
name: SKILL_FILE_NAME$1,
|
|
24939
25717
|
body,
|
|
24940
25718
|
frontmatter: { ...frontmatter }
|
|
24941
25719
|
},
|
|
@@ -24959,7 +25737,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
24959
25737
|
validate() {
|
|
24960
25738
|
if (!this.mainFile) return {
|
|
24961
25739
|
success: false,
|
|
24962
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25740
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
24963
25741
|
};
|
|
24964
25742
|
const result = AgentsSkillsSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
24965
25743
|
if (!result.success) return {
|
|
@@ -25031,7 +25809,7 @@ var AgentsSkillsSkill = class AgentsSkillsSkill extends ToolSkill {
|
|
|
25031
25809
|
const result = AgentsSkillsSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25032
25810
|
if (!result.success) {
|
|
25033
25811
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25034
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25812
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25035
25813
|
}
|
|
25036
25814
|
return new this({
|
|
25037
25815
|
outputRoot: loaded.outputRoot,
|
|
@@ -25088,7 +25866,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25088
25866
|
relativeDirPath,
|
|
25089
25867
|
dirName,
|
|
25090
25868
|
mainFile: {
|
|
25091
|
-
name: SKILL_FILE_NAME,
|
|
25869
|
+
name: SKILL_FILE_NAME$1,
|
|
25092
25870
|
body,
|
|
25093
25871
|
frontmatter: { ...frontmatter }
|
|
25094
25872
|
},
|
|
@@ -25113,7 +25891,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25113
25891
|
validate() {
|
|
25114
25892
|
if (!this.mainFile) return {
|
|
25115
25893
|
success: false,
|
|
25116
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
25894
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25117
25895
|
};
|
|
25118
25896
|
const result = AiassistantSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25119
25897
|
if (!result.success) return {
|
|
@@ -25173,7 +25951,7 @@ var AiassistantSkill = class AiassistantSkill extends ToolSkill {
|
|
|
25173
25951
|
const result = AiassistantSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25174
25952
|
if (!result.success) {
|
|
25175
25953
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25176
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
25954
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25177
25955
|
}
|
|
25178
25956
|
return new AiassistantSkill({
|
|
25179
25957
|
outputRoot: loaded.outputRoot,
|
|
@@ -25224,7 +26002,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25224
26002
|
relativeDirPath,
|
|
25225
26003
|
dirName,
|
|
25226
26004
|
mainFile: {
|
|
25227
|
-
name: SKILL_FILE_NAME,
|
|
26005
|
+
name: SKILL_FILE_NAME$1,
|
|
25228
26006
|
body,
|
|
25229
26007
|
frontmatter: { ...frontmatter }
|
|
25230
26008
|
},
|
|
@@ -25248,7 +26026,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25248
26026
|
validate() {
|
|
25249
26027
|
if (!this.mainFile) return {
|
|
25250
26028
|
success: false,
|
|
25251
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26029
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25252
26030
|
};
|
|
25253
26031
|
const result = AmpSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25254
26032
|
if (!result.success) return {
|
|
@@ -25308,7 +26086,7 @@ var AmpSkill = class AmpSkill extends ToolSkill {
|
|
|
25308
26086
|
const result = AmpSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25309
26087
|
if (!result.success) {
|
|
25310
26088
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25311
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26089
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25312
26090
|
}
|
|
25313
26091
|
return new AmpSkill({
|
|
25314
26092
|
outputRoot: loaded.outputRoot,
|
|
@@ -25364,7 +26142,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25364
26142
|
relativeDirPath,
|
|
25365
26143
|
dirName,
|
|
25366
26144
|
mainFile: {
|
|
25367
|
-
name: SKILL_FILE_NAME,
|
|
26145
|
+
name: SKILL_FILE_NAME$1,
|
|
25368
26146
|
body,
|
|
25369
26147
|
frontmatter: { ...frontmatter }
|
|
25370
26148
|
},
|
|
@@ -25397,7 +26175,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25397
26175
|
validate() {
|
|
25398
26176
|
if (this.mainFile === void 0) return {
|
|
25399
26177
|
success: false,
|
|
25400
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26178
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25401
26179
|
};
|
|
25402
26180
|
const result = AntigravitySkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25403
26181
|
if (!result.success) return {
|
|
@@ -25457,7 +26235,7 @@ var AntigravitySharedSkill = class extends ToolSkill {
|
|
|
25457
26235
|
const result = AntigravitySkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25458
26236
|
if (!result.success) {
|
|
25459
26237
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25460
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26238
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25461
26239
|
}
|
|
25462
26240
|
return new this({
|
|
25463
26241
|
outputRoot: loaded.outputRoot,
|
|
@@ -25541,7 +26319,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25541
26319
|
relativeDirPath,
|
|
25542
26320
|
dirName,
|
|
25543
26321
|
mainFile: {
|
|
25544
|
-
name: SKILL_FILE_NAME,
|
|
26322
|
+
name: SKILL_FILE_NAME$1,
|
|
25545
26323
|
body,
|
|
25546
26324
|
frontmatter: { ...frontmatter }
|
|
25547
26325
|
},
|
|
@@ -25568,7 +26346,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25568
26346
|
validate() {
|
|
25569
26347
|
if (this.mainFile === void 0) return {
|
|
25570
26348
|
success: false,
|
|
25571
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26349
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25572
26350
|
};
|
|
25573
26351
|
const result = AugmentcodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25574
26352
|
if (!result.success) return {
|
|
@@ -25628,7 +26406,7 @@ var AugmentcodeSkill = class AugmentcodeSkill extends ToolSkill {
|
|
|
25628
26406
|
const result = AugmentcodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25629
26407
|
if (!result.success) {
|
|
25630
26408
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25631
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26409
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25632
26410
|
}
|
|
25633
26411
|
return new AugmentcodeSkill({
|
|
25634
26412
|
outputRoot: loaded.outputRoot,
|
|
@@ -25769,7 +26547,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25769
26547
|
relativeDirPath,
|
|
25770
26548
|
dirName,
|
|
25771
26549
|
mainFile: {
|
|
25772
|
-
name: SKILL_FILE_NAME,
|
|
26550
|
+
name: SKILL_FILE_NAME$1,
|
|
25773
26551
|
body,
|
|
25774
26552
|
frontmatter: { ...frontmatter }
|
|
25775
26553
|
},
|
|
@@ -25796,7 +26574,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25796
26574
|
validate() {
|
|
25797
26575
|
if (this.mainFile === void 0) return {
|
|
25798
26576
|
success: false,
|
|
25799
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26577
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25800
26578
|
};
|
|
25801
26579
|
const result = ClaudecodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25802
26580
|
if (!result.success) return {
|
|
@@ -25884,7 +26662,7 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
|
|
|
25884
26662
|
const result = ClaudecodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
25885
26663
|
if (!result.success) {
|
|
25886
26664
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
25887
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26665
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
25888
26666
|
}
|
|
25889
26667
|
return new ClaudecodeSkill({
|
|
25890
26668
|
outputRoot: loaded.outputRoot,
|
|
@@ -25930,7 +26708,7 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
25930
26708
|
relativeDirPath,
|
|
25931
26709
|
dirName,
|
|
25932
26710
|
mainFile: {
|
|
25933
|
-
name: SKILL_FILE_NAME,
|
|
26711
|
+
name: SKILL_FILE_NAME$1,
|
|
25934
26712
|
body,
|
|
25935
26713
|
frontmatter: { ...frontmatter }
|
|
25936
26714
|
},
|
|
@@ -25954,7 +26732,7 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
25954
26732
|
validate() {
|
|
25955
26733
|
if (!this.mainFile) return {
|
|
25956
26734
|
success: false,
|
|
25957
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26735
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
25958
26736
|
};
|
|
25959
26737
|
const result = ClineSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
25960
26738
|
if (!result.success) return {
|
|
@@ -26018,10 +26796,10 @@ var ClineSkill = class ClineSkill extends ToolSkill {
|
|
|
26018
26796
|
const result = ClineSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26019
26797
|
if (!result.success) {
|
|
26020
26798
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26021
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
26799
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26022
26800
|
}
|
|
26023
26801
|
if (result.data.name !== loaded.dirName) {
|
|
26024
|
-
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
26802
|
+
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
26025
26803
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
26026
26804
|
}
|
|
26027
26805
|
return new ClineSkill({
|
|
@@ -26135,7 +26913,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26135
26913
|
relativeDirPath,
|
|
26136
26914
|
dirName,
|
|
26137
26915
|
mainFile: {
|
|
26138
|
-
name: SKILL_FILE_NAME,
|
|
26916
|
+
name: SKILL_FILE_NAME$1,
|
|
26139
26917
|
body,
|
|
26140
26918
|
frontmatter: { ...frontmatter }
|
|
26141
26919
|
},
|
|
@@ -26159,7 +26937,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26159
26937
|
validate() {
|
|
26160
26938
|
if (!this.mainFile) return {
|
|
26161
26939
|
success: false,
|
|
26162
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
26940
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26163
26941
|
};
|
|
26164
26942
|
const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26165
26943
|
if (!result.success) return {
|
|
@@ -26237,7 +27015,7 @@ var CodexCliSkill = class CodexCliSkill extends ToolSkill {
|
|
|
26237
27015
|
const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26238
27016
|
if (!result.success) {
|
|
26239
27017
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26240
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27018
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26241
27019
|
}
|
|
26242
27020
|
return new CodexCliSkill({
|
|
26243
27021
|
outputRoot: loaded.outputRoot,
|
|
@@ -26289,7 +27067,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26289
27067
|
relativeDirPath,
|
|
26290
27068
|
dirName,
|
|
26291
27069
|
mainFile: {
|
|
26292
|
-
name: SKILL_FILE_NAME,
|
|
27070
|
+
name: SKILL_FILE_NAME$1,
|
|
26293
27071
|
body,
|
|
26294
27072
|
frontmatter: { ...frontmatter }
|
|
26295
27073
|
},
|
|
@@ -26314,7 +27092,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26314
27092
|
validate() {
|
|
26315
27093
|
if (!this.mainFile) return {
|
|
26316
27094
|
success: false,
|
|
26317
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27095
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26318
27096
|
};
|
|
26319
27097
|
const result = CopilotSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26320
27098
|
if (!result.success) return {
|
|
@@ -26381,7 +27159,7 @@ var CopilotSkill = class CopilotSkill extends ToolSkill {
|
|
|
26381
27159
|
const result = CopilotSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26382
27160
|
if (!result.success) {
|
|
26383
27161
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26384
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27162
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26385
27163
|
}
|
|
26386
27164
|
return new CopilotSkill({
|
|
26387
27165
|
outputRoot: loaded.outputRoot,
|
|
@@ -26435,7 +27213,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26435
27213
|
relativeDirPath,
|
|
26436
27214
|
dirName,
|
|
26437
27215
|
mainFile: {
|
|
26438
|
-
name: SKILL_FILE_NAME,
|
|
27216
|
+
name: SKILL_FILE_NAME$1,
|
|
26439
27217
|
body,
|
|
26440
27218
|
frontmatter: { ...frontmatter }
|
|
26441
27219
|
},
|
|
@@ -26460,7 +27238,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26460
27238
|
validate() {
|
|
26461
27239
|
if (!this.mainFile) return {
|
|
26462
27240
|
success: false,
|
|
26463
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27241
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26464
27242
|
};
|
|
26465
27243
|
const result = CopilotcliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26466
27244
|
if (!result.success) return {
|
|
@@ -26529,7 +27307,7 @@ var CopilotcliSkill = class CopilotcliSkill extends ToolSkill {
|
|
|
26529
27307
|
const result = CopilotcliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26530
27308
|
if (!result.success) {
|
|
26531
27309
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26532
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27310
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26533
27311
|
}
|
|
26534
27312
|
return new CopilotcliSkill({
|
|
26535
27313
|
outputRoot: loaded.outputRoot,
|
|
@@ -26579,7 +27357,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26579
27357
|
relativeDirPath,
|
|
26580
27358
|
dirName,
|
|
26581
27359
|
mainFile: {
|
|
26582
|
-
name: SKILL_FILE_NAME,
|
|
27360
|
+
name: SKILL_FILE_NAME$1,
|
|
26583
27361
|
body,
|
|
26584
27362
|
frontmatter: { ...frontmatter }
|
|
26585
27363
|
},
|
|
@@ -26603,7 +27381,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26603
27381
|
validate() {
|
|
26604
27382
|
if (!this.mainFile) return {
|
|
26605
27383
|
success: false,
|
|
26606
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27384
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26607
27385
|
};
|
|
26608
27386
|
const result = CursorSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26609
27387
|
if (!result.success) return {
|
|
@@ -26677,7 +27455,7 @@ var CursorSkill = class CursorSkill extends ToolSkill {
|
|
|
26677
27455
|
const result = CursorSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26678
27456
|
if (!result.success) {
|
|
26679
27457
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26680
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27458
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26681
27459
|
}
|
|
26682
27460
|
return new CursorSkill({
|
|
26683
27461
|
outputRoot: loaded.outputRoot,
|
|
@@ -26724,7 +27502,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26724
27502
|
relativeDirPath,
|
|
26725
27503
|
dirName,
|
|
26726
27504
|
mainFile: {
|
|
26727
|
-
name: SKILL_FILE_NAME,
|
|
27505
|
+
name: SKILL_FILE_NAME$1,
|
|
26728
27506
|
body,
|
|
26729
27507
|
frontmatter: { ...frontmatter }
|
|
26730
27508
|
},
|
|
@@ -26748,7 +27526,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26748
27526
|
validate() {
|
|
26749
27527
|
if (!this.mainFile) return {
|
|
26750
27528
|
success: false,
|
|
26751
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27529
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26752
27530
|
};
|
|
26753
27531
|
const result = DeepagentsSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26754
27532
|
if (!result.success) return {
|
|
@@ -26824,7 +27602,7 @@ var DeepagentsSkill = class DeepagentsSkill extends ToolSkill {
|
|
|
26824
27602
|
const result = DeepagentsSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26825
27603
|
if (!result.success) {
|
|
26826
27604
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26827
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27605
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26828
27606
|
}
|
|
26829
27607
|
return new DeepagentsSkill({
|
|
26830
27608
|
outputRoot: loaded.outputRoot,
|
|
@@ -26875,7 +27653,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26875
27653
|
relativeDirPath,
|
|
26876
27654
|
dirName,
|
|
26877
27655
|
mainFile: {
|
|
26878
|
-
name: SKILL_FILE_NAME,
|
|
27656
|
+
name: SKILL_FILE_NAME$1,
|
|
26879
27657
|
body,
|
|
26880
27658
|
frontmatter: { ...frontmatter }
|
|
26881
27659
|
},
|
|
@@ -26900,7 +27678,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26900
27678
|
validate() {
|
|
26901
27679
|
if (!this.mainFile) return {
|
|
26902
27680
|
success: false,
|
|
26903
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27681
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
26904
27682
|
};
|
|
26905
27683
|
const result = DevinSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
26906
27684
|
if (!result.success) return {
|
|
@@ -26952,6 +27730,18 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26952
27730
|
const targets = rulesyncSkill.getFrontmatter().targets;
|
|
26953
27731
|
return targets.includes("*") || targets.includes("devin");
|
|
26954
27732
|
}
|
|
27733
|
+
/**
|
|
27734
|
+
* Commands are emitted into this same skills tree as `<slug>/SKILL.md`
|
|
27735
|
+
* (see `DevinCommand`), so a directory matching a current rulesync command
|
|
27736
|
+
* slug is owned by the commands feature: it must not be imported as a
|
|
27737
|
+
* skill nor deleted as an orphan skill.
|
|
27738
|
+
*/
|
|
27739
|
+
static async isDirOwned({ dirName, inputRoot }) {
|
|
27740
|
+
return !await rulesyncCommandSlugExists({
|
|
27741
|
+
inputRoot,
|
|
27742
|
+
dirName
|
|
27743
|
+
});
|
|
27744
|
+
}
|
|
26955
27745
|
static async fromDir(params) {
|
|
26956
27746
|
const loaded = await this.loadSkillDirContent({
|
|
26957
27747
|
...params,
|
|
@@ -26960,7 +27750,7 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
26960
27750
|
const result = DevinSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
26961
27751
|
if (!result.success) {
|
|
26962
27752
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
26963
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27753
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
26964
27754
|
}
|
|
26965
27755
|
return new DevinSkill({
|
|
26966
27756
|
outputRoot: loaded.outputRoot,
|
|
@@ -27012,7 +27802,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27012
27802
|
relativeDirPath,
|
|
27013
27803
|
dirName,
|
|
27014
27804
|
mainFile: {
|
|
27015
|
-
name: SKILL_FILE_NAME,
|
|
27805
|
+
name: SKILL_FILE_NAME$1,
|
|
27016
27806
|
body,
|
|
27017
27807
|
frontmatter: { ...frontmatter }
|
|
27018
27808
|
},
|
|
@@ -27036,7 +27826,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27036
27826
|
validate() {
|
|
27037
27827
|
if (this.mainFile === void 0) return {
|
|
27038
27828
|
success: false,
|
|
27039
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27829
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27040
27830
|
};
|
|
27041
27831
|
const result = FactorydroidSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27042
27832
|
if (!result.success) return {
|
|
@@ -27111,7 +27901,7 @@ var FactorydroidSkill = class FactorydroidSkill extends ToolSkill {
|
|
|
27111
27901
|
const result = FactorydroidSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27112
27902
|
if (!result.success) {
|
|
27113
27903
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27114
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
27904
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27115
27905
|
}
|
|
27116
27906
|
return new FactorydroidSkill({
|
|
27117
27907
|
outputRoot: loaded.outputRoot,
|
|
@@ -27158,7 +27948,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27158
27948
|
relativeDirPath,
|
|
27159
27949
|
dirName,
|
|
27160
27950
|
mainFile: {
|
|
27161
|
-
name: SKILL_FILE_NAME,
|
|
27951
|
+
name: SKILL_FILE_NAME$1,
|
|
27162
27952
|
body,
|
|
27163
27953
|
frontmatter: { ...frontmatter }
|
|
27164
27954
|
},
|
|
@@ -27183,7 +27973,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27183
27973
|
validate() {
|
|
27184
27974
|
if (!this.mainFile) return {
|
|
27185
27975
|
success: false,
|
|
27186
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
27976
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27187
27977
|
};
|
|
27188
27978
|
const result = GooseSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27189
27979
|
if (!result.success) return {
|
|
@@ -27243,7 +28033,7 @@ var GooseSkill = class GooseSkill extends ToolSkill {
|
|
|
27243
28033
|
const result = GooseSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27244
28034
|
if (!result.success) {
|
|
27245
28035
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27246
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28036
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27247
28037
|
}
|
|
27248
28038
|
return new GooseSkill({
|
|
27249
28039
|
outputRoot: loaded.outputRoot,
|
|
@@ -27296,7 +28086,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27296
28086
|
relativeDirPath,
|
|
27297
28087
|
dirName,
|
|
27298
28088
|
mainFile: {
|
|
27299
|
-
name: SKILL_FILE_NAME,
|
|
28089
|
+
name: SKILL_FILE_NAME$1,
|
|
27300
28090
|
body,
|
|
27301
28091
|
frontmatter: { ...frontmatter }
|
|
27302
28092
|
},
|
|
@@ -27320,7 +28110,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27320
28110
|
validate() {
|
|
27321
28111
|
if (this.mainFile === void 0) return {
|
|
27322
28112
|
success: false,
|
|
27323
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28113
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27324
28114
|
};
|
|
27325
28115
|
const result = GrokcliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27326
28116
|
if (!result.success) return {
|
|
@@ -27380,7 +28170,7 @@ var GrokcliSkill = class GrokcliSkill extends ToolSkill {
|
|
|
27380
28170
|
const result = GrokcliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27381
28171
|
if (!result.success) {
|
|
27382
28172
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27383
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28173
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27384
28174
|
}
|
|
27385
28175
|
return new GrokcliSkill({
|
|
27386
28176
|
outputRoot: loaded.outputRoot,
|
|
@@ -27415,6 +28205,18 @@ var HermesagentSkill = class extends AgentsSkillsSkill {
|
|
|
27415
28205
|
static getSettablePaths() {
|
|
27416
28206
|
return { relativeDirPath: HERMESAGENT_SKILLS_DIR_PATH };
|
|
27417
28207
|
}
|
|
28208
|
+
/**
|
|
28209
|
+
* Commands are emitted into this same skills tree as `<slug>/SKILL.md`
|
|
28210
|
+
* (see `HermesagentCommand`), so a directory matching a current rulesync
|
|
28211
|
+
* command slug is owned by the commands feature: it must not be imported
|
|
28212
|
+
* as a skill nor deleted as an orphan skill.
|
|
28213
|
+
*/
|
|
28214
|
+
static async isDirOwned({ dirName, inputRoot }) {
|
|
28215
|
+
return !await rulesyncCommandSlugExists({
|
|
28216
|
+
inputRoot,
|
|
28217
|
+
dirName
|
|
28218
|
+
});
|
|
28219
|
+
}
|
|
27418
28220
|
constructor(params) {
|
|
27419
28221
|
super({
|
|
27420
28222
|
...params,
|
|
@@ -27439,7 +28241,7 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27439
28241
|
relativeDirPath,
|
|
27440
28242
|
dirName,
|
|
27441
28243
|
mainFile: {
|
|
27442
|
-
name: SKILL_FILE_NAME,
|
|
28244
|
+
name: SKILL_FILE_NAME$1,
|
|
27443
28245
|
body,
|
|
27444
28246
|
frontmatter: { ...frontmatter }
|
|
27445
28247
|
},
|
|
@@ -27463,7 +28265,7 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27463
28265
|
validate() {
|
|
27464
28266
|
if (!this.mainFile) return {
|
|
27465
28267
|
success: false,
|
|
27466
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28268
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27467
28269
|
};
|
|
27468
28270
|
const result = JunieSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27469
28271
|
if (!result.success) return {
|
|
@@ -27527,10 +28329,10 @@ var JunieSkill = class JunieSkill extends ToolSkill {
|
|
|
27527
28329
|
const result = JunieSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27528
28330
|
if (!result.success) {
|
|
27529
28331
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27530
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28332
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27531
28333
|
}
|
|
27532
28334
|
if (result.data.name !== loaded.dirName) {
|
|
27533
|
-
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
28335
|
+
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
27534
28336
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
27535
28337
|
}
|
|
27536
28338
|
return new JunieSkill({
|
|
@@ -27578,7 +28380,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27578
28380
|
relativeDirPath,
|
|
27579
28381
|
dirName,
|
|
27580
28382
|
mainFile: {
|
|
27581
|
-
name: SKILL_FILE_NAME,
|
|
28383
|
+
name: SKILL_FILE_NAME$1,
|
|
27582
28384
|
body,
|
|
27583
28385
|
frontmatter: { ...frontmatter }
|
|
27584
28386
|
},
|
|
@@ -27602,7 +28404,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27602
28404
|
validate() {
|
|
27603
28405
|
if (this.mainFile === void 0) return {
|
|
27604
28406
|
success: false,
|
|
27605
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28407
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27606
28408
|
};
|
|
27607
28409
|
const result = KiloSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27608
28410
|
if (!result.success) return {
|
|
@@ -27674,7 +28476,7 @@ var KiloSkill = class KiloSkill extends ToolSkill {
|
|
|
27674
28476
|
const result = KiloSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27675
28477
|
if (!result.success) {
|
|
27676
28478
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27677
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28479
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27678
28480
|
}
|
|
27679
28481
|
return new KiloSkill({
|
|
27680
28482
|
outputRoot: loaded.outputRoot,
|
|
@@ -27720,7 +28522,7 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27720
28522
|
relativeDirPath,
|
|
27721
28523
|
dirName,
|
|
27722
28524
|
mainFile: {
|
|
27723
|
-
name: SKILL_FILE_NAME,
|
|
28525
|
+
name: SKILL_FILE_NAME$1,
|
|
27724
28526
|
body,
|
|
27725
28527
|
frontmatter: { ...frontmatter }
|
|
27726
28528
|
},
|
|
@@ -27744,7 +28546,7 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27744
28546
|
validate() {
|
|
27745
28547
|
if (!this.mainFile) return {
|
|
27746
28548
|
success: false,
|
|
27747
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28549
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27748
28550
|
};
|
|
27749
28551
|
const result = KiroSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27750
28552
|
if (!result.success) return {
|
|
@@ -27808,10 +28610,10 @@ var KiroSkill = class KiroSkill extends ToolSkill {
|
|
|
27808
28610
|
const result = KiroSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
27809
28611
|
if (!result.success) {
|
|
27810
28612
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
27811
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28613
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
27812
28614
|
}
|
|
27813
28615
|
if (result.data.name !== loaded.dirName) {
|
|
27814
|
-
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
28616
|
+
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
27815
28617
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
27816
28618
|
}
|
|
27817
28619
|
return new KiroSkill({
|
|
@@ -27894,7 +28696,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
27894
28696
|
relativeDirPath,
|
|
27895
28697
|
dirName,
|
|
27896
28698
|
mainFile: {
|
|
27897
|
-
name: SKILL_FILE_NAME,
|
|
28699
|
+
name: SKILL_FILE_NAME$1,
|
|
27898
28700
|
body,
|
|
27899
28701
|
frontmatter: { ...frontmatter }
|
|
27900
28702
|
},
|
|
@@ -27921,7 +28723,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
27921
28723
|
validate() {
|
|
27922
28724
|
if (this.mainFile === void 0) return {
|
|
27923
28725
|
success: false,
|
|
27924
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28726
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
27925
28727
|
};
|
|
27926
28728
|
const result = OpenCodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
27927
28729
|
if (!result.success) return {
|
|
@@ -28000,7 +28802,7 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
|
|
|
28000
28802
|
const result = OpenCodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28001
28803
|
if (!result.success) {
|
|
28002
28804
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28003
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28805
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28004
28806
|
}
|
|
28005
28807
|
return new OpenCodeSkill({
|
|
28006
28808
|
outputRoot: loaded.outputRoot,
|
|
@@ -28061,7 +28863,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28061
28863
|
relativeDirPath: resolvedDirPath,
|
|
28062
28864
|
dirName,
|
|
28063
28865
|
mainFile: {
|
|
28064
|
-
name: SKILL_FILE_NAME,
|
|
28866
|
+
name: SKILL_FILE_NAME$1,
|
|
28065
28867
|
body,
|
|
28066
28868
|
frontmatter: { ...frontmatter }
|
|
28067
28869
|
},
|
|
@@ -28086,7 +28888,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28086
28888
|
validate() {
|
|
28087
28889
|
if (!this.mainFile) return {
|
|
28088
28890
|
success: false,
|
|
28089
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
28891
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28090
28892
|
};
|
|
28091
28893
|
const result = PiSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28092
28894
|
if (!result.success) return {
|
|
@@ -28161,7 +28963,7 @@ var PiSkill = class PiSkill extends ToolSkill {
|
|
|
28161
28963
|
const result = PiSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28162
28964
|
if (!result.success) {
|
|
28163
28965
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28164
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
28966
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28165
28967
|
}
|
|
28166
28968
|
return new PiSkill({
|
|
28167
28969
|
outputRoot: loaded.outputRoot,
|
|
@@ -28214,7 +29016,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28214
29016
|
relativeDirPath,
|
|
28215
29017
|
dirName,
|
|
28216
29018
|
mainFile: {
|
|
28217
|
-
name: SKILL_FILE_NAME,
|
|
29019
|
+
name: SKILL_FILE_NAME$1,
|
|
28218
29020
|
body,
|
|
28219
29021
|
frontmatter: { ...frontmatter }
|
|
28220
29022
|
},
|
|
@@ -28238,7 +29040,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28238
29040
|
validate() {
|
|
28239
29041
|
if (this.mainFile === void 0) return {
|
|
28240
29042
|
success: false,
|
|
28241
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29043
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28242
29044
|
};
|
|
28243
29045
|
const result = QwencodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28244
29046
|
if (!result.success) return {
|
|
@@ -28318,7 +29120,7 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
|
|
|
28318
29120
|
const result = QwencodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28319
29121
|
if (!result.success) {
|
|
28320
29122
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28321
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29123
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28322
29124
|
}
|
|
28323
29125
|
return new QwencodeSkill({
|
|
28324
29126
|
outputRoot: loaded.outputRoot,
|
|
@@ -28368,7 +29170,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28368
29170
|
relativeDirPath,
|
|
28369
29171
|
dirName,
|
|
28370
29172
|
mainFile: {
|
|
28371
|
-
name: SKILL_FILE_NAME,
|
|
29173
|
+
name: SKILL_FILE_NAME$1,
|
|
28372
29174
|
body,
|
|
28373
29175
|
frontmatter: { ...frontmatter }
|
|
28374
29176
|
},
|
|
@@ -28392,7 +29194,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28392
29194
|
validate() {
|
|
28393
29195
|
if (this.mainFile === void 0) return {
|
|
28394
29196
|
success: false,
|
|
28395
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29197
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28396
29198
|
};
|
|
28397
29199
|
const result = ReasonixSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28398
29200
|
if (!result.success) return {
|
|
@@ -28452,7 +29254,7 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28452
29254
|
const result = ReasonixSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28453
29255
|
if (!result.success) {
|
|
28454
29256
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28455
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29257
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28456
29258
|
}
|
|
28457
29259
|
return new ReasonixSkill({
|
|
28458
29260
|
outputRoot: loaded.outputRoot,
|
|
@@ -28465,6 +29267,24 @@ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
|
|
|
28465
29267
|
global: loaded.global
|
|
28466
29268
|
});
|
|
28467
29269
|
}
|
|
29270
|
+
/**
|
|
29271
|
+
* Whether the skill directory belongs to the skills feature.
|
|
29272
|
+
*
|
|
29273
|
+
* `.reasonix/skills/` is shared with the subagents feature: a directory whose
|
|
29274
|
+
* SKILL.md declares `runAs: subagent` is a subagent profile, not a regular
|
|
29275
|
+
* skill, so it must be neither imported as a skill nor deleted as an orphan
|
|
29276
|
+
* skill. Directories without a readable/parsable SKILL.md keep the default
|
|
29277
|
+
* skills-feature ownership, matching the previous behavior for such dirs.
|
|
29278
|
+
*/
|
|
29279
|
+
static async isDirOwned({ outputRoot, relativeDirPath, dirName }) {
|
|
29280
|
+
const skillFilePath = join(outputRoot, relativeDirPath, dirName, SKILL_FILE_NAME$1);
|
|
29281
|
+
try {
|
|
29282
|
+
const { frontmatter } = parseFrontmatter(await readFileContent(skillFilePath), skillFilePath);
|
|
29283
|
+
return frontmatter["runAs"] !== REASONIX_SUBAGENT_RUN_AS;
|
|
29284
|
+
} catch {
|
|
29285
|
+
return true;
|
|
29286
|
+
}
|
|
29287
|
+
}
|
|
28468
29288
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, dirName, global = false }) {
|
|
28469
29289
|
return new ReasonixSkill({
|
|
28470
29290
|
outputRoot,
|
|
@@ -28507,7 +29327,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28507
29327
|
relativeDirPath,
|
|
28508
29328
|
dirName,
|
|
28509
29329
|
mainFile: {
|
|
28510
|
-
name: SKILL_FILE_NAME,
|
|
29330
|
+
name: SKILL_FILE_NAME$1,
|
|
28511
29331
|
body,
|
|
28512
29332
|
frontmatter: { ...frontmatter }
|
|
28513
29333
|
},
|
|
@@ -28531,7 +29351,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28531
29351
|
validate() {
|
|
28532
29352
|
if (!this.mainFile) return {
|
|
28533
29353
|
success: false,
|
|
28534
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29354
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28535
29355
|
};
|
|
28536
29356
|
const result = ReplitSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28537
29357
|
if (!result.success) return {
|
|
@@ -28599,7 +29419,7 @@ var ReplitSkill = class ReplitSkill extends ToolSkill {
|
|
|
28599
29419
|
const result = ReplitSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28600
29420
|
if (!result.success) {
|
|
28601
29421
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28602
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29422
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28603
29423
|
}
|
|
28604
29424
|
return new ReplitSkill({
|
|
28605
29425
|
outputRoot: loaded.outputRoot,
|
|
@@ -28646,7 +29466,7 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28646
29466
|
relativeDirPath,
|
|
28647
29467
|
dirName,
|
|
28648
29468
|
mainFile: {
|
|
28649
|
-
name: SKILL_FILE_NAME,
|
|
29469
|
+
name: SKILL_FILE_NAME$1,
|
|
28650
29470
|
body,
|
|
28651
29471
|
frontmatter: { ...frontmatter }
|
|
28652
29472
|
},
|
|
@@ -28670,7 +29490,7 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28670
29490
|
validate() {
|
|
28671
29491
|
if (!this.mainFile) return {
|
|
28672
29492
|
success: false,
|
|
28673
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29493
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28674
29494
|
};
|
|
28675
29495
|
const result = RooSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28676
29496
|
if (!result.success) return {
|
|
@@ -28734,10 +29554,10 @@ var RooSkill = class RooSkill extends ToolSkill {
|
|
|
28734
29554
|
const result = RooSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
28735
29555
|
if (!result.success) {
|
|
28736
29556
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
28737
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29557
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
28738
29558
|
}
|
|
28739
29559
|
if (result.data.name !== loaded.dirName) {
|
|
28740
|
-
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME);
|
|
29560
|
+
const skillFilePath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName, SKILL_FILE_NAME$1);
|
|
28741
29561
|
throw new Error(`Frontmatter name (${result.data.name}) must match directory name (${loaded.dirName}) in ${skillFilePath}`);
|
|
28742
29562
|
}
|
|
28743
29563
|
return new RooSkill({
|
|
@@ -28954,7 +29774,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
28954
29774
|
relativeDirPath,
|
|
28955
29775
|
dirName,
|
|
28956
29776
|
mainFile: {
|
|
28957
|
-
name: SKILL_FILE_NAME,
|
|
29777
|
+
name: SKILL_FILE_NAME$1,
|
|
28958
29778
|
body,
|
|
28959
29779
|
frontmatter: { ...frontmatter }
|
|
28960
29780
|
},
|
|
@@ -28981,7 +29801,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
28981
29801
|
validate() {
|
|
28982
29802
|
if (!this.mainFile) return {
|
|
28983
29803
|
success: false,
|
|
28984
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29804
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
28985
29805
|
};
|
|
28986
29806
|
const result = VibeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
28987
29807
|
if (!result.success) return {
|
|
@@ -29045,7 +29865,7 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
29045
29865
|
const result = VibeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29046
29866
|
if (!result.success) {
|
|
29047
29867
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29048
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
29868
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29049
29869
|
}
|
|
29050
29870
|
return new VibeSkill({
|
|
29051
29871
|
outputRoot: loaded.outputRoot,
|
|
@@ -29101,7 +29921,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29101
29921
|
relativeDirPath,
|
|
29102
29922
|
dirName,
|
|
29103
29923
|
mainFile: {
|
|
29104
|
-
name: SKILL_FILE_NAME,
|
|
29924
|
+
name: SKILL_FILE_NAME$1,
|
|
29105
29925
|
body,
|
|
29106
29926
|
frontmatter: { ...frontmatter }
|
|
29107
29927
|
},
|
|
@@ -29125,7 +29945,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29125
29945
|
validate() {
|
|
29126
29946
|
if (this.mainFile === void 0) return {
|
|
29127
29947
|
success: false,
|
|
29128
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
29948
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
29129
29949
|
};
|
|
29130
29950
|
const result = WarpSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
29131
29951
|
if (!result.success) return {
|
|
@@ -29185,7 +30005,7 @@ var WarpSkill = class WarpSkill extends ToolSkill {
|
|
|
29185
30005
|
const result = WarpSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29186
30006
|
if (!result.success) {
|
|
29187
30007
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29188
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
30008
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29189
30009
|
}
|
|
29190
30010
|
return new WarpSkill({
|
|
29191
30011
|
outputRoot: loaded.outputRoot,
|
|
@@ -29233,7 +30053,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29233
30053
|
relativeDirPath,
|
|
29234
30054
|
dirName,
|
|
29235
30055
|
mainFile: {
|
|
29236
|
-
name: SKILL_FILE_NAME,
|
|
30056
|
+
name: SKILL_FILE_NAME$1,
|
|
29237
30057
|
body,
|
|
29238
30058
|
frontmatter: { ...frontmatter }
|
|
29239
30059
|
},
|
|
@@ -29257,7 +30077,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29257
30077
|
validate() {
|
|
29258
30078
|
if (!this.mainFile) return {
|
|
29259
30079
|
success: false,
|
|
29260
|
-
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
30080
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME$1} file does not exist`)
|
|
29261
30081
|
};
|
|
29262
30082
|
const result = ZedSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
29263
30083
|
if (!result.success) return {
|
|
@@ -29326,7 +30146,7 @@ var ZedSkill = class ZedSkill extends ToolSkill {
|
|
|
29326
30146
|
const result = ZedSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
29327
30147
|
if (!result.success) {
|
|
29328
30148
|
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
29329
|
-
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
30149
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME$1)}: ${formatError(result.error)}`);
|
|
29330
30150
|
}
|
|
29331
30151
|
return new ZedSkill({
|
|
29332
30152
|
outputRoot: loaded.outputRoot,
|
|
@@ -29763,6 +30583,12 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
29763
30583
|
for (const dirPath of dirPaths) {
|
|
29764
30584
|
const dirName = basename(dirPath);
|
|
29765
30585
|
if (seenDirNames.has(dirName)) continue;
|
|
30586
|
+
if (factory.class.isDirOwned && !await factory.class.isDirOwned({
|
|
30587
|
+
outputRoot: this.outputRoot,
|
|
30588
|
+
relativeDirPath: root,
|
|
30589
|
+
dirName,
|
|
30590
|
+
inputRoot: this.inputRoot
|
|
30591
|
+
})) continue;
|
|
29766
30592
|
seenDirNames.add(dirName);
|
|
29767
30593
|
loadEntries.push({
|
|
29768
30594
|
root,
|
|
@@ -29789,6 +30615,12 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
29789
30615
|
const dirPaths = await findFilesByGlobs(join(skillsDirPath, "*"), { type: "dir" });
|
|
29790
30616
|
for (const dirPath of dirPaths) {
|
|
29791
30617
|
const dirName = basename(dirPath);
|
|
30618
|
+
if (factory.class.isDirOwned && !await factory.class.isDirOwned({
|
|
30619
|
+
outputRoot: this.outputRoot,
|
|
30620
|
+
relativeDirPath: root,
|
|
30621
|
+
dirName,
|
|
30622
|
+
inputRoot: this.inputRoot
|
|
30623
|
+
})) continue;
|
|
29792
30624
|
const toolSkill = factory.class.forDeletion({
|
|
29793
30625
|
outputRoot: this.outputRoot,
|
|
29794
30626
|
relativeDirPath: root,
|
|
@@ -33088,6 +33920,188 @@ var OpenCodeSubagent = class OpenCodeSubagent extends OpenCodeStyleSubagent {
|
|
|
33088
33920
|
}
|
|
33089
33921
|
};
|
|
33090
33922
|
//#endregion
|
|
33923
|
+
//#region src/features/subagents/reasonix-subagent.ts
|
|
33924
|
+
const ReasonixSubagentFrontmatterSchema = z.looseObject({
|
|
33925
|
+
name: z.string(),
|
|
33926
|
+
description: z.optional(z.string()),
|
|
33927
|
+
invocation: z.optional(z.string()),
|
|
33928
|
+
runAs: z.optional(z.string()),
|
|
33929
|
+
model: z.optional(z.string()),
|
|
33930
|
+
effort: z.optional(z.string()),
|
|
33931
|
+
"allowed-tools": z.optional(z.array(z.string())),
|
|
33932
|
+
color: z.optional(z.string())
|
|
33933
|
+
});
|
|
33934
|
+
/**
|
|
33935
|
+
* Represents a DeepSeek-Reasonix subagent profile.
|
|
33936
|
+
*
|
|
33937
|
+
* Reasonix discovers subagents as directory-layout Skills (`<name>/SKILL.md`)
|
|
33938
|
+
* under `.reasonix/skills/` (project) and `~/.reasonix/skills/` (global); the
|
|
33939
|
+
* global scope is served by the processor supplying the home directory as
|
|
33940
|
+
* outputRoot, so the relative directory path is identical for both scopes. A
|
|
33941
|
+
* subagent is a Skill whose frontmatter declares `invocation: manual` and
|
|
33942
|
+
* `runAs: subagent`.
|
|
33943
|
+
*
|
|
33944
|
+
* @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/SUBAGENT_PROFILES.md
|
|
33945
|
+
*/
|
|
33946
|
+
var ReasonixSubagent = class ReasonixSubagent extends ToolSubagent {
|
|
33947
|
+
frontmatter;
|
|
33948
|
+
body;
|
|
33949
|
+
constructor({ frontmatter, body, fileContent, ...rest }) {
|
|
33950
|
+
if (rest.validate !== false) {
|
|
33951
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
33952
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${join(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
33953
|
+
}
|
|
33954
|
+
super({
|
|
33955
|
+
...rest,
|
|
33956
|
+
fileContent: fileContent ?? stringifyFrontmatter(body, frontmatter)
|
|
33957
|
+
});
|
|
33958
|
+
this.frontmatter = frontmatter;
|
|
33959
|
+
this.body = body;
|
|
33960
|
+
}
|
|
33961
|
+
static getSettablePaths({ global: _global = false } = {}) {
|
|
33962
|
+
return { relativeDirPath: REASONIX_SUBAGENTS_DIR_PATH };
|
|
33963
|
+
}
|
|
33964
|
+
getFrontmatter() {
|
|
33965
|
+
return this.frontmatter;
|
|
33966
|
+
}
|
|
33967
|
+
getBody() {
|
|
33968
|
+
return this.body;
|
|
33969
|
+
}
|
|
33970
|
+
toRulesyncSubagent() {
|
|
33971
|
+
const { name, description, invocation: _invocation, runAs: _runAs, ...restFields } = this.frontmatter;
|
|
33972
|
+
const reasonixSection = { ...restFields };
|
|
33973
|
+
const rulesyncFrontmatter = {
|
|
33974
|
+
targets: ["*"],
|
|
33975
|
+
name,
|
|
33976
|
+
description,
|
|
33977
|
+
...Object.keys(reasonixSection).length > 0 && { reasonix: reasonixSection }
|
|
33978
|
+
};
|
|
33979
|
+
return new RulesyncSubagent({
|
|
33980
|
+
outputRoot: this.getOutputRoot(),
|
|
33981
|
+
frontmatter: rulesyncFrontmatter,
|
|
33982
|
+
body: this.body,
|
|
33983
|
+
relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
|
|
33984
|
+
relativeFilePath: `${this.getSubagentName()}.md`,
|
|
33985
|
+
validate: true
|
|
33986
|
+
});
|
|
33987
|
+
}
|
|
33988
|
+
/**
|
|
33989
|
+
* Derive the subagent name from this instance's relative file path.
|
|
33990
|
+
*
|
|
33991
|
+
* The tool-side layout is `<name>/SKILL.md`, so the name is the parent
|
|
33992
|
+
* directory of the file. If the path is unexpectedly flat (e.g. a legacy
|
|
33993
|
+
* `<name>.md`), fall back to the basename without extension.
|
|
33994
|
+
*/
|
|
33995
|
+
getSubagentName() {
|
|
33996
|
+
const relativeFilePath = this.getRelativeFilePath();
|
|
33997
|
+
const dir = dirname(relativeFilePath);
|
|
33998
|
+
if (dir && dir !== ".") return basename(dir);
|
|
33999
|
+
return basename(relativeFilePath, extname(relativeFilePath));
|
|
34000
|
+
}
|
|
34001
|
+
static fromRulesyncSubagent({ outputRoot = process.cwd(), rulesyncSubagent, validate = true, global = false }) {
|
|
34002
|
+
const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
|
|
34003
|
+
const reasonixSection = this.filterToolSpecificSection(rulesyncFrontmatter.reasonix ?? {}, ["name", "description"]);
|
|
34004
|
+
const rawReasonixFrontmatter = {
|
|
34005
|
+
name: rulesyncFrontmatter.name,
|
|
34006
|
+
description: rulesyncFrontmatter.description,
|
|
34007
|
+
...reasonixSection,
|
|
34008
|
+
invocation: REASONIX_SUBAGENT_INVOCATION,
|
|
34009
|
+
runAs: REASONIX_SUBAGENT_RUN_AS
|
|
34010
|
+
};
|
|
34011
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(rawReasonixFrontmatter);
|
|
34012
|
+
if (!result.success) throw new Error(`Invalid reasonix subagent frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(result.error)}`);
|
|
34013
|
+
const reasonixFrontmatter = result.data;
|
|
34014
|
+
const body = rulesyncSubagent.getBody();
|
|
34015
|
+
const fileContent = stringifyFrontmatter(body, reasonixFrontmatter);
|
|
34016
|
+
const paths = this.getSettablePaths({ global });
|
|
34017
|
+
const subagentName = basename(rulesyncSubagent.getRelativeFilePath(), extname(rulesyncSubagent.getRelativeFilePath()));
|
|
34018
|
+
return new ReasonixSubagent({
|
|
34019
|
+
outputRoot,
|
|
34020
|
+
frontmatter: reasonixFrontmatter,
|
|
34021
|
+
body,
|
|
34022
|
+
relativeDirPath: paths.relativeDirPath,
|
|
34023
|
+
relativeFilePath: join(subagentName, SKILL_FILE_NAME$1),
|
|
34024
|
+
fileContent,
|
|
34025
|
+
validate,
|
|
34026
|
+
global
|
|
34027
|
+
});
|
|
34028
|
+
}
|
|
34029
|
+
validate() {
|
|
34030
|
+
if (!this.frontmatter) return {
|
|
34031
|
+
success: true,
|
|
34032
|
+
error: null
|
|
34033
|
+
};
|
|
34034
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(this.frontmatter);
|
|
34035
|
+
if (result.success) return {
|
|
34036
|
+
success: true,
|
|
34037
|
+
error: null
|
|
34038
|
+
};
|
|
34039
|
+
else return {
|
|
34040
|
+
success: false,
|
|
34041
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${join(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`)
|
|
34042
|
+
};
|
|
34043
|
+
}
|
|
34044
|
+
static isTargetedByRulesyncSubagent(rulesyncSubagent) {
|
|
34045
|
+
return this.isTargetedByRulesyncSubagentDefault({
|
|
34046
|
+
rulesyncSubagent,
|
|
34047
|
+
toolTarget: "reasonix"
|
|
34048
|
+
});
|
|
34049
|
+
}
|
|
34050
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
34051
|
+
const paths = this.getSettablePaths({ global });
|
|
34052
|
+
const filePath = join(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
34053
|
+
const fileContent = await readFileContent(filePath);
|
|
34054
|
+
const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
|
|
34055
|
+
const result = ReasonixSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
34056
|
+
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
34057
|
+
return new ReasonixSubagent({
|
|
34058
|
+
outputRoot,
|
|
34059
|
+
relativeDirPath: paths.relativeDirPath,
|
|
34060
|
+
relativeFilePath,
|
|
34061
|
+
frontmatter: result.data,
|
|
34062
|
+
body: content.trim(),
|
|
34063
|
+
fileContent,
|
|
34064
|
+
validate,
|
|
34065
|
+
global
|
|
34066
|
+
});
|
|
34067
|
+
}
|
|
34068
|
+
/**
|
|
34069
|
+
* Whether the SKILL.md at the given path is a subagent profile.
|
|
34070
|
+
*
|
|
34071
|
+
* `.reasonix/skills/` is shared with the skills feature: a regular skill and
|
|
34072
|
+
* a subagent profile differ only by their frontmatter markers. Only files
|
|
34073
|
+
* carrying `runAs: subagent` belong to this feature, so regular skills are
|
|
34074
|
+
* neither imported as subagents nor deleted as orphans by the subagents
|
|
34075
|
+
* feature. `runAs` alone is checked (not `invocation`) because it is the
|
|
34076
|
+
* marker that switches the execution mode; generation always emits both.
|
|
34077
|
+
* Unreadable or unparsable files are treated as not owned, erring on the
|
|
34078
|
+
* side of leaving foreign files untouched.
|
|
34079
|
+
*/
|
|
34080
|
+
static async isFileOwned({ outputRoot, relativeDirPath, relativeFilePath }) {
|
|
34081
|
+
const filePath = join(outputRoot, relativeDirPath, relativeFilePath);
|
|
34082
|
+
try {
|
|
34083
|
+
const { frontmatter } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
34084
|
+
return frontmatter["runAs"] === REASONIX_SUBAGENT_RUN_AS;
|
|
34085
|
+
} catch {
|
|
34086
|
+
return false;
|
|
34087
|
+
}
|
|
34088
|
+
}
|
|
34089
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
34090
|
+
return new ReasonixSubagent({
|
|
34091
|
+
outputRoot,
|
|
34092
|
+
relativeDirPath,
|
|
34093
|
+
relativeFilePath,
|
|
34094
|
+
frontmatter: {
|
|
34095
|
+
name: "",
|
|
34096
|
+
description: ""
|
|
34097
|
+
},
|
|
34098
|
+
body: "",
|
|
34099
|
+
fileContent: "",
|
|
34100
|
+
validate: false
|
|
34101
|
+
});
|
|
34102
|
+
}
|
|
34103
|
+
};
|
|
34104
|
+
//#endregion
|
|
33091
34105
|
//#region src/features/subagents/roo-subagent.ts
|
|
33092
34106
|
/**
|
|
33093
34107
|
* Default tool groups assigned to a generated mode when the rulesync source
|
|
@@ -33722,6 +34736,14 @@ const toolSubagentFactories = /* @__PURE__ */ new Map([
|
|
|
33722
34736
|
filePattern: "*.md"
|
|
33723
34737
|
}
|
|
33724
34738
|
}],
|
|
34739
|
+
["reasonix", {
|
|
34740
|
+
class: ReasonixSubagent,
|
|
34741
|
+
meta: {
|
|
34742
|
+
supportsSimulated: false,
|
|
34743
|
+
supportsGlobal: true,
|
|
34744
|
+
filePattern: join("*", "SKILL.md")
|
|
34745
|
+
}
|
|
34746
|
+
}],
|
|
33725
34747
|
["roo", {
|
|
33726
34748
|
class: RooSubagent,
|
|
33727
34749
|
meta: {
|
|
@@ -33874,8 +34896,17 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
33874
34896
|
const baseDir = join(this.outputRoot, dirPath);
|
|
33875
34897
|
const subagentFilePaths = await findFilesByGlobs(join(baseDir, factory.meta.filePattern));
|
|
33876
34898
|
const toRelativeFilePath = (path) => relative(baseDir, path);
|
|
34899
|
+
let ownedFilePaths = subagentFilePaths;
|
|
34900
|
+
if (factory.class.isFileOwned) {
|
|
34901
|
+
const ownership = await Promise.all(subagentFilePaths.map((path) => factory.class.isFileOwned({
|
|
34902
|
+
outputRoot: this.outputRoot,
|
|
34903
|
+
relativeDirPath: dirPath,
|
|
34904
|
+
relativeFilePath: toRelativeFilePath(path)
|
|
34905
|
+
})));
|
|
34906
|
+
ownedFilePaths = subagentFilePaths.filter((_, index) => ownership[index]);
|
|
34907
|
+
}
|
|
33877
34908
|
if (forDeletion) {
|
|
33878
|
-
toolSubagents.push(...
|
|
34909
|
+
toolSubagents.push(...ownedFilePaths.map((path) => factory.class.forDeletion({
|
|
33879
34910
|
outputRoot: this.outputRoot,
|
|
33880
34911
|
relativeDirPath: dirPath,
|
|
33881
34912
|
relativeFilePath: toRelativeFilePath(path),
|
|
@@ -33883,7 +34914,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
33883
34914
|
})).filter((subagent) => subagent.isDeletable()));
|
|
33884
34915
|
continue;
|
|
33885
34916
|
}
|
|
33886
|
-
const loaded = await Promise.all(
|
|
34917
|
+
const loaded = await Promise.all(ownedFilePaths.map((path) => factory.class.fromFile({
|
|
33887
34918
|
outputRoot: this.outputRoot,
|
|
33888
34919
|
relativeDirPath: dirPath,
|
|
33889
34920
|
relativeFilePath: toRelativeFilePath(path),
|
|
@@ -33995,6 +35026,7 @@ const RulesyncRuleFrontmatterSchema = z.object({
|
|
|
33995
35026
|
name: z.optional(z.string()),
|
|
33996
35027
|
description: z.optional(z.string())
|
|
33997
35028
|
})),
|
|
35029
|
+
pi: z.optional(z.looseObject({ systemPrompt: z.optional(z.enum(["append"])) })),
|
|
33998
35030
|
takt: z.optional(z.looseObject({
|
|
33999
35031
|
name: z.optional(z.string()),
|
|
34000
35032
|
extends: z.optional(z.string()),
|
|
@@ -34158,6 +35190,16 @@ var ToolRule = class extends ToolFile {
|
|
|
34158
35190
|
isRoot() {
|
|
34159
35191
|
return this.root;
|
|
34160
35192
|
}
|
|
35193
|
+
/**
|
|
35194
|
+
* Whether this rule must be left out of the root rule's reference/MCP
|
|
35195
|
+
* instruction listings even though it is a non-root survivor. Used by files
|
|
35196
|
+
* the tool loads through its own mechanism (e.g. Pi's `APPEND_SYSTEM.md`,
|
|
35197
|
+
* which Pi appends to the system prompt itself — referencing it from
|
|
35198
|
+
* `AGENTS.md` would double-load the content).
|
|
35199
|
+
*/
|
|
35200
|
+
isExcludedFromRootReferences() {
|
|
35201
|
+
return false;
|
|
35202
|
+
}
|
|
34161
35203
|
getDescription() {
|
|
34162
35204
|
return this.description;
|
|
34163
35205
|
}
|
|
@@ -36504,6 +37546,15 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
36504
37546
|
* is `undefined`). This mirrors the grokcli, warp, and deepagents targets.
|
|
36505
37547
|
*
|
|
36506
37548
|
* Goose uses plain markdown files (.goosehints) without frontmatter.
|
|
37549
|
+
*
|
|
37550
|
+
* Global scope emits only `~/.config/goose/.goosehints`. Goose v1.41.0 (PR
|
|
37551
|
+
* block/goose#9736) additionally loads the vendor-neutral
|
|
37552
|
+
* `~/.agents/AGENTS.md` alongside the config-dir hints, but rulesync
|
|
37553
|
+
* deliberately does not emit that shared path from the goose target: the
|
|
37554
|
+
* config-dir hints remain fully loaded (no capability loss), and the
|
|
37555
|
+
* cross-tool `~/.agents/AGENTS.md` is already written by targets that own it
|
|
37556
|
+
* (e.g. cline in global mode) — a second writer would need cross-target
|
|
37557
|
+
* shared-file coordination for zero gain (decision recorded in issue #2207).
|
|
36507
37558
|
*/
|
|
36508
37559
|
var GooseRule = class GooseRule extends ToolRule {
|
|
36509
37560
|
static getSettablePaths({ global } = {}) {
|
|
@@ -36705,14 +37756,21 @@ var HermesagentRule = class HermesagentRule extends ToolRule {
|
|
|
36705
37756
|
/**
|
|
36706
37757
|
* Rule generator for JetBrains Junie AI coding agent
|
|
36707
37758
|
*
|
|
36708
|
-
* Generates `.junie/AGENTS.md` files based on rulesync rule content.
|
|
36709
|
-
*
|
|
36710
|
-
*
|
|
36711
|
-
*
|
|
36712
|
-
*
|
|
36713
|
-
*
|
|
36714
|
-
*
|
|
36715
|
-
*
|
|
37759
|
+
* Generates `.junie/AGENTS.md` files based on rulesync rule content. Junie CLI
|
|
37760
|
+
* resolves project guidelines **first-match-wins**: `.junie/AGENTS.md` → root
|
|
37761
|
+
* `AGENTS.md` → legacy `.junie/guidelines.md` / `.junie/guidelines/`. Only the
|
|
37762
|
+
* first match is loaded, it documents no `@`-reference or file-inclusion
|
|
37763
|
+
* mechanism, and no `.junie/memories/` read path exists — so non-root rules
|
|
37764
|
+
* are folded into the single root `.junie/AGENTS.md` by the RulesProcessor
|
|
37765
|
+
* (`nonRoot` is `undefined`, mirroring the grokcli / warp / deepagents
|
|
37766
|
+
* targets; decision recorded in issue #2211). The legacy
|
|
37767
|
+
* `.junie/guidelines.md` is still accepted as an import fallback, but
|
|
37768
|
+
* generation always targets `.junie/AGENTS.md`. Junie uses plain markdown
|
|
37769
|
+
* without frontmatter requirements.
|
|
37770
|
+
*
|
|
37771
|
+
* Global (user) scope writes a single `~/.junie/AGENTS.md` file. Junie merges
|
|
37772
|
+
* these user-scope guidelines with the project guidelines (both are included
|
|
37773
|
+
* and marked clearly).
|
|
36716
37774
|
*
|
|
36717
37775
|
* @see https://junie.jetbrains.com/docs/junie-ide-plugin.html
|
|
36718
37776
|
* @see https://junie.jetbrains.com/docs/guidelines-and-memory.html
|
|
@@ -36731,15 +37789,12 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36731
37789
|
alternativeRoots: [{
|
|
36732
37790
|
relativeDirPath: buildToolPath(JUNIE_DIR, ".", excludeToolDir),
|
|
36733
37791
|
relativeFilePath: JUNIE_LEGACY_RULE_FILE_NAME
|
|
36734
|
-
}]
|
|
36735
|
-
nonRoot: { relativeDirPath: buildToolPath(JUNIE_DIR, "memories", excludeToolDir) }
|
|
37792
|
+
}]
|
|
36736
37793
|
};
|
|
36737
37794
|
}
|
|
36738
37795
|
/**
|
|
36739
37796
|
* Determines whether a given relative file path refers to a root guideline file.
|
|
36740
37797
|
* The preferred file is `AGENTS.md`; the legacy `guidelines.md` is still accepted.
|
|
36741
|
-
* Memory files live under `.junie/memories/` and are passed in as bare filenames
|
|
36742
|
-
* (e.g. `memo.md`), so a top-level `AGENTS.md`/`guidelines.md` is the root entry.
|
|
36743
37798
|
*/
|
|
36744
37799
|
static isRootRelativeFilePath(relativeFilePath) {
|
|
36745
37800
|
return relativeFilePath === "AGENTS.md" || relativeFilePath === "guidelines.md";
|
|
@@ -36758,10 +37813,7 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36758
37813
|
root: true
|
|
36759
37814
|
});
|
|
36760
37815
|
}
|
|
36761
|
-
const
|
|
36762
|
-
const settablePaths = this.getSettablePaths();
|
|
36763
|
-
if (!settablePaths.nonRoot) throw new Error("JunieRule project settable paths must include a nonRoot path");
|
|
36764
|
-
const relativeDirPath = isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath;
|
|
37816
|
+
const relativeDirPath = this.getSettablePaths().root.relativeDirPath;
|
|
36765
37817
|
const fileContent = await readFileContent(join(outputRoot, join(relativeDirPath, relativeFilePath)));
|
|
36766
37818
|
return new JunieRule({
|
|
36767
37819
|
outputRoot,
|
|
@@ -36769,7 +37821,7 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36769
37821
|
relativeFilePath,
|
|
36770
37822
|
fileContent,
|
|
36771
37823
|
validate,
|
|
36772
|
-
root:
|
|
37824
|
+
root: JunieRule.isRootRelativeFilePath(relativeFilePath)
|
|
36773
37825
|
});
|
|
36774
37826
|
}
|
|
36775
37827
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
@@ -36784,13 +37836,15 @@ var JunieRule = class JunieRule extends ToolRule {
|
|
|
36784
37836
|
rootPath: paths.root
|
|
36785
37837
|
}));
|
|
36786
37838
|
}
|
|
36787
|
-
|
|
37839
|
+
const { root } = this.getSettablePaths();
|
|
37840
|
+
return new JunieRule({
|
|
36788
37841
|
outputRoot,
|
|
36789
|
-
|
|
37842
|
+
relativeDirPath: root.relativeDirPath,
|
|
37843
|
+
relativeFilePath: root.relativeFilePath,
|
|
37844
|
+
fileContent: rulesyncRule.getBody(),
|
|
36790
37845
|
validate,
|
|
36791
|
-
|
|
36792
|
-
|
|
36793
|
-
}));
|
|
37846
|
+
root: rulesyncRule.getFrontmatter().root ?? false
|
|
37847
|
+
});
|
|
36794
37848
|
}
|
|
36795
37849
|
toRulesyncRule() {
|
|
36796
37850
|
return this.toRulesyncRuleDefault();
|
|
@@ -37193,31 +38247,68 @@ var OpenCodeRule = class OpenCodeRule extends ToolRule {
|
|
|
37193
38247
|
* RulesProcessor (there is no separate non-root output location — `nonRoot` is
|
|
37194
38248
|
* `undefined`). This mirrors the codexcli, grokcli, warp, and deepagents targets.
|
|
37195
38249
|
*
|
|
37196
|
-
* Pi also loads two system-prompt instruction files
|
|
38250
|
+
* Pi also loads two system-prompt instruction files. `.pi/APPEND_SYSTEM.md`
|
|
38251
|
+
* (global `~/.pi/agent/APPEND_SYSTEM.md`) *appends* to the default system prompt,
|
|
38252
|
+
* and rulesync emits it from any rule that opts in via the `pi.systemPrompt:
|
|
38253
|
+
* append` frontmatter block: those bodies are routed here instead of being folded
|
|
38254
|
+
* into `AGENTS.md`, and multiple opted-in rules concatenate in source order.
|
|
37197
38255
|
* `.pi/SYSTEM.md` (global `~/.pi/agent/SYSTEM.md`) *replaces* the default system
|
|
37198
|
-
* prompt entirely
|
|
37199
|
-
*
|
|
37200
|
-
*
|
|
37201
|
-
* for marking a rule as "replace" vs "append" the system prompt, so these
|
|
37202
|
-
* surfaces are documented in docs/reference/file-formats.md and left to be
|
|
37203
|
-
* authored by hand rather than mapped to a speculative new frontmatter flag.
|
|
38256
|
+
* prompt entirely — which silently disables Pi's built-in tool instructions — so
|
|
38257
|
+
* rulesync deliberately never emits it and leaves it to be authored by hand.
|
|
38258
|
+
* See docs/reference/file-formats.md.
|
|
37204
38259
|
*/
|
|
37205
38260
|
var PiRule = class PiRule extends ToolRule {
|
|
37206
|
-
|
|
38261
|
+
appendSystemPrompt;
|
|
38262
|
+
constructor({ fileContent, root, appendSystemPrompt = false, ...rest }) {
|
|
37207
38263
|
super({
|
|
37208
38264
|
...rest,
|
|
37209
38265
|
fileContent,
|
|
37210
38266
|
root: root ?? false
|
|
37211
38267
|
});
|
|
38268
|
+
this.appendSystemPrompt = appendSystemPrompt;
|
|
37212
38269
|
}
|
|
37213
38270
|
static getSettablePaths({ global = false, excludeToolDir } = {}) {
|
|
37214
|
-
return {
|
|
37215
|
-
|
|
37216
|
-
|
|
37217
|
-
|
|
38271
|
+
return {
|
|
38272
|
+
root: {
|
|
38273
|
+
relativeDirPath: global ? buildToolPath(".pi", "agent", excludeToolDir) : ".",
|
|
38274
|
+
relativeFilePath: PI_RULE_FILE_NAME
|
|
38275
|
+
},
|
|
38276
|
+
appendSystemPrompt: {
|
|
38277
|
+
relativeDirPath: global ? buildToolPath(".pi", "agent", excludeToolDir) : ".pi",
|
|
38278
|
+
relativeFilePath: PI_APPEND_SYSTEM_FILE_NAME
|
|
38279
|
+
}
|
|
38280
|
+
};
|
|
37218
38281
|
}
|
|
37219
|
-
|
|
37220
|
-
|
|
38282
|
+
/**
|
|
38283
|
+
* Extra fixed files this tool manages beyond the root rule. The
|
|
38284
|
+
* RulesProcessor enumerates these for import and deletion so a stale
|
|
38285
|
+
* `APPEND_SYSTEM.md` is cleaned up once no rule opts in anymore.
|
|
38286
|
+
*/
|
|
38287
|
+
static getExtraFixedFiles({ global = false } = {}) {
|
|
38288
|
+
return [this.getSettablePaths({ global }).appendSystemPrompt];
|
|
38289
|
+
}
|
|
38290
|
+
/**
|
|
38291
|
+
* Pi appends `APPEND_SYSTEM.md` to the system prompt itself, so listing it in
|
|
38292
|
+
* the root rule's reference section (toon/explicit discovery modes) would
|
|
38293
|
+
* double-load the content.
|
|
38294
|
+
*/
|
|
38295
|
+
isExcludedFromRootReferences() {
|
|
38296
|
+
return this.appendSystemPrompt;
|
|
38297
|
+
}
|
|
38298
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
38299
|
+
const { root, appendSystemPrompt } = this.getSettablePaths({ global });
|
|
38300
|
+
if (relativeFilePath === "APPEND_SYSTEM.md") {
|
|
38301
|
+
const fileContent = await readFileContent(join(outputRoot, join(appendSystemPrompt.relativeDirPath, appendSystemPrompt.relativeFilePath)));
|
|
38302
|
+
return new PiRule({
|
|
38303
|
+
outputRoot,
|
|
38304
|
+
relativeDirPath: appendSystemPrompt.relativeDirPath,
|
|
38305
|
+
relativeFilePath: appendSystemPrompt.relativeFilePath,
|
|
38306
|
+
fileContent,
|
|
38307
|
+
validate,
|
|
38308
|
+
root: false,
|
|
38309
|
+
appendSystemPrompt: true
|
|
38310
|
+
});
|
|
38311
|
+
}
|
|
37221
38312
|
const fileContent = await readFileContent(join(outputRoot, join(root.relativeDirPath, root.relativeFilePath)));
|
|
37222
38313
|
return new PiRule({
|
|
37223
38314
|
outputRoot,
|
|
@@ -37229,8 +38320,18 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37229
38320
|
});
|
|
37230
38321
|
}
|
|
37231
38322
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
37232
|
-
const { root } = this.getSettablePaths({ global });
|
|
37233
|
-
const
|
|
38323
|
+
const { root, appendSystemPrompt } = this.getSettablePaths({ global });
|
|
38324
|
+
const frontmatter = rulesyncRule.getFrontmatter();
|
|
38325
|
+
if (!frontmatter.root && frontmatter.pi?.systemPrompt === "append") return new PiRule({
|
|
38326
|
+
outputRoot,
|
|
38327
|
+
relativeDirPath: appendSystemPrompt.relativeDirPath,
|
|
38328
|
+
relativeFilePath: appendSystemPrompt.relativeFilePath,
|
|
38329
|
+
fileContent: rulesyncRule.getBody(),
|
|
38330
|
+
validate,
|
|
38331
|
+
root: false,
|
|
38332
|
+
appendSystemPrompt: true
|
|
38333
|
+
});
|
|
38334
|
+
const isRoot = frontmatter.root ?? false;
|
|
37234
38335
|
return new PiRule({
|
|
37235
38336
|
outputRoot,
|
|
37236
38337
|
relativeDirPath: root.relativeDirPath,
|
|
@@ -37241,6 +38342,17 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37241
38342
|
});
|
|
37242
38343
|
}
|
|
37243
38344
|
toRulesyncRule() {
|
|
38345
|
+
if (this.appendSystemPrompt) return new RulesyncRule({
|
|
38346
|
+
outputRoot: process.cwd(),
|
|
38347
|
+
relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
|
|
38348
|
+
relativeFilePath: PI_APPEND_SYSTEM_FILE_NAME,
|
|
38349
|
+
frontmatter: {
|
|
38350
|
+
root: false,
|
|
38351
|
+
targets: ["pi"],
|
|
38352
|
+
pi: { systemPrompt: "append" }
|
|
38353
|
+
},
|
|
38354
|
+
body: this.getFileContent()
|
|
38355
|
+
});
|
|
37244
38356
|
return this.toRulesyncRuleDefault();
|
|
37245
38357
|
}
|
|
37246
38358
|
validate() {
|
|
@@ -37251,6 +38363,15 @@ var PiRule = class PiRule extends ToolRule {
|
|
|
37251
38363
|
}
|
|
37252
38364
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
|
|
37253
38365
|
const { root } = this.getSettablePaths({ global });
|
|
38366
|
+
if (relativeFilePath === "APPEND_SYSTEM.md") return new PiRule({
|
|
38367
|
+
outputRoot,
|
|
38368
|
+
relativeDirPath,
|
|
38369
|
+
relativeFilePath,
|
|
38370
|
+
fileContent: "",
|
|
38371
|
+
validate: false,
|
|
38372
|
+
root: false,
|
|
38373
|
+
appendSystemPrompt: true
|
|
38374
|
+
});
|
|
37254
38375
|
const isRoot = relativeFilePath === "AGENTS.md" && (relativeDirPath === "." || relativeDirPath === root.relativeDirPath);
|
|
37255
38376
|
return new PiRule({
|
|
37256
38377
|
outputRoot,
|
|
@@ -38410,7 +39531,8 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
38410
39531
|
meta: {
|
|
38411
39532
|
extension: "md",
|
|
38412
39533
|
supportsGlobal: true,
|
|
38413
|
-
ruleDiscoveryMode: "
|
|
39534
|
+
ruleDiscoveryMode: "auto",
|
|
39535
|
+
foldsNonRootIntoRoot: true
|
|
38414
39536
|
}
|
|
38415
39537
|
}],
|
|
38416
39538
|
["kilo", {
|
|
@@ -38676,7 +39798,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38676
39798
|
*/
|
|
38677
39799
|
async buildMcpInstructionFiles({ toolRules, meta }) {
|
|
38678
39800
|
if (!meta.mcpInstructionsRegistrar || this.global) return [];
|
|
38679
|
-
const instructionPaths = toolRules.filter((rule) => !rule.isRoot()).map((rule) => toPosixPath(join(rule.getRelativeDirPath(), rule.getRelativeFilePath())));
|
|
39801
|
+
const instructionPaths = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences()).map((rule) => toPosixPath(join(rule.getRelativeDirPath(), rule.getRelativeFilePath())));
|
|
38680
39802
|
if (instructionPaths.length === 0) return [];
|
|
38681
39803
|
return [await meta.mcpInstructionsRegistrar.fromInstructions({
|
|
38682
39804
|
outputRoot: this.outputRoot,
|
|
@@ -38708,7 +39830,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38708
39830
|
const toolRelativeDirPath = skillClass.getSettablePaths({ global: this.global }).relativeDirPath;
|
|
38709
39831
|
return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
|
|
38710
39832
|
const frontmatter = skill.getFrontmatter();
|
|
38711
|
-
const relativePath = join(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
|
|
39833
|
+
const relativePath = join(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME$1);
|
|
38712
39834
|
return {
|
|
38713
39835
|
name: frontmatter.name,
|
|
38714
39836
|
description: frontmatter.description,
|
|
@@ -38732,11 +39854,25 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
38732
39854
|
*/
|
|
38733
39855
|
foldNonRootRulesIntoRootRule(toolRules) {
|
|
38734
39856
|
if (toolRules.length <= 1) return;
|
|
38735
|
-
const
|
|
38736
|
-
|
|
38737
|
-
|
|
38738
|
-
|
|
38739
|
-
|
|
39857
|
+
const groups = /* @__PURE__ */ new Map();
|
|
39858
|
+
for (const rule of toolRules) {
|
|
39859
|
+
const path = join(rule.getRelativeDirPath(), rule.getRelativeFilePath());
|
|
39860
|
+
const group = groups.get(path);
|
|
39861
|
+
if (group) group.push(rule);
|
|
39862
|
+
else groups.set(path, [rule]);
|
|
39863
|
+
}
|
|
39864
|
+
const survivors = /* @__PURE__ */ new Set();
|
|
39865
|
+
for (const group of groups.values()) {
|
|
39866
|
+
const target = group.find((rule) => rule.isRoot()) ?? group[0];
|
|
39867
|
+
if (!target) continue;
|
|
39868
|
+
const mergedContent = [target, ...group.filter((rule) => rule !== target)].map((rule) => rule.getFileContent().trim()).filter((content) => content.length > 0).join("\n\n");
|
|
39869
|
+
target.setFileContent(mergedContent);
|
|
39870
|
+
survivors.add(target);
|
|
39871
|
+
}
|
|
39872
|
+
for (let i = toolRules.length - 1; i >= 0; i--) {
|
|
39873
|
+
const rule = toolRules[i];
|
|
39874
|
+
if (rule && !survivors.has(rule)) toolRules.splice(i, 1);
|
|
39875
|
+
}
|
|
38740
39876
|
}
|
|
38741
39877
|
/**
|
|
38742
39878
|
* Handle localRoot rule generation based on tool target.
|
|
@@ -38946,6 +40082,27 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
38946
40082
|
const mirrorPaths = await findFilesByGlobs(mirrorGlob);
|
|
38947
40083
|
return buildDeletionRulesFromPaths(mirrorPaths);
|
|
38948
40084
|
})();
|
|
40085
|
+
const extraFixedToolRules = await (async () => {
|
|
40086
|
+
const extraFiles = factory.class.getExtraFixedFiles?.({ global: this.global });
|
|
40087
|
+
if (!extraFiles || extraFiles.length === 0) return [];
|
|
40088
|
+
const filePaths = await findFilesByGlobs(extraFiles.map((file) => join(this.outputRoot, file.relativeDirPath, file.relativeFilePath)));
|
|
40089
|
+
if (filePaths.length === 0) return [];
|
|
40090
|
+
if (forDeletion) return buildDeletionRulesFromPaths(filePaths);
|
|
40091
|
+
return await Promise.all(filePaths.map((filePath) => {
|
|
40092
|
+
const relativeDirPath = resolveRelativeDirPath(filePath);
|
|
40093
|
+
checkPathTraversal({
|
|
40094
|
+
relativePath: relativeDirPath,
|
|
40095
|
+
intendedRootDir: this.outputRoot
|
|
40096
|
+
});
|
|
40097
|
+
return factory.class.fromFile({
|
|
40098
|
+
outputRoot: this.outputRoot,
|
|
40099
|
+
relativeDirPath,
|
|
40100
|
+
relativeFilePath: basename(filePath),
|
|
40101
|
+
global: this.global
|
|
40102
|
+
});
|
|
40103
|
+
}));
|
|
40104
|
+
})();
|
|
40105
|
+
this.logger.debug(`Found ${extraFixedToolRules.length} extra fixed tool rule files`);
|
|
38949
40106
|
const nonRootToolRules = await (async () => {
|
|
38950
40107
|
if (!settablePaths.nonRoot) return [];
|
|
38951
40108
|
const nonRootOutputRoot = join(this.outputRoot, settablePaths.nonRoot.relativeDirPath);
|
|
@@ -38981,6 +40138,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
38981
40138
|
...rootToolRules,
|
|
38982
40139
|
...localRootToolRules,
|
|
38983
40140
|
...rootMirrorDeletionRules,
|
|
40141
|
+
...extraFixedToolRules,
|
|
38984
40142
|
...nonRootToolRules
|
|
38985
40143
|
];
|
|
38986
40144
|
} catch (error) {
|
|
@@ -39008,7 +40166,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39008
40166
|
return toolRuleFactories.get(result.data);
|
|
39009
40167
|
}
|
|
39010
40168
|
generateToonReferencesSection(toolRules) {
|
|
39011
|
-
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
|
|
40169
|
+
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences());
|
|
39012
40170
|
if (toolRulesWithoutRoot.length === 0) return "";
|
|
39013
40171
|
const lines = [];
|
|
39014
40172
|
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.");
|
|
@@ -39024,7 +40182,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39024
40182
|
return lines.join("\n") + "\n\n";
|
|
39025
40183
|
}
|
|
39026
40184
|
generateReferencesSection(toolRules) {
|
|
39027
|
-
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
|
|
40185
|
+
const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot() && !rule.isExcludedFromRootReferences());
|
|
39028
40186
|
if (toolRulesWithoutRoot.length === 0) return "";
|
|
39029
40187
|
const lines = [];
|
|
39030
40188
|
lines.push("Please also reference the following rules as needed:");
|
|
@@ -39045,7 +40203,7 @@ As this project's AI coding tool, you must follow the additional conventions bel
|
|
|
39045
40203
|
*/
|
|
39046
40204
|
async function convertFromTool(params) {
|
|
39047
40205
|
const ctx = params;
|
|
39048
|
-
const [rulesCount, ignoreCount, mcpCount, commandsCount, subagentsCount, skillsCount, hooksCount, permissionsCount] = [
|
|
40206
|
+
const [rulesCount, ignoreCount, mcpCount, commandsCount, subagentsCount, skillsCount, hooksCount, permissionsCount, checksCount] = [
|
|
39049
40207
|
await runFeatureConvert(ctx, buildRulesStrategy(ctx)),
|
|
39050
40208
|
await runFeatureConvert(ctx, buildIgnoreStrategy(ctx)),
|
|
39051
40209
|
await runFeatureConvert(ctx, buildMcpStrategy(ctx)),
|
|
@@ -39053,7 +40211,8 @@ async function convertFromTool(params) {
|
|
|
39053
40211
|
await runFeatureConvert(ctx, buildSubagentsStrategy(ctx)),
|
|
39054
40212
|
await runFeatureConvert(ctx, buildSkillsStrategy(ctx)),
|
|
39055
40213
|
await runFeatureConvert(ctx, buildHooksStrategy(ctx)),
|
|
39056
|
-
await runFeatureConvert(ctx, buildPermissionsStrategy(ctx))
|
|
40214
|
+
await runFeatureConvert(ctx, buildPermissionsStrategy(ctx)),
|
|
40215
|
+
await runFeatureConvert(ctx, buildChecksStrategy(ctx))
|
|
39057
40216
|
];
|
|
39058
40217
|
return {
|
|
39059
40218
|
rulesCount,
|
|
@@ -39063,7 +40222,8 @@ async function convertFromTool(params) {
|
|
|
39063
40222
|
subagentsCount,
|
|
39064
40223
|
skillsCount,
|
|
39065
40224
|
hooksCount,
|
|
39066
|
-
permissionsCount
|
|
40225
|
+
permissionsCount,
|
|
40226
|
+
checksCount
|
|
39067
40227
|
};
|
|
39068
40228
|
}
|
|
39069
40229
|
async function runFeatureConvert(ctx, strategy) {
|
|
@@ -39296,6 +40456,27 @@ function buildPermissionsStrategy(ctx) {
|
|
|
39296
40456
|
write: (p, files) => p.writeAiFiles(files)
|
|
39297
40457
|
};
|
|
39298
40458
|
}
|
|
40459
|
+
function buildChecksStrategy(ctx) {
|
|
40460
|
+
const { config, logger } = ctx;
|
|
40461
|
+
const global = config.getGlobal();
|
|
40462
|
+
const outputRoot = getOutputRoot(config);
|
|
40463
|
+
return {
|
|
40464
|
+
feature: "checks",
|
|
40465
|
+
itemLabel: "check file(s)",
|
|
40466
|
+
allTargets: ChecksProcessor.getToolTargets({ global }),
|
|
40467
|
+
createProcessor: ({ toolTarget, dryRun }) => new ChecksProcessor({
|
|
40468
|
+
outputRoot,
|
|
40469
|
+
toolTarget,
|
|
40470
|
+
global,
|
|
40471
|
+
dryRun,
|
|
40472
|
+
logger
|
|
40473
|
+
}),
|
|
40474
|
+
loadSource: (p) => p.loadToolFiles(),
|
|
40475
|
+
toRulesync: (p, files) => p.convertToolFilesToRulesyncFiles(files),
|
|
40476
|
+
fromRulesync: (p, files) => p.convertRulesyncFilesToToolFiles(files),
|
|
40477
|
+
write: (p, files) => p.writeAiFiles(files)
|
|
40478
|
+
};
|
|
40479
|
+
}
|
|
39299
40480
|
//#endregion
|
|
39300
40481
|
//#region src/types/processor-registry.ts
|
|
39301
40482
|
const PROCESSOR_REGISTRY = [
|
|
@@ -39346,6 +40527,12 @@ const PROCESSOR_REGISTRY = [
|
|
|
39346
40527
|
processor: PermissionsProcessor,
|
|
39347
40528
|
schema: PermissionsProcessorToolTargetSchema,
|
|
39348
40529
|
factory: toolPermissionsFactories
|
|
40530
|
+
},
|
|
40531
|
+
{
|
|
40532
|
+
feature: "checks",
|
|
40533
|
+
processor: ChecksProcessor,
|
|
40534
|
+
schema: ChecksProcessorToolTargetSchema,
|
|
40535
|
+
factory: toolCheckFactories
|
|
39349
40536
|
}
|
|
39350
40537
|
];
|
|
39351
40538
|
const getProcessorRegistryEntry = (feature) => {
|
|
@@ -39695,6 +40882,7 @@ const GENERATION_STEP_GRAPH = [
|
|
|
39695
40882
|
id: "permissions",
|
|
39696
40883
|
...sharedWriteMeta("permissions")
|
|
39697
40884
|
},
|
|
40885
|
+
{ id: "checks" },
|
|
39698
40886
|
{
|
|
39699
40887
|
id: "rules",
|
|
39700
40888
|
...sharedWriteMeta("rules"),
|
|
@@ -39702,11 +40890,51 @@ const GENERATION_STEP_GRAPH = [
|
|
|
39702
40890
|
}
|
|
39703
40891
|
];
|
|
39704
40892
|
/**
|
|
40893
|
+
* Warn when a rulesync skill and a rulesync subagent share a name for a tool
|
|
40894
|
+
* that emits both features into the same directory (e.g. Reasonix, where both
|
|
40895
|
+
* write `<name>/SKILL.md` under `.reasonix/skills/`). The colliding outputs
|
|
40896
|
+
* target the same on-disk file, so whichever generation step runs later
|
|
40897
|
+
* silently overwrites the other's file.
|
|
40898
|
+
*/
|
|
40899
|
+
async function warnSkillSubagentNameCollisions(params) {
|
|
40900
|
+
const { config, logger } = params;
|
|
40901
|
+
const global = config.getGlobal();
|
|
40902
|
+
for (const toolTarget of config.getTargets()) {
|
|
40903
|
+
const features = config.getFeatures(toolTarget);
|
|
40904
|
+
if (!features.includes("skills") || !features.includes("subagents")) continue;
|
|
40905
|
+
if (!SubagentsProcessor.getToolTargets({ global }).includes(toolTarget) || !SkillsProcessor.getToolTargets({ global }).includes(toolTarget)) continue;
|
|
40906
|
+
const subagentFactory = SubagentsProcessor.getFactory(toolTarget);
|
|
40907
|
+
const skillFactory = SkillsProcessor.getFactory(toolTarget);
|
|
40908
|
+
if (!subagentFactory || !skillFactory) continue;
|
|
40909
|
+
const subagentsDirPath = subagentFactory.class.getSettablePaths({ global }).relativeDirPath;
|
|
40910
|
+
if (subagentsDirPath !== skillFactory.class.getSettablePaths({ global }).relativeDirPath) continue;
|
|
40911
|
+
const subagentsProcessor = new SubagentsProcessor({
|
|
40912
|
+
inputRoot: config.getInputRoot(),
|
|
40913
|
+
toolTarget,
|
|
40914
|
+
global,
|
|
40915
|
+
logger
|
|
40916
|
+
});
|
|
40917
|
+
const subagentNames = new Set((await subagentsProcessor.loadRulesyncFiles()).filter((file) => file instanceof RulesyncSubagent).filter((file) => subagentFactory.class.isTargetedByRulesyncSubagent(file)).map((file) => basename(file.getRelativeFilePath(), extname(file.getRelativeFilePath()))));
|
|
40918
|
+
if (subagentNames.size === 0) continue;
|
|
40919
|
+
const skillNames = (await new SkillsProcessor({
|
|
40920
|
+
inputRoot: config.getInputRoot(),
|
|
40921
|
+
toolTarget,
|
|
40922
|
+
global,
|
|
40923
|
+
logger
|
|
40924
|
+
}).loadRulesyncDirs()).filter((dir) => dir instanceof RulesyncSkill).filter((skill) => skillFactory.class.isTargetedByRulesyncSkill(skill)).map((skill) => skill.getDirName());
|
|
40925
|
+
for (const name of skillNames) if (subagentNames.has(name)) logger.warn(`Skill "${name}" and subagent "${name}" both target '${toolTarget}' and write the same path '${join(subagentsDirPath, name)}'; the later generation step overwrites the other's output. Rename one of them or narrow their targets.`);
|
|
40926
|
+
}
|
|
40927
|
+
}
|
|
40928
|
+
/**
|
|
39705
40929
|
* Generate configuration files for AI tools.
|
|
39706
40930
|
* @throws Error if generation fails
|
|
39707
40931
|
*/
|
|
39708
40932
|
async function generate(params) {
|
|
39709
40933
|
const { config, logger } = params;
|
|
40934
|
+
await warnSkillSubagentNameCollisions({
|
|
40935
|
+
config,
|
|
40936
|
+
logger
|
|
40937
|
+
});
|
|
39710
40938
|
let skillsResult;
|
|
39711
40939
|
const runners = {
|
|
39712
40940
|
ignore: () => generateIgnoreCore({
|
|
@@ -39740,6 +40968,10 @@ async function generate(params) {
|
|
|
39740
40968
|
config,
|
|
39741
40969
|
logger
|
|
39742
40970
|
}),
|
|
40971
|
+
checks: () => generateChecksCore({
|
|
40972
|
+
config,
|
|
40973
|
+
logger
|
|
40974
|
+
}),
|
|
39743
40975
|
rules: () => generateRulesCore({
|
|
39744
40976
|
config,
|
|
39745
40977
|
logger,
|
|
@@ -39776,6 +41008,8 @@ async function generate(params) {
|
|
|
39776
41008
|
hooksPaths: get("hooks").paths,
|
|
39777
41009
|
permissionsCount: get("permissions").count,
|
|
39778
41010
|
permissionsPaths: get("permissions").paths,
|
|
41011
|
+
checksCount: get("checks").count,
|
|
41012
|
+
checksPaths: get("checks").paths,
|
|
39779
41013
|
skills: skillsResult.skills,
|
|
39780
41014
|
hasDiff
|
|
39781
41015
|
};
|
|
@@ -40144,6 +41378,44 @@ async function generatePermissionsCore(params) {
|
|
|
40144
41378
|
hasDiff
|
|
40145
41379
|
};
|
|
40146
41380
|
}
|
|
41381
|
+
async function generateChecksCore(params) {
|
|
41382
|
+
const { config, logger } = params;
|
|
41383
|
+
let totalCount = 0;
|
|
41384
|
+
const allPaths = [];
|
|
41385
|
+
let hasDiff = false;
|
|
41386
|
+
const supportedChecksTargets = ChecksProcessor.getToolTargets({ global: config.getGlobal() });
|
|
41387
|
+
const toolTargets = intersection(config.getTargets(), supportedChecksTargets);
|
|
41388
|
+
warnUnsupportedTargets({
|
|
41389
|
+
config,
|
|
41390
|
+
supportedTargets: supportedChecksTargets,
|
|
41391
|
+
featureName: "checks",
|
|
41392
|
+
logger
|
|
41393
|
+
});
|
|
41394
|
+
for (const toolTarget of toolTargets) for (const outputRoot of config.getOutputRoots(toolTarget)) {
|
|
41395
|
+
if (!config.getFeatures(toolTarget).includes("checks")) continue;
|
|
41396
|
+
const processor = new ChecksProcessor({
|
|
41397
|
+
outputRoot,
|
|
41398
|
+
inputRoot: config.getInputRoot(),
|
|
41399
|
+
toolTarget,
|
|
41400
|
+
global: config.getGlobal(),
|
|
41401
|
+
dryRun: config.isPreviewMode(),
|
|
41402
|
+
logger
|
|
41403
|
+
});
|
|
41404
|
+
const result = await processFeatureWithRulesyncFiles({
|
|
41405
|
+
config,
|
|
41406
|
+
processor,
|
|
41407
|
+
rulesyncFiles: await processor.loadRulesyncFiles()
|
|
41408
|
+
});
|
|
41409
|
+
totalCount += result.count;
|
|
41410
|
+
allPaths.push(...result.paths);
|
|
41411
|
+
if (result.hasDiff) hasDiff = true;
|
|
41412
|
+
}
|
|
41413
|
+
return {
|
|
41414
|
+
count: totalCount,
|
|
41415
|
+
paths: allPaths,
|
|
41416
|
+
hasDiff
|
|
41417
|
+
};
|
|
41418
|
+
}
|
|
40147
41419
|
//#endregion
|
|
40148
41420
|
//#region src/lib/import.ts
|
|
40149
41421
|
/**
|
|
@@ -40201,6 +41473,11 @@ async function importFromTool(params) {
|
|
|
40201
41473
|
config,
|
|
40202
41474
|
tool,
|
|
40203
41475
|
logger
|
|
41476
|
+
}),
|
|
41477
|
+
checksCount: await importChecksCore({
|
|
41478
|
+
config,
|
|
41479
|
+
tool,
|
|
41480
|
+
logger
|
|
40204
41481
|
})
|
|
40205
41482
|
};
|
|
40206
41483
|
}
|
|
@@ -40417,7 +41694,28 @@ async function importPermissionsCore(params) {
|
|
|
40417
41694
|
if (config.getVerbose() && writtenCount > 0) logger.success(`Created ${writtenCount} permissions file(s)`);
|
|
40418
41695
|
return writtenCount;
|
|
40419
41696
|
}
|
|
41697
|
+
async function importChecksCore(params) {
|
|
41698
|
+
const { config, tool, logger } = params;
|
|
41699
|
+
if (!config.getFeatures(tool).includes("checks")) return 0;
|
|
41700
|
+
const global = config.getGlobal();
|
|
41701
|
+
if (!ChecksProcessor.getToolTargets({ global }).includes(tool)) return 0;
|
|
41702
|
+
const checksProcessor = new ChecksProcessor({
|
|
41703
|
+
outputRoot: config.getOutputRoots()[0] ?? ".",
|
|
41704
|
+
toolTarget: tool,
|
|
41705
|
+
global,
|
|
41706
|
+
logger
|
|
41707
|
+
});
|
|
41708
|
+
const toolFiles = await checksProcessor.loadToolFiles();
|
|
41709
|
+
if (toolFiles.length === 0) {
|
|
41710
|
+
logger.warn(`No check files found for ${tool}. Skipping import.`);
|
|
41711
|
+
return 0;
|
|
41712
|
+
}
|
|
41713
|
+
const rulesyncFiles = await checksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
41714
|
+
const { count: writtenCount } = await checksProcessor.writeAiFiles(rulesyncFiles);
|
|
41715
|
+
if (config.getVerbose() && writtenCount > 0) logger.success(`Created ${writtenCount} check files`);
|
|
41716
|
+
return writtenCount;
|
|
41717
|
+
}
|
|
40420
41718
|
//#endregion
|
|
40421
|
-
export {
|
|
41719
|
+
export { isSymlink as $, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as A, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as At, findControlCharacter as B, CommandsProcessor as C, RULESYNC_MCP_FILE_NAME as Ct, CLAUDECODE_DIR as D, RULESYNC_OVERVIEW_FILE_NAME as Dt, CODEXCLI_DIR as E, RULESYNC_MCP_SCHEMA_URL as Et, RulesyncCheck as F, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Ft, checkPathTraversal as G, JsonLogger as H, RulesyncCheckFrontmatterSchema as I, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as It, ensureDir as J, createTempDirectory as K, stringifyFrontmatter as L, formatError as Lt, RulesyncCommand as M, RULESYNC_RELATIVE_DIR_PATH as Mt, RulesyncCommandFrontmatterSchema as N, RULESYNC_RULES_RELATIVE_DIR_PATH as Nt, CLAUDECODE_LOCAL_RULE_FILE_NAME as O, RULESYNC_PERMISSIONS_FILE_NAME as Ot, ChecksProcessor as P, RULESYNC_SKILLS_RELATIVE_DIR_PATH as Pt, getHomeDirectory as Q, loadYaml as R, ALL_FEATURES as Rt, RulesyncHooks as S, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as St, CODEXCLI_BASH_RULES_FILE_NAME as T, RULESYNC_MCP_RELATIVE_FILE_PATH as Tt, CLIError as U, ConsoleLogger as V, ErrorCodes as W, findFilesByGlobs as X, fileExists as Y, getFileSize as Z, McpProcessor as _, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as _t, convertFromTool as a, toPosixPath as at, RulesyncIgnore as b, RULESYNC_HOOKS_RELATIVE_FILE_PATH as bt, RulesyncRuleFrontmatterSchema as c, ALL_TOOL_TARGETS_WITH_WILDCARD as ct, RulesyncSubagentFrontmatterSchema as d, RULESYNC_AIIGNORE_FILE_NAME as dt, listDirectoryFiles as et, SkillsProcessor as f, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as ft, RulesyncPermissions as g, RULESYNC_CONFIG_SCHEMA_URL as gt, RulesyncSkillFrontmatterSchema as h, RULESYNC_CONFIG_RELATIVE_FILE_PATH as ht, getProcessorRegistryEntry as i, removeTempDirectory as it, CLAUDECODE_SKILLS_DIR_PATH as j, RULESYNC_PERMISSIONS_SCHEMA_URL as jt, CLAUDECODE_MEMORIES_DIR_NAME as k, RULESYNC_PERMISSIONS_JSONC_FILE_NAME as kt, SubagentsProcessor as l, ToolTargetSchema as lt, RulesyncSkill as m, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as mt, checkRulesyncDirExists as n, removeDirectory as nt, RulesProcessor as o, writeFileContent as ot, getLocalSkillDirNames as p, RULESYNC_CHECKS_RELATIVE_DIR_PATH as pt, directoryExists as q, generate as r, removeFile as rt, RulesyncRule as s, ALL_TOOL_TARGETS as st, importFromTool as t, readFileContent as tt, RulesyncSubagent as u, MAX_FILE_SIZE as ut, RulesyncMcp as v, RULESYNC_HOOKS_FILE_NAME as vt, SKILL_FILE_NAME$1 as w, RULESYNC_MCP_JSONC_FILE_NAME as wt, HooksProcessor as x, RULESYNC_IGNORE_RELATIVE_FILE_PATH as xt, IgnoreProcessor as y, RULESYNC_HOOKS_JSONC_FILE_NAME as yt, ConfigResolver as z, ALL_FEATURES_WITH_WILDCARD as zt };
|
|
40422
41720
|
|
|
40423
|
-
//# sourceMappingURL=import-
|
|
41721
|
+
//# sourceMappingURL=import-CMSHVMqU.js.map
|