@intellectronica/ruler 0.3.41 → 0.3.42

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.
Files changed (94) hide show
  1. package/README.md +40 -28
  2. package/dist/agents/AbstractAgent.d.ts +53 -0
  3. package/dist/agents/AgentsMdAgent.d.ts +14 -0
  4. package/dist/agents/AiderAgent.d.ts +14 -0
  5. package/dist/agents/AiderAgent.js +3 -1
  6. package/dist/agents/AmazonQCliAgent.d.ts +13 -0
  7. package/dist/agents/AmpAgent.d.ts +6 -0
  8. package/dist/agents/AntigravityAgent.d.ts +10 -0
  9. package/dist/agents/AugmentCodeAgent.d.ts +13 -0
  10. package/dist/agents/ClaudeAgent.d.ts +13 -0
  11. package/dist/agents/ClineAgent.d.ts +9 -0
  12. package/dist/agents/CodexCliAgent.d.ts +31 -0
  13. package/dist/agents/CopilotAgent.d.ts +20 -0
  14. package/dist/agents/CrushAgent.d.ts +14 -0
  15. package/dist/agents/CrushAgent.js +5 -2
  16. package/dist/agents/CursorAgent.d.ts +17 -0
  17. package/dist/agents/FactoryDroidAgent.d.ts +13 -0
  18. package/dist/agents/FirebaseAgent.d.ts +11 -0
  19. package/dist/agents/FirebenderAgent.d.ts +36 -0
  20. package/dist/agents/GeminiCliAgent.d.ts +11 -0
  21. package/dist/agents/GeminiCliAgent.js +2 -2
  22. package/dist/agents/GooseAgent.d.ts +12 -0
  23. package/dist/agents/IAgent.d.ts +72 -0
  24. package/dist/agents/JetBrainsAiAssistantAgent.d.ts +10 -0
  25. package/dist/agents/JulesAgent.d.ts +5 -0
  26. package/dist/agents/JunieAgent.d.ts +12 -0
  27. package/dist/agents/KiloCodeAgent.d.ts +14 -0
  28. package/dist/agents/KiroAgent.d.ts +8 -0
  29. package/dist/agents/MistralVibeAgent.d.ts +31 -0
  30. package/dist/agents/OpenCodeAgent.d.ts +11 -0
  31. package/dist/agents/OpenCodeAgent.js +14 -9
  32. package/dist/agents/OpenHandsAgent.d.ts +8 -0
  33. package/dist/agents/PiAgent.d.ts +9 -0
  34. package/dist/agents/QwenCodeAgent.d.ts +10 -0
  35. package/dist/agents/QwenCodeAgent.js +2 -2
  36. package/dist/agents/RooCodeAgent.d.ts +16 -0
  37. package/dist/agents/TraeAgent.d.ts +10 -0
  38. package/dist/agents/WarpAgent.d.ts +12 -0
  39. package/dist/agents/WindsurfAgent.d.ts +13 -0
  40. package/dist/agents/ZedAgent.d.ts +21 -0
  41. package/dist/agents/ZedAgent.js +5 -2
  42. package/dist/agents/agent-utils.d.ts +5 -0
  43. package/dist/agents/agent-utils.js +8 -5
  44. package/dist/agents/index.d.ts +9 -0
  45. package/dist/cli/commands.d.ts +4 -0
  46. package/dist/cli/commands.js +1 -2
  47. package/dist/cli/handlers.d.ts +41 -0
  48. package/dist/cli/handlers.js +75 -59
  49. package/dist/cli/index.d.ts +2 -0
  50. package/dist/constants.d.ts +35 -0
  51. package/dist/core/ConfigLoader.d.ts +57 -0
  52. package/dist/core/ConfigLoader.js +106 -39
  53. package/dist/core/FileSystemUtils.d.ts +51 -0
  54. package/dist/core/FileSystemUtils.js +37 -17
  55. package/dist/core/GitignoreUtils.d.ts +15 -0
  56. package/dist/core/GitignoreUtils.js +32 -1
  57. package/dist/core/RuleProcessor.d.ts +8 -0
  58. package/dist/core/SkillsProcessor.d.ts +127 -0
  59. package/dist/core/SkillsProcessor.js +104 -218
  60. package/dist/core/SkillsUtils.d.ts +26 -0
  61. package/dist/core/SubagentsProcessor.d.ts +38 -0
  62. package/dist/core/SubagentsUtils.d.ts +34 -0
  63. package/dist/core/UnifiedConfigLoader.d.ts +10 -0
  64. package/dist/core/UnifiedConfigLoader.js +61 -31
  65. package/dist/core/UnifiedConfigTypes.d.ts +95 -0
  66. package/dist/core/agent-selection.d.ts +12 -0
  67. package/dist/core/agent-selection.js +11 -3
  68. package/dist/core/apply-engine.d.ts +69 -0
  69. package/dist/core/apply-engine.js +57 -50
  70. package/dist/core/config-utils.d.ts +14 -0
  71. package/dist/core/config-utils.js +9 -3
  72. package/dist/core/hash.d.ts +2 -0
  73. package/dist/core/path-utils.d.ts +1 -0
  74. package/dist/core/path-utils.js +42 -0
  75. package/dist/core/revert-engine.d.ts +36 -0
  76. package/dist/core/revert-engine.js +70 -9
  77. package/dist/lib.d.ts +13 -0
  78. package/dist/lib.js +16 -3
  79. package/dist/mcp/capabilities.d.ts +20 -0
  80. package/dist/mcp/merge.d.ts +10 -0
  81. package/dist/mcp/merge.js +19 -1
  82. package/dist/mcp/propagateOpenCodeMcp.d.ts +2 -0
  83. package/dist/mcp/propagateOpenCodeMcp.js +21 -9
  84. package/dist/mcp/propagateOpenHandsMcp.d.ts +2 -0
  85. package/dist/mcp/propagateOpenHandsMcp.js +31 -15
  86. package/dist/mcp/validate.d.ts +7 -0
  87. package/dist/mcp/validate.js +6 -1
  88. package/dist/paths/mcp.d.ts +8 -0
  89. package/dist/paths/mcp.js +33 -4
  90. package/dist/revert.d.ts +6 -0
  91. package/dist/revert.js +39 -27
  92. package/dist/types.d.ts +87 -0
  93. package/dist/vscode/settings.d.ts +40 -0
  94. package/package.json +6 -4
package/dist/revert.js CHANGED
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.allAgents = void 0;
37
37
  exports.revertAllAgentConfigs = revertAllAgentConfigs;
38
- const path = __importStar(require("path"));
39
38
  const fs_1 = require("fs");
40
39
  const FileSystemUtils = __importStar(require("./core/FileSystemUtils"));
41
40
  const ConfigLoader_1 = require("./core/ConfigLoader");
@@ -45,7 +44,11 @@ const constants_1 = require("./constants");
45
44
  const revert_engine_1 = require("./core/revert-engine");
46
45
  const agent_selection_1 = require("./core/agent-selection");
47
46
  const config_utils_1 = require("./core/config-utils");
47
+ const GitignoreUtils_1 = require("./core/GitignoreUtils");
48
48
  const agents = agents_1.allAgents;
49
+ const RULER_IGNORE_START_MARKER = '# START Ruler Generated Files';
50
+ const RULER_IGNORE_END_MARKER = '# END Ruler Generated Files';
51
+ const MANAGED_IGNORE_FILES = ['.gitignore', '.git/info/exclude'];
49
52
  /**
50
53
  * Reverts ruler configurations for selected AI agents.
51
54
  */
@@ -55,6 +58,7 @@ async function revertAllAgentConfigs(projectRoot, includedAgents, configPath, ke
55
58
  projectRoot,
56
59
  cliAgents: includedAgents,
57
60
  configPath,
61
+ checkGlobal: !localOnly,
58
62
  });
59
63
  const rulerDir = await FileSystemUtils.findRulerDir(projectRoot, !localOnly);
60
64
  if (!rulerDir) {
@@ -77,18 +81,19 @@ async function revertAllAgentConfigs(projectRoot, includedAgents, configPath, ke
77
81
  // Fall back to the old logic without validation
78
82
  if (config.cliAgents && config.cliAgents.length > 0) {
79
83
  const filters = config.cliAgents.map((n) => n.toLowerCase());
80
- selected = agents.filter((agent) => filters.some((f) => agent.getIdentifier() === f ||
81
- agent.getName().toLowerCase().includes(f)));
84
+ const validAgentIdentifiers = new Set(agents.map((agent) => agent.getIdentifier()));
85
+ selected = agents.filter((agent) => filters.some((f) => (0, agent_selection_1.agentMatchesFilter)(agent, f, validAgentIdentifiers)));
82
86
  }
83
87
  else if (config.defaultAgents && config.defaultAgents.length > 0) {
84
88
  const defaults = config.defaultAgents.map((n) => n.toLowerCase());
89
+ const validAgentIdentifiers = new Set(agents.map((agent) => agent.getIdentifier()));
85
90
  selected = agents.filter((agent) => {
86
91
  const identifier = agent.getIdentifier();
87
92
  const override = config.agentConfigs[identifier]?.enabled;
88
93
  if (override !== undefined) {
89
94
  return override;
90
95
  }
91
- return defaults.some((d) => identifier === d || agent.getName().toLowerCase().includes(d));
96
+ return defaults.some((d) => (0, agent_selection_1.agentMatchesFilter)(agent, d, validAgentIdentifiers));
92
97
  });
93
98
  }
94
99
  else {
@@ -118,10 +123,10 @@ async function revertAllAgentConfigs(projectRoot, includedAgents, configPath, ke
118
123
  // Clean up auxiliary files and directories
119
124
  const cleanupResult = await (0, revert_engine_1.cleanUpAuxiliaryFiles)(projectRoot, verbose, dryRun);
120
125
  totalFilesRemoved += cleanupResult.additionalFilesRemoved;
121
- // Clean .gitignore if reverting all agents
122
- const gitignoreCleaned = !config.cliAgents || config.cliAgents.length === 0
123
- ? await cleanGitignore(projectRoot, verbose, dryRun)
124
- : false;
126
+ // Clean managed ignore blocks if reverting all agents.
127
+ const cleanedIgnoreFiles = !config.cliAgents || config.cliAgents.length === 0
128
+ ? await cleanManagedIgnoreFiles(projectRoot, verbose, dryRun)
129
+ : [];
125
130
  // Display summary
126
131
  const prefix = (0, constants_1.actionPrefix)(dryRun);
127
132
  if (dryRun) {
@@ -139,47 +144,54 @@ async function revertAllAgentConfigs(projectRoot, includedAgents, configPath, ke
139
144
  if (cleanupResult.directoriesRemoved > 0) {
140
145
  console.log(` Empty directories removed: ${cleanupResult.directoriesRemoved}`);
141
146
  }
142
- if (gitignoreCleaned) {
143
- console.log(` .gitignore cleaned: yes`);
147
+ for (const ignoreFile of cleanedIgnoreFiles) {
148
+ console.log(` ${ignoreFile} cleaned: yes`);
144
149
  }
145
150
  }
146
151
  /**
147
- * Removes the ruler-managed block from .gitignore file.
152
+ * Removes the ruler-managed block from ignore files Ruler can update.
148
153
  */
149
- async function cleanGitignore(projectRoot, verbose, dryRun) {
150
- const gitignorePath = path.join(projectRoot, '.gitignore');
154
+ async function cleanManagedIgnoreFiles(projectRoot, verbose, dryRun) {
155
+ const cleanedFiles = [];
156
+ for (const ignoreFile of MANAGED_IGNORE_FILES) {
157
+ if (await cleanIgnoreFile(projectRoot, ignoreFile, verbose, dryRun)) {
158
+ cleanedFiles.push(ignoreFile);
159
+ }
160
+ }
161
+ return cleanedFiles;
162
+ }
163
+ async function cleanIgnoreFile(projectRoot, ignoreFile, verbose, dryRun) {
164
+ const ignorePath = await (0, GitignoreUtils_1.resolveIgnoreFilePath)(projectRoot, ignoreFile);
151
165
  try {
152
- await fs_1.promises.access(gitignorePath);
166
+ await fs_1.promises.access(ignorePath);
153
167
  }
154
168
  catch {
155
- (0, constants_1.logVerbose)('No .gitignore file found', verbose);
169
+ (0, constants_1.logVerbose)(`No ${ignoreFile} file found`, verbose);
156
170
  return false;
157
171
  }
158
- const content = await fs_1.promises.readFile(gitignorePath, 'utf8');
159
- const startMarker = '# START Ruler Generated Files';
160
- const endMarker = '# END Ruler Generated Files';
161
- const startIndex = content.indexOf(startMarker);
162
- const endIndex = content.indexOf(endMarker);
172
+ const content = await fs_1.promises.readFile(ignorePath, 'utf8');
173
+ const startIndex = content.indexOf(RULER_IGNORE_START_MARKER);
174
+ const endIndex = content.indexOf(RULER_IGNORE_END_MARKER);
163
175
  if (startIndex === -1 || endIndex === -1) {
164
- (0, constants_1.logVerbose)('No ruler-managed block found in .gitignore', verbose);
176
+ (0, constants_1.logVerbose)(`No ruler-managed block found in ${ignoreFile}`, verbose);
165
177
  return false;
166
178
  }
167
179
  const prefix = (0, constants_1.actionPrefix)(dryRun);
168
180
  if (dryRun) {
169
- (0, constants_1.logVerbose)(`${prefix} Would remove ruler block from .gitignore`, verbose);
181
+ (0, constants_1.logVerbose)(`${prefix} Would remove ruler block from ${ignoreFile}`, verbose);
170
182
  }
171
183
  else {
172
184
  const beforeBlock = content.substring(0, startIndex);
173
- const afterBlock = content.substring(endIndex + endMarker.length);
185
+ const afterBlock = content.substring(endIndex + RULER_IGNORE_END_MARKER.length);
174
186
  let newContent = beforeBlock + afterBlock;
175
187
  newContent = newContent.replace(/\n{3,}/g, '\n\n'); // Replace 3+ newlines with 2
176
188
  if (newContent.trim() === '') {
177
- await fs_1.promises.unlink(gitignorePath);
178
- (0, constants_1.logVerbose)(`${prefix} Removed empty .gitignore file`, verbose);
189
+ await fs_1.promises.unlink(ignorePath);
190
+ (0, constants_1.logVerbose)(`${prefix} Removed empty ${ignoreFile} file`, verbose);
179
191
  }
180
192
  else {
181
- await fs_1.promises.writeFile(gitignorePath, newContent);
182
- (0, constants_1.logVerbose)(`${prefix} Removed ruler block from .gitignore`, verbose);
193
+ await fs_1.promises.writeFile(ignorePath, newContent);
194
+ (0, constants_1.logVerbose)(`${prefix} Removed ruler block from ${ignoreFile}`, verbose);
183
195
  }
184
196
  }
185
197
  return true;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Types for Model Context Protocol (MCP) server configuration.
3
+ */
4
+ export type McpStrategy = 'merge' | 'overwrite';
5
+ /** MCP configuration for an agent or global. */
6
+ export interface McpConfig {
7
+ /** Enable or disable MCP propagation (merge or overwrite). */
8
+ enabled?: boolean;
9
+ /** Merge strategy: 'merge' to merge servers, 'overwrite' to replace config. */
10
+ strategy?: McpStrategy;
11
+ }
12
+ /** Global MCP configuration section (same as agent-specific config). */
13
+ export type GlobalMcpConfig = McpConfig;
14
+ /** Gitignore configuration for automatic .gitignore file updates. */
15
+ export interface GitignoreConfig {
16
+ /** Enable or disable automatic .gitignore updates. */
17
+ enabled?: boolean;
18
+ /** Write managed ignore entries to .git/info/exclude instead of .gitignore. */
19
+ local?: boolean;
20
+ }
21
+ /** Backup configuration for .bak file generation. */
22
+ export interface BackupConfig {
23
+ /** Enable or disable creation of .bak backup files. */
24
+ enabled?: boolean;
25
+ }
26
+ /** Skills configuration for automatic skills distribution. */
27
+ export interface SkillsConfig {
28
+ /** Enable or disable skills support. */
29
+ enabled?: boolean;
30
+ }
31
+ /** Information about a discovered skill. */
32
+ export interface SkillInfo {
33
+ /** Name of the skill (directory name). */
34
+ name: string;
35
+ /** Absolute path to the skill directory. */
36
+ path: string;
37
+ /** Whether the directory contains a SKILL.md file. */
38
+ hasSkillMd: boolean;
39
+ /** Whether this is a valid skill. */
40
+ valid: boolean;
41
+ /** Error message if invalid. */
42
+ error?: string;
43
+ }
44
+ /** Subagents configuration for automatic subagent distribution. */
45
+ export interface SubagentsConfig {
46
+ /** Enable or disable subagents support. */
47
+ enabled?: boolean;
48
+ /**
49
+ * When true, Ruler may delete previously generated native subagent
50
+ * directories that are stale (disabled, no source definitions, or
51
+ * deselected targets). Defaults to false (non-destructive).
52
+ */
53
+ cleanup_orphaned?: boolean;
54
+ /**
55
+ * When true, `.ruler/agents/*.md` are also concatenated into the
56
+ * generated top-level rule files (CLAUDE.md, AGENTS.md, Copilot
57
+ * instructions, etc.). When false (default), `.ruler/agents/` is
58
+ * skipped during rule concatenation, mirroring `.ruler/skills/`.
59
+ */
60
+ include_in_rules?: boolean;
61
+ }
62
+ /** Frontmatter fields recognised on a source subagent definition. */
63
+ export interface SubagentFrontmatter {
64
+ name: string;
65
+ description: string;
66
+ tools?: string[];
67
+ model?: string;
68
+ readonly?: boolean;
69
+ is_background?: boolean;
70
+ }
71
+ /** Information about a discovered subagent. */
72
+ export interface SubagentInfo {
73
+ /** Name of the subagent (filename stem and frontmatter `name`). */
74
+ name: string;
75
+ /** Absolute path to the source `.md` file. */
76
+ path: string;
77
+ /** Relative `.md` path under `.ruler/agents/` (preserves nested layout). */
78
+ sourceRelativePath?: string;
79
+ /** Parsed frontmatter (only present when valid). */
80
+ frontmatter?: SubagentFrontmatter;
81
+ /** Body content after the frontmatter delimiter. */
82
+ body?: string;
83
+ /** Whether this subagent passed validation. */
84
+ valid: boolean;
85
+ /** Error message if invalid. */
86
+ error?: string;
87
+ }
@@ -0,0 +1,40 @@
1
+ import { McpStrategy } from '../types';
2
+ /**
3
+ * VSCode settings.json structure for Augment MCP configuration
4
+ */
5
+ export interface VSCodeSettings {
6
+ 'augment.advanced'?: {
7
+ mcpServers?: AugmentMcpServer[];
8
+ [key: string]: unknown;
9
+ };
10
+ [key: string]: unknown;
11
+ }
12
+ /**
13
+ * Augment MCP server configuration format
14
+ */
15
+ export interface AugmentMcpServer {
16
+ name: string;
17
+ command: string;
18
+ args?: string[];
19
+ env?: Record<string, string>;
20
+ }
21
+ /**
22
+ * Read VSCode settings.json file
23
+ */
24
+ export declare function readVSCodeSettings(settingsPath: string): Promise<VSCodeSettings>;
25
+ /**
26
+ * Write VSCode settings.json file
27
+ */
28
+ export declare function writeVSCodeSettings(settingsPath: string, settings: VSCodeSettings): Promise<void>;
29
+ /**
30
+ * Transform ruler MCP config to Augment MCP server array format
31
+ */
32
+ export declare function transformRulerToAugmentMcp(rulerMcpJson: Record<string, unknown>): AugmentMcpServer[];
33
+ /**
34
+ * Merge MCP servers into VSCode settings using the specified strategy
35
+ */
36
+ export declare function mergeAugmentMcpServers(existingSettings: VSCodeSettings, newServers: AugmentMcpServer[], strategy: McpStrategy): VSCodeSettings;
37
+ /**
38
+ * Get the VSCode settings.json path for a project (local)
39
+ */
40
+ export declare function getVSCodeSettingsPath(projectRoot: string): string;
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.41",
3
+ "version": "0.3.42",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
+ "types": "dist/lib.d.ts",
6
7
  "scripts": {
7
8
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
8
- "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
9
- "test": "jest",
9
+ "format": "prettier --write package.json package-lock.json tsconfig.json README.md \".github/**/*.yml\" \"src/**/*.{ts,tsx,json,md}\" \"tests/**/*.{ts,tsx,json,md}\"",
10
+ "format:check": "prettier --check package.json package-lock.json tsconfig.json README.md \".github/**/*.yml\" \"src/**/*.{ts,tsx,json,md}\" \"tests/**/*.{ts,tsx,json,md}\"",
11
+ "test": "jest --coverage",
10
12
  "test:watch": "jest --watch",
11
13
  "test:coverage": "jest --coverage",
12
14
  "test:integration": "jest tests/e2e/ruler.integration.test.ts --verbose",
@@ -66,7 +68,7 @@
66
68
  },
67
69
  "dependencies": {
68
70
  "@iarna/toml": "^2.2.5",
69
- "js-yaml": "^4.1.0",
71
+ "js-yaml": "^4.1.1",
70
72
  "yargs": "^18.0.0",
71
73
  "zod": "^4.1.12"
72
74
  }