@ebowwa/coder 0.7.63 → 0.7.65

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 (364) hide show
  1. package/dist/core/__tests__/permissions.test.d.ts +12 -0
  2. package/dist/core/__tests__/permissions.test.d.ts.map +1 -0
  3. package/dist/core/__tests__/permissions.test.js +851 -0
  4. package/dist/core/agent-loop/__tests__/compaction.test.d.ts +5 -0
  5. package/dist/core/agent-loop/__tests__/compaction.test.d.ts.map +1 -0
  6. package/dist/core/agent-loop/__tests__/compaction.test.js +209 -0
  7. package/dist/core/agent-loop/__tests__/formatters.test.d.ts +5 -0
  8. package/dist/core/agent-loop/__tests__/formatters.test.d.ts.map +1 -0
  9. package/dist/core/agent-loop/__tests__/formatters.test.js +195 -0
  10. package/dist/core/agent-loop/__tests__/index.test.d.ts +5 -0
  11. package/dist/core/agent-loop/__tests__/index.test.d.ts.map +1 -0
  12. package/dist/core/agent-loop/__tests__/index.test.js +121 -0
  13. package/dist/core/agent-loop/__tests__/loop-state.test.d.ts +5 -0
  14. package/dist/core/agent-loop/__tests__/loop-state.test.d.ts.map +1 -0
  15. package/dist/core/agent-loop/__tests__/loop-state.test.js +340 -0
  16. package/dist/core/agent-loop/__tests__/message-builder.test.d.ts +5 -0
  17. package/dist/core/agent-loop/__tests__/message-builder.test.d.ts.map +1 -0
  18. package/dist/core/agent-loop/__tests__/message-builder.test.js +178 -0
  19. package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts +5 -0
  20. package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts.map +1 -0
  21. package/dist/core/agent-loop/__tests__/tool-executor.test.js +331 -0
  22. package/dist/core/agent-loop/compaction.d.ts +39 -0
  23. package/dist/core/agent-loop/compaction.d.ts.map +1 -0
  24. package/dist/core/agent-loop/compaction.js +51 -0
  25. package/dist/core/agent-loop/formatters.d.ts +21 -0
  26. package/dist/core/agent-loop/formatters.d.ts.map +1 -0
  27. package/dist/core/agent-loop/formatters.js +42 -0
  28. package/dist/core/agent-loop/index.d.ts +25 -0
  29. package/dist/core/agent-loop/index.d.ts.map +1 -0
  30. package/dist/core/agent-loop/index.js +83 -0
  31. package/dist/core/agent-loop/loop-state.d.ts +74 -0
  32. package/dist/core/agent-loop/loop-state.d.ts.map +1 -0
  33. package/dist/core/agent-loop/loop-state.js +147 -0
  34. package/dist/core/agent-loop/message-builder.d.ts +13 -0
  35. package/dist/core/agent-loop/message-builder.d.ts.map +1 -0
  36. package/dist/core/agent-loop/message-builder.js +49 -0
  37. package/dist/core/agent-loop/tool-executor.d.ts +23 -0
  38. package/dist/core/agent-loop/tool-executor.d.ts.map +1 -0
  39. package/dist/core/agent-loop/tool-executor.js +152 -0
  40. package/dist/core/agent-loop/turn-executor.d.ts +57 -0
  41. package/dist/core/agent-loop/turn-executor.d.ts.map +1 -0
  42. package/dist/core/agent-loop/turn-executor.js +124 -0
  43. package/dist/core/agent-loop/types.d.ts +141 -0
  44. package/dist/core/agent-loop/types.d.ts.map +1 -0
  45. package/dist/core/agent-loop/types.js +4 -0
  46. package/dist/core/agent-loop.d.ts +17 -0
  47. package/dist/core/agent-loop.d.ts.map +1 -0
  48. package/dist/core/agent-loop.js +16 -0
  49. package/dist/core/api-client-impl.d.ts +62 -0
  50. package/dist/core/api-client-impl.d.ts.map +1 -0
  51. package/dist/core/api-client-impl.js +479 -0
  52. package/dist/core/api-client.d.ts +6 -0
  53. package/dist/core/api-client.d.ts.map +1 -0
  54. package/dist/core/api-client.js +5 -0
  55. package/dist/core/checkpoints.d.ts +128 -0
  56. package/dist/core/checkpoints.d.ts.map +1 -0
  57. package/dist/core/checkpoints.js +438 -0
  58. package/dist/core/claude-md.d.ts +71 -0
  59. package/dist/core/claude-md.d.ts.map +1 -0
  60. package/dist/core/claude-md.js +198 -0
  61. package/dist/core/cognitive-security/hooks.d.ts +138 -0
  62. package/dist/core/cognitive-security/hooks.d.ts.map +1 -0
  63. package/dist/core/cognitive-security/hooks.js +389 -0
  64. package/dist/core/cognitive-security/index.d.ts +751 -0
  65. package/dist/core/cognitive-security/index.d.ts.map +1 -0
  66. package/dist/core/cognitive-security/index.js +1123 -0
  67. package/dist/core/cognitive-security/middleware.d.ts +136 -0
  68. package/dist/core/cognitive-security/middleware.d.ts.map +1 -0
  69. package/dist/core/cognitive-security/middleware.js +376 -0
  70. package/dist/core/config-loader.d.ts +127 -0
  71. package/dist/core/config-loader.d.ts.map +1 -0
  72. package/dist/core/config-loader.js +219 -0
  73. package/dist/core/context-compaction.d.ts +87 -0
  74. package/dist/core/context-compaction.d.ts.map +1 -0
  75. package/dist/core/context-compaction.js +428 -0
  76. package/dist/core/git-status.d.ts +25 -0
  77. package/dist/core/git-status.d.ts.map +1 -0
  78. package/dist/core/git-status.js +204 -0
  79. package/dist/core/image.d.ts +69 -0
  80. package/dist/core/image.d.ts.map +1 -0
  81. package/dist/core/image.js +290 -0
  82. package/dist/core/image.test.d.ts +2 -0
  83. package/dist/core/image.test.d.ts.map +1 -0
  84. package/dist/core/image.test.js +149 -0
  85. package/dist/core/models.d.ts +123 -0
  86. package/dist/core/models.d.ts.map +1 -0
  87. package/dist/core/models.js +325 -0
  88. package/dist/core/permissions.d.ts +81 -0
  89. package/dist/core/permissions.d.ts.map +1 -0
  90. package/dist/core/permissions.js +327 -0
  91. package/dist/core/retry.d.ts +25 -0
  92. package/dist/core/retry.d.ts.map +1 -0
  93. package/dist/core/retry.js +121 -0
  94. package/dist/core/session-store.d.ts +9 -0
  95. package/dist/core/session-store.d.ts.map +1 -0
  96. package/dist/core/session-store.js +10 -0
  97. package/dist/core/sessions/export.d.ts +47 -0
  98. package/dist/core/sessions/export.d.ts.map +1 -0
  99. package/dist/core/sessions/export.js +256 -0
  100. package/dist/core/sessions/index.d.ts +132 -0
  101. package/dist/core/sessions/index.d.ts.map +1 -0
  102. package/dist/core/sessions/index.js +442 -0
  103. package/dist/core/sessions/metadata.d.ts +77 -0
  104. package/dist/core/sessions/metadata.d.ts.map +1 -0
  105. package/dist/core/sessions/metadata.js +233 -0
  106. package/dist/core/sessions/persistence.d.ts +72 -0
  107. package/dist/core/sessions/persistence.d.ts.map +1 -0
  108. package/dist/core/sessions/persistence.js +201 -0
  109. package/dist/core/sessions/types.d.ts +110 -0
  110. package/dist/core/sessions/types.d.ts.map +1 -0
  111. package/dist/core/sessions/types.js +4 -0
  112. package/dist/core/stream-highlighter.d.ts +18 -0
  113. package/dist/core/stream-highlighter.d.ts.map +1 -0
  114. package/dist/core/stream-highlighter.js +916 -0
  115. package/dist/core/system-reminders.d.ts +89 -0
  116. package/dist/core/system-reminders.d.ts.map +1 -0
  117. package/dist/core/system-reminders.js +285 -0
  118. package/dist/ecosystem/hooks/__tests__/index.test.d.ts +5 -0
  119. package/dist/ecosystem/hooks/__tests__/index.test.d.ts.map +1 -0
  120. package/dist/ecosystem/hooks/__tests__/index.test.js +458 -0
  121. package/dist/ecosystem/hooks/index.d.ts +59 -0
  122. package/dist/ecosystem/hooks/index.d.ts.map +1 -0
  123. package/dist/ecosystem/hooks/index.js +294 -0
  124. package/dist/ecosystem/hooks/prompt-evaluator.d.ts +32 -0
  125. package/dist/ecosystem/hooks/prompt-evaluator.d.ts.map +1 -0
  126. package/dist/ecosystem/hooks/prompt-evaluator.js +229 -0
  127. package/dist/ecosystem/skills/index.d.ts +55 -0
  128. package/dist/ecosystem/skills/index.d.ts.map +1 -0
  129. package/dist/ecosystem/skills/index.js +258 -0
  130. package/dist/ecosystem/tools/__tests__/index.test.d.ts +7 -0
  131. package/dist/ecosystem/tools/__tests__/index.test.d.ts.map +1 -0
  132. package/dist/ecosystem/tools/__tests__/index.test.js +856 -0
  133. package/dist/ecosystem/tools/index.d.ts +24 -0
  134. package/dist/ecosystem/tools/index.d.ts.map +1 -0
  135. package/dist/ecosystem/tools/index.js +1709 -0
  136. package/dist/index.d.ts +24 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +33688 -49712
  139. package/dist/interfaces/mcp/client.d.ts +40 -0
  140. package/dist/interfaces/mcp/client.d.ts.map +1 -0
  141. package/dist/interfaces/mcp/client.js +309 -0
  142. package/dist/interfaces/ui/index.d.ts +36 -0
  143. package/dist/interfaces/ui/index.d.ts.map +1 -0
  144. package/dist/interfaces/ui/index.js +61 -0
  145. package/dist/interfaces/ui/spinner.d.ts +140 -0
  146. package/dist/interfaces/ui/spinner.d.ts.map +1 -0
  147. package/dist/interfaces/ui/spinner.js +342 -0
  148. package/dist/interfaces/ui/terminal/cli/index.d.ts +12 -0
  149. package/dist/interfaces/ui/terminal/cli/index.d.ts.map +1 -0
  150. package/dist/interfaces/ui/terminal/cli/index.js +32012 -50526
  151. package/dist/interfaces/ui/terminal/native/README.md +53 -0
  152. package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
  153. package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
  154. package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
  155. package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
  156. package/dist/interfaces/ui/terminal/native/index.js +43 -0
  157. package/dist/interfaces/ui/terminal/native/index.node +0 -0
  158. package/dist/interfaces/ui/terminal/native/package.json +34 -0
  159. package/dist/interfaces/ui/terminal/shared/args.d.ts +39 -0
  160. package/dist/interfaces/ui/terminal/shared/args.d.ts.map +1 -0
  161. package/dist/interfaces/ui/terminal/shared/args.js +176 -0
  162. package/dist/interfaces/ui/terminal/shared/index.d.ts +11 -0
  163. package/dist/interfaces/ui/terminal/shared/index.d.ts.map +1 -0
  164. package/dist/interfaces/ui/terminal/shared/index.js +16 -0
  165. package/dist/interfaces/ui/terminal/shared/loading-state.d.ts +124 -0
  166. package/dist/interfaces/ui/terminal/shared/loading-state.d.ts.map +1 -0
  167. package/dist/interfaces/ui/terminal/shared/loading-state.js +246 -0
  168. package/dist/interfaces/ui/terminal/shared/query.d.ts +22 -0
  169. package/dist/interfaces/ui/terminal/shared/query.d.ts.map +1 -0
  170. package/dist/interfaces/ui/terminal/shared/query.js +100 -0
  171. package/dist/interfaces/ui/terminal/shared/setup.d.ts +33 -0
  172. package/dist/interfaces/ui/terminal/shared/setup.d.ts.map +1 -0
  173. package/dist/interfaces/ui/terminal/shared/setup.js +226 -0
  174. package/dist/interfaces/ui/terminal/shared/status-line.d.ts +117 -0
  175. package/dist/interfaces/ui/terminal/shared/status-line.d.ts.map +1 -0
  176. package/dist/interfaces/ui/terminal/shared/status-line.js +267 -0
  177. package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts +38 -0
  178. package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts.map +1 -0
  179. package/dist/interfaces/ui/terminal/shared/system-prompt.js +102 -0
  180. package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts +39 -0
  181. package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts.map +1 -0
  182. package/dist/interfaces/ui/terminal/tui/HelpPanel.js +215 -0
  183. package/dist/interfaces/ui/terminal/tui/InputContext.d.ts +91 -0
  184. package/dist/interfaces/ui/terminal/tui/InputContext.d.ts.map +1 -0
  185. package/dist/interfaces/ui/terminal/tui/InputContext.js +154 -0
  186. package/dist/interfaces/ui/terminal/tui/InputField.d.ts +18 -0
  187. package/dist/interfaces/ui/terminal/tui/InputField.d.ts.map +1 -0
  188. package/dist/interfaces/ui/terminal/tui/InputField.js +41 -0
  189. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts +16 -0
  190. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts.map +1 -0
  191. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.js +451 -0
  192. package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts +10 -0
  193. package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts.map +1 -0
  194. package/dist/interfaces/ui/terminal/tui/MessageArea.js +91 -0
  195. package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts +48 -0
  196. package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts.map +1 -0
  197. package/dist/interfaces/ui/terminal/tui/MessageStore.js +151 -0
  198. package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts +9 -0
  199. package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts.map +1 -0
  200. package/dist/interfaces/ui/terminal/tui/StatusBar.js +36 -0
  201. package/dist/interfaces/ui/terminal/tui/commands.d.ts +21 -0
  202. package/dist/interfaces/ui/terminal/tui/commands.d.ts.map +1 -0
  203. package/dist/interfaces/ui/terminal/tui/commands.js +359 -0
  204. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts +115 -0
  205. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts.map +1 -0
  206. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.js +306 -0
  207. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts +92 -0
  208. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts.map +1 -0
  209. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.js +399 -0
  210. package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts +59 -0
  211. package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts.map +1 -0
  212. package/dist/interfaces/ui/terminal/tui/components/PaneManager.js +139 -0
  213. package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts +68 -0
  214. package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts.map +1 -0
  215. package/dist/interfaces/ui/terminal/tui/components/Sidebar.js +340 -0
  216. package/dist/interfaces/ui/terminal/tui/components/index.d.ts +23 -0
  217. package/dist/interfaces/ui/terminal/tui/components/index.d.ts.map +1 -0
  218. package/dist/interfaces/ui/terminal/tui/components/index.js +51 -0
  219. package/dist/interfaces/ui/terminal/tui/console.d.ts +20 -0
  220. package/dist/interfaces/ui/terminal/tui/console.d.ts.map +1 -0
  221. package/dist/interfaces/ui/terminal/tui/console.js +46 -0
  222. package/dist/interfaces/ui/terminal/tui/index.d.ts +20 -0
  223. package/dist/interfaces/ui/terminal/tui/index.d.ts.map +1 -0
  224. package/dist/interfaces/ui/terminal/tui/index.js +28 -0
  225. package/dist/interfaces/ui/terminal/tui/run.d.ts +13 -0
  226. package/dist/interfaces/ui/terminal/tui/run.d.ts.map +1 -0
  227. package/dist/interfaces/ui/terminal/tui/run.js +31 -0
  228. package/dist/interfaces/ui/terminal/tui/spinner.d.ts +44 -0
  229. package/dist/interfaces/ui/terminal/tui/spinner.d.ts.map +1 -0
  230. package/dist/interfaces/ui/terminal/tui/spinner.js +59 -0
  231. package/dist/interfaces/ui/terminal/tui/tui-app.d.ts +39 -0
  232. package/dist/interfaces/ui/terminal/tui/tui-app.d.ts.map +1 -0
  233. package/dist/interfaces/ui/terminal/tui/tui-app.js +198 -0
  234. package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts +167 -0
  235. package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts.map +1 -0
  236. package/dist/interfaces/ui/terminal/tui/tui-footer.js +330 -0
  237. package/dist/interfaces/ui/terminal/tui/types.d.ts +165 -0
  238. package/dist/interfaces/ui/terminal/tui/types.d.ts.map +1 -0
  239. package/dist/interfaces/ui/terminal/tui/types.js +5 -0
  240. package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts +23 -0
  241. package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts.map +1 -0
  242. package/dist/interfaces/ui/terminal/tui/useInputHandler.js +72 -0
  243. package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts +90 -0
  244. package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts.map +1 -0
  245. package/dist/interfaces/ui/terminal/tui/useNativeInput.js +188 -0
  246. package/dist/native/README.md +53 -0
  247. package/dist/native/claude_code_native.darwin-x64.node +0 -0
  248. package/dist/native/claude_code_native.dylib +0 -0
  249. package/dist/native/index.d.ts +0 -0
  250. package/dist/native/index.d.ts.map +1 -0
  251. package/dist/native/index.darwin-arm64.node +0 -0
  252. package/dist/native/index.js +43 -0
  253. package/dist/native/index.node +0 -0
  254. package/dist/native/package.json +34 -0
  255. package/dist/teammates/index.d.ts +161 -0
  256. package/dist/teammates/index.d.ts.map +1 -0
  257. package/dist/teammates/index.js +827 -0
  258. package/dist/types/index.d.ts +482 -0
  259. package/dist/types/index.d.ts.map +1 -0
  260. package/dist/types/index.js +52 -0
  261. package/native/index.darwin-arm64.node +0 -0
  262. package/native/index.js +33 -19
  263. package/package.json +6 -3
  264. package/packages/src/core/__tests__/permissions.test.ts +1091 -0
  265. package/packages/src/core/agent-loop/__tests__/compaction.test.ts +283 -0
  266. package/packages/src/core/agent-loop/__tests__/formatters.test.ts +234 -0
  267. package/packages/src/core/agent-loop/__tests__/index.test.ts +162 -0
  268. package/packages/src/core/agent-loop/__tests__/loop-state.test.ts +413 -0
  269. package/packages/src/core/agent-loop/__tests__/message-builder.test.ts +229 -0
  270. package/packages/src/core/agent-loop/__tests__/tool-executor.test.ts +457 -0
  271. package/packages/src/core/agent-loop/compaction.ts +92 -0
  272. package/packages/src/core/agent-loop/formatters.ts +50 -0
  273. package/packages/src/core/agent-loop/index.ts +137 -0
  274. package/packages/src/core/agent-loop/loop-state.ts +187 -0
  275. package/packages/src/core/agent-loop/message-builder.ts +62 -0
  276. package/packages/src/core/agent-loop/tool-executor.ts +211 -0
  277. package/packages/src/core/agent-loop/turn-executor.ts +226 -0
  278. package/packages/src/core/agent-loop/types.ts +152 -0
  279. package/packages/src/core/agent-loop.ts +18 -0
  280. package/packages/src/core/api-client-impl.ts +729 -0
  281. package/packages/src/core/api-client.ts +6 -0
  282. package/packages/src/core/checkpoints.ts +606 -0
  283. package/packages/src/core/claude-md.ts +272 -0
  284. package/packages/src/core/cognitive-security/hooks.ts +591 -0
  285. package/packages/src/core/cognitive-security/index.ts +2041 -0
  286. package/packages/src/core/cognitive-security/middleware.ts +536 -0
  287. package/packages/src/core/config/todo +7 -0
  288. package/packages/src/core/config-loader.ts +324 -0
  289. package/packages/src/core/context/__tests__/integration.test.ts +334 -0
  290. package/packages/src/core/context/compaction.ts +170 -0
  291. package/packages/src/core/context/constants.ts +58 -0
  292. package/packages/src/core/context/extraction.ts +85 -0
  293. package/packages/src/core/context/index.ts +66 -0
  294. package/packages/src/core/context/summarization.ts +251 -0
  295. package/packages/src/core/context/token-estimation.ts +98 -0
  296. package/packages/src/core/context/types.ts +59 -0
  297. package/packages/src/core/git-status.ts +262 -0
  298. package/packages/src/core/image.test.ts +180 -0
  299. package/packages/src/core/image.ts +350 -0
  300. package/packages/src/core/lmdb.db +0 -0
  301. package/packages/src/core/lmdb.db-lock +0 -0
  302. package/packages/src/core/models.ts +507 -0
  303. package/packages/src/core/normalizers/todo +8 -0
  304. package/packages/src/core/permissions.ts +431 -0
  305. package/packages/src/core/providers/README.md +230 -0
  306. package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
  307. package/packages/src/core/providers/index.ts +419 -0
  308. package/packages/src/core/providers/types.ts +132 -0
  309. package/packages/src/core/retry.ts +180 -0
  310. package/packages/src/core/session-store.ts +36 -0
  311. package/packages/src/core/sessions/export.ts +329 -0
  312. package/packages/src/core/sessions/index.ts +587 -0
  313. package/packages/src/core/sessions/metadata.ts +309 -0
  314. package/packages/src/core/sessions/persistence.ts +244 -0
  315. package/packages/src/core/sessions/types.ts +169 -0
  316. package/packages/src/core/stream-highlighter.ts +1123 -0
  317. package/packages/src/core/system-reminders.ts +402 -0
  318. package/packages/src/core/todo +8 -0
  319. package/packages/src/ecosystem/hooks/__tests__/index.test.ts +561 -0
  320. package/packages/src/ecosystem/hooks/index.ts +341 -0
  321. package/packages/src/ecosystem/hooks/prompt-evaluator.ts +300 -0
  322. package/packages/src/ecosystem/skills/index.ts +295 -0
  323. package/packages/src/ecosystem/tools/__tests__/index.test.ts +1335 -0
  324. package/packages/src/ecosystem/tools/index.ts +2051 -0
  325. package/packages/src/index.ts +141 -0
  326. package/packages/src/interfaces/mcp/client.ts +389 -0
  327. package/packages/src/interfaces/ui/index.ts +158 -0
  328. package/packages/src/interfaces/ui/lmdb.db +0 -0
  329. package/packages/src/interfaces/ui/lmdb.db-lock +0 -0
  330. package/packages/src/interfaces/ui/spinner.ts +451 -0
  331. package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
  332. package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
  333. package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
  334. package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
  335. package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
  336. package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
  337. package/packages/src/interfaces/ui/terminal/cli/index.ts +415 -0
  338. package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
  339. package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +393 -0
  340. package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
  341. package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
  342. package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
  343. package/packages/src/interfaces/ui/terminal/lmdb.db +0 -0
  344. package/packages/src/interfaces/ui/terminal/lmdb.db-lock +0 -0
  345. package/packages/src/interfaces/ui/terminal/shared/args.ts +222 -0
  346. package/packages/src/interfaces/ui/terminal/shared/index.ts +84 -0
  347. package/packages/src/interfaces/ui/terminal/shared/loading-state.ts +322 -0
  348. package/packages/src/interfaces/ui/terminal/shared/query.ts +152 -0
  349. package/packages/src/interfaces/ui/terminal/shared/setup.ts +299 -0
  350. package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
  351. package/packages/src/interfaces/ui/terminal/shared/status-line.ts +366 -0
  352. package/packages/src/interfaces/ui/terminal/shared/system-prompt.ts +146 -0
  353. package/packages/src/lmdb.db +0 -0
  354. package/packages/src/lmdb.db-lock +0 -0
  355. package/packages/src/native/index.ts +2722 -0
  356. package/packages/src/native/tui_v2_types.ts +39 -0
  357. package/packages/src/teammates/coordination.test.ts +279 -0
  358. package/packages/src/teammates/coordination.ts +646 -0
  359. package/packages/src/teammates/index.ts +1052 -0
  360. package/packages/src/teammates/integration.test.ts +272 -0
  361. package/packages/src/teammates/runner.test.ts +235 -0
  362. package/packages/src/teammates/runner.ts +750 -0
  363. package/packages/src/teammates/schemas.ts +673 -0
  364. package/packages/src/types/index.ts +723 -0
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Config Loader - Load Coder configuration files
3
+ *
4
+ * Loads from:
5
+ * 1. ~/.claude.json (MCP servers, project settings)
6
+ * 2. ~/.claude/settings.json (hooks, permissions)
7
+ * 3. ~/.claude/keybindings.json (keybindings)
8
+ * 4. .claude/settings.json (project-level overrides)
9
+ */
10
+
11
+ import { readFile, access } from "fs/promises";
12
+ import { join } from "path";
13
+ import type { MCPServerConfig, PermissionMode, HookDefinition, HookEvent } from "../types/index.js";
14
+
15
+ // ============================================
16
+ // TYPES
17
+ // ============================================
18
+
19
+ export interface ClaudeMainConfig {
20
+ numStartups?: number;
21
+ verbose?: boolean;
22
+ preferredNotifChannel?: "terminal_bell" | "notification";
23
+ projects?: Record<string, ProjectConfig>;
24
+ mcpServers?: Record<string, MCPServerConfig>;
25
+ }
26
+
27
+ export interface ProjectConfig {
28
+ allowedTools?: string[];
29
+ mcpServers?: Record<string, MCPServerConfig>;
30
+ enabledMcpjsonServers?: string[];
31
+ disabledMcpjsonServers?: string[];
32
+ hasTrustDialogAccepted?: boolean;
33
+ lastSessionId?: string;
34
+ }
35
+
36
+ export interface SettingsConfig {
37
+ hooks?: Partial<Record<HookEvent, HookMatcherConfig[]>>;
38
+ permissions?: {
39
+ defaultMode?: PermissionMode;
40
+ allowedTools?: string[];
41
+ disallowedTools?: string[];
42
+ };
43
+ }
44
+
45
+ export interface HookMatcherConfig {
46
+ matcher?: string;
47
+ hooks: Array<{
48
+ type: "command" | "prompt";
49
+ command?: string;
50
+ prompt?: string;
51
+ timeout?: number;
52
+ }>;
53
+ }
54
+
55
+ export interface KeybindingConfig {
56
+ bindings: Array<{
57
+ key: string;
58
+ command: string;
59
+ when?: string;
60
+ }>;
61
+ }
62
+
63
+ export interface LoadedConfig {
64
+ main: ClaudeMainConfig;
65
+ settings: SettingsConfig;
66
+ keybindings: KeybindingConfig;
67
+ projectSettings: SettingsConfig;
68
+ sources: string[];
69
+ }
70
+
71
+ // ============================================
72
+ // PATHS
73
+ // ============================================
74
+
75
+ const HOME = process.env.HOME || "";
76
+ const CLAUDE_DIR = join(HOME, ".claude");
77
+
78
+ export const CONFIG_PATHS = {
79
+ main: join(HOME, ".claude.json"),
80
+ settings: join(CLAUDE_DIR, "settings.json"),
81
+ keybindings: join(CLAUDE_DIR, "keybindings.json"),
82
+ projectSettings: (projectDir: string) => join(projectDir, ".claude", "settings.json"),
83
+ };
84
+
85
+ // ============================================
86
+ // HELPERS
87
+ // ============================================
88
+
89
+ async function fileExists(path: string): Promise<boolean> {
90
+ try {
91
+ await access(path);
92
+ return true;
93
+ } catch {
94
+ return false;
95
+ }
96
+ }
97
+
98
+ async function loadJsonFile<T>(path: string, defaultValue: T): Promise<{ config: T; loaded: boolean }> {
99
+ try {
100
+ if (await fileExists(path)) {
101
+ const content = await readFile(path, "utf-8");
102
+ return { config: JSON.parse(content) as T, loaded: true };
103
+ }
104
+ } catch (error) {
105
+ // File not readable or invalid JSON
106
+ }
107
+ return { config: defaultValue, loaded: false };
108
+ }
109
+
110
+ // ============================================
111
+ // LOADERS
112
+ // ============================================
113
+
114
+ /**
115
+ * Load main ~/.claude.json config
116
+ */
117
+ export async function loadMainConfig(): Promise<{ config: ClaudeMainConfig; loaded: boolean }> {
118
+ return loadJsonFile<ClaudeMainConfig>(CONFIG_PATHS.main, {});
119
+ }
120
+
121
+ /**
122
+ * Load settings from ~/.claude/settings.json
123
+ */
124
+ export async function loadSettings(): Promise<{ config: SettingsConfig; loaded: boolean }> {
125
+ return loadJsonFile<SettingsConfig>(CONFIG_PATHS.settings, {});
126
+ }
127
+
128
+ /**
129
+ * Load keybindings from ~/.claude/keybindings.json
130
+ */
131
+ export async function loadKeybindings(): Promise<{ config: KeybindingConfig; loaded: boolean }> {
132
+ return loadJsonFile<KeybindingConfig>(CONFIG_PATHS.keybindings, { bindings: [] });
133
+ }
134
+
135
+ /**
136
+ * Load project-level settings
137
+ */
138
+ export async function loadProjectSettings(
139
+ projectDir: string
140
+ ): Promise<{ config: SettingsConfig; loaded: boolean }> {
141
+ return loadJsonFile<SettingsConfig>(CONFIG_PATHS.projectSettings(projectDir), {});
142
+ }
143
+
144
+ /**
145
+ * Get project-specific config from main config
146
+ */
147
+ export function getProjectConfig(
148
+ mainConfig: ClaudeMainConfig,
149
+ projectDir: string
150
+ ): ProjectConfig | undefined {
151
+ return mainConfig.projects?.[projectDir];
152
+ }
153
+
154
+ /**
155
+ * Load all configs at once
156
+ */
157
+ export async function loadAllConfigs(projectDir: string = process.cwd()): Promise<LoadedConfig> {
158
+ const sources: string[] = [];
159
+
160
+ const { config: main, loaded: mainLoaded } = await loadMainConfig();
161
+ if (mainLoaded) sources.push(CONFIG_PATHS.main);
162
+
163
+ const { config: settings, loaded: settingsLoaded } = await loadSettings();
164
+ if (settingsLoaded) sources.push(CONFIG_PATHS.settings);
165
+
166
+ const { config: keybindings, loaded: kbLoaded } = await loadKeybindings();
167
+ if (kbLoaded) sources.push(CONFIG_PATHS.keybindings);
168
+
169
+ const { config: projectSettings, loaded: projLoaded } = await loadProjectSettings(projectDir);
170
+ if (projLoaded) sources.push(CONFIG_PATHS.projectSettings(projectDir));
171
+
172
+ return {
173
+ main,
174
+ settings,
175
+ keybindings,
176
+ projectSettings,
177
+ sources,
178
+ };
179
+ }
180
+
181
+ // ============================================
182
+ // MERGED CONFIG
183
+ // ============================================
184
+
185
+ /**
186
+ * Get merged settings (global + project overrides)
187
+ */
188
+ export function getMergedSettings(
189
+ global: SettingsConfig,
190
+ project: SettingsConfig
191
+ ): SettingsConfig {
192
+ return {
193
+ hooks: { ...global.hooks, ...project.hooks },
194
+ permissions: {
195
+ ...global.permissions,
196
+ ...project.permissions,
197
+ },
198
+ };
199
+ }
200
+
201
+ /**
202
+ * Get all MCP servers (global + project-specific)
203
+ */
204
+ export function getAllMCPServers(
205
+ mainConfig: ClaudeMainConfig,
206
+ projectDir: string
207
+ ): Record<string, MCPServerConfig> {
208
+ const servers: Record<string, MCPServerConfig> = {};
209
+
210
+ // Global MCP servers
211
+ if (mainConfig.mcpServers) {
212
+ Object.assign(servers, mainConfig.mcpServers);
213
+ }
214
+
215
+ // Project-specific MCP servers
216
+ const projectConfig = getProjectConfig(mainConfig, projectDir);
217
+ if (projectConfig?.mcpServers) {
218
+ // Project servers can override global
219
+ Object.assign(servers, projectConfig.mcpServers);
220
+ }
221
+
222
+ return servers;
223
+ }
224
+
225
+ // Note: HookDefinition is imported at the top of the file
226
+
227
+ /**
228
+ * Get hooks for a specific event and tool
229
+ */
230
+ export function getHooksForEvent(
231
+ settings: SettingsConfig,
232
+ event: HookEvent,
233
+ toolName?: string
234
+ ): HookMatcherConfig["hooks"] {
235
+ const eventHooks = settings.hooks?.[event];
236
+ if (!eventHooks) return [];
237
+
238
+ // Find matching hooks
239
+ for (const hookConfig of eventHooks) {
240
+ if (!hookConfig.matcher) {
241
+ // No matcher = matches all
242
+ return hookConfig.hooks;
243
+ }
244
+
245
+ // Check if tool name matches
246
+ if (toolName) {
247
+ const regex = new RegExp(hookConfig.matcher);
248
+ if (regex.test(toolName)) {
249
+ return hookConfig.hooks;
250
+ }
251
+ }
252
+ }
253
+
254
+ return [];
255
+ }
256
+
257
+ /**
258
+ * Convert settings hooks to HookDefinitions for HookManager
259
+ */
260
+ export function settingsToHookDefinitions(
261
+ settings: SettingsConfig
262
+ ): Partial<Record<HookEvent, HookDefinition[]>> {
263
+ const result: Partial<Record<HookEvent, HookDefinition[]>> = {};
264
+
265
+ if (!settings.hooks) return result;
266
+
267
+ for (const [event, matcherConfigs] of Object.entries(settings.hooks)) {
268
+ const definitions: HookDefinition[] = [];
269
+ const hookEvent = event as HookEvent;
270
+
271
+ for (const matcherConfig of matcherConfigs) {
272
+ for (const hook of matcherConfig.hooks) {
273
+ // Handle prompt-type hooks - they will be evaluated by LLM
274
+ if (hook.type === "prompt") {
275
+ definitions.push({
276
+ event: hookEvent,
277
+ command: "", // Not used for prompt hooks
278
+ prompt: hook.prompt || "",
279
+ timeout: hook.timeout || 30000,
280
+ enabled: true,
281
+ // Store matcher for runtime filtering
282
+ _matcher: matcherConfig.matcher,
283
+ } as HookDefinition & { _matcher?: string });
284
+ continue;
285
+ }
286
+ definitions.push({
287
+ event: hookEvent,
288
+ command: hook.type === "command" ? hook.command || "" : "",
289
+ timeout: hook.timeout || 60000,
290
+ enabled: true,
291
+ // Store matcher for runtime filtering
292
+ _matcher: matcherConfig.matcher,
293
+ } as HookDefinition & { _matcher?: string });
294
+ }
295
+ }
296
+
297
+ if (definitions.length > 0) {
298
+ result[hookEvent] = definitions;
299
+ }
300
+ }
301
+
302
+ return result;
303
+ }
304
+
305
+ /**
306
+ * Get permission mode from settings
307
+ */
308
+ export function getPermissionMode(settings: SettingsConfig): PermissionMode {
309
+ return settings.permissions?.defaultMode || "default";
310
+ }
311
+
312
+ /**
313
+ * Get allowed tools from settings
314
+ */
315
+ export function getAllowedTools(settings: SettingsConfig): Set<string> {
316
+ return new Set(settings.permissions?.allowedTools || []);
317
+ }
318
+
319
+ /**
320
+ * Get disallowed tools from settings
321
+ */
322
+ export function getDisallowedTools(settings: SettingsConfig): Set<string> {
323
+ return new Set(settings.permissions?.disallowedTools || []);
324
+ }
@@ -0,0 +1,334 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { compactMessages, needsCompaction, getCompactionStats } from "../compaction.js";
3
+ import { LoopState } from "../../agent-loop/loop-state.js";
4
+ import type { Message, ContentBlock } from "../../../types/index.js";
5
+
6
+ /**
7
+ * Integration tests for context compaction module
8
+ * Tests compaction, token estimation, and LoopState integration
9
+ */
10
+ describe("Context Compaction Integration", () => {
11
+ // Helper to create text content blocks
12
+ const textBlock = (text: string): ContentBlock => ({ type: "text", text });
13
+
14
+ // Helper to create messages
15
+ const userMessage = (content: string | ContentBlock[]): Message => ({
16
+ role: "user",
17
+ content: Array.isArray(content) ? content : [textBlock(content)]
18
+ });
19
+
20
+ const assistantMessage = (content: string | ContentBlock[]): Message => ({
21
+ role: "assistant",
22
+ content: Array.isArray(content) ? content : [textBlock(content)]
23
+ });
24
+
25
+ describe("needsCompaction", () => {
26
+ it("returns false for empty messages", () => {
27
+ const messages: Message[] = [];
28
+ const result = needsCompaction(messages, 1000);
29
+ expect(result).toBe(false);
30
+ });
31
+
32
+ it("returns false for small messages", () => {
33
+ const messages = [
34
+ userMessage("Hello"),
35
+ assistantMessage("Hi there!")
36
+ ];
37
+
38
+ const result = needsCompaction(messages, 100000);
39
+ expect(result).toBe(false);
40
+ });
41
+
42
+ it("returns true when exceeding threshold", () => {
43
+ // Add many large messages to exceed threshold
44
+ const messages: Message[] = [];
45
+ for (let i = 0; i < 100; i++) {
46
+ messages.push(userMessage("This is a test message ".repeat(100)));
47
+ messages.push(assistantMessage("This is a response message ".repeat(100)));
48
+ }
49
+
50
+ const result = needsCompaction(messages, 1000);
51
+ expect(result).toBe(true);
52
+ });
53
+ });
54
+
55
+ describe("compactMessages", () => {
56
+ it("compacts messages while preserving first and last", async () => {
57
+ const messages: Message[] = [];
58
+
59
+ // First messages (to preserve)
60
+ messages.push(userMessage("Initial question"));
61
+ messages.push(assistantMessage("Initial response"));
62
+
63
+ // Middle messages (to summarize)
64
+ for (let i = 0; i < 20; i++) {
65
+ messages.push(userMessage(`User question ${i}: ` + "test ".repeat(50)));
66
+ messages.push(assistantMessage(`Assistant answer ${i}: ` + "response ".repeat(50)));
67
+ }
68
+
69
+ // Last messages (to preserve)
70
+ messages.push(userMessage("Final question"));
71
+ messages.push(assistantMessage("Final response"));
72
+
73
+ // Use lower maxTokens to ensure compaction triggers
74
+ const result = await compactMessages(messages, 500, {
75
+ keepFirst: 2,
76
+ keepLast: 2,
77
+ useLLMSummarization: false
78
+ });
79
+
80
+ // Verify compaction occurred
81
+ expect(result.didCompact).toBe(true);
82
+ expect(result.messages.length).toBeLessThan(messages.length);
83
+ expect(result.messages.length).toBeGreaterThan(0);
84
+ expect(result.tokensAfter).toBeLessThan(result.tokensBefore);
85
+
86
+ // Verify first messages preserved
87
+ expect(result.messages[0]).toEqual(messages[0]);
88
+ expect(result.messages[1]).toEqual(messages[1]);
89
+
90
+ // Verify last messages preserved
91
+ const lastIdx = result.messages.length - 1;
92
+ expect(result.messages[lastIdx - 1]).toEqual(messages[messages.length - 2]);
93
+ expect(result.messages[lastIdx]).toEqual(messages[messages.length - 1]);
94
+
95
+ // Verify summary inserted
96
+ const hasSummary = result.messages.some(m =>
97
+ m.content.some(block =>
98
+ block.type === "text" &&
99
+ (block as any).text?.includes("compacted")
100
+ )
101
+ );
102
+ expect(hasSummary).toBe(true);
103
+ });
104
+
105
+ it("handles empty messages gracefully", async () => {
106
+ const messages: Message[] = [];
107
+
108
+ const result = await compactMessages(messages, 1000);
109
+
110
+ expect(result.messages).toEqual([]);
111
+ expect(result.didCompact).toBe(false);
112
+ });
113
+
114
+ it("returns unchanged if under token limit", async () => {
115
+ const messages = [
116
+ userMessage("Hello"),
117
+ assistantMessage("Hi!")
118
+ ];
119
+
120
+ const result = await compactMessages(messages, 100000);
121
+
122
+ expect(result.didCompact).toBe(false);
123
+ expect(result.messages).toEqual(messages);
124
+ });
125
+
126
+ it("preserves tool use and tool result pairs", async () => {
127
+ const messages: Message[] = [
128
+ userMessage("Read the file"),
129
+ {
130
+ role: "assistant",
131
+ content: [
132
+ textBlock("I'll read the file."),
133
+ { type: "tool_use", id: "tool-1", name: "Read", input: { file_path: "/test.txt" } }
134
+ ]
135
+ },
136
+ {
137
+ role: "user",
138
+ content: [
139
+ { type: "tool_result", tool_use_id: "tool-1", content: "File contents here" }
140
+ ]
141
+ },
142
+ assistantMessage("The file contains test data.")
143
+ ];
144
+
145
+ const result = await compactMessages(messages, 500, {
146
+ keepFirst: 1,
147
+ keepLast: 1,
148
+ preserveToolPairs: true,
149
+ useLLMSummarization: false
150
+ });
151
+
152
+ // Should have compacted with tool pairs preserved
153
+ expect(result.messages.length).toBeGreaterThan(0);
154
+ });
155
+ });
156
+
157
+ describe("getCompactionStats", () => {
158
+ it("returns zero stats for no compaction", () => {
159
+ const result = {
160
+ messages: [],
161
+ messagesRemoved: 0,
162
+ tokensBefore: 100,
163
+ tokensAfter: 100,
164
+ didCompact: false
165
+ };
166
+
167
+ const stats = getCompactionStats(result);
168
+
169
+ expect(stats.reductionPercent).toBe(0);
170
+ expect(stats.tokensSaved).toBe(0);
171
+ });
172
+
173
+ it("calculates correct stats after compaction", () => {
174
+ const result = {
175
+ messages: [],
176
+ messagesRemoved: 50,
177
+ tokensBefore: 1000,
178
+ tokensAfter: 300,
179
+ didCompact: true
180
+ };
181
+
182
+ const stats = getCompactionStats(result);
183
+
184
+ expect(stats.tokensSaved).toBe(700);
185
+ expect(stats.reductionPercent).toBeCloseTo(70, 0);
186
+ });
187
+ });
188
+
189
+ describe("LoopState integration", () => {
190
+ it("LoopState.applyCompaction works with compactMessages result", async () => {
191
+ const initialMessages: Message[] = [];
192
+ for (let i = 0; i < 30; i++) {
193
+ initialMessages.push(userMessage(`Message ${i}: ` + "x".repeat(100)));
194
+ initialMessages.push(assistantMessage(`Response ${i}: ` + "y".repeat(100)));
195
+ }
196
+
197
+ const loopState = new LoopState(initialMessages);
198
+
199
+ // Compact
200
+ const compactionResult = await compactMessages(loopState.messages, 5000, {
201
+ keepFirst: 2,
202
+ keepLast: 4,
203
+ useLLMSummarization: false
204
+ });
205
+
206
+ // Apply to state
207
+ const applied = loopState.applyCompaction(compactionResult, getCompactionStats);
208
+
209
+ if (compactionResult.didCompact) {
210
+ expect(applied).toBe(true);
211
+ expect(loopState.messages.length).toBeLessThan(initialMessages.length);
212
+ expect(loopState.compactionCount).toBe(1);
213
+ expect(loopState.totalTokensCompacted).toBeGreaterThan(0);
214
+ }
215
+ });
216
+ });
217
+
218
+ describe("extraction and summarization integration", () => {
219
+ it("extracts text correctly from mixed content blocks", async () => {
220
+ const messages: Message[] = [
221
+ {
222
+ role: "user",
223
+ content: [
224
+ textBlock("Here's my question:"),
225
+ { type: "image", source: { type: "base64", media_type: "image/png", data: "abc123" } } as ContentBlock,
226
+ textBlock("Please help with this.")
227
+ ]
228
+ },
229
+ assistantMessage("I'll help you with that.")
230
+ ];
231
+
232
+ const result = await compactMessages(messages, 500, {
233
+ useLLMSummarization: false
234
+ });
235
+
236
+ // Text should be handled, image preserved or summarized
237
+ expect(result.messages.length).toBeGreaterThan(0);
238
+ });
239
+
240
+ it("summarizes long conversations effectively", async () => {
241
+ const messages: Message[] = [
242
+ userMessage("I need to build a REST API"),
243
+ assistantMessage("I'll help you build a REST API. What framework?"),
244
+ userMessage("Express.js"),
245
+ assistantMessage("Great choice. Let's set up routes.")
246
+ ];
247
+
248
+ // Add more conversation to ensure we exceeds token limit
249
+ for (let i = 0; i < 30; i++) {
250
+ messages.push(userMessage(`Question about route ${i}: ` + "test ".repeat(100)));
251
+ messages.push(assistantMessage(`Answer about route ${i}: ` + "response ".repeat(100)));
252
+ }
253
+
254
+ // Use a very low token limit to force compaction
255
+ const result = await compactMessages(messages, 100, {
256
+ keepFirst: 2,
257
+ keepLast: 4,
258
+ useLLMSummarization: false
259
+ });
260
+
261
+ // Should have summary of earlier conversation
262
+ expect(result.didCompact).toBe(true);
263
+ expect(result.messages.length).toBeLessThan(messages.length);
264
+ expect(result.messagesRemoved).toBeGreaterThan(0);
265
+ });
266
+ });
267
+
268
+ describe("performance with large contexts", () => {
269
+ it("handles 100+ messages efficiently", async () => {
270
+ const messages: Message[] = [];
271
+
272
+ // Add 100 messages
273
+ for (let i = 0; i < 100; i++) {
274
+ messages.push(userMessage(`User ${i}: ` + "test ".repeat(20)));
275
+ messages.push(assistantMessage(`Assistant ${i}: ` + "response ".repeat(20)));
276
+ }
277
+
278
+ const startTime = Date.now();
279
+
280
+ const result = await compactMessages(messages, 5000, {
281
+ keepFirst: 2,
282
+ keepLast: 4,
283
+ useLLMSummarization: false
284
+ });
285
+
286
+ const duration = Date.now() - startTime;
287
+
288
+ // Should complete in reasonable time (< 5s for integration test)
289
+ expect(duration).toBeLessThan(5000);
290
+ expect(result.didCompact).toBe(true);
291
+ expect(result.messages.length).toBeLessThan(200);
292
+ });
293
+ });
294
+
295
+ describe("error handling and edge cases", () => {
296
+ it("handles messages with empty content", async () => {
297
+ const messages: Message[] = [
298
+ { role: "user", content: [] },
299
+ { role: "assistant", content: [] }
300
+ ];
301
+
302
+ const result = await compactMessages(messages, 1000);
303
+
304
+ expect(result.messages).toBeDefined();
305
+ expect(result.didCompact).toBe(false);
306
+ });
307
+
308
+ it("handles malformed content blocks gracefully", async () => {
309
+ const messages: Message[] = [
310
+ {
311
+ role: "user",
312
+ content: [
313
+ { type: "unknown" } as unknown as ContentBlock,
314
+ textBlock("Valid text")
315
+ ]
316
+ }
317
+ ];
318
+
319
+ const result = await compactMessages(messages, 1000);
320
+
321
+ expect(result.messages.length).toBeGreaterThan(0);
322
+ });
323
+
324
+ it("handles very large single messages", async () => {
325
+ const hugeText = "x".repeat(100000);
326
+ const messages = [userMessage(hugeText)];
327
+
328
+ const result = await compactMessages(messages, 1000);
329
+
330
+ // Should return as-is (not enough messages to compact)
331
+ expect(result.messages.length).toBe(1);
332
+ });
333
+ });
334
+ });