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,402 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { getCurrentConfig } from '../../config/environment.js';
3
+ import { PROJECT } from '../../constants.js';
4
+ import { formatError } from '../../utils/error-handler.js';
5
+ import { formatToolCall, formatToolResult } from '../../utils/tool-display-formatter.js';
6
+ import { CipherAgent } from '../cipher/cipher-agent.js';
7
+ import { getAgentStorage, getAgentStorageSync } from '../cipher/storage/agent-storage.js';
8
+ import { WorkspaceNotInitializedError } from '../cipher/validation/workspace-validator.js';
9
+ export class QueryUseCase {
10
+ projectConfigStore;
11
+ terminal;
12
+ tokenStore;
13
+ trackingService;
14
+ constructor(options) {
15
+ this.projectConfigStore = options.projectConfigStore;
16
+ this.terminal = options.terminal;
17
+ this.tokenStore = options.tokenStore;
18
+ this.trackingService = options.trackingService;
19
+ }
20
+ /**
21
+ * Create CipherAgent instance. Protected to allow test overrides.
22
+ */
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ createCipherAgent(llmConfig, brvConfig) {
25
+ return new CipherAgent(llmConfig, brvConfig);
26
+ }
27
+ /**
28
+ * Generate a unique session ID for the query agent.
29
+ * Uses crypto.randomUUID() for guaranteed uniqueness (122 bits of entropy).
30
+ */
31
+ generateSessionId() {
32
+ return randomUUID();
33
+ }
34
+ async run(options) {
35
+ await this.trackingService.track('mem:query', { status: 'started' });
36
+ // Initialize storage for tool call tracking (auto-detects .brv/blobs)
37
+ const storage = await getAgentStorage();
38
+ let executionId = null;
39
+ try {
40
+ // Get authentication token
41
+ const token = await this.tokenStore.load();
42
+ if (!token) {
43
+ this.terminal.log('Authentication required. Please run "/login" first.');
44
+ return;
45
+ }
46
+ // Load project config
47
+ const brvConfig = await this.projectConfigStore.read();
48
+ // Validate workspace is initialized
49
+ if (!brvConfig) {
50
+ throw new WorkspaceNotInitializedError('Project not initialized. Please run "/init" to select your team and workspace.', '.brv');
51
+ }
52
+ // Create execution with status='running' (query runs synchronously)
53
+ executionId = storage.createExecution('query', options.query);
54
+ // Create LLM config
55
+ const model = options.model ?? (options.apiKey ? 'google/gemini-2.5-pro' : 'gemini-2.5-pro');
56
+ const envConfig = getCurrentConfig();
57
+ const llmConfig = {
58
+ accessToken: token.accessToken,
59
+ apiBaseUrl: envConfig.llmApiBaseUrl,
60
+ fileSystemConfig: { workingDirectory: process.cwd() },
61
+ maxIterations: 5,
62
+ maxTokens: 2048,
63
+ model,
64
+ openRouterApiKey: options.apiKey,
65
+ projectId: PROJECT,
66
+ sessionKey: token.sessionKey,
67
+ temperature: 0.7,
68
+ topK: 10,
69
+ topP: 0.95,
70
+ verbose: options.verbose ?? false,
71
+ };
72
+ // Create and start CipherAgent
73
+ const agent = this.createCipherAgent(llmConfig, brvConfig);
74
+ this.terminal.log('Querying context tree...');
75
+ await agent.start();
76
+ try {
77
+ const sessionId = this.generateSessionId();
78
+ // Setup event listeners (display + tool call tracking)
79
+ this.setupEventListeners(agent, options.verbose ?? false);
80
+ this.setupToolCallTracking(agent, executionId);
81
+ // Execute with autonomous mode and query commandType
82
+ const prompt = `Search the context tree for: ${options.query}`;
83
+ const response = await agent.execute(prompt, sessionId, {
84
+ executionContext: { commandType: 'query' },
85
+ mode: 'autonomous',
86
+ });
87
+ // Mark execution as completed
88
+ storage.updateExecutionStatus(executionId, 'completed', response);
89
+ this.terminal.log('\nQuery Results:');
90
+ this.terminal.log(response);
91
+ await this.trackingService.track('mem:query', { status: 'finished' });
92
+ }
93
+ finally {
94
+ // Cleanup old executions
95
+ storage.cleanupOldExecutions(100);
96
+ }
97
+ }
98
+ catch (error) {
99
+ // Mark execution as failed
100
+ if (executionId) {
101
+ const errorMessage = error instanceof Error ? error.message : String(error);
102
+ storage.updateExecutionStatus(executionId, 'failed', undefined, errorMessage);
103
+ }
104
+ if (error instanceof WorkspaceNotInitializedError) {
105
+ this.handleWorkspaceError(error);
106
+ return;
107
+ }
108
+ // Display context on one line, error on separate line
109
+ process.stderr.write('Failed to query context tree:\n');
110
+ await this.trackingService.track('mem:query', { message: formatError(error), status: 'error' });
111
+ this.terminal.log(formatError(error));
112
+ }
113
+ }
114
+ /**
115
+ * Create result summary for tool call
116
+ */
117
+ createResultSummary(result) {
118
+ const lines = result.split('\n').length;
119
+ const chars = result.length;
120
+ return `${lines} lines, ${chars} chars`;
121
+ }
122
+ /**
123
+ * Extract summary from curate tool result
124
+ */
125
+ extractCurateSummary(result) {
126
+ if (typeof result === 'string') {
127
+ try {
128
+ const parsed = JSON.parse(result);
129
+ return parsed.summary ?? null;
130
+ }
131
+ catch {
132
+ return null;
133
+ }
134
+ }
135
+ if (typeof result === 'object' && result !== null) {
136
+ const resultObj = result;
137
+ return resultObj.summary ?? null;
138
+ }
139
+ return null;
140
+ }
141
+ /**
142
+ * Format curate tool operation summary
143
+ */
144
+ formatCurateResult(result) {
145
+ const summary = this.extractCurateSummary(result);
146
+ if (!summary) {
147
+ return '';
148
+ }
149
+ const { added = 0, deleted = 0, failed = 0, merged = 0, updated = 0 } = summary;
150
+ const parts = [];
151
+ if (added > 0)
152
+ parts.push(`${added} added`);
153
+ if (updated > 0)
154
+ parts.push(`${updated} updated`);
155
+ if (merged > 0)
156
+ parts.push(`${merged} merged`);
157
+ if (deleted > 0)
158
+ parts.push(`${deleted} deleted`);
159
+ if (failed > 0)
160
+ parts.push(`${failed} failed`);
161
+ return parts.length > 0 ? parts.join(', ') : 'No operations';
162
+ }
163
+ /**
164
+ * Format items count from list_directory result
165
+ */
166
+ formatItemsCount(result) {
167
+ if (typeof result === 'string') {
168
+ const lines = result.split('\n').filter((line) => line.trim());
169
+ return `${lines.length} items`;
170
+ }
171
+ if (Array.isArray(result)) {
172
+ return `${result.length} items`;
173
+ }
174
+ return '';
175
+ }
176
+ /**
177
+ * Format matches count from grep_content result
178
+ */
179
+ formatMatchesCount(result) {
180
+ if (typeof result === 'string') {
181
+ const lines = result.split('\n').filter((line) => line.trim());
182
+ return `${lines.length} matches found`;
183
+ }
184
+ if (Array.isArray(result)) {
185
+ return `${result.length} matches found`;
186
+ }
187
+ return '';
188
+ }
189
+ /**
190
+ * Format tool result summary for display
191
+ */
192
+ formatToolResultSummary(toolName, result) {
193
+ try {
194
+ switch (toolName) {
195
+ case 'bash_exec':
196
+ case 'create_knowledge_topic':
197
+ case 'delete_knowledge_topic':
198
+ case 'detect_domains':
199
+ case 'read_file':
200
+ case 'write_file': {
201
+ return '';
202
+ }
203
+ case 'curate': {
204
+ return this.formatCurateResult(result);
205
+ }
206
+ case 'find_knowledge_topics': {
207
+ return this.formatTopicsCount(result);
208
+ }
209
+ case 'grep_content': {
210
+ return this.formatMatchesCount(result);
211
+ }
212
+ case 'list_directory': {
213
+ return this.formatItemsCount(result);
214
+ }
215
+ default: {
216
+ return '';
217
+ }
218
+ }
219
+ }
220
+ catch {
221
+ return '';
222
+ }
223
+ }
224
+ /**
225
+ * Format topics count from find_knowledge_topics result
226
+ */
227
+ formatTopicsCount(result) {
228
+ if (typeof result === 'string') {
229
+ try {
230
+ const parsed = JSON.parse(result);
231
+ const count = Array.isArray(parsed) ? parsed.length : Object.keys(parsed).length;
232
+ return `${count} topics retrieved`;
233
+ }
234
+ catch {
235
+ return '';
236
+ }
237
+ }
238
+ if (typeof result === 'object' && result !== null) {
239
+ const resultObj = result;
240
+ if (Array.isArray(resultObj.results)) {
241
+ return `${resultObj.results.length} topics retrieved`;
242
+ }
243
+ if (typeof resultObj.total === 'number') {
244
+ return `${resultObj.total} topics retrieved`;
245
+ }
246
+ if (Array.isArray(result)) {
247
+ return `${result.length} topics retrieved`;
248
+ }
249
+ }
250
+ return '';
251
+ }
252
+ /**
253
+ * Get user-friendly description for a tool
254
+ *
255
+ * @param toolName - Name of the tool
256
+ * @param args - Tool arguments
257
+ * @returns User-friendly description
258
+ */
259
+ getToolDescription(toolName, args) {
260
+ switch (toolName) {
261
+ case 'bash_exec': {
262
+ const cmd = String(args.command ?? '');
263
+ return cmd.length > 60 ? `Running command...` : `Running: ${cmd}`;
264
+ }
265
+ case 'create_knowledge_topic': {
266
+ return 'Creating knowledge topic...';
267
+ }
268
+ case 'curate': {
269
+ return 'Curating context tree...';
270
+ }
271
+ case 'find_knowledge_topics': {
272
+ return 'Querying context tree...';
273
+ }
274
+ case 'grep_content': {
275
+ return 'Searching context tree...';
276
+ }
277
+ case 'list_directory': {
278
+ return 'Listing directory...';
279
+ }
280
+ case 'read_file': {
281
+ return `Reading file...`;
282
+ }
283
+ case 'write_file': {
284
+ return 'Writing file...';
285
+ }
286
+ default: {
287
+ return 'Processing...';
288
+ }
289
+ }
290
+ }
291
+ /**
292
+ * Handle workspace not initialized error
293
+ */
294
+ handleWorkspaceError(_error) {
295
+ const message = 'Project not initialized. Please run "brv init" to select your team and workspace.';
296
+ this.terminal.log(message);
297
+ }
298
+ /**
299
+ * Setup event listeners for CipherAgent
300
+ */
301
+ setupEventListeners(agent, verbose) {
302
+ if (!agent.agentEventBus) {
303
+ throw new Error('Agent event bus not initialized');
304
+ }
305
+ const eventBus = agent.agentEventBus;
306
+ if (verbose) {
307
+ // Verbose mode: show detailed events
308
+ eventBus.on('llmservice:thinking', () => {
309
+ this.terminal.log('🤔 [Event] LLM is thinking...');
310
+ });
311
+ eventBus.on('llmservice:response', (payload) => {
312
+ this.terminal.log(`✅ [Event] LLM Response (${payload.provider}/${payload.model})`);
313
+ });
314
+ eventBus.on('llmservice:toolCall', (payload) => {
315
+ // Clear any spinner on current line before printing (use spaces instead of ANSI codes)
316
+ const formattedCall = formatToolCall(payload.toolName, payload.args);
317
+ this.terminal.log(`🔧 [Event] Tool Call: ${formattedCall}`);
318
+ });
319
+ eventBus.on('llmservice:toolResult', (payload) => {
320
+ const resultSummary = formatToolResult(payload.toolName, payload.success, payload.result, payload.error);
321
+ if (payload.success) {
322
+ this.terminal.log(`✓ [Event] Tool Success: ${payload.toolName} → ${resultSummary}`);
323
+ }
324
+ else {
325
+ this.terminal.log(`✗ [Event] Tool Error: ${payload.toolName} → ${resultSummary}`);
326
+ }
327
+ });
328
+ // NOTE: llmservice:error is handled by catch block in the run method
329
+ // which displays error via this.error(). DO NOT display here to avoid duplicate.
330
+ }
331
+ else {
332
+ // Non-verbose mode: show concise tool progress with descriptions
333
+ // eventBus.on('llmservice:toolCall', (payload) => {
334
+ // // Clear any spinner on current line before printing (use spaces instead of ANSI codes)
335
+ // const description = this.getToolDescription(payload.toolName, payload.args)
336
+ // this.terminal.log(`🔧 ${payload.toolName} → ${description}`)
337
+ // })
338
+ // eventBus.on('llmservice:toolResult', (payload) => {
339
+ // if (payload.success) {
340
+ // // Show brief success summary for tool completion
341
+ // const summary = this.formatToolResultSummary(payload.toolName, payload.result)
342
+ // const completionText = summary ? `Complete (${summary})` : 'Complete'
343
+ // this.terminal.log(`✅ ${payload.toolName} → ${completionText}`)
344
+ // } else {
345
+ // this.terminal.log(`✗ ${payload.toolName} → Failed: ${payload.error}`)
346
+ // }
347
+ // })
348
+ // NOTE: llmservice:error is handled by catch block in the run method
349
+ // which displays error via this.error(). DO NOT display here to avoid duplicate.
350
+ }
351
+ }
352
+ /**
353
+ * Setup tool call tracking to persist in database
354
+ */
355
+ setupToolCallTracking(agent, executionId) {
356
+ if (!agent.agentEventBus) {
357
+ return;
358
+ }
359
+ const storage = getAgentStorageSync();
360
+ const eventBus = agent.agentEventBus;
361
+ const toolCallMap = new Map(); // callId -> dbToolCallId
362
+ eventBus.on('llmservice:toolCall', (payload) => {
363
+ try {
364
+ if (!payload.callId)
365
+ return;
366
+ const toolCallId = storage.addToolCall(executionId, {
367
+ args: payload.args,
368
+ name: payload.toolName,
369
+ });
370
+ toolCallMap.set(payload.callId, toolCallId);
371
+ }
372
+ catch {
373
+ // Ignore errors - don't break query execution
374
+ }
375
+ });
376
+ eventBus.on('llmservice:toolResult', (payload) => {
377
+ try {
378
+ if (!payload.callId)
379
+ return;
380
+ const toolCallId = toolCallMap.get(payload.callId);
381
+ if (toolCallId) {
382
+ // Format result: if error, wrap in {error: "..."} object
383
+ let result;
384
+ if (payload.success) {
385
+ result = typeof payload.result === 'string' ? payload.result : JSON.stringify(payload.result);
386
+ }
387
+ else {
388
+ const errorMsg = payload.error ?? (typeof payload.result === 'string' ? payload.result : 'Unknown error');
389
+ result = JSON.stringify({ error: errorMsg });
390
+ }
391
+ storage.updateToolCall(toolCallId, payload.success ? 'completed' : 'failed', {
392
+ result,
393
+ resultSummary: payload.success ? this.createResultSummary(result) : undefined,
394
+ });
395
+ }
396
+ }
397
+ catch {
398
+ // Ignore errors - don't break query execution
399
+ }
400
+ });
401
+ }
402
+ }
@@ -0,0 +1,27 @@
1
+ import type { IProjectConfigStore } from '../../core/interfaces/i-project-config-store.js';
2
+ import type { ISpaceService } from '../../core/interfaces/i-space-service.js';
3
+ import type { ITerminal } from '../../core/interfaces/i-terminal.js';
4
+ import type { ITokenStore } from '../../core/interfaces/i-token-store.js';
5
+ import type { ISpaceListUseCase } from '../../core/interfaces/usecase/i-space-list-use-case.js';
6
+ export interface SpaceListFlags {
7
+ all: boolean;
8
+ json: boolean;
9
+ limit: number;
10
+ offset: number;
11
+ }
12
+ export interface SpaceListUseCaseDependencies {
13
+ flags: SpaceListFlags;
14
+ projectConfigStore: IProjectConfigStore;
15
+ spaceService: ISpaceService;
16
+ terminal: ITerminal;
17
+ tokenStore: ITokenStore;
18
+ }
19
+ export declare class SpaceListUseCase implements ISpaceListUseCase {
20
+ private readonly flags;
21
+ private readonly projectConfigStore;
22
+ private readonly spaceService;
23
+ private readonly terminal;
24
+ private readonly tokenStore;
25
+ constructor(deps: SpaceListUseCaseDependencies);
26
+ run(): Promise<void>;
27
+ }
@@ -0,0 +1,64 @@
1
+ export class SpaceListUseCase {
2
+ flags;
3
+ projectConfigStore;
4
+ spaceService;
5
+ terminal;
6
+ tokenStore;
7
+ constructor(deps) {
8
+ this.flags = deps.flags;
9
+ this.projectConfigStore = deps.projectConfigStore;
10
+ this.spaceService = deps.spaceService;
11
+ this.terminal = deps.terminal;
12
+ this.tokenStore = deps.tokenStore;
13
+ }
14
+ async run() {
15
+ // Check project initialization
16
+ const projectConfig = await this.projectConfigStore.read();
17
+ if (!projectConfig) {
18
+ this.terminal.error('Project not initialized. Please run "brv init" first.');
19
+ return;
20
+ }
21
+ const token = await this.tokenStore.load();
22
+ if (!token) {
23
+ this.terminal.error('Not authenticated. Please run "brv login" first.');
24
+ return;
25
+ }
26
+ if (!token.isValid()) {
27
+ this.terminal.error('Authentication token expired. Please run "brv login" again.');
28
+ return;
29
+ }
30
+ // Fetch spaces for the team from project config
31
+ this.terminal.actionStart(`Fetching spaces for ${projectConfig.teamName}`);
32
+ const result = await this.spaceService.getSpaces(token.accessToken, token.sessionKey, projectConfig.teamId, this.flags.all ? { fetchAll: true } : { limit: this.flags.limit, offset: this.flags.offset });
33
+ this.terminal.actionStop();
34
+ // Handle empty results
35
+ if (result.spaces.length === 0) {
36
+ this.terminal.log(`No spaces found in team "${projectConfig.teamName}".`);
37
+ return;
38
+ }
39
+ // Display results based on format
40
+ if (this.flags.json) {
41
+ this.terminal.log(JSON.stringify({
42
+ showing: result.spaces.length,
43
+ spaces: result.spaces.map((s) => s.toJson()),
44
+ team: { id: projectConfig.teamId, name: projectConfig.teamName },
45
+ total: result.total,
46
+ }, null, 2));
47
+ return;
48
+ }
49
+ // Human-readable format
50
+ this.terminal.log(`\nSpaces in team "${projectConfig.teamName}":\n`);
51
+ this.terminal.log(`Found ${result.spaces.length} space(s):\n`);
52
+ for (const [index, space] of result.spaces.entries()) {
53
+ this.terminal.log(` ${index + 1}. ${space.getDisplayName()}`);
54
+ }
55
+ // Pagination warning
56
+ if (!this.flags.all && result.spaces.length < result.total) {
57
+ const remaining = result.total - result.spaces.length - this.flags.offset;
58
+ this.terminal.log(`\nShowing ${result.spaces.length} of ${result.total} spaces.`);
59
+ if (remaining > 0) {
60
+ this.terminal.log('Use --all to fetch all spaces, or use --limit and --offset for pagination.');
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,36 @@
1
+ import type { Space } from '../../core/domain/entities/space.js';
2
+ import type { Team } from '../../core/domain/entities/team.js';
3
+ import type { IProjectConfigStore } from '../../core/interfaces/i-project-config-store.js';
4
+ import type { ISpaceService } from '../../core/interfaces/i-space-service.js';
5
+ import type { ITeamService } from '../../core/interfaces/i-team-service.js';
6
+ import type { ITerminal } from '../../core/interfaces/i-terminal.js';
7
+ import type { ITokenStore } from '../../core/interfaces/i-token-store.js';
8
+ import type { IWorkspaceDetectorService } from '../../core/interfaces/i-workspace-detector-service.js';
9
+ import type { ISpaceSwitchUseCase } from '../../core/interfaces/usecase/i-space-switch-use-case.js';
10
+ import { Agent } from '../../core/domain/entities/agent.js';
11
+ export interface SpaceSwitchUseCaseDependencies {
12
+ projectConfigStore: IProjectConfigStore;
13
+ spaceService: ISpaceService;
14
+ teamService: ITeamService;
15
+ terminal: ITerminal;
16
+ tokenStore: ITokenStore;
17
+ workspaceDetector: IWorkspaceDetectorService;
18
+ }
19
+ export declare class SpaceSwitchUseCase implements ISpaceSwitchUseCase {
20
+ private readonly projectConfigStore;
21
+ private readonly spaceService;
22
+ private readonly teamService;
23
+ private readonly terminal;
24
+ private readonly tokenStore;
25
+ private readonly workspaceDetector;
26
+ constructor(deps: SpaceSwitchUseCaseDependencies);
27
+ /**
28
+ * Prompts the user to select an agent.
29
+ * This method is protected to allow test overrides.
30
+ * @returns The selected agent
31
+ */
32
+ protected promptForAgentSelection(): Promise<Agent>;
33
+ protected promptForSpaceSelection(spaces: Space[]): Promise<Space | undefined>;
34
+ protected promptForTeamSelection(teams: Team[]): Promise<Team | undefined>;
35
+ run(): Promise<void>;
36
+ }
@@ -0,0 +1,140 @@
1
+ import { BRV_DIR, PROJECT_CONFIG_FILE } from '../../constants.js';
2
+ import { AGENT_VALUES } from '../../core/domain/entities/agent.js';
3
+ import { BrvConfig } from '../../core/domain/entities/brv-config.js';
4
+ /**
5
+ * Array of all agents with name and value properties.
6
+ * Useful for UI components like select dropdowns.
7
+ */
8
+ const AGENTS = AGENT_VALUES.map((agent) => ({
9
+ name: agent,
10
+ value: agent,
11
+ }));
12
+ export class SpaceSwitchUseCase {
13
+ projectConfigStore;
14
+ spaceService;
15
+ teamService;
16
+ terminal;
17
+ tokenStore;
18
+ workspaceDetector;
19
+ constructor(deps) {
20
+ this.projectConfigStore = deps.projectConfigStore;
21
+ this.spaceService = deps.spaceService;
22
+ this.teamService = deps.teamService;
23
+ this.terminal = deps.terminal;
24
+ this.tokenStore = deps.tokenStore;
25
+ this.workspaceDetector = deps.workspaceDetector;
26
+ }
27
+ /**
28
+ * Prompts the user to select an agent.
29
+ * This method is protected to allow test overrides.
30
+ * @returns The selected agent
31
+ */
32
+ async promptForAgentSelection() {
33
+ return this.terminal.search({
34
+ message: 'Which agent you are using (type to search):',
35
+ source(input) {
36
+ if (!input)
37
+ return AGENTS;
38
+ return AGENTS.filter((agent) => agent.name.toLowerCase().includes(input.toLowerCase()) ||
39
+ agent.value.toLowerCase().includes(input.toLowerCase()));
40
+ },
41
+ });
42
+ }
43
+ async promptForSpaceSelection(spaces) {
44
+ const selectedSpaceId = await this.terminal.select({
45
+ choices: spaces.map((space) => ({
46
+ name: space.getDisplayName(),
47
+ value: space.id,
48
+ })),
49
+ message: 'Select a space',
50
+ });
51
+ const selectedSpace = spaces.find((space) => space.id === selectedSpaceId);
52
+ if (!selectedSpace) {
53
+ this.terminal.log('Space selection failed');
54
+ return undefined;
55
+ }
56
+ return selectedSpace;
57
+ }
58
+ async promptForTeamSelection(teams) {
59
+ const selectedTeamId = await this.terminal.select({
60
+ choices: teams.map((team) => ({
61
+ name: team.name,
62
+ value: team.id,
63
+ })),
64
+ message: 'Select a team',
65
+ });
66
+ const selectedTeam = teams.find((team) => team.id === selectedTeamId);
67
+ if (!selectedTeam) {
68
+ this.terminal.log('Team selection failed');
69
+ return undefined;
70
+ }
71
+ return selectedTeam;
72
+ }
73
+ async run() {
74
+ // Check project initialization (MUST exist for switch)
75
+ const currentConfig = await this.projectConfigStore.read();
76
+ if (!currentConfig) {
77
+ this.terminal.log('Project not initialized. Please run "brv init" first.');
78
+ return;
79
+ }
80
+ // Show current configuration
81
+ this.terminal.log('Current configuration:');
82
+ this.terminal.log(` Team: ${currentConfig.teamName}`);
83
+ this.terminal.log(` Space: ${currentConfig.spaceName}`);
84
+ this.terminal.log();
85
+ // Validate authentication
86
+ const token = await this.tokenStore.load();
87
+ if (!token) {
88
+ this.terminal.log('Not authenticated. Please run "brv login" first.');
89
+ return;
90
+ }
91
+ if (!token.isValid()) {
92
+ this.terminal.log('Authentication token expired. Please run "brv login" again.');
93
+ return;
94
+ }
95
+ // Fetch all teams
96
+ this.terminal.actionStart('Fetching all teams');
97
+ const teamResult = await this.teamService.getTeams(token.accessToken, token.sessionKey, { fetchAll: true });
98
+ this.terminal.actionStop();
99
+ if (teamResult.teams.length === 0) {
100
+ this.terminal.log('No teams found. Please create a team in the ByteRover dashboard first.');
101
+ return;
102
+ }
103
+ // Prompt for team selection
104
+ this.terminal.log();
105
+ const selectedTeam = await this.promptForTeamSelection(teamResult.teams);
106
+ if (!selectedTeam)
107
+ return;
108
+ // Fetch spaces for selected team
109
+ this.terminal.actionStart('Fetching all spaces');
110
+ const spaceResult = await this.spaceService.getSpaces(token.accessToken, token.sessionKey, selectedTeam.id, {
111
+ fetchAll: true,
112
+ });
113
+ this.terminal.actionStop();
114
+ if (spaceResult.spaces.length === 0) {
115
+ this.terminal.log(`No spaces found in team "${selectedTeam.getDisplayName()}". Please create a space in the ByteRover dashboard first.`);
116
+ return;
117
+ }
118
+ // Prompt for space selection
119
+ this.terminal.log();
120
+ const selectedSpace = await this.promptForSpaceSelection(spaceResult.spaces);
121
+ if (!selectedSpace)
122
+ return;
123
+ // Prompt for agent selection
124
+ this.terminal.log();
125
+ const selectedAgent = await this.promptForAgentSelection();
126
+ this.terminal.log();
127
+ const { chatLogPath, cwd } = this.workspaceDetector.detectWorkspaces(selectedAgent);
128
+ // Update configuration
129
+ const newConfig = BrvConfig.fromSpace({
130
+ chatLogPath,
131
+ cwd,
132
+ ide: selectedAgent,
133
+ space: selectedSpace,
134
+ });
135
+ await this.projectConfigStore.write(newConfig);
136
+ // Display success
137
+ this.terminal.log(`\n✓ Successfully switched to space: ${selectedSpace.getDisplayName()}`);
138
+ this.terminal.log(`✓ Configuration updated in: ${BRV_DIR}/${PROJECT_CONFIG_FILE}`);
139
+ }
140
+ }