byterover-cli 1.1.0 → 1.2.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.
Files changed (103) hide show
  1. package/README.md +8 -4
  2. package/dist/commands/mcp.d.ts +13 -0
  3. package/dist/commands/mcp.js +61 -0
  4. package/dist/core/domain/cipher/agent-events/types.d.ts +44 -1
  5. package/dist/core/domain/entities/agent.js +72 -18
  6. package/dist/core/domain/entities/connector-type.d.ts +2 -1
  7. package/dist/core/domain/entities/connector-type.js +2 -1
  8. package/dist/core/interfaces/connectors/connector-types.d.ts +13 -0
  9. package/dist/core/interfaces/i-mcp-config-writer.d.ts +40 -0
  10. package/dist/core/interfaces/i-mcp-config-writer.js +1 -0
  11. package/dist/core/interfaces/i-rule-template-service.d.ts +4 -2
  12. package/dist/core/interfaces/transport/i-transport-client.d.ts +7 -0
  13. package/dist/infra/cipher/agent/cipher-agent.d.ts +8 -0
  14. package/dist/infra/cipher/agent/cipher-agent.js +16 -0
  15. package/dist/infra/cipher/llm/context/context-manager.d.ts +8 -0
  16. package/dist/infra/cipher/llm/context/context-manager.js +16 -0
  17. package/dist/infra/cipher/llm/internal-llm-service.d.ts +4 -0
  18. package/dist/infra/cipher/llm/internal-llm-service.js +38 -10
  19. package/dist/infra/cipher/session/chat-session.d.ts +3 -0
  20. package/dist/infra/cipher/session/chat-session.js +7 -1
  21. package/dist/infra/cipher/tools/implementations/curate-tool.d.ts +1 -8
  22. package/dist/infra/cipher/tools/implementations/curate-tool.js +360 -22
  23. package/dist/infra/connectors/connector-manager.js +2 -0
  24. package/dist/infra/connectors/mcp/index.d.ts +4 -0
  25. package/dist/infra/connectors/mcp/index.js +4 -0
  26. package/dist/infra/connectors/mcp/json-mcp-config-writer.d.ts +26 -0
  27. package/dist/infra/connectors/mcp/json-mcp-config-writer.js +71 -0
  28. package/dist/infra/connectors/mcp/mcp-connector-config.d.ts +229 -0
  29. package/dist/infra/connectors/mcp/mcp-connector-config.js +173 -0
  30. package/dist/infra/connectors/mcp/mcp-connector.d.ts +80 -0
  31. package/dist/infra/connectors/mcp/mcp-connector.js +324 -0
  32. package/dist/infra/connectors/mcp/toml-mcp-config-writer.d.ts +45 -0
  33. package/dist/infra/connectors/mcp/toml-mcp-config-writer.js +134 -0
  34. package/dist/infra/connectors/rules/rules-connector.d.ts +1 -8
  35. package/dist/infra/connectors/rules/rules-connector.js +20 -85
  36. package/dist/infra/connectors/shared/rule-file-manager.d.ts +72 -0
  37. package/dist/infra/connectors/shared/rule-file-manager.js +119 -0
  38. package/dist/infra/connectors/shared/template-service.d.ts +10 -1
  39. package/dist/infra/connectors/shared/template-service.js +53 -16
  40. package/dist/infra/mcp/index.d.ts +2 -0
  41. package/dist/infra/mcp/index.js +2 -0
  42. package/dist/infra/mcp/mcp-server.d.ts +58 -0
  43. package/dist/infra/mcp/mcp-server.js +178 -0
  44. package/dist/infra/mcp/tools/brv-curate-tool.d.ts +23 -0
  45. package/dist/infra/mcp/tools/brv-curate-tool.js +68 -0
  46. package/dist/infra/mcp/tools/brv-query-tool.d.ts +17 -0
  47. package/dist/infra/mcp/tools/brv-query-tool.js +68 -0
  48. package/dist/infra/mcp/tools/index.d.ts +3 -0
  49. package/dist/infra/mcp/tools/index.js +3 -0
  50. package/dist/infra/mcp/tools/task-result-waiter.d.ts +30 -0
  51. package/dist/infra/mcp/tools/task-result-waiter.js +56 -0
  52. package/dist/infra/process/agent-worker.js +37 -0
  53. package/dist/infra/repl/commands/curate-command.js +2 -2
  54. package/dist/infra/transport/socket-io-transport-client.d.ts +7 -0
  55. package/dist/infra/transport/socket-io-transport-client.js +25 -0
  56. package/dist/infra/transport/socket-io-transport-server.js +4 -0
  57. package/dist/infra/usecase/connectors-use-case.d.ts +4 -0
  58. package/dist/infra/usecase/connectors-use-case.js +29 -10
  59. package/dist/infra/usecase/init-use-case.js +2 -3
  60. package/dist/infra/usecase/status-use-case.d.ts +10 -0
  61. package/dist/infra/usecase/status-use-case.js +53 -0
  62. package/dist/resources/prompts/curate.yml +107 -4
  63. package/dist/templates/mcp-base.md +1 -0
  64. package/dist/templates/sections/mcp-workflow.md +13 -0
  65. package/dist/tui/app.js +4 -1
  66. package/dist/tui/components/command-details.js +1 -1
  67. package/dist/tui/components/execution/execution-changes.d.ts +2 -0
  68. package/dist/tui/components/execution/execution-changes.js +5 -1
  69. package/dist/tui/components/execution/execution-content.d.ts +2 -0
  70. package/dist/tui/components/execution/execution-content.js +8 -18
  71. package/dist/tui/components/execution/execution-input.d.ts +2 -0
  72. package/dist/tui/components/execution/execution-input.js +6 -4
  73. package/dist/tui/components/execution/execution-progress.d.ts +2 -0
  74. package/dist/tui/components/execution/execution-progress.js +6 -2
  75. package/dist/tui/components/execution/expanded-log-view.d.ts +20 -0
  76. package/dist/tui/components/execution/expanded-log-view.js +75 -0
  77. package/dist/tui/components/execution/expanded-message-view.d.ts +24 -0
  78. package/dist/tui/components/execution/expanded-message-view.js +68 -0
  79. package/dist/tui/components/execution/index.d.ts +2 -0
  80. package/dist/tui/components/execution/index.js +2 -0
  81. package/dist/tui/components/execution/log-item.d.ts +4 -0
  82. package/dist/tui/components/execution/log-item.js +2 -2
  83. package/dist/tui/components/footer.js +1 -1
  84. package/dist/tui/components/index.d.ts +2 -1
  85. package/dist/tui/components/index.js +2 -1
  86. package/dist/tui/components/init.js +2 -9
  87. package/dist/tui/components/logo.js +4 -3
  88. package/dist/tui/components/markdown.d.ts +13 -0
  89. package/dist/tui/components/markdown.js +88 -0
  90. package/dist/tui/components/message-item.js +1 -1
  91. package/dist/tui/components/onboarding/onboarding-flow.js +1 -1
  92. package/dist/tui/components/suggestions.js +3 -3
  93. package/dist/tui/contexts/mode-context.js +6 -2
  94. package/dist/tui/hooks/index.d.ts +1 -0
  95. package/dist/tui/hooks/index.js +1 -0
  96. package/dist/tui/hooks/use-is-latest-version.d.ts +6 -0
  97. package/dist/tui/hooks/use-is-latest-version.js +22 -0
  98. package/dist/tui/views/command-view.d.ts +1 -1
  99. package/dist/tui/views/command-view.js +83 -98
  100. package/dist/tui/views/logs-view.d.ts +8 -0
  101. package/dist/tui/views/logs-view.js +55 -27
  102. package/oclif.manifest.json +26 -1
  103. package/package.json +9 -1
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { AGENT_CONNECTOR_CONFIG } from '../../../core/domain/entities/agent.js';
3
- import { BRV_RULE_MARKERS, BRV_RULE_TAG } from '../shared/constants.js';
3
+ import { RuleFileManager } from '../shared/rule-file-manager.js';
4
4
  import { RULES_CONNECTOR_CONFIGS } from './rules-connector-config.js';
5
5
  /**
6
6
  * Connector that integrates BRV with coding agents via rule files.
@@ -10,12 +10,17 @@ export class RulesConnector {
10
10
  type = 'rules';
11
11
  fileService;
12
12
  projectRoot;
13
+ ruleFileManager;
13
14
  supportedAgents;
14
15
  templateService;
15
16
  constructor(options) {
16
17
  this.fileService = options.fileService;
17
18
  this.projectRoot = options.projectRoot;
18
19
  this.templateService = options.templateService;
20
+ this.ruleFileManager = new RuleFileManager({
21
+ fileService: options.fileService,
22
+ projectRoot: options.projectRoot,
23
+ });
19
24
  this.supportedAgents = Object.entries(AGENT_CONNECTOR_CONFIG)
20
25
  .filter(([_, config]) => config.supported.includes(this.type))
21
26
  .map(([agent]) => agent);
@@ -28,36 +33,10 @@ export class RulesConnector {
28
33
  }
29
34
  async install(agent) {
30
35
  const config = RULES_CONNECTOR_CONFIGS[agent];
31
- const fullPath = path.join(this.projectRoot, config.filePath);
32
36
  try {
33
- const exists = await this.fileService.exists(fullPath);
34
- if (exists) {
35
- const content = await this.fileService.read(fullPath);
36
- const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
37
- // File exists but no BRV content or different agent - append or replace based on writeMode
38
- const ruleContent = await this.templateService.generateRuleContent(agent);
39
- if (config.writeMode === 'overwrite') {
40
- await this.fileService.write(ruleContent, fullPath, 'overwrite');
41
- }
42
- else if (hasMarkers) {
43
- // Replace existing markers section
44
- const newContent = this.replaceMarkerSection(content, ruleContent);
45
- await this.fileService.write(newContent, fullPath, 'overwrite');
46
- }
47
- else {
48
- // Append to file
49
- await this.fileService.write(ruleContent, fullPath, 'append');
50
- }
51
- return {
52
- alreadyInstalled: false,
53
- configPath: config.filePath,
54
- message: `Rules connector installed for ${agent}`,
55
- success: true,
56
- };
57
- }
58
- // File doesn't exist - create it
59
- const ruleContent = await this.templateService.generateRuleContent(agent);
60
- await this.fileService.write(ruleContent, fullPath, 'overwrite');
37
+ const ruleContent = await this.templateService.generateRuleContent(agent, this.type);
38
+ // Write the rule content to the file
39
+ await this.ruleFileManager.install(config.filePath, config.writeMode, ruleContent);
61
40
  return {
62
41
  alreadyInstalled: false,
63
42
  configPath: config.filePath,
@@ -81,8 +60,8 @@ export class RulesConnector {
81
60
  const config = RULES_CONNECTOR_CONFIGS[agent];
82
61
  const fullPath = path.join(this.projectRoot, config.filePath);
83
62
  try {
84
- const exists = await this.fileService.exists(fullPath);
85
- if (!exists) {
63
+ const { fileExists, hasMarkers } = await this.ruleFileManager.status(config.filePath);
64
+ if (!fileExists) {
86
65
  return {
87
66
  configExists: false,
88
67
  configPath: config.filePath,
@@ -90,12 +69,10 @@ export class RulesConnector {
90
69
  };
91
70
  }
92
71
  const content = await this.fileService.read(fullPath);
93
- // Check for boundary markers (new format)
94
- const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
95
- const hasAgentTag = content.includes(`${BRV_RULE_TAG} ${agent}`);
72
+ const hasMcpTools = content.includes('brv-query') || content.includes('brv-curate');
96
73
  // For overwrite files, any BRV content means installed
97
74
  // For append files, need both markers and agent tag
98
- const installed = config.writeMode === 'overwrite' ? hasMarkers || hasAgentTag : hasMarkers && hasAgentTag;
75
+ const installed = hasMarkers && !hasMcpTools;
99
76
  return {
100
77
  configExists: true,
101
78
  configPath: config.filePath,
@@ -113,10 +90,9 @@ export class RulesConnector {
113
90
  }
114
91
  async uninstall(agent) {
115
92
  const config = RULES_CONNECTOR_CONFIGS[agent];
116
- const fullPath = path.join(this.projectRoot, config.filePath);
117
93
  try {
118
- const exists = await this.fileService.exists(fullPath);
119
- if (!exists) {
94
+ const { fileExists, hasLegacyTag, hasMarkers } = await this.ruleFileManager.status(config.filePath);
95
+ if (!fileExists) {
120
96
  return {
121
97
  configPath: config.filePath,
122
98
  message: `Rule file does not exist: ${config.filePath}`,
@@ -124,11 +100,7 @@ export class RulesConnector {
124
100
  wasInstalled: false,
125
101
  };
126
102
  }
127
- const content = await this.fileService.read(fullPath);
128
- const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
129
103
  if (!hasMarkers) {
130
- // Check for legacy format (footer tag without markers)
131
- const hasLegacyTag = content.includes(`${BRV_RULE_TAG} ${agent}`);
132
104
  if (!hasLegacyTag) {
133
105
  return {
134
106
  configPath: config.filePath,
@@ -145,24 +117,14 @@ export class RulesConnector {
145
117
  wasInstalled: true,
146
118
  };
147
119
  }
148
- // Remove the section between markers (inclusive)
149
- if (config.writeMode === 'overwrite') {
150
- // For dedicated files, delete the entire file
151
- await this.fileService.delete(fullPath);
152
- }
153
- else {
154
- // For shared files, remove only the BRV section
155
- const newContent = this.removeMarkerSection(content);
156
- // If file would be empty, delete it; otherwise write the new content
157
- await (newContent.trim() === ''
158
- ? this.fileService.delete(fullPath)
159
- : this.fileService.write(newContent, fullPath, 'overwrite'));
160
- }
120
+ const result = await this.ruleFileManager.uninstall(config.filePath, config.writeMode);
161
121
  return {
162
122
  configPath: config.filePath,
163
- message: `Rules connector uninstalled for ${agent}`,
123
+ message: result.wasInstalled
124
+ ? `Rules connector uninstalled for ${agent}`
125
+ : `Rules connector is not installed for ${agent}`,
164
126
  success: true,
165
- wasInstalled: true,
127
+ wasInstalled: result.wasInstalled,
166
128
  };
167
129
  }
168
130
  catch (error) {
@@ -174,31 +136,4 @@ export class RulesConnector {
174
136
  };
175
137
  }
176
138
  }
177
- /**
178
- * Removes the section between BRV markers (inclusive).
179
- */
180
- removeMarkerSection(content) {
181
- const startIndex = content.indexOf(BRV_RULE_MARKERS.START);
182
- const endIndex = content.indexOf(BRV_RULE_MARKERS.END);
183
- if (startIndex === -1 || endIndex === -1) {
184
- return content;
185
- }
186
- const before = content.slice(0, startIndex);
187
- const after = content.slice(endIndex + BRV_RULE_MARKERS.END.length);
188
- // Clean up extra newlines
189
- return (before + after).replaceAll(/\n{3,}/g, '\n\n').trim();
190
- }
191
- /**
192
- * Replaces the section between BRV markers with new content.
193
- */
194
- replaceMarkerSection(content, newRuleContent) {
195
- const startIndex = content.indexOf(BRV_RULE_MARKERS.START);
196
- const endIndex = content.indexOf(BRV_RULE_MARKERS.END);
197
- if (startIndex === -1 || endIndex === -1) {
198
- return content;
199
- }
200
- const before = content.slice(0, startIndex);
201
- const after = content.slice(endIndex + BRV_RULE_MARKERS.END.length);
202
- return before + newRuleContent + after;
203
- }
204
139
  }
@@ -0,0 +1,72 @@
1
+ import type { IFileService, WriteMode } from '../../../core/interfaces/i-file-service.js';
2
+ /**
3
+ * Result of a rule file installation operation.
4
+ */
5
+ export type RuleFileInstallResult = {
6
+ /** Whether the content was newly installed (false if replaced existing) */
7
+ isNew: boolean;
8
+ /** Whether the operation succeeded */
9
+ success: boolean;
10
+ };
11
+ /**
12
+ * Result of a rule file uninstallation operation.
13
+ */
14
+ export type RuleFileUninstallResult = {
15
+ /** Whether the operation succeeded */
16
+ success: boolean;
17
+ /** Whether there was content to remove */
18
+ wasInstalled: boolean;
19
+ };
20
+ /**
21
+ * Result of a rule file status check.
22
+ */
23
+ export type RuleFileStatusResult = {
24
+ /** Whether the file exists */
25
+ fileExists: boolean;
26
+ /** Whether the file contains legacy BRV tag (without markers) */
27
+ hasLegacyTag: boolean;
28
+ /** Whether the file contains BRV markers */
29
+ hasMarkers: boolean;
30
+ };
31
+ /**
32
+ * Manages rule file operations including installation, uninstallation,
33
+ * and marker section manipulation.
34
+ *
35
+ * This class centralizes the logic for working with rule files that use
36
+ * BRV markers to delimit managed content sections.
37
+ */
38
+ export declare class RuleFileManager {
39
+ private readonly fileService;
40
+ private readonly projectRoot;
41
+ constructor(options: {
42
+ fileService: IFileService;
43
+ projectRoot: string;
44
+ });
45
+ /**
46
+ * Install rule content into a file.
47
+ *
48
+ * @param filePath - Relative path to the rule file
49
+ * @param writeMode - How to write the content ('overwrite' or 'append')
50
+ * @param ruleContent - The rule content to write (should include markers)
51
+ */
52
+ install(filePath: string, writeMode: WriteMode, ruleContent: string): Promise<RuleFileInstallResult>;
53
+ /**
54
+ * Removes the section between BRV markers (inclusive).
55
+ */
56
+ removeMarkerSection(content: string): string;
57
+ /**
58
+ * Replaces the section between BRV markers with new content.
59
+ */
60
+ replaceMarkerSection(content: string, newRuleContent: string): string;
61
+ /**
62
+ * Check the status of rule content in a file.
63
+ */
64
+ status(filePath: string): Promise<RuleFileStatusResult>;
65
+ /**
66
+ * Uninstall rule content from a file.
67
+ *
68
+ * @param filePath - Relative path to the rule file
69
+ * @param writeMode - How the content was written ('overwrite' or 'append')
70
+ */
71
+ uninstall(filePath: string, writeMode: WriteMode): Promise<RuleFileUninstallResult>;
72
+ }
@@ -0,0 +1,119 @@
1
+ import path from 'node:path';
2
+ import { BRV_RULE_MARKERS, BRV_RULE_TAG } from './constants.js';
3
+ /**
4
+ * Manages rule file operations including installation, uninstallation,
5
+ * and marker section manipulation.
6
+ *
7
+ * This class centralizes the logic for working with rule files that use
8
+ * BRV markers to delimit managed content sections.
9
+ */
10
+ export class RuleFileManager {
11
+ fileService;
12
+ projectRoot;
13
+ constructor(options) {
14
+ this.fileService = options.fileService;
15
+ this.projectRoot = options.projectRoot;
16
+ }
17
+ /**
18
+ * Install rule content into a file.
19
+ *
20
+ * @param filePath - Relative path to the rule file
21
+ * @param writeMode - How to write the content ('overwrite' or 'append')
22
+ * @param ruleContent - The rule content to write (should include markers)
23
+ */
24
+ async install(filePath, writeMode, ruleContent) {
25
+ const fullPath = path.join(this.projectRoot, filePath);
26
+ const exists = await this.fileService.exists(fullPath);
27
+ if (exists) {
28
+ const content = await this.fileService.read(fullPath);
29
+ const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
30
+ if (writeMode === 'overwrite') {
31
+ await this.fileService.write(ruleContent, fullPath, 'overwrite');
32
+ }
33
+ else if (hasMarkers) {
34
+ // Replace existing markers section
35
+ const newContent = this.replaceMarkerSection(content, ruleContent);
36
+ await this.fileService.write(newContent, fullPath, 'overwrite');
37
+ }
38
+ else {
39
+ // Append to file
40
+ await this.fileService.write(ruleContent, fullPath, 'append');
41
+ }
42
+ return { isNew: !hasMarkers, success: true };
43
+ }
44
+ // File doesn't exist - create it
45
+ await this.fileService.write(ruleContent, fullPath, 'overwrite');
46
+ return { isNew: true, success: true };
47
+ }
48
+ /**
49
+ * Removes the section between BRV markers (inclusive).
50
+ */
51
+ removeMarkerSection(content) {
52
+ const startIndex = content.indexOf(BRV_RULE_MARKERS.START);
53
+ const endIndex = content.indexOf(BRV_RULE_MARKERS.END);
54
+ if (startIndex === -1 || endIndex === -1) {
55
+ return content;
56
+ }
57
+ const before = content.slice(0, startIndex);
58
+ const after = content.slice(endIndex + BRV_RULE_MARKERS.END.length);
59
+ // Clean up extra newlines
60
+ return (before + after).replaceAll(/\n{3,}/g, '\n\n').trim();
61
+ }
62
+ /**
63
+ * Replaces the section between BRV markers with new content.
64
+ */
65
+ replaceMarkerSection(content, newRuleContent) {
66
+ const startIndex = content.indexOf(BRV_RULE_MARKERS.START);
67
+ const endIndex = content.indexOf(BRV_RULE_MARKERS.END);
68
+ if (startIndex === -1 || endIndex === -1) {
69
+ return content;
70
+ }
71
+ const before = content.slice(0, startIndex);
72
+ const after = content.slice(endIndex + BRV_RULE_MARKERS.END.length);
73
+ return before + newRuleContent + after;
74
+ }
75
+ /**
76
+ * Check the status of rule content in a file.
77
+ */
78
+ async status(filePath) {
79
+ const fullPath = path.join(this.projectRoot, filePath);
80
+ const fileExists = await this.fileService.exists(fullPath);
81
+ if (!fileExists) {
82
+ return { fileExists: false, hasLegacyTag: false, hasMarkers: false };
83
+ }
84
+ const content = await this.fileService.read(fullPath);
85
+ const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
86
+ const hasLegacyTag = content.includes(BRV_RULE_TAG);
87
+ return { fileExists: true, hasLegacyTag, hasMarkers };
88
+ }
89
+ /**
90
+ * Uninstall rule content from a file.
91
+ *
92
+ * @param filePath - Relative path to the rule file
93
+ * @param writeMode - How the content was written ('overwrite' or 'append')
94
+ */
95
+ async uninstall(filePath, writeMode) {
96
+ const fullPath = path.join(this.projectRoot, filePath);
97
+ const exists = await this.fileService.exists(fullPath);
98
+ if (!exists) {
99
+ return { success: true, wasInstalled: false };
100
+ }
101
+ const content = await this.fileService.read(fullPath);
102
+ const hasMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
103
+ if (!hasMarkers) {
104
+ return { success: true, wasInstalled: false };
105
+ }
106
+ if (writeMode === 'overwrite') {
107
+ // For dedicated files, delete the entire file
108
+ await this.fileService.delete(fullPath);
109
+ }
110
+ else {
111
+ // For shared files, remove only the BRV section
112
+ const newContent = this.removeMarkerSection(content);
113
+ await (newContent.trim() === ''
114
+ ? this.fileService.delete(fullPath)
115
+ : this.fileService.write(newContent, fullPath, 'overwrite'));
116
+ }
117
+ return { success: true, wasInstalled: true };
118
+ }
119
+ }
@@ -1,4 +1,5 @@
1
1
  import type { Agent } from '../../../core/domain/entities/agent.js';
2
+ import type { ConnectorType } from '../../../core/domain/entities/connector-type.js';
2
3
  import type { IRuleTemplateService } from '../../../core/interfaces/i-rule-template-service.js';
3
4
  import type { ITemplateLoader } from '../../../core/interfaces/i-template-loader.js';
4
5
  /**
@@ -14,5 +15,13 @@ export declare class RuleTemplateService implements IRuleTemplateService {
14
15
  * @returns Promise resolving to the rule content as a string.
15
16
  * @throws Error if templates cannot be loaded or assembled.
16
17
  */
17
- generateRuleContent(agent: Agent): Promise<string>;
18
+ generateRuleContent(agent: Agent, type?: ConnectorType): Promise<string>;
19
+ /**
20
+ * Generates CLI mode content with full workflow and command reference.
21
+ */
22
+ private generateCliContent;
23
+ /**
24
+ * Generates MCP mode content with concise tool-focused instructions.
25
+ */
26
+ private generateMcpContent;
18
27
  }
@@ -60,29 +60,66 @@ export class RuleTemplateService {
60
60
  * @returns Promise resolving to the rule content as a string.
61
61
  * @throws Error if templates cannot be loaded or assembled.
62
62
  */
63
- async generateRuleContent(agent) {
63
+ async generateRuleContent(agent, type) {
64
64
  try {
65
65
  // Load section templates
66
- const workflow = await this.templateLoader.loadSection('workflow');
67
- const commandReference = await this.templateLoader.loadSection('command-reference');
68
- // Load base template
69
- const baseTemplate = await this.templateLoader.loadTemplate('base.md');
70
- // Assemble context for variable substitution
71
- const context = {
72
- /* eslint-disable camelcase */
73
- agent_name: agent,
74
- command_reference: commandReference,
75
- workflow,
76
- /* eslint-enable camelcase */
77
- };
78
- // Substitute variables and get content
79
- const content = this.templateLoader.substituteVariables(baseTemplate, context);
66
+ let content;
67
+ switch (type) {
68
+ case 'mcp': {
69
+ content = await this.generateMcpContent();
70
+ break;
71
+ }
72
+ case 'rules': {
73
+ content = await this.generateCliContent(agent);
74
+ break;
75
+ }
76
+ default: {
77
+ throw new Error(`Unsupported connector type: ${type}`);
78
+ }
79
+ }
80
80
  // Add agent-specific header if available
81
81
  const header = guideHeaders.find((h) => h.agent === agent)?.value || '';
82
82
  return wrapContentWithBoundaryMarkers(content, agent, header);
83
83
  }
84
84
  catch (error) {
85
- throw new Error(`Failed to generate rule content for agent '${agent}': ${error instanceof Error ? error.message : String(error)}`);
85
+ throw new Error(`Failed to generate rule content for agent '${agent}' - type '${type}': ${error instanceof Error ? error.message : String(error)}`);
86
86
  }
87
87
  }
88
+ /**
89
+ * Generates CLI mode content with full workflow and command reference.
90
+ */
91
+ async generateCliContent(agent) {
92
+ // Load section templates
93
+ const workflow = await this.templateLoader.loadSection('workflow');
94
+ const commandReference = await this.templateLoader.loadSection('command-reference');
95
+ // Load base template
96
+ const baseTemplate = await this.templateLoader.loadTemplate('base.md');
97
+ // Assemble context for variable substitution
98
+ const context = {
99
+ /* eslint-disable camelcase */
100
+ agent_name: agent,
101
+ command_reference: commandReference,
102
+ workflow,
103
+ /* eslint-enable camelcase */
104
+ };
105
+ // Substitute variables and get content
106
+ return this.templateLoader.substituteVariables(baseTemplate, context);
107
+ }
108
+ /**
109
+ * Generates MCP mode content with concise tool-focused instructions.
110
+ */
111
+ async generateMcpContent() {
112
+ // Load MCP-specific section
113
+ const mcpWorkflow = await this.templateLoader.loadSection('mcp-workflow');
114
+ // Load MCP base template
115
+ const mcpBaseTemplate = await this.templateLoader.loadTemplate('mcp-base.md');
116
+ // Assemble context for variable substitution
117
+ const context = {
118
+ /* eslint-disable camelcase */
119
+ mcp_workflow: mcpWorkflow,
120
+ /* eslint-enable camelcase */
121
+ };
122
+ // Substitute variables and get content
123
+ return this.templateLoader.substituteVariables(mcpBaseTemplate, context);
124
+ }
88
125
  }
@@ -0,0 +1,2 @@
1
+ export { ByteRoverMcpServer, type McpServerConfig } from './mcp-server.js';
2
+ export { registerBrvCurateTool, registerBrvQueryTool, waitForTaskResult } from './tools/index.js';
@@ -0,0 +1,2 @@
1
+ export { ByteRoverMcpServer } from './mcp-server.js';
2
+ export { registerBrvCurateTool, registerBrvQueryTool, waitForTaskResult } from './tools/index.js';
@@ -0,0 +1,58 @@
1
+ export interface McpServerConfig {
2
+ /** CLI version for MCP server identification */
3
+ version: string;
4
+ /** Working directory for file operations */
5
+ workingDirectory: string;
6
+ }
7
+ /**
8
+ * ByteRover MCP Server.
9
+ *
10
+ * Exposes brv-query and brv-curate as MCP tools for coding agents.
11
+ * Connects to a running brv instance via Socket.IO transport.
12
+ *
13
+ * Architecture:
14
+ * - Coding agent spawns `brv mcp` process
15
+ * - MCP server connects to running brv instance via Socket.IO
16
+ * - MCP tools create tasks via transport
17
+ * - Tasks are executed by the existing agent process
18
+ */
19
+ export declare class ByteRoverMcpServer {
20
+ private client;
21
+ private readonly config;
22
+ private currentReconnectDelay;
23
+ private isReconnecting;
24
+ private reconnectTimer;
25
+ private readonly server;
26
+ private transport;
27
+ constructor(config: McpServerConfig);
28
+ /**
29
+ * Starts the MCP server.
30
+ *
31
+ * 1. Connects to running brv instance via Socket.IO
32
+ * 2. Starts MCP server with stdio transport
33
+ *
34
+ * @throws NoInstanceRunningError - No brv instance is running
35
+ * @throws ConnectionFailedError - Failed to connect to brv instance
36
+ */
37
+ start(): Promise<void>;
38
+ /**
39
+ * Stops the MCP server.
40
+ *
41
+ * Disconnects from the brv instance.
42
+ */
43
+ stop(): Promise<void>;
44
+ /**
45
+ * Attempts to reconnect to the brv instance.
46
+ * Uses exponential backoff for retry delays.
47
+ */
48
+ private attemptReconnect;
49
+ /**
50
+ * Log to stderr (stdout is reserved for MCP protocol).
51
+ */
52
+ private log;
53
+ /**
54
+ * Sets up the state change handler for a client.
55
+ * Handles disconnection by triggering auto-reconnect.
56
+ */
57
+ private setupStateChangeHandler;
58
+ }