@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,695 @@
1
+ // compare/stream.js — SSE streaming to panes
2
+ import state from './state.js';
3
+ import { addFinishBadge } from './vote.js';
4
+ import { getModelCost } from '../chatRenderer.js';
5
+ import markdownModule from '../markdown.js';
6
+ import spinnerModule from '../spinner.js';
7
+ import uiModule from '../ui.js';
8
+ import presetsModule from '../presets.js';
9
+
10
+ var escapeHtml = uiModule.esc;
11
+
12
+ const WAVE_FRAMES = ['▁▂▃', '▂▃▄', '▃▄▅', '▄▅▆', '▅▆▇', '▆▅▄', '▅▄▃', '▄▃▂'];
13
+
14
+ // ── Lazy-registered functions from compare.js (avoids circular deps) ──
15
+ let _rerollPane = null;
16
+ let _autoPreviewHtml = null;
17
+
18
+ /** Register external functions that live in compare.js. */
19
+ function registerStreamActions({ rerollPane, autoPreviewHtml }) {
20
+ _rerollPane = rerollPane;
21
+ _autoPreviewHtml = autoPreviewHtml;
22
+ }
23
+
24
+ /** Format milliseconds as human-readable duration (e.g. "120ms", "1.23s", "4.5s"). */
25
+ function _formatMs(ms) {
26
+ if (ms < 1000) return Math.round(ms) + 'ms';
27
+ if (ms < 10000) return (ms / 1000).toFixed(2) + 's';
28
+ return (ms / 1000).toFixed(1) + 's';
29
+ }
30
+
31
+ /** Build a DOM container of search-result cards from a search response. Returns an HTMLElement. */
32
+ function _renderSearchResults(data) {
33
+ const container = document.createElement('div');
34
+ container.className = 'compare-search-results';
35
+ (data.results || []).forEach(r => {
36
+ const card = document.createElement('div');
37
+ card.className = 'compare-search-result';
38
+ const titleLink = document.createElement('a');
39
+ titleLink.href = r.url || '#';
40
+ titleLink.target = '_blank';
41
+ titleLink.rel = 'noopener';
42
+ titleLink.className = 'search-result-title';
43
+ titleLink.textContent = r.title || 'Untitled';
44
+ card.appendChild(titleLink);
45
+ if (r.snippet) {
46
+ const s = document.createElement('div');
47
+ s.className = 'search-result-snippet';
48
+ s.textContent = r.snippet;
49
+ card.appendChild(s);
50
+ }
51
+ if (r.url) {
52
+ const u = document.createElement('div');
53
+ u.className = 'search-result-url';
54
+ u.textContent = r.url;
55
+ card.appendChild(u);
56
+ }
57
+ container.appendChild(card);
58
+ });
59
+ return container;
60
+ }
61
+
62
+ /** Run synthesis for a search pane — sends search results to an LLM for analysis. */
63
+ async function _runSynthForPane(modelToUse, synthPrompt, synthBody, spinner, hist) {
64
+ // Create temp session for synthesis
65
+ const fd = new FormData();
66
+ fd.append('name', 'Synthesis');
67
+ fd.append('endpoint_url', modelToUse.endpoint || '');
68
+ fd.append('model', modelToUse.model || '');
69
+ if (modelToUse.endpointId) {
70
+ fd.append('endpoint_id', modelToUse.endpointId);
71
+ fd.append('skip_validation', 'true');
72
+ }
73
+
74
+ try {
75
+ const createRes = await fetch(`${state.API_BASE}/api/session`, { method: 'POST', body: fd });
76
+ if (!createRes.ok) {
77
+ const errData = await createRes.json().catch(() => ({}));
78
+ throw new Error(errData.detail || 'Failed to create session');
79
+ }
80
+ const createData = await createRes.json();
81
+
82
+ const synthAc = new AbortController();
83
+ state._abortControllers.push(synthAc);
84
+ const streamRes = await fetch(`${state.API_BASE}/api/chat_stream`, {
85
+ method: 'POST',
86
+ headers: { 'Content-Type': 'application/json' },
87
+ body: JSON.stringify({ session: createData.id, message: synthPrompt }),
88
+ signal: synthAc.signal,
89
+ });
90
+
91
+ if (spinner) spinner.stop();
92
+ synthBody.innerHTML = '';
93
+ const reader = streamRes.body.getReader();
94
+ const decoder = new TextDecoder();
95
+ let synthText = '';
96
+
97
+ while (true) {
98
+ const { done, value } = await reader.read();
99
+ if (done) break;
100
+ const chunk = decoder.decode(value);
101
+ const lines = chunk.split('\n');
102
+ for (const line of lines) {
103
+ if (line.startsWith('data: ') && line !== 'data: [DONE]') {
104
+ try {
105
+ const d = JSON.parse(line.slice(6));
106
+ if (d.delta) {
107
+ synthText += d.delta;
108
+ if (markdownModule && synthText.trim()) {
109
+ synthBody.innerHTML = markdownModule.processWithThinking(
110
+ markdownModule.squashOutsideCode(synthText)
111
+ );
112
+ } else {
113
+ synthBody.textContent = synthText;
114
+ }
115
+ hist.scrollTop = hist.scrollHeight;
116
+ }
117
+ } catch (e) {}
118
+ }
119
+ }
120
+ }
121
+
122
+ // Final highlight
123
+ if (window.hljs) synthBody.querySelectorAll('pre code:not(.hljs)').forEach(b => window.hljs.highlightElement(b));
124
+
125
+ // Cleanup temp session
126
+ fetch(`${state.API_BASE}/api/session/${createData.id}`, { method: 'DELETE' }).catch(() => {});
127
+ } catch (e) {
128
+ if (spinner) spinner.stop();
129
+ synthBody.innerHTML = '<div style="color:var(--color-error);font-size:0.85em;">Synthesis failed: ' + escapeHtml(e.message) + '</div>';
130
+ }
131
+ }
132
+
133
+ /** Stream an SSE response into a compare pane. Handles text, tool blocks, images, metrics. */
134
+ async function streamToPane(paneIdx, sessionId, message, aiMsgEl, opts) {
135
+ opts = opts || {};
136
+ const aiBody = aiMsgEl ? aiMsgEl.querySelector('.body') : null;
137
+ const hist = aiMsgEl ? aiMsgEl.parentElement : null;
138
+ if (!aiBody) return;
139
+
140
+ const ac = new AbortController();
141
+ state._abortControllers[paneIdx] = ac;
142
+
143
+ // Show stop button for this pane
144
+ const _paneEl = document.querySelector(`.compare-pane[data-pane="${paneIdx}"]`);
145
+ if (_paneEl) {
146
+ const _stopBtn = _paneEl.querySelector('.pane-stop-btn');
147
+ if (_stopBtn) _stopBtn.style.display = '';
148
+ }
149
+
150
+ let accumulated = '';
151
+ let metrics = null;
152
+ let timedOut = false;
153
+ let streamOk = false;
154
+ let currentToolBlock = null; // track active agent tool block
155
+ // Idle timeout — abort only if no data is received for this many seconds.
156
+ // Long generations (SVG, big code) are fine as long as the stream stays
157
+ // active. opts.timeout may still tighten this for specific paths.
158
+ const effectiveTimeout = opts.timeout || state._timeout;
159
+ let timeoutId = setTimeout(() => { timedOut = true; ac.abort(); }, effectiveTimeout * 1000);
160
+ const _resetIdleTimeout = () => {
161
+ clearTimeout(timeoutId);
162
+ timeoutId = setTimeout(() => { timedOut = true; ac.abort(); }, effectiveTimeout * 1000);
163
+ };
164
+
165
+ // Live timer
166
+ const _timerStart = performance.now();
167
+ let _ttft = 0; // time to first token
168
+ let _timerDone = false;
169
+ const _timerEl = document.getElementById('cmp-timer-' + paneIdx);
170
+ let _rafId = 0;
171
+ function _tickTimer() {
172
+ if (_timerDone) return;
173
+ const elapsed = performance.now() - _timerStart;
174
+ if (_timerEl) _timerEl.textContent = _formatMs(elapsed);
175
+ _rafId = requestAnimationFrame(_tickTimer);
176
+ }
177
+ _rafId = requestAnimationFrame(_tickTimer);
178
+
179
+ // Throttled markdown render — re-rendering the entire growing buffer on
180
+ // every token is O(n²) total work. Coalesce updates so we paint at most
181
+ // every ~80ms. The final render still runs at end-of-stream for quality.
182
+ let _renderPending = false;
183
+ let _renderLastAt = 0;
184
+ const _RENDER_THROTTLE_MS = 80;
185
+ function _scheduleLiveRender(target) {
186
+ if (_renderPending) return;
187
+ const now = performance.now();
188
+ const elapsed = now - _renderLastAt;
189
+ const delay = elapsed >= _RENDER_THROTTLE_MS ? 0 : _RENDER_THROTTLE_MS - elapsed;
190
+ _renderPending = true;
191
+ setTimeout(() => {
192
+ _renderPending = false;
193
+ _renderLastAt = performance.now();
194
+ if (markdownModule && accumulated.trim()) {
195
+ target.innerHTML = markdownModule.processWithThinking(
196
+ markdownModule.squashOutsideCode(accumulated)
197
+ );
198
+ } else {
199
+ target.textContent = accumulated;
200
+ }
201
+ if (hist) hist.scrollTop = hist.scrollHeight;
202
+ }, delay);
203
+ }
204
+
205
+ try {
206
+ const fd = new FormData();
207
+ fd.append('message', message);
208
+ fd.append('session', sessionId);
209
+
210
+ // Compare mode determines what tools/features are enabled
211
+ const isAgent = state._compareMode === 'agent';
212
+ const isResearch = state._compareMode === 'research';
213
+
214
+ // Agent mode: enable all tools (web, bash, etc.)
215
+ if (isAgent) {
216
+ fd.append('mode', 'agent');
217
+ fd.append('allow_web_search', 'true');
218
+ fd.append('allow_bash', 'true');
219
+ } else if (isResearch) {
220
+ fd.append('use_research', 'true');
221
+ } else {
222
+ // Chat/Image: pure chat only — no tools, no search, no bash, no RAG.
223
+ // Explicitly send mode='chat' so the backend's compare_mode strip
224
+ // (chat_routes.py line 385) actually triggers — otherwise the form
225
+ // field was missing and chat_mode defaulted to "", which meant
226
+ // bash/python/web_search were never added to disabled_tools and
227
+ // models would still attempt to run Python.
228
+ fd.append('mode', 'chat');
229
+ fd.append('use_rag', 'false');
230
+ }
231
+ const incognitoChk = document.getElementById('incognito-toggle');
232
+ if (incognitoChk && incognitoChk.checked) {
233
+ fd.append('incognito', 'true');
234
+ }
235
+ // Disable document tool and memory injection in compare mode
236
+ fd.append('no_documents', 'true');
237
+ fd.append('no_memory', 'true');
238
+ // Tell backend this is compare mode — strip all non-toggled tools
239
+ fd.append('compare_mode', 'true');
240
+ // Forward preset if selected
241
+ if (presetsModule && presetsModule.getSelectedPreset()) {
242
+ fd.append('preset_id', presetsModule.getSelectedPreset());
243
+ }
244
+
245
+ const response = await fetch(`${state.API_BASE}/api/chat_stream`, {
246
+ method: 'POST', body: fd, signal: ac.signal
247
+ });
248
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
249
+
250
+ const reader = response.body.getReader();
251
+ const decoder = new TextDecoder();
252
+ let buffer = '';
253
+
254
+ while (true) {
255
+ const { done, value } = await reader.read();
256
+ if (done) break;
257
+ _resetIdleTimeout(); // any chunk = stream is alive
258
+
259
+ buffer += decoder.decode(value, { stream: true });
260
+ const lines = buffer.split('\n');
261
+ buffer = lines.pop() || '';
262
+
263
+ for (const line of lines) {
264
+ if (!line.startsWith('data: ')) continue;
265
+ const data = line.slice(6);
266
+ if (data === '[DONE]') break;
267
+ try {
268
+ const json = JSON.parse(data);
269
+ if (json.type === 'metrics') {
270
+ metrics = json.data;
271
+
272
+ // ── Research progress (spinner updates) ──
273
+ } else if (json.type === 'research_progress') {
274
+ const rp = json.data;
275
+ const spinner = aiMsgEl._spinner;
276
+ if (spinner) {
277
+ if (rp.phase === 'searching') {
278
+ const q = rp.queries ? `${rp.queries} queries` : '';
279
+ const s = rp.total_sources ? ` · ${rp.total_sources} sources` : '';
280
+ spinner.updateMessage(`R${rp.round || '?'}: Searching${q ? ' (' + q + ')' : ''}${s}`);
281
+ } else if (rp.phase === 'reading') {
282
+ spinner.updateMessage(`R${rp.round || '?'}: Reading ${rp.new_sources || ''} pages`);
283
+ } else if (rp.phase === 'analyzing') {
284
+ spinner.updateMessage(`R${rp.round || '?'}: Analyzing ${rp.total_findings || 0} findings`);
285
+ } else if (rp.phase === 'writing') {
286
+ spinner.updateMessage(`Writing report · ${rp.total_sources || 0} sources`);
287
+ } else if (rp.phase === 'error') {
288
+ spinner.updateMessage(rp.message || 'Research error');
289
+ }
290
+ }
291
+
292
+ // ── Research sources / Web sources (compact sources box) ──
293
+ } else if (json.type === 'research_sources' || json.type === 'web_sources') {
294
+ const sources = json.data || [];
295
+ if (sources.length > 0) {
296
+ const label = json.type === 'research_sources' ? 'Research' : 'Web';
297
+ const box = document.createElement('div');
298
+ box.className = 'compare-sources-box';
299
+ box.innerHTML = '<span class="sources-label">' + sources.length + ' ' + label + ' sources</span>';
300
+ box.title = sources.map(s => s.title || s.url).join('\n');
301
+ // Replace spinner with sources + new spinner
302
+ aiBody.innerHTML = '';
303
+ aiBody.appendChild(box);
304
+ if (spinnerModule) {
305
+ const newSpinner = spinnerModule.create('Generating response...', 'right');
306
+ aiBody.appendChild(newSpinner.createElement());
307
+ newSpinner.start();
308
+ aiMsgEl._spinner = newSpinner;
309
+ }
310
+ }
311
+
312
+ // ── Tool start (bash, web search agent tool) ──
313
+ } else if (json.type === 'tool_start') {
314
+ // Finalize any accumulated text before the tool block
315
+ if (accumulated.trim() && aiMsgEl._textEl) {
316
+ if (markdownModule) {
317
+ aiMsgEl._textEl.innerHTML = markdownModule.processWithThinking(
318
+ markdownModule.squashOutsideCode(accumulated));
319
+ if (window.hljs) aiMsgEl._textEl.querySelectorAll('pre code:not(.hljs)').forEach(b => window.hljs.highlightElement(b));
320
+ }
321
+ }
322
+ // Destroy spinner if still present
323
+ if (aiMsgEl._spinner && aiMsgEl._spinner.element) {
324
+ aiMsgEl._spinner.destroy();
325
+ aiMsgEl._spinner = null;
326
+ // Clean up spinner element but keep sources box + text
327
+ const spinnerEl = aiBody.querySelector('.spinner-wrapper, .mini-spinner');
328
+ if (spinnerEl) spinnerEl.remove();
329
+ }
330
+ const toolName = json.tool || 'tool';
331
+ const cmd = json.command || '';
332
+ // Image generation: show ASCII spinner instead of compact tool block
333
+ if (toolName === 'generate_image' && spinnerModule) {
334
+ aiBody.innerHTML = '';
335
+ const imgSpinner = spinnerModule.create('Generating image...', 'right');
336
+ aiBody.appendChild(imgSpinner.createElement());
337
+ imgSpinner.start();
338
+ aiMsgEl._imgSpinner = imgSpinner;
339
+ currentToolBlock = null;
340
+ } else {
341
+ // Agent thread node — matches main chat style
342
+ const _toolLabels = { bash: 'Terminal', python: 'Python', web_search: 'Web Search', read_file: 'Read File', write_file: 'Write File' };
343
+ const toolLabel = _toolLabels[toolName.toLowerCase()] || toolName;
344
+ const cmdHtml = cmd ? `<pre class="agent-thread-cmd">${escapeHtml(cmd)}</pre>` : '';
345
+ const node = document.createElement('div');
346
+ node.className = 'agent-thread-node running';
347
+ node.innerHTML = `<div class="agent-thread-dot"></div><div class="agent-thread-header"><span class="agent-thread-icon">\u25B6</span><span class="agent-thread-tool">${toolLabel}</span><span class="agent-thread-wave">▁▂▃</span></div><div class="agent-thread-content">${cmdHtml}</div>`;
348
+ node.querySelector('.agent-thread-header').addEventListener('click', () => node.classList.toggle('open'));
349
+ // Animate wave
350
+ const waveEl = node.querySelector('.agent-thread-wave');
351
+ if (waveEl) {
352
+ const waveFrames = WAVE_FRAMES;
353
+ let waveIdx = 0;
354
+ node._waveInterval = setInterval(() => { waveIdx = (waveIdx + 1) % waveFrames.length; waveEl.textContent = waveFrames[waveIdx]; }, 100);
355
+ }
356
+ aiBody.appendChild(node);
357
+ currentToolBlock = node;
358
+ }
359
+ if (hist) hist.scrollTop = hist.scrollHeight;
360
+
361
+ // ── Tool output (image or non-image) ──
362
+ } else if (json.type === 'tool_output') {
363
+ if (json.image_url) {
364
+ // Stop image spinner and render generated image in pane
365
+ if (aiMsgEl._imgSpinner) { aiMsgEl._imgSpinner.destroy(); aiMsgEl._imgSpinner = null; }
366
+ aiBody.innerHTML = '';
367
+ const img = document.createElement('img');
368
+ img.className = 'compare-gen-image';
369
+ img.src = json.image_url;
370
+ img.alt = json.image_prompt || '';
371
+ img.title = json.image_prompt || '';
372
+ img.addEventListener('click', () => window.open(img.src, '_blank'));
373
+ aiBody.appendChild(img);
374
+ if (json.image_prompt) {
375
+ const caption = document.createElement('div');
376
+ caption.style.cssText = 'font-size:0.82em;color:color-mix(in srgb, var(--fg) 55%, transparent);margin-top:6px;line-height:1.4;';
377
+ caption.textContent = json.image_prompt;
378
+ aiBody.appendChild(caption);
379
+ }
380
+ // Show model name below image (hidden in blind mode until vote)
381
+ if (json.image_model && !state._blindMode) {
382
+ const modelLabel = document.createElement('div');
383
+ modelLabel.style.cssText = 'font-size:0.75em;color:color-mix(in srgb, var(--fg) 40%, transparent);margin-top:4px;';
384
+ modelLabel.textContent = json.image_model;
385
+ aiBody.appendChild(modelLabel);
386
+ }
387
+ aiMsgEl._imageData = { url: json.image_url, prompt: json.image_prompt, model: json.image_model, size: json.image_size, quality: json.image_quality };
388
+ } else if (currentToolBlock) {
389
+ // Stop wave animation
390
+ if (currentToolBlock._waveInterval) { clearInterval(currentToolBlock._waveInterval); currentToolBlock._waveInterval = null; }
391
+ const ok = (json.exit_code === 0 || json.exit_code == null);
392
+ const cmd = json.command || '';
393
+ const _toolLabels2 = { bash: 'Terminal', python: 'Python', web_search: 'Web Search', read_file: 'Read File', write_file: 'Write File' };
394
+ const tLabel = _toolLabels2[(json.tool || '').toLowerCase()] || json.tool || '';
395
+ let outHtml = '';
396
+ if (json.output && json.output.trim()) {
397
+ outHtml = `<details class="agent-tool-output"><summary>Output</summary><pre>${escapeHtml(json.output)}</pre></details>`;
398
+ }
399
+ const cmdHtml = cmd ? `<pre class="agent-thread-cmd">${escapeHtml(cmd)}</pre>` : '';
400
+ currentToolBlock.className = 'agent-thread-node' + (ok ? '' : ' error');
401
+ currentToolBlock.innerHTML = `<div class="agent-thread-dot"></div><div class="agent-thread-header"><span class="agent-thread-icon">${ok ? '\u2713' : '\u2717'}</span><span class="agent-thread-tool">${escapeHtml(tLabel)}</span><span class="agent-thread-status">${ok ? 'done' : 'failed'}</span><span class="agent-thread-chevron">\u25B6</span></div><div class="agent-thread-content">${cmdHtml}${outHtml}</div>`;
402
+ currentToolBlock.querySelector('.agent-thread-header').addEventListener('click', () => currentToolBlock.classList.toggle('open'));
403
+ currentToolBlock = null;
404
+ // Reset text element so next deltas create a fresh container
405
+ aiMsgEl._textEl = null;
406
+ accumulated = '';
407
+ }
408
+ if (hist) hist.scrollTop = hist.scrollHeight;
409
+ } else if (json.delta) {
410
+ // Skip text deltas if we already rendered an image
411
+ if (aiMsgEl._imageData) continue;
412
+ // Capture TTFT on very first text delta
413
+ if (!accumulated && !_ttft) _ttft = performance.now() - _timerStart;
414
+ // On first delta, destroy spinner and prepare text area
415
+ if (!accumulated && aiMsgEl._spinner) {
416
+ if (aiMsgEl._spinner.element) aiMsgEl._spinner.destroy();
417
+ aiMsgEl._spinner = null;
418
+ // Keep sources box if present, clear everything else
419
+ const srcBox = aiBody.querySelector('.compare-sources-box');
420
+ aiBody.innerHTML = '';
421
+ if (srcBox) aiBody.appendChild(srcBox);
422
+ // Add text container
423
+ const textEl = document.createElement('div');
424
+ textEl.className = 'compare-text-content';
425
+ aiBody.appendChild(textEl);
426
+ aiMsgEl._textEl = textEl;
427
+ }
428
+ // After a tool block, create a new text container for continuing text
429
+ if (!accumulated && !aiMsgEl._textEl) {
430
+ const textEl = document.createElement('div');
431
+ textEl.className = 'compare-text-content';
432
+ aiBody.appendChild(textEl);
433
+ aiMsgEl._textEl = textEl;
434
+ }
435
+ accumulated += json.delta;
436
+ const target = aiMsgEl._textEl || aiBody;
437
+ _scheduleLiveRender(target);
438
+ }
439
+ } catch (e) { console.warn('Compare stream render error:', e); }
440
+ }
441
+ }
442
+
443
+ streamOk = true;
444
+ // Destroy any remaining spinner
445
+ if (aiMsgEl._spinner && aiMsgEl._spinner.element) aiMsgEl._spinner.destroy();
446
+ aiMsgEl._spinner = null;
447
+ // Final render
448
+ const finalTarget = aiMsgEl._textEl || aiBody;
449
+ if (markdownModule && accumulated.trim()) {
450
+ finalTarget.innerHTML = markdownModule.processWithThinking(
451
+ markdownModule.squashOutsideCode(accumulated)
452
+ );
453
+ }
454
+ if (window.hljs) {
455
+ finalTarget.querySelectorAll('pre code:not(.hljs)').forEach(b => window.hljs.highlightElement(b));
456
+ }
457
+
458
+ // ── Show play button if response contains HTML ──
459
+ if (_autoPreviewHtml) _autoPreviewHtml(paneIdx, accumulated);
460
+
461
+ // Metrics footer
462
+ if (aiMsgEl && aiMsgEl._imageData) {
463
+ // Image-specific footer with actions + metrics
464
+ const imgD = aiMsgEl._imageData;
465
+ const footer = document.createElement('div');
466
+ footer.className = 'msg-footer';
467
+
468
+ // Action buttons (copy prompt + download)
469
+ const actions = document.createElement('span');
470
+ actions.className = 'msg-actions';
471
+
472
+ const copyBtn = document.createElement('button');
473
+ copyBtn.className = 'footer-copy-btn';
474
+ copyBtn.type = 'button';
475
+ copyBtn.title = 'Copy prompt';
476
+ copyBtn.textContent = '\u2398';
477
+ copyBtn.addEventListener('click', (e) => {
478
+ e.stopPropagation();
479
+ const txt = imgD.prompt || '';
480
+ if (navigator.clipboard) navigator.clipboard.writeText(txt).catch(() => {});
481
+ else { const ta = document.createElement('textarea'); ta.value = txt; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); }
482
+ copyBtn.textContent = '\u2713';
483
+ setTimeout(() => { copyBtn.textContent = '\u2398'; }, 1500);
484
+ if (uiModule) uiModule.showToast('Prompt copied!');
485
+ });
486
+ actions.appendChild(copyBtn);
487
+
488
+ const dlBtn = document.createElement('button');
489
+ dlBtn.className = 'footer-copy-btn';
490
+ dlBtn.type = 'button';
491
+ dlBtn.title = 'Download image';
492
+ dlBtn.textContent = '\u2913';
493
+ dlBtn.addEventListener('click', async (e) => {
494
+ e.stopPropagation();
495
+ try {
496
+ const resp = await fetch(imgD.url);
497
+ const blob = await resp.blob();
498
+ const a = document.createElement('a');
499
+ a.href = URL.createObjectURL(blob);
500
+ a.download = (imgD.prompt || 'image').slice(0, 40).replace(/[^a-zA-Z0-9 ]/g, '') + '.png';
501
+ document.body.appendChild(a);
502
+ a.click();
503
+ a.remove();
504
+ URL.revokeObjectURL(a.href);
505
+ dlBtn.textContent = '\u2713';
506
+ setTimeout(() => { dlBtn.textContent = '\u2913'; }, 1500);
507
+ } catch { dlBtn.textContent = '\u2717'; setTimeout(() => { dlBtn.textContent = '\u2913'; }, 1500); }
508
+ });
509
+ actions.appendChild(dlBtn);
510
+
511
+ footer.appendChild(actions);
512
+
513
+ // Metrics — hide in blind mode to avoid revealing model identity
514
+ if (!state._blindMode) {
515
+ const span = document.createElement('span');
516
+ span.className = 'response-metrics';
517
+ const parts = [];
518
+ if (imgD.model) parts.push(imgD.model.split('/').pop());
519
+ if (imgD.size) parts.push(imgD.size);
520
+ if (imgD.quality) parts.push(imgD.quality);
521
+ if (metrics && metrics.response_time) parts.push(metrics.response_time + 's');
522
+ const costFn = window.chatModule && window.chatModule.getImageCost;
523
+ if (costFn) {
524
+ const cost = costFn(imgD.model, imgD.quality, imgD.size);
525
+ if (cost !== null) parts.push('$' + (cost < 0.01 ? cost.toFixed(4) : cost.toFixed(3)));
526
+ }
527
+ span.textContent = parts.join(' \u00b7 ');
528
+ footer.appendChild(span);
529
+ }
530
+ aiMsgEl.appendChild(footer);
531
+ } else if (metrics && aiMsgEl) {
532
+ const footer = document.createElement('div');
533
+ footer.className = 'msg-footer';
534
+ const span = document.createElement('span');
535
+ span.className = 'response-metrics';
536
+ let text = metrics.output_tokens + ' tokens | ' + metrics.tokens_per_second + ' tok/s';
537
+ // Add per-request cost and cost per 1000
538
+ const _model = metrics.model || (state._selectedModels[paneIdx] && state._selectedModels[paneIdx].model) || '';
539
+ const _cost = getModelCost(_model, metrics.input_tokens || 0, metrics.output_tokens || 0);
540
+ // Build the metrics span with optional cost and context
541
+ span.textContent = text;
542
+ if (_cost !== null) {
543
+ const _cost1k = _cost * 1000;
544
+ const costSpan = document.createElement('span');
545
+ costSpan.style.color = 'var(--color-success, #4caf50)';
546
+ costSpan.title = 'Estimated cost per 1,000 responses like this one';
547
+ costSpan.textContent = ' | $' + (_cost1k < 1 ? _cost1k.toFixed(2) : _cost1k.toFixed(0)) + '/1k';
548
+ span.appendChild(costSpan);
549
+ }
550
+ if (metrics.context_percent > 0) {
551
+ const ctx = document.createElement('span');
552
+ ctx.textContent = ' | ' + metrics.context_percent + '% ctx';
553
+ if (metrics.context_percent >= 85) ctx.style.color = 'var(--color-error)';
554
+ else if (metrics.context_percent >= 70) ctx.style.color = '#ff9900';
555
+ span.appendChild(ctx);
556
+ }
557
+ footer.appendChild(span);
558
+ aiMsgEl.appendChild(footer);
559
+ }
560
+ if (hist) hist.scrollTop = hist.scrollHeight;
561
+
562
+ } catch (error) {
563
+ if (error.name === 'AbortError') {
564
+ if (timedOut) {
565
+ if (accumulated.trim()) {
566
+ if (markdownModule) {
567
+ aiBody.innerHTML = markdownModule.processWithThinking(
568
+ markdownModule.squashOutsideCode(accumulated));
569
+ }
570
+ }
571
+ const notice = document.createElement('div');
572
+ notice.style.cssText = 'color:#ff9800;font-size:0.8em;margin-top:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;';
573
+ const text = document.createElement('span');
574
+ text.style.fontStyle = 'italic';
575
+ text.textContent = 'Timed out after ' + effectiveTimeout + 's' + (accumulated.trim() ? ' \u2014 response may be incomplete' : '');
576
+ notice.appendChild(text);
577
+ const retryBtn = document.createElement('button');
578
+ retryBtn.textContent = 'Retry +' + effectiveTimeout + 's';
579
+ retryBtn.style.cssText = 'background:rgba(255,152,0,0.15);border:1px solid #ff9800;color:#ff9800;border-radius:4px;cursor:pointer;padding:2px 8px;font-size:0.9em;white-space:nowrap;transition:all 0.15s;';
580
+ retryBtn.addEventListener('mouseenter', () => { retryBtn.style.background = 'rgba(255,152,0,0.3)'; });
581
+ retryBtn.addEventListener('mouseleave', () => { retryBtn.style.background = 'rgba(255,152,0,0.15)'; });
582
+ retryBtn.addEventListener('click', () => { if (_rerollPane) _rerollPane(paneIdx, effectiveTimeout * 2); });
583
+ notice.appendChild(retryBtn);
584
+ aiBody.appendChild(notice);
585
+ } else {
586
+ if (!accumulated.trim()) aiBody.innerHTML = '<div style="color:#f0ad4e;font-size:0.9em;">Cancelled.</div>';
587
+ }
588
+ } else {
589
+ console.error('Compare stream error:', error);
590
+ aiBody.innerHTML = '<span style="color:var(--color-error);">Error: ' + escapeHtml(error.message) + '</span>';
591
+ }
592
+ } finally {
593
+ clearTimeout(timeoutId);
594
+ _timerDone = true;
595
+ cancelAnimationFrame(_rafId);
596
+ // Show final time with TTFT
597
+ const _totalMs = performance.now() - _timerStart;
598
+ if (_timerEl) {
599
+ // TTFT removed from the header per user request — just show total time.
600
+ _timerEl.textContent = _formatMs(_totalMs);
601
+ }
602
+ state._abortControllers[paneIdx] = null;
603
+ // Hide stop button, show response action buttons
604
+ const _paneElFinal = document.querySelector(`.compare-pane[data-pane="${paneIdx}"]`);
605
+ if (_paneElFinal) {
606
+ const _stopBtnFinal = _paneElFinal.querySelector('.pane-stop-btn');
607
+ if (_stopBtnFinal) _stopBtnFinal.style.display = 'none';
608
+ if (accumulated.trim()) {
609
+ _paneElFinal.querySelectorAll('.pane-needs-response').forEach(b => b.style.display = '');
610
+ }
611
+ }
612
+ state._paneMetrics[paneIdx] = metrics;
613
+ state._paneElapsed[paneIdx] = _totalMs;
614
+ if (!opts.skipBadge) {
615
+ if (streamOk) {
616
+ state._finishOrder++;
617
+ if (state._parallel) {
618
+ // Parallel: all panes started at the same instant, so first
619
+ // to finish is genuinely the fastest.
620
+ if (state._finishOrder === 1) addFinishBadge(paneIdx);
621
+ } else {
622
+ // Sequential: panes run one after another, so "first to
623
+ // finish" is meaningless (it's just whoever ran first).
624
+ // Wait until all panes are done, then badge whichever had
625
+ // the lowest measured per-pane elapsed time.
626
+ const total = state._selectedModels.length;
627
+ const finished = state._paneElapsed.filter(v => typeof v === 'number').length;
628
+ if (finished >= total) {
629
+ let winnerIdx = -1, winnerMs = Infinity;
630
+ for (let i = 0; i < total; i++) {
631
+ const v = state._paneElapsed[i];
632
+ if (typeof v === 'number' && v < winnerMs) { winnerMs = v; winnerIdx = i; }
633
+ }
634
+ if (winnerIdx >= 0) addFinishBadge(winnerIdx);
635
+ }
636
+ }
637
+ } else {
638
+ // Timed out or errored — show failed badge
639
+ const badge = document.getElementById('cmp-badge-' + paneIdx);
640
+ if (badge) { badge.textContent = timedOut ? 'Timeout' : 'Failed'; badge.style.color = 'var(--color-error)'; }
641
+ }
642
+ }
643
+ // Auto-grade against expected answer — stamps ✓ or ✗ on the pane header.
644
+ if (streamOk && state._expectedAnswer) {
645
+ _stampGradeBadge(paneIdx, accumulated, state._expectedAnswer);
646
+ }
647
+ // Show copy/reroll buttons now that response exists
648
+ const paneEl = document.querySelector('.compare-pane:nth-child(' + (paneIdx + 1) + ')');
649
+ if (paneEl) paneEl.querySelectorAll('.pane-needs-response').forEach(b => b.style.display = '');
650
+ }
651
+ }
652
+
653
+ /**
654
+ * Auto-grade a pane's response against the eval prompt's expected answer.
655
+ * Heuristic: lowercased substring match, plus a number-extraction fallback
656
+ * so "the answer is 882" matches expected "882".
657
+ * Skips meta answers like "count the words yourself…".
658
+ */
659
+ function _stampGradeBadge(paneIdx, response, expected) {
660
+ const norm = (s) => String(s).toLowerCase().replace(/\s+/g, ' ').trim();
661
+ const r = norm(response);
662
+ const e = norm(expected);
663
+ if (!r || !e) return;
664
+ // Skip non-checkable instructions
665
+ if (e.includes('yourself') || e.includes('verify') || e.length > 120) return;
666
+
667
+ let pass = r.includes(e);
668
+ if (!pass) {
669
+ // Numeric fallback — find first number in expected, look for it standalone in response
670
+ const m = expected.match(/-?\d[\d,]*(?:\.\d+)?/);
671
+ if (m) {
672
+ const n = m[0].replace(/,/g, '');
673
+ const re = new RegExp('(?<![\\d.])' + n.replace('.', '\\.') + '(?![\\d.])');
674
+ pass = re.test(response);
675
+ }
676
+ }
677
+
678
+ const paneEl = document.querySelector(`.compare-pane[data-pane="${paneIdx}"]`);
679
+ if (!paneEl) return;
680
+ const header = paneEl.querySelector('.pane-header');
681
+ if (!header) return;
682
+ // Remove any prior grade badge (re-roll case)
683
+ const prev = header.querySelector('.pane-grade-badge');
684
+ if (prev) prev.remove();
685
+ const badge = document.createElement('span');
686
+ badge.className = 'pane-grade-badge ' + (pass ? 'pass' : 'fail');
687
+ badge.title = pass ? 'Response contains the expected answer' : 'Expected answer not found in response';
688
+ badge.textContent = pass ? '✓' : '✗';
689
+ // Insert just before the finish badge if present, else after the title
690
+ const finBadge = header.querySelector('.pane-finish-badge');
691
+ if (finBadge) header.insertBefore(badge, finBadge);
692
+ else header.appendChild(badge);
693
+ }
694
+
695
+ export { streamToPane, _renderSearchResults, _runSynthForPane, _formatMs, registerStreamActions };