byterover-cli 1.0.5 → 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 (204) hide show
  1. package/README.md +19 -13
  2. package/dist/commands/hook-prompt-submit.d.ts +27 -0
  3. package/dist/commands/hook-prompt-submit.js +39 -0
  4. package/dist/commands/mcp.d.ts +13 -0
  5. package/dist/commands/mcp.js +61 -0
  6. package/dist/commands/status.js +8 -3
  7. package/dist/constants.d.ts +1 -1
  8. package/dist/constants.js +1 -1
  9. package/dist/core/domain/cipher/agent-events/types.d.ts +44 -1
  10. package/dist/core/domain/cipher/tools/constants.d.ts +1 -0
  11. package/dist/core/domain/cipher/tools/constants.js +1 -0
  12. package/dist/core/domain/entities/agent.d.ts +16 -0
  13. package/dist/core/domain/entities/agent.js +78 -0
  14. package/dist/core/domain/entities/connector-type.d.ts +10 -0
  15. package/dist/core/domain/entities/connector-type.js +9 -0
  16. package/dist/core/domain/entities/event.d.ts +1 -1
  17. package/dist/core/domain/entities/event.js +2 -0
  18. package/dist/core/domain/errors/task-error.d.ts +4 -0
  19. package/dist/core/domain/errors/task-error.js +7 -0
  20. package/dist/core/domain/transport/schemas.d.ts +40 -0
  21. package/dist/core/domain/transport/schemas.js +28 -0
  22. package/dist/core/interfaces/connectors/connector-types.d.ts +70 -0
  23. package/dist/core/interfaces/connectors/i-connector-manager.d.ts +72 -0
  24. package/dist/core/interfaces/connectors/i-connector-manager.js +1 -0
  25. package/dist/core/interfaces/connectors/i-connector.d.ts +54 -0
  26. package/dist/core/interfaces/connectors/i-connector.js +1 -0
  27. package/dist/core/interfaces/i-file-service.d.ts +7 -0
  28. package/dist/core/interfaces/i-mcp-config-writer.d.ts +40 -0
  29. package/dist/core/interfaces/i-mcp-config-writer.js +1 -0
  30. package/dist/core/interfaces/i-rule-template-service.d.ts +4 -2
  31. package/dist/core/interfaces/transport/i-transport-client.d.ts +7 -0
  32. package/dist/core/interfaces/usecase/i-connectors-use-case.d.ts +3 -0
  33. package/dist/core/interfaces/usecase/i-connectors-use-case.js +1 -0
  34. package/dist/hooks/init/update-notifier.d.ts +1 -0
  35. package/dist/hooks/init/update-notifier.js +10 -1
  36. package/dist/infra/cipher/agent/cipher-agent.d.ts +8 -0
  37. package/dist/infra/cipher/agent/cipher-agent.js +16 -0
  38. package/dist/infra/cipher/file-system/binary-utils.d.ts +7 -12
  39. package/dist/infra/cipher/file-system/binary-utils.js +46 -31
  40. package/dist/infra/cipher/llm/context/context-manager.d.ts +10 -2
  41. package/dist/infra/cipher/llm/context/context-manager.js +39 -2
  42. package/dist/infra/cipher/llm/formatters/gemini-formatter.js +48 -9
  43. package/dist/infra/cipher/llm/internal-llm-service.d.ts +4 -0
  44. package/dist/infra/cipher/llm/internal-llm-service.js +40 -12
  45. package/dist/infra/cipher/session/chat-session.d.ts +3 -0
  46. package/dist/infra/cipher/session/chat-session.js +7 -1
  47. package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.d.ts +6 -7
  48. package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.js +57 -18
  49. package/dist/infra/cipher/tools/implementations/curate-tool.d.ts +1 -8
  50. package/dist/infra/cipher/tools/implementations/curate-tool.js +380 -24
  51. package/dist/infra/cipher/tools/implementations/read-file-tool.js +38 -17
  52. package/dist/infra/cipher/tools/implementations/search-knowledge-tool.d.ts +7 -0
  53. package/dist/infra/cipher/tools/implementations/search-knowledge-tool.js +303 -0
  54. package/dist/infra/cipher/tools/index.d.ts +1 -0
  55. package/dist/infra/cipher/tools/index.js +1 -0
  56. package/dist/infra/cipher/tools/tool-manager.js +1 -0
  57. package/dist/infra/cipher/tools/tool-registry.js +7 -0
  58. package/dist/infra/connectors/connector-manager.d.ts +32 -0
  59. package/dist/infra/connectors/connector-manager.js +158 -0
  60. package/dist/infra/connectors/hook/hook-connector-config.d.ts +52 -0
  61. package/dist/infra/connectors/hook/hook-connector-config.js +41 -0
  62. package/dist/infra/connectors/hook/hook-connector.d.ts +46 -0
  63. package/dist/infra/connectors/hook/hook-connector.js +231 -0
  64. package/dist/infra/connectors/mcp/index.d.ts +4 -0
  65. package/dist/infra/connectors/mcp/index.js +4 -0
  66. package/dist/infra/connectors/mcp/json-mcp-config-writer.d.ts +26 -0
  67. package/dist/infra/connectors/mcp/json-mcp-config-writer.js +71 -0
  68. package/dist/infra/connectors/mcp/mcp-connector-config.d.ts +229 -0
  69. package/dist/infra/connectors/mcp/mcp-connector-config.js +173 -0
  70. package/dist/infra/connectors/mcp/mcp-connector.d.ts +80 -0
  71. package/dist/infra/connectors/mcp/mcp-connector.js +324 -0
  72. package/dist/infra/connectors/mcp/toml-mcp-config-writer.d.ts +45 -0
  73. package/dist/infra/connectors/mcp/toml-mcp-config-writer.js +134 -0
  74. package/dist/infra/{rule → connectors/rules}/legacy-rule-detector.d.ts +2 -2
  75. package/dist/infra/{rule → connectors/rules}/legacy-rule-detector.js +1 -1
  76. package/dist/infra/connectors/rules/rules-connector-config.d.ts +95 -0
  77. package/dist/infra/{rule/agent-rule-config.js → connectors/rules/rules-connector-config.js} +10 -10
  78. package/dist/infra/connectors/rules/rules-connector.d.ts +34 -0
  79. package/dist/infra/connectors/rules/rules-connector.js +139 -0
  80. package/dist/infra/connectors/shared/rule-file-manager.d.ts +72 -0
  81. package/dist/infra/connectors/shared/rule-file-manager.js +119 -0
  82. package/dist/infra/connectors/shared/template-service.d.ts +27 -0
  83. package/dist/infra/connectors/shared/template-service.js +125 -0
  84. package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +5 -2
  85. package/dist/infra/context-tree/file-context-tree-writer-service.js +20 -5
  86. package/dist/infra/core/executors/curate-executor.d.ts +2 -2
  87. package/dist/infra/core/executors/curate-executor.js +7 -7
  88. package/dist/infra/core/executors/query-executor.d.ts +12 -0
  89. package/dist/infra/core/executors/query-executor.js +62 -1
  90. package/dist/infra/file/fs-file-service.d.ts +7 -0
  91. package/dist/infra/file/fs-file-service.js +15 -1
  92. package/dist/infra/mcp/index.d.ts +2 -0
  93. package/dist/infra/mcp/index.js +2 -0
  94. package/dist/infra/mcp/mcp-server.d.ts +58 -0
  95. package/dist/infra/mcp/mcp-server.js +178 -0
  96. package/dist/infra/mcp/tools/brv-curate-tool.d.ts +23 -0
  97. package/dist/infra/mcp/tools/brv-curate-tool.js +68 -0
  98. package/dist/infra/mcp/tools/brv-query-tool.d.ts +17 -0
  99. package/dist/infra/mcp/tools/brv-query-tool.js +68 -0
  100. package/dist/infra/mcp/tools/index.d.ts +3 -0
  101. package/dist/infra/mcp/tools/index.js +3 -0
  102. package/dist/infra/mcp/tools/task-result-waiter.d.ts +30 -0
  103. package/dist/infra/mcp/tools/task-result-waiter.js +56 -0
  104. package/dist/infra/process/agent-worker.d.ts +2 -2
  105. package/dist/infra/process/agent-worker.js +663 -142
  106. package/dist/infra/process/constants.d.ts +1 -1
  107. package/dist/infra/process/constants.js +1 -1
  108. package/dist/infra/process/ipc-types.d.ts +17 -4
  109. package/dist/infra/process/ipc-types.js +3 -3
  110. package/dist/infra/process/parent-heartbeat.d.ts +47 -0
  111. package/dist/infra/process/parent-heartbeat.js +118 -0
  112. package/dist/infra/process/process-manager.d.ts +79 -0
  113. package/dist/infra/process/process-manager.js +277 -3
  114. package/dist/infra/process/task-queue-manager.d.ts +13 -0
  115. package/dist/infra/process/task-queue-manager.js +19 -0
  116. package/dist/infra/process/transport-handlers.d.ts +3 -0
  117. package/dist/infra/process/transport-handlers.js +51 -5
  118. package/dist/infra/process/transport-worker.js +9 -69
  119. package/dist/infra/repl/commands/connectors-command.d.ts +8 -0
  120. package/dist/infra/repl/commands/{gen-rules-command.js → connectors-command.js} +21 -10
  121. package/dist/infra/repl/commands/curate-command.js +2 -2
  122. package/dist/infra/repl/commands/index.js +3 -2
  123. package/dist/infra/repl/commands/init-command.js +11 -7
  124. package/dist/infra/repl/commands/query-command.js +22 -2
  125. package/dist/infra/repl/commands/reset-command.js +1 -1
  126. package/dist/infra/transport/socket-io-transport-client.d.ts +75 -0
  127. package/dist/infra/transport/socket-io-transport-client.js +308 -7
  128. package/dist/infra/transport/socket-io-transport-server.js +4 -0
  129. package/dist/infra/usecase/connectors-use-case.d.ts +63 -0
  130. package/dist/infra/usecase/connectors-use-case.js +222 -0
  131. package/dist/infra/usecase/init-use-case.d.ts +8 -43
  132. package/dist/infra/usecase/init-use-case.js +27 -252
  133. package/dist/infra/usecase/logout-use-case.js +1 -1
  134. package/dist/infra/usecase/pull-use-case.js +5 -5
  135. package/dist/infra/usecase/push-use-case.js +4 -4
  136. package/dist/infra/usecase/reset-use-case.js +3 -4
  137. package/dist/infra/usecase/space-list-use-case.js +3 -3
  138. package/dist/infra/usecase/space-switch-use-case.js +3 -3
  139. package/dist/infra/usecase/status-use-case.d.ts +10 -0
  140. package/dist/infra/usecase/status-use-case.js +53 -0
  141. package/dist/resources/prompts/curate.yml +114 -4
  142. package/dist/resources/prompts/explore.yml +34 -0
  143. package/dist/resources/prompts/query-orchestrator.yml +112 -0
  144. package/dist/resources/prompts/system-prompt.yml +12 -2
  145. package/dist/resources/tools/search_knowledge.txt +32 -0
  146. package/dist/templates/mcp-base.md +1 -0
  147. package/dist/templates/sections/brv-instructions.md +98 -0
  148. package/dist/templates/sections/mcp-workflow.md +13 -0
  149. package/dist/tui/app.js +4 -1
  150. package/dist/tui/components/command-details.js +1 -1
  151. package/dist/tui/components/execution/execution-changes.d.ts +2 -0
  152. package/dist/tui/components/execution/execution-changes.js +5 -1
  153. package/dist/tui/components/execution/execution-content.d.ts +2 -0
  154. package/dist/tui/components/execution/execution-content.js +8 -18
  155. package/dist/tui/components/execution/execution-input.d.ts +2 -0
  156. package/dist/tui/components/execution/execution-input.js +6 -4
  157. package/dist/tui/components/execution/execution-progress.d.ts +2 -0
  158. package/dist/tui/components/execution/execution-progress.js +6 -2
  159. package/dist/tui/components/execution/expanded-log-view.d.ts +20 -0
  160. package/dist/tui/components/execution/expanded-log-view.js +75 -0
  161. package/dist/tui/components/execution/expanded-message-view.d.ts +24 -0
  162. package/dist/tui/components/execution/expanded-message-view.js +68 -0
  163. package/dist/tui/components/execution/index.d.ts +2 -0
  164. package/dist/tui/components/execution/index.js +2 -0
  165. package/dist/tui/components/execution/log-item.d.ts +4 -0
  166. package/dist/tui/components/execution/log-item.js +2 -2
  167. package/dist/tui/components/footer.js +1 -1
  168. package/dist/tui/components/index.d.ts +2 -1
  169. package/dist/tui/components/index.js +2 -1
  170. package/dist/tui/components/init.js +2 -9
  171. package/dist/tui/components/logo.js +4 -3
  172. package/dist/tui/components/markdown.d.ts +13 -0
  173. package/dist/tui/components/markdown.js +88 -0
  174. package/dist/tui/components/message-item.js +1 -1
  175. package/dist/tui/components/onboarding/onboarding-flow.js +14 -11
  176. package/dist/tui/components/onboarding/welcome-box.js +1 -1
  177. package/dist/tui/components/suggestions.js +3 -3
  178. package/dist/tui/contexts/mode-context.js +6 -2
  179. package/dist/tui/contexts/onboarding-context.d.ts +4 -0
  180. package/dist/tui/contexts/onboarding-context.js +14 -2
  181. package/dist/tui/hooks/index.d.ts +1 -0
  182. package/dist/tui/hooks/index.js +1 -0
  183. package/dist/tui/hooks/use-is-latest-version.d.ts +6 -0
  184. package/dist/tui/hooks/use-is-latest-version.js +22 -0
  185. package/dist/tui/views/command-view.d.ts +1 -1
  186. package/dist/tui/views/command-view.js +87 -98
  187. package/dist/tui/views/logs-view.d.ts +8 -0
  188. package/dist/tui/views/logs-view.js +55 -27
  189. package/dist/utils/file-validator.d.ts +1 -1
  190. package/dist/utils/file-validator.js +25 -28
  191. package/dist/utils/type-guards.d.ts +5 -0
  192. package/dist/utils/type-guards.js +7 -0
  193. package/oclif.manifest.json +55 -4
  194. package/package.json +12 -1
  195. package/dist/core/interfaces/usecase/i-generate-rules-use-case.d.ts +0 -3
  196. package/dist/infra/repl/commands/gen-rules-command.d.ts +0 -7
  197. package/dist/infra/rule/agent-rule-config.d.ts +0 -19
  198. package/dist/infra/rule/rule-template-service.d.ts +0 -18
  199. package/dist/infra/rule/rule-template-service.js +0 -88
  200. package/dist/infra/usecase/generate-rules-use-case.d.ts +0 -61
  201. package/dist/infra/usecase/generate-rules-use-case.js +0 -285
  202. /package/dist/core/interfaces/{usecase/i-generate-rules-use-case.js → connectors/connector-types.js} +0 -0
  203. /package/dist/infra/{rule → connectors/shared}/constants.d.ts +0 -0
  204. /package/dist/infra/{rule → connectors/shared}/constants.js +0 -0
@@ -5,34 +5,30 @@ import { ACE_DIR, BRV_CONFIG_VERSION, BRV_DIR, DEFAULT_BRANCH, PROJECT_CONFIG_FI
5
5
  import { AGENT_VALUES } from '../../core/domain/entities/agent.js';
6
6
  import { BrvConfig } from '../../core/domain/entities/brv-config.js';
7
7
  import { BrvConfigVersionError } from '../../core/domain/errors/brv-config-version-error.js';
8
- import { AGENT_RULE_CONFIGS } from '../rule/agent-rule-config.js';
9
- import { BRV_RULE_MARKERS, BRV_RULE_TAG } from '../rule/constants.js';
10
8
  import { WorkspaceDetectorService } from '../workspace/workspace-detector-service.js';
11
9
  export class InitUseCase {
12
10
  cogitPullService;
11
+ connectorManager;
13
12
  contextTreeService;
14
13
  contextTreeSnapshotService;
15
14
  contextTreeWriterService;
16
15
  fileService;
17
- legacyRuleDetector;
18
16
  projectConfigStore;
19
17
  spaceService;
20
18
  teamService;
21
- templateService;
22
19
  terminal;
23
20
  tokenStore;
24
21
  trackingService;
25
22
  constructor(options) {
26
23
  this.cogitPullService = options.cogitPullService;
24
+ this.connectorManager = options.connectorManager;
27
25
  this.contextTreeService = options.contextTreeService;
28
26
  this.contextTreeSnapshotService = options.contextTreeSnapshotService;
29
27
  this.contextTreeWriterService = options.contextTreeWriterService;
30
28
  this.fileService = options.fileService;
31
- this.legacyRuleDetector = options.legacyRuleDetector;
32
29
  this.projectConfigStore = options.projectConfigStore;
33
30
  this.spaceService = options.spaceService;
34
31
  this.teamService = options.teamService;
35
- this.templateService = options.templateService;
36
32
  this.terminal = options.terminal;
37
33
  this.tokenStore = options.tokenStore;
38
34
  this.trackingService = options.trackingService;
@@ -126,78 +122,6 @@ export class InitUseCase {
126
122
  this.terminal.log();
127
123
  return this.promptForTeamSelection(teams);
128
124
  }
129
- async generateRulesForAgent(selectedAgent) {
130
- this.terminal.log(`Generating rules for: ${selectedAgent}`);
131
- // try {
132
- // await ruleWriterService.writeRule(agent, false)
133
- // this.log(`✅ Successfully generated rule file for ${agent}`)
134
- // } catch (error) {
135
- // if (error instanceof RuleExistsError) {
136
- // const overwrite = await this.promptForOverwriteConfirmation(agent)
137
- // if (overwrite) {
138
- // await ruleWriterService.writeRule(agent, true)
139
- // this.log(`✅ Successfully generated rule file for ${agent}`)
140
- // } else {
141
- // this.log(`Skipping rule file generation for ${agent}`)
142
- // }
143
- // } else {
144
- // throw error
145
- // }
146
- // }
147
- const { filePath, writeMode } = AGENT_RULE_CONFIGS[selectedAgent];
148
- // STEP 1: Check if file exists
149
- const fileExists = await this.fileService.exists(filePath);
150
- if (!fileExists) {
151
- // Scenario A: File doesn't exist
152
- const shouldCreate = await this.promptForFileCreation(selectedAgent, filePath);
153
- if (!shouldCreate) {
154
- this.terminal.log(`Skipped rule file creation for ${selectedAgent}`);
155
- return;
156
- }
157
- await this.createNewRuleFile({
158
- agent: selectedAgent,
159
- filePath,
160
- });
161
- return;
162
- }
163
- // STEP 2: File exists - read content
164
- const content = await this.fileService.read(filePath);
165
- // STEP 3: Check for LEGACY rules (priority: clean these up first)
166
- const hasFooterTag = content.includes(`${BRV_RULE_TAG} ${selectedAgent}`);
167
- const hasBoundaryMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
168
- const hasLegacyRules = hasFooterTag && !hasBoundaryMarkers;
169
- if (hasLegacyRules) {
170
- // Scenario B: Legacy rules detected - handle cleanup
171
- await this.handleLegacyRulesCleanup({
172
- agent: selectedAgent,
173
- content,
174
- filePath,
175
- });
176
- return;
177
- }
178
- // STEP 4: Check for NEW rules (boundary markers)
179
- if (hasBoundaryMarkers) {
180
- // Scenario C: New rules exist - prompt for overwrite
181
- const shouldOverwrite = await this.promptForOverwriteConfirmation(selectedAgent);
182
- if (!shouldOverwrite) {
183
- this.terminal.log(`Skipped rule file update for ${selectedAgent}`);
184
- return;
185
- }
186
- await this.replaceExistingRules({
187
- agent: selectedAgent,
188
- content,
189
- filePath,
190
- writeMode,
191
- });
192
- return;
193
- }
194
- // STEP 5: No ByteRover content - append rules
195
- await this.appendRulesToFile({
196
- agent: selectedAgent,
197
- filePath,
198
- writeMode,
199
- });
200
- }
201
125
  async getExistingConfig() {
202
126
  const exists = await this.projectConfigStore.exists();
203
127
  if (!exists)
@@ -239,6 +163,30 @@ export class InitUseCase {
239
163
  this.terminal.warn(`${name} initialization skipped: ${error instanceof Error ? error.message : 'Unknown error'}`);
240
164
  }
241
165
  }
166
+ /**
167
+ * Installs the default connector for the selected agent.
168
+ * Uses ConnectorManager to handle the installation.
169
+ */
170
+ async installConnectorForAgent(selectedAgent) {
171
+ const defaultType = this.connectorManager.getDefaultConnectorType(selectedAgent);
172
+ const result = await this.connectorManager.installDefault(selectedAgent);
173
+ if (result.success) {
174
+ if (result.alreadyInstalled) {
175
+ this.terminal.log(`${selectedAgent} is already connected via ${defaultType}`);
176
+ }
177
+ else {
178
+ this.terminal.log(`${selectedAgent} connected via ${defaultType}`);
179
+ this.terminal.log(` Installed: ${result.configPath}`);
180
+ // Show restart message for hook connector
181
+ if (defaultType === 'hook' || defaultType === 'mcp') {
182
+ this.terminal.warn(`\n⚠️ Please restart ${selectedAgent} to apply the new ${defaultType}.`);
183
+ }
184
+ }
185
+ }
186
+ else {
187
+ this.terminal.error(`Failed to install connector for ${selectedAgent}: ${result.message}`);
188
+ }
189
+ }
242
190
  isLegacyProjectConfig(config) {
243
191
  return 'type' in config && config.type === 'legacy';
244
192
  }
@@ -282,51 +230,6 @@ export class InitUseCase {
282
230
  },
283
231
  });
284
232
  }
285
- /**
286
- * Prompts the user to choose cleanup strategy for legacy rules.
287
- * This method is protected to allow test overrides.
288
- * @returns The chosen cleanup strategy
289
- */
290
- async promptForCleanupStrategy() {
291
- return this.terminal.select({
292
- choices: [
293
- {
294
- description: 'New rules will be added with boundary markers. You manually remove old sections at your convenience.',
295
- name: 'Manual cleanup (recommended)',
296
- value: 'manual',
297
- },
298
- {
299
- description: '⚠️ We will remove all detected old sections. May cause content loss if detection is imperfect. A backup will be created.',
300
- name: 'Automatic cleanup',
301
- value: 'automatic',
302
- },
303
- ],
304
- message: 'How would you like to proceed?',
305
- });
306
- }
307
- /**
308
- * Prompts the user to create a new rule file.
309
- * This method is protected to allow test overrides.
310
- * @param agent The agent for which the rule file doesn't exist
311
- * @param filePath The path where the file would be created
312
- * @returns True if the user wants to create the file, false otherwise
313
- */
314
- async promptForFileCreation(agent, filePath) {
315
- return this.terminal.confirm({
316
- default: true,
317
- message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules`,
318
- });
319
- }
320
- /**
321
- * Prompts the user to confirm overwriting an existing rule file.
322
- * This method is protected to allow test overrides.
323
- */
324
- async promptForOverwriteConfirmation(agent) {
325
- return this.terminal.confirm({
326
- default: true,
327
- message: `Rule file already exists for ${agent}. Overwrite`,
328
- });
329
- }
330
233
  async promptForSpaceSelection(spaces) {
331
234
  const selectedSpaceId = await this.terminal.select({
332
235
  choices: spaces.map((space) => ({
@@ -403,7 +306,6 @@ export class InitUseCase {
403
306
  });
404
307
  this.terminal.log();
405
308
  const selectedAgent = await this.promptForAgentSelection();
406
- this.terminal.log('Detecting workspaces...');
407
309
  const { chatLogPath, cwd } = this.detectWorkspacesForAgent(selectedAgent);
408
310
  this.terminal.log(`✓ Detected workspace: ${cwd}`);
409
311
  const config = BrvConfig.fromSpace({
@@ -413,10 +315,8 @@ export class InitUseCase {
413
315
  space: selectedSpace,
414
316
  });
415
317
  await this.projectConfigStore.write(config);
416
- this.terminal.log(`\nGenerate rule instructions for coding agents to work with ByteRover correctly`);
417
318
  this.terminal.log();
418
- await this.generateRulesForAgent(selectedAgent);
419
- await this.trackingService.track('rule:generate');
319
+ await this.installConnectorForAgent(selectedAgent);
420
320
  await this.trackingService.track('space:init');
421
321
  this.logSuccess(selectedSpace);
422
322
  await this.trackingService.track('init', { status: 'finished' });
@@ -451,7 +351,6 @@ export class InitUseCase {
451
351
  this.terminal.log('✓ Context tree initialized');
452
352
  }
453
353
  else {
454
- // Remote has real data - sync it to local
455
354
  await this.contextTreeWriterService.sync({ files: [...coGitSnapshot.files] });
456
355
  await this.contextTreeSnapshotService.saveSnapshot();
457
356
  this.terminal.log(`✓ Synced ${coGitSnapshot.files.length} context files from remote`);
@@ -464,134 +363,10 @@ export class InitUseCase {
464
363
  }
465
364
  this.terminal.actionStop();
466
365
  }
467
- /**
468
- * Appends ByteRover rules to a file that has no ByteRover content.
469
- */
470
- async appendRulesToFile(params) {
471
- const { agent, filePath, writeMode } = params;
472
- const ruleContent = await this.templateService.generateRuleContent(agent);
473
- // For dedicated ByteRover files, overwrite; for shared instruction files, append
474
- const mode = writeMode === 'overwrite' ? 'overwrite' : 'append';
475
- await this.fileService.write(ruleContent, filePath, mode);
476
- this.terminal.log(`✅ Successfully added rule file for ${agent}`);
477
- }
478
- /**
479
- * Creates a new rule file with ByteRover rules.
480
- */
481
- async createNewRuleFile(params) {
482
- const { agent, filePath } = params;
483
- const ruleContent = await this.templateService.generateRuleContent(agent);
484
- await this.fileService.write(ruleContent, filePath, 'overwrite');
485
- this.terminal.log(`✅ Successfully created rule file for ${agent} at ${filePath}`);
486
- }
487
- async handleLegacyRulesCleanup(params) {
488
- const { agent, content, filePath } = params;
489
- const detectionResult = this.legacyRuleDetector.detectLegacyRules(content, agent);
490
- const { reliableMatches, uncertainMatches } = detectionResult;
491
- this.terminal.log(`\n⚠️ Detected ${reliableMatches.length + uncertainMatches.length} old ByteRover rule section(s) in ${filePath}:\n`);
492
- if (reliableMatches.length > 0) {
493
- this.terminal.log('Reliable matches:');
494
- for (const [index, match] of reliableMatches.entries()) {
495
- this.terminal.log(` Section ${index + 1}: lines ${match.startLine}-${match.endLine}`);
496
- }
497
- this.terminal.log();
498
- }
499
- if (uncertainMatches.length > 0) {
500
- this.terminal.log(' ⚠️ Uncertain matches (cannot determine start):');
501
- for (const match of uncertainMatches) {
502
- this.terminal.log(` Footer found at line ${match.footerLine}`);
503
- this.terminal.log(` Reason: ${match.reason}`);
504
- }
505
- this.terminal.log();
506
- this.terminal.log('⚠️ Due to uncertain matches, only manual cleanup is available.\n');
507
- await this.performManualCleanup({
508
- agent,
509
- filePath,
510
- reliableMatches,
511
- uncertainMatches,
512
- });
513
- return;
514
- }
515
- const selectedStrategy = await this.promptForCleanupStrategy();
516
- await (selectedStrategy === 'manual'
517
- ? this.performManualCleanup({
518
- agent,
519
- filePath,
520
- reliableMatches,
521
- uncertainMatches,
522
- })
523
- : this.performAutomaticCleanup({
524
- agent,
525
- filePath,
526
- reliableMatches,
527
- }));
528
- }
529
366
  logSuccess(space) {
530
367
  this.terminal.log(`\n✓ Project initialized successfully!`);
531
368
  this.terminal.log(`✓ Connected to space: ${space.getDisplayName()}`);
532
369
  this.terminal.log(`✓ Configuration saved to: ${BRV_DIR}/${PROJECT_CONFIG_FILE}`);
533
370
  this.terminal.log("NOTE: It's recommended to add .brv/ to your .gitignore file since ByteRover already takes care of memory/context versioning for you.");
534
371
  }
535
- async performAutomaticCleanup(params) {
536
- const { agent, filePath, reliableMatches } = params;
537
- const backupPath = await this.fileService.createBackup(filePath);
538
- this.terminal.log(`📦 Backup created: ${backupPath}`);
539
- let content = await this.fileService.read(filePath);
540
- // Remove all reliable matches (in reverse order to preserve line numbers)
541
- const sortedMatches = [...reliableMatches].sort((a, b) => b.startLine - a.startLine);
542
- for (const match of sortedMatches) {
543
- content = content.replace(match.content, '');
544
- }
545
- // Write cleaned content
546
- await this.fileService.write(content, filePath, 'overwrite');
547
- // Append new rules
548
- const ruleContent = await this.templateService.generateRuleContent(agent);
549
- await this.fileService.write(ruleContent, filePath, 'append');
550
- this.terminal.log(`✅ Removed ${reliableMatches.length} old ByteRover section(s)`);
551
- this.terminal.log(`✅ Added new rules with boundary markers`);
552
- this.terminal.log(`\nYou can safely delete the backup file once verified.`);
553
- }
554
- async performManualCleanup(params) {
555
- const { agent, filePath, reliableMatches, uncertainMatches } = params;
556
- const ruleContent = await this.templateService.generateRuleContent(agent);
557
- await this.fileService.write(ruleContent, filePath, 'append');
558
- this.terminal.log(`✅ New ByteRover rules added with boundary markers\n`);
559
- this.terminal.log('Please manually remove old sections:');
560
- for (const [index, match] of reliableMatches.entries()) {
561
- this.terminal.log(` - Section ${index + 1}: lines ${match.startLine}-${match.endLine} in ${filePath}`);
562
- }
563
- for (const match of uncertainMatches) {
564
- this.terminal.log(` - Section ending at line ${match.footerLine} in ${filePath}`);
565
- }
566
- this.terminal.log('\nKeep only the section between:');
567
- this.terminal.log(' <!-- BEGIN BYTEROVER RULES -->');
568
- this.terminal.log(' <!-- END BYTEROVER RULES -->');
569
- }
570
- /**
571
- * Replaces existing ByteRover rules (with boundary markers) with new rules.
572
- */
573
- async replaceExistingRules(params) {
574
- const { agent, content, filePath, writeMode } = params;
575
- const ruleContent = await this.templateService.generateRuleContent(agent);
576
- if (writeMode === 'overwrite') {
577
- // For dedicated ByteRover files, just overwrite the entire file
578
- await this.fileService.write(ruleContent, filePath, 'overwrite');
579
- }
580
- else {
581
- // For shared instruction files, replace the section between markers
582
- const startMarker = BRV_RULE_MARKERS.START;
583
- const endMarker = BRV_RULE_MARKERS.END;
584
- const startIndex = content.indexOf(startMarker);
585
- const endIndex = content.indexOf(endMarker, startIndex);
586
- if (startIndex === -1 || endIndex === -1) {
587
- this.terminal.log('Could not find boundary markers in the file');
588
- return;
589
- }
590
- const before = content.slice(0, startIndex);
591
- const after = content.slice(endIndex + endMarker.length);
592
- const newContent = before + ruleContent + after;
593
- await this.fileService.write(newContent, filePath, 'overwrite');
594
- }
595
- this.terminal.log(`✅ Successfully updated rule file for ${agent}`);
596
- }
597
372
  }
@@ -38,7 +38,7 @@ export class LogoutUseCase {
38
38
  await this.tokenStore.clear();
39
39
  await this.onboardingPreferenceStore.clear();
40
40
  this.terminal.log("Successfully logged out.");
41
- this.terminal.log("Run 'brv login' to authenticate again.");
41
+ this.terminal.log("Run '/login' to authenticate again.");
42
42
  }
43
43
  catch (error) {
44
44
  if (error instanceof Error && error.message.includes("keychain")) {
@@ -23,7 +23,7 @@ export class PullUseCase {
23
23
  async checkProjectInit() {
24
24
  const projectConfig = await this.projectConfigStore.read();
25
25
  if (projectConfig === undefined) {
26
- throw new WorkspaceNotInitializedError('Project not initialized. Please run "brv init" to select your team and workspace.', '.brv');
26
+ throw new WorkspaceNotInitializedError('Project not initialized. Please run "/init" to select your team and workspace.', '.brv');
27
27
  }
28
28
  return projectConfig;
29
29
  }
@@ -39,7 +39,7 @@ export class PullUseCase {
39
39
  const hasLocalChanges = await this.checkLocalChanges();
40
40
  this.terminal.actionStop();
41
41
  if (hasLocalChanges) {
42
- this.terminal.log('You have local changes that have not been pushed. Run "brv push" first.');
42
+ this.terminal.log('You have local changes that have not been pushed. Run "/push" first.');
43
43
  return;
44
44
  }
45
45
  // Pull from CoGit
@@ -67,7 +67,7 @@ export class PullUseCase {
67
67
  // Stop action if it's in progress
68
68
  this.terminal.actionStop();
69
69
  if (error instanceof WorkspaceNotInitializedError) {
70
- this.terminal.log('Project not initialized. Please run "brv init" to select your team and workspace.');
70
+ this.terminal.log('Project not initialized. Please run "/init" to select your team and workspace.');
71
71
  return;
72
72
  }
73
73
  const message = error instanceof Error ? error.message : 'Pull failed';
@@ -77,11 +77,11 @@ export class PullUseCase {
77
77
  async validateAuth() {
78
78
  const token = await this.tokenStore.load();
79
79
  if (token === undefined) {
80
- this.terminal.error('Not authenticated. Run "brv login" first.');
80
+ this.terminal.error('Not authenticated. Run "/login" first.');
81
81
  return undefined;
82
82
  }
83
83
  if (!token.isValid()) {
84
- this.terminal.error('Authentication token expired. Run "brv login" again.');
84
+ this.terminal.error('Authentication token expired. Run "/login" again.');
85
85
  return undefined;
86
86
  }
87
87
  return token;
@@ -82,7 +82,7 @@ export class PushUseCase {
82
82
  // Stop action if it's in progress
83
83
  this.terminal.actionStop();
84
84
  if (error instanceof WorkspaceNotInitializedError) {
85
- this.terminal.log('Project not initialized. Please run "brv init" to select your team and workspace.');
85
+ this.terminal.log('Project not initialized. Please run "/init" to select your team and workspace.');
86
86
  return;
87
87
  }
88
88
  // For other errors, to properly display error before exit
@@ -96,7 +96,7 @@ export class PushUseCase {
96
96
  async checkProjectInit() {
97
97
  const projectConfig = await this.projectConfigStore.read();
98
98
  if (projectConfig === undefined) {
99
- throw new WorkspaceNotInitializedError('Project not initialized. Please run "brv init" to select your team and workspace.', '.brv');
99
+ throw new WorkspaceNotInitializedError('Project not initialized. Please run "/init" to select your team and workspace.', '.brv');
100
100
  }
101
101
  return projectConfig;
102
102
  }
@@ -112,11 +112,11 @@ export class PushUseCase {
112
112
  async validateAuth() {
113
113
  const token = await this.tokenStore.load();
114
114
  if (token === undefined) {
115
- this.terminal.error('Not authenticated. Run "brv login" first.');
115
+ this.terminal.error('Not authenticated. Run "/login" first.');
116
116
  return undefined;
117
117
  }
118
118
  if (!token.isValid()) {
119
- this.terminal.error('Authentication token expired. Run "brv login" again.');
119
+ this.terminal.error('Authentication token expired. Run "/login" again.');
120
120
  return undefined;
121
121
  }
122
122
  return token;
@@ -14,7 +14,7 @@ export class ResetUseCase {
14
14
  async confirmReset() {
15
15
  return this.terminal.confirm({
16
16
  default: false,
17
- message: 'Are you sure you want to reset the context tree? This will remove all existing context and restore default domains',
17
+ message: 'Are you sure you want to reset the context tree? This will remove all existing context. Your context tree will be empty.',
18
18
  });
19
19
  }
20
20
  async run(options) {
@@ -37,12 +37,11 @@ export class ResetUseCase {
37
37
  const baseDir = options.directory ?? process.cwd();
38
38
  const contextTreeDir = join(baseDir, BRV_DIR, CONTEXT_TREE_DIR);
39
39
  await rm(contextTreeDir, { force: true, recursive: true });
40
- // Re-initialize context tree with default domains
40
+ // Re-initialize empty context tree
41
41
  await this.contextTreeService.initialize(options.directory);
42
42
  // Re-initialize empty snapshot
43
43
  await this.contextTreeSnapshotService.initEmptySnapshot(options.directory);
44
- this.terminal.log('✓ Context tree reset successfully.');
45
- this.terminal.log(' 6 default domains restored: code_style, design, structure, compliance, testing, bug_fixes');
44
+ this.terminal.log('✓ Context tree reset successfully. Your context tree is now empty.');
46
45
  }
47
46
  catch (error) {
48
47
  // Handle user cancelling the prompt (Ctrl+C or closing stdin)
@@ -15,16 +15,16 @@ export class SpaceListUseCase {
15
15
  // Check project initialization
16
16
  const projectConfig = await this.projectConfigStore.read();
17
17
  if (!projectConfig) {
18
- this.terminal.error('Project not initialized. Please run "brv init" first.');
18
+ this.terminal.error('Project not initialized. Please run "/init" first.');
19
19
  return;
20
20
  }
21
21
  const token = await this.tokenStore.load();
22
22
  if (!token) {
23
- this.terminal.error('Not authenticated. Please run "brv login" first.');
23
+ this.terminal.error('Not authenticated. Please run "/login" first.');
24
24
  return;
25
25
  }
26
26
  if (!token.isValid()) {
27
- this.terminal.error('Authentication token expired. Please run "brv login" again.');
27
+ this.terminal.error('Authentication token expired. Please run "/login" again.');
28
28
  return;
29
29
  }
30
30
  // Fetch spaces for the team from project config
@@ -74,7 +74,7 @@ export class SpaceSwitchUseCase {
74
74
  // Check project initialization (MUST exist for switch)
75
75
  const currentConfig = await this.projectConfigStore.read();
76
76
  if (!currentConfig) {
77
- this.terminal.log('Project not initialized. Please run "brv init" first.');
77
+ this.terminal.log('Project not initialized. Please run "/init" first.');
78
78
  return;
79
79
  }
80
80
  // Show current configuration
@@ -85,11 +85,11 @@ export class SpaceSwitchUseCase {
85
85
  // Validate authentication
86
86
  const token = await this.tokenStore.load();
87
87
  if (!token) {
88
- this.terminal.log('Not authenticated. Please run "brv login" first.');
88
+ this.terminal.log('Not authenticated. Please run "/login" first.');
89
89
  return;
90
90
  }
91
91
  if (!token.isValid()) {
92
- this.terminal.log('Authentication token expired. Please run "brv login" again.');
92
+ this.terminal.log('Authentication token expired. Please run "/login" again.');
93
93
  return;
94
94
  }
95
95
  // Fetch all teams
@@ -4,10 +4,12 @@ import type { IProjectConfigStore } from '../../core/interfaces/i-project-config
4
4
  import type { ITerminal } from '../../core/interfaces/i-terminal.js';
5
5
  import type { ITokenStore } from '../../core/interfaces/i-token-store.js';
6
6
  import type { ITrackingService } from '../../core/interfaces/i-tracking-service.js';
7
+ import type { IInstanceDiscovery } from '../../core/interfaces/instance/i-instance-discovery.js';
7
8
  import type { IStatusUseCase } from '../../core/interfaces/usecase/i-status-use-case.js';
8
9
  export interface StatusUseCaseOptions {
9
10
  contextTreeService: IContextTreeService;
10
11
  contextTreeSnapshotService: IContextTreeSnapshotService;
12
+ instanceDiscovery?: IInstanceDiscovery;
11
13
  projectConfigStore: IProjectConfigStore;
12
14
  terminal: ITerminal;
13
15
  tokenStore: ITokenStore;
@@ -16,6 +18,7 @@ export interface StatusUseCaseOptions {
16
18
  export declare class StatusUseCase implements IStatusUseCase {
17
19
  private readonly contextTreeService;
18
20
  private readonly contextTreeSnapshotService;
21
+ private readonly instanceDiscovery;
19
22
  private readonly projectConfigStore;
20
23
  private readonly terminal;
21
24
  private readonly tokenStore;
@@ -24,4 +27,11 @@ export declare class StatusUseCase implements IStatusUseCase {
24
27
  run(options: {
25
28
  cliVersion: string;
26
29
  }): Promise<void>;
30
+ /**
31
+ * Checks the MCP connection status by:
32
+ * 1. Discovering running brv instance
33
+ * 2. Connecting to it via Socket.IO
34
+ * 3. Verifying bidirectional communication with ping
35
+ */
36
+ private checkMcpStatus;
27
37
  }
@@ -2,9 +2,12 @@ import chalk from 'chalk';
2
2
  import { join } from 'node:path';
3
3
  import { BRV_DIR, CONTEXT_TREE_DIR } from '../../constants.js';
4
4
  import { getErrorMessage } from '../../utils/error-helpers.js';
5
+ import { FileInstanceDiscovery } from '../instance/file-instance-discovery.js';
6
+ import { SocketIOTransportClient } from '../transport/socket-io-transport-client.js';
5
7
  export class StatusUseCase {
6
8
  contextTreeService;
7
9
  contextTreeSnapshotService;
10
+ instanceDiscovery;
8
11
  projectConfigStore;
9
12
  terminal;
10
13
  tokenStore;
@@ -12,6 +15,7 @@ export class StatusUseCase {
12
15
  constructor(options) {
13
16
  this.contextTreeService = options.contextTreeService;
14
17
  this.contextTreeSnapshotService = options.contextTreeSnapshotService;
18
+ this.instanceDiscovery = options.instanceDiscovery ?? new FileInstanceDiscovery();
15
19
  this.projectConfigStore = options.projectConfigStore;
16
20
  this.terminal = options.terminal;
17
21
  this.tokenStore = options.tokenStore;
@@ -56,6 +60,8 @@ export class StatusUseCase {
56
60
  this.terminal.log('Project Status: Unable to read project configuration');
57
61
  this.terminal.warn(`Warning: ${getErrorMessage(error)}`);
58
62
  }
63
+ // MCP connection status
64
+ await this.checkMcpStatus();
59
65
  // Context tree status
60
66
  try {
61
67
  const contextTreeExists = await this.contextTreeService.exists();
@@ -94,4 +100,51 @@ export class StatusUseCase {
94
100
  this.terminal.warn(`Warning: ${error instanceof Error ? error.message : 'Context Tree unable to check status'}`);
95
101
  }
96
102
  }
103
+ /**
104
+ * Checks the MCP connection status by:
105
+ * 1. Discovering running brv instance
106
+ * 2. Connecting to it via Socket.IO
107
+ * 3. Verifying bidirectional communication with ping
108
+ */
109
+ async checkMcpStatus() {
110
+ try {
111
+ // Step 1: Discover running instance
112
+ const discoveryResult = await this.instanceDiscovery.discover(process.cwd());
113
+ if (!discoveryResult.found) {
114
+ if (discoveryResult.reason === 'instance_crashed') {
115
+ this.terminal.log(`MCP Status: ${chalk.red('Instance crashed')} (stale instance file found)`);
116
+ }
117
+ else {
118
+ this.terminal.log(`MCP Status: ${chalk.yellow('No instance running')}`);
119
+ }
120
+ return;
121
+ }
122
+ const { instance, projectRoot } = discoveryResult;
123
+ this.terminal.log(`MCP Status: Instance found (PID: ${instance.pid}, Port: ${instance.port})`);
124
+ // Step 2: Connect to instance
125
+ const client = new SocketIOTransportClient();
126
+ const url = instance.getTransportUrl();
127
+ try {
128
+ await client.connect(url);
129
+ }
130
+ catch (connectError) {
131
+ this.terminal.log(`MCP Status: ${chalk.red('Connection failed')} - ${getErrorMessage(connectError)}`);
132
+ return;
133
+ }
134
+ // Step 3: Verify bidirectional communication with ping
135
+ const isResponsive = await client.isConnected(2000);
136
+ if (isResponsive) {
137
+ this.terminal.log(`MCP Status: ${chalk.green('Connected and responsive')} (${projectRoot})`);
138
+ }
139
+ else {
140
+ this.terminal.log(`MCP Status: ${chalk.yellow('Connected but not responsive')} (ping timeout)`);
141
+ }
142
+ // Clean up
143
+ await client.disconnect();
144
+ }
145
+ catch (error) {
146
+ this.terminal.log(`MCP Status: ${chalk.red('Error checking status')}`);
147
+ this.terminal.warn(`Warning: ${getErrorMessage(error)}`);
148
+ }
149
+ }
97
150
  }