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.
- pygpt_net/CHANGELOG.txt +11 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +26 -22
- pygpt_net/controller/audio/audio.py +0 -0
- pygpt_net/controller/calendar/calendar.py +0 -0
- pygpt_net/controller/calendar/note.py +0 -0
- pygpt_net/controller/chat/chat.py +0 -0
- pygpt_net/controller/chat/handler/openai_stream.py +2 -1
- pygpt_net/controller/chat/handler/worker.py +0 -0
- pygpt_net/controller/chat/remote_tools.py +0 -0
- pygpt_net/controller/chat/render.py +0 -0
- pygpt_net/controller/chat/text.py +0 -0
- pygpt_net/controller/ctx/common.py +0 -0
- pygpt_net/controller/debug/debug.py +26 -2
- pygpt_net/controller/debug/fixtures.py +1 -1
- pygpt_net/controller/dialogs/confirm.py +15 -1
- pygpt_net/controller/dialogs/debug.py +2 -0
- pygpt_net/controller/lang/mapping.py +0 -0
- pygpt_net/controller/launcher/launcher.py +0 -0
- pygpt_net/controller/mode/mode.py +0 -0
- pygpt_net/controller/presets/presets.py +0 -0
- pygpt_net/controller/realtime/realtime.py +0 -0
- pygpt_net/controller/theme/theme.py +0 -0
- pygpt_net/controller/ui/mode.py +0 -0
- pygpt_net/controller/ui/tabs.py +0 -0
- pygpt_net/core/agents/agents.py +3 -1
- pygpt_net/core/agents/custom.py +150 -0
- pygpt_net/core/agents/provider.py +0 -0
- pygpt_net/core/builder/__init__.py +12 -0
- pygpt_net/core/builder/graph.py +478 -0
- pygpt_net/core/calendar/calendar.py +0 -0
- pygpt_net/core/ctx/ctx.py +2 -1
- pygpt_net/core/ctx/output.py +0 -0
- pygpt_net/core/debug/agent.py +0 -0
- pygpt_net/core/debug/agent_builder.py +29 -0
- pygpt_net/core/debug/console/console.py +0 -0
- pygpt_net/core/debug/db.py +0 -0
- pygpt_net/core/debug/debug.py +0 -0
- pygpt_net/core/debug/events.py +0 -0
- pygpt_net/core/debug/indexes.py +0 -0
- pygpt_net/core/debug/kernel.py +0 -0
- pygpt_net/core/debug/tabs.py +0 -0
- pygpt_net/core/filesystem/filesystem.py +0 -0
- pygpt_net/core/fixtures/__init__ +0 -0
- pygpt_net/core/fixtures/stream/__init__.py +0 -0
- pygpt_net/core/fixtures/stream/generator.py +0 -0
- pygpt_net/core/models/models.py +0 -0
- pygpt_net/core/render/plain/pid.py +0 -0
- pygpt_net/core/render/plain/renderer.py +26 -4
- pygpt_net/core/render/web/body.py +46 -4
- pygpt_net/core/render/web/debug.py +0 -0
- pygpt_net/core/render/web/helpers.py +0 -0
- pygpt_net/core/render/web/pid.py +0 -0
- pygpt_net/core/render/web/renderer.py +15 -20
- pygpt_net/core/tabs/tab.py +0 -0
- pygpt_net/core/tabs/tabs.py +0 -0
- pygpt_net/core/text/utils.py +0 -0
- pygpt_net/css.qrc +0 -0
- pygpt_net/css_rc.py +0 -0
- pygpt_net/data/config/config.json +7 -7
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/css/web-blocks.css +9 -0
- pygpt_net/data/css/web-blocks.dark.css +6 -0
- pygpt_net/data/css/web-blocks.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.css +14 -6
- pygpt_net/data/css/web-chatgpt.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt.light.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.css +14 -6
- pygpt_net/data/css/web-chatgpt_wide.dark.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.darkest.css +6 -0
- pygpt_net/data/css/web-chatgpt_wide.light.css +6 -0
- pygpt_net/data/fixtures/fake_stream.txt +14 -1
- pygpt_net/data/icons/case.svg +0 -0
- pygpt_net/data/icons/chat1.svg +0 -0
- pygpt_net/data/icons/chat2.svg +0 -0
- pygpt_net/data/icons/chat3.svg +0 -0
- pygpt_net/data/icons/chat4.svg +0 -0
- pygpt_net/data/icons/fit.svg +0 -0
- pygpt_net/data/icons/note1.svg +0 -0
- pygpt_net/data/icons/note2.svg +0 -0
- pygpt_net/data/icons/note3.svg +0 -0
- pygpt_net/data/icons/stt.svg +0 -0
- pygpt_net/data/icons/translate.svg +0 -0
- pygpt_net/data/icons/tts.svg +0 -0
- pygpt_net/data/icons/url.svg +0 -0
- pygpt_net/data/icons/vision.svg +0 -0
- pygpt_net/data/icons/web_off.svg +0 -0
- pygpt_net/data/icons/web_on.svg +0 -0
- pygpt_net/data/js/app/async.js +166 -0
- pygpt_net/data/js/app/bridge.js +88 -0
- pygpt_net/data/js/app/common.js +212 -0
- pygpt_net/data/js/app/config.js +223 -0
- pygpt_net/data/js/app/custom.js +961 -0
- pygpt_net/data/js/app/data.js +84 -0
- pygpt_net/data/js/app/dom.js +322 -0
- pygpt_net/data/js/app/events.js +400 -0
- pygpt_net/data/js/app/highlight.js +542 -0
- pygpt_net/data/js/app/logger.js +305 -0
- pygpt_net/data/js/app/markdown.js +1137 -0
- pygpt_net/data/js/app/math.js +167 -0
- pygpt_net/data/js/app/nodes.js +395 -0
- pygpt_net/data/js/app/queue.js +260 -0
- pygpt_net/data/js/app/raf.js +250 -0
- pygpt_net/data/js/app/runtime.js +582 -0
- pygpt_net/data/js/app/scroll.js +433 -0
- pygpt_net/data/js/app/stream.js +2708 -0
- pygpt_net/data/js/app/template.js +287 -0
- pygpt_net/data/js/app/tool.js +87 -0
- pygpt_net/data/js/app/ui.js +86 -0
- pygpt_net/data/js/app/user.js +380 -0
- pygpt_net/data/js/app/utils.js +64 -0
- pygpt_net/data/js/app.min.js +880 -0
- pygpt_net/data/js/markdown-it/markdown-it-katex.min.js +1 -1
- pygpt_net/data/js/markdown-it/markdown-it.min.js +0 -0
- pygpt_net/data/locale/locale.de.ini +0 -0
- pygpt_net/data/locale/locale.en.ini +7 -0
- pygpt_net/data/locale/locale.es.ini +0 -0
- pygpt_net/data/locale/locale.fr.ini +0 -0
- pygpt_net/data/locale/locale.it.ini +0 -0
- pygpt_net/data/locale/locale.pl.ini +0 -0
- pygpt_net/data/locale/locale.uk.ini +0 -0
- pygpt_net/data/locale/locale.zh.ini +0 -0
- pygpt_net/data/locale/plugin.agent.de.ini +0 -0
- pygpt_net/data/locale/plugin.agent.en.ini +0 -0
- pygpt_net/data/locale/plugin.agent.es.ini +0 -0
- pygpt_net/data/locale/plugin.agent.fr.ini +0 -0
- pygpt_net/data/locale/plugin.agent.it.ini +0 -0
- pygpt_net/data/locale/plugin.agent.pl.ini +0 -0
- pygpt_net/data/locale/plugin.agent.uk.ini +0 -0
- pygpt_net/data/locale/plugin.agent.zh.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.de.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.en.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.es.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.fr.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.it.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.pl.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.uk.ini +0 -0
- pygpt_net/data/locale/plugin.audio_input.zh.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.de.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.en.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.es.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.fr.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.it.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.pl.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.uk.ini +0 -0
- pygpt_net/data/locale/plugin.audio_output.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_api.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_custom.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_files.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_history.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_mouse_control.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_serial.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_system.zh.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.de.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.en.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.es.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.it.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +0 -0
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.de.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.en.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.es.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.fr.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.it.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.pl.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.uk.ini +0 -0
- pygpt_net/data/locale/plugin.crontab.zh.ini +0 -0
- pygpt_net/data/locale/plugin.experts.de.ini +0 -0
- pygpt_net/data/locale/plugin.experts.en.ini +0 -0
- pygpt_net/data/locale/plugin.experts.es.ini +0 -0
- pygpt_net/data/locale/plugin.experts.fr.ini +0 -0
- pygpt_net/data/locale/plugin.experts.it.ini +0 -0
- pygpt_net/data/locale/plugin.experts.pl.ini +0 -0
- pygpt_net/data/locale/plugin.experts.uk.ini +0 -0
- pygpt_net/data/locale/plugin.experts.zh.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.de.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.en.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.es.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.fr.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.it.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.pl.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.uk.ini +0 -0
- pygpt_net/data/locale/plugin.extra_prompt.zh.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.de.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.en.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.es.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.it.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +0 -0
- pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +0 -0
- pygpt_net/data/locale/plugin.mailer.en.ini +0 -0
- pygpt_net/data/locale/plugin.mcp.en.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.de.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.en.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.es.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.fr.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.it.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.pl.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.uk.ini +0 -0
- pygpt_net/data/locale/plugin.openai_dalle.zh.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.de.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.en.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.es.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.fr.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.it.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.pl.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.uk.ini +0 -0
- pygpt_net/data/locale/plugin.openai_vision.zh.ini +0 -0
- pygpt_net/data/locale/plugin.osm.en.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.de.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.en.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.es.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.fr.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.it.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.pl.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.uk.ini +0 -0
- pygpt_net/data/locale/plugin.real_time.zh.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.de.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.en.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.es.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.fr.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.it.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.pl.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.uk.ini +0 -0
- pygpt_net/data/locale/plugin.voice_control.zh.ini +0 -0
- pygpt_net/data/locale/plugin.wolfram.en.ini +0 -0
- pygpt_net/fonts.qrc +0 -0
- pygpt_net/fonts_rc.py +0 -0
- pygpt_net/icons.qrc +0 -0
- pygpt_net/icons_rc.py +0 -0
- pygpt_net/item/agent.py +62 -0
- pygpt_net/item/builder_layout.py +62 -0
- pygpt_net/js.qrc +24 -1
- pygpt_net/js_rc.py +51394 -33687
- pygpt_net/plugin/base/worker.py +0 -0
- pygpt_net/plugin/mcp/__init__.py +0 -0
- pygpt_net/plugin/mcp/config.py +0 -0
- pygpt_net/plugin/mcp/plugin.py +0 -0
- pygpt_net/plugin/mcp/worker.py +0 -0
- pygpt_net/plugin/osm/__init__.py +0 -0
- pygpt_net/plugin/osm/config.py +0 -0
- pygpt_net/plugin/osm/plugin.py +0 -0
- pygpt_net/plugin/osm/worker.py +0 -0
- pygpt_net/plugin/wolfram/__init__.py +0 -0
- pygpt_net/plugin/wolfram/config.py +0 -0
- pygpt_net/plugin/wolfram/plugin.py +0 -0
- pygpt_net/plugin/wolfram/worker.py +0 -0
- pygpt_net/provider/api/anthropic/tools.py +0 -0
- pygpt_net/provider/api/google/__init__.py +0 -0
- pygpt_net/provider/api/google/video.py +0 -0
- pygpt_net/provider/api/openai/agents/experts.py +0 -0
- pygpt_net/provider/api/openai/agents/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/remote_tools.py +0 -0
- pygpt_net/provider/api/openai/responses.py +0 -0
- pygpt_net/provider/api/x_ai/__init__.py +0 -0
- pygpt_net/provider/api/x_ai/remote.py +0 -0
- pygpt_net/provider/core/agent/__init__.py +10 -0
- pygpt_net/provider/core/agent/base.py +51 -0
- pygpt_net/provider/core/agent/json_file.py +200 -0
- pygpt_net/provider/core/config/patch.py +18 -0
- pygpt_net/provider/core/config/patches/__init__.py +0 -0
- pygpt_net/provider/core/config/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +0 -0
- pygpt_net/provider/core/model/patches/__init__.py +0 -0
- pygpt_net/provider/core/model/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/core/preset/patch.py +0 -0
- pygpt_net/provider/core/preset/patches/__init__.py +0 -0
- pygpt_net/provider/core/preset/patches/patch_before_2_6_42.py +0 -0
- pygpt_net/provider/llms/base.py +0 -0
- pygpt_net/provider/llms/deepseek_api.py +0 -0
- pygpt_net/provider/llms/google.py +0 -0
- pygpt_net/provider/llms/hugging_face_api.py +0 -0
- pygpt_net/provider/llms/hugging_face_embedding.py +0 -0
- pygpt_net/provider/llms/hugging_face_router.py +0 -0
- pygpt_net/provider/llms/local.py +0 -0
- pygpt_net/provider/llms/mistral.py +0 -0
- pygpt_net/provider/llms/open_router.py +0 -0
- pygpt_net/provider/llms/perplexity.py +0 -0
- pygpt_net/provider/llms/utils.py +0 -0
- pygpt_net/provider/llms/voyage.py +0 -0
- pygpt_net/provider/llms/x_ai.py +0 -0
- pygpt_net/tools/agent_builder/__init__.py +12 -0
- pygpt_net/tools/agent_builder/tool.py +292 -0
- pygpt_net/tools/agent_builder/ui/__init__.py +0 -0
- pygpt_net/tools/agent_builder/ui/dialogs.py +152 -0
- pygpt_net/tools/agent_builder/ui/list.py +228 -0
- pygpt_net/tools/code_interpreter/ui/html.py +0 -0
- pygpt_net/tools/code_interpreter/ui/widgets.py +0 -0
- pygpt_net/tools/html_canvas/tool.py +23 -6
- pygpt_net/tools/html_canvas/ui/widgets.py +224 -2
- pygpt_net/ui/layout/chat/chat.py +0 -0
- pygpt_net/ui/main.py +10 -9
- pygpt_net/ui/menu/debug.py +39 -1
- pygpt_net/ui/widget/builder/__init__.py +12 -0
- pygpt_net/ui/widget/builder/editor.py +2001 -0
- pygpt_net/ui/widget/draw/painter.py +0 -0
- pygpt_net/ui/widget/element/labels.py +9 -4
- pygpt_net/ui/widget/lists/db.py +0 -0
- pygpt_net/ui/widget/lists/debug.py +0 -0
- pygpt_net/ui/widget/tabs/body.py +0 -0
- pygpt_net/ui/widget/textarea/input.py +17 -8
- pygpt_net/ui/widget/textarea/output.py +21 -1
- pygpt_net/ui/widget/textarea/web.py +29 -2
- pygpt_net/utils.py +40 -0
- {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/METADATA +13 -2
- {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/RECORD +86 -47
- pygpt_net/data/js/app.js +0 -5869
- {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.54.dist-info → pygpt_net-2.6.56.dist-info}/WHEEL +0 -0
- {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('&', '&')
|
|
211
|
+
.replaceAll('<', '<')
|
|
212
|
+
.replaceAll('>', '>')
|
|
213
|
+
.replaceAll('"', '"')
|
|
214
|
+
.replaceAll(''', "'");
|
|
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
|
+
}
|