@ebowwa/coder 0.2.1 → 0.7.64

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