byterover-cli 0.2.1 → 0.3.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 (490) hide show
  1. package/README.md +56 -56
  2. package/bin/dev.js +1 -1
  3. package/dist/commands/cipher-agent/run.d.ts +111 -0
  4. package/dist/commands/cipher-agent/run.js +493 -0
  5. package/dist/commands/cipher-agent/set-prompt.d.ts +14 -0
  6. package/dist/commands/cipher-agent/set-prompt.js +53 -0
  7. package/dist/commands/cipher-agent/show-prompt.d.ts +11 -0
  8. package/dist/commands/cipher-agent/show-prompt.js +48 -0
  9. package/dist/commands/clear.d.ts +6 -0
  10. package/dist/commands/clear.js +36 -15
  11. package/dist/commands/curate.d.ts +74 -0
  12. package/dist/commands/curate.js +396 -0
  13. package/dist/commands/foo.d.ts +12 -0
  14. package/dist/commands/foo.js +61 -0
  15. package/dist/commands/gen-rules.d.ts +3 -0
  16. package/dist/commands/gen-rules.js +39 -20
  17. package/dist/commands/init.d.ts +63 -3
  18. package/dist/commands/init.js +285 -70
  19. package/dist/commands/login.js +9 -4
  20. package/dist/commands/pull.d.ts +33 -0
  21. package/dist/commands/pull.js +115 -0
  22. package/dist/commands/push.d.ts +13 -13
  23. package/dist/commands/push.js +81 -101
  24. package/dist/commands/query.d.ts +63 -0
  25. package/dist/commands/query.js +349 -0
  26. package/dist/commands/space/list.d.ts +5 -2
  27. package/dist/commands/space/list.js +60 -56
  28. package/dist/commands/space/switch.d.ts +16 -0
  29. package/dist/commands/space/switch.js +102 -53
  30. package/dist/commands/status.d.ts +5 -2
  31. package/dist/commands/status.js +43 -33
  32. package/dist/commands/watch.d.ts +23 -0
  33. package/dist/commands/watch.js +171 -0
  34. package/dist/config/auth.config.js +14 -2
  35. package/dist/config/context-tree-domains.d.ts +12 -0
  36. package/dist/config/context-tree-domains.js +29 -0
  37. package/dist/config/environment.d.ts +6 -0
  38. package/dist/config/environment.js +9 -2
  39. package/dist/constants.d.ts +5 -0
  40. package/dist/constants.js +6 -0
  41. package/dist/core/domain/cipher/agent/agent-state-machine.d.ts +128 -0
  42. package/dist/core/domain/cipher/agent/agent-state-machine.js +183 -0
  43. package/dist/core/domain/cipher/agent/agent-state.d.ts +77 -0
  44. package/dist/core/domain/cipher/agent/agent-state.js +59 -0
  45. package/dist/core/domain/cipher/agent/index.d.ts +7 -0
  46. package/dist/core/domain/cipher/agent/index.js +7 -0
  47. package/dist/core/domain/cipher/agent-events/index.d.ts +8 -0
  48. package/dist/core/domain/cipher/agent-events/index.js +7 -0
  49. package/dist/core/domain/cipher/agent-events/types.d.ts +419 -0
  50. package/dist/core/domain/cipher/agent-events/types.js +42 -0
  51. package/dist/core/domain/cipher/blob/types.d.ts +108 -0
  52. package/dist/core/domain/cipher/errors/blob-error.d.ts +36 -0
  53. package/dist/core/domain/cipher/errors/blob-error.js +68 -0
  54. package/dist/core/domain/cipher/errors/file-system-error.d.ts +211 -0
  55. package/dist/core/domain/cipher/errors/file-system-error.js +291 -0
  56. package/dist/core/domain/cipher/errors/llm-error.d.ts +120 -0
  57. package/dist/core/domain/cipher/errors/llm-error.js +161 -0
  58. package/dist/core/domain/cipher/errors/memory-error.d.ts +35 -0
  59. package/dist/core/domain/cipher/errors/memory-error.js +62 -0
  60. package/dist/core/domain/cipher/errors/process-error-code.d.ts +97 -0
  61. package/dist/core/domain/cipher/errors/process-error-code.js +98 -0
  62. package/dist/core/domain/cipher/errors/process-error.d.ts +135 -0
  63. package/dist/core/domain/cipher/errors/process-error.js +173 -0
  64. package/dist/core/domain/cipher/errors/session-error.d.ts +56 -0
  65. package/dist/core/domain/cipher/errors/session-error.js +74 -0
  66. package/dist/core/domain/cipher/errors/tool-error.d.ts +57 -0
  67. package/dist/core/domain/cipher/errors/tool-error.js +81 -0
  68. package/dist/core/domain/cipher/file-system/types.d.ts +203 -0
  69. package/dist/core/domain/cipher/memory/types.d.ts +102 -0
  70. package/dist/core/domain/cipher/memory/types.js +4 -0
  71. package/dist/core/domain/cipher/parsed-interaction.d.ts +47 -0
  72. package/dist/core/domain/cipher/parsed-interaction.js +25 -0
  73. package/dist/core/domain/cipher/process/types.d.ts +286 -0
  74. package/dist/core/domain/cipher/session/types.d.ts +54 -0
  75. package/dist/core/domain/cipher/storage/history-types.d.ts +38 -0
  76. package/dist/core/domain/cipher/system-prompt/types.d.ts +131 -0
  77. package/dist/core/domain/cipher/todos/index.d.ts +4 -0
  78. package/dist/core/domain/cipher/todos/index.js +4 -0
  79. package/dist/core/domain/cipher/todos/types.d.ts +57 -0
  80. package/dist/core/domain/cipher/todos/types.js +5 -0
  81. package/dist/core/domain/cipher/tools/constants.d.ts +28 -0
  82. package/dist/core/domain/cipher/tools/constants.js +24 -0
  83. package/dist/core/domain/cipher/tools/tool-error.d.ts +183 -0
  84. package/dist/core/domain/cipher/tools/tool-error.js +246 -0
  85. package/dist/core/domain/cipher/tools/types.d.ts +145 -0
  86. package/dist/core/domain/entities/brv-config.d.ts +42 -6
  87. package/dist/core/domain/entities/brv-config.js +115 -17
  88. package/dist/core/domain/entities/cogit-push-context.d.ts +38 -0
  89. package/dist/core/domain/entities/cogit-push-context.js +91 -0
  90. package/dist/core/domain/entities/cogit-push-response.d.ts +20 -0
  91. package/dist/core/domain/entities/cogit-push-response.js +31 -0
  92. package/dist/core/domain/entities/cogit-snapshot-author.d.ts +24 -0
  93. package/dist/core/domain/entities/cogit-snapshot-author.js +39 -0
  94. package/dist/core/domain/entities/cogit-snapshot-file.d.ts +34 -0
  95. package/dist/core/domain/entities/cogit-snapshot-file.js +59 -0
  96. package/dist/core/domain/entities/cogit-snapshot.d.ts +31 -0
  97. package/dist/core/domain/entities/cogit-snapshot.js +58 -0
  98. package/dist/core/domain/entities/context-tree-index.d.ts +26 -0
  99. package/dist/core/domain/entities/context-tree-index.js +27 -0
  100. package/dist/core/domain/entities/context-tree-snapshot.d.ts +56 -0
  101. package/dist/core/domain/entities/context-tree-snapshot.js +83 -0
  102. package/dist/core/domain/entities/event.d.ts +1 -1
  103. package/dist/core/domain/entities/event.js +3 -1
  104. package/dist/core/domain/entities/parser.d.ts +567 -0
  105. package/dist/core/domain/entities/parser.js +10 -0
  106. package/dist/core/domain/entities/playbook.d.ts +2 -23
  107. package/dist/core/domain/entities/playbook.js +2 -70
  108. package/dist/core/domain/errors/brv-config-version-error.d.ts +16 -0
  109. package/dist/core/domain/errors/brv-config-version-error.js +21 -0
  110. package/dist/core/domain/knowledge/directory-manager.d.ts +80 -0
  111. package/dist/core/domain/knowledge/directory-manager.js +145 -0
  112. package/dist/core/domain/knowledge/markdown-writer.d.ts +18 -0
  113. package/dist/core/domain/knowledge/markdown-writer.js +18 -0
  114. package/dist/core/domain/knowledge/relation-parser.d.ts +90 -0
  115. package/dist/core/domain/knowledge/relation-parser.js +131 -0
  116. package/dist/core/interfaces/cipher/cipher-services.d.ts +71 -0
  117. package/dist/core/interfaces/cipher/cipher-services.js +1 -0
  118. package/dist/core/interfaces/cipher/i-blob-storage.d.ts +78 -0
  119. package/dist/core/interfaces/cipher/i-blob-storage.js +1 -0
  120. package/dist/core/interfaces/cipher/i-chat-session.d.ts +62 -0
  121. package/dist/core/interfaces/cipher/i-chat-session.js +1 -0
  122. package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +88 -0
  123. package/dist/core/interfaces/cipher/i-cipher-agent.js +1 -0
  124. package/dist/core/interfaces/cipher/i-coding-agent-log-parser.d.ts +20 -0
  125. package/dist/core/interfaces/cipher/i-coding-agent-log-parser.js +1 -0
  126. package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.d.ts +31 -0
  127. package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.js +1 -0
  128. package/dist/core/interfaces/cipher/i-content-generator.d.ts +120 -0
  129. package/dist/core/interfaces/cipher/i-content-generator.js +12 -0
  130. package/dist/core/interfaces/cipher/i-event-emitter.d.ts +76 -0
  131. package/dist/core/interfaces/cipher/i-event-emitter.js +1 -0
  132. package/dist/core/interfaces/cipher/i-file-system.d.ts +68 -0
  133. package/dist/core/interfaces/cipher/i-file-system.js +1 -0
  134. package/dist/core/interfaces/cipher/i-history-storage.d.ts +53 -0
  135. package/dist/core/interfaces/cipher/i-history-storage.js +1 -0
  136. package/dist/core/interfaces/cipher/i-llm-provider.d.ts +14 -0
  137. package/dist/core/interfaces/cipher/i-llm-provider.js +1 -0
  138. package/dist/core/interfaces/cipher/i-llm-service.d.ts +62 -0
  139. package/dist/core/interfaces/cipher/i-llm-service.js +1 -0
  140. package/dist/core/interfaces/cipher/i-logger.d.ts +78 -0
  141. package/dist/core/interfaces/cipher/i-logger.js +28 -0
  142. package/dist/core/interfaces/cipher/i-message-formatter.d.ts +44 -0
  143. package/dist/core/interfaces/cipher/i-message-formatter.js +1 -0
  144. package/dist/core/interfaces/cipher/i-policy-engine.d.ts +102 -0
  145. package/dist/core/interfaces/cipher/i-policy-engine.js +9 -0
  146. package/dist/core/interfaces/cipher/i-process-service.d.ts +65 -0
  147. package/dist/core/interfaces/cipher/i-process-service.js +1 -0
  148. package/dist/core/interfaces/cipher/i-system-prompt-contributor.d.ts +25 -0
  149. package/dist/core/interfaces/cipher/i-system-prompt-contributor.js +1 -0
  150. package/dist/core/interfaces/cipher/i-tokenizer.d.ts +15 -0
  151. package/dist/core/interfaces/cipher/i-tokenizer.js +1 -0
  152. package/dist/core/interfaces/cipher/i-tool-provider.d.ts +64 -0
  153. package/dist/core/interfaces/cipher/i-tool-provider.js +1 -0
  154. package/dist/core/interfaces/cipher/i-tool-scheduler.d.ts +103 -0
  155. package/dist/core/interfaces/cipher/i-tool-scheduler.js +11 -0
  156. package/dist/core/interfaces/cipher/llm-types.d.ts +46 -0
  157. package/dist/core/interfaces/cipher/llm-types.js +5 -0
  158. package/dist/core/interfaces/cipher/message-types.d.ts +118 -0
  159. package/dist/core/interfaces/cipher/message-types.js +5 -0
  160. package/dist/core/interfaces/cipher/tokenizer-types.d.ts +11 -0
  161. package/dist/core/interfaces/cipher/tokenizer-types.js +14 -0
  162. package/dist/core/interfaces/i-cogit-pull-service.d.ts +24 -0
  163. package/dist/core/interfaces/i-cogit-pull-service.js +1 -0
  164. package/dist/core/interfaces/i-cogit-push-service.d.ts +27 -0
  165. package/dist/core/interfaces/i-cogit-push-service.js +1 -0
  166. package/dist/core/interfaces/i-context-file-reader.d.ts +32 -0
  167. package/dist/core/interfaces/i-context-file-reader.js +1 -0
  168. package/dist/core/interfaces/i-context-tree-service.d.ts +21 -0
  169. package/dist/core/interfaces/i-context-tree-service.js +1 -0
  170. package/dist/core/interfaces/i-context-tree-snapshot-service.d.ts +36 -0
  171. package/dist/core/interfaces/i-context-tree-snapshot-service.js +1 -0
  172. package/dist/core/interfaces/i-context-tree-writer-service.d.ts +32 -0
  173. package/dist/core/interfaces/i-context-tree-writer-service.js +1 -0
  174. package/dist/core/interfaces/i-file-watcher-service.d.ts +41 -0
  175. package/dist/core/interfaces/i-file-watcher-service.js +1 -0
  176. package/dist/core/interfaces/parser/i-clean-parser-service.d.ts +18 -0
  177. package/dist/core/interfaces/parser/i-clean-parser-service.js +1 -0
  178. package/dist/core/interfaces/parser/i-raw-parser-service.d.ts +17 -0
  179. package/dist/core/interfaces/parser/i-raw-parser-service.js +1 -0
  180. package/dist/core/interfaces/parser/i-session-normalizer.d.ts +56 -0
  181. package/dist/core/interfaces/parser/i-session-normalizer.js +1 -0
  182. package/dist/hooks/command_not_found/handle-invalid-commands.d.ts +7 -0
  183. package/dist/hooks/command_not_found/handle-invalid-commands.js +32 -0
  184. package/dist/hooks/error/clean-errors.d.ts +7 -0
  185. package/dist/hooks/error/clean-errors.js +50 -0
  186. package/dist/hooks/init/welcome.js +72 -1
  187. package/dist/hooks/prerun/validate-brv-config-version.d.ts +28 -0
  188. package/dist/hooks/prerun/validate-brv-config-version.js +43 -0
  189. package/dist/infra/cipher/agent-service-factory.d.ts +86 -0
  190. package/dist/infra/cipher/agent-service-factory.js +212 -0
  191. package/dist/infra/cipher/blob/blob-storage-factory.d.ts +13 -0
  192. package/dist/infra/cipher/blob/blob-storage-factory.js +14 -0
  193. package/dist/infra/cipher/blob/index.d.ts +10 -0
  194. package/dist/infra/cipher/blob/index.js +12 -0
  195. package/dist/infra/cipher/blob/migrations.d.ts +63 -0
  196. package/dist/infra/cipher/blob/migrations.js +148 -0
  197. package/dist/infra/cipher/blob/sqlite-blob-storage.d.ts +82 -0
  198. package/dist/infra/cipher/blob/sqlite-blob-storage.js +307 -0
  199. package/dist/infra/cipher/cipher-agent-state-manager.d.ts +63 -0
  200. package/dist/infra/cipher/cipher-agent-state-manager.js +108 -0
  201. package/dist/infra/cipher/cipher-agent.d.ts +182 -0
  202. package/dist/infra/cipher/cipher-agent.js +317 -0
  203. package/dist/infra/cipher/command-parser.d.ts +23 -0
  204. package/dist/infra/cipher/command-parser.js +85 -0
  205. package/dist/infra/cipher/display/todo-display.d.ts +23 -0
  206. package/dist/infra/cipher/display/todo-display.js +129 -0
  207. package/dist/infra/cipher/events/event-emitter.d.ts +137 -0
  208. package/dist/infra/cipher/events/event-emitter.js +158 -0
  209. package/dist/infra/cipher/exit-codes.d.ts +44 -0
  210. package/dist/infra/cipher/exit-codes.js +58 -0
  211. package/dist/infra/cipher/file-system/file-system-service.d.ts +105 -0
  212. package/dist/infra/cipher/file-system/file-system-service.js +641 -0
  213. package/dist/infra/cipher/file-system/gitignore-filter.d.ts +77 -0
  214. package/dist/infra/cipher/file-system/gitignore-filter.js +120 -0
  215. package/dist/infra/cipher/file-system/glob-utils.d.ts +60 -0
  216. package/dist/infra/cipher/file-system/glob-utils.js +120 -0
  217. package/dist/infra/cipher/file-system/path-validator.d.ts +69 -0
  218. package/dist/infra/cipher/file-system/path-validator.js +184 -0
  219. package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +149 -0
  220. package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +364 -0
  221. package/dist/infra/cipher/grpc/internal-llm-grpc.proto +94 -0
  222. package/dist/infra/cipher/interactive-commands.d.ts +16 -0
  223. package/dist/infra/cipher/interactive-commands.js +198 -0
  224. package/dist/infra/cipher/interactive-loop.d.ts +24 -0
  225. package/dist/infra/cipher/interactive-loop.js +352 -0
  226. package/dist/infra/cipher/llm/context/async-mutex.d.ts +59 -0
  227. package/dist/infra/cipher/llm/context/async-mutex.js +92 -0
  228. package/dist/infra/cipher/llm/context/compression/index.d.ts +6 -0
  229. package/dist/infra/cipher/llm/context/compression/index.js +5 -0
  230. package/dist/infra/cipher/llm/context/compression/middle-removal.d.ts +40 -0
  231. package/dist/infra/cipher/llm/context/compression/middle-removal.js +76 -0
  232. package/dist/infra/cipher/llm/context/compression/oldest-removal.d.ts +38 -0
  233. package/dist/infra/cipher/llm/context/compression/oldest-removal.js +53 -0
  234. package/dist/infra/cipher/llm/context/compression/types.d.ts +36 -0
  235. package/dist/infra/cipher/llm/context/compression/types.js +1 -0
  236. package/dist/infra/cipher/llm/context/context-manager.d.ts +234 -0
  237. package/dist/infra/cipher/llm/context/context-manager.js +419 -0
  238. package/dist/infra/cipher/llm/context/index.d.ts +2 -0
  239. package/dist/infra/cipher/llm/context/index.js +2 -0
  240. package/dist/infra/cipher/llm/context/loop-detector.d.ts +125 -0
  241. package/dist/infra/cipher/llm/context/loop-detector.js +194 -0
  242. package/dist/infra/cipher/llm/context/utils.d.ts +17 -0
  243. package/dist/infra/cipher/llm/context/utils.js +89 -0
  244. package/dist/infra/cipher/llm/formatters/claude-formatter.d.ts +54 -0
  245. package/dist/infra/cipher/llm/formatters/claude-formatter.js +182 -0
  246. package/dist/infra/cipher/llm/formatters/gemini-formatter.d.ts +69 -0
  247. package/dist/infra/cipher/llm/formatters/gemini-formatter.js +253 -0
  248. package/dist/infra/cipher/llm/formatters/openrouter-formatter.d.ts +47 -0
  249. package/dist/infra/cipher/llm/formatters/openrouter-formatter.js +238 -0
  250. package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +92 -0
  251. package/dist/infra/cipher/llm/generators/byterover-content-generator.js +211 -0
  252. package/dist/infra/cipher/llm/generators/index.d.ts +13 -0
  253. package/dist/infra/cipher/llm/generators/index.js +13 -0
  254. package/dist/infra/cipher/llm/generators/logging-content-generator.d.ts +104 -0
  255. package/dist/infra/cipher/llm/generators/logging-content-generator.js +182 -0
  256. package/dist/infra/cipher/llm/generators/openrouter-content-generator.d.ts +93 -0
  257. package/dist/infra/cipher/llm/generators/openrouter-content-generator.js +254 -0
  258. package/dist/infra/cipher/llm/generators/retryable-content-generator.d.ts +90 -0
  259. package/dist/infra/cipher/llm/generators/retryable-content-generator.js +157 -0
  260. package/dist/infra/cipher/llm/index.d.ts +9 -0
  261. package/dist/infra/cipher/llm/index.js +13 -0
  262. package/dist/infra/cipher/llm/internal-llm-service.d.ts +308 -0
  263. package/dist/infra/cipher/llm/internal-llm-service.js +724 -0
  264. package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +183 -0
  265. package/dist/infra/cipher/llm/openrouter-llm-service.js +386 -0
  266. package/dist/infra/cipher/llm/response-validator.d.ts +89 -0
  267. package/dist/infra/cipher/llm/response-validator.js +157 -0
  268. package/dist/infra/cipher/llm/retry/index.d.ts +10 -0
  269. package/dist/infra/cipher/llm/retry/index.js +10 -0
  270. package/dist/infra/cipher/llm/retry/retry-policy.d.ts +74 -0
  271. package/dist/infra/cipher/llm/retry/retry-policy.js +146 -0
  272. package/dist/infra/cipher/llm/retry/retry-with-backoff.d.ts +113 -0
  273. package/dist/infra/cipher/llm/retry/retry-with-backoff.js +247 -0
  274. package/dist/infra/cipher/llm/thought-parser.d.ts +145 -0
  275. package/dist/infra/cipher/llm/thought-parser.js +190 -0
  276. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.d.ts +47 -0
  277. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.js +55 -0
  278. package/dist/infra/cipher/llm/tokenizers/default-tokenizer.d.ts +31 -0
  279. package/dist/infra/cipher/llm/tokenizers/default-tokenizer.js +38 -0
  280. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.d.ts +37 -0
  281. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.js +45 -0
  282. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.d.ts +29 -0
  283. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.js +37 -0
  284. package/dist/infra/cipher/llm/tool-output-processor.d.ts +117 -0
  285. package/dist/infra/cipher/llm/tool-output-processor.js +153 -0
  286. package/dist/infra/cipher/logger/console-logger.d.ts +42 -0
  287. package/dist/infra/cipher/logger/console-logger.js +63 -0
  288. package/dist/infra/cipher/logger/event-based-logger.d.ts +54 -0
  289. package/dist/infra/cipher/logger/event-based-logger.js +92 -0
  290. package/dist/infra/cipher/memory/index.d.ts +6 -0
  291. package/dist/infra/cipher/memory/index.js +7 -0
  292. package/dist/infra/cipher/memory/memory-manager.d.ts +136 -0
  293. package/dist/infra/cipher/memory/memory-manager.js +523 -0
  294. package/dist/infra/cipher/parsers/coding-agent-log-parser.d.ts +24 -0
  295. package/dist/infra/cipher/parsers/coding-agent-log-parser.js +51 -0
  296. package/dist/infra/cipher/process/command-validator.d.ts +59 -0
  297. package/dist/infra/cipher/process/command-validator.js +266 -0
  298. package/dist/infra/cipher/process/index.d.ts +8 -0
  299. package/dist/infra/cipher/process/index.js +8 -0
  300. package/dist/infra/cipher/process/process-service.d.ts +95 -0
  301. package/dist/infra/cipher/process/process-service.js +439 -0
  302. package/dist/infra/cipher/session/chat-session.d.ts +80 -0
  303. package/dist/infra/cipher/session/chat-session.js +165 -0
  304. package/dist/infra/cipher/session/index.d.ts +6 -0
  305. package/dist/infra/cipher/session/index.js +5 -0
  306. package/dist/infra/cipher/session/session-event-forwarder.d.ts +37 -0
  307. package/dist/infra/cipher/session/session-event-forwarder.js +83 -0
  308. package/dist/infra/cipher/session/session-manager.d.ts +109 -0
  309. package/dist/infra/cipher/session/session-manager.js +172 -0
  310. package/dist/infra/cipher/storage/blob-history-storage.d.ts +76 -0
  311. package/dist/infra/cipher/storage/blob-history-storage.js +178 -0
  312. package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +105 -0
  313. package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +290 -0
  314. package/dist/infra/cipher/tools/core-tool-scheduler.d.ts +99 -0
  315. package/dist/infra/cipher/tools/core-tool-scheduler.js +161 -0
  316. package/dist/infra/cipher/tools/default-policy-rules.d.ts +26 -0
  317. package/dist/infra/cipher/tools/default-policy-rules.js +125 -0
  318. package/dist/infra/cipher/tools/implementations/bash-exec-tool.d.ts +12 -0
  319. package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +93 -0
  320. package/dist/infra/cipher/tools/implementations/bash-output-tool.d.ts +12 -0
  321. package/dist/infra/cipher/tools/implementations/bash-output-tool.js +47 -0
  322. package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.d.ts +11 -0
  323. package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.js +142 -0
  324. package/dist/infra/cipher/tools/implementations/delete-memory-tool.d.ts +12 -0
  325. package/dist/infra/cipher/tools/implementations/delete-memory-tool.js +37 -0
  326. package/dist/infra/cipher/tools/implementations/detect-domains-tool.d.ts +7 -0
  327. package/dist/infra/cipher/tools/implementations/detect-domains-tool.js +73 -0
  328. package/dist/infra/cipher/tools/implementations/edit-file-tool.d.ts +13 -0
  329. package/dist/infra/cipher/tools/implementations/edit-file-tool.js +50 -0
  330. package/dist/infra/cipher/tools/implementations/edit-memory-tool.d.ts +13 -0
  331. package/dist/infra/cipher/tools/implementations/edit-memory-tool.js +53 -0
  332. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.d.ts +7 -0
  333. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +421 -0
  334. package/dist/infra/cipher/tools/implementations/glob-files-tool.d.ts +18 -0
  335. package/dist/infra/cipher/tools/implementations/glob-files-tool.js +70 -0
  336. package/dist/infra/cipher/tools/implementations/grep-content-tool.d.ts +12 -0
  337. package/dist/infra/cipher/tools/implementations/grep-content-tool.js +77 -0
  338. package/dist/infra/cipher/tools/implementations/kill-process-tool.d.ts +12 -0
  339. package/dist/infra/cipher/tools/implementations/kill-process-tool.js +55 -0
  340. package/dist/infra/cipher/tools/implementations/list-memories-tool.d.ts +12 -0
  341. package/dist/infra/cipher/tools/implementations/list-memories-tool.js +63 -0
  342. package/dist/infra/cipher/tools/implementations/read-file-tool.d.ts +12 -0
  343. package/dist/infra/cipher/tools/implementations/read-file-tool.js +54 -0
  344. package/dist/infra/cipher/tools/implementations/read-memory-tool.d.ts +12 -0
  345. package/dist/infra/cipher/tools/implementations/read-memory-tool.js +39 -0
  346. package/dist/infra/cipher/tools/implementations/search-history-tool.d.ts +10 -0
  347. package/dist/infra/cipher/tools/implementations/search-history-tool.js +36 -0
  348. package/dist/infra/cipher/tools/implementations/write-file-tool.d.ts +12 -0
  349. package/dist/infra/cipher/tools/implementations/write-file-tool.js +52 -0
  350. package/dist/infra/cipher/tools/implementations/write-memory-tool.d.ts +13 -0
  351. package/dist/infra/cipher/tools/implementations/write-memory-tool.js +52 -0
  352. package/dist/infra/cipher/tools/implementations/write-todos-tool.d.ts +10 -0
  353. package/dist/infra/cipher/tools/implementations/write-todos-tool.js +165 -0
  354. package/dist/infra/cipher/tools/index.d.ts +18 -0
  355. package/dist/infra/cipher/tools/index.js +19 -0
  356. package/dist/infra/cipher/tools/policy-engine.d.ts +80 -0
  357. package/dist/infra/cipher/tools/policy-engine.js +110 -0
  358. package/dist/infra/cipher/tools/tool-invocation-queue.d.ts +191 -0
  359. package/dist/infra/cipher/tools/tool-invocation-queue.js +254 -0
  360. package/dist/infra/cipher/tools/tool-invocation.d.ts +216 -0
  361. package/dist/infra/cipher/tools/tool-invocation.js +294 -0
  362. package/dist/infra/cipher/tools/tool-manager.d.ts +135 -0
  363. package/dist/infra/cipher/tools/tool-manager.js +209 -0
  364. package/dist/infra/cipher/tools/tool-markers.d.ts +48 -0
  365. package/dist/infra/cipher/tools/tool-markers.js +49 -0
  366. package/dist/infra/cipher/tools/tool-provider.d.ts +77 -0
  367. package/dist/infra/cipher/tools/tool-provider.js +196 -0
  368. package/dist/infra/cipher/tools/tool-registry.d.ts +52 -0
  369. package/dist/infra/cipher/tools/tool-registry.js +144 -0
  370. package/dist/infra/cipher/tools/utils/schema-converter.d.ts +10 -0
  371. package/dist/infra/cipher/tools/utils/schema-converter.js +29 -0
  372. package/dist/infra/cipher/validation/workspace-validator.d.ts +19 -0
  373. package/dist/infra/cipher/validation/workspace-validator.js +37 -0
  374. package/dist/infra/cipher/watcher/coding-agent-log-watcher.d.ts +14 -0
  375. package/dist/infra/cipher/watcher/coding-agent-log-watcher.js +55 -0
  376. package/dist/infra/cogit/context-tree-to-push-context-mapper.d.ts +21 -0
  377. package/dist/infra/cogit/context-tree-to-push-context-mapper.js +32 -0
  378. package/dist/infra/cogit/http-cogit-pull-service.d.ts +15 -0
  379. package/dist/infra/cogit/http-cogit-pull-service.js +30 -0
  380. package/dist/infra/cogit/http-cogit-push-service.d.ts +17 -0
  381. package/dist/infra/cogit/http-cogit-push-service.js +104 -0
  382. package/dist/infra/config/file-config-store.js +9 -3
  383. package/dist/infra/context-tree/file-context-file-reader.d.ts +14 -0
  384. package/dist/infra/context-tree/file-context-file-reader.js +46 -0
  385. package/dist/infra/context-tree/file-context-tree-service.d.ts +14 -0
  386. package/dist/infra/context-tree/file-context-tree-service.js +46 -0
  387. package/dist/infra/context-tree/file-context-tree-snapshot-service.d.ts +34 -0
  388. package/dist/infra/context-tree/file-context-tree-snapshot-service.js +117 -0
  389. package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +22 -0
  390. package/dist/infra/context-tree/file-context-tree-writer-service.js +61 -0
  391. package/dist/infra/memory/http-memory-retrieval-service.js +2 -1
  392. package/dist/infra/memory/http-memory-storage-service.js +4 -3
  393. package/dist/infra/parsers/clean/clean-claude-service.d.ts +111 -0
  394. package/dist/infra/parsers/clean/clean-claude-service.js +271 -0
  395. package/dist/infra/parsers/clean/clean-codex-service.d.ts +231 -0
  396. package/dist/infra/parsers/clean/clean-codex-service.js +534 -0
  397. package/dist/infra/parsers/clean/clean-copilot-service.d.ts +255 -0
  398. package/dist/infra/parsers/clean/clean-copilot-service.js +729 -0
  399. package/dist/infra/parsers/clean/clean-cursor-service.d.ts +161 -0
  400. package/dist/infra/parsers/clean/clean-cursor-service.js +432 -0
  401. package/dist/infra/parsers/clean/clean-parser-service-factory.d.ts +54 -0
  402. package/dist/infra/parsers/clean/clean-parser-service-factory.js +80 -0
  403. package/dist/infra/parsers/clean/shared.d.ts +84 -0
  404. package/dist/infra/parsers/clean/shared.js +273 -0
  405. package/dist/infra/parsers/raw/raw-claude-service.d.ts +195 -0
  406. package/dist/infra/parsers/raw/raw-claude-service.js +548 -0
  407. package/dist/infra/parsers/raw/raw-codex-service.d.ts +313 -0
  408. package/dist/infra/parsers/raw/raw-codex-service.js +782 -0
  409. package/dist/infra/parsers/raw/raw-copilot-service.d.ts +196 -0
  410. package/dist/infra/parsers/raw/raw-copilot-service.js +558 -0
  411. package/dist/infra/parsers/raw/raw-cursor-service.d.ts +316 -0
  412. package/dist/infra/parsers/raw/raw-cursor-service.js +818 -0
  413. package/dist/infra/parsers/raw/raw-parser-service-factory.d.ts +54 -0
  414. package/dist/infra/parsers/raw/raw-parser-service-factory.js +81 -0
  415. package/dist/infra/space/http-space-service.js +2 -1
  416. package/dist/infra/team/http-team-service.js +2 -1
  417. package/dist/infra/user/http-user-service.js +2 -1
  418. package/dist/infra/watcher/file-watcher-service.d.ts +10 -0
  419. package/dist/infra/watcher/file-watcher-service.js +81 -0
  420. package/dist/infra/workspace/workspace-detector-service.d.ts +60 -0
  421. package/dist/infra/workspace/workspace-detector-service.js +165 -0
  422. package/dist/resources/prompts/curate-context-tree-curation.yml +48 -0
  423. package/dist/resources/prompts/modes/autonomous.yml +9 -0
  424. package/dist/resources/prompts/query-context-tree-retrieval.yml +49 -0
  425. package/dist/resources/prompts/reflection.yml +27 -0
  426. package/dist/resources/prompts/system-prompt.yml +82 -0
  427. package/dist/resources/prompts/tool-outputs.yml +30 -0
  428. package/dist/templates/README.md +6 -7
  429. package/dist/templates/sections/command-reference.md +40 -111
  430. package/dist/templates/sections/workflow.md +3 -30
  431. package/dist/utils/emoji-helpers.d.ts +38 -0
  432. package/dist/utils/emoji-helpers.js +42 -0
  433. package/dist/utils/error-handler.d.ts +51 -0
  434. package/dist/utils/error-handler.js +169 -0
  435. package/dist/utils/error-helpers.d.ts +30 -0
  436. package/dist/utils/error-helpers.js +47 -0
  437. package/dist/utils/file-helpers.d.ts +15 -0
  438. package/dist/utils/file-helpers.js +44 -0
  439. package/dist/utils/oclif-error-helpers.d.ts +40 -0
  440. package/dist/utils/oclif-error-helpers.js +46 -0
  441. package/dist/utils/tool-display-formatter.d.ts +53 -0
  442. package/dist/utils/tool-display-formatter.js +257 -0
  443. package/oclif.manifest.json +381 -141
  444. package/package.json +27 -6
  445. package/dist/commands/add.d.ts +0 -49
  446. package/dist/commands/add.js +0 -192
  447. package/dist/commands/complete.d.ts +0 -108
  448. package/dist/commands/complete.js +0 -340
  449. package/dist/commands/retrieve.d.ts +0 -26
  450. package/dist/commands/retrieve.js +0 -101
  451. package/dist/core/domain/entities/curator-output.d.ts +0 -14
  452. package/dist/core/domain/entities/curator-output.js +0 -23
  453. package/dist/core/domain/entities/delta-batch.d.ts +0 -30
  454. package/dist/core/domain/entities/delta-batch.js +0 -52
  455. package/dist/core/domain/entities/delta-operation.d.ts +0 -31
  456. package/dist/core/domain/entities/delta-operation.js +0 -50
  457. package/dist/core/domain/entities/executor-output.d.ts +0 -27
  458. package/dist/core/domain/entities/executor-output.js +0 -33
  459. package/dist/core/domain/entities/reflector-output.d.ts +0 -38
  460. package/dist/core/domain/entities/reflector-output.js +0 -44
  461. package/dist/core/interfaces/i-ace-prompt-builder.d.ts +0 -48
  462. package/dist/core/interfaces/i-bullet-content-store.d.ts +0 -36
  463. package/dist/core/interfaces/i-delta-store.d.ts +0 -15
  464. package/dist/core/interfaces/i-executor-output-store.d.ts +0 -14
  465. package/dist/core/interfaces/i-playbook-service.d.ts +0 -69
  466. package/dist/core/interfaces/i-playbook-store.d.ts +0 -38
  467. package/dist/core/interfaces/i-reflection-store.d.ts +0 -21
  468. package/dist/infra/ace/ace-file-utils.d.ts +0 -46
  469. package/dist/infra/ace/ace-file-utils.js +0 -83
  470. package/dist/infra/ace/ace-prompt-templates.d.ts +0 -13
  471. package/dist/infra/ace/ace-prompt-templates.js +0 -177
  472. package/dist/infra/ace/file-bullet-content-store.d.ts +0 -27
  473. package/dist/infra/ace/file-bullet-content-store.js +0 -89
  474. package/dist/infra/ace/file-delta-store.d.ts +0 -9
  475. package/dist/infra/ace/file-delta-store.js +0 -26
  476. package/dist/infra/ace/file-executor-output-store.d.ts +0 -9
  477. package/dist/infra/ace/file-executor-output-store.js +0 -26
  478. package/dist/infra/ace/file-playbook-store.d.ts +0 -29
  479. package/dist/infra/ace/file-playbook-store.js +0 -107
  480. package/dist/infra/ace/file-reflection-store.d.ts +0 -10
  481. package/dist/infra/ace/file-reflection-store.js +0 -55
  482. package/dist/infra/playbook/file-playbook-service.d.ts +0 -42
  483. package/dist/infra/playbook/file-playbook-service.js +0 -132
  484. /package/dist/core/{interfaces/i-ace-prompt-builder.js → domain/cipher/blob/types.js} +0 -0
  485. /package/dist/core/{interfaces/i-bullet-content-store.js → domain/cipher/file-system/types.js} +0 -0
  486. /package/dist/core/{interfaces/i-delta-store.js → domain/cipher/process/types.js} +0 -0
  487. /package/dist/core/{interfaces/i-executor-output-store.js → domain/cipher/session/types.js} +0 -0
  488. /package/dist/core/{interfaces/i-playbook-service.js → domain/cipher/storage/history-types.js} +0 -0
  489. /package/dist/core/{interfaces/i-playbook-store.js → domain/cipher/system-prompt/types.js} +0 -0
  490. /package/dist/core/{interfaces/i-reflection-store.js → domain/cipher/tools/types.js} +0 -0
@@ -0,0 +1,198 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Format a timestamp as a human-readable "time ago" string.
4
+ *
5
+ * @param timestamp - Unix timestamp in milliseconds
6
+ * @returns Human-readable time ago string (e.g., "2 hours ago", "3 days ago")
7
+ */
8
+ function formatTimeAgo(timestamp) {
9
+ const now = Date.now();
10
+ const diffMs = now - timestamp;
11
+ const diffSeconds = Math.floor(diffMs / 1000);
12
+ const diffMinutes = Math.floor(diffSeconds / 60);
13
+ const diffHours = Math.floor(diffMinutes / 60);
14
+ const diffDays = Math.floor(diffHours / 24);
15
+ if (diffSeconds < 60) {
16
+ return 'just now';
17
+ }
18
+ if (diffMinutes < 60) {
19
+ return `${diffMinutes} minute${diffMinutes === 1 ? '' : 's'} ago`;
20
+ }
21
+ if (diffHours < 24) {
22
+ return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;
23
+ }
24
+ if (diffDays < 30) {
25
+ return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
26
+ }
27
+ const diffMonths = Math.floor(diffDays / 30);
28
+ return `${diffMonths} month${diffMonths === 1 ? '' : 's'} ago`;
29
+ }
30
+ /**
31
+ * Available interactive commands
32
+ */
33
+ const INTERACTIVE_COMMANDS = [
34
+ {
35
+ aliases: ['?'],
36
+ description: 'Show available commands',
37
+ async handler() {
38
+ console.log('\n' + chalk.bold.cyan('📋 Available Commands:'));
39
+ console.log(chalk.cyan('─'.repeat(60)));
40
+ for (const cmd of INTERACTIVE_COMMANDS) {
41
+ const aliases = cmd.aliases ? chalk.gray(` (${cmd.aliases.join(', ')})`) : '';
42
+ console.log(chalk.green(` /${cmd.name}`) + aliases);
43
+ console.log(chalk.white(` ${cmd.description}`));
44
+ if (cmd.usage) {
45
+ console.log(chalk.gray(` Usage: ${cmd.usage}`));
46
+ }
47
+ console.log();
48
+ }
49
+ return true; // Continue loop
50
+ },
51
+ name: 'help',
52
+ },
53
+ {
54
+ description: 'Clear conversation history',
55
+ async handler(_args, agent) {
56
+ agent.reset();
57
+ console.log('\n' + chalk.green('✓ Conversation history cleared'));
58
+ return true; // Continue loop
59
+ },
60
+ name: 'reset',
61
+ },
62
+ {
63
+ description: 'Show agent state',
64
+ async handler(_args, agent) {
65
+ const state = agent.getState();
66
+ console.log('\n' + chalk.bold.cyan('📊 Agent State:'));
67
+ console.log(chalk.cyan('─'.repeat(60)));
68
+ console.log(chalk.white(` Iterations: ${chalk.bold(state.currentIteration.toString())}`));
69
+ console.log(chalk.white(` Execution history entries: ${chalk.bold(state.executionHistory.length.toString())}`));
70
+ if (state.executionHistory.length > 0) {
71
+ console.log(chalk.white('\n Recent executions:'));
72
+ const recent = state.executionHistory.slice(-3);
73
+ for (const entry of recent) {
74
+ console.log(chalk.gray(` • ${entry}`));
75
+ }
76
+ }
77
+ console.log();
78
+ return true; // Continue loop
79
+ },
80
+ name: 'status',
81
+ },
82
+ {
83
+ description: 'List all persisted sessions',
84
+ async handler(_args, agent) {
85
+ console.log('\n' + chalk.bold.cyan('📋 Available Sessions:'));
86
+ console.log(chalk.cyan('─'.repeat(60)));
87
+ const sessionIds = await agent.listPersistedSessions();
88
+ if (sessionIds.length === 0) {
89
+ console.log(chalk.gray(' No sessions found'));
90
+ console.log();
91
+ return true;
92
+ }
93
+ // Load metadata for each session and sort by last activity
94
+ const sessions = [];
95
+ for (const sessionId of sessionIds) {
96
+ // eslint-disable-next-line no-await-in-loop -- Sequential metadata loading required
97
+ const metadata = await agent.getSessionMetadata(sessionId);
98
+ if (metadata) {
99
+ sessions.push(metadata);
100
+ }
101
+ }
102
+ // Sort by last activity (most recent first)
103
+ sessions.sort((a, b) => b.lastActivity - a.lastActivity);
104
+ // Display sessions
105
+ for (const session of sessions) {
106
+ const timeAgo = formatTimeAgo(session.lastActivity);
107
+ console.log(chalk.green(` • ${session.sessionId}`));
108
+ console.log(chalk.white(` ${session.messageCount} messages, ${timeAgo}`));
109
+ }
110
+ console.log();
111
+ return true; // Continue loop
112
+ },
113
+ name: 'sessions',
114
+ },
115
+ {
116
+ description: 'Delete a session',
117
+ async handler(args, agent) {
118
+ if (args.length === 0) {
119
+ console.log('\n' + chalk.red('❌ Session ID is required'));
120
+ console.log(chalk.yellow('Usage: /delete <sessionId>'));
121
+ console.log();
122
+ return true;
123
+ }
124
+ const sessionId = args[0];
125
+ // Check if session exists
126
+ const metadata = await agent.getSessionMetadata(sessionId);
127
+ if (!metadata) {
128
+ console.log('\n' + chalk.red(`❌ Session '${sessionId}' not found`));
129
+ console.log();
130
+ return true;
131
+ }
132
+ // Delete the session
133
+ const deleted = await agent.deleteSession(sessionId);
134
+ if (deleted) {
135
+ console.log('\n' + chalk.green(`✓ Deleted session: ${sessionId}`));
136
+ }
137
+ else {
138
+ console.log('\n' + chalk.yellow(`⚠️ Session '${sessionId}' was not in memory`));
139
+ }
140
+ console.log();
141
+ return true; // Continue loop
142
+ },
143
+ name: 'delete',
144
+ usage: '/delete <sessionId>',
145
+ },
146
+ {
147
+ aliases: ['quit', 'q'],
148
+ description: 'Exit interactive mode',
149
+ async handler() {
150
+ console.log('\n' + chalk.yellow('👋 Goodbye!'));
151
+ return false; // Exit loop
152
+ },
153
+ name: 'exit',
154
+ },
155
+ ];
156
+ /**
157
+ * Get all available command names (including aliases) for autocomplete
158
+ *
159
+ * @returns Array of command names with '/' prefix
160
+ */
161
+ export function getCommandNames() {
162
+ const names = [];
163
+ for (const cmd of INTERACTIVE_COMMANDS) {
164
+ names.push(`/${cmd.name}`);
165
+ if (cmd.aliases) {
166
+ for (const alias of cmd.aliases) {
167
+ names.push(`/${alias}`);
168
+ }
169
+ }
170
+ }
171
+ return names;
172
+ }
173
+ /**
174
+ * Execute an interactive command
175
+ *
176
+ * @param command - Command name
177
+ * @param args - Command arguments
178
+ * @param agent - CipherAgent instance
179
+ * @returns Promise<boolean> - true to continue loop, false to exit
180
+ */
181
+ export async function executeCommand(command, args, agent) {
182
+ // Find the command (including aliases)
183
+ const cmd = INTERACTIVE_COMMANDS.find((c) => c.name === command || (c.aliases && c.aliases.includes(command)));
184
+ if (!cmd) {
185
+ console.log('\n' + chalk.red(`❌ Unknown command: /${command}`));
186
+ console.log(chalk.yellow('Type /help to see available commands\n'));
187
+ return true; // Continue loop
188
+ }
189
+ try {
190
+ return await cmd.handler(args, agent); // Execute command handler
191
+ }
192
+ catch (error) {
193
+ console.error('\n' + chalk.red(`❌ Error executing command /${command}:`));
194
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
195
+ console.log();
196
+ return true; // Continue loop on error
197
+ }
198
+ }
@@ -0,0 +1,24 @@
1
+ import type { ICipherAgent } from '../../core/interfaces/cipher/i-cipher-agent.js';
2
+ import type { AgentEventBus } from './events/event-emitter.js';
3
+ /**
4
+ * Display system information message on the same line using carriage return
5
+ * This allows messages to overwrite each other for cleaner output
6
+ *
7
+ * @param message - Info message to display
8
+ * @param clear - If true, clear the line after displaying (for completed actions)
9
+ */
10
+ export declare function displayInfo(message: string, clear?: boolean): void;
11
+ /**
12
+ * Start interactive loop for CipherAgent
13
+ *
14
+ * @param agent - CipherAgent instance
15
+ * @param options - Optional configuration
16
+ * @param options.model - LLM model name
17
+ * @param options.sessionId - Session identifier
18
+ * @param options.eventBus - Optional event bus for listening to agent events
19
+ */
20
+ export declare function startInteractiveLoop(agent: ICipherAgent, options?: {
21
+ eventBus?: AgentEventBus;
22
+ model?: string;
23
+ sessionId?: string;
24
+ }): Promise<void>;
@@ -0,0 +1,352 @@
1
+ /* eslint-disable unicorn/no-process-exit */
2
+ /* eslint-disable n/no-process-exit */
3
+ import chalk from 'chalk';
4
+ import readline from 'node:readline';
5
+ import { parseInput } from './command-parser.js';
6
+ import { executeCommand } from './interactive-commands.js';
7
+ /**
8
+ * Prompt user for input using readline
9
+ *
10
+ * @param rl - Readline interface
11
+ * @returns Promise resolving to user input
12
+ */
13
+ function promptUser(rl) {
14
+ return new Promise((resolve, reject) => {
15
+ // Set the prompt and display it immediately
16
+ const prompt = chalk.cyan('💬 You: ');
17
+ rl.setPrompt(prompt);
18
+ rl.prompt();
19
+ // Listen for line event instead of using question()
20
+ // This ensures the prompt appears immediately
21
+ const lineHandler = (answer) => {
22
+ rl.removeListener('line', lineHandler);
23
+ rl.removeListener('close', closeHandler);
24
+ resolve(answer);
25
+ };
26
+ const closeHandler = () => {
27
+ rl.removeListener('line', lineHandler);
28
+ rl.removeListener('close', closeHandler);
29
+ reject(new Error('Readline closed unexpectedly'));
30
+ };
31
+ rl.on('line', lineHandler);
32
+ rl.on('close', closeHandler);
33
+ });
34
+ }
35
+ /**
36
+ * Display welcome message for interactive mode
37
+ *
38
+ * @param sessionId - Session identifier
39
+ * @param model - LLM model name
40
+ * @param eventBus - Event bus to emit UI events
41
+ */
42
+ function displayWelcome(sessionId, model, eventBus) {
43
+ if (eventBus) {
44
+ eventBus.emit('cipher:ui', {
45
+ context: { model, sessionId },
46
+ type: 'banner',
47
+ });
48
+ }
49
+ }
50
+ /**
51
+ * Format and display AI response
52
+ *
53
+ * @param response - AI response text
54
+ * @param eventBus - Event bus to emit UI events
55
+ */
56
+ function displayResponse(response, eventBus) {
57
+ if (eventBus) {
58
+ eventBus.emit('cipher:ui', {
59
+ message: response,
60
+ type: 'response',
61
+ });
62
+ }
63
+ }
64
+ /**
65
+ * Safely clear the current terminal line
66
+ * Uses carriage return and spaces instead of ANSI codes to avoid rendering issues
67
+ */
68
+ function clearTerminalLine() {
69
+ // Clear line by overwriting with spaces, then return to start
70
+ // Use terminal width or 200 chars (enough for long error messages)
71
+ const width = process.stdout.columns || 200;
72
+ process.stdout.write('\r' + ' '.repeat(width) + '\r');
73
+ }
74
+ /**
75
+ * Display system information message on the same line using carriage return
76
+ * This allows messages to overwrite each other for cleaner output
77
+ *
78
+ * @param message - Info message to display
79
+ * @param clear - If true, clear the line after displaying (for completed actions)
80
+ */
81
+ export function displayInfo(message, clear = false) {
82
+ if (clear) {
83
+ // Clear the current line completely
84
+ clearTerminalLine();
85
+ }
86
+ else {
87
+ // Clear current line (spinner), write message, then newline to persist it
88
+ clearTerminalLine();
89
+ // Don't use gray - use default color for better visibility
90
+ process.stdout.write(message + '\n');
91
+ }
92
+ }
93
+ /**
94
+ * Setup event listeners for spinner and error handling
95
+ */
96
+ function setupEventListeners(eventBus, spinnerState) {
97
+ const { frames: spinnerFrames, indexRef: spinnerIndexRef, isExecutingRef, ref: spinnerRef } = spinnerState;
98
+ // Thinking event - start spinner
99
+ eventBus.on('llmservice:thinking', () => {
100
+ // Only start spinner if currently executing and not already running
101
+ if (isExecutingRef.value && !spinnerRef.current) {
102
+ // Start animated spinner
103
+ spinnerRef.current = setInterval(() => {
104
+ clearTerminalLine();
105
+ process.stdout.write(chalk.gray(`💭 Agent thinking ${spinnerFrames[spinnerIndexRef.value]}`));
106
+ spinnerIndexRef.value = (spinnerIndexRef.value + 1) % spinnerFrames.length;
107
+ }, 80);
108
+ }
109
+ });
110
+ // Response event - clear spinner
111
+ eventBus.on('llmservice:response', () => {
112
+ if (spinnerRef.current) {
113
+ clearInterval(spinnerRef.current);
114
+ spinnerRef.current = null;
115
+ clearTerminalLine();
116
+ }
117
+ });
118
+ // Tool call event - clear spinner before tool execution
119
+ eventBus.on('llmservice:toolCall', () => {
120
+ if (spinnerRef.current) {
121
+ clearInterval(spinnerRef.current);
122
+ spinnerRef.current = null;
123
+ clearTerminalLine();
124
+ }
125
+ });
126
+ // Error event - SINGLE POINT where ALL errors are displayed
127
+ // Clear spinner and display formatted error message
128
+ eventBus.on('llmservice:error', (payload) => {
129
+ // Stop spinner first
130
+ if (spinnerRef.current) {
131
+ clearInterval(spinnerRef.current);
132
+ spinnerRef.current = null;
133
+ clearTerminalLine();
134
+ }
135
+ // Display error message (already formatted with ❌ from gRPC layer)
136
+ process.stdout.write('\n' + chalk.red(payload.error) + '\n\n');
137
+ });
138
+ // cipher:ui event - handle UI events (welcome banner, responses, etc.)
139
+ eventBus.on('cipher:ui', (payload) => {
140
+ switch (payload.type) {
141
+ case 'banner': {
142
+ // Welcome banner
143
+ const { model, sessionId } = payload.context;
144
+ console.log('\n' + chalk.cyan('═'.repeat(60)));
145
+ console.log(chalk.bold.cyan('🤖 CipherAgent Interactive Mode'));
146
+ console.log(chalk.cyan('═'.repeat(60)));
147
+ console.log(chalk.gray(`Model: ${model}`));
148
+ console.log(chalk.gray(`Session: ${sessionId}`));
149
+ console.log(chalk.yellow('\nType /help for available commands'));
150
+ console.log(chalk.cyan('─'.repeat(60)) + '\n');
151
+ break;
152
+ }
153
+ case 'help': {
154
+ // Help message
155
+ if (payload.message) {
156
+ console.log(chalk.yellow(`ℹ ${payload.message}`));
157
+ }
158
+ break;
159
+ }
160
+ case 'response': {
161
+ // AI response
162
+ if (payload.message) {
163
+ console.log('\n' + chalk.rgb(255, 165, 0)('─'.repeat(60)));
164
+ console.log(chalk.bold.rgb(255, 165, 0)('🤖 AI Response:'));
165
+ console.log(chalk.rgb(255, 165, 0)('─'.repeat(60)));
166
+ console.log(chalk.white(payload.message));
167
+ console.log(chalk.rgb(255, 165, 0)('─'.repeat(60)) + '\n');
168
+ }
169
+ break;
170
+ }
171
+ case 'shutdown': {
172
+ // Shutdown message
173
+ if (payload.message) {
174
+ console.log(chalk.gray(`✓ ${payload.message}`));
175
+ }
176
+ break;
177
+ }
178
+ // No default case needed - other UI types can be ignored
179
+ }
180
+ });
181
+ // cipher:log event - handle structured logging
182
+ // NOTE: Skip 'error' level - those are handled by llmservice:error to avoid duplicates
183
+ eventBus.on('cipher:log', (payload) => {
184
+ const prefix = payload.source ? `[${payload.source}] ` : '';
185
+ const message = `${prefix}${payload.message}`;
186
+ switch (payload.level) {
187
+ case 'debug': {
188
+ console.log(chalk.gray(`🔍 ${message}`));
189
+ break;
190
+ }
191
+ case 'error': {
192
+ // Skip - llmservice:error handler displays errors to avoid duplicates
193
+ break;
194
+ }
195
+ case 'info': {
196
+ console.log(chalk.blue(`ℹ ${message}`));
197
+ break;
198
+ }
199
+ case 'warn': {
200
+ console.warn(chalk.yellow(`⚠ ${message}`));
201
+ break;
202
+ }
203
+ }
204
+ });
205
+ }
206
+ /**
207
+ * Stop and clear spinner if running
208
+ */
209
+ function stopSpinner(spinnerRef) {
210
+ if (spinnerRef.current) {
211
+ clearInterval(spinnerRef.current);
212
+ spinnerRef.current = null;
213
+ clearTerminalLine();
214
+ }
215
+ }
216
+ /**
217
+ * Handle command execution
218
+ * @returns true to continue loop, false to exit
219
+ */
220
+ async function handleCommand(command, args, agent, eventBus) {
221
+ if (!command) {
222
+ if (eventBus) {
223
+ eventBus.emit('cipher:ui', {
224
+ message: 'Type /help to see available commands',
225
+ type: 'help',
226
+ });
227
+ }
228
+ return true;
229
+ }
230
+ const shouldContinue = await executeCommand(command, args, agent);
231
+ return shouldContinue;
232
+ }
233
+ /**
234
+ * Execute user prompt with AI agent
235
+ */
236
+ async function executePrompt(prompt, agent, state, eventBus) {
237
+ const { isExecutingRef, spinnerRef } = state;
238
+ try {
239
+ // Mark execution started - prevents late thinking events from starting spinner
240
+ isExecutingRef.value = true;
241
+ // Execute AI prompt
242
+ const response = await agent.execute(prompt);
243
+ // Mark execution finished - no more spinners allowed
244
+ isExecutingRef.value = false;
245
+ // Stop spinner immediately after execution completes (redundant safety check)
246
+ stopSpinner(spinnerRef);
247
+ // Display response
248
+ displayResponse(response, eventBus);
249
+ // Final safety cleanup - ensure no spinner is running after response displayed
250
+ stopSpinner(spinnerRef);
251
+ }
252
+ catch {
253
+ // Mark execution finished on error
254
+ isExecutingRef.value = false;
255
+ // Error is already handled by llmservice:error event listener
256
+ // No need to display here - just clean up state
257
+ }
258
+ }
259
+ /**
260
+ * Start interactive loop for CipherAgent
261
+ *
262
+ * @param agent - CipherAgent instance
263
+ * @param options - Optional configuration
264
+ * @param options.model - LLM model name
265
+ * @param options.sessionId - Session identifier
266
+ * @param options.eventBus - Optional event bus for listening to agent events
267
+ */
268
+ export async function startInteractiveLoop(agent, options) {
269
+ // Display welcome message
270
+ displayWelcome(options?.sessionId ?? 'cipher-agent-session', options?.model ?? 'gemini-2.5-pro', options?.eventBus);
271
+ // Create readline interface
272
+ const rl = readline.createInterface({
273
+ input: process.stdin,
274
+ output: process.stdout,
275
+ });
276
+ // Create custom spinner using carriage return for clean output
277
+ const spinnerRef = { current: null };
278
+ const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
279
+ const spinnerIndexRef = { value: 0 };
280
+ const isExecutingRef = { value: false };
281
+ // Setup event listeners
282
+ if (options?.eventBus) {
283
+ setupEventListeners(options.eventBus, {
284
+ frames: spinnerFrames,
285
+ indexRef: spinnerIndexRef,
286
+ isExecutingRef,
287
+ ref: spinnerRef,
288
+ });
289
+ }
290
+ const isExitingRef = { value: false };
291
+ const exitEventHandler = async () => {
292
+ stopSpinner(spinnerRef);
293
+ await cleanup(agent, rl, isExitingRef, options?.eventBus);
294
+ process.exit(0);
295
+ };
296
+ rl.on('SIGINT', exitEventHandler);
297
+ process.on('SIGTERM', exitEventHandler);
298
+ try {
299
+ // Main interactive loop
300
+ while (true) {
301
+ // Get user input
302
+ // eslint-disable-next-line no-await-in-loop -- Sequential user input required for interactive loop
303
+ const userInput = await promptUser(rl);
304
+ // Parse input
305
+ const parsed = parseInput(userInput);
306
+ if (parsed.type === 'command') {
307
+ // Handle slash command
308
+ // eslint-disable-next-line no-await-in-loop -- Sequential command execution required for interactive loop
309
+ const shouldContinue = await handleCommand(parsed.command, parsed.args || [], agent, options?.eventBus);
310
+ if (!shouldContinue) {
311
+ // Exit command was called
312
+ break;
313
+ }
314
+ continue;
315
+ }
316
+ // Handle regular prompt - pass to AI
317
+ if (!parsed.rawInput.trim()) {
318
+ // Empty input, skip
319
+ continue;
320
+ }
321
+ // Execute AI prompt
322
+ // eslint-disable-next-line no-await-in-loop -- Sequential agent execution required for interactive loop
323
+ await executePrompt(parsed.rawInput, agent, { isExecutingRef, spinnerRef }, options?.eventBus);
324
+ }
325
+ }
326
+ finally {
327
+ stopSpinner(spinnerRef);
328
+ await cleanup(agent, rl, isExitingRef, options?.eventBus);
329
+ rl.off('SIGINT', exitEventHandler);
330
+ process.off('SIGTERM', exitEventHandler);
331
+ }
332
+ }
333
+ /**
334
+ * Cleans up resources when interactive loop is exiting.
335
+ * @param agent CipherAgent instance to stop
336
+ * @param rl Readline interface to close
337
+ * @param isExitingRef Reference object to track if exiting
338
+ * @param isExitingRef.value Boolean flag indicating if cleanup is in progress
339
+ */
340
+ const cleanup = async (agent, rl, isExitingRef, eventBus) => {
341
+ if (isExitingRef.value)
342
+ return;
343
+ isExitingRef.value = true;
344
+ if (eventBus) {
345
+ eventBus.emit('cipher:ui', {
346
+ message: 'Shutting down...',
347
+ type: 'shutdown',
348
+ });
349
+ }
350
+ rl.close();
351
+ console.log(chalk.gray('✓ Cleanup complete'));
352
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * AsyncMutex - Simple asynchronous mutex for thread safety in parallel execution.
3
+ *
4
+ * Provides mutual exclusion for async operations, ensuring that only one
5
+ * operation can execute the critical section at a time. Uses a FIFO queue
6
+ * to ensure fairness among waiting operations.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const mutex = new AsyncMutex()
11
+ *
12
+ * // Option 1: Manual acquire/release
13
+ * await mutex.acquire()
14
+ * try {
15
+ * // Critical section
16
+ * } finally {
17
+ * mutex.release()
18
+ * }
19
+ *
20
+ * // Option 2: Using withLock (recommended)
21
+ * await mutex.withLock(async () => {
22
+ * // Critical section - automatically released
23
+ * })
24
+ * ```
25
+ */
26
+ export declare class AsyncMutex {
27
+ private locked;
28
+ private readonly queue;
29
+ /**
30
+ * Acquire the mutex lock.
31
+ * If the mutex is already locked, the caller will wait in a FIFO queue.
32
+ *
33
+ * @returns Promise that resolves when the lock is acquired
34
+ */
35
+ acquire(): Promise<void>;
36
+ /**
37
+ * Get the number of operations waiting for the lock.
38
+ */
39
+ getQueueLength(): number;
40
+ /**
41
+ * Check if the mutex is currently locked.
42
+ */
43
+ isLocked(): boolean;
44
+ /**
45
+ * Release the mutex lock.
46
+ * If there are waiting operations, the next one in the queue will be granted the lock.
47
+ *
48
+ * @throws Error if the mutex is not currently locked
49
+ */
50
+ release(): void;
51
+ /**
52
+ * Execute a function with the mutex lock held.
53
+ * The lock is automatically released when the function completes or throws.
54
+ *
55
+ * @param fn - Async function to execute with the lock held
56
+ * @returns The result of the function
57
+ */
58
+ withLock<T>(fn: () => Promise<T>): Promise<T>;
59
+ }