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,523 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { getCurrentConfig } from '../../../config/environment.js';
3
+ import { PROJECT } from '../../../constants.js';
4
+ import { CipherAgent } from '../cipher-agent.js';
5
+ import { closeAgentStorage, getAgentStorage, getAgentStorageSync } from '../storage/agent-storage.js';
6
+ // Heartbeat interval for consumer liveness detection (10 seconds)
7
+ const HEARTBEAT_INTERVAL_MS = 1000;
8
+ // Consumer is considered stale after 5 seconds without heartbeat
9
+ const STALE_TIMEOUT_MS = 5000;
10
+ // Check for orphaned executions every N poll cycles (10 seconds with 1s poll interval)
11
+ const ORPHAN_CHECK_INTERVAL_CYCLES = 10;
12
+ /**
13
+ * Sleep for specified milliseconds
14
+ */
15
+ function sleep(ms) {
16
+ return new Promise((resolve) => {
17
+ setTimeout(resolve, ms);
18
+ });
19
+ }
20
+ /**
21
+ * Create result summary for display
22
+ */
23
+ function createResultSummary(result) {
24
+ if (typeof result !== 'string') {
25
+ return '';
26
+ }
27
+ const lines = result.split('\n').length;
28
+ const chars = result.length;
29
+ return `${lines} lines, ${chars} chars`;
30
+ }
31
+ /**
32
+ * Calculate lines and chars count from result
33
+ */
34
+ function calculateMetrics(result) {
35
+ if (typeof result !== 'string' || result.length === 0) {
36
+ return undefined;
37
+ }
38
+ return {
39
+ charsCount: result.length,
40
+ linesCount: result.split('\n').length,
41
+ };
42
+ }
43
+ /**
44
+ * ExecutionConsumer - Polls queue and executes jobs in parallel
45
+ *
46
+ * Features:
47
+ * - DB-based lock with heartbeat (detects dead consumers)
48
+ * - Poll loop every 1 second
49
+ * - Parallel processing with configurable concurrency (default 5)
50
+ * - Process curate executions
51
+ * - Track tool calls to database
52
+ * - Cleanup old executions periodically
53
+ */
54
+ export class ExecutionConsumer {
55
+ activeJobs = new Set(); // Track running execution IDs
56
+ authToken;
57
+ brvConfig;
58
+ consumerId; // Unique ID for this consumer instance
59
+ heartbeatInterval;
60
+ maxConcurrency;
61
+ pollInterval;
62
+ running = false;
63
+ constructor(options) {
64
+ this.brvConfig = options?.brvConfig;
65
+ this.authToken = options?.authToken;
66
+ this.maxConcurrency = options?.maxConcurrency ?? 5; // Default 5 concurrent jobs
67
+ this.pollInterval = options?.pollInterval ?? 1000; // 1 second default
68
+ this.consumerId = randomUUID(); // Generate unique consumer ID
69
+ }
70
+ /**
71
+ * Get the unique consumer ID for this instance
72
+ */
73
+ getConsumerId() {
74
+ return this.consumerId;
75
+ }
76
+ /**
77
+ * Check if consumer is running
78
+ */
79
+ isRunning() {
80
+ return this.running;
81
+ }
82
+ /**
83
+ * Set auth token (can be set after construction)
84
+ */
85
+ setAuthToken(token) {
86
+ this.authToken = token;
87
+ }
88
+ /**
89
+ * Start the consumer
90
+ * @returns true if started successfully, false if another consumer is running
91
+ */
92
+ async start() {
93
+ // Initialize storage (auto-detects .brv/blobs from cwd)
94
+ const storage = await getAgentStorage();
95
+ // Cleanup stale consumers and orphan their executions
96
+ const orphaned = storage.cleanupStaleConsumers(STALE_TIMEOUT_MS);
97
+ if (orphaned > 0) {
98
+ console.log(`[Consumer] Cleaned up ${orphaned} orphaned executions from dead consumers`);
99
+ }
100
+ // Try acquire DB-based lock
101
+ if (!storage.acquireConsumerLock(this.consumerId)) {
102
+ console.log('[Consumer] Failed to acquire consumer lock');
103
+ return false;
104
+ }
105
+ // Register cleanup handlers
106
+ // eslint-disable-next-line unicorn/consistent-function-scoping
107
+ const cleanup = () => {
108
+ this.stop();
109
+ closeAgentStorage();
110
+ };
111
+ // Use 'once' to prevent multiple handler calls
112
+ // 'exit' is always fired, so just cleanup (no need for process.exit)
113
+ process.once('exit', cleanup);
114
+ process.once('SIGTERM', () => {
115
+ cleanup();
116
+ // eslint-disable-next-line n/no-process-exit
117
+ process.exit(0);
118
+ });
119
+ process.once('SIGINT', () => {
120
+ cleanup();
121
+ // eslint-disable-next-line n/no-process-exit
122
+ process.exit(0);
123
+ });
124
+ this.running = true;
125
+ // Start heartbeat to keep lock alive
126
+ this.heartbeatInterval = setInterval(() => {
127
+ try {
128
+ // Note: DB reconnect is handled in poll() loop
129
+ // Heartbeat just updates if lock exists, poll() handles reconnection
130
+ const currentStorage = getAgentStorageSync();
131
+ currentStorage.updateConsumerHeartbeat(this.consumerId);
132
+ }
133
+ catch {
134
+ // Ignore heartbeat errors - poll() will handle reconnection
135
+ // This prevents noisy errors when DB is being replaced
136
+ }
137
+ }, HEARTBEAT_INTERVAL_MS);
138
+ // Log initial queue status
139
+ // const queued = storage.getQueuedExecutions()
140
+ // const running = storage.getRunningExecutions()
141
+ // console.log(
142
+ // `[Consumer] Started (${this.consumerId.slice(0, 8)}). Concurrency: ${this.maxConcurrency}, Queue: ${
143
+ // queued.length
144
+ // } pending, ${running.length} running`,
145
+ // )
146
+ // Start poll loop (fire and forget)
147
+ this.poll().catch((error) => {
148
+ console.error('[Consumer] Poll error:', error);
149
+ this.stop();
150
+ });
151
+ return true;
152
+ }
153
+ /**
154
+ * Stop the consumer
155
+ * Idempotent - safe to call multiple times (only runs cleanup once)
156
+ */
157
+ stop() {
158
+ // Guard: Only run cleanup once
159
+ if (!this.running && !this.heartbeatInterval) {
160
+ return; // Already stopped
161
+ }
162
+ this.running = false;
163
+ // Stop heartbeat
164
+ if (this.heartbeatInterval) {
165
+ clearInterval(this.heartbeatInterval);
166
+ this.heartbeatInterval = undefined;
167
+ }
168
+ // Release DB lock
169
+ try {
170
+ const storage = getAgentStorageSync();
171
+ storage.releaseConsumerLock(this.consumerId);
172
+ }
173
+ catch {
174
+ // Ignore errors during shutdown
175
+ }
176
+ // console.log(`[Consumer] Stopped (${this.consumerId.slice(0, 8)})`)
177
+ }
178
+ /**
179
+ * Execute a curate job
180
+ */
181
+ async executeCurate(execution) {
182
+ const storage = getAgentStorageSync();
183
+ // Parse input
184
+ let input;
185
+ try {
186
+ input = JSON.parse(execution.input);
187
+ }
188
+ catch {
189
+ throw new Error('Invalid curate input: failed to parse JSON');
190
+ }
191
+ if (!input.content) {
192
+ throw new Error('Invalid curate input: missing content');
193
+ }
194
+ // Check auth token
195
+ if (!this.authToken) {
196
+ throw new Error('No auth token available. Consumer needs authentication.');
197
+ }
198
+ // Create LLM config
199
+ const model = input.flags?.model ?? (input.flags?.apiKey ? 'google/gemini-2.5-pro' : 'gemini-2.5-pro');
200
+ const envConfig = getCurrentConfig();
201
+ const llmConfig = {
202
+ accessToken: this.authToken.accessToken,
203
+ apiBaseUrl: envConfig.llmApiBaseUrl,
204
+ fileSystemConfig: { workingDirectory: process.cwd() },
205
+ maxIterations: 10,
206
+ maxTokens: 8192,
207
+ model,
208
+ openRouterApiKey: input.flags?.apiKey,
209
+ projectId: PROJECT,
210
+ sessionKey: this.authToken.sessionKey,
211
+ teamId: this.brvConfig?.teamId ?? '',
212
+ temperature: 0.7,
213
+ verbose: input.flags?.verbose ?? false,
214
+ };
215
+ // Create and start CipherAgent
216
+ const agent = new CipherAgent(llmConfig, this.brvConfig);
217
+ await agent.start();
218
+ try {
219
+ const sessionId = randomUUID();
220
+ // Setup event listeners for tool call tracking
221
+ this.setupToolCallTracking(agent, execution.id);
222
+ // Execute with autonomous mode
223
+ const prompt = `Add the following context to the context tree:\n\n${input.content}`;
224
+ const response = await agent.execute(prompt, sessionId, {
225
+ executionContext: {
226
+ commandType: 'curate',
227
+ fileReferenceInstructions: input.fileReferenceInstructions,
228
+ },
229
+ mode: 'autonomous',
230
+ });
231
+ // Mark completed
232
+ storage.updateExecutionStatus(execution.id, 'completed', response);
233
+ console.log(`[Consumer] Execution ${execution.id} completed`);
234
+ }
235
+ finally {
236
+ // Agent cleanup (if needed in future)
237
+ }
238
+ }
239
+ /**
240
+ * Log execution start (extracted to reduce nesting depth)
241
+ */
242
+ logExecutionStart(execution) {
243
+ try {
244
+ const input = JSON.parse(execution.input);
245
+ const content = input.content ?? '';
246
+ const preview = content.slice(0, 100).replaceAll('\n', ' ');
247
+ console.log(`[Consumer] Starting (${this.activeJobs.size}/${this.maxConcurrency}): "${preview}${content.length > 100 ? '...' : ''}"`);
248
+ }
249
+ catch {
250
+ console.log(`[Consumer] Starting (${this.activeJobs.size}/${this.maxConcurrency}): ${execution.id}`);
251
+ }
252
+ }
253
+ /**
254
+ * Main poll loop - dequeues and processes jobs in parallel up to maxConcurrency
255
+ */
256
+ async poll() {
257
+ let storage = getAgentStorageSync();
258
+ let cleanupCounter = 0;
259
+ let orphanCheckCounter = 0;
260
+ while (this.running) {
261
+ try {
262
+ // Check if our lock is still valid (handles race condition when QueuePollingService reconnects first)
263
+ // This covers both: DB file replaced AND another component already reconnected
264
+ if (!storage.hasConsumerLock(this.consumerId)) {
265
+ console.log('[Consumer] Lock lost, re-acquiring...');
266
+ // If DB file also changed, reconnect first
267
+ if (storage.isDbFileChanged()) {
268
+ console.log('[Consumer] DB file changed, reconnecting...');
269
+ // eslint-disable-next-line no-await-in-loop -- Must wait for reconnect before continuing
270
+ await storage.reconnect();
271
+ storage = getAgentStorageSync(); // Get fresh reference after reconnect
272
+ }
273
+ // Re-acquire lock
274
+ if (!storage.acquireConsumerLock(this.consumerId)) {
275
+ console.error('[Consumer] Failed to re-acquire lock');
276
+ this.stop();
277
+ return;
278
+ }
279
+ console.log(`[Consumer] Re-acquired lock (${this.consumerId.slice(0, 8)})`);
280
+ }
281
+ // Calculate available slots
282
+ const availableSlots = this.maxConcurrency - this.activeJobs.size;
283
+ // Dequeue batch of jobs atomically (ensures all queued items are seen in one transaction)
284
+ if (availableSlots > 0) {
285
+ const executions = storage.dequeueBatch(availableSlots, this.consumerId);
286
+ for (const execution of executions) {
287
+ // Track this job
288
+ this.activeJobs.add(execution.id);
289
+ // Log execution start
290
+ this.logExecutionStart(execution);
291
+ // Process in background (fire and forget with completion tracking)
292
+ this.processExecutionAsync(execution);
293
+ }
294
+ }
295
+ // Periodic orphan detection - check for dead consumers and fail their executions
296
+ orphanCheckCounter++;
297
+ if (orphanCheckCounter >= ORPHAN_CHECK_INTERVAL_CYCLES) {
298
+ orphanCheckCounter = 0;
299
+ const orphaned = storage.cleanupStaleConsumers(STALE_TIMEOUT_MS);
300
+ if (orphaned > 0) {
301
+ console.log(`[Consumer] Detected ${orphaned} orphaned executions from dead consumers`);
302
+ }
303
+ }
304
+ // Periodic cleanup (every 10 poll cycles when idle)
305
+ cleanupCounter++;
306
+ if (cleanupCounter >= 10 && this.activeJobs.size === 0) {
307
+ cleanupCounter = 0;
308
+ const cleaned = storage.cleanupOldExecutions(100);
309
+ if (cleaned > 0) {
310
+ console.log(`[Consumer] Cleaned up ${cleaned} old executions`);
311
+ }
312
+ }
313
+ }
314
+ catch (error) {
315
+ console.error('[Consumer] Poll error:', error);
316
+ // Try to recover - re-acquire lock if lost
317
+ // eslint-disable-next-line no-await-in-loop -- Must wait for recovery before continuing
318
+ storage = await this.tryRecoverLock(storage);
319
+ }
320
+ // eslint-disable-next-line no-await-in-loop
321
+ await sleep(this.pollInterval);
322
+ }
323
+ }
324
+ /**
325
+ * Process a single execution
326
+ */
327
+ async processExecution(execution) {
328
+ const storage = getAgentStorageSync();
329
+ try {
330
+ switch (execution.type) {
331
+ case 'curate': {
332
+ await this.executeCurate(execution);
333
+ break;
334
+ }
335
+ case 'query': {
336
+ // Query should not be in queue (runs sync)
337
+ console.warn(`[Consumer] Query execution ${execution.id} found in queue, marking failed`);
338
+ storage.updateExecutionStatus(execution.id, 'failed', undefined, 'Query should not be queued');
339
+ break;
340
+ }
341
+ default: {
342
+ storage.updateExecutionStatus(execution.id, 'failed', undefined, `Unknown execution type: ${execution.type}`);
343
+ }
344
+ }
345
+ }
346
+ catch (error) {
347
+ const errorMessage = error instanceof Error ? error.message : String(error);
348
+ console.error(`[Consumer] Execution ${execution.id} failed:`, errorMessage);
349
+ storage.updateExecutionStatus(execution.id, 'failed', undefined, errorMessage);
350
+ }
351
+ }
352
+ /**
353
+ * Process execution asynchronously (fire and forget with tracking)
354
+ */
355
+ processExecutionAsync(execution) {
356
+ const storage = getAgentStorageSync();
357
+ this.processExecution(execution)
358
+ .then(() => {
359
+ // Log completion
360
+ const updated = storage.getExecution(execution.id);
361
+ if (updated?.status === 'completed') {
362
+ const resultPreview = (updated.result ?? '').slice(0, 100).replaceAll('\n', ' ');
363
+ console.log(`[Consumer] ✓ Done (${this.activeJobs.size - 1}/${this.maxConcurrency}): "${resultPreview}${(updated.result?.length ?? 0) > 100 ? '...' : ''}"`);
364
+ }
365
+ })
366
+ .catch((error) => {
367
+ console.error(`[Consumer] ✗ Failed: ${error instanceof Error ? error.message : String(error)}`);
368
+ })
369
+ .finally(() => {
370
+ // Remove from active jobs
371
+ this.activeJobs.delete(execution.id);
372
+ // Log queue status
373
+ const queued = storage.getQueuedExecutions();
374
+ if (queued.length > 0 || this.activeJobs.size > 0) {
375
+ console.log(`[Consumer] Status: ${this.activeJobs.size} running, ${queued.length} queued`);
376
+ }
377
+ // Immediately try to pick up more jobs (don't wait for next poll cycle)
378
+ if (this.running && queued.length > 0) {
379
+ this.tryPickupJobs();
380
+ }
381
+ });
382
+ }
383
+ /**
384
+ * Setup tool call tracking via event listeners
385
+ */
386
+ setupToolCallTracking(agent, executionId) {
387
+ if (!agent.agentEventBus) {
388
+ console.warn('[Consumer] Agent event bus not available, tool call tracking disabled');
389
+ return;
390
+ }
391
+ const storage = getAgentStorageSync();
392
+ const eventBus = agent.agentEventBus;
393
+ const toolCallMap = new Map(); // callId -> dbToolCallId
394
+ eventBus.on('llmservice:toolCall', (payload) => {
395
+ try {
396
+ if (!payload.callId)
397
+ return;
398
+ const toolCallId = storage.addToolCall(executionId, {
399
+ args: payload.args,
400
+ name: payload.toolName,
401
+ });
402
+ toolCallMap.set(payload.callId, toolCallId);
403
+ }
404
+ catch (error) {
405
+ console.error('[Consumer] Failed to add tool call:', error);
406
+ }
407
+ });
408
+ eventBus.on('llmservice:toolResult', (payload) => {
409
+ try {
410
+ if (!payload.callId)
411
+ return;
412
+ const toolCallId = toolCallMap.get(payload.callId);
413
+ if (toolCallId) {
414
+ // Format result: if error, wrap in {error: "..."} object
415
+ let resultStr;
416
+ if (payload.success) {
417
+ resultStr = typeof payload.result === 'string' ? payload.result : JSON.stringify(payload.result);
418
+ }
419
+ else {
420
+ // Error case: store as {error: "message"} format
421
+ const errorMsg = payload.error ?? (typeof payload.result === 'string' ? payload.result : 'Unknown error');
422
+ resultStr = JSON.stringify({ error: errorMsg });
423
+ }
424
+ const metrics = payload.success ? calculateMetrics(payload.result) : undefined;
425
+ storage.updateToolCall(toolCallId, payload.success ? 'completed' : 'failed', {
426
+ charsCount: metrics?.charsCount,
427
+ linesCount: metrics?.linesCount,
428
+ result: resultStr,
429
+ resultSummary: payload.success ? createResultSummary(payload.result) : undefined,
430
+ });
431
+ }
432
+ }
433
+ catch (error) {
434
+ console.error('[Consumer] Failed to update tool call:', error);
435
+ }
436
+ });
437
+ }
438
+ /**
439
+ * Try to pick up queued jobs (called after job completion)
440
+ */
441
+ tryPickupJobs() {
442
+ const storage = getAgentStorageSync();
443
+ const availableSlots = this.maxConcurrency - this.activeJobs.size;
444
+ if (availableSlots <= 0)
445
+ return;
446
+ // Dequeue batch atomically
447
+ const executions = storage.dequeueBatch(availableSlots, this.consumerId);
448
+ for (const execution of executions) {
449
+ this.activeJobs.add(execution.id);
450
+ try {
451
+ const input = JSON.parse(execution.input);
452
+ const content = input.content ?? '';
453
+ const preview = content.slice(0, 100).replaceAll('\n', ' ');
454
+ console.log(`[Consumer] Starting (${this.activeJobs.size}/${this.maxConcurrency}): "${preview}${content.length > 100 ? '...' : ''}"`);
455
+ }
456
+ catch {
457
+ console.log(`[Consumer] Starting (${this.activeJobs.size}/${this.maxConcurrency}): ${execution.id}`);
458
+ }
459
+ this.processExecutionAsync(execution);
460
+ }
461
+ }
462
+ /**
463
+ * Try to recover lock after error (extracted to reduce nesting depth)
464
+ */
465
+ async tryRecoverLock(currentStorage) {
466
+ try {
467
+ let storage = getAgentStorageSync();
468
+ if (!storage.hasConsumerLock(this.consumerId)) {
469
+ if (storage.isDbFileChanged()) {
470
+ await storage.reconnect();
471
+ storage = getAgentStorageSync();
472
+ }
473
+ storage.acquireConsumerLock(this.consumerId);
474
+ console.log('[Consumer] Recovered from error, re-acquired lock');
475
+ }
476
+ return storage;
477
+ }
478
+ catch {
479
+ // Ignore recovery errors, will retry on next poll
480
+ return currentStorage;
481
+ }
482
+ }
483
+ }
484
+ // ==================== FACTORY & SINGLETON ====================
485
+ let consumerInstance = null;
486
+ /**
487
+ * Create a new ExecutionConsumer instance
488
+ */
489
+ export function createExecutionConsumer(options) {
490
+ return new ExecutionConsumer(options);
491
+ }
492
+ /**
493
+ * Try to start a consumer (singleton pattern)
494
+ * Returns the consumer instance if started, null if already running
495
+ */
496
+ export async function tryStartConsumer(options) {
497
+ // If we already have a running consumer, return null
498
+ if (consumerInstance?.isRunning()) {
499
+ return null;
500
+ }
501
+ const consumer = createExecutionConsumer(options);
502
+ const started = await consumer.start();
503
+ if (started) {
504
+ consumerInstance = consumer;
505
+ return consumer;
506
+ }
507
+ return null;
508
+ }
509
+ /**
510
+ * Get the current consumer instance (if running)
511
+ */
512
+ export function getConsumer() {
513
+ return consumerInstance?.isRunning() ? consumerInstance : null;
514
+ }
515
+ /**
516
+ * Stop the current consumer
517
+ */
518
+ export function stopConsumer() {
519
+ if (consumerInstance) {
520
+ consumerInstance.stop();
521
+ consumerInstance = null;
522
+ }
523
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Consumer Module - Public API for queue processing and UI monitoring
3
+ *
4
+ * Architecture:
5
+ * - ConsumerService: Singleton background worker (start once in main)
6
+ * - QueuePollingService: UI subscribes here for real-time updates
7
+ * - Both communicate via AgentStorage (SQLite DB)
8
+ *
9
+ * Usage:
10
+ * ```typescript
11
+ * // Main process - start consumer singleton
12
+ * import { getConsumerService } from 'byterover-cli/dist/infra/cipher/consumer'
13
+ * const consumer = getConsumerService({ concurrency: 5 })
14
+ * await consumer.start()
15
+ *
16
+ * // UI components - subscribe to polling service
17
+ * import { getQueuePollingService } from 'byterover-cli/dist/infra/cipher/consumer'
18
+ * const poller = getQueuePollingService({ pollInterval: 500 })
19
+ * poller.on('snapshot', (snapshot) => renderUI(snapshot))
20
+ * poller.on('execution:completed', (exec) => showNotification(exec))
21
+ * await poller.start()
22
+ *
23
+ * // Cleanup
24
+ * consumer.dispose()
25
+ * poller.stop()
26
+ * ```
27
+ */
28
+ export { isConsumerRunning, isConsumerRunningSync } from './consumer-lock.js';
29
+ export { ConsumerService, disposeConsumerService, getConsumerService } from './consumer-service.js';
30
+ export type { ConsumerServiceOptions } from './consumer-service.js';
31
+ export { createExecutionConsumer, ExecutionConsumer, getConsumer, stopConsumer, tryStartConsumer, } from './execution-consumer.js';
32
+ export { getQueuePollingService, QueuePollingService, stopQueuePollingService } from './queue-polling-service.js';
33
+ export type { ExecutionWithToolCalls, QueueSnapshot, QueueStats } from './queue-polling-service.js';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Consumer Module - Public API for queue processing and UI monitoring
3
+ *
4
+ * Architecture:
5
+ * - ConsumerService: Singleton background worker (start once in main)
6
+ * - QueuePollingService: UI subscribes here for real-time updates
7
+ * - Both communicate via AgentStorage (SQLite DB)
8
+ *
9
+ * Usage:
10
+ * ```typescript
11
+ * // Main process - start consumer singleton
12
+ * import { getConsumerService } from 'byterover-cli/dist/infra/cipher/consumer'
13
+ * const consumer = getConsumerService({ concurrency: 5 })
14
+ * await consumer.start()
15
+ *
16
+ * // UI components - subscribe to polling service
17
+ * import { getQueuePollingService } from 'byterover-cli/dist/infra/cipher/consumer'
18
+ * const poller = getQueuePollingService({ pollInterval: 500 })
19
+ * poller.on('snapshot', (snapshot) => renderUI(snapshot))
20
+ * poller.on('execution:completed', (exec) => showNotification(exec))
21
+ * await poller.start()
22
+ *
23
+ * // Cleanup
24
+ * consumer.dispose()
25
+ * poller.stop()
26
+ * ```
27
+ */
28
+ // ==================== LOW-LEVEL API (for advanced usage) ====================
29
+ export { isConsumerRunning, isConsumerRunningSync } from './consumer-lock.js';
30
+ // ==================== HIGH-LEVEL API (for UI/REPL) ====================
31
+ export { ConsumerService, disposeConsumerService, getConsumerService } from './consumer-service.js';
32
+ export { createExecutionConsumer, ExecutionConsumer, getConsumer, stopConsumer, tryStartConsumer, } from './execution-consumer.js';
33
+ export { getQueuePollingService, QueuePollingService, stopQueuePollingService } from './queue-polling-service.js';