@fraziym/axoniz 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/dist/agents/definition.d.ts +15 -0
  4. package/dist/agents/definition.d.ts.map +1 -0
  5. package/dist/agents/definition.js +41 -0
  6. package/dist/agents/definition.js.map +1 -0
  7. package/dist/agents/index.d.ts +12 -0
  8. package/dist/agents/index.d.ts.map +1 -0
  9. package/dist/agents/index.js +11 -0
  10. package/dist/agents/index.js.map +1 -0
  11. package/dist/agents/registry.d.ts +17 -0
  12. package/dist/agents/registry.d.ts.map +1 -0
  13. package/dist/agents/registry.js +23 -0
  14. package/dist/agents/registry.js.map +1 -0
  15. package/dist/agents/specialized.d.ts +31 -0
  16. package/dist/agents/specialized.d.ts.map +1 -0
  17. package/dist/agents/specialized.js +75 -0
  18. package/dist/agents/specialized.js.map +1 -0
  19. package/dist/awareness/index.d.ts +14 -0
  20. package/dist/awareness/index.d.ts.map +1 -0
  21. package/dist/awareness/index.js +22 -0
  22. package/dist/awareness/index.js.map +1 -0
  23. package/dist/awareness/service.d.ts +180 -0
  24. package/dist/awareness/service.d.ts.map +1 -0
  25. package/dist/awareness/service.js +789 -0
  26. package/dist/awareness/service.js.map +1 -0
  27. package/dist/cli/entry.d.ts +13 -0
  28. package/dist/cli/entry.d.ts.map +1 -0
  29. package/dist/cli/entry.js +35 -0
  30. package/dist/cli/entry.js.map +1 -0
  31. package/dist/comms/telegram.d.ts +41 -0
  32. package/dist/comms/telegram.d.ts.map +1 -0
  33. package/dist/comms/telegram.js +332 -0
  34. package/dist/comms/telegram.js.map +1 -0
  35. package/dist/core/agent.d.ts +252 -0
  36. package/dist/core/agent.d.ts.map +1 -0
  37. package/dist/core/agent.js +1399 -0
  38. package/dist/core/agent.js.map +1 -0
  39. package/dist/core/auth.d.ts +23 -0
  40. package/dist/core/auth.d.ts.map +1 -0
  41. package/dist/core/auth.js +113 -0
  42. package/dist/core/auth.js.map +1 -0
  43. package/dist/core/authority.d.ts +118 -0
  44. package/dist/core/authority.d.ts.map +1 -0
  45. package/dist/core/authority.js +402 -0
  46. package/dist/core/authority.js.map +1 -0
  47. package/dist/core/backend/async_queue.d.ts +17 -0
  48. package/dist/core/backend/async_queue.d.ts.map +1 -0
  49. package/dist/core/backend/async_queue.js +66 -0
  50. package/dist/core/backend/async_queue.js.map +1 -0
  51. package/dist/core/backend/index.d.ts +24 -0
  52. package/dist/core/backend/index.d.ts.map +1 -0
  53. package/dist/core/backend/index.js +128 -0
  54. package/dist/core/backend/index.js.map +1 -0
  55. package/dist/core/backend/llama_server.d.ts +39 -0
  56. package/dist/core/backend/llama_server.d.ts.map +1 -0
  57. package/dist/core/backend/llama_server.js +182 -0
  58. package/dist/core/backend/llama_server.js.map +1 -0
  59. package/dist/core/backend/llamacpp.d.ts +40 -0
  60. package/dist/core/backend/llamacpp.d.ts.map +1 -0
  61. package/dist/core/backend/llamacpp.js +200 -0
  62. package/dist/core/backend/llamacpp.js.map +1 -0
  63. package/dist/core/backend/lmstudio.d.ts +53 -0
  64. package/dist/core/backend/lmstudio.d.ts.map +1 -0
  65. package/dist/core/backend/lmstudio.js +274 -0
  66. package/dist/core/backend/lmstudio.js.map +1 -0
  67. package/dist/core/backend/ollama.d.ts +25 -0
  68. package/dist/core/backend/ollama.d.ts.map +1 -0
  69. package/dist/core/backend/ollama.js +86 -0
  70. package/dist/core/backend/ollama.js.map +1 -0
  71. package/dist/core/backend/openai.d.ts +27 -0
  72. package/dist/core/backend/openai.d.ts.map +1 -0
  73. package/dist/core/backend/openai.js +84 -0
  74. package/dist/core/backend/openai.js.map +1 -0
  75. package/dist/core/backend/types.d.ts +73 -0
  76. package/dist/core/backend/types.d.ts.map +1 -0
  77. package/dist/core/backend/types.js +137 -0
  78. package/dist/core/backend/types.js.map +1 -0
  79. package/dist/core/chat_store.d.ts +77 -0
  80. package/dist/core/chat_store.d.ts.map +1 -0
  81. package/dist/core/chat_store.js +332 -0
  82. package/dist/core/chat_store.js.map +1 -0
  83. package/dist/core/cli.d.ts +82 -0
  84. package/dist/core/cli.d.ts.map +1 -0
  85. package/dist/core/cli.js +602 -0
  86. package/dist/core/cli.js.map +1 -0
  87. package/dist/core/config.d.ts +127 -0
  88. package/dist/core/config.d.ts.map +1 -0
  89. package/dist/core/config.js +295 -0
  90. package/dist/core/config.js.map +1 -0
  91. package/dist/core/debug.d.ts +8 -0
  92. package/dist/core/debug.d.ts.map +1 -0
  93. package/dist/core/debug.js +8 -0
  94. package/dist/core/debug.js.map +1 -0
  95. package/dist/core/downloader.d.ts +31 -0
  96. package/dist/core/downloader.d.ts.map +1 -0
  97. package/dist/core/downloader.js +180 -0
  98. package/dist/core/downloader.js.map +1 -0
  99. package/dist/core/errors.d.ts +80 -0
  100. package/dist/core/errors.d.ts.map +1 -0
  101. package/dist/core/errors.js +134 -0
  102. package/dist/core/errors.js.map +1 -0
  103. package/dist/core/extras.d.ts +160 -0
  104. package/dist/core/extras.d.ts.map +1 -0
  105. package/dist/core/extras.js +553 -0
  106. package/dist/core/extras.js.map +1 -0
  107. package/dist/core/health.d.ts +27 -0
  108. package/dist/core/health.d.ts.map +1 -0
  109. package/dist/core/health.js +96 -0
  110. package/dist/core/health.js.map +1 -0
  111. package/dist/core/history.d.ts +50 -0
  112. package/dist/core/history.d.ts.map +1 -0
  113. package/dist/core/history.js +276 -0
  114. package/dist/core/history.js.map +1 -0
  115. package/dist/core/index.d.ts +6 -0
  116. package/dist/core/index.d.ts.map +1 -0
  117. package/dist/core/index.js +6 -0
  118. package/dist/core/index.js.map +1 -0
  119. package/dist/core/intelligence/ast_index.d.ts +255 -0
  120. package/dist/core/intelligence/ast_index.d.ts.map +1 -0
  121. package/dist/core/intelligence/ast_index.js +1369 -0
  122. package/dist/core/intelligence/ast_index.js.map +1 -0
  123. package/dist/core/intelligence/confidence.d.ts +113 -0
  124. package/dist/core/intelligence/confidence.d.ts.map +1 -0
  125. package/dist/core/intelligence/confidence.js +298 -0
  126. package/dist/core/intelligence/confidence.js.map +1 -0
  127. package/dist/core/intelligence/context_compressor.d.ts +80 -0
  128. package/dist/core/intelligence/context_compressor.d.ts.map +1 -0
  129. package/dist/core/intelligence/context_compressor.js +245 -0
  130. package/dist/core/intelligence/context_compressor.js.map +1 -0
  131. package/dist/core/intelligence/daemon.d.ts +247 -0
  132. package/dist/core/intelligence/daemon.d.ts.map +1 -0
  133. package/dist/core/intelligence/daemon.js +842 -0
  134. package/dist/core/intelligence/daemon.js.map +1 -0
  135. package/dist/core/intelligence/index.d.ts +60 -0
  136. package/dist/core/intelligence/index.d.ts.map +1 -0
  137. package/dist/core/intelligence/index.js +101 -0
  138. package/dist/core/intelligence/index.js.map +1 -0
  139. package/dist/core/intelligence/predictor.d.ts +246 -0
  140. package/dist/core/intelligence/predictor.d.ts.map +1 -0
  141. package/dist/core/intelligence/predictor.js +590 -0
  142. package/dist/core/intelligence/predictor.js.map +1 -0
  143. package/dist/core/intelligence/reflex.d.ts +84 -0
  144. package/dist/core/intelligence/reflex.d.ts.map +1 -0
  145. package/dist/core/intelligence/reflex.js +344 -0
  146. package/dist/core/intelligence/reflex.js.map +1 -0
  147. package/dist/core/intelligence/self_correction.d.ts +121 -0
  148. package/dist/core/intelligence/self_correction.d.ts.map +1 -0
  149. package/dist/core/intelligence/self_correction.js +327 -0
  150. package/dist/core/intelligence/self_correction.js.map +1 -0
  151. package/dist/core/intelligence/skill_distiller.d.ts +100 -0
  152. package/dist/core/intelligence/skill_distiller.d.ts.map +1 -0
  153. package/dist/core/intelligence/skill_distiller.js +246 -0
  154. package/dist/core/intelligence/skill_distiller.js.map +1 -0
  155. package/dist/core/intelligence/swarm.d.ts +330 -0
  156. package/dist/core/intelligence/swarm.d.ts.map +1 -0
  157. package/dist/core/intelligence/swarm.js +1064 -0
  158. package/dist/core/intelligence/swarm.js.map +1 -0
  159. package/dist/core/intelligence/trajectory.d.ts +107 -0
  160. package/dist/core/intelligence/trajectory.d.ts.map +1 -0
  161. package/dist/core/intelligence/trajectory.js +330 -0
  162. package/dist/core/intelligence/trajectory.js.map +1 -0
  163. package/dist/core/logger.d.ts +111 -0
  164. package/dist/core/logger.d.ts.map +1 -0
  165. package/dist/core/logger.js +640 -0
  166. package/dist/core/logger.js.map +1 -0
  167. package/dist/core/loop.d.ts +123 -0
  168. package/dist/core/loop.d.ts.map +1 -0
  169. package/dist/core/loop.js +423 -0
  170. package/dist/core/loop.js.map +1 -0
  171. package/dist/core/memory.d.ts +81 -0
  172. package/dist/core/memory.d.ts.map +1 -0
  173. package/dist/core/memory.js +328 -0
  174. package/dist/core/memory.js.map +1 -0
  175. package/dist/core/metrics.d.ts +29 -0
  176. package/dist/core/metrics.d.ts.map +1 -0
  177. package/dist/core/metrics.js +109 -0
  178. package/dist/core/metrics.js.map +1 -0
  179. package/dist/core/models.d.ts +51 -0
  180. package/dist/core/models.d.ts.map +1 -0
  181. package/dist/core/models.js +146 -0
  182. package/dist/core/models.js.map +1 -0
  183. package/dist/core/optimizer.d.ts +34 -0
  184. package/dist/core/optimizer.d.ts.map +1 -0
  185. package/dist/core/optimizer.js +131 -0
  186. package/dist/core/optimizer.js.map +1 -0
  187. package/dist/core/persona.d.ts +35 -0
  188. package/dist/core/persona.d.ts.map +1 -0
  189. package/dist/core/persona.js +126 -0
  190. package/dist/core/persona.js.map +1 -0
  191. package/dist/core/rate_limit.d.ts +23 -0
  192. package/dist/core/rate_limit.d.ts.map +1 -0
  193. package/dist/core/rate_limit.js +62 -0
  194. package/dist/core/rate_limit.js.map +1 -0
  195. package/dist/core/runner.d.ts +63 -0
  196. package/dist/core/runner.d.ts.map +1 -0
  197. package/dist/core/runner.js +671 -0
  198. package/dist/core/runner.js.map +1 -0
  199. package/dist/core/stream_parser.d.ts +43 -0
  200. package/dist/core/stream_parser.d.ts.map +1 -0
  201. package/dist/core/stream_parser.js +140 -0
  202. package/dist/core/stream_parser.js.map +1 -0
  203. package/dist/core/tool_schemas.d.ts +26 -0
  204. package/dist/core/tool_schemas.d.ts.map +1 -0
  205. package/dist/core/tool_schemas.js +124 -0
  206. package/dist/core/tool_schemas.js.map +1 -0
  207. package/dist/core/which.d.ts +2 -0
  208. package/dist/core/which.d.ts.map +1 -0
  209. package/dist/core/which.js +35 -0
  210. package/dist/core/which.js.map +1 -0
  211. package/dist/goals/index.d.ts +9 -0
  212. package/dist/goals/index.d.ts.map +1 -0
  213. package/dist/goals/index.js +17 -0
  214. package/dist/goals/index.js.map +1 -0
  215. package/dist/goals/service.d.ts +115 -0
  216. package/dist/goals/service.d.ts.map +1 -0
  217. package/dist/goals/service.js +415 -0
  218. package/dist/goals/service.js.map +1 -0
  219. package/dist/goals/types.d.ts +47 -0
  220. package/dist/goals/types.d.ts.map +1 -0
  221. package/dist/goals/types.js +66 -0
  222. package/dist/goals/types.js.map +1 -0
  223. package/dist/index.d.ts +22 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +22 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/integrations/autonomous_startup.d.ts +51 -0
  228. package/dist/integrations/autonomous_startup.d.ts.map +1 -0
  229. package/dist/integrations/autonomous_startup.js +419 -0
  230. package/dist/integrations/autonomous_startup.js.map +1 -0
  231. package/dist/integrations/goose.d.ts +105 -0
  232. package/dist/integrations/goose.d.ts.map +1 -0
  233. package/dist/integrations/goose.js +408 -0
  234. package/dist/integrations/goose.js.map +1 -0
  235. package/dist/integrations/index.d.ts +21 -0
  236. package/dist/integrations/index.d.ts.map +1 -0
  237. package/dist/integrations/index.js +17 -0
  238. package/dist/integrations/index.js.map +1 -0
  239. package/dist/integrations/mcp.d.ts +73 -0
  240. package/dist/integrations/mcp.d.ts.map +1 -0
  241. package/dist/integrations/mcp.js +307 -0
  242. package/dist/integrations/mcp.js.map +1 -0
  243. package/dist/integrations/mempalace.d.ts +18 -0
  244. package/dist/integrations/mempalace.d.ts.map +1 -0
  245. package/dist/integrations/mempalace.js +25 -0
  246. package/dist/integrations/mempalace.js.map +1 -0
  247. package/dist/integrations/multi_agent.d.ts +82 -0
  248. package/dist/integrations/multi_agent.d.ts.map +1 -0
  249. package/dist/integrations/multi_agent.js +280 -0
  250. package/dist/integrations/multi_agent.js.map +1 -0
  251. package/dist/integrations/unified_memory.d.ts +415 -0
  252. package/dist/integrations/unified_memory.d.ts.map +1 -0
  253. package/dist/integrations/unified_memory.js +1489 -0
  254. package/dist/integrations/unified_memory.js.map +1 -0
  255. package/dist/roles/beru.yaml +48 -0
  256. package/dist/sidecar/client.d.ts +63 -0
  257. package/dist/sidecar/client.d.ts.map +1 -0
  258. package/dist/sidecar/client.js +222 -0
  259. package/dist/sidecar/client.js.map +1 -0
  260. package/dist/sidecar/index.d.ts +7 -0
  261. package/dist/sidecar/index.d.ts.map +1 -0
  262. package/dist/sidecar/index.js +6 -0
  263. package/dist/sidecar/index.js.map +1 -0
  264. package/dist/startup.d.ts +22 -0
  265. package/dist/startup.d.ts.map +1 -0
  266. package/dist/startup.js +194 -0
  267. package/dist/startup.js.map +1 -0
  268. package/dist/tools/_internal.d.ts +90 -0
  269. package/dist/tools/_internal.d.ts.map +1 -0
  270. package/dist/tools/_internal.js +375 -0
  271. package/dist/tools/_internal.js.map +1 -0
  272. package/dist/tools/_smoke.d.ts +2 -0
  273. package/dist/tools/_smoke.d.ts.map +1 -0
  274. package/dist/tools/_smoke.js +203 -0
  275. package/dist/tools/_smoke.js.map +1 -0
  276. package/dist/tools/axodex_tools.d.ts +51 -0
  277. package/dist/tools/axodex_tools.d.ts.map +1 -0
  278. package/dist/tools/axodex_tools.js +181 -0
  279. package/dist/tools/axodex_tools.js.map +1 -0
  280. package/dist/tools/code_tools.d.ts +33 -0
  281. package/dist/tools/code_tools.d.ts.map +1 -0
  282. package/dist/tools/code_tools.js +191 -0
  283. package/dist/tools/code_tools.js.map +1 -0
  284. package/dist/tools/computer_tools.d.ts +59 -0
  285. package/dist/tools/computer_tools.d.ts.map +1 -0
  286. package/dist/tools/computer_tools.js +348 -0
  287. package/dist/tools/computer_tools.js.map +1 -0
  288. package/dist/tools/file_tools.d.ts +51 -0
  289. package/dist/tools/file_tools.d.ts.map +1 -0
  290. package/dist/tools/file_tools.js +424 -0
  291. package/dist/tools/file_tools.js.map +1 -0
  292. package/dist/tools/index.d.ts +13 -0
  293. package/dist/tools/index.d.ts.map +1 -0
  294. package/dist/tools/index.js +13 -0
  295. package/dist/tools/index.js.map +1 -0
  296. package/dist/tools/shell_tools.d.ts +39 -0
  297. package/dist/tools/shell_tools.d.ts.map +1 -0
  298. package/dist/tools/shell_tools.js +163 -0
  299. package/dist/tools/shell_tools.js.map +1 -0
  300. package/dist/tools/web_tools.d.ts +31 -0
  301. package/dist/tools/web_tools.d.ts.map +1 -0
  302. package/dist/tools/web_tools.js +117 -0
  303. package/dist/tools/web_tools.js.map +1 -0
  304. package/dist/voice/index.d.ts +41 -0
  305. package/dist/voice/index.d.ts.map +1 -0
  306. package/dist/voice/index.js +58 -0
  307. package/dist/voice/index.js.map +1 -0
  308. package/dist/voice/light_daemon.d.ts +197 -0
  309. package/dist/voice/light_daemon.d.ts.map +1 -0
  310. package/dist/voice/light_daemon.js +746 -0
  311. package/dist/voice/light_daemon.js.map +1 -0
  312. package/dist/voice/setup.d.ts +63 -0
  313. package/dist/voice/setup.d.ts.map +1 -0
  314. package/dist/voice/setup.js +443 -0
  315. package/dist/voice/setup.js.map +1 -0
  316. package/dist/voice/stt.d.ts +148 -0
  317. package/dist/voice/stt.d.ts.map +1 -0
  318. package/dist/voice/stt.js +361 -0
  319. package/dist/voice/stt.js.map +1 -0
  320. package/dist/voice/tts.d.ts +168 -0
  321. package/dist/voice/tts.d.ts.map +1 -0
  322. package/dist/voice/tts.js +698 -0
  323. package/dist/voice/tts.js.map +1 -0
  324. package/dist/voice/voice_loop.d.ts +101 -0
  325. package/dist/voice/voice_loop.d.ts.map +1 -0
  326. package/dist/voice/voice_loop.js +463 -0
  327. package/dist/voice/voice_loop.js.map +1 -0
  328. package/dist/voice/wake_word.d.ts +153 -0
  329. package/dist/voice/wake_word.d.ts.map +1 -0
  330. package/dist/voice/wake_word.js +458 -0
  331. package/dist/voice/wake_word.js.map +1 -0
  332. package/dist/voice/wav.d.ts +99 -0
  333. package/dist/voice/wav.d.ts.map +1 -0
  334. package/dist/voice/wav.js +306 -0
  335. package/dist/voice/wav.js.map +1 -0
  336. package/dist/web/broker.d.ts +33 -0
  337. package/dist/web/broker.d.ts.map +1 -0
  338. package/dist/web/broker.js +58 -0
  339. package/dist/web/broker.js.map +1 -0
  340. package/dist/web/open_browser.d.ts +2 -0
  341. package/dist/web/open_browser.d.ts.map +1 -0
  342. package/dist/web/open_browser.js +42 -0
  343. package/dist/web/open_browser.js.map +1 -0
  344. package/dist/web/server.d.ts +54 -0
  345. package/dist/web/server.d.ts.map +1 -0
  346. package/dist/web/server.js +831 -0
  347. package/dist/web/server.js.map +1 -0
  348. package/dist/web/static/app.js +4121 -0
  349. package/dist/web/static/index.html +2281 -0
  350. package/dist/web/static/js/MODULE_SUMMARY.md +124 -0
  351. package/dist/web/static/js/a11y.js +165 -0
  352. package/dist/web/static/js/admin.js +2145 -0
  353. package/dist/web/static/js/assistant.js +475 -0
  354. package/dist/web/static/js/calendar/reminders.js +114 -0
  355. package/dist/web/static/js/calendar/utils.js +166 -0
  356. package/dist/web/static/js/calendar.js +3348 -0
  357. package/dist/web/static/js/censor.js +356 -0
  358. package/dist/web/static/js/chat.js +4546 -0
  359. package/dist/web/static/js/chatRenderer.js +2294 -0
  360. package/dist/web/static/js/chatStream.js +276 -0
  361. package/dist/web/static/js/codeRunner.js +398 -0
  362. package/dist/web/static/js/color/hex.js +14 -0
  363. package/dist/web/static/js/colorPicker.js +453 -0
  364. package/dist/web/static/js/compare/icons.js +77 -0
  365. package/dist/web/static/js/compare/index.js +1482 -0
  366. package/dist/web/static/js/compare/models.js +104 -0
  367. package/dist/web/static/js/compare/panes.js +817 -0
  368. package/dist/web/static/js/compare/probe.js +78 -0
  369. package/dist/web/static/js/compare/scoreboard.js +223 -0
  370. package/dist/web/static/js/compare/selector.js +1335 -0
  371. package/dist/web/static/js/compare/state.js +58 -0
  372. package/dist/web/static/js/compare/stream.js +695 -0
  373. package/dist/web/static/js/compare/vote.js +254 -0
  374. package/dist/web/static/js/cookbook-diagnosis.js +694 -0
  375. package/dist/web/static/js/cookbook-hwfit.js +1888 -0
  376. package/dist/web/static/js/cookbook.js +2093 -0
  377. package/dist/web/static/js/cookbookDownload.js +633 -0
  378. package/dist/web/static/js/cookbookProgressSignal.js +29 -0
  379. package/dist/web/static/js/cookbookRunning.js +3506 -0
  380. package/dist/web/static/js/cookbookServe.js +2128 -0
  381. package/dist/web/static/js/document.js +9731 -0
  382. package/dist/web/static/js/documentLibrary.js +3376 -0
  383. package/dist/web/static/js/dragSort.js +265 -0
  384. package/dist/web/static/js/editor/ai-inpaint.js +374 -0
  385. package/dist/web/static/js/editor/ai-models.js +273 -0
  386. package/dist/web/static/js/editor/ai-rembg.js +230 -0
  387. package/dist/web/static/js/editor/ai-tool-runner.js +147 -0
  388. package/dist/web/static/js/editor/ai-tools-misc.js +216 -0
  389. package/dist/web/static/js/editor/build/controls.js +366 -0
  390. package/dist/web/static/js/editor/build/popups.js +112 -0
  391. package/dist/web/static/js/editor/build/right-panel.js +200 -0
  392. package/dist/web/static/js/editor/build/toolbar.js +73 -0
  393. package/dist/web/static/js/editor/build/topbar.js +131 -0
  394. package/dist/web/static/js/editor/build/transform-popup.js +109 -0
  395. package/dist/web/static/js/editor/canvas-coords.js +21 -0
  396. package/dist/web/static/js/editor/canvas-events.js +197 -0
  397. package/dist/web/static/js/editor/canvas-transforms.js +132 -0
  398. package/dist/web/static/js/editor/checkerboard.js +24 -0
  399. package/dist/web/static/js/editor/clipboard-and-drop.js +133 -0
  400. package/dist/web/static/js/editor/composite-helpers.js +83 -0
  401. package/dist/web/static/js/editor/filters/blur.js +118 -0
  402. package/dist/web/static/js/editor/filters/edge-feather.js +70 -0
  403. package/dist/web/static/js/editor/fx/adj-popup.js +677 -0
  404. package/dist/web/static/js/editor/fx/filter-string.js +38 -0
  405. package/dist/web/static/js/editor/fx/histogram.js +67 -0
  406. package/dist/web/static/js/editor/fx/pixel-pass.js +249 -0
  407. package/dist/web/static/js/editor/harmonize-masks.js +116 -0
  408. package/dist/web/static/js/editor/history-panel.js +176 -0
  409. package/dist/web/static/js/editor/keyboard-shortcuts.js +271 -0
  410. package/dist/web/static/js/editor/layer-helpers.js +131 -0
  411. package/dist/web/static/js/editor/layer-panel.js +600 -0
  412. package/dist/web/static/js/editor/mask-utils.js +91 -0
  413. package/dist/web/static/js/editor/shortcuts-popover.js +149 -0
  414. package/dist/web/static/js/editor/slider-ux.js +191 -0
  415. package/dist/web/static/js/editor/snap.js +107 -0
  416. package/dist/web/static/js/editor/state.js +257 -0
  417. package/dist/web/static/js/editor/stroke-pipeline.js +162 -0
  418. package/dist/web/static/js/editor/stroke-tool-sliders.js +64 -0
  419. package/dist/web/static/js/editor/tools/clone.js +81 -0
  420. package/dist/web/static/js/editor/tools/crop.js +137 -0
  421. package/dist/web/static/js/editor/tools/flood-fill.js +72 -0
  422. package/dist/web/static/js/editor/tools/lasso-mask.js +171 -0
  423. package/dist/web/static/js/editor/tools/lasso.js +65 -0
  424. package/dist/web/static/js/editor/tools/move.js +79 -0
  425. package/dist/web/static/js/editor/tools/stroke.js +123 -0
  426. package/dist/web/static/js/editor/tools/transform-drag.js +174 -0
  427. package/dist/web/static/js/editor/tools/transform-handles.js +271 -0
  428. package/dist/web/static/js/editor/tools/transform-session.js +381 -0
  429. package/dist/web/static/js/editor/tools/wand.js +46 -0
  430. package/dist/web/static/js/editor/wire-import.js +148 -0
  431. package/dist/web/static/js/editor/wire-inpaint-controls.js +164 -0
  432. package/dist/web/static/js/editor/wire-merge-buttons.js +103 -0
  433. package/dist/web/static/js/editor/wire-selection-controls.js +170 -0
  434. package/dist/web/static/js/editor/wire-topbar-menus.js +174 -0
  435. package/dist/web/static/js/editor/wire-topbar-overflow.js +49 -0
  436. package/dist/web/static/js/editor/wire-topbar.js +188 -0
  437. package/dist/web/static/js/emailInbox.js +1245 -0
  438. package/dist/web/static/js/emailLibrary/replyRecipients.js +27 -0
  439. package/dist/web/static/js/emailLibrary/signatureFold.js +339 -0
  440. package/dist/web/static/js/emailLibrary/state.js +34 -0
  441. package/dist/web/static/js/emailLibrary/utils.js +202 -0
  442. package/dist/web/static/js/emailLibrary.js +5217 -0
  443. package/dist/web/static/js/emojiPicker.js +311 -0
  444. package/dist/web/static/js/escMenuStack.js +102 -0
  445. package/dist/web/static/js/fileHandler.js +295 -0
  446. package/dist/web/static/js/gallery.js +2835 -0
  447. package/dist/web/static/js/galleryEditor.js +3798 -0
  448. package/dist/web/static/js/group.js +955 -0
  449. package/dist/web/static/js/init.js +405 -0
  450. package/dist/web/static/js/keyboard-shortcuts.js +292 -0
  451. package/dist/web/static/js/langIcons.js +187 -0
  452. package/dist/web/static/js/markdown/tableRow.js +19 -0
  453. package/dist/web/static/js/markdown.js +806 -0
  454. package/dist/web/static/js/memory.js +1418 -0
  455. package/dist/web/static/js/modalManager.js +1552 -0
  456. package/dist/web/static/js/modalSnap.js +782 -0
  457. package/dist/web/static/js/model/matchKey.js +19 -0
  458. package/dist/web/static/js/modelPicker.js +695 -0
  459. package/dist/web/static/js/modelSort.js +33 -0
  460. package/dist/web/static/js/models.js +642 -0
  461. package/dist/web/static/js/notes.js +5054 -0
  462. package/dist/web/static/js/package.json +1 -0
  463. package/dist/web/static/js/platform.js +47 -0
  464. package/dist/web/static/js/presets.js +1110 -0
  465. package/dist/web/static/js/providers.js +93 -0
  466. package/dist/web/static/js/rag.js +177 -0
  467. package/dist/web/static/js/research/jobs.js +335 -0
  468. package/dist/web/static/js/research/panel.js +1233 -0
  469. package/dist/web/static/js/researchSynapse.js +225 -0
  470. package/dist/web/static/js/search-chat.js +201 -0
  471. package/dist/web/static/js/search.js +52 -0
  472. package/dist/web/static/js/section-management.js +260 -0
  473. package/dist/web/static/js/sessions.js +3108 -0
  474. package/dist/web/static/js/settings.js +4991 -0
  475. package/dist/web/static/js/sidebar-layout.js +573 -0
  476. package/dist/web/static/js/signature.js +504 -0
  477. package/dist/web/static/js/skills.js +1908 -0
  478. package/dist/web/static/js/slashAutocomplete.js +267 -0
  479. package/dist/web/static/js/slashCommands.js +6099 -0
  480. package/dist/web/static/js/spinner.js +406 -0
  481. package/dist/web/static/js/storage.js +123 -0
  482. package/dist/web/static/js/tasks.js +2699 -0
  483. package/dist/web/static/js/theme.js +2086 -0
  484. package/dist/web/static/js/tileManager.js +386 -0
  485. package/dist/web/static/js/tourAutoplay.js +133 -0
  486. package/dist/web/static/js/tourHints.js +179 -0
  487. package/dist/web/static/js/tts-ai.js +521 -0
  488. package/dist/web/static/js/ui.js +1288 -0
  489. package/dist/web/static/js/util/ordinal.js +13 -0
  490. package/dist/web/static/js/voiceRecorder.js +283 -0
  491. package/dist/web/static/js/windowDrag.js +326 -0
  492. package/dist/web/static/js/windowResize.js +233 -0
  493. package/dist/web/static/landing.html +824 -0
  494. package/dist/web/static/lib/docx.umd.min.js +20116 -0
  495. package/dist/web/static/lib/highlight.min.js +1213 -0
  496. package/dist/web/static/lib/html2pdf.bundle.min.js +3 -0
  497. package/dist/web/static/lib/mammoth.browser.min.js +21 -0
  498. package/dist/web/static/lib/qrcode.min.js +8 -0
  499. package/dist/web/static/lib/xlsx.full.min.js +24 -0
  500. package/dist/web/static/login.html +582 -0
  501. package/dist/web/static/manifest.json +15 -0
  502. package/dist/web/static/style.css +35733 -0
  503. package/dist/web/static/sw.js +144 -0
  504. package/dist/workflows/engine.d.ts +162 -0
  505. package/dist/workflows/engine.d.ts.map +1 -0
  506. package/dist/workflows/engine.js +625 -0
  507. package/dist/workflows/engine.js.map +1 -0
  508. package/dist/workflows/index.d.ts +8 -0
  509. package/dist/workflows/index.d.ts.map +1 -0
  510. package/dist/workflows/index.js +14 -0
  511. package/dist/workflows/index.js.map +1 -0
  512. package/package.json +112 -0
@@ -0,0 +1,789 @@
1
+ /**
2
+ * src/awareness/service.ts
3
+ * ============================
4
+ * BERU Awareness Service — proactive environment monitoring.
5
+ *
6
+ * Inspired by Jarvis src/awareness/ — Python reimplementation, now ported.
7
+ *
8
+ * Monitors:
9
+ * - Screen content via screenshot + OCR (tesseract via node:child_process)
10
+ * - Clipboard changes
11
+ * - Active window title
12
+ * - System load (CPU/RAM/disk)
13
+ * - Proactively suggests relevant actions based on context
14
+ *
15
+ * BERU wakes up and says: "I see you're looking at X — want me to Y?"
16
+ *
17
+ * ── Port notes ───────────────────────────────────────────────────────────────
18
+ * psutil → `systeminformation` (installed) with a zero-dep fallback
19
+ * pyautogui/PIL → `screenshot-desktop` (installed) + `sharp` (installed)
20
+ * pytesseract → shell out to the `tesseract` binary (this is exactly what
21
+ * pytesseract does internally)
22
+ * pyperclip/win32 → PowerShell `Get-Clipboard` / `pbpaste` / `xclip`
23
+ *
24
+ * Every degraded capability returns a clear `[ERROR] …`/`[X unavailable …]`
25
+ * string and never throws.
26
+ */
27
+ import { execFileSync, spawn } from "node:child_process";
28
+ import fs from "node:fs";
29
+ import os from "node:os";
30
+ import path from "node:path";
31
+ import { getLogger } from "../core/logger.js";
32
+ import { info as logInfo, debug as logDebug } from "../core/debug.js";
33
+ import { whichSync } from "../core/which.js";
34
+ import { loadConfig } from "../core/config.js";
35
+ const logger = getLogger();
36
+ /**
37
+ * Optional-dependency loader.
38
+ *
39
+ * All three packages are CommonJS, so a plain `await import()` nests the real
40
+ * exports under `.default`; `unwrapModule()` normalises that. Dynamic import also
41
+ * resolves relative to *this* module (unlike `createRequire(import.meta.url)`,
42
+ * which breaks when the compiled output lives outside the project tree).
43
+ */
44
+ async function loadOptional(id) {
45
+ try {
46
+ return unwrapModule(await import(id));
47
+ }
48
+ catch (e) {
49
+ logDebug(`[Awareness] optional dependency '${id}' unavailable: ${errText(e)}`);
50
+ return null;
51
+ }
52
+ }
53
+ /** Unwrap a CJS namespace object (`await import()` nests named exports in `.default`). */
54
+ function unwrapModule(mod) {
55
+ if (mod === null || mod === undefined)
56
+ return null;
57
+ if (typeof mod !== "object")
58
+ return mod;
59
+ const record = mod;
60
+ const dflt = record["default"];
61
+ if (dflt !== undefined && (typeof dflt === "function" || typeof dflt === "object")) {
62
+ return dflt;
63
+ }
64
+ return record;
65
+ }
66
+ let _sharp;
67
+ async function getSharp() {
68
+ if (_sharp === undefined) {
69
+ _sharp = await loadOptional("sharp");
70
+ }
71
+ return _sharp;
72
+ }
73
+ let _screenshot;
74
+ async function getScreenshot() {
75
+ if (_screenshot === undefined) {
76
+ _screenshot = await loadOptional("screenshot-desktop");
77
+ }
78
+ return _screenshot;
79
+ }
80
+ let _cachedMetrics = null;
81
+ let _cachedMetricsAt = 0;
82
+ let _metricsInFlight = null;
83
+ function osName() {
84
+ switch (os.platform()) {
85
+ case "win32":
86
+ return "Windows";
87
+ case "darwin":
88
+ return "Darwin";
89
+ case "linux":
90
+ return "Linux";
91
+ default:
92
+ return os.platform();
93
+ }
94
+ }
95
+ /**
96
+ * Returns CPU, RAM and disk usage.
97
+ *
98
+ * TODO(port): Python used `psutil` behind an ImportError guard with a zero-dep
99
+ * fallback. The Node equivalent is `systeminformation` (installed). This keeps
100
+ * the synchronous Python signature by serving a short-lived cache and
101
+ * refreshing in the background, so the very first call returns zeros exactly
102
+ * like the Python fallback path did.
103
+ */
104
+ export function get_system_metrics() {
105
+ if (_cachedMetrics && Date.now() - _cachedMetricsAt < 2000)
106
+ return _cachedMetrics;
107
+ if (!_metricsInFlight) {
108
+ _metricsInFlight = collectMetrics()
109
+ .then((m) => {
110
+ _cachedMetrics = m;
111
+ _cachedMetricsAt = Date.now();
112
+ return m;
113
+ })
114
+ .catch((e) => {
115
+ logDebug(`[Awareness] metrics refresh failed: ${errText(e)}`);
116
+ const fallback = emptyMetrics();
117
+ _cachedMetrics = fallback;
118
+ _cachedMetricsAt = Date.now();
119
+ return fallback;
120
+ })
121
+ .finally(() => {
122
+ _metricsInFlight = null;
123
+ });
124
+ }
125
+ return _cachedMetrics ?? emptyMetrics();
126
+ }
127
+ function emptyMetrics() {
128
+ return { cpu_percent: 0, ram_percent: 0, disk_percent: 0, platform: osName() };
129
+ }
130
+ /** Await a fresh metrics sample (used by the awareness loop). */
131
+ export async function getSystemMetricsAsync() {
132
+ const m = await collectMetrics().catch(() => emptyMetrics());
133
+ _cachedMetrics = m;
134
+ _cachedMetricsAt = Date.now();
135
+ return m;
136
+ }
137
+ async function collectMetrics() {
138
+ const metrics = emptyMetrics();
139
+ try {
140
+ const si = await loadOptional("systeminformation");
141
+ if (!si)
142
+ return metrics;
143
+ if (typeof si.currentLoad === "function") {
144
+ const load = await si.currentLoad();
145
+ metrics.cpu_percent = clampPercent(load.currentLoad ?? 0);
146
+ }
147
+ if (typeof si.mem === "function") {
148
+ const mem = await si.mem();
149
+ const used = mem.active ?? mem.used ?? 0;
150
+ const total = mem.total ?? 0;
151
+ metrics.ram_percent = total > 0 ? clampPercent((used / total) * 100) : 0;
152
+ }
153
+ if (typeof si.fsSize === "function") {
154
+ const fsSizes = await si.fsSize();
155
+ const root = Array.isArray(fsSizes) && fsSizes.length > 0 ? (fsSizes[0]?.use ?? 0) : 0;
156
+ metrics.disk_percent = clampPercent(root);
157
+ }
158
+ }
159
+ catch (e) {
160
+ // Missing/unusable `systeminformation` mirrors Python's `except ImportError: pass`.
161
+ logDebug(`[Awareness] systeminformation unavailable: ${errText(e)}`);
162
+ }
163
+ return metrics;
164
+ }
165
+ function clampPercent(n) {
166
+ if (!Number.isFinite(n))
167
+ return 0;
168
+ return Math.max(0, Math.min(100, Number(n.toFixed(1))));
169
+ }
170
+ /* ────────────────────────────────────────────────────────────────────────────
171
+ * Active window title / clipboard
172
+ * ──────────────────────────────────────────────────────────────────────────── */
173
+ /** Run a short-lived helper command, returning stdout or "" (never throws). */
174
+ function tryExec(file, args, timeoutMs = 2000) {
175
+ try {
176
+ const out = execFileSync(file, args, {
177
+ timeout: timeoutMs,
178
+ windowsHide: true,
179
+ stdio: ["ignore", "pipe", "ignore"],
180
+ });
181
+ return Buffer.isBuffer(out) ? out.toString("utf8") : String(out);
182
+ }
183
+ catch {
184
+ return "";
185
+ }
186
+ }
187
+ const WIN_FOREGROUND_PS = "Add-Type -Namespace W -Name N -MemberDefinition '" +
188
+ '[DllImport("user32.dll")] public static extern System.IntPtr GetForegroundWindow();' +
189
+ '[DllImport("user32.dll")] public static extern int GetWindowTextLength(System.IntPtr h);' +
190
+ '[DllImport("user32.dll", CharSet=CharSet.Unicode)] public static extern int GetWindowText(System.IntPtr h, System.Text.StringBuilder s, int n);' +
191
+ "';" +
192
+ "$h=[W.N]::GetForegroundWindow();" +
193
+ "$len=[W.N]::GetWindowTextLength($h);" +
194
+ "$sb=New-Object System.Text.StringBuilder ($len+1);" +
195
+ "[void][W.N]::GetWindowText($h,$sb,$len+1);" +
196
+ "[Console]::Out.Write($sb.ToString())";
197
+ /**
198
+ * Best-effort active window title.
199
+ *
200
+ * TODO(port): Python used `ctypes.windll.user32` on Windows, `osascript` on
201
+ * macOS and `xdotool` on Linux. There is no synchronous Win32 binding here, so
202
+ * Windows shells out to PowerShell. The "return '' on any failure" contract is
203
+ * preserved exactly.
204
+ */
205
+ export function get_active_window_title() {
206
+ try {
207
+ switch (os.platform()) {
208
+ case "win32":
209
+ return tryExec("powershell", ["-NoProfile", "-c", WIN_FOREGROUND_PS]).trim();
210
+ case "darwin":
211
+ return tryExec("osascript", [
212
+ "-e",
213
+ 'tell application "System Events" to get name of first process whose frontmost is true',
214
+ ]).trim();
215
+ default: {
216
+ const xdotool = whichSync("xdotool");
217
+ if (xdotool)
218
+ return tryExec(xdotool, ["getactivewindow", "getwindowname"]).trim();
219
+ const xprop = whichSync("xprop");
220
+ if (xprop) {
221
+ const line = tryExec(xprop, ["-root", "_NET_ACTIVE_WINDOW"]).split("\n")[0] ?? "";
222
+ const id = line.split("#")[1]?.trim();
223
+ if (id) {
224
+ const name = tryExec(xprop, ["-id", id, "_NET_WM_NAME", "WM_NAME"]);
225
+ const match = /=\s*"?(.*?)"?\s*$/.exec(name.split("\n")[0] ?? "");
226
+ return (match?.[1] ?? "").trim();
227
+ }
228
+ }
229
+ return "";
230
+ }
231
+ }
232
+ }
233
+ catch {
234
+ return "";
235
+ }
236
+ }
237
+ export function getActiveWindowTitle() {
238
+ return get_active_window_title();
239
+ }
240
+ /**
241
+ * Get clipboard content (capped at 500 chars, as in Python).
242
+ *
243
+ * TODO(port): Python used `win32clipboard`, then `pbpaste` / `xclip`. Windows
244
+ * now shells out to PowerShell `Get-Clipboard`; any failure yields "".
245
+ */
246
+ export function get_clipboard() {
247
+ try {
248
+ switch (os.platform()) {
249
+ case "win32":
250
+ return tryExec("powershell", ["-NoProfile", "-c", "Get-Clipboard -Raw"]).slice(0, 500);
251
+ case "darwin":
252
+ return tryExec("pbpaste", []).slice(0, 500);
253
+ default: {
254
+ const xclip = whichSync("xclip");
255
+ if (xclip)
256
+ return tryExec(xclip, ["-selection", "clipboard", "-o"]).slice(0, 500);
257
+ const wlPaste = whichSync("wl-paste");
258
+ if (wlPaste)
259
+ return tryExec(wlPaste, ["-n"]).slice(0, 500);
260
+ return "";
261
+ }
262
+ }
263
+ }
264
+ catch {
265
+ return "";
266
+ }
267
+ }
268
+ export function getClipboard() {
269
+ return get_clipboard();
270
+ }
271
+ /* ────────────────────────────────────────────────────────────────────────────
272
+ * Screenshot + OCR
273
+ * ──────────────────────────────────────────────────────────────────────────── */
274
+ export const OCR_UNAVAILABLE_ERROR = "[OCR unavailable — the `tesseract` binary was not found on PATH. Install it " +
275
+ "(winget install UB-Mannheim.TesseractOCR, brew install tesseract, " +
276
+ "apt install tesseract-ocr) or set TESSERACT_BIN. pytesseract does exactly the " +
277
+ "same shell-out in Python.]";
278
+ export const SCREENSHOT_UNAVAILABLE_ERROR = "[ERROR] screenshot unavailable — the `screenshot-desktop` package is not installed.";
279
+ /** Locate the tesseract binary (PATH first, then the usual install spots). */
280
+ export function findTesseract() {
281
+ const fromEnv = process.env.TESSERACT_BIN;
282
+ if (fromEnv && fromEnv.trim())
283
+ return fromEnv.trim();
284
+ const onPath = whichSync("tesseract");
285
+ if (onPath)
286
+ return onPath;
287
+ const candidates = os.platform() === "win32"
288
+ ? [
289
+ "C:\\Program Files\\Tesseract-OCR\\tesseract.exe",
290
+ "C:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe",
291
+ path.join(os.homedir(), "AppData", "Local", "Programs", "Tesseract-OCR", "tesseract.exe"),
292
+ ]
293
+ : ["/usr/bin/tesseract", "/usr/local/bin/tesseract", "/opt/homebrew/bin/tesseract"];
294
+ for (const c of candidates) {
295
+ try {
296
+ if (fs.existsSync(c))
297
+ return c;
298
+ }
299
+ catch {
300
+ /* keep looking */
301
+ }
302
+ }
303
+ return null;
304
+ }
305
+ /** Capture the screen as PNG bytes, or null when capture is unavailable. */
306
+ export async function captureScreen(display) {
307
+ const shot = await getScreenshot();
308
+ if (!shot) {
309
+ logDebug(SCREENSHOT_UNAVAILABLE_ERROR);
310
+ return null;
311
+ }
312
+ try {
313
+ return await shot(display === undefined ? {} : { screen: display });
314
+ }
315
+ catch (e) {
316
+ logDebug(`[Awareness] screenshot failed: ${errText(e)}`);
317
+ return null;
318
+ }
319
+ }
320
+ /**
321
+ * OCR an image buffer through the `tesseract` binary.
322
+ *
323
+ * TODO(port): `pytesseract` (NOT available for Node) is itself a thin wrapper
324
+ * around this binary, so the port calls it directly via node:child_process.
325
+ * No `tesseract.js` dependency is needed or available.
326
+ */
327
+ export async function ocrImage(image) {
328
+ const bin = findTesseract();
329
+ if (!bin) {
330
+ logDebug(OCR_UNAVAILABLE_ERROR);
331
+ return OCR_UNAVAILABLE_ERROR;
332
+ }
333
+ const tmp = path.join(os.tmpdir(), `beru-ocr-${Date.now()}-${Math.floor(Math.random() * 1e6)}.png`);
334
+ try {
335
+ fs.writeFileSync(tmp, image);
336
+ const { stdout, code } = await runProcess(bin, [tmp, "stdout"], 30_000);
337
+ if (code !== 0 && !stdout)
338
+ return `[OCR error: tesseract exited with code ${code}]`;
339
+ return stdout.slice(0, 1000);
340
+ }
341
+ catch (e) {
342
+ return `[OCR error: ${errText(e)}]`;
343
+ }
344
+ finally {
345
+ try {
346
+ fs.unlinkSync(tmp);
347
+ }
348
+ catch {
349
+ /* best effort */
350
+ }
351
+ }
352
+ }
353
+ /** Crop + normalise a PNG buffer with `sharp` (falls back to passthrough). */
354
+ export async function cropAndPreprocess(image, region) {
355
+ const sharp = await getSharp();
356
+ if (!sharp) {
357
+ logDebug("[Awareness] sharp unavailable — using the uncropped screenshot");
358
+ return image;
359
+ }
360
+ try {
361
+ return await sharp(image)
362
+ .extract({
363
+ left: Math.max(0, Math.round(region.left)),
364
+ top: Math.max(0, Math.round(region.top)),
365
+ width: Math.max(1, Math.round(region.width)),
366
+ height: Math.max(1, Math.round(region.height)),
367
+ })
368
+ .grayscale()
369
+ .normalize()
370
+ .png()
371
+ .toBuffer();
372
+ }
373
+ catch (e) {
374
+ logDebug(`[Awareness] sharp crop failed: ${errText(e)}`);
375
+ return image;
376
+ }
377
+ }
378
+ /**
379
+ * Take a screenshot and OCR it. Returns the extracted text, or a bracketed
380
+ * status string matching the Python contract:
381
+ * "[OCR unavailable — …]" / "[Screenshot unavailable — …]" / "[Screenshot error: …]"
382
+ */
383
+ export async function take_screenshot_ocr(region) {
384
+ let image = await captureScreen();
385
+ if (!image) {
386
+ return (await getScreenshot()) ? "[Screenshot error: capture failed]" : SCREENSHOT_UNAVAILABLE_ERROR;
387
+ }
388
+ if (region)
389
+ image = await cropAndPreprocess(image, region);
390
+ return ocrImage(image);
391
+ }
392
+ export async function takeScreenshotOcr(region) {
393
+ return take_screenshot_ocr(region);
394
+ }
395
+ /**
396
+ * Find a piece of text on screen by OCR-ing horizontal tiles and matching the
397
+ * line containing it. This is the "screen watching / text finding" capability
398
+ * that the Python stack reached through `pyautogui` + `pytesseract`.
399
+ */
400
+ export async function findTextOnScreen(needle, tileHeight = 400, display) {
401
+ const image = await captureScreen(display);
402
+ if (!image) {
403
+ return {
404
+ found: false,
405
+ error: (await getScreenshot())
406
+ ? "[Screenshot error: capture failed]"
407
+ : SCREENSHOT_UNAVAILABLE_ERROR,
408
+ };
409
+ }
410
+ const sharp = await getSharp();
411
+ let height = 0;
412
+ if (sharp) {
413
+ try {
414
+ const meta = await sharp(image).metadata();
415
+ height = meta.height ?? 0;
416
+ }
417
+ catch {
418
+ height = 0;
419
+ }
420
+ }
421
+ const scan = async (tile, top, tileH) => {
422
+ const text = await ocrImage(tile);
423
+ if (text.startsWith("[OCR unavailable"))
424
+ return { found: false, error: text };
425
+ const line = text
426
+ .split("\n")
427
+ .find((l) => l.toLowerCase().includes(needle.toLowerCase()));
428
+ if (!line)
429
+ return null;
430
+ return {
431
+ found: true,
432
+ region: { left: 0, top, width: 0, height: tileH },
433
+ line: line.trim(),
434
+ };
435
+ };
436
+ if (height <= 0) {
437
+ const result = await scan(image, 0, 0);
438
+ return result ?? { found: false };
439
+ }
440
+ for (let top = 0; top < height; top += tileHeight) {
441
+ const tileH = Math.min(tileHeight, height - top);
442
+ const tile = await cropAndPreprocess(image, {
443
+ left: 0,
444
+ top,
445
+ width: 100_000,
446
+ height: tileH,
447
+ });
448
+ const result = await scan(tile, top, tileH);
449
+ if (result)
450
+ return result;
451
+ }
452
+ return { found: false };
453
+ }
454
+ export async function find_text_on_screen(needle, tileHeight = 400, display) {
455
+ return findTextOnScreen(needle, tileHeight, display);
456
+ }
457
+ /* ────────────────────────────────────────────────────────────────────────────
458
+ * Context snapshot
459
+ * ──────────────────────────────────────────────────────────────────────────── */
460
+ /** Point-in-time awareness snapshot. */
461
+ export class ContextSnapshot {
462
+ ts;
463
+ window_title;
464
+ clipboard;
465
+ metrics;
466
+ ocr_text;
467
+ suggestions;
468
+ constructor() {
469
+ this.ts = Date.now() / 1000;
470
+ this.window_title = "";
471
+ this.clipboard = "";
472
+ this.metrics = { cpu_percent: 0, ram_percent: 0, disk_percent: 0, platform: osName() };
473
+ this.ocr_text = "";
474
+ this.suggestions = [];
475
+ }
476
+ /** camelCase aliases for the Python attribute names. */
477
+ get windowTitle() {
478
+ return this.window_title;
479
+ }
480
+ get ocrText() {
481
+ return this.ocr_text;
482
+ }
483
+ to_dict() {
484
+ return {
485
+ ts: this.ts,
486
+ window: this.window_title,
487
+ clipboard: this.clipboard.slice(0, 100),
488
+ cpu: this.metrics["cpu_percent"] ?? 0,
489
+ ram: this.metrics["ram_percent"] ?? 0,
490
+ suggestions: this.suggestions,
491
+ };
492
+ }
493
+ toDict() {
494
+ return this.to_dict();
495
+ }
496
+ /** Format as an agent context block. */
497
+ context_block() {
498
+ const lines = [];
499
+ if (this.window_title)
500
+ lines.push(`Active window: ${this.window_title}`);
501
+ const cpu = Number(this.metrics["cpu_percent"] ?? 0);
502
+ const ram = Number(this.metrics["ram_percent"] ?? 0);
503
+ if (cpu > 80)
504
+ lines.push(`⚠ CPU ${cpu.toFixed(0)}% — system under load`);
505
+ if (ram > 85)
506
+ lines.push(`⚠ RAM ${ram.toFixed(0)}% — memory pressure`);
507
+ if (this.suggestions.length > 0) {
508
+ lines.push("Proactive suggestions:");
509
+ for (const s of this.suggestions)
510
+ lines.push(` • ${s}`);
511
+ }
512
+ return lines.length > 0 ? lines.join("\n") : "";
513
+ }
514
+ contextBlock() {
515
+ return this.context_block();
516
+ }
517
+ }
518
+ /**
519
+ * Rule-based proactive suggestion generator.
520
+ * Looks at context and fires suggestions to the user.
521
+ */
522
+ export class SuggestionEngine {
523
+ _rules;
524
+ constructor() {
525
+ this._rules = [
526
+ // (condition_fn, suggestion_str)
527
+ [
528
+ (s) => s.window_title.toLowerCase().includes("github.com") ||
529
+ s.window_title.toLowerCase().includes("git"),
530
+ "Looks like you're on GitHub — want me to summarize recent changes?",
531
+ ],
532
+ [
533
+ (s) => s.window_title.toLowerCase().includes("stackoverflow"),
534
+ "Stack Overflow detected — want me to search for a solution?",
535
+ ],
536
+ [
537
+ (s) => Number(s.metrics["cpu_percent"] ?? 0) > 85,
538
+ "CPU is pegged — want me to identify what's eating compute?",
539
+ ],
540
+ [
541
+ (s) => Number(s.metrics["ram_percent"] ?? 0) > 90,
542
+ "Memory critical — want me to find large processes?",
543
+ ],
544
+ [
545
+ (s) => ["error", "traceback", "exception"].some((kw) => s.clipboard.toLowerCase().includes(kw)),
546
+ "Saw an error in your clipboard — want me to diagnose it?",
547
+ ],
548
+ [
549
+ (s) => ["http://", "https://"].some((kw) => s.clipboard.toLowerCase().includes(kw)),
550
+ "URL detected in clipboard — want me to summarize that page?",
551
+ ],
552
+ [
553
+ (s) => ["python", ".py", "vscode", "pycharm", "typescript", ".ts"].some((kw) => s.window_title.toLowerCase().includes(kw)),
554
+ "Coding detected — want me to review what you're working on?",
555
+ ],
556
+ ];
557
+ }
558
+ evaluate(snapshot) {
559
+ const suggestions = [];
560
+ for (const [condition, suggestion] of this._rules) {
561
+ try {
562
+ if (condition(snapshot))
563
+ suggestions.push(suggestion);
564
+ }
565
+ catch {
566
+ /* a broken rule must never kill the loop */
567
+ }
568
+ }
569
+ return suggestions.slice(0, 3); // cap at 3
570
+ }
571
+ }
572
+ /**
573
+ * Background service that monitors context and delivers proactive suggestions.
574
+ *
575
+ * TODO(port): Python used `threading.Thread(daemon=True)` + `time.sleep`.
576
+ * This is a cancellable async loop; `stop()` aborts the sleep immediately.
577
+ */
578
+ export class AwarenessService {
579
+ interval_s;
580
+ enable_ocr;
581
+ _suggester = new SuggestionEngine();
582
+ _running = false;
583
+ _abort = null;
584
+ _thread = null;
585
+ _last = null;
586
+ _on_suggestion = null;
587
+ _last_window = "";
588
+ _last_clip = "";
589
+ constructor(interval_s = 60, enable_ocr = false) {
590
+ this.interval_s = interval_s;
591
+ this.enable_ocr = enable_ocr;
592
+ }
593
+ /** Called when BERU has a proactive suggestion. */
594
+ set_suggestion_callback(cb) {
595
+ this._on_suggestion = cb;
596
+ }
597
+ setSuggestionCallback(cb) {
598
+ this.set_suggestion_callback(cb);
599
+ }
600
+ /** Take a single context snapshot. */
601
+ async snapshot() {
602
+ const s = new ContextSnapshot();
603
+ s.window_title = get_active_window_title();
604
+ s.metrics = await getSystemMetricsAsync();
605
+ s.clipboard = get_clipboard();
606
+ if (this.enable_ocr) {
607
+ s.ocr_text = await take_screenshot_ocr();
608
+ }
609
+ s.suggestions = this._suggester.evaluate(s);
610
+ this._last = s;
611
+ return s;
612
+ }
613
+ /** Snapshot without the async metrics refresh (sync Python signature parity). */
614
+ snapshot_sync() {
615
+ const s = new ContextSnapshot();
616
+ s.window_title = get_active_window_title();
617
+ s.metrics = get_system_metrics();
618
+ s.clipboard = get_clipboard();
619
+ if (this.enable_ocr) {
620
+ s.ocr_text = "[OCR is async in the Node port — await snapshot() instead]";
621
+ }
622
+ s.suggestions = this._suggester.evaluate(s);
623
+ this._last = s;
624
+ return s;
625
+ }
626
+ /** For injecting into the agent system prompt. */
627
+ get_context_block() {
628
+ if (this._last === null) {
629
+ try {
630
+ return this.snapshot_sync().context_block();
631
+ }
632
+ catch {
633
+ return "";
634
+ }
635
+ }
636
+ return this._last.context_block();
637
+ }
638
+ getContextBlock() {
639
+ return this.get_context_block();
640
+ }
641
+ start() {
642
+ if (this._running)
643
+ return;
644
+ this._running = true;
645
+ this._abort = new AbortController();
646
+ const signal = this._abort.signal;
647
+ this._thread = this._loop(signal)
648
+ .catch((e) => {
649
+ logger.error(`[Awareness] loop crashed: ${errText(e)}`);
650
+ })
651
+ .finally(() => {
652
+ this._thread = null;
653
+ });
654
+ logInfo(`[Awareness] Service started (interval=${this.interval_s}s)`);
655
+ }
656
+ stop() {
657
+ this._running = false;
658
+ this._abort?.abort();
659
+ this._abort = null;
660
+ }
661
+ is_running() {
662
+ return this._running;
663
+ }
664
+ isRunning() {
665
+ return this.is_running();
666
+ }
667
+ async _loop(signal) {
668
+ while (this._running && !signal.aborted) {
669
+ try {
670
+ const s = await this.snapshot();
671
+ this._check_changes(s);
672
+ }
673
+ catch (e) {
674
+ logger.debug(`Awareness tick error: ${errText(e)}`);
675
+ }
676
+ await interruptibleSleep(this.interval_s * 1000, signal);
677
+ }
678
+ }
679
+ _check_changes(s) {
680
+ // Notify on new suggestions only when context has meaningfully changed.
681
+ if (s.window_title !== this._last_window ||
682
+ s.clipboard.slice(0, 50) !== this._last_clip.slice(0, 50)) {
683
+ this._last_window = s.window_title;
684
+ this._last_clip = s.clipboard;
685
+ if (s.suggestions.length > 0 && this._on_suggestion) {
686
+ for (const suggestion of s.suggestions.slice(0, 1)) {
687
+ // one at a time
688
+ try {
689
+ this._on_suggestion(suggestion);
690
+ }
691
+ catch {
692
+ /* callback errors must never break the loop */
693
+ }
694
+ }
695
+ }
696
+ }
697
+ }
698
+ status() {
699
+ if (!this._last)
700
+ return { running: this._running, last_snapshot: null };
701
+ return {
702
+ running: this._running,
703
+ last_snapshot: this._last.to_dict(),
704
+ };
705
+ }
706
+ }
707
+ /* ────────────────────────────────────────────────────────────────────────────
708
+ * Singleton
709
+ * ──────────────────────────────────────────────────────────────────────────── */
710
+ let _service = null;
711
+ export function get_awareness_service(interval_s = 60) {
712
+ if (_service === null) {
713
+ try {
714
+ const cfg = loadConfig();
715
+ const acfg = (cfg["awareness"] ?? {});
716
+ _service = new AwarenessService(Number(acfg["interval_s"] ?? interval_s), Boolean(acfg["enable_ocr"] ?? false));
717
+ }
718
+ catch {
719
+ _service = new AwarenessService(interval_s);
720
+ }
721
+ }
722
+ return _service;
723
+ }
724
+ /** camelCase alias of `get_awareness_service`. */
725
+ export const getAwarenessService = get_awareness_service;
726
+ /** Test/DI hook — replace the singleton. */
727
+ export function setAwarenessService(service) {
728
+ _service = service;
729
+ }
730
+ /* ────────────────────────────────────────────────────────────────────────────
731
+ * helpers
732
+ * ──────────────────────────────────────────────────────────────────────────── */
733
+ function runProcess(cmd, args, timeoutMs) {
734
+ return new Promise((resolve) => {
735
+ let child;
736
+ try {
737
+ child = spawn(cmd, args, { windowsHide: true });
738
+ }
739
+ catch (e) {
740
+ resolve({ code: -1, stdout: "", stderr: String(e) });
741
+ return;
742
+ }
743
+ let stdout = "";
744
+ let stderr = "";
745
+ let done = false;
746
+ const finish = (code) => {
747
+ if (done)
748
+ return;
749
+ done = true;
750
+ clearTimeout(timer);
751
+ resolve({ code, stdout, stderr });
752
+ };
753
+ const timer = setTimeout(() => {
754
+ try {
755
+ child.kill();
756
+ }
757
+ catch {
758
+ /* best effort */
759
+ }
760
+ finish(-1);
761
+ }, timeoutMs);
762
+ child.stdout?.on("data", (d) => {
763
+ stdout += d.toString("utf8");
764
+ });
765
+ child.stderr?.on("data", (d) => {
766
+ stderr += d.toString("utf8");
767
+ });
768
+ child.on("error", (e) => {
769
+ stderr += String(e);
770
+ finish(-1);
771
+ });
772
+ child.on("close", (code) => finish(code ?? -1));
773
+ });
774
+ }
775
+ function interruptibleSleep(ms, signal) {
776
+ if (signal.aborted)
777
+ return Promise.resolve();
778
+ return new Promise((resolve) => {
779
+ const timer = setTimeout(resolve, Math.max(0, ms));
780
+ signal.addEventListener("abort", () => {
781
+ clearTimeout(timer);
782
+ resolve();
783
+ }, { once: true });
784
+ });
785
+ }
786
+ function errText(e) {
787
+ return e instanceof Error ? e.message : String(e);
788
+ }
789
+ //# sourceMappingURL=service.js.map