byterover-cli 0.3.5 → 0.4.1

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 (345) hide show
  1. package/README.md +119 -63
  2. package/bin/dev.js +8 -1
  3. package/bin/run.js +7 -0
  4. package/dist/commands/cipher-agent/run.d.ts +30 -0
  5. package/dist/commands/cipher-agent/run.js +123 -61
  6. package/dist/commands/cipher-agent/set-prompt.d.ts +2 -0
  7. package/dist/commands/cipher-agent/set-prompt.js +13 -8
  8. package/dist/commands/cipher-agent/show-prompt.d.ts +2 -0
  9. package/dist/commands/cipher-agent/show-prompt.js +17 -12
  10. package/dist/commands/curate.d.ts +3 -60
  11. package/dist/commands/curate.js +45 -341
  12. package/dist/commands/foo.d.ts +4 -2
  13. package/dist/commands/foo.js +21 -16
  14. package/dist/commands/main.d.ts +9 -0
  15. package/dist/commands/main.js +34 -0
  16. package/dist/commands/query.d.ts +2 -48
  17. package/dist/commands/query.js +19 -287
  18. package/dist/commands/status.d.ts +2 -13
  19. package/dist/commands/status.js +12 -91
  20. package/dist/commands/watch.d.ts +2 -0
  21. package/dist/commands/watch.js +23 -19
  22. package/dist/config/environment.d.ts +1 -1
  23. package/dist/config/environment.js +2 -2
  24. package/dist/constants.d.ts +4 -5
  25. package/dist/constants.js +5 -5
  26. package/dist/core/domain/cipher/errors/storage-error.d.ts +89 -0
  27. package/dist/core/domain/cipher/errors/storage-error.js +130 -0
  28. package/dist/core/domain/cipher/queue/types.d.ts +71 -0
  29. package/dist/core/domain/cipher/queue/types.js +9 -0
  30. package/dist/core/domain/cipher/storage/message-storage-types.d.ts +218 -0
  31. package/dist/core/domain/cipher/storage/message-storage-types.js +18 -0
  32. package/dist/core/domain/cipher/tools/constants.d.ts +1 -0
  33. package/dist/core/domain/cipher/tools/constants.js +1 -0
  34. package/dist/core/domain/entities/event.d.ts +1 -1
  35. package/dist/core/domain/entities/event.js +8 -1
  36. package/dist/core/domain/entities/global-config.d.ts +36 -0
  37. package/dist/core/domain/entities/global-config.js +66 -0
  38. package/dist/core/domain/knowledge/directory-manager.d.ts +10 -0
  39. package/dist/core/domain/knowledge/directory-manager.js +18 -0
  40. package/dist/core/domain/knowledge/markdown-writer.d.ts +9 -0
  41. package/dist/core/domain/knowledge/markdown-writer.js +51 -1
  42. package/dist/core/interfaces/cipher/i-agent-storage.d.ts +152 -0
  43. package/dist/core/interfaces/cipher/i-agent-storage.js +1 -0
  44. package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +2 -0
  45. package/dist/core/interfaces/cipher/i-key-storage.d.ts +91 -0
  46. package/dist/core/interfaces/cipher/i-key-storage.js +1 -0
  47. package/dist/core/interfaces/i-global-config-store.d.ts +34 -0
  48. package/dist/core/interfaces/i-global-config-store.js +1 -0
  49. package/dist/core/interfaces/i-onboarding-preference-store.d.ts +20 -0
  50. package/dist/core/interfaces/i-onboarding-preference-store.js +1 -0
  51. package/dist/core/interfaces/i-terminal.d.ts +146 -0
  52. package/dist/core/interfaces/i-terminal.js +1 -0
  53. package/dist/core/interfaces/i-workspace-detector-service.d.ts +8 -0
  54. package/dist/core/interfaces/i-workspace-detector-service.js +1 -0
  55. package/dist/core/interfaces/usecase/i-clear-use-case.d.ts +6 -0
  56. package/dist/core/interfaces/usecase/i-clear-use-case.js +1 -0
  57. package/dist/core/interfaces/usecase/i-curate-use-case.d.ts +10 -0
  58. package/dist/core/interfaces/usecase/i-curate-use-case.js +1 -0
  59. package/dist/core/interfaces/usecase/i-generate-rules-use-case.d.ts +3 -0
  60. package/dist/core/interfaces/usecase/i-generate-rules-use-case.js +1 -0
  61. package/dist/core/interfaces/usecase/i-init-use-case.d.ts +5 -0
  62. package/dist/core/interfaces/usecase/i-init-use-case.js +1 -0
  63. package/dist/core/interfaces/usecase/i-login-use-case.d.ts +3 -0
  64. package/dist/core/interfaces/usecase/i-login-use-case.js +1 -0
  65. package/dist/core/interfaces/usecase/i-logout-use-case.d.ts +5 -0
  66. package/dist/core/interfaces/usecase/i-logout-use-case.js +1 -0
  67. package/dist/core/interfaces/usecase/i-pull-use-case.d.ts +5 -0
  68. package/dist/core/interfaces/usecase/i-pull-use-case.js +1 -0
  69. package/dist/core/interfaces/usecase/i-push-use-case.d.ts +6 -0
  70. package/dist/core/interfaces/usecase/i-push-use-case.js +1 -0
  71. package/dist/core/interfaces/usecase/i-query-use-case.d.ts +9 -0
  72. package/dist/core/interfaces/usecase/i-query-use-case.js +1 -0
  73. package/dist/core/interfaces/usecase/i-space-list-use-case.d.ts +3 -0
  74. package/dist/core/interfaces/usecase/i-space-list-use-case.js +1 -0
  75. package/dist/core/interfaces/usecase/i-space-switch-use-case.d.ts +3 -0
  76. package/dist/core/interfaces/usecase/i-space-switch-use-case.js +1 -0
  77. package/dist/core/interfaces/usecase/i-status-use-case.d.ts +5 -0
  78. package/dist/core/interfaces/usecase/i-status-use-case.js +1 -0
  79. package/dist/hooks/init/welcome.js +10 -26
  80. package/dist/infra/cipher/agent-service-factory.d.ts +13 -6
  81. package/dist/infra/cipher/agent-service-factory.js +40 -16
  82. package/dist/infra/cipher/cipher-agent.js +4 -4
  83. package/dist/infra/cipher/consumer/consumer-lock.d.ts +20 -0
  84. package/dist/infra/cipher/consumer/consumer-lock.js +40 -0
  85. package/dist/infra/cipher/consumer/consumer-service.d.ts +99 -0
  86. package/dist/infra/cipher/consumer/consumer-service.js +165 -0
  87. package/dist/infra/cipher/consumer/execution-consumer.d.ts +121 -0
  88. package/dist/infra/cipher/consumer/execution-consumer.js +523 -0
  89. package/dist/infra/cipher/consumer/index.d.ts +33 -0
  90. package/dist/infra/cipher/consumer/index.js +33 -0
  91. package/dist/infra/cipher/consumer/queue-polling-service.d.ts +120 -0
  92. package/dist/infra/cipher/consumer/queue-polling-service.js +248 -0
  93. package/dist/infra/cipher/http/internal-llm-http-service.d.ts +94 -0
  94. package/dist/infra/cipher/http/internal-llm-http-service.js +118 -0
  95. package/dist/infra/cipher/llm/context/compaction/compaction-service.d.ts +106 -0
  96. package/dist/infra/cipher/llm/context/compaction/compaction-service.js +132 -0
  97. package/dist/infra/cipher/llm/context/compaction/index.d.ts +9 -0
  98. package/dist/infra/cipher/llm/context/compaction/index.js +9 -0
  99. package/dist/infra/cipher/llm/context/context-manager.d.ts +46 -2
  100. package/dist/infra/cipher/llm/context/context-manager.js +68 -4
  101. package/dist/infra/cipher/llm/context/rw-lock.d.ts +72 -0
  102. package/dist/infra/cipher/llm/context/rw-lock.js +145 -0
  103. package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +7 -7
  104. package/dist/infra/cipher/llm/generators/byterover-content-generator.js +8 -8
  105. package/dist/infra/cipher/llm/internal-llm-service.js +2 -0
  106. package/dist/infra/cipher/session/session-manager.d.ts +4 -4
  107. package/dist/infra/cipher/session/session-manager.js +5 -5
  108. package/dist/infra/cipher/storage/agent-storage.d.ts +246 -0
  109. package/dist/infra/cipher/storage/agent-storage.js +956 -0
  110. package/dist/infra/cipher/storage/dual-format-history-storage.d.ts +77 -0
  111. package/dist/infra/cipher/storage/dual-format-history-storage.js +149 -0
  112. package/dist/infra/cipher/storage/granular-history-storage.d.ts +65 -0
  113. package/dist/infra/cipher/storage/granular-history-storage.js +118 -0
  114. package/dist/infra/cipher/storage/message-storage-service.d.ts +108 -0
  115. package/dist/infra/cipher/storage/message-storage-service.js +529 -0
  116. package/dist/infra/cipher/storage/process-utils.d.ts +16 -0
  117. package/dist/infra/cipher/storage/process-utils.js +43 -0
  118. package/dist/infra/cipher/storage/sqlite-key-storage.d.ts +105 -0
  119. package/dist/infra/cipher/storage/sqlite-key-storage.js +404 -0
  120. package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +1 -0
  121. package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +7 -0
  122. package/dist/infra/cipher/tools/default-policy-rules.js +1 -1
  123. package/dist/infra/cipher/tools/implementations/curate-tool.d.ts +10 -0
  124. package/dist/infra/cipher/tools/implementations/curate-tool.js +371 -0
  125. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +11 -8
  126. package/dist/infra/cipher/tools/tool-manager.d.ts +8 -2
  127. package/dist/infra/cipher/tools/tool-manager.js +29 -2
  128. package/dist/infra/cipher/tools/tool-registry.js +7 -0
  129. package/dist/infra/http/authenticated-http-client.d.ts +21 -0
  130. package/dist/infra/http/authenticated-http-client.js +38 -0
  131. package/dist/infra/repl/commands/arg-parser.d.ts +97 -0
  132. package/dist/infra/repl/commands/arg-parser.js +129 -0
  133. package/dist/infra/repl/commands/clear-command.d.ts +5 -0
  134. package/dist/infra/repl/commands/clear-command.js +61 -0
  135. package/dist/infra/repl/commands/curate-command.d.ts +9 -0
  136. package/dist/infra/repl/commands/curate-command.js +88 -0
  137. package/dist/infra/repl/commands/gen-rules-command.d.ts +7 -0
  138. package/dist/infra/repl/commands/gen-rules-command.js +38 -0
  139. package/dist/infra/repl/commands/index.d.ts +8 -0
  140. package/dist/infra/repl/commands/index.js +36 -0
  141. package/dist/infra/repl/commands/init-command.d.ts +7 -0
  142. package/dist/infra/repl/commands/init-command.js +83 -0
  143. package/dist/infra/repl/commands/login-command.d.ts +7 -0
  144. package/dist/infra/repl/commands/login-command.js +50 -0
  145. package/dist/infra/repl/commands/logout-command.d.ts +5 -0
  146. package/dist/infra/repl/commands/logout-command.js +48 -0
  147. package/dist/infra/repl/commands/pull-command.d.ts +5 -0
  148. package/dist/infra/repl/commands/pull-command.js +61 -0
  149. package/dist/infra/repl/commands/push-command.d.ts +5 -0
  150. package/dist/infra/repl/commands/push-command.js +66 -0
  151. package/dist/infra/repl/commands/query-command.d.ts +5 -0
  152. package/dist/infra/repl/commands/query-command.js +66 -0
  153. package/dist/infra/repl/commands/space/index.d.ts +5 -0
  154. package/dist/infra/repl/commands/space/index.js +14 -0
  155. package/dist/infra/repl/commands/space/list-command.d.ts +5 -0
  156. package/dist/infra/repl/commands/space/list-command.js +70 -0
  157. package/dist/infra/repl/commands/space/switch-command.d.ts +5 -0
  158. package/dist/infra/repl/commands/space/switch-command.js +37 -0
  159. package/dist/infra/repl/commands/status-command.d.ts +5 -0
  160. package/dist/infra/repl/commands/status-command.js +39 -0
  161. package/dist/infra/repl/repl-startup.d.ts +18 -0
  162. package/dist/infra/repl/repl-startup.js +28 -0
  163. package/dist/infra/storage/file-global-config-store.d.ts +22 -0
  164. package/dist/infra/storage/file-global-config-store.js +65 -0
  165. package/dist/infra/storage/file-onboarding-preference-store.d.ts +10 -0
  166. package/dist/infra/storage/file-onboarding-preference-store.js +46 -0
  167. package/dist/infra/terminal/oclif-terminal.d.ts +19 -0
  168. package/dist/infra/terminal/oclif-terminal.js +60 -0
  169. package/dist/infra/terminal/repl-terminal.d.ts +31 -0
  170. package/dist/infra/terminal/repl-terminal.js +116 -0
  171. package/dist/infra/tracking/mixpanel-tracking-service.d.ts +11 -1
  172. package/dist/infra/tracking/mixpanel-tracking-service.js +18 -13
  173. package/dist/infra/usecase/clear-use-case.d.ts +20 -0
  174. package/dist/infra/usecase/clear-use-case.js +58 -0
  175. package/dist/infra/usecase/curate-use-case.d.ts +66 -0
  176. package/dist/infra/usecase/curate-use-case.js +288 -0
  177. package/dist/{commands/gen-rules.d.ts → infra/usecase/generate-rules-use-case.d.ts} +14 -20
  178. package/dist/{commands/gen-rules.js → infra/usecase/generate-rules-use-case.js} +59 -78
  179. package/dist/infra/usecase/init-use-case.d.ts +139 -0
  180. package/dist/{commands/init.js → infra/usecase/init-use-case.js} +197 -233
  181. package/dist/infra/usecase/login-use-case.d.ts +28 -0
  182. package/dist/infra/usecase/login-use-case.js +94 -0
  183. package/dist/infra/usecase/logout-use-case.d.ts +22 -0
  184. package/dist/infra/usecase/logout-use-case.js +51 -0
  185. package/dist/infra/usecase/pull-use-case.d.ts +35 -0
  186. package/dist/infra/usecase/pull-use-case.js +89 -0
  187. package/dist/infra/usecase/push-use-case.d.ts +37 -0
  188. package/dist/infra/usecase/push-use-case.js +124 -0
  189. package/dist/infra/usecase/query-use-case.d.ts +78 -0
  190. package/dist/infra/usecase/query-use-case.js +402 -0
  191. package/dist/infra/usecase/space-list-use-case.d.ts +27 -0
  192. package/dist/infra/usecase/space-list-use-case.js +64 -0
  193. package/dist/infra/usecase/space-switch-use-case.d.ts +36 -0
  194. package/dist/infra/usecase/space-switch-use-case.js +140 -0
  195. package/dist/infra/usecase/status-use-case.d.ts +27 -0
  196. package/dist/infra/usecase/status-use-case.js +97 -0
  197. package/dist/infra/workspace/workspace-detector-service.d.ts +3 -6
  198. package/dist/resources/prompts/curate-context-tree-curation.yml +23 -11
  199. package/dist/resources/prompts/query-context-tree-retrieval.yml +3 -4
  200. package/dist/resources/prompts/system-prompt.yml +1 -1
  201. package/dist/resources/prompts/tool-outputs.yml +4 -3
  202. package/dist/templates/sections/command-reference.md +12 -0
  203. package/dist/templates/sections/workflow.md +10 -1
  204. package/dist/tui/app.d.ts +9 -0
  205. package/dist/tui/app.js +26 -0
  206. package/dist/tui/components/enter-prompt.d.ts +13 -0
  207. package/dist/tui/components/enter-prompt.js +15 -0
  208. package/dist/tui/components/execution/execution-changes.d.ts +14 -0
  209. package/dist/tui/components/execution/execution-changes.js +15 -0
  210. package/dist/tui/components/execution/execution-content.d.ts +25 -0
  211. package/dist/tui/components/execution/execution-content.js +67 -0
  212. package/dist/tui/components/execution/execution-input.d.ts +12 -0
  213. package/dist/tui/components/execution/execution-input.js +16 -0
  214. package/dist/tui/components/execution/execution-progress.d.ts +21 -0
  215. package/dist/tui/components/execution/execution-progress.js +21 -0
  216. package/dist/tui/components/execution/execution-status.d.ts +13 -0
  217. package/dist/tui/components/execution/execution-status.js +19 -0
  218. package/dist/tui/components/execution/index.d.ts +11 -0
  219. package/dist/tui/components/execution/index.js +11 -0
  220. package/dist/tui/components/execution/log-item.d.ts +17 -0
  221. package/dist/tui/components/execution/log-item.js +25 -0
  222. package/dist/tui/components/footer.d.ts +5 -0
  223. package/dist/tui/components/footer.js +12 -0
  224. package/dist/tui/components/header.d.ts +18 -0
  225. package/dist/tui/components/header.js +18 -0
  226. package/dist/tui/components/index.d.ts +17 -0
  227. package/dist/tui/components/index.js +14 -0
  228. package/dist/tui/components/inline-prompts/index.d.ts +15 -0
  229. package/dist/tui/components/inline-prompts/index.js +10 -0
  230. package/dist/tui/components/inline-prompts/inline-confirm.d.ts +17 -0
  231. package/dist/tui/components/inline-prompts/inline-confirm.js +32 -0
  232. package/dist/tui/components/inline-prompts/inline-file-selector.d.ts +43 -0
  233. package/dist/tui/components/inline-prompts/inline-file-selector.js +185 -0
  234. package/dist/tui/components/inline-prompts/inline-input.d.ts +19 -0
  235. package/dist/tui/components/inline-prompts/inline-input.js +32 -0
  236. package/dist/tui/components/inline-prompts/inline-search.d.ts +20 -0
  237. package/dist/tui/components/inline-prompts/inline-search.js +50 -0
  238. package/dist/tui/components/inline-prompts/inline-select.d.ts +20 -0
  239. package/dist/tui/components/inline-prompts/inline-select.js +34 -0
  240. package/dist/tui/components/logo.d.ts +43 -0
  241. package/dist/tui/components/logo.js +103 -0
  242. package/dist/tui/components/message-item.d.ts +12 -0
  243. package/dist/tui/components/message-item.js +12 -0
  244. package/dist/tui/components/onboarding/copyable-prompt.d.ts +15 -0
  245. package/dist/tui/components/onboarding/copyable-prompt.js +65 -0
  246. package/dist/tui/components/onboarding/index.d.ts +7 -0
  247. package/dist/tui/components/onboarding/index.js +6 -0
  248. package/dist/tui/components/onboarding/onboarding-flow.d.ts +13 -0
  249. package/dist/tui/components/onboarding/onboarding-flow.js +304 -0
  250. package/dist/tui/components/onboarding/onboarding-step.d.ts +23 -0
  251. package/dist/tui/components/onboarding/onboarding-step.js +12 -0
  252. package/dist/tui/components/output-log.d.ts +14 -0
  253. package/dist/tui/components/output-log.js +13 -0
  254. package/dist/tui/components/scrollable-list.d.ts +30 -0
  255. package/dist/tui/components/scrollable-list.js +121 -0
  256. package/dist/tui/components/suggestions.d.ts +16 -0
  257. package/dist/tui/components/suggestions.js +162 -0
  258. package/dist/tui/components/tab-bar.d.ts +10 -0
  259. package/dist/tui/components/tab-bar.js +12 -0
  260. package/dist/tui/constants.d.ts +11 -0
  261. package/dist/tui/constants.js +13 -0
  262. package/dist/tui/contexts/auth-context.d.ts +30 -0
  263. package/dist/tui/contexts/auth-context.js +153 -0
  264. package/dist/tui/contexts/consumer.d.ts +31 -0
  265. package/dist/tui/contexts/consumer.js +56 -0
  266. package/dist/tui/contexts/index.d.ts +6 -0
  267. package/dist/tui/contexts/index.js +6 -0
  268. package/dist/tui/contexts/onboarding-context.d.ts +43 -0
  269. package/dist/tui/contexts/onboarding-context.js +181 -0
  270. package/dist/tui/contexts/services-context.d.ts +29 -0
  271. package/dist/tui/contexts/services-context.js +20 -0
  272. package/dist/tui/contexts/use-commands.d.ts +29 -0
  273. package/dist/tui/contexts/use-commands.js +54 -0
  274. package/dist/tui/contexts/use-mode.d.ts +43 -0
  275. package/dist/tui/contexts/use-mode.js +76 -0
  276. package/dist/tui/contexts/use-theme.d.ts +53 -0
  277. package/dist/tui/contexts/use-theme.js +60 -0
  278. package/dist/tui/hooks/index.d.ts +17 -0
  279. package/dist/tui/hooks/index.js +14 -0
  280. package/dist/tui/hooks/use-activity-logs.d.ts +26 -0
  281. package/dist/tui/hooks/use-activity-logs.js +90 -0
  282. package/dist/tui/hooks/use-consumer.d.ts +12 -0
  283. package/dist/tui/hooks/use-consumer.js +50 -0
  284. package/dist/tui/hooks/use-onboarding.d.ts +7 -0
  285. package/dist/tui/hooks/use-onboarding.js +6 -0
  286. package/dist/tui/hooks/use-queue-polling.d.ts +31 -0
  287. package/dist/tui/hooks/use-queue-polling.js +90 -0
  288. package/dist/tui/hooks/use-slash-command-processor.d.ts +16 -0
  289. package/dist/tui/hooks/use-slash-command-processor.js +132 -0
  290. package/dist/tui/hooks/use-slash-completion.d.ts +30 -0
  291. package/dist/tui/hooks/use-slash-completion.js +230 -0
  292. package/dist/tui/hooks/use-tab-navigation.d.ts +10 -0
  293. package/dist/tui/hooks/use-tab-navigation.js +35 -0
  294. package/dist/tui/hooks/use-visible-window.d.ts +22 -0
  295. package/dist/tui/hooks/use-visible-window.js +37 -0
  296. package/dist/tui/index.d.ts +1 -0
  297. package/dist/tui/index.js +1 -0
  298. package/dist/tui/providers/app-providers.d.ts +25 -0
  299. package/dist/tui/providers/app-providers.js +9 -0
  300. package/dist/tui/types/commands.d.ts +252 -0
  301. package/dist/tui/types/commands.js +16 -0
  302. package/dist/tui/types/dialogs.d.ts +37 -0
  303. package/dist/tui/types/dialogs.js +4 -0
  304. package/dist/tui/types/index.d.ts +11 -0
  305. package/dist/tui/types/index.js +7 -0
  306. package/dist/tui/types/messages.d.ts +55 -0
  307. package/dist/tui/types/messages.js +4 -0
  308. package/dist/tui/types/prompts.d.ts +100 -0
  309. package/dist/tui/types/prompts.js +4 -0
  310. package/dist/tui/types/ui.d.ts +14 -0
  311. package/dist/tui/types/ui.js +4 -0
  312. package/dist/tui/types.d.ts +1 -0
  313. package/dist/tui/types.js +1 -0
  314. package/dist/tui/views/command-view.d.ts +12 -0
  315. package/dist/tui/views/command-view.js +451 -0
  316. package/dist/tui/views/index.d.ts +6 -0
  317. package/dist/tui/views/index.js +6 -0
  318. package/dist/tui/views/login-view.d.ts +10 -0
  319. package/dist/tui/views/login-view.js +30 -0
  320. package/dist/tui/views/logs-view.d.ts +11 -0
  321. package/dist/tui/views/logs-view.js +73 -0
  322. package/dist/utils/file-validator.d.ts +16 -0
  323. package/dist/utils/file-validator.js +81 -0
  324. package/dist/utils/global-config-path.d.ts +15 -0
  325. package/dist/utils/global-config-path.js +38 -0
  326. package/oclif.manifest.json +29 -315
  327. package/package.json +11 -4
  328. package/dist/commands/clear.d.ts +0 -19
  329. package/dist/commands/clear.js +0 -78
  330. package/dist/commands/init.d.ts +0 -130
  331. package/dist/commands/login.d.ts +0 -22
  332. package/dist/commands/login.js +0 -108
  333. package/dist/commands/logout.d.ts +0 -16
  334. package/dist/commands/logout.js +0 -61
  335. package/dist/commands/pull.d.ts +0 -33
  336. package/dist/commands/pull.js +0 -115
  337. package/dist/commands/push.d.ts +0 -35
  338. package/dist/commands/push.js +0 -160
  339. package/dist/commands/space/list.d.ts +0 -25
  340. package/dist/commands/space/list.js +0 -114
  341. package/dist/commands/space/switch.d.ts +0 -36
  342. package/dist/commands/space/switch.js +0 -160
  343. package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +0 -149
  344. package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +0 -364
  345. package/dist/infra/cipher/grpc/internal-llm-grpc.proto +0 -94
@@ -0,0 +1,288 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import open from 'open';
5
+ import { CONTEXT_TREE_DOMAINS } from '../../config/context-tree-domains.js';
6
+ import { BRV_DIR, CONTEXT_FILE, CONTEXT_TREE_DIR } from '../../constants.js';
7
+ import { validateFileForCurate } from '../../utils/file-validator.js';
8
+ import { getAgentStorage } from '../cipher/storage/agent-storage.js';
9
+ import { WorkspaceNotInitializedError } from '../cipher/validation/workspace-validator.js';
10
+ // Full path to context tree
11
+ const CONTEXT_TREE_PATH = path.join(BRV_DIR, CONTEXT_TREE_DIR);
12
+ export class CurateUseCase {
13
+ projectConfigStore;
14
+ terminal;
15
+ tokenStore;
16
+ trackingService;
17
+ constructor(options) {
18
+ this.projectConfigStore = options.projectConfigStore;
19
+ this.terminal = options.terminal;
20
+ this.tokenStore = options.tokenStore;
21
+ this.trackingService = options.trackingService;
22
+ }
23
+ /**
24
+ * Create topic folder with context.md file
25
+ * @param targetPath - The parent path where the topic folder will be created
26
+ * @param topicName - The name of the topic folder to create
27
+ * @returns The path to the created context.md file
28
+ */
29
+ createTopicWithContextFile(targetPath, topicName) {
30
+ const topicPath = path.join(targetPath, topicName);
31
+ const contextFilePath = path.join(topicPath, CONTEXT_FILE);
32
+ // Create the topic directory
33
+ fs.mkdirSync(topicPath, { recursive: true });
34
+ // Create the context.md file with initial content
35
+ const initialContent = `# ${topicName}\n\n<!-- Add your context here -->\n`;
36
+ fs.writeFileSync(contextFilePath, initialContent, 'utf8');
37
+ return contextFilePath;
38
+ }
39
+ /**
40
+ * Generate a unique session ID for the autonomous agent.
41
+ * Uses crypto.randomUUID() for guaranteed uniqueness (122 bits of entropy).
42
+ */
43
+ generateSessionId() {
44
+ return randomUUID();
45
+ }
46
+ /**
47
+ * Navigate through the context tree using file selector
48
+ * Returns the selected path relative to context-tree root
49
+ */
50
+ async navigateContextTree() {
51
+ const contextTreePath = path.resolve(process.cwd(), CONTEXT_TREE_PATH);
52
+ // Ensure context tree directory exists
53
+ if (!fs.existsSync(contextTreePath)) {
54
+ fs.mkdirSync(contextTreePath, { recursive: true });
55
+ }
56
+ // Ensure predefined domains exist as directories
57
+ for (const domain of CONTEXT_TREE_DOMAINS) {
58
+ const domainPath = path.join(contextTreePath, domain.name);
59
+ if (!fs.existsSync(domainPath)) {
60
+ fs.mkdirSync(domainPath, { recursive: true });
61
+ }
62
+ }
63
+ while (true) {
64
+ try {
65
+ // eslint-disable-next-line no-await-in-loop
66
+ const selectedItem = await this.terminal.fileSelector({
67
+ allowCancel: true,
68
+ basePath: contextTreePath,
69
+ filter: (item) => item.isDirectory,
70
+ message: 'Target context location:',
71
+ pageSize: 15,
72
+ theme: {
73
+ labels: {
74
+ messages: {
75
+ cancel: 'Selection cancelled.',
76
+ empty: 'No sub-folders. Press Enter to add content here.',
77
+ },
78
+ },
79
+ },
80
+ type: 'directory',
81
+ });
82
+ // User cancelled
83
+ if (!selectedItem) {
84
+ return null;
85
+ }
86
+ // Restrict navigation to stay within the context tree
87
+ const normalizedItemPath = path.resolve(selectedItem.path);
88
+ const isValid = normalizedItemPath.startsWith(contextTreePath);
89
+ if (isValid) {
90
+ // Valid selection - proceed
91
+ return selectedItem.path;
92
+ }
93
+ // Invalid selection - retry
94
+ this.terminal.log('Invalid selection. Please choose a valid location within the context tree.');
95
+ }
96
+ catch {
97
+ // Error occurred
98
+ return null;
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Open a file in the default editor
104
+ * @param filePath - The path to the file to open
105
+ */
106
+ async openFile(filePath) {
107
+ await open(filePath);
108
+ }
109
+ /**
110
+ * Prompt user to enter topic name with validation
111
+ * @param targetPath - The path where the topic folder will be created
112
+ * @returns The topic name or null if cancelled
113
+ */
114
+ async promptForTopicName(targetPath) {
115
+ try {
116
+ const topicName = await this.terminal.input({
117
+ message: 'New topic name:',
118
+ validate: (value) => this.validateTopicName(value, targetPath),
119
+ });
120
+ return topicName.trim();
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ }
126
+ async run(options) {
127
+ await this.trackingService.track('mem:curate', { status: 'started' });
128
+ // Determine mode: autonomous if context is provided
129
+ return options.context ? this.runAutonomous(options.context, options) : this.runInteractive();
130
+ }
131
+ /**
132
+ * Handle workspace not initialized error
133
+ */
134
+ handleWorkspaceError(_error) {
135
+ const message = 'Project not initialized. Please run "/init" to select your team and workspace.';
136
+ this.terminal.log(message);
137
+ }
138
+ /**
139
+ * Process file paths from --files flag
140
+ * @param filePaths - Array of file paths (relative or absolute)
141
+ * @returns Formatted instructions for the agent to read the specified files, or undefined if validation fails
142
+ */
143
+ processFileReferences(filePaths) {
144
+ const MAX_FILES = 5;
145
+ if (!filePaths || filePaths.length === 0) {
146
+ return '';
147
+ }
148
+ // Validate max files and truncate if needed
149
+ if (filePaths.length > MAX_FILES) {
150
+ const ignored = filePaths.slice(MAX_FILES);
151
+ this.terminal.log(`\n⚠️ Only the first ${MAX_FILES} files will be processed. Ignoring: ${ignored.join(', ')}\n`);
152
+ filePaths = filePaths.slice(0, MAX_FILES);
153
+ }
154
+ // Get project root (current directory with .brv)
155
+ const projectRoot = process.cwd();
156
+ // Validate each file and collect errors
157
+ const validPaths = [];
158
+ const errors = [];
159
+ for (const filePath of filePaths) {
160
+ const result = validateFileForCurate(filePath, projectRoot);
161
+ if (result.valid && result.normalizedPath) {
162
+ validPaths.push(result.normalizedPath);
163
+ }
164
+ else {
165
+ errors.push(` ✗ ${result.error}`);
166
+ }
167
+ }
168
+ // If there are any validation errors, show them and return undefined
169
+ if (errors.length > 0) {
170
+ this.terminal.log('\n❌ File validation failed:\n');
171
+ this.terminal.log(errors.join('\n'));
172
+ this.terminal.log('');
173
+ this.terminal.log('Invalid files provided. Please fix the errors above and try again.');
174
+ return undefined;
175
+ }
176
+ // Format instructions for the agent
177
+ const instructions = [
178
+ '\n## IMPORTANT: Critical Files to Read (--files flag)',
179
+ '',
180
+ 'The user has explicitly specified these files as critical context that MUST be read before creating knowledge topics:',
181
+ '',
182
+ ...validPaths.map((p) => `- ${p}`),
183
+ '',
184
+ '**MANDATORY INSTRUCTIONS:**',
185
+ '- You MUST use the `read_file` tool to read ALL of these files IN PARALLEL (in a single iteration) before proceeding to create knowledge topics',
186
+ '- These files contain essential context that will help you create comprehensive and accurate knowledge topics',
187
+ '- Read them in parallel to maximize efficiency - they do not depend on each other',
188
+ '- After reading all files, proceed with the normal workflow: detect domains, find existing knowledge, and create/update topics',
189
+ '',
190
+ ];
191
+ return instructions.join('\n');
192
+ }
193
+ /**
194
+ * Run in autonomous mode - push to queue for background processing
195
+ */
196
+ async runAutonomous(content, options) {
197
+ try {
198
+ // Get authentication token
199
+ const token = await this.tokenStore.load();
200
+ if (!token) {
201
+ this.terminal.log('Authentication required. Please run "/login" first.');
202
+ return;
203
+ }
204
+ // Load project config
205
+ const brvConfig = await this.projectConfigStore.read();
206
+ // Validate workspace is initialized
207
+ if (!brvConfig) {
208
+ throw new WorkspaceNotInitializedError('Project not initialized. Please run "/init" to select your team and workspace.', '.brv');
209
+ }
210
+ // Process file references if provided (validates and creates instructions)
211
+ const fileReferenceInstructions = this.processFileReferences(options.files ?? []);
212
+ if (fileReferenceInstructions === undefined) {
213
+ // Validation failed, error already displayed
214
+ return;
215
+ }
216
+ // Initialize storage and create execution (auto-detects .brv/blobs)
217
+ const storage = await getAgentStorage();
218
+ // Create execution with status='queued'
219
+ storage.createExecution('curate', JSON.stringify({
220
+ content,
221
+ fileReferenceInstructions,
222
+ flags: { apiKey: options.apiKey, model: options.model, verbose: options.verbose },
223
+ }));
224
+ // Simple output for agents - just confirm saved
225
+ this.terminal.log('✓ Context queued for processing.');
226
+ // Track the event
227
+ await this.trackingService.track('mem:curate', { status: 'finished' });
228
+ }
229
+ catch (error) {
230
+ if (error instanceof WorkspaceNotInitializedError) {
231
+ this.handleWorkspaceError(error);
232
+ return;
233
+ }
234
+ // Display error
235
+ const errMsg = error instanceof Error ? error.message : 'Runtime error occurred';
236
+ await this.trackingService.track('mem:curate', { message: errMsg, status: 'error' });
237
+ this.terminal.error(errMsg);
238
+ }
239
+ }
240
+ /**
241
+ * Run in interactive mode with manual prompts
242
+ */
243
+ async runInteractive() {
244
+ try {
245
+ // Navigate to target location in context tree
246
+ const targetPath = await this.navigateContextTree();
247
+ if (!targetPath) {
248
+ this.terminal.log('\nOperation cancelled.');
249
+ return;
250
+ }
251
+ // Prompt for topic name with validation
252
+ const topicName = await this.promptForTopicName(targetPath);
253
+ if (!topicName) {
254
+ this.terminal.log('\nOperation cancelled.');
255
+ return;
256
+ }
257
+ // Create the topic folder with context.md
258
+ const contextFilePath = this.createTopicWithContextFile(targetPath, topicName);
259
+ this.terminal.log(`\nCreated: ${path.relative(process.cwd(), contextFilePath)}`);
260
+ // Track the event
261
+ this.trackingService.track('mem:curate');
262
+ // Auto-open context.md in default editor
263
+ this.terminal.log('Opening context.md for editing...');
264
+ await this.openFile(contextFilePath);
265
+ }
266
+ catch (error) {
267
+ const errMsg = error instanceof Error ? error.message : 'Unexpected error occurred';
268
+ await this.trackingService.track('mem:curate', { message: errMsg, status: 'error' });
269
+ this.terminal.error(errMsg);
270
+ }
271
+ }
272
+ validateTopicName(value, targetPath) {
273
+ const trimmed = value.trim();
274
+ if (!trimmed) {
275
+ return 'Topic name cannot be empty';
276
+ }
277
+ // Only allow letters, numbers, and hyphens
278
+ if (!/^[a-zA-Z0-9-]+$/.test(trimmed)) {
279
+ return 'Topic name can only contain letters (a-z, A-Z), numbers (0-9), and hyphens (-)';
280
+ }
281
+ // Check if folder already exists
282
+ const topicPath = path.join(targetPath, trimmed);
283
+ if (fs.existsSync(topicPath)) {
284
+ return `Topic "${trimmed}" already exists at this location`;
285
+ }
286
+ return true;
287
+ }
288
+ }
@@ -1,31 +1,25 @@
1
- import { Command } from '@oclif/core';
2
- import type { Agent } from '../core/domain/entities/agent.js';
3
- import type { IFileService } from '../core/interfaces/i-file-service.js';
4
- import type { IRuleTemplateService } from '../core/interfaces/i-rule-template-service.js';
5
- import type { ITrackingService } from '../core/interfaces/i-tracking-service.js';
6
- import { LegacyRuleDetector } from '../infra/rule/legacy-rule-detector.js';
1
+ import type { Agent } from '../../core/domain/entities/agent.js';
2
+ import type { IFileService } from '../../core/interfaces/i-file-service.js';
3
+ import type { IRuleTemplateService } from '../../core/interfaces/i-rule-template-service.js';
4
+ import type { ITerminal } from '../../core/interfaces/i-terminal.js';
5
+ import type { ITrackingService } from '../../core/interfaces/i-tracking-service.js';
6
+ import type { IGenerateRulesUseCase } from '../../core/interfaces/usecase/i-generate-rules-use-case.js';
7
+ import { LegacyRuleDetector } from '../rule/legacy-rule-detector.js';
7
8
  type CleanupStrategy = 'automatic' | 'manual';
8
- export default class GenRules extends Command {
9
- static description: string;
10
- static examples: string[];
11
- static flags: {
12
- agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
- };
14
- protected createServices(): {
15
- fileService: IFileService;
16
- legacyRuleDetector: LegacyRuleDetector;
17
- templateService: IRuleTemplateService;
18
- trackingService: ITrackingService;
19
- };
9
+ export declare class GenerateRulesUseCase implements IGenerateRulesUseCase {
10
+ private readonly fileService;
11
+ private readonly legacyRuleDetector;
12
+ private readonly templateService;
13
+ private readonly terminal;
14
+ private readonly trackingService;
15
+ constructor(fileService: IFileService, legacyRuleDetector: LegacyRuleDetector, templateService: IRuleTemplateService, terminal: ITerminal, trackingService: ITrackingService);
20
16
  /**
21
17
  * Prompts the user to select an agent.
22
- * This method is protected to allow test overrides.
23
18
  * @returns The selected agent
24
19
  */
25
20
  protected promptForAgentSelection(): Promise<Agent>;
26
21
  /**
27
22
  * Prompts the user to choose cleanup strategy for legacy rules.
28
- * This method is protected to allow test overrides.
29
23
  * @returns The chosen cleanup strategy
30
24
  */
31
25
  protected promptForCleanupStrategy(): Promise<CleanupStrategy>;
@@ -1,14 +1,6 @@
1
- import { confirm, search, select } from '@inquirer/prompts';
2
- import { Command, Flags } from '@oclif/core';
3
- import { AGENT_VALUES } from '../core/domain/entities/agent.js';
4
- import { FsFileService } from '../infra/file/fs-file-service.js';
5
- import { AGENT_RULE_CONFIGS } from '../infra/rule/agent-rule-config.js';
6
- import { BRV_RULE_MARKERS, BRV_RULE_TAG } from '../infra/rule/constants.js';
7
- import { LegacyRuleDetector } from '../infra/rule/legacy-rule-detector.js';
8
- import { RuleTemplateService } from '../infra/rule/rule-template-service.js';
9
- import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
10
- import { FsTemplateLoader } from '../infra/template/fs-template-loader.js';
11
- import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
1
+ import { AGENT_VALUES } from '../../core/domain/entities/agent.js';
2
+ import { AGENT_RULE_CONFIGS } from '../rule/agent-rule-config.js';
3
+ import { BRV_RULE_MARKERS, BRV_RULE_TAG } from '../rule/constants.js';
12
4
  /**
13
5
  * Array of all agents with name and value properties.
14
6
  * Useful for UI components like select dropdowns.
@@ -17,50 +9,41 @@ const AGENTS = AGENT_VALUES.map((agent) => ({
17
9
  name: agent,
18
10
  value: agent,
19
11
  }));
20
- export default class GenRules extends Command {
21
- static description = 'Generate rule instructions for coding agents to work with ByteRover correctly';
22
- static examples = ['<%= config.bin %> <%= command.id %>'];
23
- static flags = {
24
- agent: Flags.string({
25
- char: 'a',
26
- description: 'Agent to generate rules for (optional, will prompt if not provided)',
27
- }),
28
- };
29
- createServices() {
30
- const fileService = new FsFileService();
31
- const templateLoader = new FsTemplateLoader(fileService);
32
- const templateService = new RuleTemplateService(templateLoader);
33
- return {
34
- fileService,
35
- legacyRuleDetector: new LegacyRuleDetector(),
36
- templateService,
37
- trackingService: new MixpanelTrackingService(new KeychainTokenStore()),
38
- };
12
+ export class GenerateRulesUseCase {
13
+ fileService;
14
+ legacyRuleDetector;
15
+ templateService;
16
+ terminal;
17
+ trackingService;
18
+ // eslint-disable-next-line max-params
19
+ constructor(fileService, legacyRuleDetector, templateService, terminal, trackingService) {
20
+ this.fileService = fileService;
21
+ this.legacyRuleDetector = legacyRuleDetector;
22
+ this.templateService = templateService;
23
+ this.terminal = terminal;
24
+ this.trackingService = trackingService;
39
25
  }
40
26
  /**
41
27
  * Prompts the user to select an agent.
42
- * This method is protected to allow test overrides.
43
28
  * @returns The selected agent
44
29
  */
45
30
  async promptForAgentSelection() {
46
- const answer = await search({
31
+ return this.terminal.search({
47
32
  message: 'Which agent you are using (type to search):',
48
- async source(input) {
33
+ source(input) {
49
34
  if (!input)
50
35
  return AGENTS;
51
36
  return AGENTS.filter((agent) => agent.name.toLowerCase().includes(input.toLowerCase()) ||
52
37
  agent.value.toLowerCase().includes(input.toLowerCase()));
53
38
  },
54
39
  });
55
- return answer;
56
40
  }
57
41
  /**
58
42
  * Prompts the user to choose cleanup strategy for legacy rules.
59
- * This method is protected to allow test overrides.
60
43
  * @returns The chosen cleanup strategy
61
44
  */
62
45
  async promptForCleanupStrategy() {
63
- return select({
46
+ return this.terminal.select({
64
47
  choices: [
65
48
  {
66
49
  description: 'New rules will be added with boundary markers. You manually remove old sections at your convenience.',
@@ -84,7 +67,7 @@ export default class GenRules extends Command {
84
67
  * @returns True if the user wants to create the file, false otherwise
85
68
  */
86
69
  async promptForFileCreation(agent, filePath) {
87
- return confirm({
70
+ return this.terminal.confirm({
88
71
  default: true,
89
72
  message: `Rule file '${filePath}' doesn't exist. Create it with ByteRover rules?`,
90
73
  });
@@ -96,36 +79,35 @@ export default class GenRules extends Command {
96
79
  * @returns True if the user confirms overwrite, false otherwise
97
80
  */
98
81
  async promptForOverwriteConfirmation(agent) {
99
- return confirm({
82
+ return this.terminal.confirm({
100
83
  default: true,
101
84
  message: `Rule file already exists for ${agent}. Overwrite?`,
102
85
  });
103
86
  }
104
87
  async run() {
105
- const { fileService, legacyRuleDetector, templateService, trackingService } = this.createServices();
106
- await trackingService.track('rule:generate');
88
+ await this.trackingService.track('rule:generate');
107
89
  const selectedAgent = await this.promptForAgentSelection();
108
90
  const { filePath, writeMode } = AGENT_RULE_CONFIGS[selectedAgent];
109
- this.log(`Generating rules for: ${selectedAgent}`);
91
+ this.terminal.log(`Generating rules for: ${selectedAgent}`);
110
92
  // STEP 1: Check if file exists
111
- const fileExists = await fileService.exists(filePath);
93
+ const fileExists = await this.fileService.exists(filePath);
112
94
  if (!fileExists) {
113
95
  // Scenario A: File doesn't exist
114
96
  const shouldCreate = await this.promptForFileCreation(selectedAgent, filePath);
115
97
  if (!shouldCreate) {
116
- this.log(`Skipped rule file creation for ${selectedAgent}`);
98
+ this.terminal.log(`Skipped rule file creation for ${selectedAgent}`);
117
99
  return;
118
100
  }
119
101
  await this.createNewRuleFile({
120
102
  agent: selectedAgent,
121
103
  filePath,
122
- fileService,
123
- templateService,
104
+ fileService: this.fileService,
105
+ templateService: this.templateService,
124
106
  });
125
107
  return;
126
108
  }
127
109
  // STEP 2: File exists - read content
128
- const content = await fileService.read(filePath);
110
+ const content = await this.fileService.read(filePath);
129
111
  // STEP 3: Check for LEGACY rules (priority: clean these up first)
130
112
  const hasFooterTag = content.includes(`${BRV_RULE_TAG} ${selectedAgent}`);
131
113
  const hasBoundaryMarkers = content.includes(BRV_RULE_MARKERS.START) && content.includes(BRV_RULE_MARKERS.END);
@@ -136,9 +118,9 @@ export default class GenRules extends Command {
136
118
  agent: selectedAgent,
137
119
  content,
138
120
  filePath,
139
- fileService,
140
- legacyRuleDetector,
141
- templateService,
121
+ fileService: this.fileService,
122
+ legacyRuleDetector: this.legacyRuleDetector,
123
+ templateService: this.templateService,
142
124
  });
143
125
  return;
144
126
  }
@@ -147,15 +129,15 @@ export default class GenRules extends Command {
147
129
  // Scenario C: New rules exist - prompt for overwrite
148
130
  const shouldOverwrite = await this.promptForOverwriteConfirmation(selectedAgent);
149
131
  if (!shouldOverwrite) {
150
- this.log(`Skipped rule file update for ${selectedAgent}`);
132
+ this.terminal.log(`Skipped rule file update for ${selectedAgent}`);
151
133
  return;
152
134
  }
153
135
  await this.replaceExistingRules({
154
136
  agent: selectedAgent,
155
137
  content,
156
138
  filePath,
157
- fileService,
158
- templateService,
139
+ fileService: this.fileService,
140
+ templateService: this.templateService,
159
141
  writeMode,
160
142
  });
161
143
  return;
@@ -164,8 +146,8 @@ export default class GenRules extends Command {
164
146
  await this.appendRulesToFile({
165
147
  agent: selectedAgent,
166
148
  filePath,
167
- fileService,
168
- templateService,
149
+ fileService: this.fileService,
150
+ templateService: this.templateService,
169
151
  writeMode,
170
152
  });
171
153
  }
@@ -178,7 +160,7 @@ export default class GenRules extends Command {
178
160
  // For dedicated ByteRover files, overwrite; for shared instruction files, append
179
161
  const mode = writeMode === 'overwrite' ? 'overwrite' : 'append';
180
162
  await fileService.write(ruleContent, filePath, mode);
181
- this.log(`✅ Successfully added rule file for ${agent}`);
163
+ this.terminal.log(`✅ Successfully added rule file for ${agent}`);
182
164
  }
183
165
  /**
184
166
  * Creates a new rule file with ByteRover rules.
@@ -187,7 +169,7 @@ export default class GenRules extends Command {
187
169
  const { agent, filePath, fileService, templateService } = params;
188
170
  const ruleContent = await templateService.generateRuleContent(agent);
189
171
  await fileService.write(ruleContent, filePath, 'overwrite');
190
- this.log(`✅ Successfully created rule file for ${agent} at ${filePath}`);
172
+ this.terminal.log(`✅ Successfully created rule file for ${agent} at ${filePath}`);
191
173
  }
192
174
  /**
193
175
  * Handles legacy rules cleanup with user choice of automatic or manual.
@@ -196,22 +178,21 @@ export default class GenRules extends Command {
196
178
  const { agent, content, filePath, fileService, legacyRuleDetector, templateService } = params;
197
179
  const detectionResult = legacyRuleDetector.detectLegacyRules(content, agent);
198
180
  const { reliableMatches, uncertainMatches } = detectionResult;
199
- this.log(`\n⚠️ Detected ${reliableMatches.length + uncertainMatches.length} old ByteRover rule section(s) in ${filePath}:\n`);
181
+ this.terminal.log(`\n⚠️ Detected ${reliableMatches.length + uncertainMatches.length} old ByteRover rule section(s) in ${filePath}:\n`);
200
182
  if (reliableMatches.length > 0) {
201
- this.log('Reliable matches:');
183
+ this.terminal.log('Reliable matches:');
202
184
  for (const [index, match] of reliableMatches.entries()) {
203
- this.log(` Section ${index + 1}: lines ${match.startLine}-${match.endLine}`);
185
+ this.terminal.log(` Section ${index + 1}: lines ${match.startLine}-${match.endLine}`);
204
186
  }
205
- this.log();
187
+ this.terminal.log('');
206
188
  }
207
189
  if (uncertainMatches.length > 0) {
208
- this.log(' ⚠️ Uncertain matches (cannot determine start):');
190
+ this.terminal.log(' ⚠️ Uncertain matches (cannot determine start):');
209
191
  for (const match of uncertainMatches) {
210
- this.log(` Footer found at line ${match.footerLine}`);
211
- this.log(` Reason: ${match.reason}`);
192
+ this.terminal.log(` Footer found at line ${match.footerLine}`);
193
+ this.terminal.log(` Reason: ${match.reason}`);
212
194
  }
213
- this.log();
214
- this.log('⚠️ Due to uncertain matches, only manual cleanup is available.\n');
195
+ this.terminal.log('\n⚠️ Due to uncertain matches, only manual cleanup is available.\n');
215
196
  await this.performManualCleanup({
216
197
  agent,
217
198
  filePath,
@@ -243,7 +224,7 @@ export default class GenRules extends Command {
243
224
  async performAutomaticCleanup(params) {
244
225
  const { agent, filePath, fileService, reliableMatches, templateService } = params;
245
226
  const backupPath = await fileService.createBackup(filePath);
246
- this.log(`📦 Backup created: ${backupPath}`);
227
+ this.terminal.log(`📦 Backup created: ${backupPath}`);
247
228
  let content = await fileService.read(filePath);
248
229
  // Remove all reliable matches (in reverse order to preserve line numbers)
249
230
  const sortedMatches = [...reliableMatches].sort((a, b) => b.startLine - a.startLine);
@@ -255,25 +236,25 @@ export default class GenRules extends Command {
255
236
  // Append new rules
256
237
  const ruleContent = await templateService.generateRuleContent(agent);
257
238
  await fileService.write(ruleContent, filePath, 'append');
258
- this.log(`✅ Removed ${reliableMatches.length} old ByteRover section(s)`);
259
- this.log(`✅ Added new rules with boundary markers`);
260
- this.log(`\nYou can safely delete the backup file once verified.`);
239
+ this.terminal.log(`✅ Removed ${reliableMatches.length} old ByteRover section(s)`);
240
+ this.terminal.log(`✅ Added new rules with boundary markers`);
241
+ this.terminal.log(`\nYou can safely delete the backup file once verified.`);
261
242
  }
262
243
  async performManualCleanup(params) {
263
244
  const { agent, filePath, fileService, reliableMatches, templateService, uncertainMatches } = params;
264
245
  const ruleContent = await templateService.generateRuleContent(agent);
265
246
  await fileService.write(ruleContent, filePath, 'append');
266
- this.log(`✅ New ByteRover rules added with boundary markers\n`);
267
- this.log('Please manually remove old sections:');
247
+ this.terminal.log(`✅ New ByteRover rules added with boundary markers\n`);
248
+ this.terminal.log('Please manually remove old sections:');
268
249
  for (const [index, match] of reliableMatches.entries()) {
269
- this.log(` - Section ${index + 1}: lines ${match.startLine}-${match.endLine} in ${filePath}`);
250
+ this.terminal.log(` - Section ${index + 1}: lines ${match.startLine}-${match.endLine} in ${filePath}`);
270
251
  }
271
252
  for (const match of uncertainMatches) {
272
- this.log(` - Section ending at line ${match.footerLine} in ${filePath}`);
253
+ this.terminal.log(` - Section ending at line ${match.footerLine} in ${filePath}`);
273
254
  }
274
- this.log('\nKeep only the section between:');
275
- this.log(' <!-- BEGIN BYTEROVER RULES -->');
276
- this.log(' <!-- END BYTEROVER RULES -->');
255
+ this.terminal.log('\nKeep only the section between:');
256
+ this.terminal.log(' <!-- BEGIN BYTEROVER RULES -->');
257
+ this.terminal.log(' <!-- END BYTEROVER RULES -->');
277
258
  }
278
259
  /**
279
260
  * Replaces existing ByteRover rules (with boundary markers) with new rules.
@@ -292,13 +273,13 @@ export default class GenRules extends Command {
292
273
  const startIndex = content.indexOf(startMarker);
293
274
  const endIndex = content.indexOf(endMarker, startIndex);
294
275
  if (startIndex === -1 || endIndex === -1) {
295
- this.error('Could not find boundary markers in the file');
276
+ this.terminal.error('Could not find boundary markers in the file');
296
277
  }
297
278
  const before = content.slice(0, startIndex);
298
279
  const after = content.slice(endIndex + endMarker.length);
299
280
  const newContent = before + ruleContent + after;
300
281
  await fileService.write(newContent, filePath, 'overwrite');
301
282
  }
302
- this.log(`✅ Successfully updated rule file for ${agent}`);
283
+ this.terminal.log(`✅ Successfully updated rule file for ${agent}`);
303
284
  }
304
285
  }