rulesync 30.0.0 → 31.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 +1 -1
- package/dist/cli/index.cjs +4 -4
- package/dist/cli/index.js +4 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-XIYCKmjg.cjs → import-CBvXTNp8.cjs} +240 -42
- package/dist/{import-DBd2G6Eo.js → import-ORYbMDJK.js} +241 -43
- package/dist/{import-DBd2G6Eo.js.map → import-ORYbMDJK.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -935,6 +935,7 @@ const checksProcessorToolTargetTuple = [
|
|
|
935
935
|
"cursor",
|
|
936
936
|
"factorydroid",
|
|
937
937
|
"gitlabduo",
|
|
938
|
+
"goose",
|
|
938
939
|
"hermesagent",
|
|
939
940
|
"kilo",
|
|
940
941
|
"qwencode",
|
|
@@ -14221,12 +14222,12 @@ const AmpCheckFrontmatterSchema = zod_mini.z.looseObject({
|
|
|
14221
14222
|
* this format continue to apply.
|
|
14222
14223
|
* @see https://ampcode.com/docs/review
|
|
14223
14224
|
*/
|
|
14224
|
-
var AmpCheck = class
|
|
14225
|
+
var AmpCheck = class extends ToolCheck {
|
|
14225
14226
|
frontmatter;
|
|
14226
14227
|
body;
|
|
14227
14228
|
constructor({ frontmatter, body, fileContent, ...rest }) {
|
|
14228
14229
|
if (rest.validate !== false) {
|
|
14229
|
-
const result =
|
|
14230
|
+
const result = new.target.getFrontmatterSchema().safeParse(frontmatter);
|
|
14230
14231
|
if (!result.success) throw new Error(`Invalid frontmatter in ${(0, node_path.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`);
|
|
14231
14232
|
}
|
|
14232
14233
|
super({
|
|
@@ -14236,6 +14237,26 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14236
14237
|
this.frontmatter = frontmatter;
|
|
14237
14238
|
this.body = body;
|
|
14238
14239
|
}
|
|
14240
|
+
/**
|
|
14241
|
+
* The tool target this check format belongs to, which is also the name of
|
|
14242
|
+
* its tool-specific frontmatter section. Goose reads the same per-file
|
|
14243
|
+
* format with a few extra keys, so `GooseCheck` reuses this class through
|
|
14244
|
+
* these hooks.
|
|
14245
|
+
*/
|
|
14246
|
+
static getCheckToolTarget() {
|
|
14247
|
+
return "amp";
|
|
14248
|
+
}
|
|
14249
|
+
/** The frontmatter schema a check file of this tool is validated against. */
|
|
14250
|
+
static getFrontmatterSchema() {
|
|
14251
|
+
return AmpCheckFrontmatterSchema;
|
|
14252
|
+
}
|
|
14253
|
+
/**
|
|
14254
|
+
* Frontmatter keys only this tool reads. Import moves them into the tool's
|
|
14255
|
+
* own section so they are not passed on to every other checks target.
|
|
14256
|
+
*/
|
|
14257
|
+
static getToolOnlyKeys() {
|
|
14258
|
+
return [];
|
|
14259
|
+
}
|
|
14239
14260
|
static getSettablePaths({ global = false } = {}) {
|
|
14240
14261
|
return { relativeDirPath: global ? AMP_CHECKS_GLOBAL_DIR : AMP_CHECKS_PROJECT_DIR };
|
|
14241
14262
|
}
|
|
@@ -14247,6 +14268,10 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14247
14268
|
}
|
|
14248
14269
|
toRulesyncCheck() {
|
|
14249
14270
|
const { name: _name, description, "severity-default": severityDefault, tools, ...restFields } = this.frontmatter;
|
|
14271
|
+
const checkClass = this.constructor;
|
|
14272
|
+
const toolOnlyKeys = new Set(checkClass.getToolOnlyKeys());
|
|
14273
|
+
const sharedFields = Object.fromEntries(Object.entries(restFields).filter(([key]) => !toolOnlyKeys.has(key)));
|
|
14274
|
+
const toolSection = Object.fromEntries(Object.entries(restFields).filter(([key]) => toolOnlyKeys.has(key)));
|
|
14250
14275
|
return new RulesyncCheck({
|
|
14251
14276
|
outputRoot: ".",
|
|
14252
14277
|
frontmatter: {
|
|
@@ -14254,7 +14279,8 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14254
14279
|
...description !== void 0 && { description },
|
|
14255
14280
|
...severityDefault !== void 0 && { severity: severityDefault },
|
|
14256
14281
|
...tools !== void 0 && { tools },
|
|
14257
|
-
...
|
|
14282
|
+
...sharedFields,
|
|
14283
|
+
...Object.keys(toolSection).length > 0 && { [checkClass.getCheckToolTarget()]: toolSection }
|
|
14258
14284
|
},
|
|
14259
14285
|
body: this.body,
|
|
14260
14286
|
relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH,
|
|
@@ -14269,22 +14295,24 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14269
14295
|
const { targets: _targets, description, severity, tools, ...restFields } = rulesyncFrontmatter;
|
|
14270
14296
|
const toolTargetKeys = new Set(ALL_TOOL_TARGETS);
|
|
14271
14297
|
const passthroughFields = Object.fromEntries(Object.entries(restFields).filter(([key]) => !toolTargetKeys.has(key) && key !== "name"));
|
|
14272
|
-
const
|
|
14298
|
+
const toolTarget = this.getCheckToolTarget();
|
|
14299
|
+
const rawSection = rulesyncFrontmatter[toolTarget];
|
|
14300
|
+
const toolSection = this.filterToolSpecificSection(rawSection !== null && typeof rawSection === "object" && !Array.isArray(rawSection) ? rawSection : {}, ["name"]);
|
|
14273
14301
|
const rawAmpFrontmatter = {
|
|
14274
14302
|
name,
|
|
14275
14303
|
...description !== void 0 && { description },
|
|
14276
14304
|
...severity !== void 0 && { "severity-default": severity },
|
|
14277
14305
|
...tools !== void 0 && { tools },
|
|
14278
14306
|
...passthroughFields,
|
|
14279
|
-
...
|
|
14307
|
+
...toolSection
|
|
14280
14308
|
};
|
|
14281
|
-
const result =
|
|
14282
|
-
if (!result.success) throw new Error(`Invalid
|
|
14309
|
+
const result = this.getFrontmatterSchema().safeParse(rawAmpFrontmatter);
|
|
14310
|
+
if (!result.success) throw new Error(`Invalid ${toolTarget} check frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
14283
14311
|
const ampFrontmatter = result.data;
|
|
14284
14312
|
const body = rulesyncCheck.getBody();
|
|
14285
14313
|
const fileContent = stringifyFrontmatter(body, ampFrontmatter);
|
|
14286
14314
|
const paths = this.getSettablePaths({ global });
|
|
14287
|
-
return new
|
|
14315
|
+
return new this({
|
|
14288
14316
|
outputRoot,
|
|
14289
14317
|
frontmatter: ampFrontmatter,
|
|
14290
14318
|
body,
|
|
@@ -14299,7 +14327,7 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14299
14327
|
success: true,
|
|
14300
14328
|
error: null
|
|
14301
14329
|
};
|
|
14302
|
-
const result =
|
|
14330
|
+
const result = this.constructor.getFrontmatterSchema().safeParse(this.frontmatter);
|
|
14303
14331
|
if (result.success) return {
|
|
14304
14332
|
success: true,
|
|
14305
14333
|
error: null
|
|
@@ -14312,7 +14340,7 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14312
14340
|
static isTargetedByRulesyncCheck(rulesyncCheck) {
|
|
14313
14341
|
return this.isTargetedByRulesyncCheckDefault({
|
|
14314
14342
|
rulesyncCheck,
|
|
14315
|
-
toolTarget:
|
|
14343
|
+
toolTarget: this.getCheckToolTarget()
|
|
14316
14344
|
});
|
|
14317
14345
|
}
|
|
14318
14346
|
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
@@ -14320,9 +14348,9 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14320
14348
|
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
14321
14349
|
const fileContent = await readFileContent(filePath);
|
|
14322
14350
|
const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
|
|
14323
|
-
const result =
|
|
14351
|
+
const result = this.getFrontmatterSchema().safeParse(frontmatter);
|
|
14324
14352
|
if (!result.success) throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
|
|
14325
|
-
return new
|
|
14353
|
+
return new this({
|
|
14326
14354
|
outputRoot,
|
|
14327
14355
|
relativeDirPath: paths.relativeDirPath,
|
|
14328
14356
|
relativeFilePath,
|
|
@@ -14333,7 +14361,7 @@ var AmpCheck = class AmpCheck extends ToolCheck {
|
|
|
14333
14361
|
});
|
|
14334
14362
|
}
|
|
14335
14363
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
14336
|
-
return new
|
|
14364
|
+
return new this({
|
|
14337
14365
|
outputRoot,
|
|
14338
14366
|
relativeDirPath,
|
|
14339
14367
|
relativeFilePath,
|
|
@@ -15433,6 +15461,60 @@ var GitlabduoCheck = class GitlabduoCheck extends ToolCheck {
|
|
|
15433
15461
|
}
|
|
15434
15462
|
};
|
|
15435
15463
|
//#endregion
|
|
15464
|
+
//#region src/constants/goose-paths.ts
|
|
15465
|
+
const GOOSE_DIR = ".goose";
|
|
15466
|
+
const GOOSE_GLOBAL_DIR = (0, node_path.join)(".config", "goose");
|
|
15467
|
+
const GOOSE_RULE_FILE_NAME = ".goosehints";
|
|
15468
|
+
const GOOSE_MCP_FILE_NAME = "config.yaml";
|
|
15469
|
+
const GOOSE_PERMISSIONS_FILE_NAME = "permission.yaml";
|
|
15470
|
+
const GOOSE_HOOKS_DIR_PATH = (0, node_path.join)(".agents", "plugins", "rulesync", "hooks");
|
|
15471
|
+
const GOOSE_HOOKS_FILE_NAME = "hooks.json";
|
|
15472
|
+
const GOOSE_PLUGIN_MCP_DIR_PATH = (0, node_path.join)(".agents", "plugins", "rulesync");
|
|
15473
|
+
const GOOSE_PLUGIN_MCP_FILE_NAME = ".mcp.json";
|
|
15474
|
+
const GOOSE_SKILLS_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "skills");
|
|
15475
|
+
const GOOSE_GLOBAL_SKILLS_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "skills");
|
|
15476
|
+
const GOOSE_RECIPES_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "recipes");
|
|
15477
|
+
const GOOSE_GLOBAL_RECIPES_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "recipes");
|
|
15478
|
+
const GOOSE_AGENTS_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "agents");
|
|
15479
|
+
const GOOSE_GLOBAL_AGENTS_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "agents");
|
|
15480
|
+
const GOOSE_CHECKS_PROJECT_DIR = (0, node_path.join)(".agents", "checks");
|
|
15481
|
+
const GOOSE_CHECKS_GLOBAL_DIR = (0, node_path.join)(GOOSE_GLOBAL_DIR, "checks");
|
|
15482
|
+
//#endregion
|
|
15483
|
+
//#region src/features/checks/goose-check.ts
|
|
15484
|
+
const GooseCheckFrontmatterSchema = zod_mini.z.extend(AmpCheckFrontmatterSchema, {
|
|
15485
|
+
model: zod_mini.z.optional(zod_mini.z.string()),
|
|
15486
|
+
"turn-limit": zod_mini.z.optional(zod_mini.z.int().check(zod_mini.z.nonnegative()))
|
|
15487
|
+
});
|
|
15488
|
+
/**
|
|
15489
|
+
* Represents a Goose review check (`goose review`), written to the user-wide
|
|
15490
|
+
* `~/.config/goose/checks/` (global scope only).
|
|
15491
|
+
*
|
|
15492
|
+
* Goose discovers repository checks in `.agents/checks/*.md`, the same
|
|
15493
|
+
* cross-tool directory the `amp` checks target already writes (Goose's
|
|
15494
|
+
* `tools` and `severity-default` fields exist for parity with Amp's), so the
|
|
15495
|
+
* project scope is left to `amp` rather than having two targets own the same
|
|
15496
|
+
* files. Its global discovery reads `~/.config/goose/checks/` first, then
|
|
15497
|
+
* `~/.config/agents/checks/`. The file format is Amp's, so this class reuses
|
|
15498
|
+
* `AmpCheck` and adds Goose's `model` and `turn-limit`, which live in the
|
|
15499
|
+
* `goose:` section of a rulesync check; `name` is derived from the file name.
|
|
15500
|
+
*
|
|
15501
|
+
* @see https://github.com/aaif-goose/goose/blob/main/crates/goose/src/checks/mod.rs
|
|
15502
|
+
*/
|
|
15503
|
+
var GooseCheck = class extends AmpCheck {
|
|
15504
|
+
static getCheckToolTarget() {
|
|
15505
|
+
return "goose";
|
|
15506
|
+
}
|
|
15507
|
+
static getFrontmatterSchema() {
|
|
15508
|
+
return GooseCheckFrontmatterSchema;
|
|
15509
|
+
}
|
|
15510
|
+
static getToolOnlyKeys() {
|
|
15511
|
+
return ["model", "turn-limit"];
|
|
15512
|
+
}
|
|
15513
|
+
static getSettablePaths({ global = false } = {}) {
|
|
15514
|
+
return { relativeDirPath: global ? GOOSE_CHECKS_GLOBAL_DIR : GOOSE_CHECKS_PROJECT_DIR };
|
|
15515
|
+
}
|
|
15516
|
+
};
|
|
15517
|
+
//#endregion
|
|
15436
15518
|
//#region src/constants/hermesagent-paths.ts
|
|
15437
15519
|
/**
|
|
15438
15520
|
* Hermes Agent configuration-layout conventions.
|
|
@@ -16161,6 +16243,14 @@ const toolCheckFactories = /* @__PURE__ */ new Map([
|
|
|
16161
16243
|
committedOutput: true
|
|
16162
16244
|
}
|
|
16163
16245
|
}],
|
|
16246
|
+
["goose", {
|
|
16247
|
+
class: GooseCheck,
|
|
16248
|
+
meta: {
|
|
16249
|
+
supportsGlobal: true,
|
|
16250
|
+
supportsProject: false,
|
|
16251
|
+
filePattern: "*.md"
|
|
16252
|
+
}
|
|
16253
|
+
}],
|
|
16164
16254
|
["hermesagent", {
|
|
16165
16255
|
class: HermesagentCheck,
|
|
16166
16256
|
meta: {
|
|
@@ -16206,7 +16296,9 @@ const defaultGetFactory$6 = (target) => {
|
|
|
16206
16296
|
return factory;
|
|
16207
16297
|
};
|
|
16208
16298
|
const allToolTargetKeys$5 = [...toolCheckFactories.keys()];
|
|
16209
|
-
const checksProcessorToolTargets = allToolTargetKeys$5
|
|
16299
|
+
const checksProcessorToolTargets = allToolTargetKeys$5.filter((target) => {
|
|
16300
|
+
return toolCheckFactories.get(target)?.meta.supportsProject !== false;
|
|
16301
|
+
});
|
|
16210
16302
|
const checksProcessorToolTargetsGlobal = allToolTargetKeys$5.filter((target) => {
|
|
16211
16303
|
return toolCheckFactories.get(target)?.meta.supportsGlobal ?? false;
|
|
16212
16304
|
});
|
|
@@ -16377,23 +16469,6 @@ var ChecksProcessor = class extends FeatureProcessor {
|
|
|
16377
16469
|
}
|
|
16378
16470
|
};
|
|
16379
16471
|
//#endregion
|
|
16380
|
-
//#region src/constants/goose-paths.ts
|
|
16381
|
-
const GOOSE_DIR = ".goose";
|
|
16382
|
-
const GOOSE_GLOBAL_DIR = (0, node_path.join)(".config", "goose");
|
|
16383
|
-
const GOOSE_RULE_FILE_NAME = ".goosehints";
|
|
16384
|
-
const GOOSE_MCP_FILE_NAME = "config.yaml";
|
|
16385
|
-
const GOOSE_PERMISSIONS_FILE_NAME = "permission.yaml";
|
|
16386
|
-
const GOOSE_HOOKS_DIR_PATH = (0, node_path.join)(".agents", "plugins", "rulesync", "hooks");
|
|
16387
|
-
const GOOSE_HOOKS_FILE_NAME = "hooks.json";
|
|
16388
|
-
const GOOSE_PLUGIN_MCP_DIR_PATH = (0, node_path.join)(".agents", "plugins", "rulesync");
|
|
16389
|
-
const GOOSE_PLUGIN_MCP_FILE_NAME = ".mcp.json";
|
|
16390
|
-
const GOOSE_SKILLS_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "skills");
|
|
16391
|
-
const GOOSE_GLOBAL_SKILLS_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "skills");
|
|
16392
|
-
const GOOSE_RECIPES_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "recipes");
|
|
16393
|
-
const GOOSE_GLOBAL_RECIPES_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "recipes");
|
|
16394
|
-
const GOOSE_AGENTS_DIR_PATH = (0, node_path.join)(GOOSE_DIR, "agents");
|
|
16395
|
-
const GOOSE_GLOBAL_AGENTS_DIR_PATH = (0, node_path.join)(GOOSE_GLOBAL_DIR, "agents");
|
|
16396
|
-
//#endregion
|
|
16397
16472
|
//#region src/utils/tool-home.ts
|
|
16398
16473
|
/**
|
|
16399
16474
|
* Where the rulesync-side source files of a tool with a home override belong.
|
|
@@ -18115,27 +18190,71 @@ const CLINE_HOOKS_GLOBAL_DIR_PATH = (0, node_path.join)("Documents", "Cline", "H
|
|
|
18115
18190
|
const CLINE_HOOKS_MANIFEST_FILE_NAME = "rulesync-hooks.json";
|
|
18116
18191
|
//#endregion
|
|
18117
18192
|
//#region src/features/commands/cline-command.ts
|
|
18193
|
+
const CLINE_WORKFLOW_FIELD_TYPES = {
|
|
18194
|
+
name: "string",
|
|
18195
|
+
disabled: "boolean",
|
|
18196
|
+
enabled: "boolean"
|
|
18197
|
+
};
|
|
18198
|
+
function sanitizeClineWorkflowFrontmatter({ cline, relativeFilePath, logger }) {
|
|
18199
|
+
if (!isRecord$1(cline)) return {};
|
|
18200
|
+
return Object.fromEntries(Object.entries(cline).filter(([key, value]) => {
|
|
18201
|
+
const expected = Object.hasOwn(CLINE_WORKFLOW_FIELD_TYPES, key) ? CLINE_WORKFLOW_FIELD_TYPES[key] : void 0;
|
|
18202
|
+
if (expected === void 0 || typeof value === expected) return true;
|
|
18203
|
+
warnWithFallback(logger, `Cline commands: dropping cline.${key} from ${relativeFilePath}: Cline rejects the whole workflow unless it is a ${expected}.`);
|
|
18204
|
+
return false;
|
|
18205
|
+
}));
|
|
18206
|
+
}
|
|
18207
|
+
/**
|
|
18208
|
+
* Cline workflows (commands). A workflow may carry YAML frontmatter that Cline
|
|
18209
|
+
* reads: `name` (the slash-command name) and a `disabled` / `enabled` switch
|
|
18210
|
+
* (`parseWorkflowConfigFromMarkdown` in Cline's
|
|
18211
|
+
* `user-instruction-config-loader.ts`). The `cline:` section of a
|
|
18212
|
+
* `.rulesync/commands/*.md` file is written as that frontmatter, and every key
|
|
18213
|
+
* of an imported workflow's frontmatter is lifted back into `cline:`, so
|
|
18214
|
+
* hand-written workflow frontmatter survives an import → generate round trip.
|
|
18215
|
+
* Cline's own UI toggle is kept in Cline's state, not in the file. A workflow
|
|
18216
|
+
* without a `cline:` section is written as a bare body, as before.
|
|
18217
|
+
*
|
|
18218
|
+
* @see https://github.com/cline/cline/blob/main/sdk/packages/core/src/extensions/config/user-instruction-config-loader.ts
|
|
18219
|
+
*/
|
|
18118
18220
|
var ClineCommand = class ClineCommand extends ToolCommand {
|
|
18119
18221
|
static getSettablePaths({ global } = {}) {
|
|
18120
18222
|
if (global) return { relativeDirPath: CLINE_COMMANDS_GLOBAL_DIR_PATH };
|
|
18121
18223
|
return { relativeDirPath: CLINE_COMMANDS_DIR_PATH };
|
|
18122
18224
|
}
|
|
18225
|
+
/** The workflow's own frontmatter, or an empty object for a bare body. */
|
|
18226
|
+
getClineFrontmatter() {
|
|
18227
|
+
const { frontmatter } = parseFrontmatter(this.getFileContent(), this.getFilePath());
|
|
18228
|
+
return isRecord$1(frontmatter) ? frontmatter : {};
|
|
18229
|
+
}
|
|
18123
18230
|
toRulesyncCommand() {
|
|
18231
|
+
const cline = this.getClineFrontmatter();
|
|
18232
|
+
const rulesyncFrontmatter = {
|
|
18233
|
+
targets: ["*"],
|
|
18234
|
+
...Object.keys(cline).length > 0 && { cline }
|
|
18235
|
+
};
|
|
18236
|
+
const body = this.getBody();
|
|
18124
18237
|
return new RulesyncCommand({
|
|
18125
18238
|
outputRoot: process.cwd(),
|
|
18126
|
-
frontmatter:
|
|
18127
|
-
body
|
|
18239
|
+
frontmatter: rulesyncFrontmatter,
|
|
18240
|
+
body,
|
|
18128
18241
|
relativeDirPath: RulesyncCommand.getSettablePaths().relativeDirPath,
|
|
18129
18242
|
relativeFilePath: this.relativeFilePath,
|
|
18130
|
-
fileContent:
|
|
18243
|
+
fileContent: stringifyFrontmatter(body, rulesyncFrontmatter),
|
|
18131
18244
|
validate: true
|
|
18132
18245
|
});
|
|
18133
18246
|
}
|
|
18134
|
-
static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
|
|
18247
|
+
static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false, logger }) {
|
|
18135
18248
|
const paths = this.getSettablePaths({ global });
|
|
18249
|
+
const cline = sanitizeClineWorkflowFrontmatter({
|
|
18250
|
+
cline: rulesyncCommand.getFrontmatter().cline,
|
|
18251
|
+
relativeFilePath: rulesyncCommand.getRelativeFilePath(),
|
|
18252
|
+
logger
|
|
18253
|
+
});
|
|
18254
|
+
const body = rulesyncCommand.getBody();
|
|
18136
18255
|
return new ClineCommand({
|
|
18137
18256
|
outputRoot,
|
|
18138
|
-
fileContent:
|
|
18257
|
+
fileContent: Object.keys(cline).length > 0 ? stringifyFrontmatter(body, cline) : body,
|
|
18139
18258
|
relativeDirPath: paths.relativeDirPath,
|
|
18140
18259
|
relativeFilePath: rulesyncCommand.getRelativeFilePath(),
|
|
18141
18260
|
validate
|
|
@@ -18148,7 +18267,7 @@ var ClineCommand = class ClineCommand extends ToolCommand {
|
|
|
18148
18267
|
};
|
|
18149
18268
|
}
|
|
18150
18269
|
getBody() {
|
|
18151
|
-
return this.getFileContent();
|
|
18270
|
+
return parseFrontmatter(this.getFileContent(), this.getFilePath()).body.trim();
|
|
18152
18271
|
}
|
|
18153
18272
|
static isTargetedByRulesyncCommand(rulesyncCommand) {
|
|
18154
18273
|
return this.isTargetedByRulesyncCommandDefault({
|
|
@@ -18159,12 +18278,13 @@ var ClineCommand = class ClineCommand extends ToolCommand {
|
|
|
18159
18278
|
static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true, global = false }) {
|
|
18160
18279
|
const paths = this.getSettablePaths({ global });
|
|
18161
18280
|
const filePath = (0, node_path.join)(outputRoot, paths.relativeDirPath, relativeFilePath);
|
|
18162
|
-
const { body
|
|
18281
|
+
const { frontmatter, body } = parseFrontmatter(await readFileContent(filePath), filePath);
|
|
18282
|
+
const cline = isRecord$1(frontmatter) ? frontmatter : {};
|
|
18163
18283
|
return new ClineCommand({
|
|
18164
18284
|
outputRoot,
|
|
18165
18285
|
relativeDirPath: paths.relativeDirPath,
|
|
18166
18286
|
relativeFilePath,
|
|
18167
|
-
fileContent:
|
|
18287
|
+
fileContent: Object.keys(cline).length > 0 ? stringifyFrontmatter(body.trim(), cline) : body.trim(),
|
|
18168
18288
|
validate
|
|
18169
18289
|
});
|
|
18170
18290
|
}
|
|
@@ -40544,6 +40664,35 @@ function convertFromCodexFormat(codexMcp) {
|
|
|
40544
40664
|
}
|
|
40545
40665
|
return result;
|
|
40546
40666
|
}
|
|
40667
|
+
/**
|
|
40668
|
+
* Keys Codex refuses on each transport. Its `McpServerConfig` deserializer
|
|
40669
|
+
* calls `throw_if_set` for these, and the error fails the whole `config.toml`,
|
|
40670
|
+
* not just the one server, so they are dropped with a warning instead of
|
|
40671
|
+
* written. Checked against `codex-rs/config/src/mcp_types.rs` at rust-v0.162.1.
|
|
40672
|
+
*/
|
|
40673
|
+
const CODEX_STDIO_REJECTED_KEYS = [
|
|
40674
|
+
"url",
|
|
40675
|
+
"bearer_token_env_var",
|
|
40676
|
+
"bearer_token",
|
|
40677
|
+
"http_headers_helper",
|
|
40678
|
+
"http_headers",
|
|
40679
|
+
"env_http_headers",
|
|
40680
|
+
"oauth",
|
|
40681
|
+
"oauth_resource",
|
|
40682
|
+
"auth"
|
|
40683
|
+
];
|
|
40684
|
+
const CODEX_HTTP_REJECTED_KEYS = [
|
|
40685
|
+
"args",
|
|
40686
|
+
"env",
|
|
40687
|
+
"env_vars",
|
|
40688
|
+
"cwd",
|
|
40689
|
+
"bearer_token"
|
|
40690
|
+
];
|
|
40691
|
+
function dropTransportRejectedKeys({ converted, isStdio, serverName }) {
|
|
40692
|
+
const dropped = (isStdio ? CODEX_STDIO_REJECTED_KEYS : CODEX_HTTP_REJECTED_KEYS).filter((key) => converted[key] !== void 0);
|
|
40693
|
+
for (const key of dropped) delete converted[key];
|
|
40694
|
+
if (dropped.length > 0) warnWithFallback(void 0, `[CodexCliMcp] Dropping ${dropped.map((key) => `'${key}'`).join(", ")} from ${isStdio ? "stdio" : "url-based"} MCP server "${serverName}": Codex rejects ${dropped.length === 1 ? "this key" : "these keys"} on a ${isStdio ? "stdio" : "url-based"} server and would fail to load the whole config.toml.`);
|
|
40695
|
+
}
|
|
40547
40696
|
function convertToCodexFormat(mcpServers) {
|
|
40548
40697
|
const result = {};
|
|
40549
40698
|
const originalNames = /* @__PURE__ */ new Map();
|
|
@@ -40586,6 +40735,11 @@ function convertToCodexFormat(mcpServers) {
|
|
|
40586
40735
|
converted,
|
|
40587
40736
|
serverName: name
|
|
40588
40737
|
});
|
|
40738
|
+
dropTransportRejectedKeys({
|
|
40739
|
+
converted,
|
|
40740
|
+
isStdio,
|
|
40741
|
+
serverName: name
|
|
40742
|
+
});
|
|
40589
40743
|
const previousName = originalNames.get(codexName);
|
|
40590
40744
|
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}"; "${name}" (processed last) overwrites "${previousName}".`);
|
|
40591
40745
|
originalNames.set(codexName, name);
|
|
@@ -67806,10 +67960,15 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
|
|
|
67806
67960
|
outputRoot,
|
|
67807
67961
|
logger
|
|
67808
67962
|
});
|
|
67963
|
+
const inheritedProvider = global ? void 0 : await readGlobalTaktProvider({
|
|
67964
|
+
projectFilePath: filePath,
|
|
67965
|
+
logger
|
|
67966
|
+
});
|
|
67809
67967
|
const rulesyncJson = rulesyncPermissions.getJson();
|
|
67810
67968
|
const provider = resolveActiveProvider({
|
|
67811
67969
|
config,
|
|
67812
|
-
runtime: runtime.active ? runtime.config : void 0
|
|
67970
|
+
runtime: runtime.active ? runtime.config : void 0,
|
|
67971
|
+
inheritedProvider
|
|
67813
67972
|
});
|
|
67814
67973
|
const mode = deriveTaktPermissionMode(rulesyncJson);
|
|
67815
67974
|
const override = isPlainObject$1(rulesyncJson.takt) ? rulesyncJson.takt : void 0;
|
|
@@ -67919,10 +68078,12 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
|
|
|
67919
68078
|
* `provider_profiles` (unless that key is the pre-0.68.0 `claude` fallback),
|
|
67920
68079
|
* else the `claude-sdk` default (Takt 0.68.0+).
|
|
67921
68080
|
*/
|
|
67922
|
-
function resolveActiveProvider({ config, runtime }) {
|
|
68081
|
+
function resolveActiveProvider({ config, runtime, inheritedProvider }) {
|
|
67923
68082
|
const fromRuntime = runtime === void 0 ? void 0 : resolveRuntimeProvider(runtime);
|
|
67924
68083
|
if (fromRuntime !== void 0) return fromRuntime;
|
|
67925
|
-
|
|
68084
|
+
const local = readProviderName(config);
|
|
68085
|
+
if (local !== void 0) return local;
|
|
68086
|
+
if (inheritedProvider !== void 0) return inheritedProvider;
|
|
67926
68087
|
const profiles = config[TAKT_PROVIDER_PROFILES_KEY];
|
|
67927
68088
|
if (isPlainObject$1(profiles)) {
|
|
67928
68089
|
const keys = Object.keys(profiles);
|
|
@@ -67930,6 +68091,43 @@ function resolveActiveProvider({ config, runtime }) {
|
|
|
67930
68091
|
}
|
|
67931
68092
|
return TAKT_DEFAULT_PROVIDER;
|
|
67932
68093
|
}
|
|
68094
|
+
/**
|
|
68095
|
+
* The top-level `provider:` of a Takt `config.yaml`, when it names one: either
|
|
68096
|
+
* the plain name or the block form `provider: { type: <name>, ... }` Takt also
|
|
68097
|
+
* accepts (`ConfigProviderReference`).
|
|
68098
|
+
*/
|
|
68099
|
+
function readProviderName(config) {
|
|
68100
|
+
const raw = config[TAKT_PROVIDER_KEY];
|
|
68101
|
+
const provider = isPlainObject$1(raw) ? raw.type : raw;
|
|
68102
|
+
return typeof provider === "string" && provider.trim() !== "" ? provider : void 0;
|
|
68103
|
+
}
|
|
68104
|
+
/**
|
|
68105
|
+
* The top-level `provider:` of the global `~/.takt/config.yaml`, read for a
|
|
68106
|
+
* project-scope generate. An unresolvable home directory, a missing or
|
|
68107
|
+
* unparsable file, or one that names no provider all mean "nothing inherited".
|
|
68108
|
+
*/
|
|
68109
|
+
async function readGlobalTaktProvider({ projectFilePath, logger }) {
|
|
68110
|
+
let globalPath;
|
|
68111
|
+
try {
|
|
68112
|
+
globalPath = (0, node_path.join)(getHomeDirectory(), TAKT_DIR, TAKT_CONFIG_FILE_NAME);
|
|
68113
|
+
} catch {
|
|
68114
|
+
return;
|
|
68115
|
+
}
|
|
68116
|
+
if (globalPath === projectFilePath) return;
|
|
68117
|
+
try {
|
|
68118
|
+
const content = await readFileContentOrNull(globalPath);
|
|
68119
|
+
if (content === null) return;
|
|
68120
|
+
return readProviderName(parseSharedConfig({
|
|
68121
|
+
format: "yaml",
|
|
68122
|
+
fileContent: content,
|
|
68123
|
+
filePath: globalPath,
|
|
68124
|
+
invalidRootPolicy: "error"
|
|
68125
|
+
}));
|
|
68126
|
+
} catch (error) {
|
|
68127
|
+
logger?.warn(`Takt permissions: could not read the provider from ${globalPath} (${formatError(error)}); falling back to the project config alone.`);
|
|
68128
|
+
return;
|
|
68129
|
+
}
|
|
68130
|
+
}
|
|
67933
68131
|
/** A plain object carrying at least one entry (Takt's "assignment" test). */
|
|
67934
68132
|
function hasEntries(value) {
|
|
67935
68133
|
return isPlainObject$1(value) && Object.keys(value).length > 0;
|