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
@@ -92,54 +92,47 @@ export function displayInfo(message, clear = false) {
92
92
  }
93
93
  /**
94
94
  * Setup event listeners for spinner and error handling
95
+ * @returns Cleanup function to remove all listeners (prevents memory leaks)
95
96
  */
96
97
  function setupEventListeners(eventBus, spinnerState) {
97
98
  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
99
+ // Store listener references for cleanup
100
+ const thinkingListener = () => {
101
101
  if (isExecutingRef.value && !spinnerRef.current) {
102
- // Start animated spinner
103
102
  spinnerRef.current = setInterval(() => {
104
103
  clearTerminalLine();
105
104
  process.stdout.write(chalk.gray(`💭 Agent thinking ${spinnerFrames[spinnerIndexRef.value]}`));
106
105
  spinnerIndexRef.value = (spinnerIndexRef.value + 1) % spinnerFrames.length;
107
106
  }, 80);
108
107
  }
109
- });
110
- // Response event - clear spinner
111
- eventBus.on('llmservice:response', () => {
108
+ };
109
+ const responseListener = () => {
112
110
  if (spinnerRef.current) {
113
111
  clearInterval(spinnerRef.current);
114
112
  spinnerRef.current = null;
115
113
  clearTerminalLine();
116
114
  }
117
- });
118
- // Tool call event - clear spinner before tool execution
119
- eventBus.on('llmservice:toolCall', () => {
115
+ };
116
+ const toolCallListener = () => {
120
117
  if (spinnerRef.current) {
121
118
  clearInterval(spinnerRef.current);
122
119
  spinnerRef.current = null;
123
120
  clearTerminalLine();
124
121
  }
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
122
+ };
123
+ const errorListener = (payload) => {
130
124
  if (spinnerRef.current) {
131
125
  clearInterval(spinnerRef.current);
132
126
  spinnerRef.current = null;
133
127
  clearTerminalLine();
134
128
  }
135
- // Display error message (already formatted with ❌ from gRPC layer)
136
129
  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) => {
130
+ };
131
+ // TODO(v0.5.0): Move to outer scope for better performance
132
+ // eslint-disable-next-line unicorn/consistent-function-scoping
133
+ const uiListener = (payload) => {
140
134
  switch (payload.type) {
141
135
  case 'banner': {
142
- // Welcome banner
143
136
  const { model, sessionId } = payload.context;
144
137
  console.log('\n' + chalk.cyan('═'.repeat(60)));
145
138
  console.log(chalk.bold.cyan('🤖 CipherAgent Interactive Mode'));
@@ -151,14 +144,12 @@ function setupEventListeners(eventBus, spinnerState) {
151
144
  break;
152
145
  }
153
146
  case 'help': {
154
- // Help message
155
147
  if (payload.message) {
156
148
  console.log(chalk.yellow(`ℹ ${payload.message}`));
157
149
  }
158
150
  break;
159
151
  }
160
152
  case 'response': {
161
- // AI response
162
153
  if (payload.message) {
163
154
  console.log('\n' + chalk.rgb(255, 165, 0)('─'.repeat(60)));
164
155
  console.log(chalk.bold.rgb(255, 165, 0)('🤖 AI Response:'));
@@ -169,18 +160,16 @@ function setupEventListeners(eventBus, spinnerState) {
169
160
  break;
170
161
  }
171
162
  case 'shutdown': {
172
- // Shutdown message
173
163
  if (payload.message) {
174
164
  console.log(chalk.gray(`✓ ${payload.message}`));
175
165
  }
176
166
  break;
177
167
  }
178
- // No default case needed - other UI types can be ignored
179
168
  }
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) => {
169
+ };
170
+ // TODO(v0.5.0): Move to outer scope for better performance
171
+ // eslint-disable-next-line unicorn/consistent-function-scoping
172
+ const logListener = (payload) => {
184
173
  const prefix = payload.source ? `[${payload.source}] ` : '';
185
174
  const message = `${prefix}${payload.message}`;
186
175
  switch (payload.level) {
@@ -201,7 +190,23 @@ function setupEventListeners(eventBus, spinnerState) {
201
190
  break;
202
191
  }
203
192
  }
204
- });
193
+ };
194
+ // Register all listeners
195
+ eventBus.on('llmservice:thinking', thinkingListener);
196
+ eventBus.on('llmservice:response', responseListener);
197
+ eventBus.on('llmservice:toolCall', toolCallListener);
198
+ eventBus.on('llmservice:error', errorListener);
199
+ eventBus.on('cipher:ui', uiListener);
200
+ eventBus.on('cipher:log', logListener);
201
+ // Return cleanup function to remove all listeners
202
+ return () => {
203
+ eventBus.off('llmservice:thinking', thinkingListener);
204
+ eventBus.off('llmservice:response', responseListener);
205
+ eventBus.off('llmservice:toolCall', toolCallListener);
206
+ eventBus.off('llmservice:error', errorListener);
207
+ eventBus.off('cipher:ui', uiListener);
208
+ eventBus.off('cipher:log', logListener);
209
+ };
205
210
  }
206
211
  /**
207
212
  * Stop and clear spinner if running
@@ -238,7 +243,7 @@ async function executePrompt(prompt, agent, state, eventBus) {
238
243
  try {
239
244
  // Mark execution started - prevents late thinking events from starting spinner
240
245
  isExecutingRef.value = true;
241
- // Execute AI prompt
246
+ // Execute AI prompt (agent uses its default session)
242
247
  const response = await agent.execute(prompt);
243
248
  // Mark execution finished - no more spinners allowed
244
249
  isExecutingRef.value = false;
@@ -278,9 +283,10 @@ export async function startInteractiveLoop(agent, options) {
278
283
  const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
279
284
  const spinnerIndexRef = { value: 0 };
280
285
  const isExecutingRef = { value: false };
281
- // Setup event listeners
286
+ // Setup event listeners and get cleanup function
287
+ let cleanupEventListeners;
282
288
  if (options?.eventBus) {
283
- setupEventListeners(options.eventBus, {
289
+ cleanupEventListeners = setupEventListeners(options.eventBus, {
284
290
  frames: spinnerFrames,
285
291
  indexRef: spinnerIndexRef,
286
292
  isExecutingRef,
@@ -290,6 +296,7 @@ export async function startInteractiveLoop(agent, options) {
290
296
  const isExitingRef = { value: false };
291
297
  const exitEventHandler = async () => {
292
298
  stopSpinner(spinnerRef);
299
+ cleanupEventListeners?.();
293
300
  await cleanup(agent, rl, isExitingRef, options?.eventBus);
294
301
  process.exit(0);
295
302
  };
@@ -318,13 +325,14 @@ export async function startInteractiveLoop(agent, options) {
318
325
  // Empty input, skip
319
326
  continue;
320
327
  }
321
- // Execute AI prompt
328
+ // Execute AI prompt (agent uses its default session)
322
329
  // eslint-disable-next-line no-await-in-loop -- Sequential agent execution required for interactive loop
323
330
  await executePrompt(parsed.rawInput, agent, { isExecutingRef, spinnerRef }, options?.eventBus);
324
331
  }
325
332
  }
326
333
  finally {
327
334
  stopSpinner(spinnerRef);
335
+ cleanupEventListeners?.();
328
336
  await cleanup(agent, rl, isExitingRef, options?.eventBus);
329
337
  rl.off('SIGINT', exitEventHandler);
330
338
  process.off('SIGTERM', exitEventHandler);
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Model Capability Cache
3
+ *
4
+ * Caches model capability lookups for performance.
5
+ * Avoids repeated registry lookups for the same model.
6
+ */
7
+ import { type LLMProvider, type ModelCapabilities } from '../../../core/domain/cipher/llm/index.js';
8
+ /**
9
+ * Cache for model capability lookups.
10
+ *
11
+ * This cache stores model information to avoid repeated registry lookups.
12
+ * The cache is keyed by "provider:model" for quick access.
13
+ */
14
+ export declare class ModelCapabilityCache {
15
+ private readonly cache;
16
+ /**
17
+ * Get cache size (number of cached models).
18
+ */
19
+ get size(): number;
20
+ /**
21
+ * Clear the cache.
22
+ */
23
+ clear(): void;
24
+ /**
25
+ * Get model capabilities.
26
+ * @param provider - LLM provider
27
+ * @param model - Model name
28
+ * @returns ModelCapabilities object
29
+ */
30
+ getCapabilities(provider: LLMProvider, model: string): ModelCapabilities;
31
+ /**
32
+ * Get characters per token ratio for model.
33
+ */
34
+ getCharsPerToken(provider: LLMProvider, model: string): number;
35
+ /**
36
+ * Get max input tokens for model.
37
+ */
38
+ getMaxInputTokens(provider: LLMProvider, model: string): number;
39
+ /**
40
+ * Check if a model is cached.
41
+ */
42
+ has(provider: LLMProvider, model: string): boolean;
43
+ /**
44
+ * Check if model supports audio.
45
+ */
46
+ supportsAudio(provider: LLMProvider, model: string): boolean;
47
+ /**
48
+ * Check if model supports a specific feature.
49
+ * @param provider - LLM provider
50
+ * @param model - Model name
51
+ * @param feature - Feature to check
52
+ * @returns true if feature is supported
53
+ */
54
+ supportsFeature(provider: LLMProvider, model: string, feature: keyof ModelCapabilities): boolean;
55
+ /**
56
+ * Check if model supports images.
57
+ */
58
+ supportsImages(provider: LLMProvider, model: string): boolean;
59
+ /**
60
+ * Check if model supports PDFs.
61
+ */
62
+ supportsPdf(provider: LLMProvider, model: string): boolean;
63
+ /**
64
+ * Check if model supports streaming.
65
+ */
66
+ supportsStreaming(provider: LLMProvider, model: string): boolean;
67
+ /**
68
+ * Check if model supports extended thinking (Gemini).
69
+ */
70
+ supportsThinking(provider: LLMProvider, model: string): boolean;
71
+ /**
72
+ * Generate cache key from provider and model.
73
+ */
74
+ private getCacheKey;
75
+ /**
76
+ * Get cached model info, fetching from registry if not cached.
77
+ * @param provider - LLM provider
78
+ * @param model - Model name
79
+ * @returns Cached model info
80
+ */
81
+ private getOrFetch;
82
+ }
83
+ /**
84
+ * Singleton instance for shared capability cache.
85
+ * Use this for application-wide caching.
86
+ */
87
+ export declare const globalCapabilityCache: ModelCapabilityCache;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Model Capability Cache
3
+ *
4
+ * Caches model capability lookups for performance.
5
+ * Avoids repeated registry lookups for the same model.
6
+ */
7
+ import { getModelInfoWithFallback, } from '../../../core/domain/cipher/llm/index.js';
8
+ /**
9
+ * Cache for model capability lookups.
10
+ *
11
+ * This cache stores model information to avoid repeated registry lookups.
12
+ * The cache is keyed by "provider:model" for quick access.
13
+ */
14
+ export class ModelCapabilityCache {
15
+ cache = new Map();
16
+ /**
17
+ * Get cache size (number of cached models).
18
+ */
19
+ get size() {
20
+ return this.cache.size;
21
+ }
22
+ /**
23
+ * Clear the cache.
24
+ */
25
+ clear() {
26
+ this.cache.clear();
27
+ }
28
+ /**
29
+ * Get model capabilities.
30
+ * @param provider - LLM provider
31
+ * @param model - Model name
32
+ * @returns ModelCapabilities object
33
+ */
34
+ getCapabilities(provider, model) {
35
+ return this.getOrFetch(provider, model).capabilities;
36
+ }
37
+ /**
38
+ * Get characters per token ratio for model.
39
+ */
40
+ getCharsPerToken(provider, model) {
41
+ return this.getOrFetch(provider, model).charsPerToken;
42
+ }
43
+ /**
44
+ * Get max input tokens for model.
45
+ */
46
+ getMaxInputTokens(provider, model) {
47
+ return this.getOrFetch(provider, model).maxInputTokens;
48
+ }
49
+ /**
50
+ * Check if a model is cached.
51
+ */
52
+ has(provider, model) {
53
+ return this.cache.has(this.getCacheKey(provider, model));
54
+ }
55
+ /**
56
+ * Check if model supports audio.
57
+ */
58
+ supportsAudio(provider, model) {
59
+ return this.supportsFeature(provider, model, 'supportsAudio');
60
+ }
61
+ /**
62
+ * Check if model supports a specific feature.
63
+ * @param provider - LLM provider
64
+ * @param model - Model name
65
+ * @param feature - Feature to check
66
+ * @returns true if feature is supported
67
+ */
68
+ supportsFeature(provider, model, feature) {
69
+ const capabilities = this.getCapabilities(provider, model);
70
+ return capabilities[feature] ?? false;
71
+ }
72
+ /**
73
+ * Check if model supports images.
74
+ */
75
+ supportsImages(provider, model) {
76
+ return this.supportsFeature(provider, model, 'supportsImages');
77
+ }
78
+ /**
79
+ * Check if model supports PDFs.
80
+ */
81
+ supportsPdf(provider, model) {
82
+ return this.supportsFeature(provider, model, 'supportsPdf');
83
+ }
84
+ /**
85
+ * Check if model supports streaming.
86
+ */
87
+ supportsStreaming(provider, model) {
88
+ return this.supportsFeature(provider, model, 'supportsStreaming');
89
+ }
90
+ /**
91
+ * Check if model supports extended thinking (Gemini).
92
+ */
93
+ supportsThinking(provider, model) {
94
+ return this.supportsFeature(provider, model, 'supportsThinking');
95
+ }
96
+ /**
97
+ * Generate cache key from provider and model.
98
+ */
99
+ getCacheKey(provider, model) {
100
+ return `${provider}:${model}`;
101
+ }
102
+ /**
103
+ * Get cached model info, fetching from registry if not cached.
104
+ * @param provider - LLM provider
105
+ * @param model - Model name
106
+ * @returns Cached model info
107
+ */
108
+ getOrFetch(provider, model) {
109
+ const key = this.getCacheKey(provider, model);
110
+ if (!this.cache.has(key)) {
111
+ const modelInfo = getModelInfoWithFallback(provider, model);
112
+ this.cache.set(key, {
113
+ capabilities: modelInfo.capabilities,
114
+ charsPerToken: modelInfo.charsPerToken,
115
+ maxInputTokens: modelInfo.maxInputTokens,
116
+ });
117
+ }
118
+ return this.cache.get(key);
119
+ }
120
+ }
121
+ /**
122
+ * Singleton instance for shared capability cache.
123
+ * Use this for application-wide caching.
124
+ */
125
+ export const globalCapabilityCache = new ModelCapabilityCache();
@@ -1,5 +1,7 @@
1
1
  import type { CompactionResult } from '../../../../../core/domain/cipher/storage/message-storage-types.js';
2
+ import type { IContentGenerator } from '../../../../../core/interfaces/cipher/i-content-generator.js';
2
3
  import type { ITokenizer } from '../../../../../core/interfaces/cipher/i-tokenizer.js';
4
+ import type { InternalMessage } from '../../../../../core/interfaces/cipher/message-types.js';
3
5
  import type { MessageStorageService } from '../../../storage/message-storage-service.js';
4
6
  /**
5
7
  * Configuration for compaction behavior.
@@ -10,11 +12,26 @@ export interface CompactionConfig {
10
12
  * Default: 0.85 (85%)
11
13
  */
12
14
  overflowThreshold?: number;
15
+ /**
16
+ * Number of recent user turns to protect from pruning.
17
+ * Based on OpenCode's turn-based protection pattern.
18
+ * Tool outputs in these turns will not be compacted.
19
+ * Default: 2
20
+ */
21
+ protectedTurns?: number;
13
22
  /**
14
23
  * Number of tokens to keep in tool outputs after pruning.
24
+ * Based on OpenCode's PRUNE_PROTECT constant.
15
25
  * Default: 40000
16
26
  */
17
27
  pruneKeepTokens?: number;
28
+ /**
29
+ * Minimum tokens that must be recoverable to perform pruning.
30
+ * Based on OpenCode's PRUNE_MINIMUM constant.
31
+ * If pruning would save less than this, skip it.
32
+ * Default: 20000
33
+ */
34
+ pruneMinimumTokens?: number;
18
35
  /**
19
36
  * System prompt for generating compaction summaries.
20
37
  */
@@ -82,6 +99,17 @@ export declare class CompactionService {
82
99
  * Uses the configured tokenizer.
83
100
  */
84
101
  estimateTokens(text: string): Promise<number>;
102
+ /**
103
+ * Generate a compaction summary using the LLM.
104
+ * Called when context overflow requires full compaction (not just pruning).
105
+ *
106
+ * @param generator - The content generator to use for LLM calls
107
+ * @param messages - The conversation history to summarize
108
+ * @param taskId - Task ID from usecase for billing tracking
109
+ * @param model - The model ID to use for generation
110
+ * @returns The generated summary text
111
+ */
112
+ generateSummary(generator: IContentGenerator, messages: InternalMessage[], taskId: string, model: string): Promise<string>;
85
113
  /**
86
114
  * Get the current compaction configuration.
87
115
  */
@@ -97,6 +125,10 @@ export declare class CompactionService {
97
125
  /**
98
126
  * Prune old tool outputs to reduce context size.
99
127
  * Keeps the most recent tool outputs up to the configured token limit.
128
+ * Only executes if minimum token threshold can be recovered.
129
+ *
130
+ * @param sessionId - The session to prune
131
+ * @returns CompactionResult with count and tokens saved (or zeros if below threshold)
100
132
  */
101
133
  pruneToolOutputs(sessionId: string): Promise<CompactionResult>;
102
134
  }
@@ -32,7 +32,9 @@ export class CompactionService {
32
32
  this.tokenizer = tokenizer;
33
33
  this.config = {
34
34
  overflowThreshold: config?.overflowThreshold ?? 0.85,
35
+ protectedTurns: config?.protectedTurns ?? 2,
35
36
  pruneKeepTokens: config?.pruneKeepTokens ?? 40_000,
37
+ pruneMinimumTokens: config?.pruneMinimumTokens ?? 20_000,
36
38
  summaryPrompt: config?.summaryPrompt ?? DEFAULT_SUMMARY_PROMPT,
37
39
  };
38
40
  }
@@ -96,6 +98,36 @@ export class CompactionService {
96
98
  async estimateTokens(text) {
97
99
  return this.tokenizer.countTokens(text);
98
100
  }
101
+ /**
102
+ * Generate a compaction summary using the LLM.
103
+ * Called when context overflow requires full compaction (not just pruning).
104
+ *
105
+ * @param generator - The content generator to use for LLM calls
106
+ * @param messages - The conversation history to summarize
107
+ * @param taskId - Task ID from usecase for billing tracking
108
+ * @param model - The model ID to use for generation
109
+ * @returns The generated summary text
110
+ */
111
+ async generateSummary(generator, messages, taskId, model) {
112
+ const { systemPrompt, userMessage } = this.getSummaryPromptParts();
113
+ try {
114
+ const response = await generator.generateContent({
115
+ config: {
116
+ maxTokens: 4096, // Reasonable limit for summaries
117
+ temperature: 0.3, // Lower temperature for more focused summaries
118
+ },
119
+ contents: [...messages, { content: userMessage, role: 'user' }],
120
+ model,
121
+ systemPrompt,
122
+ taskId,
123
+ tools: {}, // No tools for summary generation
124
+ });
125
+ return typeof response.content === 'string' ? response.content : '[Summary generation failed]';
126
+ }
127
+ catch {
128
+ return '[Summary generation failed due to error]';
129
+ }
130
+ }
99
131
  /**
100
132
  * Get the current compaction configuration.
101
133
  */
@@ -109,19 +141,28 @@ export class CompactionService {
109
141
  getSummaryPromptParts() {
110
142
  return {
111
143
  systemPrompt: this.config.summaryPrompt,
112
- userMessage: 'Based on our conversation so far, provide a detailed summary that captures all important context. ' +
113
- 'This summary will be used to continue the conversation without the full history.',
144
+ userMessage: 'Provide a detailed prompt for continuing our conversation above. ' +
145
+ 'Focus on information that would be helpful for continuing the conversation, including ' +
146
+ 'what we did, what we are doing, which files we are working on, and what we are going to do next ' +
147
+ 'considering a new session will not have access to our conversation.',
114
148
  };
115
149
  }
116
150
  /**
117
151
  * Prune old tool outputs to reduce context size.
118
152
  * Keeps the most recent tool outputs up to the configured token limit.
153
+ * Only executes if minimum token threshold can be recovered.
154
+ *
155
+ * @param sessionId - The session to prune
156
+ * @returns CompactionResult with count and tokens saved (or zeros if below threshold)
119
157
  */
120
158
  async pruneToolOutputs(sessionId) {
121
- return this.messageStorage.pruneToolOutputs({
159
+ const result = await this.messageStorage.pruneToolOutputs({
122
160
  keepTokens: this.config.pruneKeepTokens,
161
+ minimumTokens: this.config.pruneMinimumTokens,
162
+ protectedTurns: this.config.protectedTurns,
123
163
  sessionId,
124
164
  });
165
+ return result;
125
166
  }
126
167
  }
127
168
  /**
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Enhanced Compaction Strategy
3
+ *
4
+ * Extends the ReactiveOverflowStrategy with additional features from OpenCode:
5
+ * - Creates CompactionPart to track compaction metadata
6
+ * - Preserves last 2 conversation turns (configurable)
7
+ * - Only compacts if saving > 20K tokens (configurable)
8
+ * - Emits compaction events for observability
9
+ *
10
+ * This is a wrapper that adds these features on top of the existing
11
+ * ReactiveOverflowStrategy for backward compatibility.
12
+ */
13
+ import type { ITokenizer } from '../../../../../core/interfaces/cipher/i-tokenizer.js';
14
+ import type { CompactionPart, InternalMessage } from '../../../../../core/interfaces/cipher/message-types.js';
15
+ import type { SessionEventBus } from '../../../events/event-emitter.js';
16
+ import type { ICompressionStrategy } from './types.js';
17
+ import { type ReactiveOverflowOptions } from './reactive-overflow.js';
18
+ /**
19
+ * Configuration for enhanced compaction.
20
+ */
21
+ export interface EnhancedCompactionOptions extends ReactiveOverflowOptions {
22
+ /**
23
+ * Event bus for emitting compaction events.
24
+ * Optional - if not provided, events won't be emitted.
25
+ */
26
+ eventBus?: SessionEventBus;
27
+ /**
28
+ * Minimum token savings required to trigger compaction.
29
+ * Default: 20000 (20K tokens)
30
+ */
31
+ minTokenSavings?: number;
32
+ /**
33
+ * Number of recent conversation turns to always preserve.
34
+ * Default: 2
35
+ */
36
+ preserveTurns?: number;
37
+ }
38
+ /**
39
+ * Enhanced Compaction Strategy.
40
+ *
41
+ * Wraps ReactiveOverflowStrategy with additional OpenCode-style features:
42
+ * - Token savings threshold
43
+ * - CompactionPart creation
44
+ * - Event emission
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const strategy = new EnhancedCompactionStrategy({
49
+ * llmProvider: myLlmProvider,
50
+ * eventBus: sessionEventBus,
51
+ * minTokenSavings: 20000,
52
+ * preserveTurns: 2,
53
+ * })
54
+ *
55
+ * const compactedHistory = await strategy.compress(history, maxTokens, tokenizer)
56
+ * ```
57
+ */
58
+ export declare class EnhancedCompactionStrategy implements ICompressionStrategy {
59
+ private readonly baseStrategy;
60
+ private readonly eventBus?;
61
+ /** Track the last compaction result for observability */
62
+ private lastCompactionResult?;
63
+ private readonly minTokenSavings;
64
+ private readonly preserveTurns;
65
+ constructor(options: EnhancedCompactionOptions);
66
+ /**
67
+ * Compress history with enhanced features.
68
+ */
69
+ compress(history: InternalMessage[], maxHistoryTokens: number, tokenizer: ITokenizer): Promise<InternalMessage[]>;
70
+ /**
71
+ * Create a CompactionPart for the given compaction result.
72
+ * Can be used to insert into message parts for tracking.
73
+ */
74
+ createCompactionPart(summary: string): CompactionPart | undefined;
75
+ /**
76
+ * Get the last compaction result for observability.
77
+ */
78
+ getLastCompactionResult(): CompactionResult | undefined;
79
+ getName(): string;
80
+ /**
81
+ * Count total tokens in history.
82
+ */
83
+ private countTokens;
84
+ /**
85
+ * Find message IDs that were compacted (removed or summarized).
86
+ * Since messages don't have IDs, we use indices as pseudo-IDs.
87
+ */
88
+ private findCompactedMessageIds;
89
+ }
90
+ /**
91
+ * Result of a compaction operation.
92
+ */
93
+ export interface CompactionResult {
94
+ /** Timestamp when compaction occurred */
95
+ compactedAt: number;
96
+ /** IDs of messages that were compacted */
97
+ compactedMessageIds: string[];
98
+ /** Number of messages after compaction */
99
+ messageCountAfter: number;
100
+ /** Number of messages before compaction */
101
+ messageCountBefore: number;
102
+ /** Token count after compaction */
103
+ tokensAfter: number;
104
+ /** Token count before compaction */
105
+ tokensBefore: number;
106
+ /** Tokens saved by compaction */
107
+ tokensSaved: number;
108
+ }
109
+ /**
110
+ * Create an EnhancedCompactionStrategy instance.
111
+ */
112
+ export declare function createEnhancedCompactionStrategy(options: EnhancedCompactionOptions): EnhancedCompactionStrategy;