pygpt-net 2.6.54__py3-none-any.whl → 2.6.56__py3-none-any.whl

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 (371) hide show
  1. pygpt_net/CHANGELOG.txt +11 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +26 -22
  4. pygpt_net/controller/audio/audio.py +0 -0
  5. pygpt_net/controller/calendar/calendar.py +0 -0
  6. pygpt_net/controller/calendar/note.py +0 -0
  7. pygpt_net/controller/chat/chat.py +0 -0
  8. pygpt_net/controller/chat/handler/openai_stream.py +2 -1
  9. pygpt_net/controller/chat/handler/worker.py +0 -0
  10. pygpt_net/controller/chat/remote_tools.py +0 -0
  11. pygpt_net/controller/chat/render.py +0 -0
  12. pygpt_net/controller/chat/text.py +0 -0
  13. pygpt_net/controller/ctx/common.py +0 -0
  14. pygpt_net/controller/debug/debug.py +26 -2
  15. pygpt_net/controller/debug/fixtures.py +1 -1
  16. pygpt_net/controller/dialogs/confirm.py +15 -1
  17. pygpt_net/controller/dialogs/debug.py +2 -0
  18. pygpt_net/controller/lang/mapping.py +0 -0
  19. pygpt_net/controller/launcher/launcher.py +0 -0
  20. pygpt_net/controller/mode/mode.py +0 -0
  21. pygpt_net/controller/presets/presets.py +0 -0
  22. pygpt_net/controller/realtime/realtime.py +0 -0
  23. pygpt_net/controller/theme/theme.py +0 -0
  24. pygpt_net/controller/ui/mode.py +0 -0
  25. pygpt_net/controller/ui/tabs.py +0 -0
  26. pygpt_net/core/agents/agents.py +3 -1
  27. pygpt_net/core/agents/custom.py +150 -0
  28. pygpt_net/core/agents/provider.py +0 -0
  29. pygpt_net/core/builder/__init__.py +12 -0
  30. pygpt_net/core/builder/graph.py +478 -0
  31. pygpt_net/core/calendar/calendar.py +0 -0
  32. pygpt_net/core/ctx/ctx.py +2 -1
  33. pygpt_net/core/ctx/output.py +0 -0
  34. pygpt_net/core/debug/agent.py +0 -0
  35. pygpt_net/core/debug/agent_builder.py +29 -0
  36. pygpt_net/core/debug/console/console.py +0 -0
  37. pygpt_net/core/debug/db.py +0 -0
  38. pygpt_net/core/debug/debug.py +0 -0
  39. pygpt_net/core/debug/events.py +0 -0
  40. pygpt_net/core/debug/indexes.py +0 -0
  41. pygpt_net/core/debug/kernel.py +0 -0
  42. pygpt_net/core/debug/tabs.py +0 -0
  43. pygpt_net/core/filesystem/filesystem.py +0 -0
  44. pygpt_net/core/fixtures/__init__ +0 -0
  45. pygpt_net/core/fixtures/stream/__init__.py +0 -0
  46. pygpt_net/core/fixtures/stream/generator.py +0 -0
  47. pygpt_net/core/models/models.py +0 -0
  48. pygpt_net/core/render/plain/pid.py +0 -0
  49. pygpt_net/core/render/plain/renderer.py +26 -4
  50. pygpt_net/core/render/web/body.py +46 -4
  51. pygpt_net/core/render/web/debug.py +0 -0
  52. pygpt_net/core/render/web/helpers.py +0 -0
  53. pygpt_net/core/render/web/pid.py +0 -0
  54. pygpt_net/core/render/web/renderer.py +15 -20
  55. pygpt_net/core/tabs/tab.py +0 -0
  56. pygpt_net/core/tabs/tabs.py +0 -0
  57. pygpt_net/core/text/utils.py +0 -0
  58. pygpt_net/css.qrc +0 -0
  59. pygpt_net/css_rc.py +0 -0
  60. pygpt_net/data/config/config.json +7 -7
  61. pygpt_net/data/config/models.json +3 -3
  62. pygpt_net/data/css/web-blocks.css +9 -0
  63. pygpt_net/data/css/web-blocks.dark.css +6 -0
  64. pygpt_net/data/css/web-blocks.darkest.css +6 -0
  65. pygpt_net/data/css/web-chatgpt.css +14 -6
  66. pygpt_net/data/css/web-chatgpt.dark.css +6 -0
  67. pygpt_net/data/css/web-chatgpt.darkest.css +6 -0
  68. pygpt_net/data/css/web-chatgpt.light.css +6 -0
  69. pygpt_net/data/css/web-chatgpt_wide.css +14 -6
  70. pygpt_net/data/css/web-chatgpt_wide.dark.css +6 -0
  71. pygpt_net/data/css/web-chatgpt_wide.darkest.css +6 -0
  72. pygpt_net/data/css/web-chatgpt_wide.light.css +6 -0
  73. pygpt_net/data/fixtures/fake_stream.txt +14 -1
  74. pygpt_net/data/icons/case.svg +0 -0
  75. pygpt_net/data/icons/chat1.svg +0 -0
  76. pygpt_net/data/icons/chat2.svg +0 -0
  77. pygpt_net/data/icons/chat3.svg +0 -0
  78. pygpt_net/data/icons/chat4.svg +0 -0
  79. pygpt_net/data/icons/fit.svg +0 -0
  80. pygpt_net/data/icons/note1.svg +0 -0
  81. pygpt_net/data/icons/note2.svg +0 -0
  82. pygpt_net/data/icons/note3.svg +0 -0
  83. pygpt_net/data/icons/stt.svg +0 -0
  84. pygpt_net/data/icons/translate.svg +0 -0
  85. pygpt_net/data/icons/tts.svg +0 -0
  86. pygpt_net/data/icons/url.svg +0 -0
  87. pygpt_net/data/icons/vision.svg +0 -0
  88. pygpt_net/data/icons/web_off.svg +0 -0
  89. pygpt_net/data/icons/web_on.svg +0 -0
  90. pygpt_net/data/js/app/async.js +166 -0
  91. pygpt_net/data/js/app/bridge.js +88 -0
  92. pygpt_net/data/js/app/common.js +212 -0
  93. pygpt_net/data/js/app/config.js +223 -0
  94. pygpt_net/data/js/app/custom.js +961 -0
  95. pygpt_net/data/js/app/data.js +84 -0
  96. pygpt_net/data/js/app/dom.js +322 -0
  97. pygpt_net/data/js/app/events.js +400 -0
  98. pygpt_net/data/js/app/highlight.js +542 -0
  99. pygpt_net/data/js/app/logger.js +305 -0
  100. pygpt_net/data/js/app/markdown.js +1137 -0
  101. pygpt_net/data/js/app/math.js +167 -0
  102. pygpt_net/data/js/app/nodes.js +395 -0
  103. pygpt_net/data/js/app/queue.js +260 -0
  104. pygpt_net/data/js/app/raf.js +250 -0
  105. pygpt_net/data/js/app/runtime.js +582 -0
  106. pygpt_net/data/js/app/scroll.js +433 -0
  107. pygpt_net/data/js/app/stream.js +2708 -0
  108. pygpt_net/data/js/app/template.js +287 -0
  109. pygpt_net/data/js/app/tool.js +87 -0
  110. pygpt_net/data/js/app/ui.js +86 -0
  111. pygpt_net/data/js/app/user.js +380 -0
  112. pygpt_net/data/js/app/utils.js +64 -0
  113. pygpt_net/data/js/app.min.js +880 -0
  114. pygpt_net/data/js/markdown-it/markdown-it-katex.min.js +1 -1
  115. pygpt_net/data/js/markdown-it/markdown-it.min.js +0 -0
  116. pygpt_net/data/locale/locale.de.ini +0 -0
  117. pygpt_net/data/locale/locale.en.ini +7 -0
  118. pygpt_net/data/locale/locale.es.ini +0 -0
  119. pygpt_net/data/locale/locale.fr.ini +0 -0
  120. pygpt_net/data/locale/locale.it.ini +0 -0
  121. pygpt_net/data/locale/locale.pl.ini +0 -0
  122. pygpt_net/data/locale/locale.uk.ini +0 -0
  123. pygpt_net/data/locale/locale.zh.ini +0 -0
  124. pygpt_net/data/locale/plugin.agent.de.ini +0 -0
  125. pygpt_net/data/locale/plugin.agent.en.ini +0 -0
  126. pygpt_net/data/locale/plugin.agent.es.ini +0 -0
  127. pygpt_net/data/locale/plugin.agent.fr.ini +0 -0
  128. pygpt_net/data/locale/plugin.agent.it.ini +0 -0
  129. pygpt_net/data/locale/plugin.agent.pl.ini +0 -0
  130. pygpt_net/data/locale/plugin.agent.uk.ini +0 -0
  131. pygpt_net/data/locale/plugin.agent.zh.ini +0 -0
  132. pygpt_net/data/locale/plugin.audio_input.de.ini +0 -0
  133. pygpt_net/data/locale/plugin.audio_input.en.ini +0 -0
  134. pygpt_net/data/locale/plugin.audio_input.es.ini +0 -0
  135. pygpt_net/data/locale/plugin.audio_input.fr.ini +0 -0
  136. pygpt_net/data/locale/plugin.audio_input.it.ini +0 -0
  137. pygpt_net/data/locale/plugin.audio_input.pl.ini +0 -0
  138. pygpt_net/data/locale/plugin.audio_input.uk.ini +0 -0
  139. pygpt_net/data/locale/plugin.audio_input.zh.ini +0 -0
  140. pygpt_net/data/locale/plugin.audio_output.de.ini +0 -0
  141. pygpt_net/data/locale/plugin.audio_output.en.ini +0 -0
  142. pygpt_net/data/locale/plugin.audio_output.es.ini +0 -0
  143. pygpt_net/data/locale/plugin.audio_output.fr.ini +0 -0
  144. pygpt_net/data/locale/plugin.audio_output.it.ini +0 -0
  145. pygpt_net/data/locale/plugin.audio_output.pl.ini +0 -0
  146. pygpt_net/data/locale/plugin.audio_output.uk.ini +0 -0
  147. pygpt_net/data/locale/plugin.audio_output.zh.ini +0 -0
  148. pygpt_net/data/locale/plugin.cmd_api.de.ini +0 -0
  149. pygpt_net/data/locale/plugin.cmd_api.en.ini +0 -0
  150. pygpt_net/data/locale/plugin.cmd_api.es.ini +0 -0
  151. pygpt_net/data/locale/plugin.cmd_api.fr.ini +0 -0
  152. pygpt_net/data/locale/plugin.cmd_api.it.ini +0 -0
  153. pygpt_net/data/locale/plugin.cmd_api.pl.ini +0 -0
  154. pygpt_net/data/locale/plugin.cmd_api.uk.ini +0 -0
  155. pygpt_net/data/locale/plugin.cmd_api.zh.ini +0 -0
  156. pygpt_net/data/locale/plugin.cmd_code_interpreter.de.ini +0 -0
  157. pygpt_net/data/locale/plugin.cmd_code_interpreter.en.ini +0 -0
  158. pygpt_net/data/locale/plugin.cmd_code_interpreter.es.ini +0 -0
  159. pygpt_net/data/locale/plugin.cmd_code_interpreter.fr.ini +0 -0
  160. pygpt_net/data/locale/plugin.cmd_code_interpreter.it.ini +0 -0
  161. pygpt_net/data/locale/plugin.cmd_code_interpreter.pl.ini +0 -0
  162. pygpt_net/data/locale/plugin.cmd_code_interpreter.uk.ini +0 -0
  163. pygpt_net/data/locale/plugin.cmd_code_interpreter.zh.ini +0 -0
  164. pygpt_net/data/locale/plugin.cmd_custom.de.ini +0 -0
  165. pygpt_net/data/locale/plugin.cmd_custom.en.ini +0 -0
  166. pygpt_net/data/locale/plugin.cmd_custom.es.ini +0 -0
  167. pygpt_net/data/locale/plugin.cmd_custom.fr.ini +0 -0
  168. pygpt_net/data/locale/plugin.cmd_custom.it.ini +0 -0
  169. pygpt_net/data/locale/plugin.cmd_custom.pl.ini +0 -0
  170. pygpt_net/data/locale/plugin.cmd_custom.uk.ini +0 -0
  171. pygpt_net/data/locale/plugin.cmd_custom.zh.ini +0 -0
  172. pygpt_net/data/locale/plugin.cmd_files.de.ini +0 -0
  173. pygpt_net/data/locale/plugin.cmd_files.en.ini +0 -0
  174. pygpt_net/data/locale/plugin.cmd_files.es.ini +0 -0
  175. pygpt_net/data/locale/plugin.cmd_files.fr.ini +0 -0
  176. pygpt_net/data/locale/plugin.cmd_files.it.ini +0 -0
  177. pygpt_net/data/locale/plugin.cmd_files.pl.ini +0 -0
  178. pygpt_net/data/locale/plugin.cmd_files.uk.ini +0 -0
  179. pygpt_net/data/locale/plugin.cmd_files.zh.ini +0 -0
  180. pygpt_net/data/locale/plugin.cmd_history.de.ini +0 -0
  181. pygpt_net/data/locale/plugin.cmd_history.en.ini +0 -0
  182. pygpt_net/data/locale/plugin.cmd_history.es.ini +0 -0
  183. pygpt_net/data/locale/plugin.cmd_history.fr.ini +0 -0
  184. pygpt_net/data/locale/plugin.cmd_history.it.ini +0 -0
  185. pygpt_net/data/locale/plugin.cmd_history.pl.ini +0 -0
  186. pygpt_net/data/locale/plugin.cmd_history.uk.ini +0 -0
  187. pygpt_net/data/locale/plugin.cmd_history.zh.ini +0 -0
  188. pygpt_net/data/locale/plugin.cmd_mouse_control.de.ini +0 -0
  189. pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +0 -0
  190. pygpt_net/data/locale/plugin.cmd_mouse_control.es.ini +0 -0
  191. pygpt_net/data/locale/plugin.cmd_mouse_control.fr.ini +0 -0
  192. pygpt_net/data/locale/plugin.cmd_mouse_control.it.ini +0 -0
  193. pygpt_net/data/locale/plugin.cmd_mouse_control.pl.ini +0 -0
  194. pygpt_net/data/locale/plugin.cmd_mouse_control.uk.ini +0 -0
  195. pygpt_net/data/locale/plugin.cmd_mouse_control.zh.ini +0 -0
  196. pygpt_net/data/locale/plugin.cmd_serial.de.ini +0 -0
  197. pygpt_net/data/locale/plugin.cmd_serial.en.ini +0 -0
  198. pygpt_net/data/locale/plugin.cmd_serial.es.ini +0 -0
  199. pygpt_net/data/locale/plugin.cmd_serial.fr.ini +0 -0
  200. pygpt_net/data/locale/plugin.cmd_serial.it.ini +0 -0
  201. pygpt_net/data/locale/plugin.cmd_serial.pl.ini +0 -0
  202. pygpt_net/data/locale/plugin.cmd_serial.uk.ini +0 -0
  203. pygpt_net/data/locale/plugin.cmd_serial.zh.ini +0 -0
  204. pygpt_net/data/locale/plugin.cmd_system.de.ini +0 -0
  205. pygpt_net/data/locale/plugin.cmd_system.en.ini +0 -0
  206. pygpt_net/data/locale/plugin.cmd_system.es.ini +0 -0
  207. pygpt_net/data/locale/plugin.cmd_system.fr.ini +0 -0
  208. pygpt_net/data/locale/plugin.cmd_system.it.ini +0 -0
  209. pygpt_net/data/locale/plugin.cmd_system.pl.ini +0 -0
  210. pygpt_net/data/locale/plugin.cmd_system.uk.ini +0 -0
  211. pygpt_net/data/locale/plugin.cmd_system.zh.ini +0 -0
  212. pygpt_net/data/locale/plugin.cmd_web.de.ini +0 -0
  213. pygpt_net/data/locale/plugin.cmd_web.en.ini +0 -0
  214. pygpt_net/data/locale/plugin.cmd_web.es.ini +0 -0
  215. pygpt_net/data/locale/plugin.cmd_web.fr.ini +0 -0
  216. pygpt_net/data/locale/plugin.cmd_web.it.ini +0 -0
  217. pygpt_net/data/locale/plugin.cmd_web.pl.ini +0 -0
  218. pygpt_net/data/locale/plugin.cmd_web.uk.ini +0 -0
  219. pygpt_net/data/locale/plugin.cmd_web.zh.ini +0 -0
  220. pygpt_net/data/locale/plugin.crontab.de.ini +0 -0
  221. pygpt_net/data/locale/plugin.crontab.en.ini +0 -0
  222. pygpt_net/data/locale/plugin.crontab.es.ini +0 -0
  223. pygpt_net/data/locale/plugin.crontab.fr.ini +0 -0
  224. pygpt_net/data/locale/plugin.crontab.it.ini +0 -0
  225. pygpt_net/data/locale/plugin.crontab.pl.ini +0 -0
  226. pygpt_net/data/locale/plugin.crontab.uk.ini +0 -0
  227. pygpt_net/data/locale/plugin.crontab.zh.ini +0 -0
  228. pygpt_net/data/locale/plugin.experts.de.ini +0 -0
  229. pygpt_net/data/locale/plugin.experts.en.ini +0 -0
  230. pygpt_net/data/locale/plugin.experts.es.ini +0 -0
  231. pygpt_net/data/locale/plugin.experts.fr.ini +0 -0
  232. pygpt_net/data/locale/plugin.experts.it.ini +0 -0
  233. pygpt_net/data/locale/plugin.experts.pl.ini +0 -0
  234. pygpt_net/data/locale/plugin.experts.uk.ini +0 -0
  235. pygpt_net/data/locale/plugin.experts.zh.ini +0 -0
  236. pygpt_net/data/locale/plugin.extra_prompt.de.ini +0 -0
  237. pygpt_net/data/locale/plugin.extra_prompt.en.ini +0 -0
  238. pygpt_net/data/locale/plugin.extra_prompt.es.ini +0 -0
  239. pygpt_net/data/locale/plugin.extra_prompt.fr.ini +0 -0
  240. pygpt_net/data/locale/plugin.extra_prompt.it.ini +0 -0
  241. pygpt_net/data/locale/plugin.extra_prompt.pl.ini +0 -0
  242. pygpt_net/data/locale/plugin.extra_prompt.uk.ini +0 -0
  243. pygpt_net/data/locale/plugin.extra_prompt.zh.ini +0 -0
  244. pygpt_net/data/locale/plugin.idx_llama_index.de.ini +0 -0
  245. pygpt_net/data/locale/plugin.idx_llama_index.en.ini +0 -0
  246. pygpt_net/data/locale/plugin.idx_llama_index.es.ini +0 -0
  247. pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +0 -0
  248. pygpt_net/data/locale/plugin.idx_llama_index.it.ini +0 -0
  249. pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +0 -0
  250. pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +0 -0
  251. pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +0 -0
  252. pygpt_net/data/locale/plugin.mailer.en.ini +0 -0
  253. pygpt_net/data/locale/plugin.mcp.en.ini +0 -0
  254. pygpt_net/data/locale/plugin.openai_dalle.de.ini +0 -0
  255. pygpt_net/data/locale/plugin.openai_dalle.en.ini +0 -0
  256. pygpt_net/data/locale/plugin.openai_dalle.es.ini +0 -0
  257. pygpt_net/data/locale/plugin.openai_dalle.fr.ini +0 -0
  258. pygpt_net/data/locale/plugin.openai_dalle.it.ini +0 -0
  259. pygpt_net/data/locale/plugin.openai_dalle.pl.ini +0 -0
  260. pygpt_net/data/locale/plugin.openai_dalle.uk.ini +0 -0
  261. pygpt_net/data/locale/plugin.openai_dalle.zh.ini +0 -0
  262. pygpt_net/data/locale/plugin.openai_vision.de.ini +0 -0
  263. pygpt_net/data/locale/plugin.openai_vision.en.ini +0 -0
  264. pygpt_net/data/locale/plugin.openai_vision.es.ini +0 -0
  265. pygpt_net/data/locale/plugin.openai_vision.fr.ini +0 -0
  266. pygpt_net/data/locale/plugin.openai_vision.it.ini +0 -0
  267. pygpt_net/data/locale/plugin.openai_vision.pl.ini +0 -0
  268. pygpt_net/data/locale/plugin.openai_vision.uk.ini +0 -0
  269. pygpt_net/data/locale/plugin.openai_vision.zh.ini +0 -0
  270. pygpt_net/data/locale/plugin.osm.en.ini +0 -0
  271. pygpt_net/data/locale/plugin.real_time.de.ini +0 -0
  272. pygpt_net/data/locale/plugin.real_time.en.ini +0 -0
  273. pygpt_net/data/locale/plugin.real_time.es.ini +0 -0
  274. pygpt_net/data/locale/plugin.real_time.fr.ini +0 -0
  275. pygpt_net/data/locale/plugin.real_time.it.ini +0 -0
  276. pygpt_net/data/locale/plugin.real_time.pl.ini +0 -0
  277. pygpt_net/data/locale/plugin.real_time.uk.ini +0 -0
  278. pygpt_net/data/locale/plugin.real_time.zh.ini +0 -0
  279. pygpt_net/data/locale/plugin.voice_control.de.ini +0 -0
  280. pygpt_net/data/locale/plugin.voice_control.en.ini +0 -0
  281. pygpt_net/data/locale/plugin.voice_control.es.ini +0 -0
  282. pygpt_net/data/locale/plugin.voice_control.fr.ini +0 -0
  283. pygpt_net/data/locale/plugin.voice_control.it.ini +0 -0
  284. pygpt_net/data/locale/plugin.voice_control.pl.ini +0 -0
  285. pygpt_net/data/locale/plugin.voice_control.uk.ini +0 -0
  286. pygpt_net/data/locale/plugin.voice_control.zh.ini +0 -0
  287. pygpt_net/data/locale/plugin.wolfram.en.ini +0 -0
  288. pygpt_net/fonts.qrc +0 -0
  289. pygpt_net/fonts_rc.py +0 -0
  290. pygpt_net/icons.qrc +0 -0
  291. pygpt_net/icons_rc.py +0 -0
  292. pygpt_net/item/agent.py +62 -0
  293. pygpt_net/item/builder_layout.py +62 -0
  294. pygpt_net/js.qrc +24 -1
  295. pygpt_net/js_rc.py +51394 -33687
  296. pygpt_net/plugin/base/worker.py +0 -0
  297. pygpt_net/plugin/mcp/__init__.py +0 -0
  298. pygpt_net/plugin/mcp/config.py +0 -0
  299. pygpt_net/plugin/mcp/plugin.py +0 -0
  300. pygpt_net/plugin/mcp/worker.py +0 -0
  301. pygpt_net/plugin/osm/__init__.py +0 -0
  302. pygpt_net/plugin/osm/config.py +0 -0
  303. pygpt_net/plugin/osm/plugin.py +0 -0
  304. pygpt_net/plugin/osm/worker.py +0 -0
  305. pygpt_net/plugin/wolfram/__init__.py +0 -0
  306. pygpt_net/plugin/wolfram/config.py +0 -0
  307. pygpt_net/plugin/wolfram/plugin.py +0 -0
  308. pygpt_net/plugin/wolfram/worker.py +0 -0
  309. pygpt_net/provider/api/anthropic/tools.py +0 -0
  310. pygpt_net/provider/api/google/__init__.py +0 -0
  311. pygpt_net/provider/api/google/video.py +0 -0
  312. pygpt_net/provider/api/openai/agents/experts.py +0 -0
  313. pygpt_net/provider/api/openai/agents/remote_tools.py +0 -0
  314. pygpt_net/provider/api/openai/remote_tools.py +0 -0
  315. pygpt_net/provider/api/openai/responses.py +0 -0
  316. pygpt_net/provider/api/x_ai/__init__.py +0 -0
  317. pygpt_net/provider/api/x_ai/remote.py +0 -0
  318. pygpt_net/provider/core/agent/__init__.py +10 -0
  319. pygpt_net/provider/core/agent/base.py +51 -0
  320. pygpt_net/provider/core/agent/json_file.py +200 -0
  321. pygpt_net/provider/core/config/patch.py +18 -0
  322. pygpt_net/provider/core/config/patches/__init__.py +0 -0
  323. pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +0 -0
  324. pygpt_net/provider/core/ctx/db_sqlite/storage.py +0 -0
  325. pygpt_net/provider/core/model/patches/__init__.py +0 -0
  326. pygpt_net/provider/core/model/patches/patch_before_2_6_42.py +0 -0
  327. pygpt_net/provider/core/preset/patch.py +0 -0
  328. pygpt_net/provider/core/preset/patches/__init__.py +0 -0
  329. pygpt_net/provider/core/preset/patches/patch_before_2_6_42.py +0 -0
  330. pygpt_net/provider/llms/base.py +0 -0
  331. pygpt_net/provider/llms/deepseek_api.py +0 -0
  332. pygpt_net/provider/llms/google.py +0 -0
  333. pygpt_net/provider/llms/hugging_face_api.py +0 -0
  334. pygpt_net/provider/llms/hugging_face_embedding.py +0 -0
  335. pygpt_net/provider/llms/hugging_face_router.py +0 -0
  336. pygpt_net/provider/llms/local.py +0 -0
  337. pygpt_net/provider/llms/mistral.py +0 -0
  338. pygpt_net/provider/llms/open_router.py +0 -0
  339. pygpt_net/provider/llms/perplexity.py +0 -0
  340. pygpt_net/provider/llms/utils.py +0 -0
  341. pygpt_net/provider/llms/voyage.py +0 -0
  342. pygpt_net/provider/llms/x_ai.py +0 -0
  343. pygpt_net/tools/agent_builder/__init__.py +12 -0
  344. pygpt_net/tools/agent_builder/tool.py +292 -0
  345. pygpt_net/tools/agent_builder/ui/__init__.py +0 -0
  346. pygpt_net/tools/agent_builder/ui/dialogs.py +152 -0
  347. pygpt_net/tools/agent_builder/ui/list.py +228 -0
  348. pygpt_net/tools/code_interpreter/ui/html.py +0 -0
  349. pygpt_net/tools/code_interpreter/ui/widgets.py +0 -0
  350. pygpt_net/tools/html_canvas/tool.py +23 -6
  351. pygpt_net/tools/html_canvas/ui/widgets.py +224 -2
  352. pygpt_net/ui/layout/chat/chat.py +0 -0
  353. pygpt_net/ui/main.py +10 -9
  354. pygpt_net/ui/menu/debug.py +39 -1
  355. pygpt_net/ui/widget/builder/__init__.py +12 -0
  356. pygpt_net/ui/widget/builder/editor.py +2001 -0
  357. pygpt_net/ui/widget/draw/painter.py +0 -0
  358. pygpt_net/ui/widget/element/labels.py +9 -4
  359. pygpt_net/ui/widget/lists/db.py +0 -0
  360. pygpt_net/ui/widget/lists/debug.py +0 -0
  361. pygpt_net/ui/widget/tabs/body.py +0 -0
  362. pygpt_net/ui/widget/textarea/input.py +17 -8
  363. pygpt_net/ui/widget/textarea/output.py +21 -1
  364. pygpt_net/ui/widget/textarea/web.py +29 -2
  365. pygpt_net/utils.py +40 -0
  366. {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/METADATA +13 -2
  367. {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/RECORD +86 -47
  368. pygpt_net/data/js/app.js +0 -5869
  369. {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/LICENSE +0 -0
  370. {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/WHEEL +0 -0
  371. {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,542 @@
1
+ // ==========================================================================
2
+ // Highlighter (hljs) + rAF viewport scan
3
+ // ==========================================================================
4
+
5
+ class Highlighter {
6
+
7
+ // Constructor: store config/scroll/RAF, init queues and scan budget
8
+ constructor(cfg, codeScroll, raf) {
9
+ this.cfg = cfg;
10
+ this.codeScroll = codeScroll;
11
+ this.raf = raf;
12
+
13
+ this.hlScheduled = false;
14
+ this.hlQueue = [];
15
+ this.hlQueueSet = new WeakSet();
16
+
17
+ this.scanScheduled = false;
18
+
19
+ this._activeCodeEl = null;
20
+
21
+ this._globalScanState = null;
22
+
23
+ this.ALIAS = {
24
+ txt: 'plaintext',
25
+ text: 'plaintext',
26
+ plaintext: 'plaintext',
27
+ sh: 'bash',
28
+ shell: 'bash',
29
+ zsh: 'bash',
30
+ 'shell-session': 'bash',
31
+ py: 'python',
32
+ python3: 'python',
33
+ py3: 'python',
34
+ js: 'javascript',
35
+ node: 'javascript',
36
+ nodejs: 'javascript',
37
+ ts: 'typescript',
38
+ 'ts-node': 'typescript',
39
+ yml: 'yaml',
40
+ kt: 'kotlin',
41
+ rs: 'rust',
42
+ csharp: 'csharp',
43
+ 'c#': 'csharp',
44
+ 'c++': 'cpp',
45
+ ps: 'powershell',
46
+ ps1: 'powershell',
47
+ pwsh: 'powershell',
48
+ powershell7: 'powershell',
49
+ docker: 'dockerfile'
50
+ };
51
+
52
+ const hint = (cfg && cfg.RAF && cfg.RAF.FLUSH_BUDGET_MS) ? cfg.RAF.FLUSH_BUDGET_MS : 7;
53
+ this.SCAN_STEP_BUDGET_MS = Math.max(3, Math.min(12, hint));
54
+ }
55
+
56
+ // Debug helper: write structured log lines for the stream engine.
57
+ _d(tag, data) {
58
+ try {
59
+ const lg = this.logger || (this.cfg && this.cfg.logger) || (window.runtime && runtime.logger) || null;
60
+ if (!lg || typeof lg.debug !== 'function') return;
61
+ lg.debug_obj("HL", tag, data);
62
+ } catch (_) {}
63
+ }
64
+
65
+ // Decodes HTML entities in a string, handling nested entities up to a specified number of passes.
66
+ _decodeEntitiesDeep(text, maxPasses = 2) {
67
+ if (!text || text.indexOf('&') === -1) return text || '';
68
+ const ta = Highlighter._decTA || (Highlighter._decTA = document.createElement('textarea'));
69
+ const decodeOnce = (s) => {
70
+ ta.innerHTML = s;
71
+ return ta.value;
72
+ };
73
+ let prev = String(text),
74
+ cur = decodeOnce(prev),
75
+ passes = 1;
76
+ while (passes < maxPasses && cur !== prev) {
77
+ prev = cur;
78
+ cur = decodeOnce(prev);
79
+ passes++;
80
+ }
81
+ return cur;
82
+ }
83
+
84
+ // Check if highlighting is globally disabled via configuration.
85
+ isDisabled() {
86
+ return !!this.cfg.HL.DISABLE_ALL;
87
+ }
88
+
89
+ // Initializes the Highlight.js library with specific configuration settings.
90
+ initHLJS() {
91
+ if (this.isDisabled()) return;
92
+ if (typeof hljs !== 'undefined' && hljs) {
93
+ try {
94
+ hljs.configure({
95
+ ignoreUnescapedHTML: true
96
+ });
97
+ } catch (_) {}
98
+ }
99
+ }
100
+
101
+ // Returns true if the element is within (or near) the viewport,
102
+ // using a preload margin to start work slightly before it becomes visible.
103
+ _nearViewport(el) {
104
+ const preload = this.cfg.SCAN.PRELOAD_PX;
105
+ const vh = window.innerHeight || Utils.SE.clientHeight || 800;
106
+ const r = el.getBoundingClientRect();
107
+ return r.bottom >= -preload && r.top <= (vh + preload);
108
+ }
109
+
110
+ // Queue a code element for highlighting. Avoids duplicates, respects
111
+ // "active" code being streamed, and schedules a flush via rAF.
112
+ queue(codeEl, activeCode) {
113
+ if (this.isDisabled()) return;
114
+ if (!codeEl || !codeEl.isConnected) return;
115
+
116
+ // Track the currently streaming code block to avoid highlighting it mid-stream.
117
+ if (activeCode && activeCode.codeEl) this._activeCodeEl = activeCode.codeEl;
118
+
119
+ // Skip: the currently active element, already highlighted, or explicitly suspended.
120
+ if (this._activeCodeEl && codeEl === this._activeCodeEl) return;
121
+ if (codeEl.getAttribute('data-highlighted') === 'yes') return;
122
+ if (codeEl.dataset && (codeEl.dataset.hlStreamSuspended === '1' || codeEl.dataset.finalHlSkip === '1')) return;
123
+ // We only highlight bot messages; user code blocks are ignored here.
124
+ if (!codeEl.closest('.msg-box.msg-bot')) return;
125
+
126
+ // De-duplicate with a WeakSet (handles disconnected nodes GC-safe).
127
+ if (!this.hlQueueSet.has(codeEl)) {
128
+ this.hlQueueSet.add(codeEl);
129
+ this.hlQueue.push(codeEl);
130
+ }
131
+
132
+ // Coalesce flush requests into a single rAF task.
133
+ if (!this.hlScheduled) {
134
+ this.hlScheduled = true;
135
+ this.raf.schedule('HL:flush', () => this.flush(), 'Highlighter', 1);
136
+ }
137
+
138
+ // DEBUG (avoid heavy reads)
139
+ try {
140
+ const wrap = codeEl.closest('.code-wrapper');
141
+ const len = wrap ? parseInt(wrap.getAttribute('data-code-len') || '0', 10) : NaN;
142
+ this._d('queue', {
143
+ len,
144
+ hasWrap: !!wrap
145
+ });
146
+ } catch (_) {}
147
+ }
148
+
149
+ // Flush the highlight queue. Processes up to HL.PER_FRAME items per frame.
150
+ // Yields early if the browser reports pending input for responsiveness.
151
+ flush() {
152
+ if (this.isDisabled()) {
153
+ this.hlScheduled = false;
154
+ this.hlQueueSet.clear();
155
+ this.hlQueue.length = 0;
156
+ return;
157
+ }
158
+
159
+ this.hlScheduled = false;
160
+
161
+ const activeEl = this._activeCodeEl;
162
+
163
+ let count = 0;
164
+ while (this.hlQueue.length && count < this.cfg.HL.PER_FRAME) {
165
+ const el = this.hlQueue.shift();
166
+ if (el && el.isConnected) this.safeHighlight(el, activeEl);
167
+ if (el) this.hlQueueSet.delete(el);
168
+ count++;
169
+
170
+ // Cooperative yield if there's pending input to keep the UI responsive.
171
+ try {
172
+ const sched = (navigator && navigator.scheduling && navigator.scheduling.isInputPending) ? navigator.scheduling : null;
173
+ if (sched && sched.isInputPending({
174
+ includeContinuous: true
175
+ })) {
176
+ if (this.hlQueue.length) {
177
+ this.hlScheduled = true;
178
+ this.raf.schedule('HL:flush', () => this.flush(), 'Highlighter', 1);
179
+ }
180
+ this._d('flush.yield', {
181
+ processed: count,
182
+ remaining: this.hlQueue.length
183
+ });
184
+ return;
185
+ }
186
+ } catch (_) {}
187
+ }
188
+
189
+ // If there are still items, schedule another frame.
190
+ if (this.hlQueue.length) {
191
+ this.hlScheduled = true;
192
+ this.raf.schedule('HL:flush', () => this.flush(), 'Highlighter', 1);
193
+ }
194
+ this._d('flush.done', {
195
+ processed: count,
196
+ remaining: this.hlQueue.length
197
+ });
198
+ }
199
+
200
+ // Fast check: does the text contain any entity markers that might need decoding?
201
+ _needsDeepDecode(text) {
202
+ if (!text) return false;
203
+ const s = String(text);
204
+ return (s.indexOf('&') !== -1) || (s.indexOf('&#') !== -1);
205
+ }
206
+
207
+ // Cheap, single-pass entity decoder for common entities.
208
+ _decodeEntitiesCheap(s) {
209
+ return s
210
+ .replaceAll('&amp;', '&')
211
+ .replaceAll('&lt;', '<')
212
+ .replaceAll('&gt;', '>')
213
+ .replaceAll('&quot;', '"')
214
+ .replaceAll('&#39;', "'");
215
+ }
216
+
217
+ // If the code block is finalized, detach scroll handlers to avoid unnecessary work.
218
+ detachHandlersIfFinal(el) {
219
+ if (this.isFinalizedCode(el)) this.detachHandlers(el);
220
+ }
221
+
222
+ // Opportunistically highlight a small number of near-viewport code blocks immediately,
223
+ // within a tiny time budget, to improve perceived responsiveness.
224
+ microHighlightNow(root, opts, activeCode) {
225
+ if (this.isDisabled()) return;
226
+ const scope = root || document;
227
+ const options = Object.assign({
228
+ maxCount: 1,
229
+ budgetMs: 4
230
+ }, opts || {});
231
+ const activeEl = activeCode && activeCode.codeEl ? activeCode.codeEl : null;
232
+
233
+ // Clamp micro limits to avoid expensive work on large snippets.
234
+ const maxLines = (this.cfg.HL && this.cfg.HL.MICRO_MAX_LINES) || Math.min(80, this.cfg.PROFILE_CODE.finalHighlightMaxLines || 200);
235
+ const maxChars = (this.cfg.HL && this.cfg.HL.MICRO_MAX_CHARS) || Math.min(4000, this.cfg.PROFILE_CODE.finalHighlightMaxChars || 20000);
236
+
237
+ const nodes = scope.querySelectorAll('.msg-box.msg-bot pre code:not([data-highlighted="yes"])');
238
+ const start = Utils.now();
239
+ let done = 0;
240
+
241
+ for (let i = 0; i < nodes.length && done < options.maxCount; i++) {
242
+ const el = nodes[i];
243
+ if (!el || !el.isConnected) continue;
244
+ if (activeEl && el === activeEl) continue;
245
+ if (!this._nearViewport(el)) continue;
246
+
247
+ // Use precomputed size hints if available; otherwise stay conservative.
248
+ let lines = NaN,
249
+ chars = NaN;
250
+ const wrap = el.closest('.code-wrapper');
251
+ if (wrap) {
252
+ const nlAttr = wrap.getAttribute('data-code-nl');
253
+ const lenAttr = wrap.getAttribute('data-code-len');
254
+ if (nlAttr) lines = parseInt(nlAttr, 10);
255
+ if (lenAttr) chars = parseInt(lenAttr, 10);
256
+ }
257
+ if ((Number.isFinite(lines) && lines > maxLines) || (Number.isFinite(chars) && chars > maxChars)) continue;
258
+
259
+ // Highlight immediately and attach scrolling handlers.
260
+ try {
261
+ if (window.hljs) {
262
+ hljs.highlightElement(el);
263
+ el.setAttribute('data-highlighted', 'yes');
264
+ this.codeScroll.attachHandlers(el);
265
+ }
266
+ } catch (_) {}
267
+ done++;
268
+ // Stop if we exceeded our small budget.
269
+ if ((Utils.now() - start) >= options.budgetMs) break;
270
+ }
271
+ if (done) this._d('micro.now', {
272
+ done
273
+ });
274
+ }
275
+
276
+ // Safely highlight a code element. Respects size caps and preserves scroll state.
277
+ safeHighlight(codeEl, activeEl) {
278
+ if (this.isDisabled()) return;
279
+ if (!window.hljs || !codeEl || !codeEl.isConnected) return;
280
+ if (!codeEl.closest('.msg-box.msg-bot')) return;
281
+ if (codeEl.getAttribute('data-highlighted') === 'yes') return;
282
+ if (activeEl && codeEl === activeEl) return;
283
+
284
+ // Size guard: skip very large blocks and mark them as finalized without styling overhead.
285
+ try {
286
+ const wrap = codeEl.closest('.code-wrapper');
287
+ const maxLines = this.cfg.PROFILE_CODE.finalHighlightMaxLines | 0;
288
+ const maxChars = this.cfg.PROFILE_CODE.finalHighlightMaxChars | 0;
289
+
290
+ let lines = NaN,
291
+ chars = NaN;
292
+
293
+ if (wrap) {
294
+ const nlAttr = wrap.getAttribute('data-code-nl');
295
+ const lenAttr = wrap.getAttribute('data-code-len');
296
+ if (nlAttr) lines = parseInt(nlAttr, 10);
297
+ if (lenAttr) chars = parseInt(lenAttr, 10);
298
+ }
299
+
300
+ if ((Number.isFinite(lines) && maxLines > 0 && lines > maxLines) ||
301
+ (Number.isFinite(chars) && maxChars > 0 && chars > maxChars)) {
302
+ // Apply minimal hljs class for baseline styling, mark as skipped to avoid rework.
303
+ codeEl.classList.add('hljs');
304
+ codeEl.setAttribute('data-highlighted', 'yes');
305
+ codeEl.dataset.finalHlSkip = '1';
306
+ try {
307
+ this.codeScroll.attachHandlers(codeEl);
308
+ } catch (_) {}
309
+ // Keep auto-follow behavior for incoming content.
310
+ this.codeScroll.scheduleScroll(codeEl, false, false);
311
+ this._d('hl.skip.size', {
312
+ lines,
313
+ chars,
314
+ maxLines,
315
+ maxChars
316
+ });
317
+ return;
318
+ }
319
+ } catch (_) {}
320
+
321
+ // Preserve scroll-follow behavior if the user is near the bottom.
322
+ const wasNearBottom = this.codeScroll.isNearBottomEl(codeEl, 16);
323
+ const st = this.codeScroll.state(codeEl);
324
+ const shouldAutoScrollAfter = (st.autoFollow === true) || wasNearBottom;
325
+
326
+ try {
327
+ hljs.highlightElement(codeEl);
328
+ codeEl.setAttribute('data-highlighted', 'yes');
329
+ } catch (_) {
330
+ // Fallback: ensure baseline styling even if highlighting throws.
331
+ if (!codeEl.classList.contains('hljs')) codeEl.classList.add('hljs');
332
+ } finally {
333
+ // Always ensure handlers are attached at least once, then optionally scroll.
334
+ try {
335
+ this.codeScroll.attachHandlers(codeEl);
336
+ } catch (_) {}
337
+ const needInitForce = (codeEl.dataset && (codeEl.dataset.csInitBtm === '1' || codeEl.dataset.justFinalized === '1'));
338
+ const mustScroll = shouldAutoScrollAfter || needInitForce;
339
+ if (mustScroll) this.codeScroll.scheduleScroll(codeEl, false, !!needInitForce);
340
+ this.codeScroll.detachHandlers(codeEl);
341
+ if (codeEl.dataset) {
342
+ if (codeEl.dataset.csInitBtm === '1') codeEl.dataset.csInitBtm = '0';
343
+ if (codeEl.dataset.justFinalized === '1') codeEl.dataset.justFinalized = '0';
344
+ }
345
+ this._d('hl.done', {
346
+ autoScroll: mustScroll
347
+ });
348
+ }
349
+ }
350
+
351
+ // Initialize a global, time-sliced scan over all candidate code blocks,
352
+ // enqueuing those that fall within an expanded viewport.
353
+ _startGlobalScan(activeCode) {
354
+ if (this.isDisabled()) return;
355
+
356
+ this._activeCodeEl = (activeCode && activeCode.codeEl) ? activeCode.codeEl : this._activeCodeEl;
357
+
358
+ const preload = this.cfg.SCAN_PRELOAD_PX || this.cfg.SCAN.PRELOAD_PX;
359
+ const vh = window.innerHeight || Utils.SE.clientHeight || 800;
360
+ const rectTop = 0 - preload,
361
+ rectBottom = vh + preload;
362
+
363
+ const nodes = document.querySelectorAll('.msg-box.msg-bot pre code:not([data-highlighted="yes"])');
364
+
365
+ this._globalScanState = {
366
+ nodes,
367
+ idx: 0,
368
+ rectTop,
369
+ rectBottom,
370
+ activeCodeEl: this._activeCodeEl || null
371
+ };
372
+
373
+ this._d('scan.start', {
374
+ candidates: nodes.length
375
+ });
376
+ this._scanGlobalStep();
377
+ }
378
+
379
+ // Perform one incremental scan step, respecting SCAN_STEP_BUDGET_MS
380
+ // to keep main thread responsive. Queues elements near the viewport.
381
+ _scanGlobalStep() {
382
+ const state = this._globalScanState;
383
+ if (!state || !state.nodes || state.idx >= state.nodes.length) {
384
+ this._globalScanState = null;
385
+ this._d('scan.done', {});
386
+ return;
387
+ }
388
+
389
+ const start = Utils.now();
390
+
391
+ while (state.idx < state.nodes.length) {
392
+ const code = state.nodes[state.idx++];
393
+ if (!code || !code.isConnected) continue;
394
+ if (state.activeCodeEl && code === state.activeCodeEl) continue;
395
+
396
+ try {
397
+ const r = code.getBoundingClientRect();
398
+ if (r.bottom >= state.rectTop && r.top <= state.rectBottom) this.queue(code, null);
399
+ } catch (_) {}
400
+
401
+ // Time-slice the scan to avoid long tasks.
402
+ if ((Utils.now() - start) >= this.SCAN_STEP_BUDGET_MS) {
403
+ this.raf.schedule('HL:scanStep', () => this._scanGlobalStep(), 'Highlighter', 2);
404
+ return;
405
+ }
406
+ }
407
+
408
+ this._globalScanState = null;
409
+ this._d('scan.step.end', {});
410
+ }
411
+
412
+ // Discover code nodes in the provided root and conditionally queue them.
413
+ // Attaches scroll handlers immediately; defers highlighting of the last streaming block if requested.
414
+ observeNewCode(root, opts, activeCode) {
415
+ const scope = root || document;
416
+
417
+ let nodes;
418
+ if (scope.nodeType === 1 && scope.closest && scope.closest('.msg-box.msg-bot')) nodes = scope.querySelectorAll('pre code');
419
+ else nodes = document.querySelectorAll('.msg-box.msg-bot pre code');
420
+ if (!nodes || !nodes.length) return;
421
+
422
+ const options = Object.assign({
423
+ deferLastIfStreaming: false,
424
+ minLinesForLast: 2,
425
+ minCharsForLast: 120
426
+ }, (opts || {}));
427
+
428
+ nodes.forEach((code) => {
429
+ if (!code.closest('.msg-box.msg-bot')) return;
430
+ // Ensure scroll behavior works even before highlighting.
431
+ this.codeScroll.attachHandlers(code);
432
+ if (this.isDisabled()) return;
433
+ if (activeCode && code === activeCode.codeEl) return;
434
+ // Optionally defer highlighting if the last block is still very short (still streaming).
435
+ if (options.deferLastIfStreaming && activeCode && code === activeCode.codeEl) {
436
+ const tailLen = (activeCode.tailEl && activeCode.tailEl.textContent) ? activeCode.tailEl.textContent.length : 0;
437
+ const tailLines = (typeof activeCode.tailLines === 'number') ? activeCode.tailLines : 0;
438
+ if (tailLines < options.minLinesForLast && tailLen < options.minCharsForLast) return;
439
+ }
440
+ if (this._nearViewport(code)) this.queue(code, activeCode);
441
+ });
442
+
443
+ this._d('observe.codes', {
444
+ count: nodes.length
445
+ });
446
+ }
447
+
448
+ // Schedule a global scan for visible code blocks. Coalesces repeated calls and
449
+ // resumes an in-flight scan if one is already running.
450
+ scheduleScanVisibleCodes(activeCode) {
451
+ if (this.isDisabled()) return;
452
+
453
+ // Quick existence check to avoid scheduling work when nothing is pending.
454
+ try {
455
+ const anyCandidate = document.querySelector('.msg-box.msg-bot pre code:not([data-highlighted="yes"])');
456
+ const hasActive = !!(activeCode && activeCode.codeEl && activeCode.codeEl.isConnected);
457
+ if (!anyCandidate && !hasActive) return;
458
+ } catch (_) {}
459
+
460
+ this._activeCodeEl = (activeCode && activeCode.codeEl) ? activeCode.codeEl : this._activeCodeEl;
461
+
462
+ if (this._globalScanState) {
463
+ // Continue the current incremental scan.
464
+ this.raf.schedule('HL:scanStep', () => this._scanGlobalStep(), 'Highlighter', 2);
465
+ return;
466
+ }
467
+ if (this.scanScheduled) return;
468
+
469
+ // Coalesce multiple requests into a single scheduled scan.
470
+ this.scanScheduled = true;
471
+ this.raf.schedule('HL:scan', () => {
472
+ this.scanScheduled = false;
473
+ this._startGlobalScan(activeCode || null);
474
+ }, 'Highlighter', 2);
475
+ this._d('scan.scheduled', {});
476
+ }
477
+
478
+ // Immediately perform a global scan (no coalescing). Primarily for imperative calls.
479
+ scanVisibleCodes(activeCode) {
480
+ this._startGlobalScan(activeCode || null);
481
+ }
482
+
483
+ // Scan only within a specific root element for visible code blocks and queue them.
484
+ scanVisibleCodesInRoot(root, activeCode) {
485
+ if (this.isDisabled()) return;
486
+
487
+ const preload = this.cfg.SCAN_PRELOAD_PX || this.cfg.SCAN.PRELOAD_PX;
488
+ const vh = window.innerHeight || Utils.SE.clientHeight || 800;
489
+ const rectTop = 0 - preload,
490
+ rectBottom = vh + preload;
491
+
492
+ const scope = root || document;
493
+ const nodes = scope.querySelectorAll('.msg-box.msg-bot pre code:not([data-highlighted="yes"])');
494
+
495
+ nodes.forEach((code) => {
496
+ if (!code.isConnected) return;
497
+ if (activeCode && code === activeCode.codeEl) return;
498
+ const r = code.getBoundingClientRect();
499
+ if (r.bottom >= rectTop && r.top <= rectBottom) this.queue(code, activeCode);
500
+ });
501
+
502
+ this._d('scan.root', {
503
+ count: nodes.length
504
+ });
505
+ }
506
+
507
+ // Placeholder for an IntersectionObserver-based optimization. Intentionally empty.
508
+ installBoxObserver() {
509
+ /* no-op */
510
+ }
511
+
512
+ // Iterate all bot message boxes within root and invoke the supplied callback.
513
+ observeMsgBoxes(root, onBoxIntersect) {
514
+ const scope = root || document;
515
+
516
+ let boxes;
517
+ if (scope.nodeType === 1) boxes = scope.querySelectorAll('.msg-box.msg-bot');
518
+ else boxes = document.querySelectorAll('.msg-box.msg-bot');
519
+
520
+ boxes.forEach((box) => {
521
+ onBoxIntersect && onBoxIntersect(box);
522
+ });
523
+ this._d('observe.boxes', {
524
+ count: boxes.length
525
+ });
526
+ }
527
+
528
+
529
+ // Cancel all scheduled tasks and clear internal state/queues.
530
+ cleanup() {
531
+ try {
532
+ this.raf.cancelGroup('Highlighter');
533
+ } catch (_) {}
534
+ this.hlScheduled = false;
535
+ this.scanScheduled = false;
536
+ this._globalScanState = null;
537
+ this._activeCodeEl = null;
538
+ this.hlQueueSet.clear();
539
+ this.hlQueue.length = 0;
540
+ this._d('cleanup', {});
541
+ }
542
+ }