byterover-cli 2.5.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. package/.env.production +8 -0
  2. package/LICENSE +44 -0
  3. package/README.md +240 -14
  4. package/bin/dev.js +8 -1
  5. package/bin/run.js +8 -1
  6. package/dist/agent/core/domain/knowledge/conflict-detector.d.ts +38 -0
  7. package/dist/agent/core/domain/knowledge/conflict-detector.js +71 -0
  8. package/dist/agent/core/domain/knowledge/conflict-resolver.d.ts +17 -0
  9. package/dist/agent/core/domain/knowledge/conflict-resolver.js +118 -0
  10. package/dist/agent/core/domain/knowledge/utils.d.ts +4 -0
  11. package/dist/agent/core/domain/knowledge/utils.js +6 -0
  12. package/dist/agent/core/interfaces/i-curate-service.d.ts +6 -0
  13. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +67 -34
  14. package/dist/agent/infra/tools/implementations/curate-tool.js +294 -47
  15. package/dist/agent/resources/prompts/system-prompt.yml +15 -8
  16. package/dist/agent/resources/tools/code_exec.txt +3 -0
  17. package/dist/agent/resources/tools/curate.txt +12 -3
  18. package/dist/oclif/commands/connectors/install.d.ts +2 -1
  19. package/dist/oclif/commands/connectors/install.js +38 -3
  20. package/dist/oclif/commands/curate/index.d.ts +18 -0
  21. package/dist/oclif/commands/curate/index.js +78 -1
  22. package/dist/oclif/commands/init.d.ts +12 -0
  23. package/dist/oclif/commands/init.js +75 -0
  24. package/dist/oclif/commands/locations.js +1 -1
  25. package/dist/oclif/commands/providers/connect.d.ts +31 -1
  26. package/dist/oclif/commands/providers/connect.js +307 -27
  27. package/dist/oclif/commands/pull.d.ts +1 -0
  28. package/dist/oclif/commands/pull.js +7 -0
  29. package/dist/oclif/commands/push.d.ts +1 -0
  30. package/dist/oclif/commands/push.js +8 -0
  31. package/dist/oclif/commands/review/approve.d.ts +17 -0
  32. package/dist/oclif/commands/review/approve.js +37 -0
  33. package/dist/oclif/commands/review/base-review-decision.d.ts +18 -0
  34. package/dist/oclif/commands/review/base-review-decision.js +71 -0
  35. package/dist/oclif/commands/review/pending.d.ts +13 -0
  36. package/dist/oclif/commands/review/pending.js +94 -0
  37. package/dist/oclif/commands/review/reject.d.ts +17 -0
  38. package/dist/oclif/commands/review/reject.js +38 -0
  39. package/dist/oclif/commands/space/list.d.ts +2 -2
  40. package/dist/oclif/commands/space/list.js +13 -35
  41. package/dist/oclif/commands/space/switch.d.ts +2 -7
  42. package/dist/oclif/commands/space/switch.js +13 -56
  43. package/dist/oclif/commands/status.d.ts +1 -0
  44. package/dist/oclif/commands/status.js +11 -1
  45. package/dist/oclif/commands/vc/add.d.ts +7 -0
  46. package/dist/oclif/commands/vc/add.js +29 -0
  47. package/dist/oclif/commands/vc/branch.d.ts +15 -0
  48. package/dist/oclif/commands/vc/branch.js +70 -0
  49. package/dist/oclif/commands/vc/checkout.d.ts +14 -0
  50. package/dist/oclif/commands/vc/checkout.js +47 -0
  51. package/dist/oclif/commands/vc/clone.d.ts +9 -0
  52. package/dist/oclif/commands/vc/clone.js +61 -0
  53. package/dist/oclif/commands/vc/commit.d.ts +10 -0
  54. package/dist/oclif/commands/vc/commit.js +32 -0
  55. package/dist/oclif/commands/vc/config.d.ts +10 -0
  56. package/dist/oclif/commands/vc/config.js +30 -0
  57. package/dist/oclif/commands/vc/fetch.d.ts +10 -0
  58. package/dist/oclif/commands/vc/fetch.js +42 -0
  59. package/dist/oclif/commands/vc/index.d.ts +6 -0
  60. package/dist/oclif/commands/vc/index.js +8 -0
  61. package/dist/oclif/commands/vc/init.d.ts +6 -0
  62. package/dist/oclif/commands/vc/init.js +25 -0
  63. package/dist/oclif/commands/vc/log.d.ts +13 -0
  64. package/dist/oclif/commands/vc/log.js +48 -0
  65. package/dist/oclif/commands/vc/merge.d.ts +19 -0
  66. package/dist/oclif/commands/vc/merge.js +130 -0
  67. package/dist/oclif/commands/vc/pull.d.ts +13 -0
  68. package/dist/oclif/commands/vc/pull.js +60 -0
  69. package/dist/oclif/commands/vc/push.d.ts +13 -0
  70. package/dist/oclif/commands/vc/push.js +60 -0
  71. package/dist/oclif/commands/vc/remote/add.d.ts +10 -0
  72. package/dist/oclif/commands/vc/remote/add.js +30 -0
  73. package/dist/oclif/commands/vc/remote/index.d.ts +6 -0
  74. package/dist/oclif/commands/vc/remote/index.js +16 -0
  75. package/dist/oclif/commands/vc/remote/set-url.d.ts +10 -0
  76. package/dist/oclif/commands/vc/remote/set-url.js +30 -0
  77. package/dist/oclif/commands/vc/reset.d.ts +13 -0
  78. package/dist/oclif/commands/vc/reset.js +62 -0
  79. package/dist/oclif/commands/vc/status.d.ts +8 -0
  80. package/dist/oclif/commands/vc/status.js +106 -0
  81. package/dist/oclif/hooks/init/validate-brv-config.d.ts +26 -0
  82. package/dist/oclif/hooks/init/validate-brv-config.js +62 -0
  83. package/dist/oclif/lib/daemon-client.d.ts +2 -0
  84. package/dist/oclif/lib/daemon-client.js +36 -10
  85. package/dist/oclif/lib/prompt-utils.d.ts +43 -0
  86. package/dist/oclif/lib/prompt-utils.js +84 -0
  87. package/dist/oclif/lib/spinner.d.ts +8 -0
  88. package/dist/oclif/lib/spinner.js +23 -0
  89. package/dist/oclif/lib/task-client.d.ts +5 -0
  90. package/dist/oclif/lib/task-client.js +15 -2
  91. package/dist/server/config/environment.d.ts +2 -19
  92. package/dist/server/config/environment.js +31 -38
  93. package/dist/server/constants.d.ts +3 -9
  94. package/dist/server/constants.js +9 -12
  95. package/dist/server/core/domain/entities/auth-token.d.ts +2 -0
  96. package/dist/server/core/domain/entities/auth-token.js +7 -1
  97. package/dist/server/core/domain/entities/curate-log-entry.d.ts +11 -0
  98. package/dist/server/core/domain/entities/space.d.ts +4 -0
  99. package/dist/server/core/domain/entities/space.js +8 -0
  100. package/dist/server/core/domain/entities/team.d.ts +2 -0
  101. package/dist/server/core/domain/entities/team.js +4 -0
  102. package/dist/server/core/domain/errors/auth-error.d.ts +0 -6
  103. package/dist/server/core/domain/errors/auth-error.js +0 -12
  104. package/dist/server/core/domain/errors/git-error.d.ts +6 -0
  105. package/dist/server/core/domain/errors/git-error.js +12 -0
  106. package/dist/server/core/domain/errors/task-error.d.ts +4 -3
  107. package/dist/server/core/domain/errors/task-error.js +8 -8
  108. package/dist/server/core/domain/errors/transport-error.d.ts +0 -31
  109. package/dist/server/core/domain/errors/transport-error.js +0 -50
  110. package/dist/server/core/domain/errors/vc-error.d.ts +5 -0
  111. package/dist/server/core/domain/errors/vc-error.js +8 -0
  112. package/dist/server/core/domain/knowledge/markdown-writer.d.ts +4 -1
  113. package/dist/server/core/domain/knowledge/markdown-writer.js +37 -7
  114. package/dist/server/core/domain/transport/schemas.d.ts +6 -6
  115. package/dist/server/core/interfaces/context-tree/i-context-tree-service.d.ts +11 -0
  116. package/dist/server/core/interfaces/process/i-task-lifecycle-hook.d.ts +6 -0
  117. package/dist/server/core/interfaces/services/i-git-service.d.ts +234 -0
  118. package/dist/server/core/interfaces/storage/i-curate-log-store.d.ts +5 -0
  119. package/dist/server/core/interfaces/storage/i-review-backup-store.d.ts +19 -0
  120. package/dist/server/core/interfaces/vc/i-vc-git-config-store.d.ts +8 -0
  121. package/dist/server/infra/config/auto-init.d.ts +0 -2
  122. package/dist/server/infra/config/auto-init.js +0 -1
  123. package/dist/server/infra/connectors/rules/rules-connector-config.d.ts +0 -4
  124. package/dist/server/infra/context-tree/file-context-tree-service.d.ts +2 -0
  125. package/dist/server/infra/context-tree/file-context-tree-service.js +13 -0
  126. package/dist/server/infra/daemon/brv-server.js +23 -3
  127. package/dist/server/infra/git/cogit-url.d.ts +17 -0
  128. package/dist/server/infra/git/cogit-url.js +39 -0
  129. package/dist/server/infra/git/git-http-wrapper.d.ts +20 -0
  130. package/dist/server/infra/git/git-http-wrapper.js +334 -0
  131. package/dist/server/infra/git/isomorphic-git-service.d.ts +78 -0
  132. package/dist/server/infra/git/isomorphic-git-service.js +983 -0
  133. package/dist/server/infra/http/models-dev-client.d.ts +0 -4
  134. package/dist/server/infra/http/models-dev-client.js +0 -6
  135. package/dist/server/infra/http/openrouter-api-client.d.ts +0 -8
  136. package/dist/server/infra/http/openrouter-api-client.js +0 -13
  137. package/dist/server/infra/http/provider-model-fetcher-registry.d.ts +0 -5
  138. package/dist/server/infra/http/provider-model-fetcher-registry.js +0 -7
  139. package/dist/server/infra/http/review-api-handler.d.ts +13 -0
  140. package/dist/server/infra/http/review-api-handler.js +286 -0
  141. package/dist/server/infra/http/review-ui.d.ts +7 -0
  142. package/dist/server/infra/http/review-ui.js +606 -0
  143. package/dist/server/infra/mcp/tools/brv-curate-tool.d.ts +2 -2
  144. package/dist/server/infra/process/curate-log-handler.d.ts +18 -2
  145. package/dist/server/infra/process/curate-log-handler.js +50 -13
  146. package/dist/server/infra/process/feature-handlers.js +41 -1
  147. package/dist/server/infra/process/task-router.js +16 -0
  148. package/dist/server/infra/provider/env-provider-detector.d.ts +0 -20
  149. package/dist/server/infra/provider/env-provider-detector.js +0 -27
  150. package/dist/server/infra/space/http-space-service.js +2 -0
  151. package/dist/server/infra/storage/file-curate-log-store.d.ts +10 -0
  152. package/dist/server/infra/storage/file-curate-log-store.js +35 -0
  153. package/dist/server/infra/storage/file-provider-config-store.d.ts +0 -4
  154. package/dist/server/infra/storage/file-provider-config-store.js +0 -6
  155. package/dist/server/infra/storage/file-review-backup-store.d.ts +29 -0
  156. package/dist/server/infra/storage/file-review-backup-store.js +121 -0
  157. package/dist/server/infra/transport/handlers/auth-handler.js +9 -5
  158. package/dist/server/infra/transport/handlers/handler-types.d.ts +9 -0
  159. package/dist/server/infra/transport/handlers/handler-types.js +11 -0
  160. package/dist/server/infra/transport/handlers/index.d.ts +4 -0
  161. package/dist/server/infra/transport/handlers/index.js +2 -0
  162. package/dist/server/infra/transport/handlers/init-handler.d.ts +1 -0
  163. package/dist/server/infra/transport/handlers/init-handler.js +13 -1
  164. package/dist/server/infra/transport/handlers/pull-handler.d.ts +3 -0
  165. package/dist/server/infra/transport/handlers/pull-handler.js +5 -1
  166. package/dist/server/infra/transport/handlers/push-handler.d.ts +20 -0
  167. package/dist/server/infra/transport/handlers/push-handler.js +116 -14
  168. package/dist/server/infra/transport/handlers/reset-handler.d.ts +11 -0
  169. package/dist/server/infra/transport/handlers/reset-handler.js +37 -1
  170. package/dist/server/infra/transport/handlers/review-handler.d.ts +35 -0
  171. package/dist/server/infra/transport/handlers/review-handler.js +162 -0
  172. package/dist/server/infra/transport/handlers/space-handler.d.ts +3 -0
  173. package/dist/server/infra/transport/handlers/space-handler.js +4 -1
  174. package/dist/server/infra/transport/handlers/status-handler.d.ts +5 -0
  175. package/dist/server/infra/transport/handlers/status-handler.js +51 -16
  176. package/dist/server/infra/transport/handlers/vc-handler.d.ts +100 -0
  177. package/dist/server/infra/transport/handlers/vc-handler.js +1050 -0
  178. package/dist/server/infra/transport/socket-io-transport-server.d.ts +7 -0
  179. package/dist/server/infra/transport/socket-io-transport-server.js +12 -1
  180. package/dist/server/infra/transport/transport-connector.d.ts +1 -1
  181. package/dist/server/infra/transport/transport-connector.js +2 -1
  182. package/dist/server/infra/vc/file-vc-git-config-store.d.ts +11 -0
  183. package/dist/server/infra/vc/file-vc-git-config-store.js +43 -0
  184. package/dist/server/templates/skill/SKILL.md +167 -33
  185. package/dist/server/utils/curate-result-parser.d.ts +64 -0
  186. package/dist/server/utils/curate-result-parser.js +8 -0
  187. package/dist/server/utils/file-content-reader.d.ts +2 -1
  188. package/dist/server/utils/file-helpers.d.ts +0 -24
  189. package/dist/server/utils/file-helpers.js +0 -81
  190. package/dist/server/utils/gitignore.d.ts +9 -0
  191. package/dist/server/utils/gitignore.js +47 -0
  192. package/dist/server/utils/process-logger.d.ts +0 -13
  193. package/dist/server/utils/process-logger.js +1 -78
  194. package/dist/shared/transport/events/index.d.ts +6 -0
  195. package/dist/shared/transport/events/index.js +3 -0
  196. package/dist/shared/transport/events/init-events.d.ts +8 -0
  197. package/dist/shared/transport/events/init-events.js +1 -0
  198. package/dist/shared/transport/events/push-events.d.ts +6 -0
  199. package/dist/shared/transport/events/review-events.d.ts +41 -0
  200. package/dist/shared/transport/events/review-events.js +5 -0
  201. package/dist/shared/transport/events/vc-events.d.ts +257 -0
  202. package/dist/shared/transport/events/vc-events.js +67 -0
  203. package/dist/shared/transport/types/dto.d.ts +6 -1
  204. package/dist/tui/app/pages/init-project-page.d.ts +9 -0
  205. package/dist/tui/app/pages/init-project-page.js +54 -0
  206. package/dist/tui/app/pages/protected-routes.js +14 -6
  207. package/dist/tui/components/index.d.ts +0 -2
  208. package/dist/tui/components/index.js +0 -1
  209. package/dist/tui/features/activity/hooks/use-activity-logs.js +7 -1
  210. package/dist/tui/features/commands/definitions/index.js +3 -0
  211. package/dist/tui/features/commands/definitions/space-list.js +9 -18
  212. package/dist/tui/features/commands/definitions/space-switch.js +10 -6
  213. package/dist/tui/features/commands/definitions/vc-add.d.ts +2 -0
  214. package/dist/tui/features/commands/definitions/vc-add.js +15 -0
  215. package/dist/tui/features/commands/definitions/vc-branch.d.ts +2 -0
  216. package/dist/tui/features/commands/definitions/vc-branch.js +33 -0
  217. package/dist/tui/features/commands/definitions/vc-checkout.d.ts +2 -0
  218. package/dist/tui/features/commands/definitions/vc-checkout.js +32 -0
  219. package/dist/tui/features/commands/definitions/vc-clone.d.ts +2 -0
  220. package/dist/tui/features/commands/definitions/vc-clone.js +18 -0
  221. package/dist/tui/features/commands/definitions/vc-commit.d.ts +2 -0
  222. package/dist/tui/features/commands/definitions/vc-commit.js +32 -0
  223. package/dist/tui/features/commands/definitions/vc-config.d.ts +2 -0
  224. package/dist/tui/features/commands/definitions/vc-config.js +40 -0
  225. package/dist/tui/features/commands/definitions/vc-fetch.d.ts +2 -0
  226. package/dist/tui/features/commands/definitions/vc-fetch.js +37 -0
  227. package/dist/tui/features/commands/definitions/vc-init.d.ts +2 -0
  228. package/dist/tui/features/commands/definitions/vc-init.js +11 -0
  229. package/dist/tui/features/commands/definitions/vc-log.d.ts +2 -0
  230. package/dist/tui/features/commands/definitions/vc-log.js +25 -0
  231. package/dist/tui/features/commands/definitions/vc-merge.d.ts +2 -0
  232. package/dist/tui/features/commands/definitions/vc-merge.js +48 -0
  233. package/dist/tui/features/commands/definitions/vc-pull.d.ts +2 -0
  234. package/dist/tui/features/commands/definitions/vc-pull.js +42 -0
  235. package/dist/tui/features/commands/definitions/vc-push.d.ts +2 -0
  236. package/dist/tui/features/commands/definitions/vc-push.js +38 -0
  237. package/dist/tui/features/commands/definitions/vc-remote.d.ts +2 -0
  238. package/dist/tui/features/commands/definitions/vc-remote.js +57 -0
  239. package/dist/tui/features/commands/definitions/vc-reset.d.ts +2 -0
  240. package/dist/tui/features/commands/definitions/vc-reset.js +35 -0
  241. package/dist/tui/features/commands/definitions/vc-status.d.ts +2 -0
  242. package/dist/tui/features/commands/definitions/vc-status.js +11 -0
  243. package/dist/tui/features/commands/definitions/vc.d.ts +2 -0
  244. package/dist/tui/features/commands/definitions/vc.js +36 -0
  245. package/dist/tui/features/commands/hooks/use-slash-command-processor.js +5 -5
  246. package/dist/tui/features/log/api/execute-log.d.ts +8 -0
  247. package/dist/tui/features/log/api/execute-log.js +13 -0
  248. package/dist/tui/features/log/components/log-flow.d.ts +14 -0
  249. package/dist/tui/features/log/components/log-flow.js +29 -0
  250. package/dist/tui/features/log/utils/format-log.d.ts +3 -0
  251. package/dist/tui/features/log/utils/format-log.js +42 -0
  252. package/dist/tui/features/onboarding/hooks/use-app-view-mode.d.ts +9 -5
  253. package/dist/tui/features/onboarding/hooks/use-app-view-mode.js +12 -5
  254. package/dist/tui/features/push/components/push-flow.js +9 -2
  255. package/dist/tui/features/reset/components/reset-flow.js +2 -1
  256. package/dist/tui/features/status/components/status-view.js +2 -1
  257. package/dist/tui/features/status/utils/format-status.js +9 -0
  258. package/dist/tui/features/tasks/hooks/use-task-subscriptions.js +11 -0
  259. package/dist/tui/features/tasks/stores/tasks-store.d.ts +10 -0
  260. package/dist/tui/features/tasks/stores/tasks-store.js +16 -0
  261. package/dist/tui/features/vc/add/api/execute-vc-add.d.ts +8 -0
  262. package/dist/tui/features/vc/add/api/execute-vc-add.js +13 -0
  263. package/dist/tui/features/vc/add/components/vc-add-flow.d.ts +7 -0
  264. package/dist/tui/features/vc/add/components/vc-add-flow.js +35 -0
  265. package/dist/tui/features/vc/branch/api/execute-vc-branch.d.ts +8 -0
  266. package/dist/tui/features/vc/branch/api/execute-vc-branch.js +13 -0
  267. package/dist/tui/features/vc/branch/components/vc-branch-flow.d.ts +8 -0
  268. package/dist/tui/features/vc/branch/components/vc-branch-flow.js +53 -0
  269. package/dist/tui/features/vc/branch/utils/format-branch.d.ts +4 -0
  270. package/dist/tui/features/vc/branch/utils/format-branch.js +12 -0
  271. package/dist/tui/features/vc/checkout/api/execute-vc-checkout.d.ts +8 -0
  272. package/dist/tui/features/vc/checkout/api/execute-vc-checkout.js +13 -0
  273. package/dist/tui/features/vc/checkout/components/vc-checkout-flow.d.ts +8 -0
  274. package/dist/tui/features/vc/checkout/components/vc-checkout-flow.js +33 -0
  275. package/dist/tui/features/vc/clone/api/execute-vc-clone.d.ts +8 -0
  276. package/dist/tui/features/vc/clone/api/execute-vc-clone.js +13 -0
  277. package/dist/tui/features/vc/clone/components/vc-clone-flow.d.ts +7 -0
  278. package/dist/tui/features/vc/clone/components/vc-clone-flow.js +79 -0
  279. package/dist/tui/features/vc/commit/api/execute-vc-commit.d.ts +8 -0
  280. package/dist/tui/features/vc/commit/api/execute-vc-commit.js +13 -0
  281. package/dist/tui/features/vc/commit/components/vc-commit-flow.d.ts +7 -0
  282. package/dist/tui/features/vc/commit/components/vc-commit-flow.js +29 -0
  283. package/dist/tui/features/vc/config/api/execute-vc-config.d.ts +8 -0
  284. package/dist/tui/features/vc/config/api/execute-vc-config.js +13 -0
  285. package/dist/tui/features/vc/config/components/vc-config-flow.d.ts +9 -0
  286. package/dist/tui/features/vc/config/components/vc-config-flow.js +30 -0
  287. package/dist/tui/features/vc/fetch/api/execute-vc-fetch.d.ts +8 -0
  288. package/dist/tui/features/vc/fetch/api/execute-vc-fetch.js +13 -0
  289. package/dist/tui/features/vc/fetch/components/vc-fetch-flow.d.ts +8 -0
  290. package/dist/tui/features/vc/fetch/components/vc-fetch-flow.js +75 -0
  291. package/dist/tui/features/vc/init/api/execute-vc-init.d.ts +8 -0
  292. package/dist/tui/features/vc/init/api/execute-vc-init.js +13 -0
  293. package/dist/tui/features/vc/init/components/vc-init-flow.d.ts +10 -0
  294. package/dist/tui/features/vc/init/components/vc-init-flow.js +37 -0
  295. package/dist/tui/features/vc/merge/api/execute-vc-merge.d.ts +8 -0
  296. package/dist/tui/features/vc/merge/api/execute-vc-merge.js +13 -0
  297. package/dist/tui/features/vc/merge/components/vc-merge-flow.d.ts +11 -0
  298. package/dist/tui/features/vc/merge/components/vc-merge-flow.js +72 -0
  299. package/dist/tui/features/vc/pull/api/execute-vc-pull.d.ts +8 -0
  300. package/dist/tui/features/vc/pull/api/execute-vc-pull.js +13 -0
  301. package/dist/tui/features/vc/pull/components/vc-pull-flow.d.ts +9 -0
  302. package/dist/tui/features/vc/pull/components/vc-pull-flow.js +83 -0
  303. package/dist/tui/features/vc/push/api/execute-vc-push.d.ts +8 -0
  304. package/dist/tui/features/vc/push/api/execute-vc-push.js +13 -0
  305. package/dist/tui/features/vc/push/components/vc-push-flow.d.ts +8 -0
  306. package/dist/tui/features/vc/push/components/vc-push-flow.js +83 -0
  307. package/dist/tui/features/vc/remote/api/execute-vc-remote.d.ts +8 -0
  308. package/dist/tui/features/vc/remote/api/execute-vc-remote.js +13 -0
  309. package/dist/tui/features/vc/remote/components/vc-remote-flow.d.ts +9 -0
  310. package/dist/tui/features/vc/remote/components/vc-remote-flow.js +42 -0
  311. package/dist/tui/features/vc/reset/api/execute-vc-reset.d.ts +8 -0
  312. package/dist/tui/features/vc/reset/api/execute-vc-reset.js +13 -0
  313. package/dist/tui/features/vc/reset/components/vc-reset-flow.d.ts +10 -0
  314. package/dist/tui/features/vc/reset/components/vc-reset-flow.js +63 -0
  315. package/dist/tui/features/vc/status/api/execute-vc-status.d.ts +8 -0
  316. package/dist/tui/features/vc/status/api/execute-vc-status.js +13 -0
  317. package/dist/tui/features/vc/status/components/vc-status-flow.d.ts +10 -0
  318. package/dist/tui/features/vc/status/components/vc-status-flow.js +133 -0
  319. package/dist/tui/lib/environment.d.ts +8 -0
  320. package/dist/tui/lib/environment.js +8 -0
  321. package/dist/tui/utils/error-messages.d.ts +5 -1
  322. package/dist/tui/utils/error-messages.js +32 -3
  323. package/node_modules/@campfirein/brv-transport-client/LICENSE +95 -0
  324. package/node_modules/@campfirein/brv-transport-client/README.md +3 -4
  325. package/node_modules/@campfirein/brv-transport-client/package.json +2 -2
  326. package/oclif.manifest.json +985 -65
  327. package/package.json +13 -5
  328. package/dist/oclif/hooks/prerun/validate-brv-config-version.d.ts +0 -33
  329. package/dist/oclif/hooks/prerun/validate-brv-config-version.js +0 -86
  330. package/dist/server/core/domain/entities/bullet.d.ts +0 -51
  331. package/dist/server/core/domain/entities/bullet.js +0 -94
  332. package/dist/server/core/domain/entities/memory.d.ts +0 -55
  333. package/dist/server/core/domain/entities/memory.js +0 -90
  334. package/dist/server/core/domain/entities/playbook.d.ts +0 -80
  335. package/dist/server/core/domain/entities/playbook.js +0 -214
  336. package/dist/server/core/domain/entities/presigned-url.d.ts +0 -9
  337. package/dist/server/core/domain/entities/presigned-url.js +0 -18
  338. package/dist/server/core/domain/entities/presigned-urls-response.d.ts +0 -10
  339. package/dist/server/core/domain/entities/presigned-urls-response.js +0 -18
  340. package/dist/server/core/domain/entities/retrieve-result.d.ts +0 -35
  341. package/dist/server/core/domain/entities/retrieve-result.js +0 -35
  342. package/dist/server/core/domain/errors/headless-prompt-error.d.ts +0 -11
  343. package/dist/server/core/domain/errors/headless-prompt-error.js +0 -18
  344. package/dist/server/core/interfaces/services/i-legacy-rule-detector.d.ts +0 -56
  345. package/dist/server/core/interfaces/services/i-memory-retrieval-service.d.ts +0 -39
  346. package/dist/server/core/interfaces/services/i-memory-storage-service.d.ts +0 -53
  347. package/dist/server/core/interfaces/services/i-terminal.d.ts +0 -146
  348. package/dist/server/core/interfaces/services/i-terminal.js +0 -1
  349. package/dist/server/core/interfaces/services/i-workspace-detector-service.d.ts +0 -8
  350. package/dist/server/core/interfaces/services/i-workspace-detector-service.js +0 -1
  351. package/dist/server/core/interfaces/storage/i-onboarding-preference-store.d.ts +0 -20
  352. package/dist/server/core/interfaces/storage/i-onboarding-preference-store.js +0 -1
  353. package/dist/server/infra/connectors/rules/legacy-rule-detector.d.ts +0 -21
  354. package/dist/server/infra/connectors/rules/legacy-rule-detector.js +0 -106
  355. package/dist/server/infra/memory/http-memory-retrieval-service.d.ts +0 -18
  356. package/dist/server/infra/memory/http-memory-retrieval-service.js +0 -64
  357. package/dist/server/infra/memory/http-memory-storage-service.d.ts +0 -18
  358. package/dist/server/infra/memory/http-memory-storage-service.js +0 -72
  359. package/dist/server/infra/memory/memory-to-playbook-mapper.d.ts +0 -33
  360. package/dist/server/infra/memory/memory-to-playbook-mapper.js +0 -51
  361. package/dist/server/infra/storage/file-onboarding-preference-store.d.ts +0 -10
  362. package/dist/server/infra/storage/file-onboarding-preference-store.js +0 -45
  363. package/dist/server/infra/terminal/headless-terminal.d.ts +0 -91
  364. package/dist/server/infra/terminal/headless-terminal.js +0 -211
  365. package/dist/server/infra/workspace/workspace-detector-service.d.ts +0 -57
  366. package/dist/server/infra/workspace/workspace-detector-service.js +0 -165
  367. package/dist/server/utils/crash-log.d.ts +0 -14
  368. package/dist/server/utils/crash-log.js +0 -19
  369. package/dist/server/utils/emoji-helpers.d.ts +0 -38
  370. package/dist/server/utils/emoji-helpers.js +0 -42
  371. package/dist/server/utils/error-handler.d.ts +0 -51
  372. package/dist/server/utils/error-handler.js +0 -169
  373. package/dist/server/utils/oclif-error-helpers.d.ts +0 -40
  374. package/dist/server/utils/oclif-error-helpers.js +0 -46
  375. package/dist/server/utils/tool-display-formatter.d.ts +0 -53
  376. package/dist/server/utils/tool-display-formatter.js +0 -257
  377. package/dist/tui/components/init.d.ts +0 -33
  378. package/dist/tui/components/init.js +0 -234
  379. package/dist/tui/features/space/api/get-spaces.d.ts +0 -16
  380. package/dist/tui/features/space/api/get-spaces.js +0 -17
  381. package/dist/tui/features/space/api/switch-space.d.ts +0 -11
  382. package/dist/tui/features/space/api/switch-space.js +0 -24
  383. package/dist/tui/features/space/components/space-list-view.d.ts +0 -12
  384. package/dist/tui/features/space/components/space-list-view.js +0 -56
  385. package/dist/tui/features/space/components/space-switch-flow.d.ts +0 -13
  386. package/dist/tui/features/space/components/space-switch-flow.js +0 -97
  387. /package/dist/server/core/interfaces/services/{i-legacy-rule-detector.js → i-git-service.js} +0 -0
  388. /package/dist/server/core/interfaces/{services/i-memory-retrieval-service.js → storage/i-review-backup-store.js} +0 -0
  389. /package/dist/server/core/interfaces/{services/i-memory-storage-service.js → vc/i-vc-git-config-store.js} +0 -0
@@ -1,24 +1,27 @@
1
+ import { input, password, select, Separator } from '@inquirer/prompts';
1
2
  import { Args, Command, Flags } from '@oclif/core';
3
+ import chalk from 'chalk';
2
4
  import { OAUTH_CALLBACK_TIMEOUT_MS } from '../../../shared/constants/oauth.js';
3
- import { ModelEvents } from '../../../shared/transport/events/model-events.js';
5
+ import { ModelEvents, } from '../../../shared/transport/events/model-events.js';
4
6
  import { ProviderEvents, } from '../../../shared/transport/events/provider-events.js';
5
7
  import { withDaemonRetry } from '../../lib/daemon-client.js';
6
8
  import { writeJsonResponse } from '../../lib/json-response.js';
9
+ import { createEscapeSignal, isEscBack, isPromptCancelled, validateUrl, wizardSelectTheme, } from '../../lib/prompt-utils.js';
10
+ import { createSpinner } from '../../lib/spinner.js';
7
11
  export default class ProviderConnect extends Command {
8
12
  static args = {
9
13
  provider: Args.string({
10
- description: 'Provider ID to connect (e.g., anthropic, openai, openrouter)',
11
- required: true,
14
+ description: 'Provider ID to connect (e.g., anthropic, openai, openrouter). Omit for interactive selection.',
15
+ required: false,
12
16
  }),
13
17
  };
14
18
  static description = 'Connect or switch to an LLM provider';
15
19
  static examples = [
20
+ '<%= config.bin %> providers connect',
16
21
  '<%= config.bin %> providers connect anthropic --api-key sk-xxx',
17
- '<%= config.bin %> providers connect openai --api-key sk-xxx --model gpt-4.1',
18
22
  '<%= config.bin %> providers connect openai --oauth',
19
23
  '<%= config.bin %> providers connect byterover',
20
- '<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1',
21
- '<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1 --api-key sk-xxx --model llama3',
24
+ '<%= config.bin %> providers connect openai-compatible --base-url http://localhost:11434/v1 --api-key sk-xxx',
22
25
  ];
23
26
  static flags = {
24
27
  'api-key': Flags.string({
@@ -64,15 +67,9 @@ export default class ProviderConnect extends Command {
64
67
  '\nExample: brv providers connect openai-compatible --base-url http://localhost:11434/v1');
65
68
  }
66
69
  if (baseUrl) {
67
- let parsed;
68
- try {
69
- parsed = new URL(baseUrl);
70
- }
71
- catch {
72
- throw new Error(`Invalid base URL format: "${baseUrl}". Must be a valid http:// or https:// URL.`);
73
- }
74
- if (!['http:', 'https:'].includes(parsed.protocol)) {
75
- throw new Error('URL must start with http:// or https://');
70
+ const validationResult = validateUrl(baseUrl);
71
+ if (typeof validationResult === 'string') {
72
+ throw new TypeError(validationResult);
76
73
  }
77
74
  }
78
75
  }
@@ -104,7 +101,6 @@ export default class ProviderConnect extends Command {
104
101
  }
105
102
  async connectProviderOAuth({ code, providerId }, options, onProgress) {
106
103
  return withDaemonRetry(async (client) => {
107
- // 1. Verify provider exists and supports OAuth
108
104
  const { providers } = await client.requestWithAck(ProviderEvents.LIST);
109
105
  const provider = providers.find((p) => p.id === providerId);
110
106
  if (!provider) {
@@ -113,13 +109,10 @@ export default class ProviderConnect extends Command {
113
109
  if (!provider.supportsOAuth) {
114
110
  throw new Error(`Provider "${providerId}" does not support OAuth. Use --api-key instead.`);
115
111
  }
116
- // --code is only valid for code-paste providers (e.g., Anthropic).
117
- // Browser-callback providers like OpenAI handle the code exchange automatically.
118
112
  if (code && provider.oauthCallbackMode !== 'code-paste') {
119
113
  throw new Error(`Provider "${providerId}" uses browser-based OAuth and does not accept --code.\n` +
120
114
  `Run: brv providers connect ${providerId} --oauth`);
121
115
  }
122
- // If --code is provided, submit it directly (code-paste providers)
123
116
  if (code) {
124
117
  const response = await client.requestWithAck(ProviderEvents.SUBMIT_OAUTH_CODE, { code, providerId });
125
118
  if (!response.success) {
@@ -127,16 +120,13 @@ export default class ProviderConnect extends Command {
127
120
  }
128
121
  return { providerName: provider.name, showInstructions: false };
129
122
  }
130
- // 2. Start OAuth flow — returns immediately with auth URL
131
123
  const startResponse = await client.requestWithAck(ProviderEvents.START_OAUTH, {
132
124
  providerId,
133
125
  });
134
126
  if (!startResponse.success) {
135
127
  throw new Error(startResponse.error ?? 'Failed to start OAuth flow');
136
128
  }
137
- // Always print auth URL (user's machine may not support browser launch)
138
129
  onProgress?.(`\nOpen this URL to authenticate:\n ${startResponse.authUrl}\n`);
139
- // 3. Handle based on callback mode
140
130
  if (startResponse.callbackMode === 'auto') {
141
131
  onProgress?.('Waiting for authentication in browser...');
142
132
  const awaitResponse = await client.requestWithAck(ProviderEvents.AWAIT_OAUTH_CALLBACK, { providerId }, { timeout: OAUTH_CALLBACK_TIMEOUT_MS });
@@ -145,20 +135,230 @@ export default class ProviderConnect extends Command {
145
135
  }
146
136
  return { providerName: provider.name, showInstructions: false };
147
137
  }
148
- // code-paste mode: print instructions and exit
149
138
  onProgress?.('Copy the authorization code from the browser and run:');
150
139
  onProgress?.(` brv providers connect ${providerId} --oauth --code <code>`);
151
140
  return { providerName: provider.name, showInstructions: true };
152
141
  }, options);
153
142
  }
143
+ async disconnectProvider(providerId, options) {
144
+ await withDaemonRetry(async (client) => {
145
+ await client.requestWithAck(ProviderEvents.DISCONNECT, { providerId });
146
+ }, options);
147
+ }
148
+ async fetchModels(providerId, options) {
149
+ return withDaemonRetry(async (client) => client.requestWithAck(ModelEvents.LIST, { providerId }), options);
150
+ }
151
+ async fetchProviders(options) {
152
+ const { providers } = await withDaemonRetry(async (client) => client.requestWithAck(ProviderEvents.LIST), options);
153
+ return providers;
154
+ }
155
+ // All prompt methods emit a blank line before rendering for visual spacing between wizard steps.
156
+ async promptForApiKey(providerName, apiKeyUrl, signal) {
157
+ this.log();
158
+ const hint = apiKeyUrl ? ` (get one at ${apiKeyUrl}):` : ':';
159
+ return password({
160
+ mask: true,
161
+ message: `Enter API key for ${providerName}${chalk.dim(hint)}`,
162
+ }, { signal });
163
+ }
164
+ async promptForAuthMethod(provider, signal) {
165
+ this.log();
166
+ const oauthLabel = provider.oauthLabel ?? 'OAuth (browser-based)';
167
+ return select({
168
+ choices: [
169
+ {
170
+ name: `API Key${provider.apiKeyUrl ? ` — get one at ${provider.apiKeyUrl}` : ''}`,
171
+ value: 'api-key',
172
+ },
173
+ { name: oauthLabel, value: 'oauth' },
174
+ ],
175
+ message: `How do you want to authenticate with ${provider.name}?`,
176
+ theme: wizardSelectTheme,
177
+ }, { signal });
178
+ }
179
+ async promptForBaseUrl(signal) {
180
+ this.log();
181
+ return input({
182
+ message: `Enter base URL ${chalk.dim('(e.g. http://localhost:11434/v1):')}`,
183
+ required: true,
184
+ validate: validateUrl,
185
+ }, { signal });
186
+ }
187
+ async promptForConnectedAction(provider, signal) {
188
+ this.log();
189
+ const choices = [];
190
+ if (!provider.isCurrent) {
191
+ choices.push({ name: 'Set as active', value: 'activate' });
192
+ }
193
+ if (provider.isConnected) {
194
+ choices.push({ name: 'Disconnect', value: 'disconnect' });
195
+ }
196
+ if (provider.requiresApiKey || provider.supportsOAuth) {
197
+ choices.push({ name: `Reconfigure ${provider.authMethod === 'oauth' ? 'OAuth' : 'API key'}`, value: 'reconfigure' });
198
+ }
199
+ return select({
200
+ choices,
201
+ message: `${provider.name} is already connected. What would you like to do?`,
202
+ theme: wizardSelectTheme,
203
+ }, { signal });
204
+ }
205
+ async promptForModel(models, signal) {
206
+ this.log();
207
+ if (models.length === 0) {
208
+ this.log(chalk.dim('No models available. Check your API key or provider configuration.'));
209
+ // Trigger back-navigation to auth step by throwing cancel
210
+ const error = new Error('No models available');
211
+ error.name = 'AbortPromptError';
212
+ throw error;
213
+ }
214
+ return select({
215
+ choices: [{ name: 'Skip (use default)', value: '' }, ...models.map((m) => ({ name: m.name, value: m.id }))],
216
+ loop: false,
217
+ message: 'Select a model',
218
+ theme: wizardSelectTheme,
219
+ }, { signal }).then((v) => v || undefined);
220
+ }
221
+ async promptForOptionalApiKey(providerName, signal) {
222
+ this.log();
223
+ const value = await input({ message: `Enter API key for ${providerName} ${chalk.dim('(optional, press Enter to skip):')}` }, { signal });
224
+ return value.trim() || undefined;
225
+ }
226
+ async promptForProvider(providers, signal) {
227
+ this.log();
228
+ const nameMaxChars = Math.max(...providers.map((p) => p.name.length));
229
+ const popular = providers.filter((p) => p.category === 'popular');
230
+ const other = providers.filter((p) => p.category === 'other');
231
+ const formatChoice = (p) => ({
232
+ name: `${p.name.padEnd(nameMaxChars + 3)} ${p.description}`,
233
+ value: p.id,
234
+ });
235
+ return select({
236
+ choices: [
237
+ new Separator('---------- Popular ----------'),
238
+ ...popular.map((p) => formatChoice(p)),
239
+ new Separator('\n---------- Others ----------'),
240
+ ...other.map((p) => formatChoice(p)),
241
+ ],
242
+ loop: false,
243
+ message: 'Select a provider',
244
+ theme: wizardSelectTheme,
245
+ }, { signal });
246
+ }
154
247
  async run() {
155
248
  const { args, flags } = await this.parse(ProviderConnect);
156
249
  const providerId = args.provider;
157
- const apiKey = flags['api-key'];
158
- const baseUrl = flags['base-url'];
159
- const { code, model, oauth } = flags;
160
250
  const format = flags.format === 'json' ? 'json' : 'text';
161
- // Validate flag combinations
251
+ // Interactive mode: no provider arg
252
+ if (!providerId) {
253
+ if (format === 'json') {
254
+ writeJsonResponse({
255
+ command: 'providers connect',
256
+ data: { error: 'Provider argument is required for JSON output' },
257
+ success: false,
258
+ });
259
+ return;
260
+ }
261
+ try {
262
+ await this.runInteractive();
263
+ }
264
+ catch (error) {
265
+ this.log(error instanceof Error
266
+ ? error.message
267
+ : 'An unexpected error occurred while connecting the provider. Please try again.');
268
+ }
269
+ return;
270
+ }
271
+ // Non-interactive mode: provider arg provided
272
+ await this.runNonInteractive(providerId, {
273
+ apiKey: flags['api-key'],
274
+ baseUrl: flags['base-url'],
275
+ code: flags.code,
276
+ model: flags.model,
277
+ oauth: flags.oauth,
278
+ }, format);
279
+ }
280
+ /**
281
+ * Interactive flow with cancel-to-go-back navigation.
282
+ * Step 1 (provider) ← Step 2 (auth) ← Step 3 (model)
283
+ */
284
+ async runInteractive() {
285
+ const esc = createEscapeSignal();
286
+ const STEPS = ['provider', 'auth', 'model'];
287
+ let stepIndex = 0;
288
+ let providers = await this.fetchProviders();
289
+ let providerId;
290
+ let provider;
291
+ try {
292
+ /* eslint-disable no-await-in-loop -- intentional sequential interactive wizard */
293
+ while (stepIndex < STEPS.length) {
294
+ const currentStep = STEPS[stepIndex];
295
+ try {
296
+ switch (currentStep) {
297
+ case 'auth': {
298
+ // If providerId or provider is not set, go back to provider step
299
+ // eslint-disable-next-line max-depth
300
+ if (!providerId || !provider) {
301
+ stepIndex--;
302
+ break;
303
+ }
304
+ const done = await this.runAuthStep(providerId, provider, esc.signal);
305
+ // eslint-disable-next-line max-depth
306
+ if (done) {
307
+ stepIndex = STEPS.length; // skip remaining steps
308
+ }
309
+ break;
310
+ }
311
+ case 'model': {
312
+ // If providerId is not set, go back to provider step
313
+ // eslint-disable-next-line max-depth
314
+ if (!providerId) {
315
+ stepIndex = 0;
316
+ break;
317
+ }
318
+ // ByteRover does not need model selection
319
+ // eslint-disable-next-line max-depth
320
+ if (providerId === 'byterover')
321
+ break;
322
+ await this.runModelStep(providerId, esc.signal);
323
+ break;
324
+ }
325
+ case 'provider': {
326
+ providerId = await this.promptForProvider(providers, esc.signal);
327
+ provider = providers.find((p) => p.id === providerId);
328
+ break;
329
+ }
330
+ }
331
+ stepIndex++;
332
+ }
333
+ catch (error) {
334
+ if (isEscBack(error)) {
335
+ // Esc → go back one step
336
+ if (stepIndex === 0)
337
+ return;
338
+ esc.reset();
339
+ stepIndex--;
340
+ // Re-fetch providers on back-navigation so isConnected states are fresh
341
+ if (STEPS[stepIndex] === 'provider') {
342
+ providers = await this.fetchProviders();
343
+ }
344
+ }
345
+ else if (isPromptCancelled(error)) {
346
+ // Ctrl+C → exit wizard
347
+ return;
348
+ }
349
+ else {
350
+ throw error;
351
+ }
352
+ }
353
+ }
354
+ /* eslint-enable no-await-in-loop */
355
+ }
356
+ finally {
357
+ esc.cleanup();
358
+ }
359
+ }
360
+ async runNonInteractive(providerId, flags, format) {
361
+ const { apiKey, baseUrl, code, model, oauth } = flags;
162
362
  if (oauth && apiKey) {
163
363
  const msg = 'Cannot use --oauth and --api-key together';
164
364
  if (format === 'json') {
@@ -215,4 +415,84 @@ export default class ProviderConnect extends Command {
215
415
  }
216
416
  }
217
417
  }
418
+ /* eslint-disable no-await-in-loop -- intentional retry loop for interactive auth */
419
+ /** Returns true when wizard should end (skip model step), false to continue to model step. */
420
+ async runAuthStep(providerId, provider, signal) {
421
+ // Provider already connected — ask what to do
422
+ if (provider.isConnected) {
423
+ const action = await this.promptForConnectedAction(provider, signal);
424
+ if (action === 'activate') {
425
+ const spinner = createSpinner('Connecting...');
426
+ const result = await this.connectProvider({ providerId });
427
+ spinner.clear();
428
+ this.log(`Connected to ${result.providerName} (${result.providerId})`);
429
+ return false;
430
+ }
431
+ if (action === 'disconnect') {
432
+ const spinner = createSpinner('Disconnecting...');
433
+ await this.disconnectProvider(providerId);
434
+ spinner.clear();
435
+ this.log(`Disconnected from ${provider.name}`);
436
+ return true;
437
+ }
438
+ // reconfigure → fall through to auth flow below
439
+ }
440
+ // No API key required (e.g., ByteRover free) but not openai-compatible — connect directly
441
+ if (!provider.requiresApiKey && !provider.supportsOAuth && providerId !== 'openai-compatible') {
442
+ const spinner = createSpinner('Connecting...');
443
+ const result = await this.connectProvider({ providerId });
444
+ spinner.clear();
445
+ this.log(`Connected to ${result.providerName} (${result.providerId})`);
446
+ return false;
447
+ }
448
+ // Retry loop — on connection failure, show error and re-prompt credentials
449
+ while (true) {
450
+ // Choose auth method if provider supports both
451
+ let authMethod = 'api-key';
452
+ if (provider.supportsOAuth && provider.requiresApiKey) {
453
+ authMethod = await this.promptForAuthMethod(provider, signal);
454
+ }
455
+ else if (provider.supportsOAuth) {
456
+ authMethod = 'oauth';
457
+ }
458
+ try {
459
+ if (authMethod === 'oauth') {
460
+ const result = await this.connectProviderOAuth({ providerId }, undefined, (msg) => this.log(msg));
461
+ if (!result.showInstructions) {
462
+ this.log(`Connected to ${result.providerName} via OAuth`);
463
+ }
464
+ return false;
465
+ }
466
+ // API key flow
467
+ const isOpenAiCompatible = providerId === 'openai-compatible';
468
+ const baseUrl = isOpenAiCompatible ? await this.promptForBaseUrl(signal) : undefined;
469
+ const apiKey = isOpenAiCompatible
470
+ ? await this.promptForOptionalApiKey(provider.name, signal)
471
+ : await this.promptForApiKey(provider.name, provider.apiKeyUrl, signal);
472
+ const spinner = createSpinner('Connecting...');
473
+ const result = await this.connectProvider({ apiKey, baseUrl, providerId });
474
+ spinner.clear();
475
+ this.log(`Connected to ${result.providerName} (${result.providerId})`);
476
+ return false;
477
+ }
478
+ catch (error) {
479
+ // Prompt cancellation → propagate to state machine (go back to provider)
480
+ if (isPromptCancelled(error))
481
+ throw error;
482
+ // Connection error → show message and retry auth
483
+ this.log(error instanceof Error ? error.message : 'Connection failed. Please try again.');
484
+ }
485
+ }
486
+ }
487
+ /* eslint-enable no-await-in-loop */
488
+ async runModelStep(providerId, signal) {
489
+ const spinner = createSpinner('Fetching models...');
490
+ const modelList = await this.fetchModels(providerId);
491
+ spinner.clear();
492
+ const modelId = await this.promptForModel(modelList.models, signal);
493
+ if (!modelId)
494
+ return;
495
+ await withDaemonRetry(async (client) => client.requestWithAck(ModelEvents.SET_ACTIVE, { modelId, providerId }));
496
+ this.log(`Model set to: ${modelId}`);
497
+ }
218
498
  }
@@ -8,4 +8,5 @@ export default class Pull extends Command {
8
8
  };
9
9
  run(): Promise<void>;
10
10
  private executePull;
11
+ private logVcHint;
11
12
  }
@@ -38,6 +38,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
38
38
  }
39
39
  else {
40
40
  this.log(pullResult.summary);
41
+ this.logVcHint();
41
42
  }
42
43
  return;
43
44
  }
@@ -50,6 +51,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
50
51
  this.log(` Branch: ${branch}`);
51
52
  this.log(` Commit: ${result.commitSha.slice(0, 7)}`);
52
53
  this.log(` Added: ${result.added}, Edited: ${result.edited}, Deleted: ${result.deleted}`);
54
+ this.logVcHint();
53
55
  }
54
56
  }
55
57
  catch (error) {
@@ -59,6 +61,7 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
59
61
  }
60
62
  else {
61
63
  this.log(formatConnectionError(error));
64
+ this.logVcHint();
62
65
  }
63
66
  }
64
67
  }
@@ -72,4 +75,8 @@ Downloads the context tree from the ByteRover cloud to your local project.`;
72
75
  return { hasChanges: false, result };
73
76
  });
74
77
  }
78
+ logVcHint() {
79
+ this.log('\nTip: Version control is now available for your context tree.');
80
+ this.log('Learn more: https://docs.byterover.dev/git-semantic/overview');
81
+ }
75
82
  }
@@ -8,4 +8,5 @@ export default class Push extends Command {
8
8
  };
9
9
  run(): Promise<void>;
10
10
  private executePush;
11
+ private logVcHint;
11
12
  }
@@ -37,6 +37,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
37
37
  }
38
38
  else {
39
39
  this.log('Push cancelled.');
40
+ this.logVcHint();
40
41
  }
41
42
  return;
42
43
  }
@@ -46,6 +47,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
46
47
  }
47
48
  else {
48
49
  this.log('No context changes to push.');
50
+ this.logVcHint();
49
51
  }
50
52
  return;
51
53
  }
@@ -69,6 +71,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
69
71
  this.log(` Branch: ${branch}`);
70
72
  this.log(` Added: ${result.added}, Edited: ${result.edited}, Deleted: ${result.deleted}`);
71
73
  this.log(` View: ${result.url}`);
74
+ this.logVcHint();
72
75
  }
73
76
  }
74
77
  catch (error) {
@@ -78,6 +81,7 @@ Uploads your local context tree changes to the ByteRover cloud.`;
78
81
  }
79
82
  else {
80
83
  this.log(formatConnectionError(error));
84
+ this.logVcHint();
81
85
  }
82
86
  }
83
87
  }
@@ -91,4 +95,8 @@ Uploads your local context tree changes to the ByteRover cloud.`;
91
95
  return { noChanges: false, result };
92
96
  });
93
97
  }
98
+ logVcHint() {
99
+ this.log('\nTip: Version control is now available for your context tree.');
100
+ this.log('Learn more: https://docs.byterover.dev/git-semantic/overview');
101
+ }
94
102
  }
@@ -0,0 +1,17 @@
1
+ import type { ReviewDecideTaskResponse } from '../../../shared/transport/events/review-events.js';
2
+ import { ReviewDecisionCommand } from './base-review-decision.js';
3
+ type ReviewFile = ReviewDecideTaskResponse['files'][number];
4
+ export default class ReviewApprove extends ReviewDecisionCommand {
5
+ static args: {
6
+ taskId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static description: string;
9
+ static examples: string[];
10
+ static flags: {
11
+ file: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ protected readonly decision: "approved";
15
+ protected formatFileLine(file: ReviewFile): string;
16
+ }
17
+ export {};
@@ -0,0 +1,37 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { ReviewDecisionCommand } from './base-review-decision.js';
3
+ export default class ReviewApprove extends ReviewDecisionCommand {
4
+ static args = {
5
+ taskId: Args.string({
6
+ description: 'Task ID shown in the curate output (e.g. "brv review approve abc-123")',
7
+ required: true,
8
+ }),
9
+ };
10
+ static description = 'Approve pending review operations for a curate task';
11
+ static examples = [
12
+ '# Approve all pending changes from a curate task',
13
+ '<%= config.bin %> review approve abc-123',
14
+ '',
15
+ '# Approve specific files',
16
+ '<%= config.bin %> review approve abc-123 --file architecture/security/audit.md',
17
+ '<%= config.bin %> review approve abc-123 --file auth/jwt.md --file auth/oauth.md',
18
+ '',
19
+ '# Approve and get structured output (useful for coding agents)',
20
+ '<%= config.bin %> review approve abc-123 --format json',
21
+ ];
22
+ static flags = {
23
+ file: Flags.string({
24
+ description: 'Approve only the specified file path(s) (relative to context tree)',
25
+ multiple: true,
26
+ }),
27
+ format: Flags.string({
28
+ default: 'text',
29
+ description: 'Output format (text or json)',
30
+ options: ['text', 'json'],
31
+ }),
32
+ };
33
+ decision = 'approved';
34
+ formatFileLine(file) {
35
+ return `✓ Approved ${file.path}`;
36
+ }
37
+ }
@@ -0,0 +1,18 @@
1
+ import { Command } from '@oclif/core';
2
+ import { type ReviewDecideTaskResponse } from '../../../shared/transport/events/review-events.js';
3
+ import { type DaemonClientOptions } from '../../lib/daemon-client.js';
4
+ type ReviewFile = ReviewDecideTaskResponse['files'][number];
5
+ export declare abstract class ReviewDecisionCommand extends Command {
6
+ static args: {
7
+ taskId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ file: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ protected abstract readonly decision: 'approved' | 'rejected';
14
+ protected abstract formatFileLine(file: ReviewFile): string;
15
+ protected getDaemonClientOptions(): DaemonClientOptions;
16
+ run(): Promise<void>;
17
+ }
18
+ export {};
@@ -0,0 +1,71 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { ReviewEvents } from '../../../shared/transport/events/review-events.js';
3
+ import { formatConnectionError, withDaemonRetry } from '../../lib/daemon-client.js';
4
+ import { writeJsonResponse } from '../../lib/json-response.js';
5
+ export class ReviewDecisionCommand extends Command {
6
+ static args = {
7
+ taskId: Args.string({
8
+ required: true,
9
+ }),
10
+ };
11
+ static flags = {
12
+ file: Flags.string({
13
+ multiple: true,
14
+ }),
15
+ format: Flags.string({
16
+ default: 'text',
17
+ description: 'Output format (text or json)',
18
+ options: ['text', 'json'],
19
+ }),
20
+ };
21
+ getDaemonClientOptions() {
22
+ return {};
23
+ }
24
+ async run() {
25
+ const ctor = this.constructor;
26
+ const { args, flags } = await this.parse({ args: ctor.args, flags: ctor.flags });
27
+ const format = flags.format === 'json' ? 'json' : 'text';
28
+ try {
29
+ const response = await withDaemonRetry((client) => client.requestWithAck(ReviewEvents.DECIDE_TASK, {
30
+ decision: this.decision,
31
+ ...(flags.file?.length ? { filePaths: flags.file } : {}),
32
+ taskId: args.taskId,
33
+ }), this.getDaemonClientOptions());
34
+ if (format === 'json') {
35
+ writeJsonResponse({
36
+ command: 'review',
37
+ data: {
38
+ decision: this.decision,
39
+ files: response.files,
40
+ status: 'success',
41
+ taskId: args.taskId,
42
+ totalCount: response.totalCount,
43
+ },
44
+ success: true,
45
+ });
46
+ }
47
+ else {
48
+ if (response.totalCount === 0) {
49
+ this.log(`No pending operations found for task ${args.taskId}.`);
50
+ return;
51
+ }
52
+ for (const file of response.files) {
53
+ this.log(this.formatFileLine(file));
54
+ }
55
+ this.log(`\n${response.totalCount} operation${response.totalCount === 1 ? '' : 's'} ${this.decision}.`);
56
+ }
57
+ }
58
+ catch (error) {
59
+ if (format === 'json') {
60
+ writeJsonResponse({
61
+ command: 'review',
62
+ data: { error: error instanceof Error ? error.message : 'Review failed', status: 'error' },
63
+ success: false,
64
+ });
65
+ }
66
+ else {
67
+ this.log(formatConnectionError(error));
68
+ }
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ import { type DaemonClientOptions } from '../../lib/daemon-client.js';
3
+ export default class ReviewPending extends Command {
4
+ static description: string;
5
+ static examples: string[];
6
+ static flags: {
7
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ };
9
+ protected getDaemonClientOptions(): DaemonClientOptions;
10
+ run(): Promise<void>;
11
+ private printTask;
12
+ private printText;
13
+ }