@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,2722 @@
1
+ /**
2
+ * Native module loader
3
+ * Loads Rust-compiled native modules for performance-critical operations
4
+ */
5
+
6
+ import { dlopen, suffix } from "bun:ffi";
7
+ import { join, dirname } from "path";
8
+ import { fileURLToPath } from "url";
9
+
10
+ // Type definitions for native module exports
11
+
12
+ export interface HighlightResult {
13
+ /** ANSI-colored text (for terminal display) */
14
+ html: string;
15
+ /** Theme used for highlighting */
16
+ theme: string;
17
+ }
18
+
19
+ export interface HighlightDiffResult {
20
+ /** ANSI-colored diff output */
21
+ output: string;
22
+ /** Number of added lines */
23
+ additions: number;
24
+ /** Number of deleted lines */
25
+ deletions: number;
26
+ /** Number of hunks */
27
+ hunks: number;
28
+ }
29
+
30
+ export interface DiffOptions {
31
+ /** File path to display in header */
32
+ file_path?: string;
33
+ /** Number of context lines around changes (default: 3) */
34
+ context_lines?: number;
35
+ }
36
+
37
+ // ===== Multi-File Edit Types =====
38
+
39
+ /** A single edit operation for multi-file editing */
40
+ export interface MultiEditEntry {
41
+ /** File path to edit (absolute path) */
42
+ filePath: string;
43
+ /** String to find and replace */
44
+ oldString: string;
45
+ /** Replacement string */
46
+ newString: string;
47
+ /** Replace all occurrences (default: false) */
48
+ replaceAll?: boolean;
49
+ }
50
+
51
+ /** Result of an atomic multi-file edit operation */
52
+ export interface MultiEditResult {
53
+ /** Whether all edits succeeded */
54
+ success: boolean;
55
+ /** List of files that were modified */
56
+ filesModified: string[];
57
+ /** Total number of string replacements made */
58
+ totalReplacements: number;
59
+ /** Error message if operation failed */
60
+ error?: string;
61
+ /** Whether changes were rolled back due to failure */
62
+ rolledBack: boolean;
63
+ }
64
+
65
+ /** Preview result for a single file */
66
+ export interface MultiEditPreviewEntry {
67
+ /** File path */
68
+ filePath: string;
69
+ /** Number of replacements that would be made */
70
+ replacementCount: number;
71
+ }
72
+
73
+ // ===== Grep Types =====
74
+
75
+ /** Options for grep search operations */
76
+ export interface GrepQueryOptions {
77
+ /** Case insensitive matching */
78
+ caseInsensitive?: boolean;
79
+ /** Maximum number of results to return */
80
+ maxResults?: number;
81
+ /** Glob patterns for files to include */
82
+ includePatterns?: string[];
83
+ /** Glob patterns for files/dirs to exclude */
84
+ excludePatterns?: string[];
85
+ /** Treat pattern as literal string (no regex) */
86
+ literal?: boolean;
87
+ /** Match whole words only */
88
+ wholeWord?: boolean;
89
+ /** Invert match (show non-matching lines) */
90
+ invert?: boolean;
91
+ /** Enable multiline matching */
92
+ multiline?: boolean;
93
+ /** Number of context lines (sets both before and after) */
94
+ contextLines?: number;
95
+ /** Number of lines to show before match */
96
+ contextBefore?: number;
97
+ /** Number of lines to show after match */
98
+ contextAfter?: number;
99
+ /** Maximum directory depth */
100
+ maxDepth?: number;
101
+ /** Follow symbolic links */
102
+ followSymlinks?: boolean;
103
+ /** Skip hidden files and directories */
104
+ skipHidden?: boolean;
105
+ /** Respect .gitignore rules */
106
+ respectGitignore?: boolean;
107
+ /** Skip binary files */
108
+ skipBinary?: boolean;
109
+ /** Maximum file size in bytes */
110
+ maxFilesize?: number;
111
+ /** File extensions to include */
112
+ extensions?: string[];
113
+ }
114
+
115
+ /** A single grep match result */
116
+ export interface GrepMatch {
117
+ /** File path containing the match */
118
+ path: string;
119
+ /** 1-based line number */
120
+ line: number;
121
+ /** 1-based column number */
122
+ column: number;
123
+ /** The matched line content */
124
+ content: string;
125
+ /** Length of the match in bytes */
126
+ matchLength: number;
127
+ /** Lines before the match (for context) */
128
+ contextBefore: string[];
129
+ /** Lines after the match (for context) */
130
+ contextAfter: string[];
131
+ }
132
+
133
+ /** Result of a grep search operation */
134
+ export interface GrepResult {
135
+ /** Total number of matches found */
136
+ totalCount: number;
137
+ /** All matches found */
138
+ matches: GrepMatch[];
139
+ /** Number of files searched */
140
+ filesSearched: number;
141
+ /** Number of files skipped */
142
+ filesSkipped: number;
143
+ /** Time spent searching in milliseconds */
144
+ durationMs: number;
145
+ }
146
+
147
+ /** Count result per file */
148
+ export interface GrepCountResult {
149
+ /** File path */
150
+ path: string;
151
+ /** Number of matches in this file */
152
+ count: number;
153
+ /** Number of lines in this file */
154
+ lineCount: number;
155
+ }
156
+
157
+ /** Result for files-with-matches mode */
158
+ export interface GrepFilesResult {
159
+ /** List of file paths containing matches */
160
+ files: string[];
161
+ /** Total number of files with matches */
162
+ totalMatches: number;
163
+ }
164
+
165
+ // ===== Quant Types =====
166
+
167
+ /** OHLCV candlestick data */
168
+ // ===== TUI v2 Types =====
169
+
170
+ export interface RenderMessage {
171
+ role: string;
172
+ content: string;
173
+ }
174
+
175
+ export interface RenderState {
176
+ messages: RenderMessage[];
177
+ inputValue: string;
178
+ cursorPos: number;
179
+ statusText: string;
180
+ isLoading: boolean;
181
+ streamingText: string;
182
+ model: string;
183
+ showHelp: boolean;
184
+ helpText: string;
185
+ searchMode: boolean;
186
+ searchQuery: string;
187
+ searchResults: SearchResult[];
188
+ searchSelected: number;
189
+ }
190
+
191
+ export interface InputEvent {
192
+ eventType: "key" | "resize" | "none";
193
+ key?: string;
194
+ modifiers?: string;
195
+ newWidth?: number;
196
+ newHeight?: number;
197
+ }
198
+
199
+ export interface SearchResult {
200
+ filePath: string;
201
+ lineNumber: number;
202
+ content: string;
203
+ }
204
+
205
+ export interface OHLCV {
206
+ timestamp: number;
207
+ open: number;
208
+ high: number;
209
+ low: number;
210
+ close: number;
211
+ volume: number;
212
+ }
213
+
214
+ /** AMM state for constant-product AMMs */
215
+ export interface AMMState {
216
+ pool_yes: number;
217
+ pool_no: number;
218
+ k: number;
219
+ fee: number;
220
+ price_yes: number;
221
+ price_no: number;
222
+ }
223
+
224
+ /** AMM cost calculation result */
225
+ export interface AMMCostResult {
226
+ cost: number;
227
+ avg_price: number;
228
+ }
229
+
230
+ /** AMM price impact result */
231
+ export interface AMMPriceImpactResult {
232
+ price_before: number;
233
+ price_after: number;
234
+ price_impact: number;
235
+ slippage: number;
236
+ }
237
+
238
+ /** LMSR price result */
239
+ export interface LMSRPriceResult {
240
+ yes_price: number;
241
+ no_price: number;
242
+ spread: number;
243
+ }
244
+
245
+ /** Arbitrage detection result */
246
+ export interface ArbitrageResult {
247
+ has_arbitrage: boolean;
248
+ yes_price: number;
249
+ no_price: number;
250
+ total: number;
251
+ profit_per_share: number;
252
+ }
253
+
254
+ /** Odds conversion result */
255
+ export interface OddsConversion {
256
+ probability: number;
257
+ decimal_odds: number;
258
+ american_odds: number;
259
+ }
260
+
261
+ /** Value at Risk result */
262
+ export interface VaRResult {
263
+ var: number;
264
+ cvar: number;
265
+ confidence_level: number;
266
+ }
267
+
268
+ /** Drawdown analysis result */
269
+ export interface DrawdownResult {
270
+ max_drawdown: number;
271
+ max_duration: number;
272
+ current_drawdown: number;
273
+ recovery_factor: number;
274
+ }
275
+
276
+ /** Sharpe ratio result */
277
+ export interface SharpeResult {
278
+ sharpe_ratio: number;
279
+ annualized_sharpe: number;
280
+ risk_free_rate: number;
281
+ avg_return: number;
282
+ std_dev: number;
283
+ }
284
+
285
+ // ===== Terminal Input Types =====
286
+
287
+ /** Native key event from terminal */
288
+ export interface NativeKeyEvent {
289
+ /** The key code (character or special key name) */
290
+ code: string;
291
+ /** Whether this is a special key (arrow, function, etc.) */
292
+ is_special: boolean;
293
+ /** Ctrl modifier */
294
+ ctrl: boolean;
295
+ /** Alt/Meta modifier */
296
+ alt: boolean;
297
+ /** Shift modifier */
298
+ shift: boolean;
299
+ /** Event kind: "press", "release", "repeat" */
300
+ kind: "press" | "release" | "repeat";
301
+ }
302
+
303
+ /** Terminal handle for raw mode input */
304
+ export interface TerminalHandle {
305
+ /** Enter raw terminal mode */
306
+ enterRawMode(): void;
307
+ /** Exit raw terminal mode */
308
+ exitRawMode(): void;
309
+ /** Check if in raw mode (getter) */
310
+ readonly isRawMode: boolean;
311
+ /** Poll for a key event (non-blocking), returns null if no event */
312
+ pollEvent(timeoutMs?: number): NativeKeyEvent | null;
313
+ /** Read next key event (blocking, async) */
314
+ readEvent(): Promise<NativeKeyEvent>;
315
+ }
316
+
317
+ // ===== Native TUI Types =====
318
+
319
+ /** Message for display in the native TUI */
320
+ export interface TuiMessage {
321
+ id: string;
322
+ role: "user" | "assistant" | "system";
323
+ content: string;
324
+ timestamp?: number;
325
+ subType?: string;
326
+ toolName?: string;
327
+ isError?: boolean;
328
+ }
329
+
330
+ /** TUI state for rendering */
331
+ export interface TuiState {
332
+ messages: TuiMessage[];
333
+ inputValue: string;
334
+ cursorPos: number;
335
+ isLoading: boolean;
336
+ spinnerFrame: number;
337
+ model: string;
338
+ tokensUsed: number;
339
+ permissionMode: string;
340
+ streamingText: string;
341
+ scrollOffset: number;
342
+ contextWarning?: string;
343
+ }
344
+
345
+ /** Result of handling input in native TUI */
346
+ export interface InputResult {
347
+ submitted: boolean;
348
+ text?: string;
349
+ exitRequested: boolean;
350
+ command?: string;
351
+ scrollUp: boolean;
352
+ scrollDown: boolean;
353
+ inputValue: string;
354
+ cursorPos: number;
355
+ historyNavigated: boolean;
356
+ historyDirection: number;
357
+ }
358
+
359
+ /** Native TUI handle from Rust */
360
+ export interface NativeTuiHandle {
361
+ init(): void;
362
+ cleanup(): void;
363
+ render(state: TuiState): void;
364
+ pollInput(state: TuiState, timeoutMs?: number): InputResult;
365
+ addToHistory(input: string): void;
366
+ }
367
+
368
+ export interface NativeModule {
369
+ /** Syntax highlight code with ANSI escape codes */
370
+ highlight_code: (code: string, language: string) => HighlightResult;
371
+
372
+ /** Highlight markdown with nested code block syntax highlighting */
373
+ highlight_markdown: (markdown: string) => HighlightResult;
374
+
375
+ /** Highlight a diff with ANSI colors */
376
+ highlight_diff: (oldText: string, newText: string, options?: DiffOptions) => HighlightDiffResult;
377
+
378
+ // ===== Grep Functions =====
379
+
380
+ /** Legacy search_files (deprecated, use grep_search instead) */
381
+ search_files: (
382
+ pattern: string,
383
+ path: string,
384
+ options: {
385
+ case_insensitive?: boolean;
386
+ hidden?: boolean;
387
+ glob?: string;
388
+ max_results?: number;
389
+ }
390
+ ) => {
391
+ matches: Array<{
392
+ file_path: string;
393
+ line_number: number;
394
+ column: number;
395
+ line_content: string;
396
+ match_text: string;
397
+ }>;
398
+ total_count: number;
399
+ files_searched: number;
400
+ };
401
+
402
+ /** Search for pattern in files with full options */
403
+ grep_search: (pattern: string, path: string, options?: GrepQueryOptions) => Promise<GrepResult>;
404
+
405
+ /** Count matches per file */
406
+ grep_count: (pattern: string, path: string, options?: GrepQueryOptions) => Promise<GrepCountResult[]>;
407
+
408
+ /** List files containing matches */
409
+ grep_files: (pattern: string, path: string, options?: GrepQueryOptions) => Promise<GrepFilesResult>;
410
+
411
+ // ===== Token Functions =====
412
+
413
+ count_tokens: (text: string) => number;
414
+
415
+ calculate_diff: (
416
+ oldText: string,
417
+ newText: string
418
+ ) => Array<{
419
+ oldStart: number;
420
+ oldLines: number;
421
+ newStart: number;
422
+ newLines: number;
423
+ content: string;
424
+ }>;
425
+
426
+ compact_content: (
427
+ content: string,
428
+ maxTokens: number,
429
+ strategy?: "truncate" | "summarize" | "extract"
430
+ ) => string;
431
+
432
+ count_tool_use: (
433
+ messages: Array<{
434
+ role: string;
435
+ tool_use?: Array<{ name: string; input?: any }>;
436
+ tool_result?: Array<any>;
437
+ }>
438
+ ) => Record<string, number>;
439
+
440
+ find_tool_pairs: (
441
+ messages: Array<{
442
+ role: string;
443
+ tool_use?: Array<{ name: string; input?: any }>;
444
+ tool_result?: Array<any>;
445
+ }>,
446
+ window_size: number
447
+ ) => Record<string, Record<string, number>>;
448
+
449
+ find_common_patterns: (
450
+ messages: Array<{
451
+ role: string;
452
+ tool_use?: Array<{ name: string; input?: any }>;
453
+ tool_result?: Array<any>;
454
+ }>
455
+ ) => Array<{
456
+ tools: [string, string];
457
+ count: number;
458
+ percentage: number;
459
+ }>;
460
+
461
+ // Multi-file editing
462
+ /** Validate multi-file edits without applying them */
463
+ validate_multi_edits: (edits: MultiEditEntry[]) => string[];
464
+
465
+ /** Preview what edits would be applied without making changes */
466
+ preview_multi_edits: (edits: MultiEditEntry[]) => MultiEditPreviewEntry[];
467
+
468
+ /** Apply multiple file edits atomically with rollback on failure */
469
+ apply_multi_edits: (edits: MultiEditEntry[]) => MultiEditResult;
470
+
471
+ // ===== Quant Functions =====
472
+
473
+ /** Get library version */
474
+ quant_version: () => string;
475
+
476
+ // OHLCV
477
+ quant_ohlcv_new: (timestamp: bigint, open: number, high: number, low: number, close: number, volume: number) => string;
478
+
479
+ // AMM (Automated Market Maker)
480
+ quant_amm_new: (poolYes: number, poolNo: number, fee: number) => string;
481
+ quant_amm_calculate_cost: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
482
+ quant_amm_price_impact: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
483
+
484
+ // LMSR (Logarithmic Market Scoring Rule)
485
+ quant_lmsr_price: (yesShares: number, noShares: number, b: number) => string;
486
+ quant_lmsr_cost: (yesShares: number, noShares: number, b: number, buyYes: boolean, shares: number) => string;
487
+
488
+ // Arbitrage
489
+ quant_detect_arbitrage: (yesPrice: number, noPrice: number) => string;
490
+
491
+ // Odds Conversion
492
+ quant_convert_odds: (value: number, fromType: number) => string;
493
+
494
+ // Statistics
495
+ quant_mean: (data: Float64Array) => number;
496
+ quant_std_dev: (data: Float64Array) => number;
497
+ quant_variance: (data: Float64Array) => number;
498
+ quant_correlation: (x: Float64Array, y: Float64Array) => number;
499
+
500
+ // ===== Cognitive Security - Action Module =====
501
+
502
+ /** Classify an operation into an action type */
503
+ classify_operation: (operation: string, domain: string, target?: string | null, reasoning?: string | null) => any;
504
+
505
+ /** Get all supported action types */
506
+ get_action_types: () => string[];
507
+
508
+ /** Get risk levels for all action types */
509
+ get_action_risk_levels: () => Array<{ actionType: string; riskLevel: number }>;
510
+
511
+ /** Create a deny-all policy */
512
+ create_deny_all_policy: () => any;
513
+
514
+ /** Create an observe-only policy */
515
+ create_observe_only_policy: () => any;
516
+
517
+ /** Create a transfer approval policy */
518
+ create_transfer_approval_policy: () => any;
519
+
520
+ // ===== Cognitive Security - Intent Module =====
521
+
522
+ /** Generate a new Ed25519 keypair for signing intents */
523
+ cs_generate_keypair: () => { privateKey: string; publicKey: string };
524
+
525
+ /** Sign an agent intent with a private key */
526
+ cs_sign_intent: (intent: any, privateKey: string) => any;
527
+
528
+ /** Verify an intent's signature */
529
+ cs_verify_intent: (intent: any) => any;
530
+
531
+ /** Hash an intent for comparison */
532
+ cs_hash_intent: (intent: any) => string;
533
+
534
+ /** Check if two intents are equivalent */
535
+ cs_intents_equivalent: (intent1: any, intent2: any) => boolean;
536
+
537
+ /** Score how well an action aligns with an intent */
538
+ cs_score_alignment: (action: any, intent: any) => any;
539
+
540
+ /** Batch score multiple actions against an intent */
541
+ cs_batch_score_alignment: (actions: any[], intent: any) => any[];
542
+
543
+ /** Check if any action in a sequence would violate intent */
544
+ cs_check_sequence_violations: (actions: any[], intent: any) => number[];
545
+
546
+ /** Load intent from a JSON file */
547
+ cs_load_intent: (path: string) => any;
548
+
549
+ /** Save intent to a JSON file */
550
+ cs_save_intent: (intent: any, path: string) => void;
551
+
552
+ /** Parse intent from JSON string */
553
+ cs_parse_intent: (json: string) => any;
554
+
555
+ /** Serialize intent to JSON string */
556
+ cs_serialize_intent: (intent: any) => string;
557
+
558
+ /** Validate intent structure */
559
+ cs_validate_intent: (intent: any) => any;
560
+
561
+ /** Create a default data collector intent */
562
+ cs_create_data_collector_intent: (name: string, description: string) => any;
563
+
564
+ /** Merge two intents (child overrides parent) */
565
+ cs_merge_intents: (base: any, override: any) => any;
566
+
567
+ /** Analyze behavior for signs of intent corruption */
568
+ cs_analyze_corruption: (snapshot: any, intent: any) => any;
569
+
570
+ /** Detect behavioral drift between two snapshots */
571
+ cs_detect_drift: (baseline: any, current: any) => any;
572
+
573
+ /** Create an empty behavior snapshot */
574
+ cs_create_empty_snapshot: () => any;
575
+
576
+ /** Update a snapshot with a new action result */
577
+ cs_update_snapshot: (snapshot: any, action: any, alignment: any) => any;
578
+
579
+ // ===== Cognitive Security - Flow Module =====
580
+
581
+ /** Classify data based on content and source */
582
+ classify_data: (content: string, source: string, tags: string[]) => any;
583
+
584
+ /** Check if content contains sensitive data */
585
+ contains_sensitive_data: (content: string) => boolean;
586
+
587
+ /** Redact sensitive content */
588
+ redact_sensitive: (content: string, replacement?: string | null) => string;
589
+
590
+ /** Get sensitivity levels */
591
+ get_sensitivity_levels: () => Array<{ name: string; value: number; description: string }>;
592
+
593
+ /** Get data categories */
594
+ get_data_categories: () => Array<{ name: string; description: string }>;
595
+
596
+ /** Create a flow policy engine */
597
+ create_flow_policy_engine: () => any;
598
+
599
+ /** Create an allow-all flow policy */
600
+ create_allow_all_flow_policy: () => any;
601
+
602
+ /** Create a deny-all flow policy */
603
+ create_deny_all_flow_policy: () => any;
604
+
605
+ /** Create a strict flow policy */
606
+ create_strict_flow_policy: () => any;
607
+
608
+ /** Create a flow tracker */
609
+ create_flow_tracker: () => any;
610
+
611
+ /** Create a leak prevention engine */
612
+ create_leak_prevention: () => any;
613
+
614
+ /** Check content for leaks */
615
+ check_for_leaks: (content: string, channel: string) => any;
616
+
617
+ /** Sanitize content */
618
+ sanitize_content: (content: string) => string;
619
+
620
+ /** Create a taint tracker */
621
+ create_taint_tracker: () => any;
622
+
623
+ // ===== Terminal Input =====
624
+
625
+ /** Create a terminal handle for raw mode input */
626
+ create_terminal: () => TerminalHandle;
627
+
628
+ // ===== Native TUI =====
629
+
630
+ /** Create a native TUI handle */
631
+ create_tui: () => NativeTuiHandle;
632
+
633
+ /** Check if native TUI is available */
634
+ is_native_tui_available: () => boolean;
635
+ }
636
+
637
+ let nativeModule: NativeModule | null = null;
638
+
639
+ /**
640
+ * Load the native module
641
+ */
642
+ export function loadNative(): NativeModule {
643
+ if (nativeModule) {
644
+ return nativeModule;
645
+ }
646
+
647
+ // Try multiple possible locations for the native module
648
+ const __dirname = dirname(fileURLToPath(import.meta.url));
649
+ const basePaths = [
650
+ join(__dirname, "..", "native"), // dist/../native (library entry)
651
+ join(__dirname, "..", "..", "native"), // dist/foo/../native
652
+ join(__dirname, "..", "..", "..", "native"), // dist/foo/bar/../native
653
+ join(__dirname, "..", "..", "..", "..", "native"), // dist/interfaces/ui/../native
654
+ join(__dirname, "..", "..", "..", "..", "..", "native"), // dist/interfaces/ui/terminal/../native
655
+ join(__dirname, "..", "..", "..", "..", "..", "..", "native"), // CLI entry: dist/interfaces/ui/terminal/cli/../native
656
+ join(__dirname, "native"), // native/ (if running from project root)
657
+ ];
658
+
659
+ // Try .node files first (NAPI modules)
660
+ const nodeFiles = ["index.darwin-arm64.node", "index.darwin-x64.node", "index.node"];
661
+
662
+ for (const basePath of basePaths) {
663
+ for (const file of nodeFiles) {
664
+ const nativePath = join(basePath, file);
665
+ try {
666
+ // Try to load NAPI module directly
667
+ const native = require(nativePath);
668
+ if (native && (native.highlightCode || native.highlight_code)) {
669
+ // Map camelCase to snake_case if needed
670
+ nativeModule = {
671
+ highlight_code: native.highlightCode || native.highlight_code,
672
+ highlight_markdown: native.highlightMarkdown || native.highlight_markdown,
673
+ highlight_diff: native.highlightDiff || native.highlight_diff,
674
+ search_files: native.searchFiles || native.search_files,
675
+ count_tokens: native.countTokens || native.count_tokens,
676
+ calculate_diff: native.calculateDiff || native.calculate_diff,
677
+ compact_content: native.compactContent || native.compact_content,
678
+ count_tool_use: native.countToolUse || native.count_tool_use,
679
+ find_tool_pairs: native.findToolPairs || native.find_tool_pairs,
680
+ find_common_patterns: native.findCommonPatterns || native.find_common_patterns,
681
+ validate_multi_edits: native.validateMultiEdits || native.validate_multi_edits,
682
+ preview_multi_edits: native.previewMultiEdits || native.preview_multi_edits,
683
+ apply_multi_edits: native.applyMultiEdits || native.apply_multi_edits,
684
+
685
+ // Grep functions (NAPI exports camelCase for async functions)
686
+ grep_search: native.grepSearch,
687
+ grep_count: native.grepCount,
688
+ grep_files: native.grepFiles,
689
+
690
+ // Cognitive Security - Action Module (NAPI exports camelCase)
691
+ classify_operation: native.classifyOperation,
692
+ get_action_types: native.getActionTypes,
693
+ get_action_risk_levels: native.getActionRiskLevels,
694
+ create_deny_all_policy: native.createDenyAllPolicy,
695
+ create_observe_only_policy: native.createObserveOnlyPolicy,
696
+ create_transfer_approval_policy: native.createTransferApprovalPolicy,
697
+
698
+ // Cognitive Security - Intent Module (NAPI exports camelCase)
699
+ cs_generate_keypair: native.generateIntentKeypair,
700
+ cs_sign_intent: native.signIntent,
701
+ cs_verify_intent: native.verifyIntentSignature,
702
+ cs_hash_intent: native.hashIntent,
703
+ cs_intents_equivalent: native.intentsEquivalent,
704
+ cs_score_alignment: native.scoreAlignment,
705
+ cs_batch_score_alignment: native.batchScoreAlignment,
706
+ cs_check_sequence_violations: native.checkSequenceViolations,
707
+ cs_load_intent: native.loadIntentFromFile,
708
+ cs_save_intent: native.saveIntentToFile,
709
+ cs_parse_intent: native.parseIntent,
710
+ cs_serialize_intent: native.serializeIntent,
711
+ cs_validate_intent: native.validateIntentStructure,
712
+ cs_create_data_collector_intent: native.createDataCollectorIntent,
713
+ cs_merge_intents: native.mergeIntents,
714
+ cs_analyze_corruption: native.analyzeCorruption,
715
+ cs_detect_drift: native.detectBehavioralDrift,
716
+ cs_create_empty_snapshot: native.createEmptySnapshot,
717
+ cs_update_snapshot: native.updateSnapshot,
718
+
719
+ // Cognitive Security - Flow Module (NAPI exports camelCase)
720
+ classify_data: native.classifyData,
721
+ contains_sensitive_data: native.containsSensitiveData,
722
+ redact_sensitive: native.redactSensitive,
723
+ get_sensitivity_levels: native.getSensitivityLevels,
724
+ get_data_categories: native.getDataCategories,
725
+ create_flow_policy_engine: native.createFlowPolicyEngine,
726
+ create_allow_all_flow_policy: native.createAllowAllFlowPolicy,
727
+ create_deny_all_flow_policy: native.createDenyAllFlowPolicy,
728
+ create_strict_flow_policy: native.createStrictFlowPolicy,
729
+ create_flow_tracker: native.createFlowTracker,
730
+ create_leak_prevention: native.createLeakPrevention,
731
+ check_for_leaks: native.checkForLeaks,
732
+ sanitize_content: native.sanitizeContent,
733
+ create_taint_tracker: native.createTaintTracker,
734
+
735
+ // Quant Functions
736
+ quant_version: native.quantVersion || native.quant_version,
737
+ quant_ohlcv_new: native.quantOhlcvNew || native.quant_ohlcv_new,
738
+ quant_amm_new: native.quantAmmNew || native.quant_amm_new,
739
+ quant_amm_calculate_cost: native.quantAmmCalculateCost || native.quant_amm_calculate_cost,
740
+ quant_amm_price_impact: native.quantAmmPriceImpact || native.quant_amm_price_impact,
741
+ quant_lmsr_price: native.quantLmsrPrice || native.quant_lmsr_price,
742
+ quant_lmsr_cost: native.quantLmsrCost || native.quant_lmsr_cost,
743
+ quant_detect_arbitrage: native.quantDetectArbitrage || native.quant_detect_arbitrage,
744
+ quant_convert_odds: native.quantConvertOdds || native.quant_convert_odds,
745
+ quant_mean: native.quantMean || native.quant_mean,
746
+ quant_std_dev: native.quantStdDev || native.quant_std_dev,
747
+ quant_variance: native.quantVariance || native.quant_variance,
748
+ quant_correlation: native.quantCorrelation || native.quant_correlation,
749
+
750
+ // Terminal Input
751
+ create_terminal: native.createTerminal || native.create_terminal,
752
+
753
+ // Native TUI
754
+ create_tui: native.createTui || native.create_tui,
755
+ is_native_tui_available: () => typeof (native.createTui || native.create_tui) === 'function',
756
+ };
757
+ return nativeModule;
758
+ }
759
+ } catch {
760
+ // Try next path
761
+ continue;
762
+ }
763
+ }
764
+ }
765
+
766
+ // Try FFI with dylib
767
+ const dylibPaths = basePaths.map(p => join(p, `claude_code_native.${suffix}`));
768
+
769
+ for (const nativePath of dylibPaths) {
770
+ try {
771
+ const lib = dlopen(nativePath, {
772
+ highlight_code: {
773
+ args: ["cstring", "cstring"],
774
+ returns: "pointer",
775
+ },
776
+ highlight_markdown: {
777
+ args: ["cstring"],
778
+ returns: "pointer",
779
+ },
780
+ highlight_diff: {
781
+ args: ["cstring", "cstring", "pointer"],
782
+ returns: "pointer",
783
+ },
784
+ search_files: {
785
+ args: ["cstring", "cstring", "pointer"],
786
+ returns: "pointer",
787
+ },
788
+ count_tokens: {
789
+ args: ["cstring"],
790
+ returns: "u32",
791
+ },
792
+ calculate_diff: {
793
+ args: ["cstring", "cstring"],
794
+ returns: "pointer",
795
+ },
796
+ compact_content: {
797
+ args: ["cstring", "u32", "cstring"],
798
+ returns: "pointer",
799
+ },
800
+ },
801
+ );
802
+
803
+ nativeModule = lib.symbols as unknown as NativeModule;
804
+ return nativeModule;
805
+ } catch {
806
+ continue;
807
+ }
808
+ }
809
+
810
+ // No native module found, use fallback
811
+ console.warn("Native module not available, using JS fallback");
812
+ return getFallbackModule();
813
+ }
814
+
815
+ /**
816
+ * Check if native module is available
817
+ */
818
+ export function isNativeAvailable(): boolean {
819
+ try {
820
+ loadNative();
821
+ return nativeModule !== null;
822
+ } catch {
823
+ return false;
824
+ }
825
+ }
826
+
827
+ /**
828
+ * Fallback implementations in pure JavaScript
829
+ */
830
+ function getFallbackModule(): NativeModule {
831
+ return {
832
+ highlight_code: (code: string, language: string): HighlightResult => {
833
+ // ANSI color codes
834
+ const colors = {
835
+ reset: "\x1b[0m",
836
+ keyword: "\x1b[38;2;180;142;173m", // purple
837
+ string: "\x1b[38;2;163;190;140m", // green
838
+ number: "\x1b[38;2;208;135;112m", // orange
839
+ type: "\x1b[38;2;191;97;106m", // red
840
+ function: "\x1b[38;2;143;161;179m", // blue
841
+ comment: "\x1b[38;2;108;153;139m", // gray-green
842
+ default: "\x1b[38;2;192;197;206m", // gray
843
+ special: "\x1b[38;2;150;180;210m", // light blue
844
+ arrow: "\x1b[38;2;200;160;120m", // gold/tan
845
+ };
846
+
847
+ // Mermaid-specific highlighting
848
+ if (language.toLowerCase() === "mermaid" || language.toLowerCase() === "mmd") {
849
+ const MERMAID_KEYWORDS = new Set([
850
+ // Diagram types
851
+ "graph", "flowchart", "sequenceDiagram", "classDiagram", "stateDiagram",
852
+ "erDiagram", "journey", "gantt", "pie", "gitGraph", "mindmap", "timeline",
853
+ "quadrantChart", "requirementDiagram", "C4Context", "C4Container",
854
+ "C4Component", "C4Dynamic", "C4Deployment",
855
+ // Directions
856
+ "TB", "TD", "BT", "RL", "LR", "left", "right", "top", "bottom",
857
+ // Subgraphs/participants
858
+ "subgraph", "end", "participant", "actor", "as",
859
+ // Flowchart
860
+ "node", "click", "link", "href", "callback",
861
+ // Sequence
862
+ "Note", "over", "loop", "alt", "else", "opt", "par", "rect", "autonumber",
863
+ "activate", "deactivate",
864
+ // Class
865
+ "class", "namespace", "interface", "annotation", "service", "enum",
866
+ // State
867
+ "state", "note", "fork", "join", "choice",
868
+ // ER
869
+ "entity",
870
+ // Gantt
871
+ "dateFormat", "title", "section", "excludes", "includes", "todayMarker",
872
+ // Common
873
+ "title", "accTitle", "accDescr",
874
+ ]);
875
+
876
+ const MERMAID_ARROWS = new Set([
877
+ "-->", "---", "->", "->>", "-.", "-.-", "==>", "==", "--x", "--o",
878
+ "<--", "<-", "<<-", "<-->", "<->", "o--o", "x--x", "-x", "-o",
879
+ ]);
880
+
881
+ const MERMAID_SHAPES = [
882
+ ["[", "]"], // rect
883
+ ["(", ")"], // rounded
884
+ ["([", "])"], // stadium
885
+ ["[[", "]]"], // subroutine
886
+ ["[((", ")]"], // cylinder
887
+ [">", "]"], // asymmetric
888
+ ["{", "}"], // rhombus
889
+ ["{{", "}}"], // hexagon
890
+ ["[/", "/]"], // parallelogram
891
+ ["[\\", "\\]"], // parallelogram alt
892
+ ["[(", ")]"], // circle
893
+ ["(((", ")))"], // double circle
894
+ ];
895
+
896
+ const lines = code.split("\n");
897
+ const highlighted = lines.map(line => {
898
+ let result = line;
899
+
900
+ // Comments (%%)
901
+ if (line.trim().startsWith("%%")) {
902
+ return `${colors.comment}${line}${colors.reset}`;
903
+ }
904
+
905
+ // Arrows and connections (handle first to preserve them)
906
+ for (const arrow of MERMAID_ARROWS) {
907
+ const escaped = arrow.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
908
+ result = result.replace(new RegExp(escaped, 'g'), `${colors.arrow}${arrow}${colors.default}`);
909
+ }
910
+
911
+ // Strings (quoted)
912
+ result = result.replace(/"([^"\\]|\\.)*"/g, match => {
913
+ return `${colors.string}${match}${colors.default}`;
914
+ });
915
+
916
+ // Numbers
917
+ result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
918
+
919
+ // Keywords
920
+ result = result.replace(/\b([A-Za-z_][A-Za-z0-9_]*)\b/g, (match) => {
921
+ if (MERMAID_KEYWORDS.has(match)) {
922
+ return `${colors.keyword}${match}${colors.default}`;
923
+ }
924
+ return match;
925
+ });
926
+
927
+ // Special characters for shapes
928
+ for (const [open, close] of MERMAID_SHAPES) {
929
+ if (!open || !close) continue;
930
+ const openEsc = open.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
931
+ const closeEsc = close.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
932
+ result = result.replace(new RegExp(`${openEsc}([^${closeEsc}]+)${closeEsc}`, 'g'), (_, content) => {
933
+ return `${colors.special}${open}${content}${close}${colors.default}`;
934
+ });
935
+ }
936
+
937
+ // Arrow labels
938
+ result = result.replace(/\|([^|]+)\|/g, (_, content) => {
939
+ return `${colors.special}|${content}|${colors.default}`;
940
+ });
941
+
942
+ return result;
943
+ }).join("\n");
944
+
945
+ return {
946
+ html: highlighted + colors.reset,
947
+ theme: "mermaid",
948
+ };
949
+ }
950
+
951
+ // Standard code highlighting
952
+ const KEYWORDS = new Set([
953
+ "function", "const", "let", "var", "return", "if", "else", "for", "while",
954
+ "class", "interface", "type", "import", "export", "from", "async", "await",
955
+ "try", "catch", "throw", "new", "this", "extends", "implements", "static",
956
+ "public", "private", "protected", "readonly", "abstract", "enum", "namespace",
957
+ ]);
958
+
959
+ const TYPES = new Set([
960
+ "string", "number", "boolean", "void", "null", "undefined", "any", "never",
961
+ "object", "symbol", "bigint", "true", "false",
962
+ ]);
963
+
964
+ // Simple tokenization
965
+ const lines = code.split("\n");
966
+ const highlighted = lines.map(line => {
967
+ // Comments
968
+ if (line.trim().startsWith("//") || line.trim().startsWith("#")) {
969
+ return `${colors.comment}${line}${colors.reset}`;
970
+ }
971
+
972
+ // Replace strings
973
+ let result = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, match => {
974
+ return `${colors.string}${match}${colors.default}`;
975
+ });
976
+
977
+ // Replace numbers
978
+ result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
979
+
980
+ // Replace keywords
981
+ result = result.replace(/\b([a-z]+)\b/gi, (match) => {
982
+ if (KEYWORDS.has(match)) {
983
+ return `${colors.keyword}${match}${colors.default}`;
984
+ }
985
+ if (TYPES.has(match)) {
986
+ return `${colors.type}${match}${colors.default}`;
987
+ }
988
+ return match;
989
+ });
990
+
991
+ // Function names (before parentheses)
992
+ result = result.replace(/\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g, (_, name) => {
993
+ return `${colors.function}${name}${colors.default}(`;
994
+ });
995
+
996
+ return result;
997
+ }).join("\n");
998
+
999
+ return {
1000
+ html: highlighted + colors.reset,
1001
+ theme: "fallback",
1002
+ };
1003
+ },
1004
+
1005
+ highlight_markdown: (markdown: string): HighlightResult => {
1006
+ // Simple markdown highlighting - just return as-is with reset
1007
+ // Full nested code block highlighting requires native module
1008
+ return {
1009
+ html: markdown + "\x1b[0m",
1010
+ theme: "fallback",
1011
+ };
1012
+ },
1013
+
1014
+ highlight_diff: (oldText: string, newText: string, options?: DiffOptions): HighlightDiffResult => {
1015
+ // Simple line-based diff with ANSI colors
1016
+ const GREEN = "\x1b[38;2;163;190;140m";
1017
+ const RED = "\x1b[38;2;191;97;106m";
1018
+ const DIM = "\x1b[38;2;108;153;139m";
1019
+ const CYAN = "\x1b[38;2;143;161;179m";
1020
+ const RESET = "\x1b[0m";
1021
+
1022
+ const oldLines = oldText.split("\n");
1023
+ const newLines = newText.split("\n");
1024
+
1025
+ let output = "";
1026
+ let additions = 0;
1027
+ let deletions = 0;
1028
+ let hunks = 0;
1029
+
1030
+ // File header
1031
+ if (options?.file_path) {
1032
+ output += `${CYAN}${options.file_path}${RESET}\n`;
1033
+ }
1034
+
1035
+ // Simple LCS-based diff
1036
+ const lcs: string[] = [];
1037
+ const dp: number[][] = Array.from({ length: oldLines.length + 1 }, () =>
1038
+ Array.from({ length: newLines.length + 1 }, () => 0)
1039
+ );
1040
+
1041
+ for (let i = 0; i <= oldLines.length; i++) {
1042
+ for (let j = 0; j <= newLines.length; j++) {
1043
+ if (i === 0 || j === 0) {
1044
+ dp[i]![j] = 0;
1045
+ } else if (oldLines[i - 1] === newLines[j - 1]) {
1046
+ dp[i]![j] = dp[i - 1]![j - 1]! + 1;
1047
+ } else {
1048
+ dp[i]![j] = Math.max(dp[i - 1]![j]!, dp[i]![j - 1]!);
1049
+ }
1050
+ }
1051
+ }
1052
+
1053
+ // Backtrack for LCS
1054
+ let i = oldLines.length;
1055
+ let j = newLines.length;
1056
+ const lcsSet = new Set<string>();
1057
+ while (i > 0 && j > 0) {
1058
+ if (oldLines[i - 1] === newLines[j - 1]) {
1059
+ lcsSet.add(`${i - 1}:${j - 1}`);
1060
+ lcs.unshift(oldLines[i - 1]!);
1061
+ i--;
1062
+ j--;
1063
+ } else if (dp[i - 1]![j]! > dp[i]![j - 1]!) {
1064
+ i--;
1065
+ } else {
1066
+ j--;
1067
+ }
1068
+ }
1069
+
1070
+ // Build diff output
1071
+ let oldIdx = 0;
1072
+ let newIdx = 0;
1073
+ let lcsIdx = 0;
1074
+
1075
+ while (oldIdx < oldLines.length || newIdx < newLines.length) {
1076
+ // Skip matching lines
1077
+ while (
1078
+ lcsIdx < lcs.length &&
1079
+ oldIdx < oldLines.length &&
1080
+ newIdx < newLines.length &&
1081
+ oldLines[oldIdx] === lcs[lcsIdx] &&
1082
+ newLines[newIdx] === lcs[lcsIdx]
1083
+ ) {
1084
+ oldIdx++;
1085
+ newIdx++;
1086
+ lcsIdx++;
1087
+ }
1088
+
1089
+ const oldStart = oldIdx + 1;
1090
+ const newStart = newIdx + 1;
1091
+ let oldCount = 0;
1092
+ let newCount = 0;
1093
+ const hunkLines: string[] = [];
1094
+
1095
+ // Collect removed lines
1096
+ while (
1097
+ oldIdx < oldLines.length &&
1098
+ (lcsIdx >= lcs.length || oldLines[oldIdx] !== lcs[lcsIdx])
1099
+ ) {
1100
+ hunkLines.push(`${RED}-${oldLines[oldIdx]}${RESET}`);
1101
+ oldIdx++;
1102
+ oldCount++;
1103
+ deletions++;
1104
+ }
1105
+
1106
+ // Collect added lines
1107
+ while (
1108
+ newIdx < newLines.length &&
1109
+ (lcsIdx >= lcs.length || newLines[newIdx] !== lcs[lcsIdx])
1110
+ ) {
1111
+ hunkLines.push(`${GREEN}+${newLines[newIdx]}${RESET}`);
1112
+ newIdx++;
1113
+ newCount++;
1114
+ additions++;
1115
+ }
1116
+
1117
+ if (oldCount > 0 || newCount > 0) {
1118
+ hunks++;
1119
+ output += `${DIM}@@ -${oldStart},${oldCount} +${newStart},${newCount} @@${RESET}\n`;
1120
+ output += hunkLines.join("\n") + "\n";
1121
+ }
1122
+ }
1123
+
1124
+ return { output, additions, deletions, hunks };
1125
+ },
1126
+
1127
+ search_files: (pattern, path, options) => {
1128
+ // Simple grep fallback
1129
+ return {
1130
+ matches: [],
1131
+ total_count: 0,
1132
+ files_searched: 0,
1133
+ };
1134
+ },
1135
+
1136
+ count_tokens: (text: string): number => {
1137
+ // Sophisticated fallback matching Rust implementation
1138
+ if (!text || text.length === 0) return 0;
1139
+
1140
+ const bytes = text.length;
1141
+
1142
+ // Count whitespace
1143
+ const whitespace = text.split('').filter(c => /\s/.test(c)).length;
1144
+
1145
+ // Count punctuation
1146
+ const punctuation = text.split('').filter(c => /[^\w\s]/.test(c)).length;
1147
+
1148
+ // Detect if this is code (heuristic)
1149
+ const isCode = text.includes('{') ||
1150
+ text.includes('}') ||
1151
+ text.includes(';') ||
1152
+ text.includes('fn ') ||
1153
+ text.includes('function') ||
1154
+ text.includes('const ') ||
1155
+ text.includes('let ') ||
1156
+ text.includes('import ');
1157
+
1158
+ // Base estimate: ~4 characters per token
1159
+ const baseEstimate = Math.floor(bytes / 4);
1160
+
1161
+ // Adjust for code (typically more tokens)
1162
+ const codeAdjustment = isCode ? Math.floor(bytes / 10) : 0;
1163
+
1164
+ // Adjust for whitespace (tokens are often split on whitespace)
1165
+ const whitespaceAdjustment = Math.floor(whitespace * 0.2);
1166
+
1167
+ // Adjust for punctuation
1168
+ const punctuationAdjustment = Math.floor(punctuation * 0.5);
1169
+
1170
+ // Combine estimates, minimum 1
1171
+ return Math.max(1, baseEstimate + codeAdjustment + whitespaceAdjustment + punctuationAdjustment);
1172
+ },
1173
+
1174
+ calculate_diff: (oldText, newText) => {
1175
+ // Simple line-based diff
1176
+ const oldLines = oldText.split("\n");
1177
+ const newLines = newText.split("\n");
1178
+ const hunks: Array<{
1179
+ oldStart: number;
1180
+ oldLines: number;
1181
+ newStart: number;
1182
+ newLines: number;
1183
+ content: string;
1184
+ }> = [];
1185
+
1186
+ // Very simple diff - just show all changes as one hunk
1187
+ if (oldText !== newText) {
1188
+ hunks.push({
1189
+ oldStart: 1,
1190
+ oldLines: oldLines.length,
1191
+ newStart: 1,
1192
+ newLines: newLines.length,
1193
+ content: `- ${oldLines.join("\n- ")}\n+ ${newLines.join("\n+ ")}`,
1194
+ });
1195
+ }
1196
+
1197
+ return hunks;
1198
+ },
1199
+
1200
+ compact_content: (content, maxTokens, strategy = "truncate") => {
1201
+ const charsPerToken = 4;
1202
+ const maxChars = maxTokens * charsPerToken;
1203
+
1204
+ if (content.length <= maxChars) {
1205
+ return content;
1206
+ }
1207
+
1208
+ switch (strategy) {
1209
+ case "truncate": {
1210
+ // Smart truncation: find paragraph or sentence boundary
1211
+ const half = Math.floor(maxChars / 2);
1212
+ const searchStart = Math.max(0, half - 100);
1213
+ const searchEnd = Math.min(content.length, half + 100);
1214
+
1215
+ // Try to find paragraph break
1216
+ let breakPoint = half;
1217
+ for (let i = searchEnd; i >= searchStart; i--) {
1218
+ if (content[i] === '\n' && content[i + 1] === '\n') {
1219
+ breakPoint = i;
1220
+ break;
1221
+ }
1222
+ }
1223
+
1224
+ return (
1225
+ content.slice(0, breakPoint) +
1226
+ "\n\n... [content truncated: " + Math.floor((content.length - maxChars) / charsPerToken) + " tokens omitted] ...\n\n" +
1227
+ content.slice(-half)
1228
+ );
1229
+ }
1230
+ case "summarize": {
1231
+ // Return beginning, key sections, and end
1232
+ const lines = content.split("\n");
1233
+ const firstCount = Math.min(20, Math.floor(lines.length / 4));
1234
+ const lastCount = Math.min(20, Math.floor(lines.length / 4));
1235
+ const quarter = Math.floor(maxChars / 4);
1236
+
1237
+ let result = "=== BEGINNING ===\n";
1238
+ result += lines.slice(0, firstCount).join("\n").slice(0, quarter) + "\n\n";
1239
+
1240
+ result += "=== KEY LINES ===\n";
1241
+ const importantLines = lines.filter(line => {
1242
+ const t = line.trim();
1243
+ return t.startsWith('#') ||
1244
+ t.startsWith('function') ||
1245
+ t.startsWith('const') ||
1246
+ t.startsWith('class') ||
1247
+ t.startsWith('export') ||
1248
+ t.startsWith('import') ||
1249
+ t.startsWith('async ') ||
1250
+ t.startsWith('pub fn') ||
1251
+ t.startsWith('fn ');
1252
+ });
1253
+ result += importantLines.slice(0, 20).join("\n").slice(0, quarter) + "\n\n";
1254
+
1255
+ result += "=== END ===\n";
1256
+ result += lines.slice(-lastCount).join("\n").slice(0, quarter);
1257
+
1258
+ return result;
1259
+ }
1260
+ case "extract": {
1261
+ // Extract structure (headings, declarations, etc.)
1262
+ const lines = content.split("\n");
1263
+ const result: string[] = [];
1264
+ let currentChars = 0;
1265
+ let inCodeBlock = false;
1266
+
1267
+ for (const line of lines) {
1268
+ // Track code blocks
1269
+ if (line.trim().startsWith('```')) {
1270
+ inCodeBlock = !inCodeBlock;
1271
+ }
1272
+
1273
+ const trimmed = line.trim();
1274
+
1275
+ // Include important lines
1276
+ const isImportant =
1277
+ trimmed.startsWith('#') ||
1278
+ trimmed.startsWith('##') ||
1279
+ trimmed.startsWith('###') ||
1280
+ trimmed.startsWith('function ') ||
1281
+ trimmed.startsWith('const ') ||
1282
+ trimmed.startsWith('let ') ||
1283
+ trimmed.startsWith('class ') ||
1284
+ trimmed.startsWith('interface ') ||
1285
+ trimmed.startsWith('type ') ||
1286
+ trimmed.startsWith('export ') ||
1287
+ trimmed.startsWith('import ') ||
1288
+ trimmed.startsWith('async ') ||
1289
+ trimmed.startsWith('pub fn') ||
1290
+ trimmed.startsWith('fn ') ||
1291
+ trimmed.startsWith('struct ') ||
1292
+ trimmed.startsWith('impl ') ||
1293
+ trimmed.startsWith('// TODO') ||
1294
+ trimmed.startsWith('// FIXME') ||
1295
+ trimmed.startsWith('// NOTE');
1296
+
1297
+ if (isImportant && currentChars + line.length < maxChars) {
1298
+ result.push(line);
1299
+ currentChars += line.length + 1;
1300
+ }
1301
+ }
1302
+
1303
+ return result.length > 0 ? result.join("\n") : content.slice(0, maxChars);
1304
+ }
1305
+ default:
1306
+ return content.slice(0, maxChars);
1307
+ }
1308
+ },
1309
+
1310
+ // Multi-file editing fallback implementation
1311
+ validate_multi_edits: (edits: MultiEditEntry[]): string[] => {
1312
+ const errors: string[] = [];
1313
+ const fileContents = new Map<string, string>();
1314
+ const fs = require('fs');
1315
+
1316
+ for (const edit of edits) {
1317
+ // Check file exists
1318
+ try {
1319
+ if (!fs.existsSync(edit.filePath)) {
1320
+ errors.push(`File not found: ${edit.filePath}`);
1321
+ continue;
1322
+ }
1323
+
1324
+ // Load file content if not already loaded
1325
+ if (!fileContents.has(edit.filePath)) {
1326
+ const content = fs.readFileSync(edit.filePath, 'utf-8');
1327
+ fileContents.set(edit.filePath, content);
1328
+ }
1329
+
1330
+ const content = fileContents.get(edit.filePath)!;
1331
+
1332
+ // Check oldString exists
1333
+ if (!content.includes(edit.oldString)) {
1334
+ errors.push(`String not found in ${edit.filePath}: "${truncateString(edit.oldString, 50)}"`);
1335
+ continue;
1336
+ }
1337
+
1338
+ // Check uniqueness if not replaceAll
1339
+ if (!edit.replaceAll) {
1340
+ const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
1341
+ if (count > 1) {
1342
+ errors.push(`String appears ${count} times in ${edit.filePath}. Use replaceAll or provide more context.`);
1343
+ }
1344
+ }
1345
+ } catch (err) {
1346
+ errors.push(`Error reading ${edit.filePath}: ${err}`);
1347
+ }
1348
+ }
1349
+
1350
+ return errors;
1351
+ },
1352
+
1353
+ preview_multi_edits: (edits: MultiEditEntry[]): MultiEditPreviewEntry[] => {
1354
+ const results: MultiEditPreviewEntry[] = [];
1355
+ const fileReplacements = new Map<string, number>();
1356
+ const fs = require('fs');
1357
+
1358
+ for (const edit of edits) {
1359
+ try {
1360
+ if (!fs.existsSync(edit.filePath)) continue;
1361
+
1362
+ const content = fs.readFileSync(edit.filePath, 'utf-8');
1363
+ const count = edit.replaceAll
1364
+ ? (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length
1365
+ : 1;
1366
+
1367
+ fileReplacements.set(
1368
+ edit.filePath,
1369
+ (fileReplacements.get(edit.filePath) || 0) + count
1370
+ );
1371
+ } catch {
1372
+ // Skip files that can't be read
1373
+ }
1374
+ }
1375
+
1376
+ for (const [filePath, replacementCount] of fileReplacements) {
1377
+ results.push({ filePath, replacementCount });
1378
+ }
1379
+
1380
+ return results;
1381
+ },
1382
+
1383
+ apply_multi_edits: (edits: MultiEditEntry[]): MultiEditResult => {
1384
+ // First validate all edits
1385
+ const errors = getFallbackModule().validate_multi_edits(edits);
1386
+ if (errors.length > 0) {
1387
+ return {
1388
+ success: false,
1389
+ filesModified: [],
1390
+ totalReplacements: 0,
1391
+ error: errors.join("\n"),
1392
+ rolledBack: false,
1393
+ };
1394
+ }
1395
+
1396
+ // Create backups
1397
+ const backups = new Map<string, string>();
1398
+ const uniqueFiles = new Set(edits.map(e => e.filePath));
1399
+ const fs = require('fs');
1400
+
1401
+ for (const filePath of uniqueFiles) {
1402
+ try {
1403
+ backups.set(filePath, fs.readFileSync(filePath, 'utf-8'));
1404
+ } catch (err) {
1405
+ return {
1406
+ success: false,
1407
+ filesModified: [],
1408
+ totalReplacements: 0,
1409
+ error: `Failed to backup ${filePath}: ${err}`,
1410
+ rolledBack: false,
1411
+ };
1412
+ }
1413
+ }
1414
+
1415
+ // Apply edits
1416
+ const currentContents = new Map<string, string>();
1417
+ for (const [path, content] of backups) {
1418
+ currentContents.set(path, content);
1419
+ }
1420
+
1421
+ let totalReplacements = 0;
1422
+
1423
+ for (const edit of edits) {
1424
+ const content = currentContents.get(edit.filePath);
1425
+ if (!content) continue;
1426
+
1427
+ if (edit.replaceAll) {
1428
+ const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
1429
+ currentContents.set(edit.filePath, content.split(edit.oldString).join(edit.newString));
1430
+ totalReplacements += count;
1431
+ } else {
1432
+ currentContents.set(edit.filePath, content.replace(edit.oldString, edit.newString));
1433
+ totalReplacements += 1;
1434
+ }
1435
+ }
1436
+
1437
+ // Write all files
1438
+ const filesModified: string[] = [];
1439
+ for (const [path, newContent] of currentContents) {
1440
+ const originalContent = backups.get(path);
1441
+ if (newContent !== originalContent) {
1442
+ try {
1443
+ Bun.write(path, newContent);
1444
+ filesModified.push(path);
1445
+ } catch (err) {
1446
+ // Rollback on failure
1447
+ for (const [rollbackPath, rollbackContent] of backups) {
1448
+ try {
1449
+ Bun.write(rollbackPath, rollbackContent);
1450
+ } catch {
1451
+ // Ignore rollback errors
1452
+ }
1453
+ }
1454
+ return {
1455
+ success: false,
1456
+ filesModified: [],
1457
+ totalReplacements: 0,
1458
+ error: `Failed to write ${path}: ${err}. All changes rolled back.`,
1459
+ rolledBack: true,
1460
+ };
1461
+ }
1462
+ }
1463
+ }
1464
+
1465
+ return {
1466
+ success: true,
1467
+ filesModified: filesModified,
1468
+ totalReplacements: totalReplacements,
1469
+ error: undefined,
1470
+ rolledBack: false,
1471
+ };
1472
+ },
1473
+
1474
+ // Tool analysis fallback implementations
1475
+ count_tool_use: (messages) => {
1476
+ const counts: Record<string, number> = {};
1477
+ for (const msg of messages) {
1478
+ if (msg.tool_use) {
1479
+ for (const tool of msg.tool_use) {
1480
+ counts[tool.name] = (counts[tool.name] || 0) + 1;
1481
+ }
1482
+ }
1483
+ }
1484
+ return counts;
1485
+ },
1486
+
1487
+ find_tool_pairs: (messages, _windowSize) => {
1488
+ const pairs: Record<string, Record<string, number>> = {};
1489
+ for (const msg of messages) {
1490
+ if (msg.tool_use && msg.tool_use.length >= 2) {
1491
+ for (let i = 0; i < msg.tool_use.length - 1; i++) {
1492
+ const tool1 = msg.tool_use[i]?.name;
1493
+ const tool2 = msg.tool_use[i + 1]?.name;
1494
+ if (tool1 && tool2) {
1495
+ if (!pairs[tool1]) pairs[tool1] = {};
1496
+ pairs[tool1][tool2] = (pairs[tool1][tool2] || 0) + 1;
1497
+ }
1498
+ }
1499
+ }
1500
+ }
1501
+ return pairs;
1502
+ },
1503
+
1504
+ find_common_patterns: (messages) => {
1505
+ const patterns: Array<{ tools: [string, string]; count: number; percentage: number }> = [];
1506
+ const toolPairs: Map<string, number> = new Map();
1507
+ let totalPairs = 0;
1508
+
1509
+ for (const msg of messages) {
1510
+ if (msg.tool_use && msg.tool_use.length >= 2) {
1511
+ for (let i = 0; i < msg.tool_use.length - 1; i++) {
1512
+ const name1 = msg.tool_use[i]?.name;
1513
+ const name2 = msg.tool_use[i + 1]?.name;
1514
+ if (name1 && name2) {
1515
+ const key = `${name1}|${name2}`;
1516
+ toolPairs.set(key, (toolPairs.get(key) || 0) + 1);
1517
+ totalPairs++;
1518
+ }
1519
+ }
1520
+ }
1521
+ }
1522
+
1523
+ for (const [key, count] of toolPairs) {
1524
+ const [tool1, tool2] = key.split("|") as [string, string];
1525
+ patterns.push({
1526
+ tools: [tool1, tool2],
1527
+ count,
1528
+ percentage: totalPairs > 0 ? (count / totalPairs) * 100 : 0,
1529
+ });
1530
+ }
1531
+
1532
+ return patterns.sort((a, b) => b.count - a.count).slice(0, 10);
1533
+ },
1534
+
1535
+ // ===== Cognitive Security Fallbacks =====
1536
+
1537
+ // Action Module
1538
+ classify_operation: (operation: string, domain: string, target?: string | null, reasoning?: string | null) => {
1539
+ const id = `action_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1540
+ let actionType = "observe";
1541
+ let riskLevel = 1;
1542
+ let hasSideEffects = false;
1543
+ let requiresApproval = false;
1544
+
1545
+ const op = operation.toLowerCase();
1546
+ if (op.includes("write") || op.includes("edit") || op.includes("create") || op.includes("delete")) {
1547
+ actionType = "modify";
1548
+ riskLevel = 3;
1549
+ hasSideEffects = true;
1550
+ requiresApproval = true;
1551
+ } else if (op.includes("execute") || op.includes("run") || op.includes("bash")) {
1552
+ actionType = "execute";
1553
+ riskLevel = 4;
1554
+ hasSideEffects = true;
1555
+ requiresApproval = true;
1556
+ } else if (op.includes("send") || op.includes("post") || op.includes("transmit")) {
1557
+ actionType = "communicate";
1558
+ riskLevel = 2;
1559
+ hasSideEffects = true;
1560
+ requiresApproval = domain === "external";
1561
+ } else if (op.includes("read") || op.includes("get") || op.includes("list") || op.includes("search")) {
1562
+ actionType = "observe";
1563
+ riskLevel = 1;
1564
+ hasSideEffects = false;
1565
+ requiresApproval = false;
1566
+ }
1567
+
1568
+ return {
1569
+ id,
1570
+ actionType,
1571
+ domain,
1572
+ operation,
1573
+ target: target || null,
1574
+ flowDirection: "outbound",
1575
+ riskLevel,
1576
+ hasSideEffects,
1577
+ requiresApproval,
1578
+ reasoning: reasoning || `Classified as ${actionType} based on operation name`,
1579
+ timestamp: Date.now(),
1580
+ metadata: null,
1581
+ };
1582
+ },
1583
+
1584
+ get_action_types: () => ["modify", "execute", "communicate", "transfer", "observe", "create", "delete"],
1585
+
1586
+ get_action_risk_levels: () => [
1587
+ { actionType: "observe", riskLevel: 1 },
1588
+ { actionType: "communicate", riskLevel: 2 },
1589
+ { actionType: "create", riskLevel: 3 },
1590
+ { actionType: "modify", riskLevel: 3 },
1591
+ { actionType: "transfer", riskLevel: 4 },
1592
+ { actionType: "execute", riskLevel: 4 },
1593
+ { actionType: "delete", riskLevel: 5 },
1594
+ ],
1595
+
1596
+ create_deny_all_policy: () => ({
1597
+ id: "deny_all",
1598
+ description: "Deny all actions",
1599
+ actionTypes: [],
1600
+ domains: [],
1601
+ operations: [],
1602
+ effect: "deny",
1603
+ priority: 1000,
1604
+ enabled: true,
1605
+ }),
1606
+
1607
+ create_observe_only_policy: () => ({
1608
+ id: "observe_only",
1609
+ description: "Allow observe actions only",
1610
+ actionTypes: ["observe"],
1611
+ domains: [],
1612
+ operations: [],
1613
+ effect: "allow",
1614
+ priority: 100,
1615
+ enabled: true,
1616
+ }),
1617
+
1618
+ create_transfer_approval_policy: () => ({
1619
+ id: "transfer_approval",
1620
+ description: "Require approval for transfer actions",
1621
+ actionTypes: ["transfer"],
1622
+ domains: [],
1623
+ operations: [],
1624
+ effect: "require_approval",
1625
+ priority: 200,
1626
+ enabled: true,
1627
+ }),
1628
+
1629
+ // Intent Module
1630
+ cs_generate_keypair: () => ({
1631
+ privateKey: `private_${Math.random().toString(36).slice(2)}_${Date.now()}`,
1632
+ publicKey: `public_${Math.random().toString(36).slice(2)}_${Date.now()}`,
1633
+ }),
1634
+
1635
+ cs_sign_intent: (intent: any, _privateKey: string) => {
1636
+ return { ...intent, signature: `sig_${Date.now()}`, signedBy: "fallback" };
1637
+ },
1638
+
1639
+ cs_verify_intent: (_intent: any) => ({
1640
+ valid: true,
1641
+ error: null,
1642
+ signatureValid: true,
1643
+ contentIntact: true,
1644
+ expired: false,
1645
+ }),
1646
+
1647
+ cs_hash_intent: (intent: any) => {
1648
+ const str = JSON.stringify(intent);
1649
+ let hash = 0;
1650
+ for (let i = 0; i < str.length; i++) {
1651
+ const char = str.charCodeAt(i);
1652
+ hash = ((hash << 5) - hash) + char;
1653
+ hash = hash & hash;
1654
+ }
1655
+ return Math.abs(hash).toString(16).padStart(16, '0');
1656
+ },
1657
+
1658
+ cs_intents_equivalent: (intent1: any, intent2: any) => {
1659
+ const stripSignature = (i: any) => {
1660
+ const { signature, signedBy, ...rest } = i;
1661
+ return rest;
1662
+ };
1663
+ return JSON.stringify(stripSignature(intent1)) === JSON.stringify(stripSignature(intent2));
1664
+ },
1665
+
1666
+ cs_score_alignment: (_action: any, _intent: any) => ({
1667
+ score: 0.8,
1668
+ reasoning: "Fallback alignment score - native module not available",
1669
+ servesGoals: [],
1670
+ hindersGoals: [],
1671
+ boundaryConcerns: [],
1672
+ confidence: 0.5,
1673
+ shouldBlock: false,
1674
+ requiresReview: false,
1675
+ }),
1676
+
1677
+ cs_batch_score_alignment: (actions: any[], intent: any) => {
1678
+ return actions.map(() => ({
1679
+ score: 0.8,
1680
+ reasoning: "Fallback alignment score",
1681
+ servesGoals: [],
1682
+ hindersGoals: [],
1683
+ boundaryConcerns: [],
1684
+ confidence: 0.5,
1685
+ shouldBlock: false,
1686
+ requiresReview: false,
1687
+ }));
1688
+ },
1689
+
1690
+ cs_check_sequence_violations: (_actions: any[], _intent: any) => [],
1691
+
1692
+ cs_load_intent: (_path: string) => {
1693
+ throw new Error("Native module required for cs_load_intent");
1694
+ },
1695
+
1696
+ cs_save_intent: (_intent: any, _path: string) => {
1697
+ throw new Error("Native module required for cs_save_intent");
1698
+ },
1699
+
1700
+ cs_parse_intent: (json: string) => JSON.parse(json),
1701
+
1702
+ cs_serialize_intent: (intent: any) => JSON.stringify(intent, null, 2),
1703
+
1704
+ cs_validate_intent: (intent: any) => {
1705
+ const errors: string[] = [];
1706
+ const warnings: string[] = [];
1707
+
1708
+ if (!intent.id) errors.push("Missing intent id");
1709
+ if (!intent.version) warnings.push("Missing version");
1710
+ if (!intent.identity) errors.push("Missing identity");
1711
+ if (!intent.purpose) errors.push("Missing purpose");
1712
+
1713
+ return {
1714
+ valid: errors.length === 0,
1715
+ errors,
1716
+ warnings,
1717
+ };
1718
+ },
1719
+
1720
+ cs_create_data_collector_intent: (name: string, description: string) => ({
1721
+ id: `intent_${Date.now()}`,
1722
+ version: 1,
1723
+ identity: {
1724
+ name,
1725
+ description,
1726
+ capabilities: ["read", "list", "search"],
1727
+ constraints: ["no_write", "no_execute", "no_network"],
1728
+ },
1729
+ purpose: {
1730
+ goals: [],
1731
+ nonGoals: ["modify_data", "execute_commands", "send_data"],
1732
+ boundaries: [],
1733
+ },
1734
+ principles: {
1735
+ values: ["transparency", "privacy"],
1736
+ priorities: ["safety_first"],
1737
+ forbidden: ["exfiltration", "modification"],
1738
+ },
1739
+ createdAt: Date.now(),
1740
+ }),
1741
+
1742
+ cs_merge_intents: (base: any, override: any) => ({ ...base, ...override }),
1743
+
1744
+ cs_analyze_corruption: (_snapshot: any, _intent: any) => ({
1745
+ riskScore: 0,
1746
+ indicators: [],
1747
+ recommendation: "continue",
1748
+ explanation: "Fallback analysis - native module not available",
1749
+ }),
1750
+
1751
+ cs_detect_drift: (_baseline: any, _current: any) => ({
1752
+ overallDrift: 0,
1753
+ driftFactors: [],
1754
+ concernLevel: "none",
1755
+ }),
1756
+
1757
+ cs_create_empty_snapshot: () => ({
1758
+ timestamp: Date.now(),
1759
+ actionCount: 0,
1760
+ alignmentDistribution: { mean: 1, variance: 0, min: 1, max: 1, belowThresholdCount: 0 },
1761
+ actionsByDomain: [],
1762
+ actionsByType: [],
1763
+ boundaryViolations: 0,
1764
+ actionsBlocked: 0,
1765
+ }),
1766
+
1767
+ cs_update_snapshot: (snapshot: any, _action: any, alignment: any) => {
1768
+ const newScore = alignment?.score ?? 1;
1769
+ const oldMean = snapshot.alignmentDistribution?.mean ?? 1;
1770
+ const newMean = (oldMean * snapshot.actionCount + newScore) / (snapshot.actionCount + 1);
1771
+
1772
+ return {
1773
+ ...snapshot,
1774
+ timestamp: Date.now(),
1775
+ actionCount: snapshot.actionCount + 1,
1776
+ alignmentDistribution: {
1777
+ ...snapshot.alignmentDistribution,
1778
+ mean: newMean,
1779
+ },
1780
+ };
1781
+ },
1782
+
1783
+ // Flow Module
1784
+ classify_data: (content: string, source: string, tags: string[]) => {
1785
+ let sensitivity = "internal";
1786
+ let category = "generic";
1787
+
1788
+ if (content.includes("password") || content.includes("secret") || content.includes("key")) {
1789
+ sensitivity = "secret";
1790
+ category = "credentials";
1791
+ } else if (content.includes("@") && content.includes(".")) {
1792
+ sensitivity = "confidential";
1793
+ category = "pii";
1794
+ }
1795
+
1796
+ return {
1797
+ id: `data_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
1798
+ sensitivity,
1799
+ category,
1800
+ source,
1801
+ tags,
1802
+ can_log: sensitivity !== "secret",
1803
+ can_transmit: sensitivity === "public" || sensitivity === "internal",
1804
+ can_store: true,
1805
+ expires_at: null,
1806
+ created_at: Date.now(),
1807
+ };
1808
+ },
1809
+
1810
+ contains_sensitive_data: (content: string) => {
1811
+ const patterns = ["password", "secret", "api_key", "token", "credential"];
1812
+ return patterns.some(p => content.toLowerCase().includes(p));
1813
+ },
1814
+
1815
+ redact_sensitive: (content: string, replacement?: string | null) => {
1816
+ const repl = replacement || "[REDACTED]";
1817
+ return content
1818
+ .replace(/password[=:]\s*\S+/gi, `password=${repl}`)
1819
+ .replace(/api[_-]?key[=:]\s*\S+/gi, `api_key=${repl}`)
1820
+ .replace(/token[=:]\s*\S+/gi, `token=${repl}`)
1821
+ .replace(/secret[=:]\s*\S+/gi, `secret=${repl}`);
1822
+ },
1823
+
1824
+ get_sensitivity_levels: () => [
1825
+ { name: "public", value: 1, description: "Publicly shareable" },
1826
+ { name: "internal", value: 2, description: "Internal use only" },
1827
+ { name: "confidential", value: 3, description: "Confidential" },
1828
+ { name: "secret", value: 4, description: "Highly sensitive" },
1829
+ { name: "top_secret", value: 5, description: "Maximum sensitivity" },
1830
+ ],
1831
+
1832
+ get_data_categories: () => [
1833
+ { name: "generic", description: "Generic data" },
1834
+ { name: "pii", description: "Personally identifiable information" },
1835
+ { name: "credentials", description: "Authentication credentials" },
1836
+ { name: "financial", description: "Financial data" },
1837
+ { name: "source_code", description: "Source code" },
1838
+ { name: "configuration", description: "Configuration data" },
1839
+ ],
1840
+
1841
+ // Flow Policy Engine
1842
+ create_flow_policy_engine: () => ({
1843
+ addPolicy: (_policy: any) => {},
1844
+ removePolicy: (_id: string) => true,
1845
+ evaluate: (_data: any, _source: string, _target: string) => ({
1846
+ allowed: true,
1847
+ reason: "Fallback: allowed by default",
1848
+ applied_policy: null,
1849
+ can_log: true,
1850
+ can_transmit: true,
1851
+ can_store: true,
1852
+ transformations: [],
1853
+ confidence: 0.5,
1854
+ warnings: ["Fallback implementation - native module not available"],
1855
+ }),
1856
+ listPolicies: () => [],
1857
+ setDefaultAction: (_action: string) => {},
1858
+ setBlpMode: (_mode: string) => {},
1859
+ }),
1860
+
1861
+ // Flow Policies
1862
+ create_allow_all_flow_policy: () => ({
1863
+ id: "allow_all",
1864
+ description: "Allow all flows",
1865
+ source_pattern: "*",
1866
+ target_pattern: "*",
1867
+ min_source_sensitivity: null,
1868
+ max_target_sensitivity: null,
1869
+ categories: [],
1870
+ effect: "allow",
1871
+ priority: 0,
1872
+ required_transforms: [],
1873
+ log_flow: false,
1874
+ require_approval: false,
1875
+ conditions: null,
1876
+ enabled: true,
1877
+ }),
1878
+
1879
+ create_deny_all_flow_policy: () => ({
1880
+ id: "deny_all",
1881
+ description: "Deny all flows",
1882
+ source_pattern: "*",
1883
+ target_pattern: "*",
1884
+ min_source_sensitivity: null,
1885
+ max_target_sensitivity: null,
1886
+ categories: [],
1887
+ effect: "deny",
1888
+ priority: 1000,
1889
+ required_transforms: [],
1890
+ log_flow: false,
1891
+ require_approval: false,
1892
+ conditions: null,
1893
+ enabled: true,
1894
+ }),
1895
+
1896
+ create_strict_flow_policy: () => ({
1897
+ id: "strict",
1898
+ description: "Strict flow policy",
1899
+ source_pattern: "*",
1900
+ target_pattern: "*",
1901
+ min_source_sensitivity: "internal",
1902
+ max_target_sensitivity: null,
1903
+ categories: [],
1904
+ effect: "transform",
1905
+ priority: 500,
1906
+ required_transforms: ["redact_sensitive"],
1907
+ log_flow: true,
1908
+ require_approval: true,
1909
+ conditions: null,
1910
+ enabled: true,
1911
+ }),
1912
+
1913
+ // Flow Tracker
1914
+ create_flow_tracker: () => ({
1915
+ record: (_data: any, _source: string, _target: string, _direction: string, _validation: any, _sessionId: string | null, _actionId: string | null) => ({
1916
+ id: `flow_${Date.now()}`,
1917
+ data_id: _data.id,
1918
+ source_domain: _source,
1919
+ target_domain: _target,
1920
+ direction: _direction,
1921
+ allowed: _validation.allowed,
1922
+ reason: _validation.reason,
1923
+ policy_id: _validation.applied_policy || null,
1924
+ session_id: _sessionId,
1925
+ action_id: _actionId,
1926
+ timestamp: Date.now(),
1927
+ data_hash: "",
1928
+ }),
1929
+ getFlow: (_id: string) => null,
1930
+ getLineage: (_dataId: string) => [],
1931
+ bySource: (_domain: string) => [],
1932
+ byTarget: (_domain: string) => [],
1933
+ bySession: (_sessionId: string) => [],
1934
+ blocked: () => [],
1935
+ allowed: () => [],
1936
+ recent: (_limit: number) => [],
1937
+ stats: () => ({
1938
+ total_flows: 0,
1939
+ allowed_count: 0,
1940
+ blocked_count: 0,
1941
+ by_direction: [],
1942
+ by_source_domain: [],
1943
+ by_target_domain: [],
1944
+ first_timestamp: Date.now(),
1945
+ last_timestamp: Date.now(),
1946
+ }),
1947
+ domainStats: (_domain: string) => null,
1948
+ count: () => 0,
1949
+ clear: () => {},
1950
+ setMaxFlows: (_max: number) => {},
1951
+ exportJsonl: () => "",
1952
+ }),
1953
+
1954
+ // Leak Prevention
1955
+ create_leak_prevention: () => ({
1956
+ check: (_content: string, _channel: string) => ({
1957
+ action: "allow",
1958
+ detections: [],
1959
+ channel_allowed: true,
1960
+ checked_at: Date.now(),
1961
+ }),
1962
+ sanitize: (content: string) => content
1963
+ .replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
1964
+ .replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
1965
+ .replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
1966
+ .replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
1967
+ registerSensitive: (_data: string) => {},
1968
+ addChannel: (_channel: string) => {},
1969
+ removeChannel: (_channel: string) => {},
1970
+ setMode: (_mode: string) => {},
1971
+ stats: () => ({
1972
+ total_checks: 0,
1973
+ blocked_count: 0,
1974
+ alert_count: 0,
1975
+ by_leak_type: {},
1976
+ }),
1977
+ clearSensitive: () => {},
1978
+ }),
1979
+
1980
+ // Leak Prevention helpers
1981
+ check_for_leaks: (content: string, channel: string) => ({
1982
+ action: "allow",
1983
+ detections: [],
1984
+ channel_allowed: true,
1985
+ checked_at: Date.now(),
1986
+ }),
1987
+
1988
+ sanitize_content: (content: string) => content
1989
+ .replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
1990
+ .replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
1991
+ .replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
1992
+ .replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
1993
+
1994
+ // Taint Tracker
1995
+ create_taint_tracker: () => ({
1996
+ registerSource: (_type: string, _sensitivity: string, _tags: string[]) => `source_${Date.now()}`,
1997
+ taint: (_sourceId: string, _data: string, _locationType: string, _identifier: string) => `taint_${Date.now()}`,
1998
+ propagate: (_sourceTaintId: string, _newData: string, _locationType: string, _identifier: string, _propagationType: string, _operation: string) => `prop_${Date.now()}`,
1999
+ canFlow: (_taintId: string, _sink: string) => ({ allowed: true, reason: "Fallback", requires_sanitization: false }),
2000
+ isTainted: (_data: string) => false,
2001
+ getTaint: (_taintId: string) => null,
2002
+ stats: () => ({
2003
+ total_sources: 0,
2004
+ total_tainted: 0,
2005
+ total_propagations: 0,
2006
+ by_source_type: {},
2007
+ by_sensitivity: {},
2008
+ }),
2009
+ clear: (_taintId: string) => false,
2010
+ clearAll: () => {},
2011
+ }),
2012
+
2013
+ // Quant Functions (stubs)
2014
+ quant_version: () => "0.1.0-fallback",
2015
+ quant_ohlcv_new: (_ts: bigint, _o: number, _h: number, _l: number, _c: number, _v: number) => JSON.stringify({ open: _o, high: _h, low: _l, close: _c, volume: _v }),
2016
+ quant_amm_new: (_poolYes: number, _poolNo: number, _fee: number) => JSON.stringify({ poolYes: _poolYes, poolNo: _poolNo, fee: _fee }),
2017
+ quant_amm_calculate_cost: (_poolYes: number, _poolNo: number, _buyYes: boolean, _shares: number) => JSON.stringify({ cost: 0 }),
2018
+ quant_amm_price_impact: (_poolYes: number, _poolNo: number, _buyYes: boolean, _shares: number) => JSON.stringify({ impact: 0 }),
2019
+ quant_lmsr_price: (_yesShares: number, _noShares: number, _b: number) => JSON.stringify({ price: 0.5 }),
2020
+ quant_lmsr_cost: (_yesShares: number, _noShares: number, _b: number, _buyYes: boolean, _shares: number) => JSON.stringify({ cost: 0 }),
2021
+ quant_detect_arbitrage: (_yesPrice: number, _noPrice: number) => JSON.stringify({ hasArbitrage: false }),
2022
+ quant_convert_odds: (_value: number, _fromType: number) => JSON.stringify({ decimal: 0 }),
2023
+ quant_mean: (_data: Float64Array) => 0,
2024
+ quant_std_dev: (_data: Float64Array) => 0,
2025
+ quant_variance: (_data: Float64Array) => 0,
2026
+ quant_correlation: (_x: Float64Array, _y: Float64Array) => 0,
2027
+
2028
+ // Terminal Input (fallback - uses Node.js stdin directly)
2029
+ create_terminal: (): TerminalHandle => {
2030
+ let inRawMode = false;
2031
+
2032
+ return {
2033
+ get isRawMode() { return inRawMode; },
2034
+ enterRawMode(): void {
2035
+ if (process.stdin.isTTY && !inRawMode) {
2036
+ process.stdin.setRawMode(true);
2037
+ process.stdin.resume();
2038
+ inRawMode = true;
2039
+ }
2040
+ },
2041
+ exitRawMode(): void {
2042
+ if (process.stdin.isTTY && inRawMode) {
2043
+ process.stdin.setRawMode(false);
2044
+ inRawMode = false;
2045
+ }
2046
+ },
2047
+ pollEvent(_timeoutMs?: number): NativeKeyEvent | null {
2048
+ // Fallback can't poll synchronously - return null
2049
+ // Use readEvent() instead for async operation
2050
+ return null;
2051
+ },
2052
+ async readEvent(): Promise<NativeKeyEvent> {
2053
+ return new Promise((resolve) => {
2054
+ const handler = (buffer: Buffer) => {
2055
+ process.stdin.off("data", handler);
2056
+ const str = buffer.toString("utf8");
2057
+
2058
+ // Parse simple keypresses
2059
+ if (str === "\r" || str === "\n") {
2060
+ resolve({ code: "enter", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2061
+ } else if (str === "\x03") {
2062
+ // Ctrl+C
2063
+ resolve({ code: "c", is_special: false, ctrl: true, alt: false, shift: false, kind: "press" });
2064
+ } else if (str === "\x7f" || str === "\x08") {
2065
+ resolve({ code: "backspace", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2066
+ } else if (str === "\x1b") {
2067
+ resolve({ code: "escape", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2068
+ } else if (str === "\t") {
2069
+ resolve({ code: "tab", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2070
+ } else if (str.length === 1 && str >= " ") {
2071
+ // Regular printable character
2072
+ const ctrl = str.charCodeAt(0) < 32;
2073
+ const char = ctrl ? String.fromCharCode(str.charCodeAt(0) + 96) : str;
2074
+ resolve({ code: char, is_special: false, ctrl, alt: false, shift: false, kind: "press" });
2075
+ } else {
2076
+ // Handle escape sequences for arrows and special keys
2077
+ if (str === "\x1b[A") {
2078
+ resolve({ code: "up", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2079
+ } else if (str === "\x1b[B") {
2080
+ resolve({ code: "down", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2081
+ } else if (str === "\x1b[C") {
2082
+ resolve({ code: "right", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2083
+ } else if (str === "\x1b[D") {
2084
+ resolve({ code: "left", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2085
+ } else if (str === "\x1b[5~") {
2086
+ resolve({ code: "pageup", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2087
+ } else if (str === "\x1b[6~") {
2088
+ resolve({ code: "pagedown", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2089
+ } else if (str === "\x1b[H" || str === "\x1b[1~") {
2090
+ resolve({ code: "home", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2091
+ } else if (str === "\x1b[F" || str === "\x1b[4~") {
2092
+ resolve({ code: "end", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2093
+ } else if (str === "\x1b[3~") {
2094
+ resolve({ code: "delete", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
2095
+ } else if (str === "\x1b[Z") {
2096
+ resolve({ code: "backtab", is_special: true, ctrl: false, alt: false, shift: true, kind: "press" });
2097
+ } else {
2098
+ // Unknown escape sequence - treat as-is
2099
+ resolve({ code: str, is_special: false, ctrl: false, alt: false, shift: false, kind: "press" });
2100
+ }
2101
+ }
2102
+ };
2103
+ process.stdin.once("data", handler);
2104
+ });
2105
+ },
2106
+ };
2107
+ },
2108
+
2109
+ // Native TUI (fallback - not available in pure JS)
2110
+ create_tui: (): NativeTuiHandle => {
2111
+ throw new Error("Native TUI not available in fallback mode. Build the Rust native module.");
2112
+ },
2113
+ is_native_tui_available: () => false,
2114
+
2115
+ // Grep functions (fallback - use Grep tool instead)
2116
+ grep_search: async (_pattern: string, _path: string, _options?: GrepQueryOptions): Promise<GrepResult> => {
2117
+ throw new Error("grep_search not available in fallback mode. Build the Rust native module or use the Grep tool.");
2118
+ },
2119
+ grep_count: async (_pattern: string, _path: string, _options?: GrepQueryOptions): Promise<GrepCountResult[]> => {
2120
+ throw new Error("grep_count not available in fallback mode. Build the Rust native module or use the Grep tool.");
2121
+ },
2122
+ grep_files: async (_pattern: string, _path: string, _options?: GrepQueryOptions): Promise<GrepFilesResult> => {
2123
+ throw new Error("grep_files not available in fallback mode. Build the Rust native module or use the Grep tool.");
2124
+ },
2125
+ };
2126
+ }
2127
+
2128
+ // Export a singleton instance
2129
+ export const native = loadNative();
2130
+
2131
+ /**
2132
+ * Syntax highlight code with ANSI escape codes for terminal display
2133
+ * Uses native Rust module if available, falls back to JS implementation
2134
+ */
2135
+ export function highlight_code(code: string, language: string): HighlightResult {
2136
+ return native.highlight_code(code, language);
2137
+ }
2138
+
2139
+ /**
2140
+ * Highlight markdown with nested code block syntax highlighting
2141
+ * Parses markdown for code fences and highlights code blocks with their language
2142
+ */
2143
+ export function highlight_markdown(markdown: string): HighlightResult {
2144
+ return native.highlight_markdown(markdown);
2145
+ }
2146
+
2147
+ /**
2148
+ * List all supported languages for syntax highlighting
2149
+ */
2150
+ export function list_highlight_languages(): string[] {
2151
+ return [
2152
+ // Core languages
2153
+ "typescript", "ts", "javascript", "js",
2154
+ "python", "py",
2155
+ "rust", "rs",
2156
+ "go", "golang",
2157
+ "ruby", "rb",
2158
+ "java",
2159
+ "c", "cpp", "c++", "csharp", "cs", "c#",
2160
+ "php",
2161
+ "swift",
2162
+ "kotlin", "kt",
2163
+ "scala",
2164
+ // Shell & config
2165
+ "shell", "sh", "bash", "zsh",
2166
+ "json",
2167
+ "yaml", "yml",
2168
+ "toml",
2169
+ // Markup
2170
+ "markdown", "md",
2171
+ "html", "htm",
2172
+ "css", "scss", "less",
2173
+ "xml",
2174
+ // Database
2175
+ "sql",
2176
+ // Diagrams
2177
+ "mermaid", "mmd",
2178
+ ];
2179
+ }
2180
+
2181
+ /**
2182
+ * Highlight a diff with ANSI colors
2183
+ * Uses native Rust module if available, falls back to JS implementation
2184
+ */
2185
+ export function highlight_diff(
2186
+ oldText: string,
2187
+ newText: string,
2188
+ options?: DiffOptions
2189
+ ): HighlightDiffResult {
2190
+ return native.highlight_diff(oldText, newText, options);
2191
+ }
2192
+
2193
+ /**
2194
+ * Calculate diff hunks with hunk headers for LLM context
2195
+ * Returns structured diff with @@ headers included in content
2196
+ */
2197
+ export function calculate_diff(oldText: string, newText: string): Array<{
2198
+ oldStart: number;
2199
+ oldLines: number;
2200
+ newStart: number;
2201
+ newLines: number;
2202
+ content: string;
2203
+ }> {
2204
+ return native.calculate_diff(oldText, newText);
2205
+ }
2206
+
2207
+ // ===== Multi-File Edit Functions =====
2208
+
2209
+ /**
2210
+ * Validate multi-file edits without applying them
2211
+ * Returns an array of error messages (empty if valid)
2212
+ */
2213
+ export function validate_multi_edits(edits: MultiEditEntry[]): string[] {
2214
+ return native.validate_multi_edits(edits);
2215
+ }
2216
+
2217
+ /**
2218
+ * Preview what edits would be applied without making changes
2219
+ * Returns an array of { file_path, replacement_count } for each file
2220
+ */
2221
+ export function preview_multi_edits(edits: MultiEditEntry[]): MultiEditPreviewEntry[] {
2222
+ return native.preview_multi_edits(edits);
2223
+ }
2224
+
2225
+ /**
2226
+ * Apply multiple file edits atomically with rollback on failure
2227
+ *
2228
+ * This function:
2229
+ * 1. Validates all edits can be applied (files exist, strings found)
2230
+ * 2. Creates backups of all affected files
2231
+ * 3. Applies all edits
2232
+ * 4. Rolls back on any failure
2233
+ *
2234
+ * @param edits Array of edit operations
2235
+ * @returns Result with success status and list of modified files
2236
+ */
2237
+ export function apply_multi_edits(edits: MultiEditEntry[]): MultiEditResult {
2238
+ return native.apply_multi_edits(edits);
2239
+ }
2240
+
2241
+ // ===== Helper Functions =====
2242
+
2243
+ function truncateString(s: string, maxLen: number): string {
2244
+ if (s.length <= maxLen) return s;
2245
+ return s.slice(0, maxLen) + "...";
2246
+ }
2247
+
2248
+ function escapeRegex(string: string): string {
2249
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2250
+ }
2251
+
2252
+ // ===== Quant Module =====
2253
+
2254
+ /**
2255
+ * Quant module interface for financial calculations
2256
+ * Loads from @ebowwa/quant-rust native library
2257
+ */
2258
+ interface QuantModule {
2259
+ quant_version: () => string;
2260
+ quant_last_error: () => string;
2261
+ quant_clear_error: () => void;
2262
+
2263
+ // OHLCV
2264
+ quant_ohlcv_new: (timestamp: bigint, open: number, high: number, low: number, close: number, volume: number) => string;
2265
+
2266
+ // AMM
2267
+ quant_amm_new: (poolYes: number, poolNo: number, fee: number) => string;
2268
+ quant_amm_calculate_cost: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
2269
+ quant_amm_price_impact: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
2270
+
2271
+ // LMSR
2272
+ quant_lmsr_price: (yesShares: number, noShares: number, b: number) => string;
2273
+ quant_lmsr_cost: (yesShares: number, noShares: number, b: number, buyYes: boolean, shares: number) => string;
2274
+
2275
+ // Arbitrage
2276
+ quant_detect_arbitrage: (yesPrice: number, noPrice: number) => string;
2277
+
2278
+ // Odds
2279
+ quant_convert_odds: (value: number, fromType: number) => string;
2280
+
2281
+ // Statistics
2282
+ quant_mean: (ptr: number, len: number) => number;
2283
+ quant_std_dev: (ptr: number, len: number) => number;
2284
+ quant_variance: (ptr: number, len: number) => number;
2285
+ quant_correlation: (ptrX: number, ptrY: number, len: number) => number;
2286
+
2287
+ // Memory
2288
+ quant_free_string: (ptr: number) => void;
2289
+ }
2290
+
2291
+ let quantModule: QuantModule | null = null;
2292
+
2293
+ /**
2294
+ * Load the quant native module from @ebowwa/quant-rust
2295
+ */
2296
+ function loadQuant(): QuantModule | null {
2297
+ if (quantModule) return quantModule;
2298
+
2299
+ const __dirname = dirname(fileURLToPath(import.meta.url));
2300
+
2301
+ // Try multiple paths for the quant library
2302
+ const libName = process.platform === "darwin"
2303
+ ? "libquant_rust.dylib"
2304
+ : process.platform === "linux"
2305
+ ? "libquant_rust.so"
2306
+ : "quant_rust.dll";
2307
+
2308
+ const possiblePaths = [
2309
+ // From npm package
2310
+ join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
2311
+ // From npm package (alternate)
2312
+ join(__dirname, "..", "..", "..", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
2313
+ // Development build
2314
+ join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "target", "release", libName),
2315
+ ];
2316
+
2317
+ for (const libPath of possiblePaths) {
2318
+ try {
2319
+ const { existsSync } = require("fs");
2320
+ if (!existsSync(libPath)) continue;
2321
+
2322
+ const { dlopen, FFIType, ptr } = require("bun:ffi");
2323
+
2324
+ const lib = dlopen(libPath, {
2325
+ quant_version: { returns: FFIType.cstring, args: [] },
2326
+ quant_last_error: { returns: FFIType.cstring, args: [] },
2327
+ quant_clear_error: { returns: FFIType.void, args: [] },
2328
+ quant_ohlcv_new: { returns: FFIType.cstring, args: [FFIType.u64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64] },
2329
+ quant_amm_new: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
2330
+ quant_amm_calculate_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
2331
+ quant_amm_price_impact: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
2332
+ quant_lmsr_price: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
2333
+ quant_lmsr_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
2334
+ quant_detect_arbitrage: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64] },
2335
+ quant_convert_odds: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.i32] },
2336
+ quant_mean: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
2337
+ quant_std_dev: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
2338
+ quant_variance: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
2339
+ quant_correlation: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.ptr, FFIType.usize] },
2340
+ quant_free_string: { returns: FFIType.void, args: [FFIType.ptr] },
2341
+ });
2342
+
2343
+ quantModule = lib.symbols as unknown as QuantModule;
2344
+ return quantModule;
2345
+ } catch {
2346
+ continue;
2347
+ }
2348
+ }
2349
+
2350
+ return null;
2351
+ }
2352
+
2353
+ // Load quant module
2354
+ export const quant = loadQuant();
2355
+
2356
+ // ===== Quant Helper Functions =====
2357
+
2358
+ function parseQuantJson<T>(response: string | null): T {
2359
+ if (!response) {
2360
+ throw new Error(quant?.quant_last_error() || "Unknown quant error");
2361
+ }
2362
+ return JSON.parse(response) as T;
2363
+ }
2364
+
2365
+ function toFloat64Ptr(data: number[]): { buffer: Float64Array; ptr: number } {
2366
+ const { ptr } = require("bun:ffi");
2367
+ const buffer = new Float64Array(data);
2368
+ return { buffer, ptr: ptr(buffer) };
2369
+ }
2370
+
2371
+ // ===== Quant Export Functions =====
2372
+
2373
+ /** Warn once when using JS fallback */
2374
+ let quantFallbackWarned = false;
2375
+ function warnQuantFallback(): void {
2376
+ if (!quantFallbackWarned) {
2377
+ console.warn("\x1b[33m[quant] WARNING: Rust native module not loaded, using JS fallback\x1b[0m");
2378
+ quantFallbackWarned = true;
2379
+ }
2380
+ }
2381
+
2382
+ export function quantVersion(): string {
2383
+ if (!quant) {
2384
+ warnQuantFallback();
2385
+ return "JS_FALLBACK (rust failed)";
2386
+ }
2387
+ return quant.quant_version();
2388
+ }
2389
+
2390
+ export function isQuantAvailable(): boolean {
2391
+ return quant !== null;
2392
+ }
2393
+
2394
+ // ----- OHLCV -----
2395
+
2396
+ export function createOHLCV(
2397
+ timestamp: number,
2398
+ open: number,
2399
+ high: number,
2400
+ low: number,
2401
+ close: number,
2402
+ volume: number
2403
+ ): OHLCV {
2404
+ if (!quant) {
2405
+ warnQuantFallback();
2406
+ return { timestamp, open, high, low, close, volume };
2407
+ }
2408
+ const response = quant.quant_ohlcv_new(BigInt(timestamp), open, high, low, close, volume);
2409
+ return parseQuantJson(response);
2410
+ }
2411
+
2412
+ // ----- AMM -----
2413
+
2414
+ export function createAMM(poolYes: number, poolNo: number, fee: number): AMMState {
2415
+ if (!quant) {
2416
+ warnQuantFallback();
2417
+ const k = poolYes * poolNo;
2418
+ return {
2419
+ pool_yes: poolYes,
2420
+ pool_no: poolNo,
2421
+ k,
2422
+ fee,
2423
+ price_yes: poolNo / k,
2424
+ price_no: poolYes / k,
2425
+ };
2426
+ }
2427
+ const response = quant.quant_amm_new(poolYes, poolNo, fee);
2428
+ return parseQuantJson(response);
2429
+ }
2430
+
2431
+ export function ammCalculateCost(
2432
+ poolYes: number,
2433
+ poolNo: number,
2434
+ outcome: "yes" | "no" | boolean,
2435
+ shares: number
2436
+ ): number {
2437
+ if (!quant) {
2438
+ warnQuantFallback();
2439
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2440
+ const k = poolYes * poolNo;
2441
+ if (buyYes) {
2442
+ return (k / (poolYes + shares)) - poolNo;
2443
+ }
2444
+ return (k / (poolNo + shares)) - poolYes;
2445
+ }
2446
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2447
+ const response = quant.quant_amm_calculate_cost(poolYes, poolNo, buyYes, shares);
2448
+ const result = parseQuantJson<AMMCostResult>(response);
2449
+ return Math.abs(result.cost);
2450
+ }
2451
+
2452
+ export function ammPriceImpact(
2453
+ poolYes: number,
2454
+ poolNo: number,
2455
+ outcome: "yes" | "no" | boolean,
2456
+ shares: number
2457
+ ): AMMPriceImpactResult {
2458
+ if (!quant) {
2459
+ warnQuantFallback();
2460
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2461
+ const k = poolYes * poolNo;
2462
+ const priceBefore = buyYes ? poolNo / k : poolYes / k;
2463
+ const newPoolYes = buyYes ? poolYes + shares : poolYes;
2464
+ const newPoolNo = buyYes ? poolNo : poolNo + shares;
2465
+ const priceAfter = buyYes ? newPoolNo / k : newPoolYes / k;
2466
+ return {
2467
+ price_before: priceBefore,
2468
+ price_after: priceAfter,
2469
+ price_impact: Math.abs(priceAfter - priceBefore) / priceBefore,
2470
+ slippage: Math.abs(priceAfter - priceBefore),
2471
+ };
2472
+ }
2473
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2474
+ const response = quant.quant_amm_price_impact(poolYes, poolNo, buyYes, shares);
2475
+ return parseQuantJson(response);
2476
+ }
2477
+
2478
+ // ----- LMSR -----
2479
+
2480
+ export function lmsrPrice(yesShares: number, noShares: number, b: number): LMSRPriceResult {
2481
+ if (!quant) {
2482
+ warnQuantFallback();
2483
+ const expYes = Math.exp(yesShares / b);
2484
+ const expNo = Math.exp(noShares / b);
2485
+ const sum = expYes + expNo;
2486
+ return { yes_price: expYes / sum, no_price: expNo / sum, spread: Math.abs(expYes - expNo) / sum };
2487
+ }
2488
+ const response = quant.quant_lmsr_price(yesShares, noShares, b);
2489
+ return parseQuantJson(response);
2490
+ }
2491
+
2492
+ export function lmsrCost(
2493
+ yesShares: number,
2494
+ noShares: number,
2495
+ b: number,
2496
+ outcome: "yes" | "no" | boolean,
2497
+ shares: number
2498
+ ): AMMCostResult {
2499
+ if (!quant) {
2500
+ warnQuantFallback();
2501
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2502
+ const costBefore = b * Math.log(Math.exp(yesShares / b) + Math.exp(noShares / b));
2503
+ const newYes = buyYes ? yesShares + shares : yesShares;
2504
+ const newNo = buyYes ? noShares : noShares + shares;
2505
+ const costAfter = b * Math.log(Math.exp(newYes / b) + Math.exp(newNo / b));
2506
+ return { cost: costAfter - costBefore, avg_price: (costAfter - costBefore) / shares };
2507
+ }
2508
+ const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
2509
+ const response = quant.quant_lmsr_cost(yesShares, noShares, b, buyYes, shares);
2510
+ return parseQuantJson(response);
2511
+ }
2512
+
2513
+ // ----- Arbitrage -----
2514
+
2515
+ export function detectArbitrage(yesPrice: number, noPrice: number): ArbitrageResult {
2516
+ if (!quant) {
2517
+ warnQuantFallback();
2518
+ const total = yesPrice + noPrice;
2519
+ return {
2520
+ has_arbitrage: total < 1,
2521
+ yes_price: yesPrice,
2522
+ no_price: noPrice,
2523
+ total,
2524
+ profit_per_share: total < 1 ? 1 - total : 0,
2525
+ };
2526
+ }
2527
+ const response = quant.quant_detect_arbitrage(yesPrice, noPrice);
2528
+ return parseQuantJson(response);
2529
+ }
2530
+
2531
+ // ----- Odds Conversion -----
2532
+
2533
+ const ODDS_TYPE_MAP: Record<string, number> = {
2534
+ probability: 0,
2535
+ decimal: 1,
2536
+ american: 2,
2537
+ };
2538
+
2539
+ export function convertOdds(value: number, fromType: "probability" | "decimal" | "american"): OddsConversion {
2540
+ if (!quant) {
2541
+ warnQuantFallback();
2542
+ let prob: number;
2543
+ switch (fromType) {
2544
+ case "probability": prob = value; break;
2545
+ case "decimal": prob = 1 / value; break;
2546
+ case "american": prob = value > 0 ? 100 / (value + 100) : -value / (-value + 100); break;
2547
+ }
2548
+ const americanOdds = prob >= 0.5 ? Math.round(-100 / (prob - 1)) : Math.round((1 - prob) / prob * 100);
2549
+ return { probability: prob, decimal_odds: 1 / prob, american_odds: americanOdds };
2550
+ }
2551
+ const response = quant.quant_convert_odds(value, ODDS_TYPE_MAP[fromType] ?? 0);
2552
+ return parseQuantJson(response);
2553
+ }
2554
+
2555
+ // ----- Statistics -----
2556
+
2557
+ export function quantMean(data: number[]): number {
2558
+ if (data.length === 0) return NaN;
2559
+ if (!quant) {
2560
+ warnQuantFallback();
2561
+ return data.reduce((a, b) => a + b, 0) / data.length;
2562
+ }
2563
+ const { ptr } = toFloat64Ptr(data);
2564
+ return quant.quant_mean(ptr, data.length);
2565
+ }
2566
+
2567
+ export function quantStdDev(data: number[]): number {
2568
+ if (data.length === 0) return NaN;
2569
+ if (!quant) {
2570
+ warnQuantFallback();
2571
+ const m = data.reduce((a, b) => a + b, 0) / data.length;
2572
+ return Math.sqrt(data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length);
2573
+ }
2574
+ const { ptr } = toFloat64Ptr(data);
2575
+ return quant.quant_std_dev(ptr, data.length);
2576
+ }
2577
+
2578
+ export function quantVariance(data: number[]): number {
2579
+ if (data.length === 0) return NaN;
2580
+ if (!quant) {
2581
+ warnQuantFallback();
2582
+ const m = data.reduce((a, b) => a + b, 0) / data.length;
2583
+ return data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length;
2584
+ }
2585
+ const { ptr } = toFloat64Ptr(data);
2586
+ return quant.quant_variance(ptr, data.length);
2587
+ }
2588
+
2589
+ export function quantCorrelation(x: number[], y: number[]): number {
2590
+ if (x.length === 0 || y.length === 0 || x.length !== y.length) return NaN;
2591
+ if (!quant) {
2592
+ warnQuantFallback();
2593
+ const n = x.length;
2594
+ const mx = x.reduce((a, b) => a + b, 0) / n;
2595
+ const my = y.reduce((a, b) => a + b, 0) / n;
2596
+ const cov = x.reduce((s, xi, i) => s + (xi - mx) * (y[i]! - my), 0) / n;
2597
+ const vx = x.reduce((s, xi) => s + (xi - mx) ** 2, 0) / n;
2598
+ const vy = y.reduce((s, yi) => s + (yi - my) ** 2, 0) / n;
2599
+ return cov / Math.sqrt(vx * vy);
2600
+ }
2601
+ const { ptr: ptrX } = toFloat64Ptr(x);
2602
+ const { ptr: ptrY } = toFloat64Ptr(y);
2603
+ return quant.quant_correlation(ptrX, ptrY, x.length);
2604
+ }
2605
+
2606
+
2607
+
2608
+
2609
+ // ===== TUI v2 Native Renderer Re-export =====
2610
+ // Re-export the NativeRenderer class directly from the native module (the .node binary)
2611
+ // Use lazy loading to avoid circular dependency issues during module initialization
2612
+
2613
+ import * as path from "path";
2614
+
2615
+ let _NativeRendererClass: any = null;
2616
+
2617
+ /**
2618
+ * Find the native module directory at runtime
2619
+ * Works both in development and when bundled
2620
+ */
2621
+ function findNativeDir(): string | null {
2622
+ // Try multiple possible locations for the native directory
2623
+ const possiblePaths = [
2624
+ // When running from dist/ (bundled)
2625
+ path.resolve(__dirname, "..", "..", "..", "native"),
2626
+ // When running from dist/native/ (native loader location)
2627
+ path.resolve(__dirname, "..", "..", "native"),
2628
+ // When running from packages/src/native/ (development)
2629
+ path.resolve(__dirname, "..", "..", "..", "..", "..", "native"),
2630
+ // Try from current working directory
2631
+ path.resolve(process.cwd(), "native"),
2632
+ // Try from dist directory relative to executable
2633
+ path.resolve(path.dirname(process.execPath), "..", "native"),
2634
+ ];
2635
+
2636
+ for (const p of possiblePaths) {
2637
+ try {
2638
+ const files = require("fs").readdirSync(p);
2639
+ if (files.some((f: string) => f.endsWith(".node"))) {
2640
+ return p;
2641
+ }
2642
+ } catch {
2643
+ // Directory doesn't exist or can't be read, try next
2644
+ }
2645
+ }
2646
+
2647
+ return null;
2648
+ }
2649
+
2650
+ /**
2651
+ * Get the NativeRenderer class (lazy-loaded to avoid circular dependencies)
2652
+ */
2653
+ function getNativeRendererClass(): any {
2654
+ if (!_NativeRendererClass) {
2655
+ const { platform, arch } = process;
2656
+
2657
+ // Find the native directory
2658
+ const nativeDir = findNativeDir();
2659
+ if (!nativeDir) {
2660
+ throw new Error("Could not find native module directory");
2661
+ }
2662
+
2663
+ // Determine the correct native module file based on platform
2664
+ let nativeFile: string;
2665
+ if (platform === "darwin" && arch === "arm64") {
2666
+ nativeFile = "index.darwin-arm64.node";
2667
+ } else if (platform === "darwin" && arch === "x64") {
2668
+ nativeFile = "claude_code_native.darwin-x64.node";
2669
+ } else if (platform === "linux" && arch === "x64") {
2670
+ nativeFile = "claude_code_native.linux-x64-gnu.node";
2671
+ } else if (platform === "win32" && arch === "x64") {
2672
+ nativeFile = "claude_code_native.win32-x64-msvc.node";
2673
+ } else {
2674
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
2675
+ }
2676
+
2677
+ const nativePath = path.join(nativeDir, nativeFile);
2678
+ const nativeModule = require(nativePath);
2679
+ _NativeRendererClass = nativeModule.NativeRenderer;
2680
+ }
2681
+ return _NativeRendererClass;
2682
+ }
2683
+
2684
+ /**
2685
+ * Lazy-loading wrapper for the NativeRenderer class
2686
+ * This allows us to defer loading the native module until it's actually needed
2687
+ */
2688
+ export const NativeRenderer = new Proxy(
2689
+ // Use a function as the target so it can be called with `new`
2690
+ function NativeRenderer(this: any, ...args: any[]) {
2691
+ const ActualClass = getNativeRendererClass();
2692
+ const instance = new ActualClass(...args);
2693
+ // Copy instance to `this` if called with new
2694
+ Object.assign(this, instance);
2695
+ return instance;
2696
+ } as any,
2697
+ {
2698
+ // Proxy property access to the actual class
2699
+ get(_target, prop) {
2700
+ const ActualClass = getNativeRendererClass();
2701
+ return Reflect.get(ActualClass, prop, ActualClass);
2702
+ },
2703
+ // Proxy static method calls
2704
+ apply(_target, _thisArg, args) {
2705
+ const ActualClass = getNativeRendererClass();
2706
+ return ActualClass(...args);
2707
+ },
2708
+ }
2709
+ ) as any;
2710
+
2711
+ // Type alias for the NativeRenderer instance type
2712
+ // Use typeof since NativeRenderer is a value (Proxy)
2713
+ export type NativeRendererType = typeof NativeRenderer;
2714
+
2715
+ // Note: RenderState, RenderMessage, InputEvent, SearchResult types are already
2716
+ // defined as interfaces in this file (lines 78-107).
2717
+ // Type aliases for the v2 TUI using the already-defined types
2718
+ export type NativeRenderState = RenderState;
2719
+ export type NativeRenderMessage = RenderMessage;
2720
+ export type NativeInputEvent = InputEvent;
2721
+ export type NativeSearchResult = SearchResult;
2722
+