rulesync 8.17.0 → 8.18.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.
@@ -7983,14 +7983,21 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
7983
7983
  // src/features/mcp/codexcli-mcp.ts
7984
7984
  import { join as join51 } from "path";
7985
7985
  import * as smolToml3 from "smol-toml";
7986
+ var MAX_REMOVE_EMPTY_ENTRIES_DEPTH = 32;
7987
+ var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
7988
+ function isPlainObject2(value) {
7989
+ if (!isRecord(value)) return false;
7990
+ const proto = Object.getPrototypeOf(value);
7991
+ return proto === null || proto === Object.prototype;
7992
+ }
7986
7993
  function convertFromCodexFormat(codexMcp) {
7987
7994
  const result = {};
7988
7995
  for (const [name, config] of Object.entries(codexMcp)) {
7989
- if (typeof config !== "object" || config === null || Array.isArray(config)) {
7990
- continue;
7991
- }
7996
+ if (PROTOTYPE_POLLUTION_KEYS.has(name)) continue;
7997
+ if (!isRecord(config)) continue;
7992
7998
  const converted = {};
7993
7999
  for (const [key, value] of Object.entries(config)) {
8000
+ if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
7994
8001
  if (key === "enabled") {
7995
8002
  if (value === false) {
7996
8003
  converted["disabled"] = true;
@@ -8012,8 +8019,11 @@ function convertFromCodexFormat(codexMcp) {
8012
8019
  function convertToCodexFormat(mcpServers) {
8013
8020
  const result = {};
8014
8021
  for (const [name, config] of Object.entries(mcpServers)) {
8022
+ if (PROTOTYPE_POLLUTION_KEYS.has(name)) continue;
8023
+ if (!isRecord(config)) continue;
8015
8024
  const converted = {};
8016
8025
  for (const [key, value] of Object.entries(config)) {
8026
+ if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
8017
8027
  if (key === "disabled") {
8018
8028
  if (value === true) {
8019
8029
  converted["enabled"] = false;
@@ -8095,6 +8105,14 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
8095
8105
  const mcpServers = rulesyncMcp.getJson().mcpServers;
8096
8106
  const converted = convertToCodexFormat(mcpServers);
8097
8107
  const filteredMcpServers = this.removeEmptyEntries(converted);
8108
+ for (const name of Object.keys(converted)) {
8109
+ if (!Object.hasOwn(filteredMcpServers, name)) {
8110
+ warnWithFallback(
8111
+ void 0,
8112
+ `MCP server "${name}" had no non-empty configuration and was dropped from the codex CLI config`
8113
+ );
8114
+ }
8115
+ }
8098
8116
  configToml["mcp_servers"] = filteredMcpServers;
8099
8117
  return new _CodexcliMcp({
8100
8118
  outputRoot,
@@ -8114,13 +8132,21 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
8114
8132
  validate() {
8115
8133
  return { success: true, error: null };
8116
8134
  }
8117
- static removeEmptyEntries(obj) {
8135
+ static removeEmptyEntries(obj, depth = 0) {
8118
8136
  if (!obj) return {};
8137
+ if (depth > MAX_REMOVE_EMPTY_ENTRIES_DEPTH) {
8138
+ warnWithFallback(
8139
+ void 0,
8140
+ `removeEmptyEntries: maximum recursion depth (${MAX_REMOVE_EMPTY_ENTRIES_DEPTH}) exceeded; empty nested objects may remain`
8141
+ );
8142
+ return obj;
8143
+ }
8119
8144
  const filtered = {};
8120
8145
  for (const [key, value] of Object.entries(obj)) {
8146
+ if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
8121
8147
  if (value === null) continue;
8122
- if (typeof value === "object" && !Array.isArray(value)) {
8123
- const cleaned = this.removeEmptyEntries(value);
8148
+ if (isPlainObject2(value)) {
8149
+ const cleaned = this.removeEmptyEntries(value, depth + 1);
8124
8150
  if (Object.keys(cleaned).length === 0) continue;
8125
8151
  filtered[key] = cleaned;
8126
8152
  continue;
@@ -9813,7 +9839,13 @@ var toolMcpFactories = /* @__PURE__ */ new Map([
9813
9839
  class: KiloMcp,
9814
9840
  meta: {
9815
9841
  supportsProject: true,
9816
- supportsGlobal: false,
9842
+ // Kilo CLI reads global MCP from `~/.config/kilo/kilo.json` (or
9843
+ // `kilo.jsonc`). The path machinery in `KiloMcp.getSettablePaths`
9844
+ // already routes global mode to that location; only this flag
9845
+ // was gating it off. Kilo is an OpenCode fork and uses an
9846
+ // identical native MCP schema, so global parity with opencode
9847
+ // is the natural state.
9848
+ supportsGlobal: true,
9817
9849
  supportsEnabledTools: false,
9818
9850
  supportsDisabledTools: false
9819
9851
  }
@@ -12934,7 +12966,7 @@ var PermissionsProcessor = class extends FeatureProcessor {
12934
12966
  // src/features/rules/rules-processor.ts
12935
12967
  import { basename as basename10, dirname as dirname3, join as join151, relative as relative6 } from "path";
12936
12968
  import { encode } from "@toon-format/toon";
12937
- import { z as z79 } from "zod/mini";
12969
+ import { z as z80 } from "zod/mini";
12938
12970
 
12939
12971
  // src/constants/general.ts
12940
12972
  var SKILL_FILE_NAME = "SKILL.md";
@@ -17886,7 +17918,7 @@ var RovodevSubagent = class _RovodevSubagent extends ToolSubagent {
17886
17918
 
17887
17919
  // src/features/subagents/subagents-processor.ts
17888
17920
  import { basename as basename9, join as join122 } from "path";
17889
- import { z as z72 } from "zod/mini";
17921
+ import { z as z73 } from "zod/mini";
17890
17922
 
17891
17923
  // src/features/subagents/claudecode-subagent.ts
17892
17924
  import { join as join110 } from "path";
@@ -19046,6 +19078,7 @@ var JunieSubagent = class _JunieSubagent extends ToolSubagent {
19046
19078
 
19047
19079
  // src/features/subagents/kilo-subagent.ts
19048
19080
  import { join as join118 } from "path";
19081
+ import { z as z71 } from "zod/mini";
19049
19082
 
19050
19083
  // src/features/subagents/opencode-style-subagent.ts
19051
19084
  import { basename as basename8, join as join117 } from "path";
@@ -19112,7 +19145,13 @@ var OpenCodeStyleSubagent = class extends ToolSubagent {
19112
19145
  };
19113
19146
 
19114
19147
  // src/features/subagents/kilo-subagent.ts
19115
- var KiloSubagentFrontmatterSchema = OpenCodeStyleSubagentFrontmatterSchema;
19148
+ var KiloSubagentFrontmatterSchema = z71.looseObject({
19149
+ description: z71.optional(z71.string()),
19150
+ // Kilo's documented default for user-defined agents is "all":
19151
+ // available both as a top-level pick and as a subagent.
19152
+ mode: z71._default(z71.string(), "all"),
19153
+ name: z71.optional(z71.string())
19154
+ });
19116
19155
  var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19117
19156
  getToolTarget() {
19118
19157
  return "kilo";
@@ -19132,12 +19171,11 @@ var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19132
19171
  }) {
19133
19172
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
19134
19173
  const kiloSection = rulesyncFrontmatter.kilo ?? {};
19135
- const kiloFrontmatter = {
19174
+ const kiloFrontmatter = KiloSubagentFrontmatterSchema.parse({
19136
19175
  ...kiloSection,
19137
19176
  description: rulesyncFrontmatter.description,
19138
- mode: typeof kiloSection.mode === "string" ? kiloSection.mode : "subagent",
19139
19177
  ...rulesyncFrontmatter.name && { name: rulesyncFrontmatter.name }
19140
- };
19178
+ });
19141
19179
  const body = rulesyncSubagent.getBody();
19142
19180
  const fileContent = stringifyFrontmatter(body, kiloFrontmatter);
19143
19181
  const paths = this.getSettablePaths({ global });
@@ -19186,38 +19224,40 @@ var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19186
19224
  static forDeletion({
19187
19225
  outputRoot = process.cwd(),
19188
19226
  relativeDirPath,
19189
- relativeFilePath
19227
+ relativeFilePath,
19228
+ global = false
19190
19229
  }) {
19191
19230
  return new _KiloSubagent({
19192
19231
  outputRoot,
19193
19232
  relativeDirPath,
19194
19233
  relativeFilePath,
19195
- frontmatter: { description: "", mode: "subagent" },
19234
+ frontmatter: { description: "", mode: "all" },
19196
19235
  body: "",
19197
19236
  fileContent: "",
19198
- validate: false
19237
+ validate: false,
19238
+ global
19199
19239
  });
19200
19240
  }
19201
19241
  };
19202
19242
 
19203
19243
  // src/features/subagents/kiro-subagent.ts
19204
19244
  import { join as join119 } from "path";
19205
- import { z as z71 } from "zod/mini";
19206
- var KiroCliSubagentJsonSchema = z71.looseObject({
19207
- name: z71.string(),
19208
- description: z71.optional(z71.nullable(z71.string())),
19209
- prompt: z71.optional(z71.nullable(z71.string())),
19210
- tools: z71.optional(z71.nullable(z71.array(z71.string()))),
19211
- toolAliases: z71.optional(z71.nullable(z71.record(z71.string(), z71.string()))),
19212
- toolSettings: z71.optional(z71.nullable(z71.unknown())),
19213
- toolSchema: z71.optional(z71.nullable(z71.unknown())),
19214
- hooks: z71.optional(z71.nullable(z71.record(z71.string(), z71.array(z71.unknown())))),
19215
- model: z71.optional(z71.nullable(z71.string())),
19216
- mcpServers: z71.optional(z71.nullable(z71.record(z71.string(), z71.unknown()))),
19217
- useLegacyMcpJson: z71.optional(z71.nullable(z71.boolean())),
19218
- resources: z71.optional(z71.nullable(z71.array(z71.string()))),
19219
- allowedTools: z71.optional(z71.nullable(z71.array(z71.string()))),
19220
- includeMcpJson: z71.optional(z71.nullable(z71.boolean()))
19245
+ import { z as z72 } from "zod/mini";
19246
+ var KiroCliSubagentJsonSchema = z72.looseObject({
19247
+ name: z72.string(),
19248
+ description: z72.optional(z72.nullable(z72.string())),
19249
+ prompt: z72.optional(z72.nullable(z72.string())),
19250
+ tools: z72.optional(z72.nullable(z72.array(z72.string()))),
19251
+ toolAliases: z72.optional(z72.nullable(z72.record(z72.string(), z72.string()))),
19252
+ toolSettings: z72.optional(z72.nullable(z72.unknown())),
19253
+ toolSchema: z72.optional(z72.nullable(z72.unknown())),
19254
+ hooks: z72.optional(z72.nullable(z72.record(z72.string(), z72.array(z72.unknown())))),
19255
+ model: z72.optional(z72.nullable(z72.string())),
19256
+ mcpServers: z72.optional(z72.nullable(z72.record(z72.string(), z72.unknown()))),
19257
+ useLegacyMcpJson: z72.optional(z72.nullable(z72.boolean())),
19258
+ resources: z72.optional(z72.nullable(z72.array(z72.string()))),
19259
+ allowedTools: z72.optional(z72.nullable(z72.array(z72.string()))),
19260
+ includeMcpJson: z72.optional(z72.nullable(z72.boolean()))
19221
19261
  });
19222
19262
  var KiroSubagent = class _KiroSubagent extends ToolSubagent {
19223
19263
  body;
@@ -19583,7 +19623,7 @@ var subagentsProcessorToolTargetTuple = [
19583
19623
  "rovodev",
19584
19624
  "takt"
19585
19625
  ];
19586
- var SubagentsProcessorToolTargetSchema = z72.enum(subagentsProcessorToolTargetTuple);
19626
+ var SubagentsProcessorToolTargetSchema = z73.enum(subagentsProcessorToolTargetTuple);
19587
19627
  var toolSubagentFactories = /* @__PURE__ */ new Map([
19588
19628
  [
19589
19629
  "agentsmd",
@@ -19912,48 +19952,48 @@ import { join as join124 } from "path";
19912
19952
 
19913
19953
  // src/features/rules/rulesync-rule.ts
19914
19954
  import { join as join123 } from "path";
19915
- import { z as z73 } from "zod/mini";
19916
- var RulesyncRuleFrontmatterSchema = z73.object({
19917
- root: z73.optional(z73.boolean()),
19918
- localRoot: z73.optional(z73.boolean()),
19919
- targets: z73._default(RulesyncTargetsSchema, ["*"]),
19920
- description: z73.optional(z73.string()),
19921
- globs: z73.optional(z73.array(z73.string())),
19922
- agentsmd: z73.optional(
19923
- z73.looseObject({
19955
+ import { z as z74 } from "zod/mini";
19956
+ var RulesyncRuleFrontmatterSchema = z74.object({
19957
+ root: z74.optional(z74.boolean()),
19958
+ localRoot: z74.optional(z74.boolean()),
19959
+ targets: z74._default(RulesyncTargetsSchema, ["*"]),
19960
+ description: z74.optional(z74.string()),
19961
+ globs: z74.optional(z74.array(z74.string())),
19962
+ agentsmd: z74.optional(
19963
+ z74.looseObject({
19924
19964
  // @example "path/to/subproject"
19925
- subprojectPath: z73.optional(z73.string())
19965
+ subprojectPath: z74.optional(z74.string())
19926
19966
  })
19927
19967
  ),
19928
- claudecode: z73.optional(
19929
- z73.looseObject({
19968
+ claudecode: z74.optional(
19969
+ z74.looseObject({
19930
19970
  // Glob patterns for conditional rules (takes precedence over globs)
19931
19971
  // @example ["src/**/*.ts", "tests/**/*.test.ts"]
19932
- paths: z73.optional(z73.array(z73.string()))
19972
+ paths: z74.optional(z74.array(z74.string()))
19933
19973
  })
19934
19974
  ),
19935
- cursor: z73.optional(
19936
- z73.looseObject({
19937
- alwaysApply: z73.optional(z73.boolean()),
19938
- description: z73.optional(z73.string()),
19939
- globs: z73.optional(z73.array(z73.string()))
19975
+ cursor: z74.optional(
19976
+ z74.looseObject({
19977
+ alwaysApply: z74.optional(z74.boolean()),
19978
+ description: z74.optional(z74.string()),
19979
+ globs: z74.optional(z74.array(z74.string()))
19940
19980
  })
19941
19981
  ),
19942
- copilot: z73.optional(
19943
- z73.looseObject({
19944
- excludeAgent: z73.optional(z73.union([z73.literal("code-review"), z73.literal("coding-agent")]))
19982
+ copilot: z74.optional(
19983
+ z74.looseObject({
19984
+ excludeAgent: z74.optional(z74.union([z74.literal("code-review"), z74.literal("coding-agent")]))
19945
19985
  })
19946
19986
  ),
19947
- antigravity: z73.optional(
19948
- z73.looseObject({
19949
- trigger: z73.optional(z73.string()),
19950
- globs: z73.optional(z73.array(z73.string()))
19987
+ antigravity: z74.optional(
19988
+ z74.looseObject({
19989
+ trigger: z74.optional(z74.string()),
19990
+ globs: z74.optional(z74.array(z74.string()))
19951
19991
  })
19952
19992
  ),
19953
- takt: z73.optional(
19954
- z73.looseObject({
19993
+ takt: z74.optional(
19994
+ z74.looseObject({
19955
19995
  // Rename the emitted file stem (e.g. "coder.md" → "{name}.md").
19956
- name: z73.optional(z73.string())
19996
+ name: z74.optional(z74.string())
19957
19997
  })
19958
19998
  )
19959
19999
  });
@@ -20254,20 +20294,20 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
20254
20294
 
20255
20295
  // src/features/rules/antigravity-rule.ts
20256
20296
  import { join as join126 } from "path";
20257
- import { z as z74 } from "zod/mini";
20258
- var AntigravityRuleFrontmatterSchema = z74.looseObject({
20259
- trigger: z74.optional(
20260
- z74.union([
20261
- z74.literal("always_on"),
20262
- z74.literal("glob"),
20263
- z74.literal("manual"),
20264
- z74.literal("model_decision"),
20265
- z74.string()
20297
+ import { z as z75 } from "zod/mini";
20298
+ var AntigravityRuleFrontmatterSchema = z75.looseObject({
20299
+ trigger: z75.optional(
20300
+ z75.union([
20301
+ z75.literal("always_on"),
20302
+ z75.literal("glob"),
20303
+ z75.literal("manual"),
20304
+ z75.literal("model_decision"),
20305
+ z75.string()
20266
20306
  // accepts any string for forward compatibility
20267
20307
  ])
20268
20308
  ),
20269
- globs: z74.optional(z74.string()),
20270
- description: z74.optional(z74.string())
20309
+ globs: z75.optional(z75.string()),
20310
+ description: z75.optional(z75.string())
20271
20311
  });
20272
20312
  function parseGlobsString(globs) {
20273
20313
  if (!globs) {
@@ -20854,9 +20894,9 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
20854
20894
 
20855
20895
  // src/features/rules/claudecode-rule.ts
20856
20896
  import { join as join130 } from "path";
20857
- import { z as z75 } from "zod/mini";
20858
- var ClaudecodeRuleFrontmatterSchema = z75.object({
20859
- paths: z75.optional(z75.array(z75.string()))
20897
+ import { z as z76 } from "zod/mini";
20898
+ var ClaudecodeRuleFrontmatterSchema = z76.object({
20899
+ paths: z76.optional(z76.array(z76.string()))
20860
20900
  });
20861
20901
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
20862
20902
  frontmatter;
@@ -21072,9 +21112,9 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
21072
21112
 
21073
21113
  // src/features/rules/cline-rule.ts
21074
21114
  import { join as join131 } from "path";
21075
- import { z as z76 } from "zod/mini";
21076
- var ClineRuleFrontmatterSchema = z76.object({
21077
- description: z76.string()
21115
+ import { z as z77 } from "zod/mini";
21116
+ var ClineRuleFrontmatterSchema = z77.object({
21117
+ description: z77.string()
21078
21118
  });
21079
21119
  var ClineRule = class _ClineRule extends ToolRule {
21080
21120
  static getSettablePaths(_options = {}) {
@@ -21253,11 +21293,11 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
21253
21293
 
21254
21294
  // src/features/rules/copilot-rule.ts
21255
21295
  import { join as join133 } from "path";
21256
- import { z as z77 } from "zod/mini";
21257
- var CopilotRuleFrontmatterSchema = z77.object({
21258
- description: z77.optional(z77.string()),
21259
- applyTo: z77.optional(z77.string()),
21260
- excludeAgent: z77.optional(z77.union([z77.literal("code-review"), z77.literal("coding-agent")]))
21296
+ import { z as z78 } from "zod/mini";
21297
+ var CopilotRuleFrontmatterSchema = z78.object({
21298
+ description: z78.optional(z78.string()),
21299
+ applyTo: z78.optional(z78.string()),
21300
+ excludeAgent: z78.optional(z78.union([z78.literal("code-review"), z78.literal("coding-agent")]))
21261
21301
  });
21262
21302
  var normalizeRelativePath = (path4) => path4.replace(/\\/g, "/").replace(/\/+/g, "/");
21263
21303
  var sameRelativePath = (leftDir, leftFile, rightDir, rightFile) => normalizeRelativePath(join133(leftDir, leftFile)) === normalizeRelativePath(join133(rightDir, rightFile));
@@ -21511,11 +21551,11 @@ var CopilotcliRule = class _CopilotcliRule extends CopilotRule {
21511
21551
 
21512
21552
  // src/features/rules/cursor-rule.ts
21513
21553
  import { join as join134 } from "path";
21514
- import { z as z78 } from "zod/mini";
21515
- var CursorRuleFrontmatterSchema = z78.object({
21516
- description: z78.optional(z78.string()),
21517
- globs: z78.optional(z78.string()),
21518
- alwaysApply: z78.optional(z78.boolean())
21554
+ import { z as z79 } from "zod/mini";
21555
+ var CursorRuleFrontmatterSchema = z79.object({
21556
+ description: z79.optional(z79.string()),
21557
+ globs: z79.optional(z79.string()),
21558
+ alwaysApply: z79.optional(z79.boolean())
21519
21559
  });
21520
21560
  var CursorRule = class _CursorRule extends ToolRule {
21521
21561
  frontmatter;
@@ -23398,11 +23438,11 @@ var rulesProcessorToolTargets = [
23398
23438
  "warp",
23399
23439
  "windsurf"
23400
23440
  ];
23401
- var RulesProcessorToolTargetSchema = z79.enum(rulesProcessorToolTargets);
23441
+ var RulesProcessorToolTargetSchema = z80.enum(rulesProcessorToolTargets);
23402
23442
  var formatRulePaths = (rules) => rules.map((r) => join151(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ");
23403
- var RulesFeatureOptionsSchema = z79.looseObject({
23404
- ruleDiscoveryMode: z79.optional(z79.enum(["none", "explicit"])),
23405
- includeLocalRoot: z79.optional(z79.boolean())
23443
+ var RulesFeatureOptionsSchema = z80.looseObject({
23444
+ ruleDiscoveryMode: z80.optional(z80.enum(["none", "explicit"])),
23445
+ includeLocalRoot: z80.optional(z80.boolean())
23406
23446
  });
23407
23447
  var resolveRuleDiscoveryMode = ({
23408
23448
  defaultMode,
@@ -23423,8 +23463,8 @@ var resolveRuleDiscoveryMode = ({
23423
23463
  }
23424
23464
  return parsed.data.ruleDiscoveryMode === "none" ? "auto" : "toon";
23425
23465
  };
23426
- var IncludeLocalRootSchema = z79.looseObject({
23427
- includeLocalRoot: z79.optional(z79.boolean())
23466
+ var IncludeLocalRootSchema = z80.looseObject({
23467
+ includeLocalRoot: z80.optional(z80.boolean())
23428
23468
  });
23429
23469
  var resolveIncludeLocalRoot = (options) => {
23430
23470
  if (!options) return true;