byterover-cli 0.4.0 → 1.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 (478) hide show
  1. package/README.md +1 -9
  2. package/dist/commands/curate.d.ts +1 -3
  3. package/dist/commands/curate.js +14 -51
  4. package/dist/commands/main.d.ts +8 -0
  5. package/dist/commands/main.js +29 -8
  6. package/dist/commands/query.d.ts +1 -3
  7. package/dist/commands/query.js +8 -35
  8. package/dist/config/context-tree-domains.d.ts +5 -0
  9. package/dist/config/context-tree-domains.js +6 -1
  10. package/dist/config/environment.js +9 -9
  11. package/dist/constants.d.ts +14 -0
  12. package/dist/constants.js +18 -0
  13. package/dist/core/domain/cipher/agent/agent-info.d.ts +199 -0
  14. package/dist/core/domain/cipher/agent/agent-info.js +143 -0
  15. package/dist/core/domain/cipher/agent/agent-registry.d.ts +96 -0
  16. package/dist/core/domain/cipher/agent/agent-registry.js +254 -0
  17. package/dist/core/domain/cipher/agent/index.d.ts +4 -1
  18. package/dist/core/domain/cipher/agent/index.js +7 -1
  19. package/dist/core/domain/cipher/agent-events/types.d.ts +355 -2
  20. package/dist/core/domain/cipher/agent-events/types.js +11 -0
  21. package/dist/core/domain/cipher/errors/error-normalizer.d.ts +156 -0
  22. package/dist/core/domain/cipher/errors/error-normalizer.js +379 -0
  23. package/dist/core/domain/cipher/errors/file-system-error.d.ts +2 -1
  24. package/dist/core/domain/cipher/errors/file-system-error.js +3 -2
  25. package/dist/core/domain/cipher/errors/system-prompt-error-codes.d.ts +79 -0
  26. package/dist/core/domain/cipher/errors/system-prompt-error-codes.js +80 -0
  27. package/dist/core/domain/cipher/errors/system-prompt-error.d.ts +114 -0
  28. package/dist/core/domain/cipher/errors/system-prompt-error.js +144 -0
  29. package/dist/core/domain/cipher/file-system/types.d.ts +57 -0
  30. package/dist/core/domain/cipher/llm/error-codes.d.ts +51 -0
  31. package/dist/core/domain/cipher/llm/error-codes.js +51 -0
  32. package/dist/core/domain/cipher/llm/index.d.ts +9 -0
  33. package/dist/core/domain/cipher/llm/index.js +13 -0
  34. package/dist/core/domain/cipher/llm/registry.d.ts +113 -0
  35. package/dist/core/domain/cipher/llm/registry.js +244 -0
  36. package/dist/core/domain/cipher/llm/schemas.d.ts +155 -0
  37. package/dist/core/domain/cipher/llm/schemas.js +151 -0
  38. package/dist/core/domain/cipher/llm/types.d.ts +121 -0
  39. package/dist/core/domain/cipher/llm/types.js +60 -0
  40. package/dist/core/domain/cipher/storage/message-storage-types.d.ts +114 -5
  41. package/dist/core/domain/cipher/streaming/types.d.ts +119 -0
  42. package/dist/core/domain/cipher/streaming/types.js +16 -0
  43. package/dist/core/domain/cipher/system-prompt/types.d.ts +44 -0
  44. package/dist/core/domain/cipher/todos/types.d.ts +34 -0
  45. package/dist/core/domain/cipher/tools/constants.d.ts +5 -2
  46. package/dist/core/domain/cipher/tools/constants.js +5 -2
  47. package/dist/core/domain/cipher/tools/types.d.ts +31 -0
  48. package/dist/core/domain/entities/event.d.ts +1 -1
  49. package/dist/core/domain/entities/event.js +3 -1
  50. package/dist/core/domain/errors/connection-error.d.ts +33 -0
  51. package/dist/core/domain/errors/connection-error.js +54 -0
  52. package/dist/core/domain/errors/core-process-error.d.ts +27 -0
  53. package/dist/core/domain/errors/core-process-error.js +43 -0
  54. package/dist/core/domain/errors/task-error.d.ts +64 -0
  55. package/dist/core/domain/errors/task-error.js +116 -0
  56. package/dist/core/domain/errors/transport-error.d.ts +72 -0
  57. package/dist/core/domain/errors/transport-error.js +114 -0
  58. package/dist/core/domain/instance/index.d.ts +1 -0
  59. package/dist/core/domain/instance/index.js +1 -0
  60. package/dist/core/domain/instance/types.d.ts +57 -0
  61. package/dist/core/domain/instance/types.js +72 -0
  62. package/dist/core/domain/knowledge/directory-manager.d.ts +16 -0
  63. package/dist/core/domain/knowledge/directory-manager.js +31 -0
  64. package/dist/core/domain/transport/index.d.ts +2 -0
  65. package/dist/core/domain/transport/index.js +2 -0
  66. package/dist/core/domain/transport/schemas.d.ts +1149 -0
  67. package/dist/core/domain/transport/schemas.js +554 -0
  68. package/dist/core/domain/transport/types.d.ts +67 -0
  69. package/dist/core/domain/transport/types.js +7 -0
  70. package/dist/core/interfaces/cipher/cipher-services.d.ts +15 -3
  71. package/dist/core/interfaces/cipher/i-chat-session.d.ts +47 -5
  72. package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +39 -4
  73. package/dist/core/interfaces/cipher/i-content-generator.d.ts +3 -5
  74. package/dist/core/interfaces/cipher/i-file-system.d.ts +12 -1
  75. package/dist/core/interfaces/cipher/i-llm-service.d.ts +4 -5
  76. package/dist/core/interfaces/cipher/i-todo-storage.d.ts +24 -0
  77. package/dist/core/interfaces/cipher/i-todo-storage.js +1 -0
  78. package/dist/core/interfaces/cipher/i-tool-plugin.d.ts +90 -0
  79. package/dist/core/interfaces/cipher/i-tool-plugin.js +1 -0
  80. package/dist/core/interfaces/cipher/i-tool-provider.d.ts +3 -2
  81. package/dist/core/interfaces/cipher/i-tool-scheduler.d.ts +4 -0
  82. package/dist/core/interfaces/cipher/index.d.ts +35 -0
  83. package/dist/core/interfaces/cipher/index.js +11 -0
  84. package/dist/core/interfaces/cipher/message-factory.d.ts +155 -0
  85. package/dist/core/interfaces/cipher/message-factory.js +252 -0
  86. package/dist/core/interfaces/cipher/message-type-guards.d.ts +139 -0
  87. package/dist/core/interfaces/cipher/message-type-guards.js +173 -0
  88. package/dist/core/interfaces/cipher/message-types.d.ts +279 -5
  89. package/dist/core/interfaces/cipher/message-types.js +6 -0
  90. package/dist/core/interfaces/cipher/sanitization-types.d.ts +147 -0
  91. package/dist/core/interfaces/cipher/sanitization-types.js +46 -0
  92. package/dist/core/interfaces/executor/i-curate-executor.d.ts +34 -0
  93. package/dist/core/interfaces/executor/i-curate-executor.js +1 -0
  94. package/dist/core/interfaces/executor/i-query-executor.d.ts +32 -0
  95. package/dist/core/interfaces/executor/i-query-executor.js +1 -0
  96. package/dist/core/interfaces/executor/index.d.ts +2 -0
  97. package/dist/core/interfaces/executor/index.js +2 -0
  98. package/dist/core/interfaces/instance/i-instance-discovery.d.ts +45 -0
  99. package/dist/core/interfaces/instance/i-instance-discovery.js +1 -0
  100. package/dist/core/interfaces/instance/i-instance-manager.d.ts +58 -0
  101. package/dist/core/interfaces/instance/i-instance-manager.js +1 -0
  102. package/dist/core/interfaces/instance/index.d.ts +2 -0
  103. package/dist/core/interfaces/instance/index.js +2 -0
  104. package/dist/core/interfaces/noop-implementations.d.ts +53 -0
  105. package/dist/core/interfaces/noop-implementations.js +62 -0
  106. package/dist/core/interfaces/transport/i-transport-client.d.ts +97 -0
  107. package/dist/core/interfaces/transport/i-transport-client.js +1 -0
  108. package/dist/core/interfaces/transport/i-transport-server.d.ts +93 -0
  109. package/dist/core/interfaces/transport/i-transport-server.js +1 -0
  110. package/dist/core/interfaces/transport/index.d.ts +2 -0
  111. package/dist/core/interfaces/transport/index.js +2 -0
  112. package/dist/hooks/init/welcome.js +9 -24
  113. package/dist/infra/cipher/agent/agent-error-codes.d.ts +16 -0
  114. package/dist/infra/cipher/agent/agent-error-codes.js +17 -0
  115. package/dist/infra/cipher/agent/agent-error.d.ts +54 -0
  116. package/dist/infra/cipher/agent/agent-error.js +79 -0
  117. package/dist/infra/cipher/agent/agent-schemas.d.ts +264 -0
  118. package/dist/infra/cipher/agent/agent-schemas.js +97 -0
  119. package/dist/infra/cipher/agent/agent-state-manager.d.ts +140 -0
  120. package/dist/infra/cipher/agent/agent-state-manager.js +275 -0
  121. package/dist/infra/cipher/agent/base-agent.d.ts +118 -0
  122. package/dist/infra/cipher/agent/base-agent.js +240 -0
  123. package/dist/infra/cipher/agent/cipher-agent.d.ts +165 -0
  124. package/dist/infra/cipher/agent/cipher-agent.js +546 -0
  125. package/dist/infra/cipher/agent/index.d.ts +22 -0
  126. package/dist/infra/cipher/agent/index.js +24 -0
  127. package/dist/infra/cipher/agent/service-initializer.d.ts +79 -0
  128. package/dist/infra/cipher/{agent-service-factory.js → agent/service-initializer.js} +117 -68
  129. package/dist/infra/cipher/agent/types.d.ts +35 -0
  130. package/dist/infra/cipher/agent/types.js +1 -0
  131. package/dist/infra/cipher/blob/blob-reference-resolver.d.ts +107 -0
  132. package/dist/infra/cipher/blob/blob-reference-resolver.js +228 -0
  133. package/dist/infra/cipher/blob/blob-reference-utils.d.ts +117 -0
  134. package/dist/infra/cipher/blob/blob-reference-utils.js +230 -0
  135. package/dist/infra/cipher/consumer/consumer-lock.js +1 -0
  136. package/dist/infra/cipher/consumer/consumer-service.js +1 -0
  137. package/dist/infra/cipher/consumer/execution-consumer.d.ts +6 -1
  138. package/dist/infra/cipher/consumer/execution-consumer.js +54 -16
  139. package/dist/infra/cipher/consumer/index.d.ts +1 -1
  140. package/dist/infra/cipher/consumer/index.js +2 -1
  141. package/dist/infra/cipher/consumer/queue-polling-service.js +1 -0
  142. package/dist/infra/cipher/file-system/binary-utils.d.ts +43 -0
  143. package/dist/infra/cipher/file-system/binary-utils.js +164 -0
  144. package/dist/infra/cipher/file-system/context-tree-file-system-factory.d.ts +9 -0
  145. package/dist/infra/cipher/file-system/context-tree-file-system-factory.js +24 -0
  146. package/dist/infra/cipher/file-system/file-system-service.d.ts +17 -1
  147. package/dist/infra/cipher/file-system/file-system-service.js +327 -36
  148. package/dist/infra/cipher/file-system/path-validator.d.ts +32 -0
  149. package/dist/infra/cipher/file-system/path-validator.js +111 -6
  150. package/dist/infra/cipher/interactive-loop.js +41 -33
  151. package/dist/infra/cipher/llm/capability-cache.d.ts +87 -0
  152. package/dist/infra/cipher/llm/capability-cache.js +125 -0
  153. package/dist/infra/cipher/llm/context/compaction/compaction-service.d.ts +32 -0
  154. package/dist/infra/cipher/llm/context/compaction/compaction-service.js +44 -3
  155. package/dist/infra/cipher/llm/context/compression/enhanced-compaction.d.ts +112 -0
  156. package/dist/infra/cipher/llm/context/compression/enhanced-compaction.js +175 -0
  157. package/dist/infra/cipher/llm/context/compression/filter-compacted.d.ts +83 -0
  158. package/dist/infra/cipher/llm/context/compression/filter-compacted.js +150 -0
  159. package/dist/infra/cipher/llm/context/compression/index.d.ts +5 -0
  160. package/dist/infra/cipher/llm/context/compression/index.js +6 -0
  161. package/dist/infra/cipher/llm/context/compression/reactive-overflow.d.ts +107 -0
  162. package/dist/infra/cipher/llm/context/compression/reactive-overflow.js +272 -0
  163. package/dist/infra/cipher/llm/context/context-manager.d.ts +47 -1
  164. package/dist/infra/cipher/llm/context/context-manager.js +129 -0
  165. package/dist/infra/cipher/llm/context/utils.js +17 -4
  166. package/dist/infra/cipher/llm/generators/byterover-content-generator.js +4 -2
  167. package/dist/infra/cipher/llm/internal-llm-service.d.ts +50 -17
  168. package/dist/infra/cipher/llm/internal-llm-service.js +273 -50
  169. package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +6 -8
  170. package/dist/infra/cipher/llm/openrouter-llm-service.js +14 -16
  171. package/dist/infra/cipher/llm/retry/retry-policy.d.ts +1 -0
  172. package/dist/infra/cipher/llm/retry/retry-policy.js +11 -0
  173. package/dist/infra/cipher/llm/retry/retry-with-backoff.js +3 -2
  174. package/dist/infra/cipher/llm/sanitization/base64-utils.d.ts +102 -0
  175. package/dist/infra/cipher/llm/sanitization/base64-utils.js +182 -0
  176. package/dist/infra/cipher/llm/sanitization/index.d.ts +12 -0
  177. package/dist/infra/cipher/llm/sanitization/index.js +13 -0
  178. package/dist/infra/cipher/llm/sanitization/tool-sanitizer.d.ts +74 -0
  179. package/dist/infra/cipher/llm/sanitization/tool-sanitizer.js +398 -0
  180. package/dist/infra/cipher/llm/stream-processor.d.ts +158 -0
  181. package/dist/infra/cipher/llm/stream-processor.js +276 -0
  182. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.d.ts +13 -20
  183. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.js +17 -24
  184. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.d.ts +12 -11
  185. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.js +16 -15
  186. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.d.ts +15 -7
  187. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.js +22 -10
  188. package/dist/infra/cipher/llm/tool-output-processor.d.ts +51 -0
  189. package/dist/infra/cipher/llm/tool-output-processor.js +139 -0
  190. package/dist/infra/cipher/process/command-validator.d.ts +23 -0
  191. package/dist/infra/cipher/process/command-validator.js +75 -0
  192. package/dist/infra/cipher/process/path-utils.d.ts +66 -0
  193. package/dist/infra/cipher/process/path-utils.js +94 -0
  194. package/dist/infra/cipher/process/process-service.d.ts +32 -0
  195. package/dist/infra/cipher/process/process-service.js +98 -17
  196. package/dist/infra/cipher/session/chat-session.d.ts +56 -7
  197. package/dist/infra/cipher/session/chat-session.js +163 -13
  198. package/dist/infra/cipher/session/index.d.ts +1 -0
  199. package/dist/infra/cipher/session/index.js +2 -0
  200. package/dist/infra/cipher/session/message-queue.d.ts +65 -0
  201. package/dist/infra/cipher/session/message-queue.js +90 -0
  202. package/dist/infra/cipher/session/session-manager.d.ts +106 -5
  203. package/dist/infra/cipher/session/session-manager.js +254 -7
  204. package/dist/infra/cipher/session/session-status.d.ts +137 -0
  205. package/dist/infra/cipher/session/session-status.js +184 -0
  206. package/dist/infra/cipher/session/title-generator.d.ts +8 -0
  207. package/dist/infra/cipher/session/title-generator.js +31 -0
  208. package/dist/infra/cipher/storage/message-storage-service.d.ts +65 -2
  209. package/dist/infra/cipher/storage/message-storage-service.js +300 -54
  210. package/dist/infra/cipher/storage/tool-part-factory.d.ts +116 -0
  211. package/dist/infra/cipher/storage/tool-part-factory.js +197 -0
  212. package/dist/infra/cipher/system-prompt/contributor-schemas.d.ts +516 -0
  213. package/dist/infra/cipher/system-prompt/contributor-schemas.js +85 -0
  214. package/dist/infra/cipher/system-prompt/contributors/agent-prompt-contributor.d.ts +59 -0
  215. package/dist/infra/cipher/system-prompt/contributors/agent-prompt-contributor.js +131 -0
  216. package/dist/infra/cipher/system-prompt/contributors/companion-contributor.d.ts +54 -0
  217. package/dist/infra/cipher/system-prompt/contributors/companion-contributor.js +107 -0
  218. package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.d.ts +68 -0
  219. package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.js +179 -0
  220. package/dist/infra/cipher/system-prompt/contributors/datetime-contributor.d.ts +25 -0
  221. package/dist/infra/cipher/system-prompt/contributors/datetime-contributor.js +29 -0
  222. package/dist/infra/cipher/system-prompt/contributors/environment-contributor.d.ts +25 -0
  223. package/dist/infra/cipher/system-prompt/contributors/environment-contributor.js +54 -0
  224. package/dist/infra/cipher/system-prompt/contributors/file-contributor.d.ts +60 -0
  225. package/dist/infra/cipher/system-prompt/contributors/file-contributor.js +128 -0
  226. package/dist/infra/cipher/system-prompt/contributors/index.d.ts +13 -0
  227. package/dist/infra/cipher/system-prompt/contributors/index.js +8 -0
  228. package/dist/infra/cipher/system-prompt/contributors/memory-contributor.d.ts +40 -0
  229. package/dist/infra/cipher/system-prompt/contributors/memory-contributor.js +56 -0
  230. package/dist/infra/cipher/system-prompt/contributors/static-contributor.d.ts +26 -0
  231. package/dist/infra/cipher/system-prompt/contributors/static-contributor.js +31 -0
  232. package/dist/infra/cipher/system-prompt/environment-context-builder.d.ts +112 -0
  233. package/dist/infra/cipher/system-prompt/environment-context-builder.js +256 -0
  234. package/dist/infra/cipher/system-prompt/prompt-cache.d.ts +102 -0
  235. package/dist/infra/cipher/system-prompt/prompt-cache.js +156 -0
  236. package/dist/infra/cipher/system-prompt/schemas.d.ts +151 -0
  237. package/dist/infra/cipher/system-prompt/schemas.js +94 -0
  238. package/dist/infra/cipher/system-prompt/system-prompt-manager.d.ts +136 -0
  239. package/dist/infra/cipher/system-prompt/system-prompt-manager.js +307 -0
  240. package/dist/infra/cipher/todos/todo-storage-service.d.ts +26 -0
  241. package/dist/infra/cipher/todos/todo-storage-service.js +28 -0
  242. package/dist/infra/cipher/tools/core-tool-scheduler.js +5 -1
  243. package/dist/infra/cipher/tools/default-policy-rules.js +1 -1
  244. package/dist/infra/cipher/tools/implementations/bash-exec-tool.d.ts +1 -0
  245. package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +27 -10
  246. package/dist/infra/cipher/tools/implementations/bash-output-tool.js +1 -5
  247. package/dist/infra/cipher/tools/implementations/batch-tool.d.ts +12 -0
  248. package/dist/infra/cipher/tools/implementations/batch-tool.js +142 -0
  249. package/dist/infra/cipher/tools/implementations/curate-tool.js +195 -68
  250. package/dist/infra/cipher/tools/implementations/list-directory-tool.d.ts +12 -0
  251. package/dist/infra/cipher/tools/implementations/list-directory-tool.js +52 -0
  252. package/dist/infra/cipher/tools/implementations/read-file-tool.d.ts +8 -1
  253. package/dist/infra/cipher/tools/implementations/read-file-tool.js +17 -7
  254. package/dist/infra/cipher/tools/implementations/read-todos-tool.d.ts +11 -0
  255. package/dist/infra/cipher/tools/implementations/read-todos-tool.js +39 -0
  256. package/dist/infra/cipher/tools/implementations/{detect-domains-tool.d.ts → spec-analyze-tool.d.ts} +1 -1
  257. package/dist/infra/cipher/tools/implementations/{detect-domains-tool.js → spec-analyze-tool.js} +9 -7
  258. package/dist/infra/cipher/tools/implementations/task-tool.d.ts +34 -0
  259. package/dist/infra/cipher/tools/implementations/task-tool.js +207 -0
  260. package/dist/infra/cipher/tools/implementations/write-todos-tool.d.ts +4 -1
  261. package/dist/infra/cipher/tools/implementations/write-todos-tool.js +19 -63
  262. package/dist/infra/cipher/tools/index.d.ts +1 -1
  263. package/dist/infra/cipher/tools/index.js +1 -1
  264. package/dist/infra/cipher/tools/plugins/index.d.ts +3 -0
  265. package/dist/infra/cipher/tools/plugins/index.js +2 -0
  266. package/dist/infra/cipher/tools/plugins/logging-plugin.d.ts +28 -0
  267. package/dist/infra/cipher/tools/plugins/logging-plugin.js +66 -0
  268. package/dist/infra/cipher/tools/plugins/plugin-manager.d.ts +81 -0
  269. package/dist/infra/cipher/tools/plugins/plugin-manager.js +122 -0
  270. package/dist/infra/cipher/tools/streaming/index.d.ts +1 -0
  271. package/dist/infra/cipher/tools/streaming/index.js +1 -0
  272. package/dist/infra/cipher/tools/streaming/metadata-handler.d.ts +31 -0
  273. package/dist/infra/cipher/tools/streaming/metadata-handler.js +39 -0
  274. package/dist/infra/cipher/tools/tool-description-loader.d.ts +57 -0
  275. package/dist/infra/cipher/tools/tool-description-loader.js +108 -0
  276. package/dist/infra/cipher/tools/tool-manager.d.ts +38 -4
  277. package/dist/infra/cipher/tools/tool-manager.js +107 -11
  278. package/dist/infra/cipher/tools/tool-provider-getter.d.ts +6 -0
  279. package/dist/infra/cipher/tools/tool-provider-getter.js +1 -0
  280. package/dist/infra/cipher/tools/tool-provider.d.ts +32 -7
  281. package/dist/infra/cipher/tools/tool-provider.js +81 -25
  282. package/dist/infra/cipher/tools/tool-registry.d.ts +23 -0
  283. package/dist/infra/cipher/tools/tool-registry.js +58 -16
  284. package/dist/infra/context-tree/file-context-tree-snapshot-service.js +10 -4
  285. package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +4 -3
  286. package/dist/infra/context-tree/file-context-tree-writer-service.js +6 -4
  287. package/dist/infra/context-tree/path-utils.d.ts +7 -0
  288. package/dist/infra/context-tree/path-utils.js +7 -0
  289. package/dist/infra/core/executors/curate-executor.d.ts +35 -0
  290. package/dist/infra/core/executors/curate-executor.js +123 -0
  291. package/dist/infra/core/executors/index.d.ts +2 -0
  292. package/dist/infra/core/executors/index.js +2 -0
  293. package/dist/infra/core/executors/query-executor.d.ts +23 -0
  294. package/dist/infra/core/executors/query-executor.js +51 -0
  295. package/dist/infra/core/task-processor.d.ts +81 -0
  296. package/dist/infra/core/task-processor.js +115 -0
  297. package/dist/infra/instance/file-instance-discovery.d.ts +31 -0
  298. package/dist/infra/instance/file-instance-discovery.js +84 -0
  299. package/dist/infra/instance/file-instance-manager.d.ts +46 -0
  300. package/dist/infra/instance/file-instance-manager.js +123 -0
  301. package/dist/infra/instance/index.d.ts +3 -0
  302. package/dist/infra/instance/index.js +3 -0
  303. package/dist/infra/instance/process-utils.d.ts +14 -0
  304. package/dist/infra/instance/process-utils.js +39 -0
  305. package/dist/infra/process/agent-worker.d.ts +20 -0
  306. package/dist/infra/process/agent-worker.js +602 -0
  307. package/dist/infra/process/index.d.ts +12 -0
  308. package/dist/infra/process/index.js +11 -0
  309. package/dist/infra/process/ipc-types.d.ts +55 -0
  310. package/dist/infra/process/ipc-types.js +12 -0
  311. package/dist/infra/process/process-manager.d.ts +154 -0
  312. package/dist/infra/process/process-manager.js +471 -0
  313. package/dist/infra/process/task-queue-manager.d.ts +123 -0
  314. package/dist/infra/process/task-queue-manager.js +226 -0
  315. package/dist/infra/process/transport-handlers.d.ts +124 -0
  316. package/dist/infra/process/transport-handlers.js +348 -0
  317. package/dist/infra/process/transport-worker.d.ts +20 -0
  318. package/dist/infra/process/transport-worker.js +168 -0
  319. package/dist/infra/repl/commands/curate-command.js +0 -5
  320. package/dist/infra/repl/commands/query-command.js +0 -3
  321. package/dist/infra/repl/repl-startup.d.ts +4 -0
  322. package/dist/infra/repl/repl-startup.js +10 -1
  323. package/dist/infra/repl/transport-client-helper.d.ts +9 -0
  324. package/dist/infra/repl/transport-client-helper.js +96 -0
  325. package/dist/infra/transport/index.d.ts +4 -0
  326. package/dist/infra/transport/index.js +4 -0
  327. package/dist/infra/transport/port-utils.d.ts +42 -0
  328. package/dist/infra/transport/port-utils.js +84 -0
  329. package/dist/infra/transport/socket-io-transport-client.d.ts +45 -0
  330. package/dist/infra/transport/socket-io-transport-client.js +270 -0
  331. package/dist/infra/transport/socket-io-transport-server.d.ts +35 -0
  332. package/dist/infra/transport/socket-io-transport-server.js +207 -0
  333. package/dist/infra/transport/transport-client-factory.d.ts +76 -0
  334. package/dist/infra/transport/transport-client-factory.js +168 -0
  335. package/dist/infra/transport/transport-factory.d.ts +33 -0
  336. package/dist/infra/transport/transport-factory.js +59 -0
  337. package/dist/infra/usecase/curate-use-case.d.ts +8 -55
  338. package/dist/infra/usecase/curate-use-case.js +73 -259
  339. package/dist/infra/usecase/init-use-case.js +19 -8
  340. package/dist/infra/usecase/login-use-case.js +9 -3
  341. package/dist/infra/usecase/query-use-case.d.ts +18 -45
  342. package/dist/infra/usecase/query-use-case.js +251 -326
  343. package/dist/infra/usecase/status-use-case.js +1 -1
  344. package/dist/resources/prompts/{curate-context-tree-curation.yml → curate.yml} +25 -22
  345. package/dist/resources/prompts/explore.yml +78 -0
  346. package/dist/resources/prompts/plan.yml +114 -0
  347. package/dist/resources/prompts/reflection.yml +1 -1
  348. package/dist/resources/prompts/system-prompt.yml +15 -8
  349. package/dist/resources/prompts/tool-outputs.yml +0 -5
  350. package/dist/resources/tools/bash_exec.txt +98 -0
  351. package/dist/resources/tools/bash_output.txt +40 -0
  352. package/dist/resources/tools/batch.txt +28 -0
  353. package/dist/resources/tools/create_knowledge_topic.txt +23 -0
  354. package/dist/resources/tools/curate.txt +22 -0
  355. package/dist/resources/tools/delete_memory.txt +1 -0
  356. package/dist/resources/tools/detect_domains.txt +11 -0
  357. package/dist/resources/tools/edit_file.txt +1 -0
  358. package/dist/resources/tools/edit_memory.txt +1 -0
  359. package/dist/resources/tools/glob_files.txt +20 -0
  360. package/dist/resources/tools/grep_content.txt +18 -0
  361. package/dist/resources/tools/kill_process.txt +16 -0
  362. package/dist/resources/tools/list_directory.txt +16 -0
  363. package/dist/resources/tools/list_memories.txt +1 -0
  364. package/dist/resources/tools/read_file.txt +31 -0
  365. package/dist/resources/tools/read_memory.txt +1 -0
  366. package/dist/resources/tools/read_todos.txt +17 -0
  367. package/dist/resources/tools/search_history.txt +1 -0
  368. package/dist/resources/tools/task.txt +23 -0
  369. package/dist/resources/tools/write_file.txt +1 -0
  370. package/dist/resources/tools/write_memory.txt +1 -0
  371. package/dist/resources/tools/write_todos.txt +29 -0
  372. package/dist/tui/app.js +9 -13
  373. package/dist/tui/components/command-details.d.ts +14 -0
  374. package/dist/tui/components/command-details.js +35 -0
  375. package/dist/tui/components/execution/execution-changes.d.ts +5 -0
  376. package/dist/tui/components/execution/execution-changes.js +19 -4
  377. package/dist/tui/components/execution/execution-content.d.ts +4 -2
  378. package/dist/tui/components/execution/execution-content.js +26 -13
  379. package/dist/tui/components/execution/execution-input.js +3 -3
  380. package/dist/tui/components/execution/execution-progress.d.ts +2 -2
  381. package/dist/tui/components/execution/execution-progress.js +8 -6
  382. package/dist/tui/components/execution/log-item.d.ts +3 -4
  383. package/dist/tui/components/execution/log-item.js +2 -5
  384. package/dist/tui/components/footer.js +9 -4
  385. package/dist/tui/components/header.d.ts +3 -3
  386. package/dist/tui/components/header.js +5 -3
  387. package/dist/tui/components/index.d.ts +1 -0
  388. package/dist/tui/components/index.js +1 -0
  389. package/dist/tui/components/onboarding/copyable-prompt.d.ts +5 -3
  390. package/dist/tui/components/onboarding/copyable-prompt.js +7 -8
  391. package/dist/tui/components/onboarding/onboarding-flow.js +35 -25
  392. package/dist/tui/components/scrollable-list.js +12 -10
  393. package/dist/tui/components/suggestions.js +39 -41
  394. package/dist/tui/components/tab-bar.d.ts +2 -1
  395. package/dist/tui/components/tab-bar.js +3 -4
  396. package/dist/tui/constants.d.ts +0 -5
  397. package/dist/tui/constants.js +0 -5
  398. package/dist/tui/contexts/auth-context.js +9 -2
  399. package/dist/tui/contexts/{use-commands.js → commands-context.js} +6 -5
  400. package/dist/tui/contexts/index.d.ts +6 -1
  401. package/dist/tui/contexts/index.js +6 -1
  402. package/dist/tui/contexts/onboarding-context.d.ts +1 -1
  403. package/dist/tui/contexts/onboarding-context.js +9 -9
  404. package/dist/tui/contexts/tasks-context.d.ts +84 -0
  405. package/dist/tui/contexts/tasks-context.js +218 -0
  406. package/dist/tui/contexts/transport-context.d.ts +29 -0
  407. package/dist/tui/contexts/transport-context.js +82 -0
  408. package/dist/tui/hooks/index.d.ts +10 -6
  409. package/dist/tui/hooks/index.js +7 -6
  410. package/dist/tui/hooks/use-activity-logs.d.ts +3 -11
  411. package/dist/tui/hooks/use-activity-logs.js +87 -34
  412. package/dist/tui/hooks/use-auth-polling.d.ts +24 -0
  413. package/dist/tui/hooks/use-auth-polling.js +104 -0
  414. package/dist/tui/hooks/use-slash-command-processor.js +0 -1
  415. package/dist/tui/hooks/use-slash-completion.js +1 -1
  416. package/dist/tui/hooks/use-tab-navigation.d.ts +2 -1
  417. package/dist/tui/hooks/use-tab-navigation.js +16 -7
  418. package/dist/tui/hooks/use-terminal-breakpoint.d.ts +21 -0
  419. package/dist/tui/hooks/use-terminal-breakpoint.js +38 -0
  420. package/dist/tui/hooks/use-ui-heights.d.ts +120 -0
  421. package/dist/tui/hooks/use-ui-heights.js +88 -0
  422. package/dist/tui/providers/app-providers.js +2 -6
  423. package/dist/tui/types/commands.d.ts +0 -26
  424. package/dist/tui/types/index.d.ts +1 -1
  425. package/dist/tui/types/ui.d.ts +9 -4
  426. package/dist/tui/utils/line.d.ts +11 -0
  427. package/dist/tui/utils/line.js +16 -0
  428. package/dist/tui/utils/log.d.ts +27 -0
  429. package/dist/tui/utils/log.js +114 -0
  430. package/dist/tui/views/command-view.d.ts +7 -0
  431. package/dist/tui/views/command-view.js +103 -80
  432. package/dist/tui/views/login-view.js +7 -4
  433. package/dist/tui/views/logs-view.d.ts +13 -0
  434. package/dist/tui/views/logs-view.js +27 -52
  435. package/dist/utils/connection-error-handler.d.ts +16 -0
  436. package/dist/utils/connection-error-handler.js +49 -0
  437. package/dist/utils/crash-log.d.ts +14 -0
  438. package/dist/utils/crash-log.js +19 -0
  439. package/dist/utils/file-helpers.d.ts +14 -0
  440. package/dist/utils/file-helpers.js +21 -0
  441. package/dist/utils/global-logs-path.d.ts +11 -0
  442. package/dist/utils/global-logs-path.js +37 -0
  443. package/dist/utils/process-logger.d.ts +53 -0
  444. package/dist/utils/process-logger.js +253 -0
  445. package/dist/utils/sandbox-detector.d.ts +31 -0
  446. package/dist/utils/sandbox-detector.js +122 -0
  447. package/oclif.manifest.json +10 -198
  448. package/package.json +5 -1
  449. package/dist/commands/cipher-agent/run.d.ts +0 -142
  450. package/dist/commands/cipher-agent/run.js +0 -555
  451. package/dist/commands/cipher-agent/set-prompt.d.ts +0 -16
  452. package/dist/commands/cipher-agent/set-prompt.js +0 -58
  453. package/dist/commands/cipher-agent/show-prompt.d.ts +0 -13
  454. package/dist/commands/cipher-agent/show-prompt.js +0 -53
  455. package/dist/commands/foo.d.ts +0 -14
  456. package/dist/commands/foo.js +0 -66
  457. package/dist/infra/cipher/agent-service-factory.d.ts +0 -93
  458. package/dist/infra/cipher/cipher-agent-state-manager.d.ts +0 -63
  459. package/dist/infra/cipher/cipher-agent-state-manager.js +0 -108
  460. package/dist/infra/cipher/cipher-agent.d.ts +0 -182
  461. package/dist/infra/cipher/cipher-agent.js +0 -317
  462. package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +0 -106
  463. package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +0 -297
  464. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.d.ts +0 -7
  465. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +0 -424
  466. package/dist/resources/prompts/modes/autonomous.yml +0 -9
  467. package/dist/resources/prompts/query-context-tree-retrieval.yml +0 -48
  468. package/dist/tui/contexts/consumer.d.ts +0 -31
  469. package/dist/tui/contexts/consumer.js +0 -56
  470. package/dist/tui/hooks/use-consumer.d.ts +0 -12
  471. package/dist/tui/hooks/use-consumer.js +0 -50
  472. package/dist/tui/hooks/use-queue-polling.d.ts +0 -31
  473. package/dist/tui/hooks/use-queue-polling.js +0 -90
  474. /package/dist/tui/contexts/{use-commands.d.ts → commands-context.d.ts} +0 -0
  475. /package/dist/tui/contexts/{use-mode.d.ts → mode-context.d.ts} +0 -0
  476. /package/dist/tui/contexts/{use-mode.js → mode-context.js} +0 -0
  477. /package/dist/tui/contexts/{use-theme.d.ts → theme-context.d.ts} +0 -0
  478. /package/dist/tui/contexts/{use-theme.js → theme-context.js} +0 -0
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Log utility functions for height calculations
3
+ */
4
+ /**
5
+ * Calculate the actual rendered height of a log item.
6
+ * This reflects the real space the item takes up when rendered.
7
+ *
8
+ * @param log - The activity log to analyze
9
+ * @param baseHeights - Base height configuration from breakpoint (maxContentLines is optional)
10
+ * @returns Total height in lines that this log item will occupy
11
+ */
12
+ export function calculateActualLogHeight(log, baseHeights) {
13
+ let totalLines = 0;
14
+ // Header: always 1 line
15
+ totalLines += baseHeights.header;
16
+ // Input: always present
17
+ totalLines += baseHeights.input;
18
+ // Progress: only if there are progress items
19
+ const actualProgress = log.progress?.length ?? 0;
20
+ if (actualProgress > 0) {
21
+ totalLines += Math.min(actualProgress, baseHeights.maxProgressItems);
22
+ }
23
+ // Status: always 1 line (from ExecutionStatus)
24
+ totalLines += 1;
25
+ // Content: only for completed/failed
26
+ if (log.status === 'completed' || log.status === 'failed') {
27
+ const contentText = log.content ?? '';
28
+ const contentLineCount = contentText.split('\n').length;
29
+ totalLines += Math.min(contentLineCount, baseHeights.maxContentLines ?? 10);
30
+ totalLines += baseHeights.contentBottomMargin;
31
+ }
32
+ // Changes: only for completed
33
+ if (log.status === 'completed') {
34
+ const actualCreated = log.changes.created.length;
35
+ const actualUpdated = log.changes.updated.length;
36
+ // Created section
37
+ if (actualCreated > 0) {
38
+ const createdOverflow = actualCreated > baseHeights.maxChanges.created;
39
+ const createdItemsMax = createdOverflow ? baseHeights.maxChanges.created - 1 : baseHeights.maxChanges.created;
40
+ const displayedCreated = Math.min(actualCreated, createdItemsMax);
41
+ totalLines += displayedCreated + (createdOverflow ? 1 : 0);
42
+ }
43
+ // Updated section
44
+ if (actualUpdated > 0) {
45
+ const updatedOverflow = actualUpdated > baseHeights.maxChanges.updated;
46
+ const updatedItemsMax = updatedOverflow ? baseHeights.maxChanges.updated - 1 : baseHeights.maxChanges.updated;
47
+ const displayedUpdated = Math.min(actualUpdated, updatedItemsMax);
48
+ totalLines += displayedUpdated + (updatedOverflow ? 1 : 0);
49
+ }
50
+ }
51
+ // Bottom margin
52
+ totalLines += baseHeights.bottomMargin;
53
+ return totalLines;
54
+ }
55
+ /**
56
+ * Calculate dynamic space usage for each part of a log
57
+ * Returns array showing how many lines each field uses
58
+ *
59
+ * @param log - The activity log to analyze
60
+ * @param scrollableHeight - Total available height for content area
61
+ * @param baseHeights - Base height configuration from breakpoint
62
+ * @returns Array of { field, lines } showing space breakdown, including calculated content lines
63
+ */
64
+ export function calculateLogContentLimit(log, scrollableHeight, baseHeights) {
65
+ const parts = [];
66
+ parts.push({ field: 'header', lines: baseHeights.header }, { field: 'input', lines: baseHeights.input });
67
+ // Progress - based on actual items
68
+ const actualProgress = log.progress?.length ?? 0;
69
+ const progressLines = Math.min(actualProgress, baseHeights.maxProgressItems);
70
+ if (progressLines > 0) {
71
+ parts.push({ field: 'progress', lines: progressLines });
72
+ }
73
+ // Content bottom margin - only if has content (completed/failed)
74
+ if (log.status === 'completed' || log.status === 'failed') {
75
+ parts.push({ field: 'contentBottomMargin', lines: baseHeights.contentBottomMargin });
76
+ }
77
+ // Changes - only if completed
78
+ if (log.status === 'completed') {
79
+ const actualCreated = log.changes.created.length;
80
+ const actualUpdated = log.changes.updated.length;
81
+ // Created section
82
+ if (actualCreated > 0) {
83
+ const createdOverflow = actualCreated > baseHeights.maxChanges.created;
84
+ const createdItemsMax = createdOverflow ? baseHeights.maxChanges.created - 1 : baseHeights.maxChanges.created;
85
+ const displayedCreated = Math.min(actualCreated, createdItemsMax);
86
+ const createdLines = displayedCreated + (createdOverflow ? 1 : 0);
87
+ parts.push({ field: 'created', lines: createdLines });
88
+ }
89
+ // Updated section
90
+ if (actualUpdated > 0) {
91
+ const updatedOverflow = actualUpdated > baseHeights.maxChanges.updated;
92
+ const updatedItemsMax = updatedOverflow ? baseHeights.maxChanges.updated - 1 : baseHeights.maxChanges.updated;
93
+ const displayedUpdated = Math.min(actualUpdated, updatedItemsMax);
94
+ const updatedLines = displayedUpdated + (updatedOverflow ? 1 : 0);
95
+ parts.push({ field: 'updated', lines: updatedLines });
96
+ }
97
+ }
98
+ // Bottom margin - always present
99
+ parts.push({ field: 'bottomMargin', lines: baseHeights.bottomMargin });
100
+ // Calculate content lines: scrollableHeight minus all other parts
101
+ const otherPartsTotal = parts.reduce((sum, part) => sum + part.lines, 0);
102
+ const contentLines = Math.max(0, scrollableHeight - otherPartsTotal);
103
+ // Insert content field (after progress/spinner, before contentBottomMargin)
104
+ const contentBottomMarginIndex = parts.findIndex((p) => p.field === 'contentBottomMargin');
105
+ if (contentBottomMarginIndex === -1) {
106
+ // If no contentBottomMargin, add before bottomMargin
107
+ const bottomMarginIndex = parts.findIndex((p) => p.field === 'bottomMargin');
108
+ parts.splice(bottomMarginIndex, 0, { field: 'content', lines: contentLines });
109
+ }
110
+ else {
111
+ parts.splice(contentBottomMarginIndex, 0, { field: 'content', lines: contentLines });
112
+ }
113
+ return parts;
114
+ }
@@ -5,6 +5,13 @@
5
5
  * Uses ScrollableList for message history with dynamic height calculation.
6
6
  */
7
7
  import React from 'react';
8
+ /**
9
+ * Props for CommandView component
10
+ *
11
+ * Calculated as: `Math.max(1, terminalHeight - header - tab - footer)`
12
+ * This represents the remaining terminal space after accounting for all UI chrome
13
+ * (header, tab bar, and footer), ensuring at least 1 line is always available.
14
+ */
8
15
  interface CommandViewProps {
9
16
  availableHeight: number;
10
17
  }
@@ -9,81 +9,95 @@ import { Box, Spacer, Text, useApp } from 'ink';
9
9
  import Spinner from 'ink-spinner';
10
10
  import TextInput from 'ink-text-input';
11
11
  import { useCallback, useEffect, useMemo, useState } from 'react';
12
- import { stopConsumer } from '../../infra/cipher/consumer/execution-consumer.js';
13
12
  import { stopQueuePollingService } from '../../infra/cipher/consumer/queue-polling-service.js';
14
13
  import { MessageItem, ScrollableList, Suggestions } from '../components/index.js';
15
14
  import { InlineConfirm, InlineFileSelector, InlineInput, InlineSearch, InlineSelect, } from '../components/inline-prompts/index.js';
16
- import { useAuth } from '../contexts/auth-context.js';
17
- import { useConsumer } from '../contexts/index.js';
18
- import { useCommands, useMode, useTheme } from '../hooks/index.js';
19
- /** Fixed height for bottom area (suggestions + input) */
20
- const BOTTOM_AREA_HEIGHT = 4;
15
+ import { useAuth, useTasks, useTransport } from '../contexts/index.js';
16
+ import { useCommands, useMode, useTerminalBreakpoint, useTheme, useUIHeights } from '../hooks/index.js';
17
+ import { getVisualLineCount } from '../utils/line.js';
21
18
  /** Max visible items in InlineSearch */
22
19
  const INLINE_SEARCH_MAX_ITEMS = 7;
23
- /** Minimum output lines to show before truncation */
24
- const MIN_OUTPUT_LINES = 5;
25
- /** Reserved lines for output box (command header + borders + hint line + margin) */
26
- const OUTPUT_BOX_OVERHEAD = 5;
27
20
  /**
28
- * Count the total number of lines in streaming messages
29
- * Each message can contain multiple lines (newlines in content)
21
+ * Calculate visual line count for a message
30
22
  */
31
- function countOutputLines(messages) {
32
- let total = 0;
33
- for (const msg of messages) {
34
- total += msg.content.split('\n').length;
23
+ function getMessageVisualLineCount(message, terminalWidth) {
24
+ return message.content
25
+ .split('\n')
26
+ .reduce((total, line) => total + getVisualLineCount(line, terminalWidth), 0);
27
+ }
28
+ /**
29
+ * Count total visual lines across all messages
30
+ */
31
+ function countOutputLines(messages, terminalWidth) {
32
+ return messages.reduce((total, msg) => total + getMessageVisualLineCount(msg, terminalWidth), 0);
33
+ }
34
+ /**
35
+ * Truncate message content from the end to fit within available visual lines
36
+ */
37
+ function truncateMessageFromEnd(message, availableLines, terminalWidth) {
38
+ const lines = message.content.split('\n');
39
+ const truncatedLines = [];
40
+ let usedLines = 0;
41
+ // Build from end, taking lines that fit
42
+ for (let i = lines.length - 1; i >= 0; i--) {
43
+ const line = lines[i];
44
+ const lineVisualCount = getVisualLineCount(line, terminalWidth);
45
+ if (usedLines + lineVisualCount <= availableLines) {
46
+ truncatedLines.unshift(line);
47
+ usedLines += lineVisualCount;
48
+ }
49
+ else if (usedLines < availableLines) {
50
+ // Partial line - take last chars that fit
51
+ const remainingLines = availableLines - usedLines;
52
+ const maxChars = remainingLines * terminalWidth;
53
+ truncatedLines.unshift(line.slice(-maxChars));
54
+ usedLines = availableLines;
55
+ break;
56
+ }
57
+ else {
58
+ break;
59
+ }
35
60
  }
36
- return total;
61
+ return { content: truncatedLines.join('\n'), usedLines };
37
62
  }
38
63
  /**
39
- * Get messages from the end that fit within maxLines, truncating from the beginning (shows newest first)
40
- * Used for both completed and live streaming output to always show the latest messages
64
+ * Get messages from end that fit within maxLines (shows newest first)
41
65
  */
42
- function getMessagesFromEnd(messages, maxLines) {
43
- const totalLines = countOutputLines(messages);
66
+ function getMessagesFromEnd(messages, maxLines, terminalWidth) {
67
+ const totalLines = countOutputLines(messages, terminalWidth);
44
68
  if (totalLines <= maxLines) {
45
69
  return { displayMessages: messages, skippedLines: 0, totalLines };
46
70
  }
47
71
  const displayMessages = [];
48
- let lineCount = 0;
49
- // Iterate from the end (newest messages first)
50
- for (let i = messages.length - 1; i >= 0; i--) {
72
+ let usedLines = 0;
73
+ // Iterate from end (newest first)
74
+ for (let i = messages.length - 1; i >= 0 && usedLines < maxLines; i--) {
51
75
  const msg = messages[i];
52
- const msgLineArray = msg.content.split('\n');
53
- const msgLineCount = msgLineArray.length;
54
- if (lineCount + msgLineCount <= maxLines) {
55
- // Message fits completely - prepend to maintain order
76
+ const msgLineCount = getMessageVisualLineCount(msg, terminalWidth);
77
+ const availableLines = maxLines - usedLines;
78
+ if (msgLineCount <= availableLines) {
79
+ // Whole message fits
56
80
  displayMessages.unshift(msg);
57
- lineCount += msgLineCount;
81
+ usedLines += msgLineCount;
58
82
  }
59
- else {
60
- // Message needs to be truncated - show partial lines from the end
61
- const remainingSpace = maxLines - lineCount;
62
- if (remainingSpace > 0) {
63
- // Take only the last lines that fit
64
- const truncatedContent = msgLineArray.slice(-remainingSpace).join('\n');
65
- displayMessages.unshift({
66
- ...msg,
67
- content: truncatedContent,
68
- });
69
- lineCount += remainingSpace;
70
- }
83
+ else if (availableLines > 0) {
84
+ // Truncate message to fit
85
+ const { content, usedLines: truncatedLines } = truncateMessageFromEnd(msg, availableLines, terminalWidth);
86
+ displayMessages.unshift({ ...msg, content });
87
+ usedLines += truncatedLines;
71
88
  break;
72
89
  }
73
90
  }
74
- // Ensure we show at least one line
91
+ // Fallback: show at least last line of last message
75
92
  if (displayMessages.length === 0 && messages.length > 0) {
76
93
  const lastMsg = messages.at(-1);
77
- const lastLines = lastMsg.content.split('\n');
78
- displayMessages.push({
79
- ...lastMsg,
80
- content: lastLines.at(-1) ?? '',
81
- });
82
- lineCount = 1;
94
+ const lastLine = lastMsg.content.split('\n').at(-1) ?? '';
95
+ displayMessages.push({ ...lastMsg, content: lastLine });
96
+ usedLines = getVisualLineCount(lastLine, terminalWidth);
83
97
  }
84
98
  return {
85
99
  displayMessages,
86
- skippedLines: totalLines - lineCount,
100
+ skippedLines: totalLines - usedLines,
87
101
  totalLines,
88
102
  };
89
103
  }
@@ -163,7 +177,7 @@ function estimatePromptHeight(prompt) {
163
177
  * Estimate the line height of a command message
164
178
  */
165
179
  function estimateMessageHeight(msg, options) {
166
- const { isLast = false, maxOutputLines, promptHeight = 0, streamingLines = 0 } = options;
180
+ const { isLast = false, maxOutputLines, promptHeight = 0, streamingLines = 0, terminalWidth } = options;
167
181
  let lines = 0;
168
182
  if (msg.type === 'command') {
169
183
  // Command header with left border
@@ -171,7 +185,7 @@ function estimateMessageHeight(msg, options) {
171
185
  // Output box if present (completed output)
172
186
  if (msg.output && msg.output.length > 0) {
173
187
  // Count actual lines in the output (each message can have multiple lines)
174
- const totalOutputLines = countOutputLines(msg.output);
188
+ const totalOutputLines = countOutputLines(msg.output, terminalWidth);
175
189
  // Account for truncation: show max lines + 1 for hint
176
190
  const displayedLines = totalOutputLines <= maxOutputLines ? totalOutputLines : maxOutputLines + 1;
177
191
  // Border top + content + border bottom
@@ -194,7 +208,8 @@ function estimateMessageHeight(msg, options) {
194
208
  export const CommandView = ({ availableHeight }) => {
195
209
  const { exit } = useApp();
196
210
  const { reloadAuth, reloadBrvConfig } = useAuth();
197
- const { restart } = useConsumer();
211
+ const { client } = useTransport();
212
+ const { clearTasks } = useTasks();
198
213
  const [command, setCommand] = useState('');
199
214
  const [inputKey, setInputKey] = useState(0);
200
215
  const [messages, setMessages] = useState([]);
@@ -202,6 +217,8 @@ export const CommandView = ({ availableHeight }) => {
202
217
  const [activePrompt, setActivePrompt] = useState(null);
203
218
  const [isStreaming, setIsStreaming] = useState(false);
204
219
  const { theme: { colors }, } = useTheme();
220
+ const { commandInput } = useUIHeights();
221
+ const { breakpoint, columns: terminalWidth } = useTerminalBreakpoint();
205
222
  // Process streaming messages to handle action_start/action_stop pairs
206
223
  const processedStreamingMessages = useMemo(() => processMessagesForActions(streamingMessages), [streamingMessages]);
207
224
  const { handleSlashCommand } = useCommands();
@@ -288,24 +305,30 @@ export const CommandView = ({ availableHeight }) => {
288
305
  const needReloadBrvConfig = trimmed.startsWith('/space switch') || trimmed.startsWith('/init');
289
306
  // Refresh state after commands that change auth or project state
290
307
  if (needReloadAuth || needReloadBrvConfig) {
291
- // Stop queue polling and consumer
292
- stopQueuePollingService();
293
- stopConsumer();
294
- // Wait for consumer to stop
295
- setTimeout(async () => {
296
- if (needReloadAuth)
297
- await reloadAuth();
298
- if (needReloadBrvConfig)
299
- await reloadBrvConfig();
300
- await restart();
301
- }, 1000);
308
+ clearTasks();
309
+ if (needReloadAuth)
310
+ await reloadAuth();
311
+ if (needReloadBrvConfig)
312
+ await reloadBrvConfig();
313
+ // Restart agent with appropriate reason
314
+ if (client) {
315
+ const reasonMap = {
316
+ '/init': 'Project initialized',
317
+ '/login': 'User logged in',
318
+ '/logout': 'User logged out',
319
+ '/space switch': 'Space switched',
320
+ };
321
+ const reason = Object.entries(reasonMap).find(([cmd]) => trimmed.startsWith(cmd))?.[1] ?? 'Command executed';
322
+ await client.request('agent:restart', { reason });
323
+ }
302
324
  }
303
325
  }
304
326
  }
305
- }, [exit, handleSlashCommand, reloadAuth, restart]);
327
+ }, [clearTasks, client, exit, handleSlashCommand, reloadAuth, reloadBrvConfig]);
306
328
  const handleSubmit = useCallback(async (value) => {
307
- if (mode === 'console' && !isStreaming)
329
+ if (mode === 'console' && !isStreaming) {
308
330
  await executeCommand(value);
331
+ }
309
332
  }, [executeCommand, isStreaming, mode]);
310
333
  const handleSelect = useCallback(async (value) => {
311
334
  if (!isStreaming)
@@ -350,11 +373,9 @@ export const CommandView = ({ availableHeight }) => {
350
373
  }
351
374
  }, [activePrompt]);
352
375
  // Calculate available height for scrollable content
353
- // Subtract bottom area (suggestions + input)
354
- const scrollableHeight = Math.max(1, availableHeight - BOTTOM_AREA_HEIGHT);
355
- // Calculate max output lines based on available height
356
- // Reserve space for command header, borders, hint line, and margin
357
- const maxOutputLines = Math.max(MIN_OUTPUT_LINES, scrollableHeight - OUTPUT_BOX_OVERHEAD);
376
+ const scrollableHeight = Math.max(1, availableHeight - commandInput);
377
+ // Subtract input + border + indicator lines + indicator page (1 + 2 + 1 + 2)
378
+ const maxOutputLines = scrollableHeight - 6;
358
379
  // Render streaming message (handles ProcessedMessage for action types)
359
380
  const renderStreamingMessage = useCallback((msg) => {
360
381
  // Handle action messages with spinner
@@ -383,7 +404,9 @@ export const CommandView = ({ availableHeight }) => {
383
404
  return (_jsx(InlineConfirm, { default: activePrompt.default, message: activePrompt.message, onConfirm: handleConfirmResponse }));
384
405
  }
385
406
  case 'file_selector': {
386
- return (_jsx(InlineFileSelector, { allowCancel: activePrompt.allowCancel, basePath: activePrompt.basePath, filter: activePrompt.filter, message: activePrompt.message, mode: activePrompt.mode, onSelect: handleFileSelectorResponse, pageSize: activePrompt.pageSize }));
407
+ // availableHeight - more above indicator - input - selector title - selector footer - command input
408
+ const pageSize = availableHeight - 1 - 1 - 4 - 4 - commandInput;
409
+ return (_jsx(InlineFileSelector, { allowCancel: activePrompt.allowCancel, basePath: activePrompt.basePath, filter: activePrompt.filter, message: activePrompt.message, mode: activePrompt.mode, onSelect: handleFileSelectorResponse, pageSize: breakpoint === 'normal' ? pageSize : 2 }));
387
410
  }
388
411
  case 'input': {
389
412
  return (_jsx(InlineInput, { message: activePrompt.message, onSubmit: handleInputResponse, placeholder: activePrompt.placeholder, validate: activePrompt.validate }));
@@ -406,22 +429,21 @@ export const CommandView = ({ availableHeight }) => {
406
429
  handleSearchResponse,
407
430
  handleSelectResponse,
408
431
  ]);
409
- // Render a single message item
410
- // For the last command message during streaming, show live streaming output
411
432
  const renderMessageItem = useCallback((msg, index) => {
412
433
  if (msg.type === 'command') {
413
434
  const hasOutput = msg.output && msg.output.length > 0;
414
435
  const isLastMessage = index === messages.length - 1;
415
436
  const showLiveOutput = isLastMessage && (isStreaming || activePrompt) && (streamingMessages.length > 0 || activePrompt);
416
- return (_jsxs(Box, { flexDirection: "column", marginTop: index === 0 ? 0 : 1, width: "100%", children: [_jsx(Box, { borderBottom: false, borderLeftColor: colors.primary, borderRight: false, borderStyle: "bold", borderTop: false, paddingLeft: 1, children: _jsxs(Text, { color: colors.text, dimColor: true, children: [msg.fromCommand, " ", _jsx(Text, { wrap: "truncate-end", children: msg.content })] }) }), hasOutput &&
437
+ const contentWidth = terminalWidth - 12;
438
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, width: "100%", children: [_jsx(Box, { borderBottom: false, borderLeftColor: colors.primary, borderRight: false, borderStyle: "bold", borderTop: false, paddingLeft: 1, children: _jsxs(Text, { color: colors.text, dimColor: true, children: [msg.fromCommand, " ", _jsx(Text, { wrap: "truncate-end", children: msg.content })] }) }), hasOutput &&
417
439
  (() => {
418
440
  const processedOutput = processMessagesForActions(msg.output);
419
- const { displayMessages, skippedLines } = getMessagesFromEnd(processedOutput, maxOutputLines);
420
- return (_jsxs(Box, { borderColor: colors.border, borderStyle: "round", flexDirection: "column", marginTop: 0, paddingX: 1, width: "100%", children: [skippedLines > 0 && (_jsxs(Text, { color: colors.secondary, dimColor: true, children: ["\u2191 ", skippedLines, " more lines above"] })), displayMessages.map((streamMsg) => renderStreamingMessage(streamMsg))] }));
441
+ const { displayMessages, skippedLines } = getMessagesFromEnd(processedOutput, maxOutputLines, contentWidth);
442
+ return (_jsxs(Box, { borderColor: colors.border, borderStyle: "round", flexDirection: "column", paddingX: 1, width: "100%", children: [skippedLines > 0 && (_jsxs(Text, { color: colors.secondary, dimColor: true, children: ["\u2191 ", skippedLines, " more lines above"] })), displayMessages.map((streamMsg) => renderStreamingMessage(streamMsg))] }));
421
443
  })(), showLiveOutput &&
422
444
  (() => {
423
- const { displayMessages: liveMessages, skippedLines } = getMessagesFromEnd(processedStreamingMessages, maxOutputLines);
424
- return (_jsxs(Box, { borderColor: colors.border, borderStyle: "round", flexDirection: "column", paddingX: 1, paddingY: 0, width: "100%", children: [skippedLines > 0 && (_jsxs(Text, { color: colors.secondary, dimColor: true, children: ["\u2191 ", skippedLines, " more lines above"] })), liveMessages.map((streamMsg) => renderStreamingMessage(streamMsg)), isStreaming && !activePrompt && msg.fromCommand.startsWith('/query') && (_jsxs(Text, { color: colors.dimText, children: [_jsx(Spinner, { type: "dots" }), " Processing..."] })), renderActivePrompt()] }));
445
+ const { displayMessages: liveMessages, skippedLines } = getMessagesFromEnd(processedStreamingMessages, maxOutputLines, contentWidth);
446
+ return (_jsxs(Box, { borderColor: colors.border, borderStyle: "round", flexDirection: "column", paddingX: 1, paddingY: 0, width: "100%", children: [skippedLines > 0 && (_jsxs(Text, { color: colors.secondary, dimColor: true, children: ["\u2191 ", skippedLines, " more lines above"] })), liveMessages.map((streamMsg) => renderStreamingMessage(streamMsg)), isStreaming && !activePrompt && liveMessages.length === 0 && (_jsxs(Text, { color: colors.dimText, children: [_jsx(Spinner, { type: "dots" }), " Processing..."] })), renderActivePrompt()] }));
425
447
  })()] }));
426
448
  }
427
449
  return _jsx(MessageItem, { message: msg });
@@ -445,7 +467,8 @@ export const CommandView = ({ availableHeight }) => {
445
467
  maxOutputLines,
446
468
  promptHeight: isLive ? estimatePromptHeight(activePrompt) : 0,
447
469
  streamingLines: isLive ? streamingMessages.length : 0,
470
+ terminalWidth,
448
471
  });
449
- }, [activePrompt, isStreaming, maxOutputLines, messages.length, streamingMessages.length]);
450
- return (_jsxs(Box, { flexDirection: "column", height: "100%", width: "100%", children: [messages.length > 0 ? (_jsx(Box, { flexDirection: "column", flexGrow: 1, paddingX: 2, children: _jsx(ScrollableList, { autoScrollToBottom: true, availableHeight: scrollableHeight, estimateItemHeight: heightEstimator, isActive: mode === 'console' && !activePrompt && !isStreaming, items: messages, keyExtractor: keyExtractor, renderItem: renderMessageItem }) })) : (_jsx(Spacer, {})), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [!isStreaming && !activePrompt && (_jsx(Suggestions, { input: command, onInsert: handleInsert, onSelect: handleSelect })), _jsxs(Box, { borderColor: colors.border, borderLeft: false, borderRight: false, borderStyle: "single", paddingX: 2, children: [_jsx(Text, { color: colors.primary, children: '> ' }), _jsx(TextInput, { focus: !activePrompt && (mode === 'console' || mode === 'suggestions'), onChange: setCommand, onSubmit: handleSubmit, placeholder: isStreaming ? 'Command running...' : 'Use / to view commands', value: command }, inputKey)] })] })] }));
472
+ }, [activePrompt, isStreaming, maxOutputLines, messages.length, streamingMessages.length, terminalWidth]);
473
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", width: "100%", children: [messages.length > 0 ? (_jsx(Box, { flexDirection: "column", flexGrow: 1, paddingX: 2, children: _jsx(ScrollableList, { autoScrollToBottom: true, availableHeight: scrollableHeight, estimateItemHeight: heightEstimator, isActive: mode === 'console' && !activePrompt && !isStreaming, items: messages, keyExtractor: keyExtractor, renderItem: renderMessageItem }) })) : (_jsx(Spacer, {})), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [!isStreaming && !activePrompt && (_jsx(Suggestions, { input: command, onInsert: handleInsert, onSelect: handleSelect })), _jsxs(Box, { borderColor: colors.border, borderLeft: false, borderRight: false, borderStyle: "single", paddingX: 2, children: [_jsx(Text, { color: colors.primary, children: '> ' }), _jsx(TextInput, { focus: !activePrompt && (mode === 'console' || mode === 'suggestions'), onChange: setCommand, onSubmit: handleSubmit, placeholder: isStreaming ? 'Processing...' : 'Use / to view commands', value: command }, inputKey)] })] })] }));
451
474
  };
@@ -11,12 +11,12 @@ import { Box, Text } from 'ink';
11
11
  import Spinner from 'ink-spinner';
12
12
  import { useState } from 'react';
13
13
  import { EnterPrompt, OutputLog } from '../components/index.js';
14
- import { useAuth, useConsumer } from '../contexts/index.js';
15
- import { useTheme } from '../contexts/use-theme.js';
14
+ import { useAuth, useTasks, useTheme, useTransport } from '../contexts/index.js';
16
15
  export const LoginView = () => {
17
16
  const { theme } = useTheme();
18
17
  const { isLoggingIn, login, loginOutput, reloadAuth } = useAuth();
19
- const { restart } = useConsumer();
18
+ const { client } = useTransport();
19
+ const { clearTasks } = useTasks();
20
20
  const [hasStartedLogin, setHasStartedLogin] = useState(false);
21
21
  // Derive state from props and local state
22
22
  const state = isLoggingIn ? 'loading' : hasStartedLogin ? 'completed' : 'idle';
@@ -24,7 +24,10 @@ export const LoginView = () => {
24
24
  login();
25
25
  setHasStartedLogin(true);
26
26
  } })), state === 'completed' && _jsx(EnterPrompt, { action: "continue", onEnter: async () => {
27
+ clearTasks();
27
28
  await reloadAuth();
28
- await restart();
29
+ if (client) {
30
+ await client.request('agent:restart', { reason: 'User logged in' });
31
+ }
29
32
  } })] }));
30
33
  };
@@ -5,6 +5,19 @@
5
5
  */
6
6
  import React from 'react';
7
7
  interface LogsViewProps {
8
+ /**
9
+ * Available height for the logs view content area (in terminal rows)
10
+ *
11
+ * Calculated as: `terminalHeight - header - tab - footer`
12
+ *
13
+ * This represents the vertical space allocated for scrollable log content
14
+ * after accounting for fixed UI elements (header, tab bar, footer).
15
+ * Internally adjusted to `availableHeight - 1` for border spacing.
16
+ *
17
+ * @example
18
+ * // Terminal: 30 rows, header: 2, tab: 3, footer: 1
19
+ * // availableHeight = 30 - 2 - 3 - 1 = 24 rows for content
20
+ */
8
21
  availableHeight: number;
9
22
  }
10
23
  export declare const LogsView: React.FC<LogsViewProps>;
@@ -7,67 +7,42 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
7
7
  import { Box, Text } from 'ink';
8
8
  import { useCallback } from 'react';
9
9
  import { LogItem, OnboardingFlow, ScrollableList } from '../components/index.js';
10
- import { useActivityLogs, useMode, useTheme } from '../hooks/index.js';
10
+ import { useActivityLogs, useMode, useTheme, useUIHeights } from '../hooks/index.js';
11
11
  import { useOnboarding } from '../hooks/use-onboarding.js';
12
- const MAX_PROGRESS_ITEMS = 3;
13
- /** Minimum content lines to show before truncation */
14
- const MIN_CONTENT_LINES = 5;
15
- /** Reserved lines for log item (header + input box + progress + margins) */
16
- const LOG_ITEM_OVERHEAD = 6;
17
- /**
18
- * Estimate the line height of a log item
19
- */
20
- function estimateLogHeight(log, maxContentLines) {
21
- let lines = 0;
22
- // Header line: [type] @source [timestamp]
23
- lines += 1;
24
- // Input box with border (top border + content + bottom border)
25
- lines += 3;
26
- // Progress items (max MAX_PROGRESS_ITEMS shown + optional "more" line)
27
- const progressCount = Math.min(log.progress?.length ?? 0, MAX_PROGRESS_ITEMS);
28
- lines += progressCount;
29
- if ((log.progress?.length ?? 0) > MAX_PROGRESS_ITEMS) {
30
- lines += 1; // "... and X more" line
31
- }
32
- // Processing spinner (if running)
33
- if (log.status === 'running') {
34
- lines += 1;
35
- }
36
- // Content (if completed or failed)
37
- if (log.status === 'completed' || log.status === 'failed') {
38
- const contentLineCount = log.content?.split('\n').length ?? 0;
39
- // Account for truncation: show max lines + 1 for hint if truncated
40
- const displayedLines = contentLineCount <= maxContentLines ? contentLineCount : maxContentLines + 1;
41
- lines += displayedLines;
42
- }
43
- // Changes sections
44
- if (log.status === 'completed') {
45
- if (log.changes.created.length > 0) {
46
- lines += 1 + log.changes.created.length;
47
- }
48
- if (log.changes.updated.length > 0) {
49
- lines += 1 + log.changes.updated.length;
50
- }
51
- }
52
- // Bottom margin
53
- lines += 1;
54
- return lines;
55
- }
12
+ import { calculateActualLogHeight, calculateLogContentLimit } from '../utils/log.js';
56
13
  export const LogsView = ({ availableHeight }) => {
57
14
  const { theme: { colors }, } = useTheme();
58
15
  const { mode } = useMode();
59
16
  const { logs } = useActivityLogs();
60
17
  const { shouldShowOnboarding } = useOnboarding();
61
- // Calculate max content lines based on available height
62
- const scrollableHeight = Math.max(1, availableHeight - 1);
63
- const maxContentLines = Math.max(MIN_CONTENT_LINES, scrollableHeight - LOG_ITEM_OVERHEAD);
64
- const renderLogItem = useCallback((log) => _jsx(LogItem, { log: log, maxContentLines: maxContentLines, maxProgressItems: MAX_PROGRESS_ITEMS }), [maxContentLines]);
18
+ const { messageItem } = useUIHeights();
19
+ // Calculate scrollable height for dynamic per-log calculations
20
+ const scrollableHeight = Math.max(1, availableHeight);
21
+ const renderLogItem = useCallback((log) => {
22
+ // Calculate dynamic content limit for this specific log
23
+ const parts = calculateLogContentLimit(log, scrollableHeight, messageItem);
24
+ const contentPart = parts.find((p) => p.field === 'content');
25
+ const maxContentLine = contentPart?.lines ?? 0;
26
+ return (_jsx(LogItem, { heights: {
27
+ ...messageItem,
28
+ maxContentLines: maxContentLine,
29
+ }, log: log }));
30
+ }, [messageItem, scrollableHeight]);
65
31
  const keyExtractor = useCallback((log) => log.id, []);
66
- // Height estimator that accounts for content truncation
67
- const heightEstimator = useCallback((log) => estimateLogHeight(log, maxContentLines), [maxContentLines]);
32
+ // Height calculator that returns the actual rendered height of each log item
33
+ const heightEstimator = useCallback((log) => {
34
+ // Calculate dynamic content limit for height estimation
35
+ const parts = calculateLogContentLimit(log, scrollableHeight, messageItem);
36
+ const contentPart = parts.find((p) => p.field === 'content');
37
+ const maxContentLine = contentPart?.lines ?? 0;
38
+ return calculateActualLogHeight(log, {
39
+ ...messageItem,
40
+ maxContentLines: maxContentLine,
41
+ });
42
+ }, [messageItem, scrollableHeight]);
68
43
  // Show onboarding when project is not initialized
69
44
  if (shouldShowOnboarding) {
70
- return _jsx(OnboardingFlow, { availableHeight: scrollableHeight });
45
+ return _jsx(OnboardingFlow, { availableHeight: availableHeight });
71
46
  }
72
47
  return (_jsx(Box, { borderColor: colors.border, borderLeft: false, borderRight: false, borderStyle: "single", borderTop: false, flexDirection: "column", height: "100%", width: "100%", children: logs.length > 0 ? (_jsx(Box, { flexDirection: "column", height: "100%", paddingX: 2, children: _jsx(ScrollableList, { autoScrollToBottom: true, availableHeight: scrollableHeight, estimateItemHeight: heightEstimator, isActive: mode === 'activity', items: logs, keyExtractor: keyExtractor, renderItem: renderLogItem }) })) : (_jsxs(_Fragment, { children: [_jsx(Text, { color: colors.primary, children: "Welcome to ByteRover!" }), _jsx(Text, { color: colors.text, children: "Start by telling your AI Agent what to save or retrieve." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.text, dimColor: true, children: "Press [Tab] to switch to commands view" }) })] })) }));
73
48
  };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Error handler callback type for oclif commands.
3
+ * @param message - Error message to display
4
+ * @param options - Options for the error (exit code, etc.)
5
+ */
6
+ type ErrorCallback = (message: string, options: {
7
+ exit: number;
8
+ }) => never;
9
+ /**
10
+ * Format and handle connection-related errors with user-friendly messages.
11
+ *
12
+ * @param error - The error to handle
13
+ * @param errorCallback - The oclif command's error() method
14
+ */
15
+ export declare function handleConnectionError(error: unknown, errorCallback: ErrorCallback): never;
16
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Shared utility for handling connection errors in CLI commands.
3
+ * Extracted from query.ts and curate.ts to avoid code duplication.
4
+ */
5
+ import { ConnectionError, ConnectionFailedError, InstanceCrashedError, NoInstanceRunningError, } from '../core/domain/errors/connection-error.js';
6
+ import { getSandboxEnvironmentName, isSandboxEnvironment, isSandboxNetworkError } from './sandbox-detector.js';
7
+ /**
8
+ * Format and handle connection-related errors with user-friendly messages.
9
+ *
10
+ * @param error - The error to handle
11
+ * @param errorCallback - The oclif command's error() method
12
+ */
13
+ export function handleConnectionError(error, errorCallback) {
14
+ if (error instanceof NoInstanceRunningError) {
15
+ if (isSandboxEnvironment()) {
16
+ const sandboxName = getSandboxEnvironmentName();
17
+ errorCallback(`Error: No ByteRover instance is running.\n` +
18
+ `⚠️ Sandbox environment detected (${sandboxName}).\n\n` +
19
+ `Please run 'brv' command in a separate terminal window/tab outside the sandbox first.`, { exit: 1 });
20
+ }
21
+ else {
22
+ errorCallback('No ByteRover instance is running.\n\n' +
23
+ 'Start a ByteRover instance by running "brv" in a separate terminal window/tab.\n' +
24
+ 'The instance will keep running and handle your commands.', { exit: 1 });
25
+ }
26
+ }
27
+ if (error instanceof InstanceCrashedError) {
28
+ errorCallback('ByteRover instance has crashed.\n\nPlease restart with: brv', { exit: 1 });
29
+ }
30
+ if (error instanceof ConnectionFailedError) {
31
+ const isSandboxError = isSandboxNetworkError(error.originalError ?? error);
32
+ if (isSandboxError) {
33
+ const sandboxName = getSandboxEnvironmentName();
34
+ errorCallback(`Error: Failed to connect to ByteRover instance.\n` +
35
+ `Port: ${error.port ?? 'unknown'}\n` +
36
+ `⚠️ Sandbox network restriction detected (${sandboxName}).\n\n` +
37
+ `Please allow network access in the sandbox and retry the command.`, { exit: 1 });
38
+ }
39
+ else {
40
+ errorCallback(`Failed to connect to ByteRover instance: ${error.message}`, { exit: 1 });
41
+ }
42
+ }
43
+ if (error instanceof ConnectionError) {
44
+ errorCallback(`Connection error: ${error.message}`, { exit: 1 });
45
+ }
46
+ // Unknown error
47
+ const message = error instanceof Error ? error.message : String(error);
48
+ errorCallback(`Unexpected error: ${message}`, { exit: 1 });
49
+ }