rulesync 9.6.2 → 9.7.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 +11 -1
- package/dist/cli/index.cjs +10 -21
- package/dist/cli/index.js +10 -21
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-rMBf0tf2.cjs → import-D5f_X4-A.cjs} +701 -246
- package/dist/{import-CUHHL2_P.js → import-DC9T1JlQ.js} +703 -247
- package/dist/import-DC9T1JlQ.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-CUHHL2_P.js.map +0 -1
|
@@ -8,6 +8,7 @@ import { intersection, kebabCase, uniq } from "es-toolkit";
|
|
|
8
8
|
import { globbySync } from "globby";
|
|
9
9
|
import { isDeepStrictEqual } from "node:util";
|
|
10
10
|
import * as smolToml from "smol-toml";
|
|
11
|
+
import { parse as parse$1, stringify } from "smol-toml";
|
|
11
12
|
import matter from "gray-matter";
|
|
12
13
|
import { YAMLException, dump, load } from "js-yaml";
|
|
13
14
|
import { omit } from "es-toolkit/object";
|
|
@@ -2677,6 +2678,13 @@ const CODEXCLI_MCP_FILE_NAME = "config.toml";
|
|
|
2677
2678
|
const CODEXCLI_RULE_FILE_NAME = "AGENTS.md";
|
|
2678
2679
|
const CODEXCLI_BASH_RULES_FILE_NAME = "rulesync.rules";
|
|
2679
2680
|
const CODEXCLI_OPENAI_YAML_RELATIVE_PATH = join("agents", "openai.yaml");
|
|
2681
|
+
const CODEXCLI_OVERRIDE_KEYS = [
|
|
2682
|
+
"approval_policy",
|
|
2683
|
+
"sandbox_mode",
|
|
2684
|
+
"sandbox_workspace_write",
|
|
2685
|
+
"apps",
|
|
2686
|
+
"approvals_reviewer"
|
|
2687
|
+
];
|
|
2680
2688
|
//#endregion
|
|
2681
2689
|
//#region src/features/commands/codexcli-command.ts
|
|
2682
2690
|
const CodexcliCommandFrontmatterSchema = z.looseObject({
|
|
@@ -4055,14 +4063,22 @@ function sanitizeSharedConfigValue(value) {
|
|
|
4055
4063
|
* root follows `invalidRootPolicy`. Syntax errors are wrapped with the file
|
|
4056
4064
|
* path when one is given.
|
|
4057
4065
|
*/
|
|
4058
|
-
function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy = "coerce-empty" }) {
|
|
4066
|
+
function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy = "coerce-empty", jsoncParseErrors = "tolerate" }) {
|
|
4059
4067
|
if (fileContent.trim() === "") return {};
|
|
4060
4068
|
const at = filePath === void 0 ? "" : ` at ${filePath}`;
|
|
4061
4069
|
let parsed;
|
|
4062
4070
|
try {
|
|
4063
4071
|
if (format === "yaml") parsed = loadYaml(fileContent);
|
|
4072
|
+
else if (format === "toml") parsed = parse$1(fileContent);
|
|
4064
4073
|
else if (format === "json") parsed = JSON.parse(fileContent);
|
|
4065
|
-
else
|
|
4074
|
+
else if (jsoncParseErrors === "error") {
|
|
4075
|
+
const errors = [];
|
|
4076
|
+
parsed = parse(fileContent, errors, { allowTrailingComma: true });
|
|
4077
|
+
if (errors.length > 0) {
|
|
4078
|
+
const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
|
|
4079
|
+
throw new Error(details);
|
|
4080
|
+
}
|
|
4081
|
+
} else parsed = parse(fileContent);
|
|
4066
4082
|
} catch (error) {
|
|
4067
4083
|
throw new Error(`Failed to parse shared config${at}: ${formatError(error)}`, { cause: error });
|
|
4068
4084
|
}
|
|
@@ -4076,13 +4092,15 @@ function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy =
|
|
|
4076
4092
|
/**
|
|
4077
4093
|
* Serialize a shared config document. YAML output always ends with exactly one
|
|
4078
4094
|
* newline; JSON output matches the 2-space `JSON.stringify` shape the JSON
|
|
4079
|
-
* writers have always emitted (no trailing newline)
|
|
4095
|
+
* writers have always emitted (no trailing newline); TOML output matches the
|
|
4096
|
+
* `smol-toml` `stringify` shape the TOML writers have always emitted.
|
|
4080
4097
|
*/
|
|
4081
4098
|
function stringifySharedConfig({ format, document }) {
|
|
4082
4099
|
if (format === "yaml") return dump(document, {
|
|
4083
4100
|
noRefs: true,
|
|
4084
4101
|
sortKeys: false
|
|
4085
4102
|
}).trimEnd() + "\n";
|
|
4103
|
+
if (format === "toml") return stringify(document);
|
|
4086
4104
|
return JSON.stringify(document, null, 2);
|
|
4087
4105
|
}
|
|
4088
4106
|
/**
|
|
@@ -4121,6 +4139,25 @@ function mergeSharedConfigDeep({ base, patch }) {
|
|
|
4121
4139
|
const CLAUDE_SETTINGS_SHARED_FILE_KEY = ".claude/settings.json";
|
|
4122
4140
|
const HERMES_CONFIG_SHARED_FILE_KEY = ".hermes/config.yaml";
|
|
4123
4141
|
const TAKT_CONFIG_SHARED_FILE_KEY = ".takt/config.yaml";
|
|
4142
|
+
const CODEXCLI_CONFIG_SHARED_FILE_KEY = ".codex/config.toml";
|
|
4143
|
+
const GROKCLI_CONFIG_SHARED_FILE_KEY = ".grok/config.toml";
|
|
4144
|
+
const VIBE_CONFIG_SHARED_FILE_KEY = ".vibe/config.toml";
|
|
4145
|
+
const REASONIX_PROJECT_CONFIG_SHARED_FILE_KEY = "reasonix.toml";
|
|
4146
|
+
const REASONIX_GLOBAL_CONFIG_SHARED_FILE_KEY = ".reasonix/config.toml";
|
|
4147
|
+
/**
|
|
4148
|
+
* Build the `SHARED_CONFIG_OWNERSHIP` lookup key from a tool's settable paths.
|
|
4149
|
+
* Mirrors `sharedFileKey` in `src/lib/shared-file-derive.ts` (kept separate so
|
|
4150
|
+
* feature classes don't pull the processor registry through this module and
|
|
4151
|
+
* create an import cycle); the ownership lock-step test keeps the two aligned.
|
|
4152
|
+
* Lets a tool whose file lives at a scope-dependent path (`.zed/settings.json`
|
|
4153
|
+
* vs `.config/zed/settings.json`) resolve its declaration from the settable
|
|
4154
|
+
* paths it already holds.
|
|
4155
|
+
*/
|
|
4156
|
+
const sharedConfigFileKey = ({ relativeDirPath, relativeFilePath }) => {
|
|
4157
|
+
const dir = relativeDirPath.replace(/\\/g, "/").replace(/\/$/, "");
|
|
4158
|
+
const file = relativeFilePath.replace(/\\/g, "/");
|
|
4159
|
+
return dir === "" || dir === "." ? file : `${dir}/${file}`;
|
|
4160
|
+
};
|
|
4124
4161
|
/**
|
|
4125
4162
|
* Who owns what in each gateway-managed shared config file, and which policy
|
|
4126
4163
|
* resolves conflicts. Keys are `dir/file` tokens matching
|
|
@@ -4177,6 +4214,298 @@ const SHARED_CONFIG_OWNERSHIP = {
|
|
|
4177
4214
|
},
|
|
4178
4215
|
permissions: { kind: "deep-merge" }
|
|
4179
4216
|
}
|
|
4217
|
+
},
|
|
4218
|
+
".zed/settings.json": {
|
|
4219
|
+
format: "json",
|
|
4220
|
+
features: {
|
|
4221
|
+
ignore: {
|
|
4222
|
+
kind: "replace-owned-keys",
|
|
4223
|
+
ownedKeys: ["private_files"]
|
|
4224
|
+
},
|
|
4225
|
+
mcp: {
|
|
4226
|
+
kind: "replace-owned-keys",
|
|
4227
|
+
ownedKeys: ["context_servers"]
|
|
4228
|
+
},
|
|
4229
|
+
permissions: {
|
|
4230
|
+
kind: "replace-owned-keys",
|
|
4231
|
+
ownedKeys: ["agent"]
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
},
|
|
4235
|
+
".config/zed/settings.json": {
|
|
4236
|
+
format: "json",
|
|
4237
|
+
features: {
|
|
4238
|
+
mcp: {
|
|
4239
|
+
kind: "replace-owned-keys",
|
|
4240
|
+
ownedKeys: ["context_servers"]
|
|
4241
|
+
},
|
|
4242
|
+
permissions: {
|
|
4243
|
+
kind: "replace-owned-keys",
|
|
4244
|
+
ownedKeys: ["agent"]
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
},
|
|
4248
|
+
".qwen/settings.json": {
|
|
4249
|
+
format: "json",
|
|
4250
|
+
features: {
|
|
4251
|
+
mcp: {
|
|
4252
|
+
kind: "replace-owned-keys",
|
|
4253
|
+
ownedKeys: ["mcpServers"]
|
|
4254
|
+
},
|
|
4255
|
+
hooks: {
|
|
4256
|
+
kind: "replace-owned-keys",
|
|
4257
|
+
ownedKeys: ["hooks", "disableAllHooks"]
|
|
4258
|
+
},
|
|
4259
|
+
permissions: {
|
|
4260
|
+
kind: "replace-owned-keys",
|
|
4261
|
+
ownedKeys: [
|
|
4262
|
+
"permissions",
|
|
4263
|
+
"tools",
|
|
4264
|
+
"security"
|
|
4265
|
+
]
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
},
|
|
4269
|
+
".augment/settings.json": {
|
|
4270
|
+
format: "json",
|
|
4271
|
+
features: {
|
|
4272
|
+
mcp: {
|
|
4273
|
+
kind: "replace-owned-keys",
|
|
4274
|
+
ownedKeys: ["mcpServers"]
|
|
4275
|
+
},
|
|
4276
|
+
hooks: {
|
|
4277
|
+
kind: "replace-owned-keys",
|
|
4278
|
+
ownedKeys: ["hooks"]
|
|
4279
|
+
},
|
|
4280
|
+
permissions: {
|
|
4281
|
+
kind: "replace-owned-keys",
|
|
4282
|
+
ownedKeys: ["toolPermissions"]
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4286
|
+
".devin/config.json": {
|
|
4287
|
+
format: "json",
|
|
4288
|
+
features: {
|
|
4289
|
+
mcp: {
|
|
4290
|
+
kind: "replace-owned-keys",
|
|
4291
|
+
ownedKeys: ["mcpServers"]
|
|
4292
|
+
},
|
|
4293
|
+
permissions: {
|
|
4294
|
+
kind: "replace-owned-keys",
|
|
4295
|
+
ownedKeys: ["permissions"]
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
},
|
|
4299
|
+
".config/devin/config.json": {
|
|
4300
|
+
format: "json",
|
|
4301
|
+
features: {
|
|
4302
|
+
mcp: {
|
|
4303
|
+
kind: "replace-owned-keys",
|
|
4304
|
+
ownedKeys: ["mcpServers"]
|
|
4305
|
+
},
|
|
4306
|
+
hooks: {
|
|
4307
|
+
kind: "replace-owned-keys",
|
|
4308
|
+
ownedKeys: ["hooks"]
|
|
4309
|
+
},
|
|
4310
|
+
permissions: {
|
|
4311
|
+
kind: "replace-owned-keys",
|
|
4312
|
+
ownedKeys: ["permissions"]
|
|
4313
|
+
}
|
|
4314
|
+
}
|
|
4315
|
+
},
|
|
4316
|
+
".kiro/agents/default.json": {
|
|
4317
|
+
format: "json",
|
|
4318
|
+
features: {
|
|
4319
|
+
hooks: {
|
|
4320
|
+
kind: "replace-owned-keys",
|
|
4321
|
+
ownedKeys: ["hooks"]
|
|
4322
|
+
},
|
|
4323
|
+
permissions: {
|
|
4324
|
+
kind: "replace-owned-keys",
|
|
4325
|
+
ownedKeys: ["allowedTools", "toolsSettings"]
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
},
|
|
4329
|
+
".amp/settings.json": {
|
|
4330
|
+
format: "jsonc",
|
|
4331
|
+
invalidRootPolicy: "error",
|
|
4332
|
+
jsoncParseErrors: "error",
|
|
4333
|
+
features: {
|
|
4334
|
+
mcp: {
|
|
4335
|
+
kind: "replace-owned-keys",
|
|
4336
|
+
ownedKeys: ["amp.mcpServers"]
|
|
4337
|
+
},
|
|
4338
|
+
permissions: {
|
|
4339
|
+
kind: "replace-owned-keys",
|
|
4340
|
+
ownedKeys: [
|
|
4341
|
+
"amp.tools.disable",
|
|
4342
|
+
"amp.permissions",
|
|
4343
|
+
"amp.guardedFiles.allowlist",
|
|
4344
|
+
"amp.dangerouslyAllowAll",
|
|
4345
|
+
"amp.mcpPermissions"
|
|
4346
|
+
]
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
},
|
|
4350
|
+
".config/amp/settings.json": {
|
|
4351
|
+
format: "jsonc",
|
|
4352
|
+
invalidRootPolicy: "error",
|
|
4353
|
+
jsoncParseErrors: "error",
|
|
4354
|
+
features: {
|
|
4355
|
+
mcp: {
|
|
4356
|
+
kind: "replace-owned-keys",
|
|
4357
|
+
ownedKeys: ["amp.mcpServers"]
|
|
4358
|
+
},
|
|
4359
|
+
permissions: {
|
|
4360
|
+
kind: "replace-owned-keys",
|
|
4361
|
+
ownedKeys: [
|
|
4362
|
+
"amp.tools.disable",
|
|
4363
|
+
"amp.permissions",
|
|
4364
|
+
"amp.guardedFiles.allowlist",
|
|
4365
|
+
"amp.dangerouslyAllowAll",
|
|
4366
|
+
"amp.mcpPermissions"
|
|
4367
|
+
]
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
},
|
|
4371
|
+
"opencode.json": {
|
|
4372
|
+
format: "jsonc",
|
|
4373
|
+
features: {
|
|
4374
|
+
mcp: {
|
|
4375
|
+
kind: "replace-owned-keys",
|
|
4376
|
+
ownedKeys: ["mcp", "tools"]
|
|
4377
|
+
},
|
|
4378
|
+
permissions: {
|
|
4379
|
+
kind: "replace-owned-keys",
|
|
4380
|
+
ownedKeys: ["permission"]
|
|
4381
|
+
},
|
|
4382
|
+
rules: {
|
|
4383
|
+
kind: "replace-owned-keys",
|
|
4384
|
+
ownedKeys: ["instructions"]
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
},
|
|
4388
|
+
".config/opencode/opencode.json": {
|
|
4389
|
+
format: "jsonc",
|
|
4390
|
+
features: {
|
|
4391
|
+
mcp: {
|
|
4392
|
+
kind: "replace-owned-keys",
|
|
4393
|
+
ownedKeys: ["mcp", "tools"]
|
|
4394
|
+
},
|
|
4395
|
+
permissions: {
|
|
4396
|
+
kind: "replace-owned-keys",
|
|
4397
|
+
ownedKeys: ["permission"]
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
},
|
|
4401
|
+
"kilo.json": {
|
|
4402
|
+
format: "jsonc",
|
|
4403
|
+
features: {
|
|
4404
|
+
mcp: {
|
|
4405
|
+
kind: "replace-owned-keys",
|
|
4406
|
+
ownedKeys: ["mcp", "tools"]
|
|
4407
|
+
},
|
|
4408
|
+
rules: {
|
|
4409
|
+
kind: "replace-owned-keys",
|
|
4410
|
+
ownedKeys: ["instructions"]
|
|
4411
|
+
}
|
|
4412
|
+
}
|
|
4413
|
+
},
|
|
4414
|
+
".config/kilo/kilo.json": {
|
|
4415
|
+
format: "jsonc",
|
|
4416
|
+
features: { mcp: {
|
|
4417
|
+
kind: "replace-owned-keys",
|
|
4418
|
+
ownedKeys: ["mcp", "tools"]
|
|
4419
|
+
} }
|
|
4420
|
+
},
|
|
4421
|
+
[CODEXCLI_CONFIG_SHARED_FILE_KEY]: {
|
|
4422
|
+
format: "toml",
|
|
4423
|
+
features: {
|
|
4424
|
+
hooks: {
|
|
4425
|
+
kind: "replace-owned-keys",
|
|
4426
|
+
ownedKeys: ["features"]
|
|
4427
|
+
},
|
|
4428
|
+
mcp: {
|
|
4429
|
+
kind: "replace-owned-keys",
|
|
4430
|
+
ownedKeys: ["mcp_servers"]
|
|
4431
|
+
},
|
|
4432
|
+
permissions: {
|
|
4433
|
+
kind: "replace-owned-keys",
|
|
4434
|
+
ownedKeys: [
|
|
4435
|
+
"permissions",
|
|
4436
|
+
"default_permissions",
|
|
4437
|
+
...CODEXCLI_OVERRIDE_KEYS
|
|
4438
|
+
]
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
},
|
|
4442
|
+
[GROKCLI_CONFIG_SHARED_FILE_KEY]: {
|
|
4443
|
+
format: "toml",
|
|
4444
|
+
features: {
|
|
4445
|
+
mcp: {
|
|
4446
|
+
kind: "replace-owned-keys",
|
|
4447
|
+
ownedKeys: ["mcp_servers"]
|
|
4448
|
+
},
|
|
4449
|
+
permissions: {
|
|
4450
|
+
kind: "replace-owned-keys",
|
|
4451
|
+
ownedKeys: ["permission", "ui"]
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
},
|
|
4455
|
+
[VIBE_CONFIG_SHARED_FILE_KEY]: {
|
|
4456
|
+
format: "toml",
|
|
4457
|
+
features: {
|
|
4458
|
+
hooks: {
|
|
4459
|
+
kind: "replace-owned-keys",
|
|
4460
|
+
ownedKeys: ["enable_experimental_hooks"]
|
|
4461
|
+
},
|
|
4462
|
+
mcp: {
|
|
4463
|
+
kind: "replace-owned-keys",
|
|
4464
|
+
ownedKeys: ["mcp_servers"]
|
|
4465
|
+
},
|
|
4466
|
+
permissions: {
|
|
4467
|
+
kind: "replace-owned-keys",
|
|
4468
|
+
ownedKeys: [
|
|
4469
|
+
"tools",
|
|
4470
|
+
"enabled_tools",
|
|
4471
|
+
"disabled_tools"
|
|
4472
|
+
]
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
},
|
|
4476
|
+
[REASONIX_PROJECT_CONFIG_SHARED_FILE_KEY]: {
|
|
4477
|
+
format: "toml",
|
|
4478
|
+
features: {
|
|
4479
|
+
mcp: {
|
|
4480
|
+
kind: "replace-owned-keys",
|
|
4481
|
+
ownedKeys: ["plugins"]
|
|
4482
|
+
},
|
|
4483
|
+
permissions: {
|
|
4484
|
+
kind: "replace-owned-keys",
|
|
4485
|
+
ownedKeys: [
|
|
4486
|
+
"permissions",
|
|
4487
|
+
"sandbox",
|
|
4488
|
+
"agent"
|
|
4489
|
+
]
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
},
|
|
4493
|
+
[REASONIX_GLOBAL_CONFIG_SHARED_FILE_KEY]: {
|
|
4494
|
+
format: "toml",
|
|
4495
|
+
features: {
|
|
4496
|
+
mcp: {
|
|
4497
|
+
kind: "replace-owned-keys",
|
|
4498
|
+
ownedKeys: ["plugins"]
|
|
4499
|
+
},
|
|
4500
|
+
permissions: {
|
|
4501
|
+
kind: "replace-owned-keys",
|
|
4502
|
+
ownedKeys: [
|
|
4503
|
+
"permissions",
|
|
4504
|
+
"sandbox",
|
|
4505
|
+
"agent"
|
|
4506
|
+
]
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4180
4509
|
}
|
|
4181
4510
|
};
|
|
4182
4511
|
/**
|
|
@@ -4197,17 +4526,20 @@ function applySharedConfigPatch({ fileKey, feature, existingContent, patch, file
|
|
|
4197
4526
|
format: declaration.format,
|
|
4198
4527
|
fileContent: existingContent,
|
|
4199
4528
|
filePath,
|
|
4200
|
-
...declaration.invalidRootPolicy !== void 0 && { invalidRootPolicy: declaration.invalidRootPolicy }
|
|
4529
|
+
...declaration.invalidRootPolicy !== void 0 && { invalidRootPolicy: declaration.invalidRootPolicy },
|
|
4530
|
+
...declaration.jsoncParseErrors !== void 0 && { jsoncParseErrors: declaration.jsoncParseErrors }
|
|
4201
4531
|
});
|
|
4202
4532
|
if (policy.kind === "replace-owned-keys") {
|
|
4203
4533
|
const unowned = Object.keys(patch).filter((key) => !policy.ownedKeys.includes(key));
|
|
4204
4534
|
if (unowned.length > 0) throw new Error(`Feature '${feature}' tried to write undeclared keys [${unowned.join(", ")}] to '${fileKey}'; extend its ownedKeys declaration if that ownership is intended.`);
|
|
4535
|
+
const document = mergeSharedConfigShallow({
|
|
4536
|
+
base,
|
|
4537
|
+
patch
|
|
4538
|
+
});
|
|
4539
|
+
for (const [key, value] of Object.entries(patch)) if (value === void 0) delete document[key];
|
|
4205
4540
|
return stringifySharedConfig({
|
|
4206
4541
|
format: declaration.format,
|
|
4207
|
-
document
|
|
4208
|
-
base,
|
|
4209
|
-
patch
|
|
4210
|
-
})
|
|
4542
|
+
document
|
|
4211
4543
|
});
|
|
4212
4544
|
}
|
|
4213
4545
|
const merged = mergeSharedConfigDeep({
|
|
@@ -7280,12 +7612,6 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
7280
7612
|
const paths = AugmentcodeHooks.getSettablePaths({ global });
|
|
7281
7613
|
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
7282
7614
|
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
7283
|
-
let settings;
|
|
7284
|
-
try {
|
|
7285
|
-
settings = JSON.parse(existingContent);
|
|
7286
|
-
} catch (error) {
|
|
7287
|
-
throw new Error(`Failed to parse existing AugmentCode settings at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
7288
|
-
}
|
|
7289
7615
|
const config = rulesyncHooks.getJson();
|
|
7290
7616
|
const augmentHooks = canonicalToToolHooks({
|
|
7291
7617
|
config,
|
|
@@ -7293,11 +7619,13 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
7293
7619
|
converterConfig: AUGMENTCODE_CONVERTER_CONFIG,
|
|
7294
7620
|
logger
|
|
7295
7621
|
});
|
|
7296
|
-
const
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7622
|
+
const fileContent = applySharedConfigPatch({
|
|
7623
|
+
fileKey: sharedConfigFileKey(paths),
|
|
7624
|
+
feature: "hooks",
|
|
7625
|
+
existingContent,
|
|
7626
|
+
patch: { hooks: augmentHooks },
|
|
7627
|
+
filePath
|
|
7628
|
+
});
|
|
7301
7629
|
return new AugmentcodeHooks({
|
|
7302
7630
|
outputRoot,
|
|
7303
7631
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -7464,15 +7792,28 @@ const CODEXCLI_CONVERTER_CONFIG = {
|
|
|
7464
7792
|
*/
|
|
7465
7793
|
async function buildCodexConfigTomlContent({ outputRoot }) {
|
|
7466
7794
|
const configPath = join(outputRoot, CODEXCLI_DIR, CODEXCLI_MCP_FILE_NAME);
|
|
7467
|
-
const existingContent = await readFileContentOrNull(configPath) ??
|
|
7795
|
+
const existingContent = await readFileContentOrNull(configPath) ?? "";
|
|
7468
7796
|
let configToml;
|
|
7469
7797
|
try {
|
|
7470
|
-
configToml = smolToml.parse(existingContent);
|
|
7798
|
+
configToml = smolToml.parse(existingContent || smolToml.stringify({}));
|
|
7471
7799
|
} catch (error) {
|
|
7472
7800
|
throw new Error(`Failed to parse existing Codex CLI config at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
7473
7801
|
}
|
|
7474
|
-
|
|
7475
|
-
|
|
7802
|
+
let features;
|
|
7803
|
+
if (typeof configToml.features === "object" && configToml.features !== null) {
|
|
7804
|
+
features = { ...configToml.features };
|
|
7805
|
+
delete features.codex_hooks;
|
|
7806
|
+
}
|
|
7807
|
+
return applySharedConfigPatch({
|
|
7808
|
+
fileKey: sharedConfigFileKey({
|
|
7809
|
+
relativeDirPath: CODEXCLI_DIR,
|
|
7810
|
+
relativeFilePath: CODEXCLI_MCP_FILE_NAME
|
|
7811
|
+
}),
|
|
7812
|
+
feature: "hooks",
|
|
7813
|
+
existingContent,
|
|
7814
|
+
patch: { features },
|
|
7815
|
+
filePath: configPath
|
|
7816
|
+
});
|
|
7476
7817
|
}
|
|
7477
7818
|
/**
|
|
7478
7819
|
* Represents the `.codex/config.toml` file as a generated ToolFile,
|
|
@@ -8388,17 +8729,13 @@ var DevinHooks = class DevinHooks extends ToolHooks {
|
|
|
8388
8729
|
let fileContent;
|
|
8389
8730
|
if (global) {
|
|
8390
8731
|
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
...isRecord(parsedSettings) ? parsedSettings : {},
|
|
8399
|
-
hooks: devinHooks
|
|
8400
|
-
};
|
|
8401
|
-
fileContent = JSON.stringify(merged, null, 2);
|
|
8732
|
+
fileContent = applySharedConfigPatch({
|
|
8733
|
+
fileKey: sharedConfigFileKey(paths),
|
|
8734
|
+
feature: "hooks",
|
|
8735
|
+
existingContent,
|
|
8736
|
+
patch: { hooks: devinHooks },
|
|
8737
|
+
filePath
|
|
8738
|
+
});
|
|
8402
8739
|
} else {
|
|
8403
8740
|
await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
8404
8741
|
fileContent = JSON.stringify(devinHooks, null, 2);
|
|
@@ -9210,18 +9547,14 @@ var KiroHooks = class KiroHooks extends ToolHooks {
|
|
|
9210
9547
|
const paths = KiroHooks.getSettablePaths({ global });
|
|
9211
9548
|
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
9212
9549
|
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
9213
|
-
let agentConfig;
|
|
9214
|
-
try {
|
|
9215
|
-
agentConfig = JSON.parse(existingContent);
|
|
9216
|
-
} catch (error) {
|
|
9217
|
-
throw new Error(`Failed to parse existing Kiro agent config at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
9218
|
-
}
|
|
9219
9550
|
const kiroHooks = canonicalToKiroHooks(rulesyncHooks.getJson(), this.getOverrideKey());
|
|
9220
|
-
const
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9551
|
+
const fileContent = applySharedConfigPatch({
|
|
9552
|
+
fileKey: sharedConfigFileKey(paths),
|
|
9553
|
+
feature: "hooks",
|
|
9554
|
+
existingContent,
|
|
9555
|
+
patch: { hooks: kiroHooks },
|
|
9556
|
+
filePath
|
|
9557
|
+
});
|
|
9225
9558
|
return new KiroHooks({
|
|
9226
9559
|
outputRoot,
|
|
9227
9560
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -9716,21 +10049,17 @@ var QwencodeHooks = class QwencodeHooks extends ToolHooks {
|
|
|
9716
10049
|
const paths = QwencodeHooks.getSettablePaths({ global });
|
|
9717
10050
|
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
9718
10051
|
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
9719
|
-
let settings;
|
|
9720
|
-
try {
|
|
9721
|
-
settings = JSON.parse(existingContent);
|
|
9722
|
-
} catch (error) {
|
|
9723
|
-
throw new Error(`Failed to parse existing Qwen Code settings at ${filePath}: ${formatError(error)}`, { cause: error });
|
|
9724
|
-
}
|
|
9725
10052
|
const config = rulesyncHooks.getJson();
|
|
9726
|
-
const
|
|
9727
|
-
const merged = {
|
|
9728
|
-
...settings,
|
|
9729
|
-
hooks: qwencodeHooks
|
|
9730
|
-
};
|
|
10053
|
+
const patch = { hooks: canonicalToQwencodeHooks(config) };
|
|
9731
10054
|
const disableAllHooks = config.qwencode?.disableAllHooks;
|
|
9732
|
-
if (typeof disableAllHooks === "boolean")
|
|
9733
|
-
const fileContent =
|
|
10055
|
+
if (typeof disableAllHooks === "boolean") patch.disableAllHooks = disableAllHooks;
|
|
10056
|
+
const fileContent = applySharedConfigPatch({
|
|
10057
|
+
fileKey: sharedConfigFileKey(paths),
|
|
10058
|
+
feature: "hooks",
|
|
10059
|
+
existingContent,
|
|
10060
|
+
patch,
|
|
10061
|
+
filePath
|
|
10062
|
+
});
|
|
9734
10063
|
return new QwencodeHooks({
|
|
9735
10064
|
outputRoot,
|
|
9736
10065
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -9989,10 +10318,6 @@ function canonicalToVibeHooks(config, toolOverride) {
|
|
|
9989
10318
|
}
|
|
9990
10319
|
return { hooks };
|
|
9991
10320
|
}
|
|
9992
|
-
/**
|
|
9993
|
-
* Reverse {@link canonicalToVibeHooks}: parse the flat `[[hooks]]` array back
|
|
9994
|
-
* into a canonical event → definition[] record.
|
|
9995
|
-
*/
|
|
9996
10321
|
/** Convert one raw `[[hooks]]` entry to a canonical definition, or null to skip. */
|
|
9997
10322
|
function vibeEntryToCanonicalDef(raw) {
|
|
9998
10323
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -10012,6 +10337,10 @@ function vibeEntryToCanonicalDef(raw) {
|
|
|
10012
10337
|
def
|
|
10013
10338
|
};
|
|
10014
10339
|
}
|
|
10340
|
+
/**
|
|
10341
|
+
* Reverse {@link canonicalToVibeHooks}: parse the flat `[[hooks]]` array back
|
|
10342
|
+
* into a canonical event → definition[] record.
|
|
10343
|
+
*/
|
|
10015
10344
|
function vibeHooksToCanonical(parsed) {
|
|
10016
10345
|
const canonical = {};
|
|
10017
10346
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return canonical;
|
|
@@ -10040,15 +10369,22 @@ function parseVibeToml(fileContent) {
|
|
|
10040
10369
|
*/
|
|
10041
10370
|
async function buildVibeConfigTomlContent({ outputRoot }) {
|
|
10042
10371
|
const configPath = join(outputRoot, VIBE_DIR, VIBE_CONFIG_FILE_NAME);
|
|
10043
|
-
const existingContent = await readFileContentOrNull(configPath) ??
|
|
10044
|
-
let config;
|
|
10372
|
+
const existingContent = await readFileContentOrNull(configPath) ?? "";
|
|
10045
10373
|
try {
|
|
10046
|
-
|
|
10374
|
+
parseVibeToml(existingContent);
|
|
10047
10375
|
} catch (error) {
|
|
10048
10376
|
throw new Error(`Failed to parse existing Vibe config at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
10049
10377
|
}
|
|
10050
|
-
|
|
10051
|
-
|
|
10378
|
+
return applySharedConfigPatch({
|
|
10379
|
+
fileKey: sharedConfigFileKey({
|
|
10380
|
+
relativeDirPath: VIBE_DIR,
|
|
10381
|
+
relativeFilePath: VIBE_CONFIG_FILE_NAME
|
|
10382
|
+
}),
|
|
10383
|
+
feature: "hooks",
|
|
10384
|
+
existingContent,
|
|
10385
|
+
patch: { enable_experimental_hooks: true },
|
|
10386
|
+
filePath: configPath
|
|
10387
|
+
});
|
|
10052
10388
|
}
|
|
10053
10389
|
/**
|
|
10054
10390
|
* Represents the `.vibe/config.toml` file as a generated ToolFile so it goes
|
|
@@ -11548,17 +11884,18 @@ var ZedIgnore = class ZedIgnore extends ToolIgnore {
|
|
|
11548
11884
|
const patterns = rulesyncIgnore.getFileContent().split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
11549
11885
|
const filePath = join(outputRoot, this.getSettablePaths().relativeDirPath, this.getSettablePaths().relativeFilePath);
|
|
11550
11886
|
const existingFileContent = await fileExists(filePath) ? await readFileContent(filePath) : "{}";
|
|
11551
|
-
const
|
|
11552
|
-
const mergedPatterns = uniq([...existingJsonValue.private_files ?? [], ...patterns].toSorted());
|
|
11553
|
-
const jsonValue = {
|
|
11554
|
-
...existingJsonValue,
|
|
11555
|
-
private_files: mergedPatterns
|
|
11556
|
-
};
|
|
11887
|
+
const mergedPatterns = uniq([...JSON.parse(existingFileContent).private_files ?? [], ...patterns].toSorted());
|
|
11557
11888
|
return new ZedIgnore({
|
|
11558
11889
|
outputRoot,
|
|
11559
11890
|
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
11560
11891
|
relativeFilePath: this.getSettablePaths().relativeFilePath,
|
|
11561
|
-
fileContent:
|
|
11892
|
+
fileContent: applySharedConfigPatch({
|
|
11893
|
+
fileKey: sharedConfigFileKey(this.getSettablePaths()),
|
|
11894
|
+
feature: "ignore",
|
|
11895
|
+
existingContent: existingFileContent,
|
|
11896
|
+
patch: { private_files: mergedPatterns },
|
|
11897
|
+
filePath
|
|
11898
|
+
}),
|
|
11562
11899
|
validate: true
|
|
11563
11900
|
});
|
|
11564
11901
|
}
|
|
@@ -12015,17 +12352,17 @@ var AmpMcp = class AmpMcp extends ToolMcp {
|
|
|
12015
12352
|
const basePaths = this.getSettablePaths({ global });
|
|
12016
12353
|
const jsonDir = join(outputRoot, basePaths.relativeDirPath);
|
|
12017
12354
|
const { fileContent, relativeFilePath } = await this.resolveSettingsFile(jsonDir);
|
|
12018
|
-
const json = fileContent ? parseAmpSettingsJsonc(fileContent) : { [AMP_MCP_SERVERS_KEY]: {} };
|
|
12019
|
-
const filteredMcpServers = filterMcpServers(rulesyncMcp.getMcpServers());
|
|
12020
|
-
const newJson = {
|
|
12021
|
-
...json,
|
|
12022
|
-
[AMP_MCP_SERVERS_KEY]: filteredMcpServers
|
|
12023
|
-
};
|
|
12024
12355
|
return new AmpMcp({
|
|
12025
12356
|
outputRoot,
|
|
12026
12357
|
relativeDirPath: basePaths.relativeDirPath,
|
|
12027
12358
|
relativeFilePath,
|
|
12028
|
-
fileContent:
|
|
12359
|
+
fileContent: applySharedConfigPatch({
|
|
12360
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
12361
|
+
feature: "mcp",
|
|
12362
|
+
existingContent: fileContent ?? "",
|
|
12363
|
+
patch: { [AMP_MCP_SERVERS_KEY]: filterMcpServers(rulesyncMcp.getMcpServers()) },
|
|
12364
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
12365
|
+
}),
|
|
12029
12366
|
validate,
|
|
12030
12367
|
global
|
|
12031
12368
|
});
|
|
@@ -12312,15 +12649,19 @@ var AugmentcodeMcp = class AugmentcodeMcp extends ToolMcp {
|
|
|
12312
12649
|
}
|
|
12313
12650
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
12314
12651
|
const paths = this.getSettablePaths({ global });
|
|
12315
|
-
const
|
|
12316
|
-
|
|
12317
|
-
mcpServers: rulesyncMcp.getMcpServers()
|
|
12318
|
-
};
|
|
12652
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
12653
|
+
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({}, null, 2));
|
|
12319
12654
|
return new AugmentcodeMcp({
|
|
12320
12655
|
outputRoot,
|
|
12321
12656
|
relativeDirPath: paths.relativeDirPath,
|
|
12322
12657
|
relativeFilePath: paths.relativeFilePath,
|
|
12323
|
-
fileContent:
|
|
12658
|
+
fileContent: applySharedConfigPatch({
|
|
12659
|
+
fileKey: sharedConfigFileKey(paths),
|
|
12660
|
+
feature: "mcp",
|
|
12661
|
+
existingContent,
|
|
12662
|
+
patch: { mcpServers: rulesyncMcp.getMcpServers() },
|
|
12663
|
+
filePath
|
|
12664
|
+
}),
|
|
12324
12665
|
validate,
|
|
12325
12666
|
global
|
|
12326
12667
|
});
|
|
@@ -12617,6 +12958,13 @@ function mapOauthFromCodex(oauth) {
|
|
|
12617
12958
|
}
|
|
12618
12959
|
return result;
|
|
12619
12960
|
}
|
|
12961
|
+
const CODEX_MCP_SERVER_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
12962
|
+
function normalizeCodexMcpServerName(name) {
|
|
12963
|
+
if (PROTOTYPE_POLLUTION_KEYS.has(name)) return null;
|
|
12964
|
+
if (CODEX_MCP_SERVER_NAME_PATTERN.test(name)) return name;
|
|
12965
|
+
const normalizedName = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
12966
|
+
return normalizedName && !PROTOTYPE_POLLUTION_KEYS.has(normalizedName) ? normalizedName : null;
|
|
12967
|
+
}
|
|
12620
12968
|
function convertFromCodexFormat(codexMcp) {
|
|
12621
12969
|
const result = {};
|
|
12622
12970
|
for (const [name, config] of Object.entries(codexMcp)) {
|
|
@@ -12639,8 +12987,13 @@ function convertFromCodexFormat(codexMcp) {
|
|
|
12639
12987
|
}
|
|
12640
12988
|
function convertToCodexFormat(mcpServers) {
|
|
12641
12989
|
const result = {};
|
|
12990
|
+
const originalNames = /* @__PURE__ */ new Map();
|
|
12642
12991
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
12643
|
-
|
|
12992
|
+
const codexName = normalizeCodexMcpServerName(name);
|
|
12993
|
+
if (codexName === null) {
|
|
12994
|
+
warnWithFallback(void 0, `MCP server "${name}" could not be normalized to a valid Codex MCP server name and was skipped.`);
|
|
12995
|
+
continue;
|
|
12996
|
+
}
|
|
12644
12997
|
if (!isRecord(config)) continue;
|
|
12645
12998
|
const converted = {};
|
|
12646
12999
|
for (const [key, value] of Object.entries(config)) {
|
|
@@ -12654,7 +13007,10 @@ function convertToCodexFormat(mcpServers) {
|
|
|
12654
13007
|
else warnWithFallback(void 0, `[CodexCliMcp] Skipping invalid value type for mapped key '${key}': expected string array, got ${typeof value}`);
|
|
12655
13008
|
} else converted[key] = value;
|
|
12656
13009
|
}
|
|
12657
|
-
|
|
13010
|
+
const previousName = originalNames.get(codexName);
|
|
13011
|
+
if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}". Only the last processed server will be used.`);
|
|
13012
|
+
originalNames.set(codexName, name);
|
|
13013
|
+
result[codexName] = converted;
|
|
12658
13014
|
}
|
|
12659
13015
|
return result;
|
|
12660
13016
|
}
|
|
@@ -12699,8 +13055,9 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
12699
13055
|
}
|
|
12700
13056
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
12701
13057
|
const paths = this.getSettablePaths({ global });
|
|
12702
|
-
const
|
|
12703
|
-
const
|
|
13058
|
+
const configTomlFilePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
13059
|
+
const configTomlFileContent = await readFileContentOrNull(configTomlFilePath) ?? "";
|
|
13060
|
+
const configToml = smolToml.parse(configTomlFileContent || smolToml.stringify({}));
|
|
12704
13061
|
const strippedMcpServers = rulesyncMcp.getMcpServers();
|
|
12705
13062
|
const rawMcpServers = rulesyncMcp.getJson().mcpServers;
|
|
12706
13063
|
const converted = convertToCodexFormat(Object.fromEntries(Object.entries(strippedMcpServers).map(([serverName, serverConfig]) => {
|
|
@@ -12713,7 +13070,7 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
12713
13070
|
const filteredMcpServers = this.removeEmptyEntries(converted);
|
|
12714
13071
|
for (const name of Object.keys(converted)) if (!Object.hasOwn(filteredMcpServers, name)) warnWithFallback(void 0, `MCP server "${name}" had no non-empty configuration and was dropped from the codex CLI config`);
|
|
12715
13072
|
const existingMcpServers = isRecord(configToml["mcp_servers"]) ? configToml["mcp_servers"] : {};
|
|
12716
|
-
|
|
13073
|
+
const mergedMcpServers = Object.fromEntries(Object.entries(filteredMcpServers).map(([name, serverConfig]) => {
|
|
12717
13074
|
const existingServer = isRecord(existingMcpServers[name]) ? existingMcpServers[name] : void 0;
|
|
12718
13075
|
const serverRecord = serverConfig;
|
|
12719
13076
|
if (existingServer && isRecord(existingServer["tools"]) && !("tools" in serverRecord)) return [name, {
|
|
@@ -12726,7 +13083,13 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
|
|
|
12726
13083
|
outputRoot,
|
|
12727
13084
|
relativeDirPath: paths.relativeDirPath,
|
|
12728
13085
|
relativeFilePath: paths.relativeFilePath,
|
|
12729
|
-
fileContent:
|
|
13086
|
+
fileContent: applySharedConfigPatch({
|
|
13087
|
+
fileKey: sharedConfigFileKey(paths),
|
|
13088
|
+
feature: "mcp",
|
|
13089
|
+
existingContent: configTomlFileContent,
|
|
13090
|
+
patch: { mcp_servers: mergedMcpServers },
|
|
13091
|
+
filePath: configTomlFilePath
|
|
13092
|
+
}),
|
|
12730
13093
|
validate
|
|
12731
13094
|
});
|
|
12732
13095
|
}
|
|
@@ -13293,16 +13656,19 @@ var DevinMcp = class DevinMcp extends ToolMcp {
|
|
|
13293
13656
|
}
|
|
13294
13657
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
13295
13658
|
const paths = this.getSettablePaths({ global });
|
|
13296
|
-
const
|
|
13297
|
-
const
|
|
13298
|
-
...this.parseJsonOrThrow(fileContent, paths.relativeDirPath, paths.relativeFilePath),
|
|
13299
|
-
mcpServers: rulesyncMcp.getMcpServers()
|
|
13300
|
-
};
|
|
13659
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
13660
|
+
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({ mcpServers: {} }, null, 2));
|
|
13301
13661
|
return new DevinMcp({
|
|
13302
13662
|
outputRoot,
|
|
13303
13663
|
relativeDirPath: paths.relativeDirPath,
|
|
13304
13664
|
relativeFilePath: paths.relativeFilePath,
|
|
13305
|
-
fileContent:
|
|
13665
|
+
fileContent: applySharedConfigPatch({
|
|
13666
|
+
fileKey: sharedConfigFileKey(paths),
|
|
13667
|
+
feature: "mcp",
|
|
13668
|
+
existingContent,
|
|
13669
|
+
patch: { mcpServers: rulesyncMcp.getMcpServers() },
|
|
13670
|
+
filePath
|
|
13671
|
+
}),
|
|
13306
13672
|
validate,
|
|
13307
13673
|
global
|
|
13308
13674
|
});
|
|
@@ -13789,17 +14155,22 @@ var GrokcliMcp = class GrokcliMcp extends ToolMcp {
|
|
|
13789
14155
|
}
|
|
13790
14156
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
13791
14157
|
const paths = this.getSettablePaths({ global });
|
|
13792
|
-
const
|
|
13793
|
-
const
|
|
14158
|
+
const configTomlFilePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
14159
|
+
const configTomlFileContent = await readFileContentOrNull(configTomlFilePath) ?? "";
|
|
13794
14160
|
const converted = convertToGrokFormat(rulesyncMcp.getMcpServers());
|
|
13795
14161
|
const filteredMcpServers = this.removeEmptyEntries(converted);
|
|
13796
14162
|
for (const name of Object.keys(converted)) if (!Object.hasOwn(filteredMcpServers, name)) warnWithFallback(void 0, `MCP server "${name}" had no non-empty configuration and was dropped from the grok CLI config`);
|
|
13797
|
-
configToml["mcp_servers"] = filteredMcpServers;
|
|
13798
14163
|
return new GrokcliMcp({
|
|
13799
14164
|
outputRoot,
|
|
13800
14165
|
relativeDirPath: paths.relativeDirPath,
|
|
13801
14166
|
relativeFilePath: paths.relativeFilePath,
|
|
13802
|
-
fileContent:
|
|
14167
|
+
fileContent: applySharedConfigPatch({
|
|
14168
|
+
fileKey: sharedConfigFileKey(paths),
|
|
14169
|
+
feature: "mcp",
|
|
14170
|
+
existingContent: configTomlFileContent,
|
|
14171
|
+
patch: { mcp_servers: filteredMcpServers },
|
|
14172
|
+
filePath: configTomlFilePath
|
|
14173
|
+
}),
|
|
13803
14174
|
validate
|
|
13804
14175
|
});
|
|
13805
14176
|
}
|
|
@@ -14332,20 +14703,21 @@ var KiloMcp = class KiloMcp extends ToolMcp {
|
|
|
14332
14703
|
fileContent = await readFileContentOrNull(jsonPath);
|
|
14333
14704
|
if (fileContent) relativeFilePath = KILO_JSON_FILE_NAME;
|
|
14334
14705
|
}
|
|
14335
|
-
if (!fileContent) fileContent = JSON.stringify({ mcp: {} }, null, 2);
|
|
14336
|
-
const json = parse(fileContent);
|
|
14337
14706
|
const { mcp: convertedMcp, tools: mcpTools } = convertToKiloFormat(rulesyncMcp.getMcpServers());
|
|
14338
|
-
const { tools: _existingTools, ...jsonWithoutTools } = json;
|
|
14339
|
-
const newJson = {
|
|
14340
|
-
...jsonWithoutTools,
|
|
14341
|
-
mcp: convertedMcp,
|
|
14342
|
-
...Object.keys(mcpTools).length > 0 && { tools: mcpTools }
|
|
14343
|
-
};
|
|
14344
14707
|
return new KiloMcp({
|
|
14345
14708
|
outputRoot,
|
|
14346
14709
|
relativeDirPath: basePaths.relativeDirPath,
|
|
14347
14710
|
relativeFilePath,
|
|
14348
|
-
fileContent:
|
|
14711
|
+
fileContent: applySharedConfigPatch({
|
|
14712
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
14713
|
+
feature: "mcp",
|
|
14714
|
+
existingContent: fileContent ?? "",
|
|
14715
|
+
patch: {
|
|
14716
|
+
mcp: convertedMcp,
|
|
14717
|
+
tools: Object.keys(mcpTools).length > 0 ? mcpTools : void 0
|
|
14718
|
+
},
|
|
14719
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
14720
|
+
}),
|
|
14349
14721
|
validate
|
|
14350
14722
|
});
|
|
14351
14723
|
}
|
|
@@ -14374,15 +14746,17 @@ var KiloMcp = class KiloMcp extends ToolMcp {
|
|
|
14374
14746
|
const json = fileContent ? parse(fileContent) : {};
|
|
14375
14747
|
const existingInstructions = Array.isArray(json.instructions) ? json.instructions.filter((entry) => typeof entry === "string") : [];
|
|
14376
14748
|
const mergedInstructions = Array.from(/* @__PURE__ */ new Set([...existingInstructions, ...instructions])).toSorted();
|
|
14377
|
-
const newJson = {
|
|
14378
|
-
...json,
|
|
14379
|
-
instructions: mergedInstructions
|
|
14380
|
-
};
|
|
14381
14749
|
return new KiloMcp({
|
|
14382
14750
|
outputRoot,
|
|
14383
14751
|
relativeDirPath: basePaths.relativeDirPath,
|
|
14384
14752
|
relativeFilePath,
|
|
14385
|
-
fileContent:
|
|
14753
|
+
fileContent: applySharedConfigPatch({
|
|
14754
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
14755
|
+
feature: "rules",
|
|
14756
|
+
existingContent: fileContent ?? "",
|
|
14757
|
+
patch: { instructions: mergedInstructions },
|
|
14758
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
14759
|
+
}),
|
|
14386
14760
|
validate
|
|
14387
14761
|
});
|
|
14388
14762
|
}
|
|
@@ -14654,23 +15028,24 @@ var OpencodeMcp = class OpencodeMcp extends ToolMcp {
|
|
|
14654
15028
|
fileContent = await readFileContentOrNull(jsonPath);
|
|
14655
15029
|
if (fileContent) relativeFilePath = OPENCODE_JSON_FILE_NAME;
|
|
14656
15030
|
}
|
|
14657
|
-
if (!fileContent) fileContent = JSON.stringify({ mcp: {} }, null, 2);
|
|
14658
|
-
const json = parse(fileContent);
|
|
14659
15031
|
const { mcp: convertedMcp, tools: mcpTools } = convertToOpencodeFormat(convertEnvVarRefsToToolFormat({
|
|
14660
15032
|
mcpServers: rulesyncMcp.getMcpServers(),
|
|
14661
15033
|
replacement: "{env:$1}"
|
|
14662
15034
|
}));
|
|
14663
|
-
const { tools: _existingTools, ...jsonWithoutTools } = json;
|
|
14664
|
-
const newJson = {
|
|
14665
|
-
...jsonWithoutTools,
|
|
14666
|
-
mcp: convertedMcp,
|
|
14667
|
-
...Object.keys(mcpTools).length > 0 && { tools: mcpTools }
|
|
14668
|
-
};
|
|
14669
15035
|
return new OpencodeMcp({
|
|
14670
15036
|
outputRoot,
|
|
14671
15037
|
relativeDirPath: basePaths.relativeDirPath,
|
|
14672
15038
|
relativeFilePath,
|
|
14673
|
-
fileContent:
|
|
15039
|
+
fileContent: applySharedConfigPatch({
|
|
15040
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
15041
|
+
feature: "mcp",
|
|
15042
|
+
existingContent: fileContent ?? "",
|
|
15043
|
+
patch: {
|
|
15044
|
+
mcp: convertedMcp,
|
|
15045
|
+
tools: Object.keys(mcpTools).length > 0 ? mcpTools : void 0
|
|
15046
|
+
},
|
|
15047
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
15048
|
+
}),
|
|
14674
15049
|
validate
|
|
14675
15050
|
});
|
|
14676
15051
|
}
|
|
@@ -14705,15 +15080,17 @@ var OpencodeMcp = class OpencodeMcp extends ToolMcp {
|
|
|
14705
15080
|
const json = fileContent ? parse(fileContent) : {};
|
|
14706
15081
|
const existingInstructions = Array.isArray(json.instructions) ? json.instructions.filter((entry) => typeof entry === "string") : [];
|
|
14707
15082
|
const mergedInstructions = Array.from(/* @__PURE__ */ new Set([...existingInstructions, ...instructions])).toSorted();
|
|
14708
|
-
const newJson = {
|
|
14709
|
-
...json,
|
|
14710
|
-
instructions: mergedInstructions
|
|
14711
|
-
};
|
|
14712
15083
|
return new OpencodeMcp({
|
|
14713
15084
|
outputRoot,
|
|
14714
15085
|
relativeDirPath: basePaths.relativeDirPath,
|
|
14715
15086
|
relativeFilePath,
|
|
14716
|
-
fileContent:
|
|
15087
|
+
fileContent: applySharedConfigPatch({
|
|
15088
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
15089
|
+
feature: "rules",
|
|
15090
|
+
existingContent: fileContent ?? "",
|
|
15091
|
+
patch: { instructions: mergedInstructions },
|
|
15092
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
15093
|
+
}),
|
|
14717
15094
|
validate
|
|
14718
15095
|
});
|
|
14719
15096
|
}
|
|
@@ -14823,16 +15200,19 @@ var QwencodeMcp = class QwencodeMcp extends ToolMcp {
|
|
|
14823
15200
|
}
|
|
14824
15201
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
14825
15202
|
const paths = this.getSettablePaths({ global });
|
|
14826
|
-
const
|
|
14827
|
-
const
|
|
14828
|
-
...JSON.parse(fileContent),
|
|
14829
|
-
mcpServers: convertToQwencodeFormat(rulesyncMcp.getMcpServers())
|
|
14830
|
-
};
|
|
15203
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
15204
|
+
const existingContent = await readOrInitializeFileContent(filePath, JSON.stringify({ mcpServers: {} }, null, 2));
|
|
14831
15205
|
return new QwencodeMcp({
|
|
14832
15206
|
outputRoot,
|
|
14833
15207
|
relativeDirPath: paths.relativeDirPath,
|
|
14834
15208
|
relativeFilePath: paths.relativeFilePath,
|
|
14835
|
-
fileContent:
|
|
15209
|
+
fileContent: applySharedConfigPatch({
|
|
15210
|
+
fileKey: sharedConfigFileKey(paths),
|
|
15211
|
+
feature: "mcp",
|
|
15212
|
+
existingContent,
|
|
15213
|
+
patch: { mcpServers: convertToQwencodeFormat(rulesyncMcp.getMcpServers()) },
|
|
15214
|
+
filePath
|
|
15215
|
+
}),
|
|
14836
15216
|
validate
|
|
14837
15217
|
});
|
|
14838
15218
|
}
|
|
@@ -14917,13 +15297,20 @@ var ReasonixMcp = class ReasonixMcp extends ToolMcp {
|
|
|
14917
15297
|
}
|
|
14918
15298
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
14919
15299
|
const paths = this.getSettablePaths({ global });
|
|
14920
|
-
const
|
|
14921
|
-
|
|
15300
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
15301
|
+
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
15302
|
+
const plugins = Object.entries(rulesyncMcp.getMcpServers()).map(([name, server]) => rulesyncMcpServerToReasonix(name, server));
|
|
14922
15303
|
return new ReasonixMcp({
|
|
14923
15304
|
outputRoot,
|
|
14924
15305
|
relativeDirPath: paths.relativeDirPath,
|
|
14925
15306
|
relativeFilePath: paths.relativeFilePath,
|
|
14926
|
-
fileContent:
|
|
15307
|
+
fileContent: applySharedConfigPatch({
|
|
15308
|
+
fileKey: sharedConfigFileKey(paths),
|
|
15309
|
+
feature: "mcp",
|
|
15310
|
+
existingContent,
|
|
15311
|
+
patch: { plugins },
|
|
15312
|
+
filePath
|
|
15313
|
+
}),
|
|
14927
15314
|
validate,
|
|
14928
15315
|
global
|
|
14929
15316
|
});
|
|
@@ -15398,13 +15785,20 @@ var VibeMcp = class VibeMcp extends ToolMcp {
|
|
|
15398
15785
|
}
|
|
15399
15786
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
15400
15787
|
const paths = this.getSettablePaths({ global });
|
|
15401
|
-
const
|
|
15402
|
-
|
|
15788
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
15789
|
+
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
15790
|
+
const mcpServers = Object.entries(rulesyncMcp.getMcpServers()).map(([name, server]) => rulesyncMcpServerToVibe(name, server));
|
|
15403
15791
|
return new VibeMcp({
|
|
15404
15792
|
outputRoot,
|
|
15405
15793
|
relativeDirPath: paths.relativeDirPath,
|
|
15406
15794
|
relativeFilePath: paths.relativeFilePath,
|
|
15407
|
-
fileContent:
|
|
15795
|
+
fileContent: applySharedConfigPatch({
|
|
15796
|
+
fileKey: sharedConfigFileKey(paths),
|
|
15797
|
+
feature: "mcp",
|
|
15798
|
+
existingContent,
|
|
15799
|
+
patch: { mcp_servers: mcpServers },
|
|
15800
|
+
filePath
|
|
15801
|
+
}),
|
|
15408
15802
|
validate,
|
|
15409
15803
|
global
|
|
15410
15804
|
});
|
|
@@ -15635,16 +16029,19 @@ var ZedMcp = class ZedMcp extends ToolMcp {
|
|
|
15635
16029
|
}
|
|
15636
16030
|
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
15637
16031
|
const paths = this.getSettablePaths({ global });
|
|
15638
|
-
const
|
|
15639
|
-
const
|
|
15640
|
-
...JSON.parse(fileContent),
|
|
15641
|
-
context_servers: rulesyncMcp.getMcpServers()
|
|
15642
|
-
};
|
|
16032
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
16033
|
+
const existingContent = await readOrInitializeFileContent(filePath, "{}");
|
|
15643
16034
|
return new ZedMcp({
|
|
15644
16035
|
outputRoot,
|
|
15645
16036
|
relativeDirPath: paths.relativeDirPath,
|
|
15646
16037
|
relativeFilePath: paths.relativeFilePath,
|
|
15647
|
-
fileContent:
|
|
16038
|
+
fileContent: applySharedConfigPatch({
|
|
16039
|
+
fileKey: sharedConfigFileKey(paths),
|
|
16040
|
+
feature: "mcp",
|
|
16041
|
+
existingContent,
|
|
16042
|
+
patch: { context_servers: rulesyncMcp.getMcpServers() },
|
|
16043
|
+
filePath
|
|
16044
|
+
}),
|
|
15648
16045
|
validate
|
|
15649
16046
|
});
|
|
15650
16047
|
}
|
|
@@ -16813,25 +17210,29 @@ var AmpPermissions = class AmpPermissions extends ToolPermissions {
|
|
|
16813
17210
|
const override = config.amp;
|
|
16814
17211
|
const authoredExtras = override?.permissions ? toPermissionsList(override.permissions) : [];
|
|
16815
17212
|
const preservedDelegates = override?.permissions ? [] : toPermissionsList(json[AMP_PERMISSIONS_KEY]).filter((entry) => entry.action === "delegate");
|
|
16816
|
-
const newJson = {
|
|
16817
|
-
...json,
|
|
16818
|
-
[AMP_TOOLS_DISABLE_KEY]: disable
|
|
16819
|
-
};
|
|
16820
17213
|
const mergedPermissions = mergeAmpPermissions([
|
|
16821
17214
|
...permissions,
|
|
16822
17215
|
...authoredExtras,
|
|
16823
17216
|
...preservedDelegates
|
|
16824
17217
|
]);
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
if (override?.
|
|
17218
|
+
const patch = {
|
|
17219
|
+
[AMP_TOOLS_DISABLE_KEY]: disable,
|
|
17220
|
+
[AMP_PERMISSIONS_KEY]: mergedPermissions.length > 0 ? mergedPermissions : void 0
|
|
17221
|
+
};
|
|
17222
|
+
if (override?.guardedFiles?.allowlist !== void 0) patch[AMP_GUARDED_FILES_ALLOWLIST_KEY] = override.guardedFiles.allowlist;
|
|
17223
|
+
if (override?.dangerouslyAllowAll !== void 0) patch[AMP_DANGEROUSLY_ALLOW_ALL_KEY] = override.dangerouslyAllowAll;
|
|
17224
|
+
if (override?.mcpPermissions !== void 0) patch[AMP_MCP_PERMISSIONS_KEY] = override.mcpPermissions;
|
|
16830
17225
|
return new AmpPermissions({
|
|
16831
17226
|
outputRoot,
|
|
16832
17227
|
relativeDirPath: basePaths.relativeDirPath,
|
|
16833
17228
|
relativeFilePath,
|
|
16834
|
-
fileContent:
|
|
17229
|
+
fileContent: applySharedConfigPatch({
|
|
17230
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
17231
|
+
feature: "permissions",
|
|
17232
|
+
existingContent: fileContent ?? "",
|
|
17233
|
+
patch,
|
|
17234
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
17235
|
+
}),
|
|
16835
17236
|
validate: true
|
|
16836
17237
|
});
|
|
16837
17238
|
}
|
|
@@ -17773,11 +18174,13 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
17773
18174
|
...preservedBasicEntries,
|
|
17774
18175
|
...authoredBasics
|
|
17775
18176
|
]);
|
|
17776
|
-
const
|
|
17777
|
-
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
18177
|
+
const fileContent = applySharedConfigPatch({
|
|
18178
|
+
fileKey: sharedConfigFileKey(paths),
|
|
18179
|
+
feature: "permissions",
|
|
18180
|
+
existingContent,
|
|
18181
|
+
patch: { toolPermissions: [...specialEntries, ...sortedBasic] },
|
|
18182
|
+
filePath
|
|
18183
|
+
});
|
|
17781
18184
|
return new AugmentcodePermissions({
|
|
17782
18185
|
outputRoot,
|
|
17783
18186
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -18369,13 +18772,6 @@ const WORKSPACE_WIDE_WRITE_PATTERNS = /* @__PURE__ */ new Set([
|
|
|
18369
18772
|
]);
|
|
18370
18773
|
const CODEX_MINIMAL_KEY = ":minimal";
|
|
18371
18774
|
const GLOBAL_WILDCARD_DOMAIN = "*";
|
|
18372
|
-
const CODEXCLI_OVERRIDE_KEYS = [
|
|
18373
|
-
"approval_policy",
|
|
18374
|
-
"sandbox_mode",
|
|
18375
|
-
"sandbox_workspace_write",
|
|
18376
|
-
"apps",
|
|
18377
|
-
"approvals_reviewer"
|
|
18378
|
-
];
|
|
18379
18775
|
var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
18380
18776
|
static getSettablePaths(_options = {}) {
|
|
18381
18777
|
return {
|
|
@@ -18399,26 +18795,27 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
18399
18795
|
}
|
|
18400
18796
|
static async fromRulesyncPermissions({ outputRoot = process.cwd(), rulesyncPermissions, validate = true, logger, global = false }) {
|
|
18401
18797
|
const paths = this.getSettablePaths({ global });
|
|
18402
|
-
const
|
|
18403
|
-
const
|
|
18798
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
18799
|
+
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
18800
|
+
const existing = toMutableTable(smolToml.parse(existingContent || smolToml.stringify({})));
|
|
18404
18801
|
const newProfile = convertRulesyncToCodexProfile({
|
|
18405
18802
|
config: rulesyncPermissions.getJson(),
|
|
18406
18803
|
logger
|
|
18407
18804
|
});
|
|
18408
|
-
const permissionsTable = toMutableTable(
|
|
18805
|
+
const permissionsTable = toMutableTable(existing.permissions);
|
|
18409
18806
|
const { profile: existingProfile, domainsHadUnknown: existingDomainsHadUnknown } = toCodexProfile(permissionsTable[RULESYNC_PROFILE_NAME]);
|
|
18410
|
-
|
|
18411
|
-
|
|
18412
|
-
|
|
18413
|
-
|
|
18807
|
+
warnAboutPreservedProfileState({
|
|
18808
|
+
existingProfile,
|
|
18809
|
+
newProfile,
|
|
18810
|
+
existingDomainsHadUnknown,
|
|
18811
|
+
logger
|
|
18812
|
+
});
|
|
18414
18813
|
permissionsTable[RULESYNC_PROFILE_NAME] = mergeWithExistingProfile({
|
|
18415
18814
|
newProfile,
|
|
18416
18815
|
existingProfile
|
|
18417
18816
|
});
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
applyCodexcliOverride({
|
|
18421
|
-
parsed,
|
|
18817
|
+
const overridePatch = computeCodexcliOverridePatch({
|
|
18818
|
+
existing,
|
|
18422
18819
|
override: rulesyncPermissions.getJson().codexcli,
|
|
18423
18820
|
logger
|
|
18424
18821
|
});
|
|
@@ -18426,7 +18823,17 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
|
|
|
18426
18823
|
outputRoot,
|
|
18427
18824
|
relativeDirPath: paths.relativeDirPath,
|
|
18428
18825
|
relativeFilePath: paths.relativeFilePath,
|
|
18429
|
-
fileContent:
|
|
18826
|
+
fileContent: applySharedConfigPatch({
|
|
18827
|
+
fileKey: sharedConfigFileKey(paths),
|
|
18828
|
+
feature: "permissions",
|
|
18829
|
+
existingContent,
|
|
18830
|
+
patch: {
|
|
18831
|
+
permissions: permissionsTable,
|
|
18832
|
+
default_permissions: RULESYNC_PROFILE_NAME,
|
|
18833
|
+
...overridePatch
|
|
18834
|
+
},
|
|
18835
|
+
filePath
|
|
18836
|
+
}),
|
|
18430
18837
|
validate
|
|
18431
18838
|
});
|
|
18432
18839
|
}
|
|
@@ -18596,6 +19003,12 @@ function toCodexProfile(value) {
|
|
|
18596
19003
|
domainsHadUnknown
|
|
18597
19004
|
};
|
|
18598
19005
|
}
|
|
19006
|
+
function warnAboutPreservedProfileState({ existingProfile, newProfile, existingDomainsHadUnknown, logger }) {
|
|
19007
|
+
if (existingProfile?.extends !== void 0 && existingProfile.extends !== newProfile.extends) logger?.warn(`Existing "extends" value "${existingProfile.extends}" will be replaced by Rulesync-managed "${newProfile.extends ?? "(none)"}".`);
|
|
19008
|
+
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.`);
|
|
19009
|
+
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.`);
|
|
19010
|
+
if (existingDomainsHadUnknown) logger?.warn(`Existing "network.domains" contained unrecognized values. These entries were skipped and will not be imported.`);
|
|
19011
|
+
}
|
|
18599
19012
|
function mergeWithExistingProfile({ newProfile, existingProfile }) {
|
|
18600
19013
|
if (!existingProfile) return newProfile;
|
|
18601
19014
|
const mergedNetwork = { ...newProfile.network };
|
|
@@ -18646,8 +19059,9 @@ function toMutableTable(value) {
|
|
|
18646
19059
|
function isPlainObject(value) {
|
|
18647
19060
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
18648
19061
|
}
|
|
18649
|
-
function
|
|
18650
|
-
|
|
19062
|
+
function computeCodexcliOverridePatch({ existing, override, logger }) {
|
|
19063
|
+
const patch = {};
|
|
19064
|
+
if (!override) return patch;
|
|
18651
19065
|
const allowed = new Set(CODEXCLI_OVERRIDE_KEYS);
|
|
18652
19066
|
for (const [key, value] of Object.entries(override)) {
|
|
18653
19067
|
if (!allowed.has(key)) {
|
|
@@ -18655,12 +19069,13 @@ function applyCodexcliOverride({ parsed, override, logger }) {
|
|
|
18655
19069
|
continue;
|
|
18656
19070
|
}
|
|
18657
19071
|
if (value === void 0) continue;
|
|
18658
|
-
const
|
|
18659
|
-
|
|
18660
|
-
...
|
|
19072
|
+
const existingValue = existing[key];
|
|
19073
|
+
patch[key] = isPlainObject(existingValue) && isPlainObject(value) ? {
|
|
19074
|
+
...existingValue,
|
|
18661
19075
|
...value
|
|
18662
19076
|
} : value;
|
|
18663
19077
|
}
|
|
19078
|
+
return patch;
|
|
18664
19079
|
}
|
|
18665
19080
|
function extractCodexcliOverride(table) {
|
|
18666
19081
|
const override = {};
|
|
@@ -19221,15 +19636,17 @@ var DevinPermissions = class DevinPermissions extends ToolPermissions {
|
|
|
19221
19636
|
else delete mergedPermissions.ask;
|
|
19222
19637
|
if (mergedDeny.length > 0) mergedPermissions.deny = mergedDeny;
|
|
19223
19638
|
else delete mergedPermissions.deny;
|
|
19224
|
-
const merged = {
|
|
19225
|
-
...settings,
|
|
19226
|
-
permissions: mergedPermissions
|
|
19227
|
-
};
|
|
19228
19639
|
return new DevinPermissions({
|
|
19229
19640
|
outputRoot,
|
|
19230
19641
|
relativeDirPath: paths.relativeDirPath,
|
|
19231
19642
|
relativeFilePath: paths.relativeFilePath,
|
|
19232
|
-
fileContent:
|
|
19643
|
+
fileContent: applySharedConfigPatch({
|
|
19644
|
+
fileKey: sharedConfigFileKey(paths),
|
|
19645
|
+
feature: "permissions",
|
|
19646
|
+
existingContent,
|
|
19647
|
+
patch: { permissions: mergedPermissions },
|
|
19648
|
+
filePath
|
|
19649
|
+
}),
|
|
19233
19650
|
validate
|
|
19234
19651
|
});
|
|
19235
19652
|
}
|
|
@@ -19838,23 +20255,31 @@ var GrokcliPermissions = class GrokcliPermissions extends ToolPermissions {
|
|
|
19838
20255
|
const config = rulesyncPermissions.getJson();
|
|
19839
20256
|
const existingPermission = isRecord(parsed[GROKCLI_PERMISSION_KEY]) ? parsed[GROKCLI_PERMISSION_KEY] : {};
|
|
19840
20257
|
const buckets = buildGrokPermissionArrays(config, existingPermission, logger);
|
|
19841
|
-
|
|
20258
|
+
const permission = {
|
|
19842
20259
|
...existingPermission,
|
|
19843
20260
|
allow: buckets.allow,
|
|
19844
20261
|
deny: buckets.deny,
|
|
19845
20262
|
ask: buckets.ask
|
|
19846
20263
|
};
|
|
19847
20264
|
const mode = deriveGrokPermissionMode(config);
|
|
19848
|
-
const
|
|
19849
|
-
|
|
19850
|
-
...existingUi,
|
|
20265
|
+
const ui = {
|
|
20266
|
+
...isRecord(parsed[GROKCLI_UI_KEY]) ? parsed[GROKCLI_UI_KEY] : {},
|
|
19851
20267
|
[GROKCLI_PERMISSION_MODE_KEY]: mode
|
|
19852
20268
|
};
|
|
19853
20269
|
return new GrokcliPermissions({
|
|
19854
20270
|
outputRoot,
|
|
19855
20271
|
relativeDirPath: paths.relativeDirPath,
|
|
19856
20272
|
relativeFilePath: paths.relativeFilePath,
|
|
19857
|
-
fileContent:
|
|
20273
|
+
fileContent: applySharedConfigPatch({
|
|
20274
|
+
fileKey: sharedConfigFileKey(paths),
|
|
20275
|
+
feature: "permissions",
|
|
20276
|
+
existingContent,
|
|
20277
|
+
patch: {
|
|
20278
|
+
[GROKCLI_PERMISSION_KEY]: permission,
|
|
20279
|
+
[GROKCLI_UI_KEY]: ui
|
|
20280
|
+
},
|
|
20281
|
+
filePath
|
|
20282
|
+
}),
|
|
19858
20283
|
validate: true,
|
|
19859
20284
|
global: true
|
|
19860
20285
|
});
|
|
@@ -20557,7 +20982,16 @@ var KiroPermissions = class KiroPermissions extends ToolPermissions {
|
|
|
20557
20982
|
outputRoot,
|
|
20558
20983
|
relativeDirPath: paths.relativeDirPath,
|
|
20559
20984
|
relativeFilePath: paths.relativeFilePath,
|
|
20560
|
-
fileContent:
|
|
20985
|
+
fileContent: applySharedConfigPatch({
|
|
20986
|
+
fileKey: sharedConfigFileKey(paths),
|
|
20987
|
+
feature: "permissions",
|
|
20988
|
+
existingContent,
|
|
20989
|
+
patch: {
|
|
20990
|
+
allowedTools: next.allowedTools,
|
|
20991
|
+
toolsSettings: next.toolsSettings
|
|
20992
|
+
},
|
|
20993
|
+
filePath
|
|
20994
|
+
}),
|
|
20561
20995
|
validate
|
|
20562
20996
|
});
|
|
20563
20997
|
}
|
|
@@ -20854,21 +21288,22 @@ var OpencodePermissions = class OpencodePermissions extends ToolPermissions {
|
|
|
20854
21288
|
fileContent = await readFileContentOrNull(jsonPath);
|
|
20855
21289
|
if (fileContent) relativeFilePath = OPENCODE_JSON_FILE_NAME;
|
|
20856
21290
|
}
|
|
20857
|
-
const parsed = parse(fileContent ?? "{}");
|
|
20858
21291
|
const rulesyncJson = rulesyncPermissions.getJson();
|
|
20859
21292
|
const overridePermission = rulesyncJson.opencode?.permission ?? {};
|
|
20860
|
-
const nextJson = {
|
|
20861
|
-
...parsed,
|
|
20862
|
-
permission: {
|
|
20863
|
-
...rulesyncJson.permission,
|
|
20864
|
-
...overridePermission
|
|
20865
|
-
}
|
|
20866
|
-
};
|
|
20867
21293
|
return new OpencodePermissions({
|
|
20868
21294
|
outputRoot,
|
|
20869
21295
|
relativeDirPath: basePaths.relativeDirPath,
|
|
20870
21296
|
relativeFilePath,
|
|
20871
|
-
fileContent:
|
|
21297
|
+
fileContent: applySharedConfigPatch({
|
|
21298
|
+
fileKey: sharedConfigFileKey(basePaths),
|
|
21299
|
+
feature: "permissions",
|
|
21300
|
+
existingContent: fileContent ?? "",
|
|
21301
|
+
patch: { permission: {
|
|
21302
|
+
...rulesyncJson.permission,
|
|
21303
|
+
...overridePermission
|
|
21304
|
+
} },
|
|
21305
|
+
filePath: join(jsonDir, relativeFilePath)
|
|
21306
|
+
}),
|
|
20872
21307
|
validate: true
|
|
20873
21308
|
});
|
|
20874
21309
|
}
|
|
@@ -21077,20 +21512,23 @@ var QwencodePermissions = class QwencodePermissions extends ToolPermissions {
|
|
|
21077
21512
|
else delete mergedPermissions.ask;
|
|
21078
21513
|
if (mergedDeny.length > 0) mergedPermissions.deny = mergedDeny;
|
|
21079
21514
|
else delete mergedPermissions.deny;
|
|
21080
|
-
const
|
|
21081
|
-
...settings,
|
|
21082
|
-
permissions: mergedPermissions
|
|
21083
|
-
};
|
|
21515
|
+
const patch = { permissions: mergedPermissions };
|
|
21084
21516
|
const override = config.qwencode;
|
|
21085
|
-
if (override?.tools !== void 0)
|
|
21517
|
+
if (override?.tools !== void 0) patch.tools = {
|
|
21086
21518
|
...asPlainRecord(settings.tools),
|
|
21087
21519
|
...asPlainRecord(override.tools)
|
|
21088
21520
|
};
|
|
21089
|
-
if (override?.security !== void 0)
|
|
21521
|
+
if (override?.security !== void 0) patch.security = {
|
|
21090
21522
|
...asPlainRecord(settings.security),
|
|
21091
21523
|
...asPlainRecord(override.security)
|
|
21092
21524
|
};
|
|
21093
|
-
const fileContent =
|
|
21525
|
+
const fileContent = applySharedConfigPatch({
|
|
21526
|
+
fileKey: sharedConfigFileKey(paths),
|
|
21527
|
+
feature: "permissions",
|
|
21528
|
+
existingContent,
|
|
21529
|
+
patch,
|
|
21530
|
+
filePath
|
|
21531
|
+
});
|
|
21094
21532
|
return new QwencodePermissions({
|
|
21095
21533
|
outputRoot,
|
|
21096
21534
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -21325,7 +21763,9 @@ var ReasonixPermissions = class ReasonixPermissions extends ToolPermissions {
|
|
|
21325
21763
|
}
|
|
21326
21764
|
static async fromRulesyncPermissions({ outputRoot = process.cwd(), rulesyncPermissions, validate = true, logger, global = false }) {
|
|
21327
21765
|
const paths = this.getSettablePaths({ global });
|
|
21328
|
-
const
|
|
21766
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
21767
|
+
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
21768
|
+
const parsed = parseReasonixConfig(existingContent);
|
|
21329
21769
|
const config = rulesyncPermissions.getJson();
|
|
21330
21770
|
const { allow, ask, deny } = convertRulesyncToReasonixPermissions(config);
|
|
21331
21771
|
const managedToolNames = new Set(Object.keys(config.permission).map((category) => toReasonixToolName(category)));
|
|
@@ -21350,25 +21790,27 @@ var ReasonixPermissions = class ReasonixPermissions extends ToolPermissions {
|
|
|
21350
21790
|
else delete mergedPermissions.ask;
|
|
21351
21791
|
if (mergedDeny.length > 0) mergedPermissions.deny = mergedDeny;
|
|
21352
21792
|
else delete mergedPermissions.deny;
|
|
21353
|
-
const
|
|
21354
|
-
...parsed,
|
|
21355
|
-
permissions: mergedPermissions
|
|
21356
|
-
};
|
|
21793
|
+
const patch = { permissions: mergedPermissions };
|
|
21357
21794
|
const override = config.reasonix;
|
|
21358
|
-
if (override?.sandbox !== void 0)
|
|
21795
|
+
if (override?.sandbox !== void 0) patch.sandbox = {
|
|
21359
21796
|
...asReasonixRecord(parsed.sandbox),
|
|
21360
21797
|
...asReasonixRecord(override.sandbox)
|
|
21361
21798
|
};
|
|
21362
|
-
if (override?.agent !== void 0)
|
|
21799
|
+
if (override?.agent !== void 0) patch.agent = {
|
|
21363
21800
|
...asReasonixRecord(parsed.agent),
|
|
21364
21801
|
...asReasonixRecord(override.agent)
|
|
21365
21802
|
};
|
|
21366
|
-
const fileContent = smolToml.stringify(merged);
|
|
21367
21803
|
return new ReasonixPermissions({
|
|
21368
21804
|
outputRoot,
|
|
21369
21805
|
relativeDirPath: paths.relativeDirPath,
|
|
21370
21806
|
relativeFilePath: paths.relativeFilePath,
|
|
21371
|
-
fileContent
|
|
21807
|
+
fileContent: applySharedConfigPatch({
|
|
21808
|
+
fileKey: sharedConfigFileKey(paths),
|
|
21809
|
+
feature: "permissions",
|
|
21810
|
+
existingContent,
|
|
21811
|
+
patch,
|
|
21812
|
+
filePath
|
|
21813
|
+
}),
|
|
21372
21814
|
validate
|
|
21373
21815
|
});
|
|
21374
21816
|
}
|
|
@@ -21939,7 +22381,9 @@ var VibePermissions = class VibePermissions extends ToolPermissions {
|
|
|
21939
22381
|
}
|
|
21940
22382
|
static async fromRulesyncPermissions({ outputRoot = process.cwd(), rulesyncPermissions, validate = true, logger, global = false }) {
|
|
21941
22383
|
const paths = this.getSettablePaths({ global });
|
|
21942
|
-
const
|
|
22384
|
+
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
22385
|
+
const existingContent = await readFileContentOrNull(filePath) ?? "";
|
|
22386
|
+
const config = parseVibeConfig(existingContent);
|
|
21943
22387
|
const permission = rulesyncPermissions.getJson().permission;
|
|
21944
22388
|
const tools = toVibeToolsRecord(config.tools);
|
|
21945
22389
|
const enabledTools = new Set(toStringArray(config.enabled_tools));
|
|
@@ -21984,16 +22428,21 @@ var VibePermissions = class VibePermissions extends ToolPermissions {
|
|
|
21984
22428
|
tools[vibeToolName] = nextTool;
|
|
21985
22429
|
}
|
|
21986
22430
|
applyVibeSensitivePatterns(tools, rulesyncPermissions.getJson().vibe);
|
|
21987
|
-
config.tools = tools;
|
|
21988
|
-
if (enabledTools.size > 0) config.enabled_tools = [...enabledTools].toSorted();
|
|
21989
|
-
else delete config.enabled_tools;
|
|
21990
|
-
if (disabledTools.size > 0) config.disabled_tools = [...disabledTools].toSorted();
|
|
21991
|
-
else delete config.disabled_tools;
|
|
21992
22431
|
return new VibePermissions({
|
|
21993
22432
|
outputRoot,
|
|
21994
22433
|
relativeDirPath: paths.relativeDirPath,
|
|
21995
22434
|
relativeFilePath: paths.relativeFilePath,
|
|
21996
|
-
fileContent:
|
|
22435
|
+
fileContent: applySharedConfigPatch({
|
|
22436
|
+
fileKey: sharedConfigFileKey(paths),
|
|
22437
|
+
feature: "permissions",
|
|
22438
|
+
existingContent,
|
|
22439
|
+
patch: {
|
|
22440
|
+
tools,
|
|
22441
|
+
enabled_tools: enabledTools.size > 0 ? [...enabledTools].toSorted() : void 0,
|
|
22442
|
+
disabled_tools: disabledTools.size > 0 ? [...disabledTools].toSorted() : void 0
|
|
22443
|
+
},
|
|
22444
|
+
filePath
|
|
22445
|
+
}),
|
|
21997
22446
|
validate,
|
|
21998
22447
|
global
|
|
21999
22448
|
});
|
|
@@ -22456,24 +22905,26 @@ var ZedPermissions = class ZedPermissions extends ToolPermissions {
|
|
|
22456
22905
|
}
|
|
22457
22906
|
const managedToolNames = new Set(Object.keys(managedTools));
|
|
22458
22907
|
const preservedTools = Object.fromEntries(Object.entries(existingTools).filter(([toolName]) => !managedToolNames.has(toolName)));
|
|
22459
|
-
const mergedSettings = {
|
|
22460
|
-
...settings,
|
|
22461
|
-
agent: {
|
|
22462
|
-
...agent,
|
|
22463
|
-
tool_permissions: {
|
|
22464
|
-
...toolPermissions,
|
|
22465
|
-
tools: {
|
|
22466
|
-
...preservedTools,
|
|
22467
|
-
...managedTools
|
|
22468
|
-
}
|
|
22469
|
-
}
|
|
22470
|
-
}
|
|
22471
|
-
};
|
|
22472
22908
|
return new ZedPermissions({
|
|
22473
22909
|
outputRoot,
|
|
22474
22910
|
relativeDirPath: paths.relativeDirPath,
|
|
22475
22911
|
relativeFilePath: paths.relativeFilePath,
|
|
22476
|
-
fileContent:
|
|
22912
|
+
fileContent: applySharedConfigPatch({
|
|
22913
|
+
fileKey: sharedConfigFileKey(paths),
|
|
22914
|
+
feature: "permissions",
|
|
22915
|
+
existingContent,
|
|
22916
|
+
patch: { agent: {
|
|
22917
|
+
...agent,
|
|
22918
|
+
tool_permissions: {
|
|
22919
|
+
...toolPermissions,
|
|
22920
|
+
tools: {
|
|
22921
|
+
...preservedTools,
|
|
22922
|
+
...managedTools
|
|
22923
|
+
}
|
|
22924
|
+
}
|
|
22925
|
+
} },
|
|
22926
|
+
filePath
|
|
22927
|
+
}),
|
|
22477
22928
|
validate: true
|
|
22478
22929
|
});
|
|
22479
22930
|
}
|
|
@@ -38163,8 +38614,13 @@ const collectFactoryPaths = (factory) => [...settablePathsForScope({
|
|
|
38163
38614
|
* Derive, from the processor registry, every on-disk file that two or more
|
|
38164
38615
|
* features read-modify-write. Source of truth the generation step graph's
|
|
38165
38616
|
* `writesSharedFile` declarations must match.
|
|
38617
|
+
*
|
|
38618
|
+
* `minWriters: 1` widens the result to single-feature files as well — used to
|
|
38619
|
+
* validate `SHARED_CONFIG_OWNERSHIP` declarations for files that route through
|
|
38620
|
+
* the gateway without being cross-feature shared (e.g. a global-scope twin
|
|
38621
|
+
* only one feature writes).
|
|
38166
38622
|
*/
|
|
38167
|
-
const deriveSharedFileWriters = () => {
|
|
38623
|
+
const deriveSharedFileWriters = ({ minWriters = 2 } = {}) => {
|
|
38168
38624
|
const byKey = /* @__PURE__ */ new Map();
|
|
38169
38625
|
const pathByKey = /* @__PURE__ */ new Map();
|
|
38170
38626
|
for (const entry of PROCESSOR_REGISTRY) {
|
|
@@ -38190,7 +38646,7 @@ const deriveSharedFileWriters = () => {
|
|
|
38190
38646
|
}
|
|
38191
38647
|
const writers = [];
|
|
38192
38648
|
for (const [key, features] of byKey) {
|
|
38193
|
-
if (features.size <
|
|
38649
|
+
if (features.size < minWriters) continue;
|
|
38194
38650
|
const path = pathByKey.get(key);
|
|
38195
38651
|
const toolsByFeature = /* @__PURE__ */ new Map();
|
|
38196
38652
|
for (const [feature, tools] of features) toolsByFeature.set(feature, [...tools].toSorted());
|
|
@@ -39135,4 +39591,4 @@ async function importPermissionsCore(params) {
|
|
|
39135
39591
|
//#endregion
|
|
39136
39592
|
export { removeTempDirectory as $, RulesyncCommand as A, checkPathTraversal as B, RulesyncHooks as C, RULESYNC_RULES_RELATIVE_DIR_PATH as Ct, CLAUDECODE_MEMORIES_DIR_NAME as D, formatError as Dt, CLAUDECODE_LOCAL_RULE_FILE_NAME as E, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as Et, findControlCharacter as F, findFilesByGlobs as G, directoryExists as H, ConsoleLogger as I, isSymlink as J, getFileSize as K, JsonLogger as L, stringifyFrontmatter as M, loadYaml as N, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as O, ALL_FEATURES as Ot, ConfigResolver as P, removeFile as Q, CLIError as R, HooksProcessor as S, RULESYNC_RELATIVE_DIR_PATH as St, CLAUDECODE_DIR as T, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Tt, ensureDir as U, createTempDirectory as V, fileExists as W, readFileContent as X, listDirectoryFiles as Y, removeDirectory as Z, RulesyncPermissions as _, RULESYNC_MCP_RELATIVE_FILE_PATH as _t, convertFromTool as a, MAX_FILE_SIZE as at, IgnoreProcessor as b, RULESYNC_PERMISSIONS_FILE_NAME as bt, RulesyncRuleFrontmatterSchema as c, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as ct, RulesyncSubagentFrontmatterSchema as d, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as dt, toPosixPath as et, SkillsProcessor as f, RULESYNC_HOOKS_FILE_NAME as ft, SKILL_FILE_NAME as g, RULESYNC_MCP_FILE_NAME as gt, RulesyncSkillFrontmatterSchema as h, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as ht, getProcessorRegistryEntry as i, ToolTargetSchema as it, RulesyncCommandFrontmatterSchema as j, CLAUDECODE_SKILLS_DIR_PATH as k, ALL_FEATURES_WITH_WILDCARD as kt, SubagentsProcessor as l, RULESYNC_CONFIG_RELATIVE_FILE_PATH as lt, RulesyncSkill as m, RULESYNC_IGNORE_RELATIVE_FILE_PATH as mt, checkRulesyncDirExists as n, ALL_TOOL_TARGETS as nt, RulesProcessor as o, RULESYNC_AIIGNORE_FILE_NAME as ot, getLocalSkillDirNames as p, RULESYNC_HOOKS_RELATIVE_FILE_PATH as pt, getHomeDirectory as q, generate as r, ALL_TOOL_TARGETS_WITH_WILDCARD as rt, RulesyncRule as s, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as st, importFromTool as t, writeFileContent as tt, RulesyncSubagent as u, RULESYNC_CONFIG_SCHEMA_URL as ut, McpProcessor as v, RULESYNC_MCP_SCHEMA_URL as vt, CommandsProcessor as w, RULESYNC_SKILLS_RELATIVE_DIR_PATH as wt, RulesyncIgnore as x, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as xt, RulesyncMcp as y, RULESYNC_OVERVIEW_FILE_NAME as yt, ErrorCodes as z };
|
|
39137
39593
|
|
|
39138
|
-
//# sourceMappingURL=import-
|
|
39594
|
+
//# sourceMappingURL=import-DC9T1JlQ.js.map
|