pygpt-net 2.6.55__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 +6 -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 +0 -0
- 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 +9 -7
- 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.55.dist-info → pygpt_net-2.6.56.dist-info}/METADATA +8 -2
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.56.dist-info}/RECORD +85 -46
- pygpt_net/data/js/app.js +0 -5869
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.56.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.56.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.55.dist-info → pygpt_net-2.6.56.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Async runner (cooperative yielding for heavy tasks)
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
class AsyncRunner {
|
|
6
|
+
|
|
7
|
+
// Cooperative scheduler (rAF-based) for CPU-heavy tasks (keeps UI responsive).
|
|
8
|
+
constructor(cfg, raf) {
|
|
9
|
+
this.cfg = cfg || {};
|
|
10
|
+
this.raf = raf || null;
|
|
11
|
+
|
|
12
|
+
const A = this.cfg.ASYNC || {};
|
|
13
|
+
// Base time budget for a slice when the page is visible.
|
|
14
|
+
this.SLICE_MS = Utils.g('ASYNC_SLICE_MS', A.SLICE_MS ?? 12);
|
|
15
|
+
// Optional hidden-page tighter budget (yield more aggressively when tab is hidden).
|
|
16
|
+
this.SLICE_HIDDEN_MS = Utils.g('ASYNC_SLICE_HIDDEN_MS', A.SLICE_HIDDEN_MS ?? Math.min(this.SLICE_MS, 6));
|
|
17
|
+
// Kept only for config compatibility (no-op in logic).
|
|
18
|
+
this.MIN_YIELD_MS = Utils.g('ASYNC_MIN_YIELD_MS', A.MIN_YIELD_MS ?? 0);
|
|
19
|
+
|
|
20
|
+
// Per-label operation generations (lets us cancel superseded passes cooperatively).
|
|
21
|
+
this._opGen = new Map(); // label -> number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Returns true if we should yield control (input pending or time budget exceeded).
|
|
25
|
+
shouldYield(startTs) {
|
|
26
|
+
// If the browser has pending input, yield immediately.
|
|
27
|
+
try {
|
|
28
|
+
const s = navigator && navigator.scheduling;
|
|
29
|
+
if (s && s.isInputPending && s.isInputPending({ includeContinuous: true })) return true;
|
|
30
|
+
} catch (_) {}
|
|
31
|
+
|
|
32
|
+
const now = Utils.now();
|
|
33
|
+
const hidden = (typeof document !== 'undefined' && document.visibilityState === 'hidden');
|
|
34
|
+
const budget = hidden ? this.SLICE_HIDDEN_MS : this.SLICE_MS;
|
|
35
|
+
return (now - startTs) >= budget;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Yield cooperatively to the next frame (rAF). Falls back to rAF or a minimal timer.
|
|
39
|
+
async yield() {
|
|
40
|
+
// Prefer the shared RafManager to avoid extra tasks and to coalesce with the app's rAF pump.
|
|
41
|
+
if (this.raf && typeof this.raf.nextFrame === 'function') {
|
|
42
|
+
await this.raf.nextFrame();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Fallback to plain requestAnimationFrame if available.
|
|
46
|
+
if (typeof requestAnimationFrame === 'function') {
|
|
47
|
+
await new Promise(res => {
|
|
48
|
+
try { requestAnimationFrame(() => res()); }
|
|
49
|
+
catch (_) { setTimeout(res, 16); }
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Final fallback (should not generally happen in QWebEngine).
|
|
54
|
+
await new Promise(res => setTimeout(res, 16));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Optional: yield to idle. Uses requestIdleCallback if available, falls back to yield().
|
|
58
|
+
async yieldIdle(timeoutMs = 100) {
|
|
59
|
+
if (typeof requestIdleCallback === 'function') {
|
|
60
|
+
await new Promise(res => {
|
|
61
|
+
try { requestIdleCallback(() => res(), { timeout: timeoutMs }); }
|
|
62
|
+
catch (_) { res(); }
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await this.yield();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Internal: start a new generation for a label; future calls with a higher gen supersede older loops.
|
|
70
|
+
_beginOp(label) {
|
|
71
|
+
if (!label) return 0;
|
|
72
|
+
const g = (this._opGen.get(label) || 0) + 1;
|
|
73
|
+
this._opGen.set(label, g);
|
|
74
|
+
return g;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Internal: check if a label/gen pair is still the latest (not superseded).
|
|
78
|
+
_isLatest(label, gen) {
|
|
79
|
+
if (!label) return true;
|
|
80
|
+
return (this._opGen.get(label) === gen);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Cancel all in-flight loops for a given label (cooperative; next yield will abort them).
|
|
84
|
+
cancel(label) {
|
|
85
|
+
if (!label) return;
|
|
86
|
+
const g = (this._opGen.get(label) || 0) + 1;
|
|
87
|
+
this._opGen.set(label, g);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Process an array in small slices with periodic yields.
|
|
91
|
+
// Options (4th param OR instead of label):
|
|
92
|
+
// { batch=1, release=false, signal, onProgress }:
|
|
93
|
+
// - batch: process N items per inner loop before checking shouldYield()
|
|
94
|
+
// - release: if true, set arr[i] = undefined after processing (helps GC for very large arrays)
|
|
95
|
+
// - signal: AbortSignal to cancel early
|
|
96
|
+
// - onProgress: callback({ index, total }) invoked after each processed item (throttled by batch)
|
|
97
|
+
async forEachChunk(arr, fn, labelOrOpts) {
|
|
98
|
+
if (!arr || !arr.length) return;
|
|
99
|
+
|
|
100
|
+
// Parse args for back-compat: label (string) or options object.
|
|
101
|
+
let label = (typeof labelOrOpts === 'string') ? labelOrOpts : (labelOrOpts && labelOrOpts.label) || undefined;
|
|
102
|
+
const opts = (label && typeof labelOrOpts === 'object')
|
|
103
|
+
? { ...labelOrOpts, label }
|
|
104
|
+
: (typeof labelOrOpts === 'object' ? labelOrOpts : {});
|
|
105
|
+
|
|
106
|
+
const batch = Math.max(1, opts.batch | 0 || 1);
|
|
107
|
+
const release = !!opts.release;
|
|
108
|
+
const signal = opts.signal;
|
|
109
|
+
const onProgress = (typeof opts.onProgress === 'function') ? opts.onProgress : null;
|
|
110
|
+
|
|
111
|
+
const gen = this._beginOp(label);
|
|
112
|
+
const total = arr.length;
|
|
113
|
+
let start = Utils.now();
|
|
114
|
+
let processedInBatch = 0;
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < total; i++) {
|
|
117
|
+
// Cancellation via AbortSignal or superseded generation (e.g., new render pass started).
|
|
118
|
+
if ((signal && signal.aborted) || !this._isLatest(label, gen)) break;
|
|
119
|
+
|
|
120
|
+
await fn(arr[i], i);
|
|
121
|
+
|
|
122
|
+
if (release) {
|
|
123
|
+
// Clear strong reference to the processed item to help GC on massive arrays.
|
|
124
|
+
try { arr[i] = undefined; } catch (_) {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
processedInBatch++;
|
|
128
|
+
if (onProgress) {
|
|
129
|
+
// Call progress hook at most once per item (cheap); caller may throttle if needed.
|
|
130
|
+
try { onProgress({ index: i + 1, total }); } catch (_) {}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (processedInBatch >= batch || this.shouldYield(start)) {
|
|
134
|
+
processedInBatch = 0;
|
|
135
|
+
await this.yield();
|
|
136
|
+
start = Utils.now();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Chunked map with cooperative yielding. Returns a new array of results.
|
|
142
|
+
// Options same as forEachChunk; accepts AbortSignal/label/batch/release/onProgress.
|
|
143
|
+
async mapChunked(arr, mapper, labelOrOpts) {
|
|
144
|
+
if (!arr || !arr.length) return [];
|
|
145
|
+
const out = new Array(arr.length);
|
|
146
|
+
let idx = 0;
|
|
147
|
+
await this.forEachChunk(
|
|
148
|
+
arr,
|
|
149
|
+
async (v, i) => { out[i] = await mapper(v, i); idx = i; },
|
|
150
|
+
labelOrOpts
|
|
151
|
+
);
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Chunked reduce with cooperative yielding.
|
|
156
|
+
// reducer(acc, value, index) -> acc
|
|
157
|
+
async reduceChunked(arr, reducer, initial, labelOrOpts) {
|
|
158
|
+
let acc = initial;
|
|
159
|
+
await this.forEachChunk(
|
|
160
|
+
arr,
|
|
161
|
+
async (v, i) => { acc = await reducer(acc, v, i); },
|
|
162
|
+
labelOrOpts
|
|
163
|
+
);
|
|
164
|
+
return acc;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Bridge manager
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
class BridgeManager {
|
|
6
|
+
|
|
7
|
+
// Manages the connection to the bridge
|
|
8
|
+
constructor(cfg, logger) {
|
|
9
|
+
this.cfg = cfg;
|
|
10
|
+
this.logger = logger || new Logger(cfg);
|
|
11
|
+
this.bridge = null;
|
|
12
|
+
this.connected = false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Log messages to the bridge
|
|
16
|
+
log(text) {
|
|
17
|
+
try {
|
|
18
|
+
if (this.bridge && this.bridge.log) this.bridge.log(text);
|
|
19
|
+
} catch (_) {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Connect to the bridge
|
|
23
|
+
connect(onChunk, onNode, onNodeReplace, onNodeInput) {
|
|
24
|
+
if (!this.bridge) return false;
|
|
25
|
+
if (this.connected) return true;
|
|
26
|
+
try {
|
|
27
|
+
if (this.bridge.chunk) this.bridge.chunk.connect((name, chunk, type) => onChunk(name, chunk, type));
|
|
28
|
+
if (this.bridge.node) this.bridge.node.connect(onNode);
|
|
29
|
+
if (this.bridge.nodeReplace) this.bridge.nodeReplace.connect(onNodeReplace);
|
|
30
|
+
if (this.bridge.nodeInput) this.bridge.nodeInput.connect(onNodeInput);
|
|
31
|
+
this.connected = true;
|
|
32
|
+
return true;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
this.log(e);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Disconnect from the bridge
|
|
40
|
+
disconnect() {
|
|
41
|
+
if (!this.bridge) return false;
|
|
42
|
+
if (!this.connected) return true;
|
|
43
|
+
try {
|
|
44
|
+
if (this.bridge.chunk) this.bridge.chunk.disconnect();
|
|
45
|
+
if (this.bridge.node) this.bridge.node.disconnect();
|
|
46
|
+
if (this.bridge.nodeReplace) this.bridge.nodeReplace.disconnect();
|
|
47
|
+
if (this.bridge.nodeInput) this.bridge.nodeInput.disconnect();
|
|
48
|
+
} catch (_) {}
|
|
49
|
+
this.connected = false;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Initialize the QWebChannel
|
|
54
|
+
initQWebChannel(pid, onReady) {
|
|
55
|
+
try {
|
|
56
|
+
new QWebChannel(qt.webChannelTransport, (channel) => {
|
|
57
|
+
this.bridge = channel.objects.bridge;
|
|
58
|
+
try {
|
|
59
|
+
this.logger.bindBridge(this.bridge);
|
|
60
|
+
} catch (_) {}
|
|
61
|
+
onReady && onReady(this.bridge);
|
|
62
|
+
if (this.bridge && this.bridge.js_ready) this.bridge.js_ready(pid);
|
|
63
|
+
});
|
|
64
|
+
} catch (e) {
|
|
65
|
+
/* swallow */
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Copy code to the bridge
|
|
70
|
+
copyCode(text) {
|
|
71
|
+
if (this.bridge && this.bridge.copy_text) this.bridge.copy_text(text);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Preview code in the bridge
|
|
75
|
+
previewCode(text) {
|
|
76
|
+
if (this.bridge && this.bridge.preview_text) this.bridge.preview_text(text);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Run code in the bridge
|
|
80
|
+
runCode(text) {
|
|
81
|
+
if (this.bridge && this.bridge.run_text) this.bridge.run_text(text);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Update the scroll position in the bridge
|
|
85
|
+
updateScrollPosition(pos) {
|
|
86
|
+
if (this.bridge && this.bridge.update_scroll_position) this.bridge.update_scroll_position(pos);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Loading indicator
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
class Loading {
|
|
6
|
+
|
|
7
|
+
// Loading indicator spinner
|
|
8
|
+
constructor(dom) {
|
|
9
|
+
this.dom = dom;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Show loader element (and hide tips if visible).
|
|
13
|
+
show() {
|
|
14
|
+
if (typeof window.hideTips === 'function') {
|
|
15
|
+
window.hideTips();
|
|
16
|
+
}
|
|
17
|
+
const el = this.dom.get('_loader_');
|
|
18
|
+
if (!el) return;
|
|
19
|
+
if (el.classList.contains('hidden')) el.classList.remove('hidden');
|
|
20
|
+
el.classList.add('visible');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Hide loader element.
|
|
24
|
+
hide() {
|
|
25
|
+
const el = this.dom.get('_loader_');
|
|
26
|
+
if (!el) return;
|
|
27
|
+
if (el.classList.contains('visible')) el.classList.remove('visible');
|
|
28
|
+
el.classList.add('hidden');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ==========================================================================
|
|
33
|
+
// Tips manager
|
|
34
|
+
// ==========================================================================
|
|
35
|
+
|
|
36
|
+
class TipsManager {
|
|
37
|
+
|
|
38
|
+
// Lightweight tips rotator that works with your CSS (.tips/.visible)
|
|
39
|
+
// and is backward-compatible with legacy `let tips = [...]` injection.
|
|
40
|
+
constructor(dom) {
|
|
41
|
+
this.dom = dom;
|
|
42
|
+
this.hidden = false;
|
|
43
|
+
this._timers = [];
|
|
44
|
+
this._running = false;
|
|
45
|
+
this._idx = 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Resolve tips list from multiple legacy/new sources.
|
|
49
|
+
_getList() {
|
|
50
|
+
// New preferred: window.TIPS (array)
|
|
51
|
+
const upper = (typeof window !== 'undefined') ? window.TIPS : undefined;
|
|
52
|
+
if (Array.isArray(upper) && upper.length) return upper;
|
|
53
|
+
|
|
54
|
+
// Legacy inline: window.tips (array or JSON string)
|
|
55
|
+
const lower = (typeof window !== 'undefined') ? window.tips : undefined;
|
|
56
|
+
if (Array.isArray(lower) && lower.length) return lower;
|
|
57
|
+
if (typeof lower === 'string' && lower.trim().length) {
|
|
58
|
+
try {
|
|
59
|
+
const arr = JSON.parse(lower);
|
|
60
|
+
if (Array.isArray(arr)) return arr;
|
|
61
|
+
} catch (_) {}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Optional: data-tips='["...","..."]' on #tips
|
|
65
|
+
const host = this._host();
|
|
66
|
+
if (host && host.dataset && typeof host.dataset.tips === 'string') {
|
|
67
|
+
try {
|
|
68
|
+
const arr = JSON.parse(host.dataset.tips);
|
|
69
|
+
if (Array.isArray(arr)) return arr;
|
|
70
|
+
} catch (_) {}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Get the tips container element.
|
|
77
|
+
_host() {
|
|
78
|
+
return this.dom.get('tips') || document.getElementById('tips');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Clear all timers.
|
|
82
|
+
_clearTimers() {
|
|
83
|
+
for (const t of this._timers) {
|
|
84
|
+
try {
|
|
85
|
+
clearTimeout(t);
|
|
86
|
+
} catch (_) {}
|
|
87
|
+
}
|
|
88
|
+
this._timers.length = 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Stop any running rotation timers.
|
|
92
|
+
stopTimers() {
|
|
93
|
+
this._clearTimers();
|
|
94
|
+
this._running = false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Apply base styles to the tips container.
|
|
98
|
+
_applyBaseStyle(el) {
|
|
99
|
+
if (!el) return;
|
|
100
|
+
// Keep your flex layout and sizing; do not overwrite width/height.
|
|
101
|
+
// Ensure it renders above other layers.
|
|
102
|
+
const z = (typeof window !== 'undefined' && typeof window.TIPS_ZINDEX !== 'undefined') ?
|
|
103
|
+
String(window.TIPS_ZINDEX) : '2147483000';
|
|
104
|
+
el.style.zIndex = z;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Hide tips layer and stop rotation.
|
|
108
|
+
hide() {
|
|
109
|
+
if (this.hidden) return;
|
|
110
|
+
this.stopTimers();
|
|
111
|
+
const el = this._host();
|
|
112
|
+
if (el) {
|
|
113
|
+
// Remove visibility class and hide hard (used when stream starts etc.)
|
|
114
|
+
el.classList.remove('visible');
|
|
115
|
+
el.classList.remove('hidden'); // in case it was set elsewhere
|
|
116
|
+
el.style.display = 'none';
|
|
117
|
+
}
|
|
118
|
+
this.hidden = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Show tips layer (does not start rotation).
|
|
122
|
+
show() {
|
|
123
|
+
const list = this._getList();
|
|
124
|
+
if (!list.length) return;
|
|
125
|
+
const el = this._host();
|
|
126
|
+
if (!el) return;
|
|
127
|
+
|
|
128
|
+
this.hidden = false;
|
|
129
|
+
this._applyBaseStyle(el);
|
|
130
|
+
el.classList.remove('hidden');
|
|
131
|
+
el.style.display = 'block'; // CSS handles opacity via .tips/.visible
|
|
132
|
+
// Do not add 'visible' yet – cycle() takes care of fade-in steps.
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Show one tip (by index) and fade it in next frame.
|
|
136
|
+
_showOne(idx) {
|
|
137
|
+
const list = this._getList();
|
|
138
|
+
if (!list.length) return;
|
|
139
|
+
const el = this._host();
|
|
140
|
+
if (!el || this.hidden) return;
|
|
141
|
+
|
|
142
|
+
this._applyBaseStyle(el);
|
|
143
|
+
el.innerHTML = list[idx % list.length];
|
|
144
|
+
|
|
145
|
+
// Centralize "next-frame" visibility toggle through RafManager to guarantee CSS transition.
|
|
146
|
+
try {
|
|
147
|
+
if (typeof runtime !== 'undefined' && runtime.raf && typeof runtime.raf.schedule === 'function') {
|
|
148
|
+
const key = {
|
|
149
|
+
t: 'Tips:show',
|
|
150
|
+
el,
|
|
151
|
+
i: Math.random()
|
|
152
|
+
};
|
|
153
|
+
runtime.raf.schedule(key, () => {
|
|
154
|
+
if (this.hidden || !el.isConnected) return;
|
|
155
|
+
el.classList.add('visible');
|
|
156
|
+
}, 'Tips', 2);
|
|
157
|
+
} else {
|
|
158
|
+
// Fallback: no frame delay – still functional, transition may not play.
|
|
159
|
+
el.classList.add('visible');
|
|
160
|
+
}
|
|
161
|
+
} catch (_) {
|
|
162
|
+
el.classList.add('visible');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Internal loop: show, wait, hide, wait fade, next.
|
|
167
|
+
_cycleLoop() {
|
|
168
|
+
if (this.hidden) return;
|
|
169
|
+
const el = this._host();
|
|
170
|
+
if (!el) return;
|
|
171
|
+
|
|
172
|
+
const VISIBLE_MS = (typeof window !== 'undefined' && window.TIPS_VISIBLE_MS) ? window.TIPS_VISIBLE_MS : 15000;
|
|
173
|
+
const FADE_MS = (typeof window !== 'undefined' && window.TIPS_FADE_MS) ? window.TIPS_FADE_MS : 1000;
|
|
174
|
+
|
|
175
|
+
this._showOne(this._idx);
|
|
176
|
+
|
|
177
|
+
// Sequence: visible -> wait -> remove 'visible' -> wait fade -> next
|
|
178
|
+
this._timers.push(setTimeout(() => {
|
|
179
|
+
if (this.hidden) return;
|
|
180
|
+
el.classList.remove('visible');
|
|
181
|
+
this._timers.push(setTimeout(() => {
|
|
182
|
+
if (this.hidden) return;
|
|
183
|
+
const list = this._getList();
|
|
184
|
+
if (!list.length) return;
|
|
185
|
+
this._idx = (this._idx + 1) % list.length;
|
|
186
|
+
this._cycleLoop();
|
|
187
|
+
}, FADE_MS));
|
|
188
|
+
}, VISIBLE_MS));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Start rotation with initial delay.
|
|
192
|
+
cycle() {
|
|
193
|
+
const list = this._getList();
|
|
194
|
+
if (!list.length || this._running) return;
|
|
195
|
+
this._running = true;
|
|
196
|
+
this._idx = 0;
|
|
197
|
+
this.show(); // make sure the host is visible and centered
|
|
198
|
+
|
|
199
|
+
const INIT_DELAY = (typeof window !== 'undefined' && window.TIPS_INIT_DELAY_MS) ? window.TIPS_INIT_DELAY_MS : 10000;
|
|
200
|
+
this._timers.push(setTimeout(() => {
|
|
201
|
+
if (this.hidden) return;
|
|
202
|
+
this._cycleLoop();
|
|
203
|
+
}, Math.max(0, INIT_DELAY)));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Stop and reset.
|
|
207
|
+
cleanup() {
|
|
208
|
+
this.stopTimers();
|
|
209
|
+
const el = this._host();
|
|
210
|
+
if (el) el.classList.remove('visible');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Config
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
class Config {
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
// Process identifier (passed from host).
|
|
9
|
+
this.PID = Utils.g('PID', 0);
|
|
10
|
+
|
|
11
|
+
// UI: scroll behavior and busy/zoom signalling thresholds (milliseconds / pixels).
|
|
12
|
+
this.UI = {
|
|
13
|
+
AUTO_FOLLOW_REENABLE_PX: Utils.g('AUTO_FOLLOW_REENABLE_PX', 8),
|
|
14
|
+
SCROLL_NEAR_MARGIN_PX: Utils.g('SCROLL_NEAR_MARGIN_PX', 450),
|
|
15
|
+
INTERACTION_BUSY_MS: Utils.g('UI_INTERACTION_BUSY_MS', 140),
|
|
16
|
+
ZOOM_BUSY_MS: Utils.g('UI_ZOOM_BUSY_MS', 300)
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// FAB (floating action button) visibility and debounce.
|
|
20
|
+
this.FAB = {
|
|
21
|
+
SHOW_DOWN_THRESHOLD_PX: Utils.g('SHOW_DOWN_THRESHOLD_PX', 0),
|
|
22
|
+
TOGGLE_DEBOUNCE_MS: Utils.g('FAB_TOGGLE_DEBOUNCE_MS', 100)
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Highlighting controls and per-frame budget.
|
|
26
|
+
this.HL = {
|
|
27
|
+
PER_FRAME: Utils.g('HL_PER_FRAME', 2),
|
|
28
|
+
DISABLE_ALL: Utils.g('DISABLE_SYNTAX_HIGHLIGHT', false)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Intersection-like margins (we do our own scan, but these guide budgets).
|
|
32
|
+
this.OBSERVER = {
|
|
33
|
+
CODE_ROOT_MARGIN: Utils.g('CODE_ROOT_MARGIN', '1000px 0px 1000px 0px'),
|
|
34
|
+
BOX_ROOT_MARGIN: Utils.g('BOX_ROOT_MARGIN', '1500px 0px 1500px 0px'),
|
|
35
|
+
CODE_THRESHOLD: [0, 0.001],
|
|
36
|
+
BOX_THRESHOLD: 0
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Viewport scan preload distance (in pixels).
|
|
40
|
+
this.SCAN = {
|
|
41
|
+
PRELOAD_PX: Utils.g('SCAN_PRELOAD_PX', 1000)
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Code scroll behavior (auto-follow re-enable margin and near-bottom margin).
|
|
45
|
+
this.CODE_SCROLL = {
|
|
46
|
+
AUTO_FOLLOW_REENABLE_PX: Utils.g('CODE_AUTO_FOLLOW_REENABLE_PX', 8),
|
|
47
|
+
NEAR_MARGIN_PX: Utils.g('CODE_SCROLL_NEAR_MARGIN_PX', 48)
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Stream (snapshot) budgets and queue limits.
|
|
51
|
+
this.STREAM = {
|
|
52
|
+
MAX_PER_FRAME: Utils.g('STREAM_MAX_PER_FRAME', 8),
|
|
53
|
+
EMERGENCY_COALESCE_LEN: Utils.g('STREAM_EMERGENCY_COALESCE_LEN', 300),
|
|
54
|
+
COALESCE_MODE: Utils.g('STREAM_COALESCE_MODE', 'fixed'),
|
|
55
|
+
SNAPSHOT_MAX_STEP: Utils.g('STREAM_SNAPSHOT_MAX_STEP', 8000),
|
|
56
|
+
QUEUE_MAX_ITEMS: Utils.g('STREAM_QUEUE_MAX_ITEMS', 1200),
|
|
57
|
+
PRESERVE_CODES_MAX: Utils.g('STREAM_PRESERVE_CODES_MAX', 120),
|
|
58
|
+
|
|
59
|
+
// switch to plain text after this many lines without markdown tokens
|
|
60
|
+
PLAIN_ACTIVATE_AFTER_LINES: Utils.g('STREAM_PLAIN_ACTIVATE_AFTER_LINES', 80),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Math (KaTeX) idle batching and per-batch hint.
|
|
64
|
+
this.MATH = {
|
|
65
|
+
IDLE_TIMEOUT_MS: Utils.g('MATH_IDLE_TIMEOUT_MS', 800),
|
|
66
|
+
BATCH_HINT: Utils.g('MATH_BATCH_HINT', 24)
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Icon URLs (provided by host app).
|
|
70
|
+
this.ICONS = {
|
|
71
|
+
EXPAND: Utils.g('ICON_EXPAND', ''),
|
|
72
|
+
COLLAPSE: Utils.g('ICON_COLLAPSE', ''),
|
|
73
|
+
CODE_MENU: Utils.g('ICON_CODE_MENU', ''),
|
|
74
|
+
CODE_COPY: Utils.g('ICON_CODE_COPY', ''),
|
|
75
|
+
CODE_RUN: Utils.g('ICON_CODE_RUN', ''),
|
|
76
|
+
CODE_PREVIEW: Utils.g('ICON_CODE_PREVIEW', '')
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Localized UI strings.
|
|
80
|
+
this.LOCALE = {
|
|
81
|
+
PREVIEW: Utils.g('LOCALE_PREVIEW', 'Preview'),
|
|
82
|
+
RUN: Utils.g('LOCALE_RUN', 'Run'),
|
|
83
|
+
COLLAPSE: Utils.g('LOCALE_COLLAPSE', 'Collapse'),
|
|
84
|
+
EXPAND: Utils.g('LOCALE_EXPAND', 'Expand'),
|
|
85
|
+
COPY: Utils.g('LOCALE_COPY', 'Copy'),
|
|
86
|
+
COPIED: Utils.g('LOCALE_COPIED', 'Copied')
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Code block styling theme (hljs theme key or custom).
|
|
90
|
+
this.CODE_STYLE = Utils.g('CODE_SYNTAX_STYLE', 'default');
|
|
91
|
+
|
|
92
|
+
// Adaptive snapshot profile for plain text.
|
|
93
|
+
this.PROFILE_TEXT = {
|
|
94
|
+
base: Utils.g('PROFILE_TEXT_BASE', 4),
|
|
95
|
+
growth: Utils.g('PROFILE_TEXT_GROWTH', 1.28),
|
|
96
|
+
minInterval: Utils.g('PROFILE_TEXT_MIN_INTERVAL', 4),
|
|
97
|
+
softLatency: Utils.g('PROFILE_TEXT_SOFT_LATENCY', 60),
|
|
98
|
+
adaptiveStep: Utils.g('PROFILE_TEXT_ADAPTIVE_STEP', false)
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Adaptive snapshot profile for code (line-aware).
|
|
102
|
+
this.PROFILE_CODE = {
|
|
103
|
+
base: 2048,
|
|
104
|
+
growth: 2.6,
|
|
105
|
+
minInterval: 500,
|
|
106
|
+
softLatency: 1200,
|
|
107
|
+
minLinesForHL: Utils.g('PROFILE_CODE_HL_N_LINE', 25),
|
|
108
|
+
minCharsForHL: Utils.g('PROFILE_CODE_HL_N_CHARS', 5000),
|
|
109
|
+
promoteMinInterval: 300,
|
|
110
|
+
promoteMaxLatency: 800,
|
|
111
|
+
promoteMinLines: Utils.g('PROFILE_CODE_HL_N_LINE', 25),
|
|
112
|
+
adaptiveStep: Utils.g('PROFILE_CODE_ADAPTIVE_STEP', false),
|
|
113
|
+
stopAfterLines: Utils.g('PROFILE_CODE_STOP_HL_AFTER_LINES', 300),
|
|
114
|
+
streamPlainAfterLines: 0,
|
|
115
|
+
streamPlainAfterChars: 0,
|
|
116
|
+
maxFrozenChars: 32000, // max chars to freeze DOM nodes in .hl-freeze
|
|
117
|
+
finalHighlightMaxLines: Utils.g('PROFILE_CODE_FINAL_HL_MAX_LINES', 1500),
|
|
118
|
+
finalHighlightMaxChars: Utils.g('PROFILE_CODE_FINAL_HL_MAX_CHARS', 350000)
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Debounce for heavy resets (ms).
|
|
122
|
+
this.RESET = {
|
|
123
|
+
HEAVY_DEBOUNCE_MS: Utils.g('RESET_HEAVY_DEBOUNCE_MS', 24)
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Logging caps (used by Logger).
|
|
127
|
+
this.LOG = {
|
|
128
|
+
MAX_QUEUE: Utils.g('LOG_MAX_QUEUE', 400),
|
|
129
|
+
MAX_BYTES: Utils.g('LOG_MAX_BYTES', 256 * 1024),
|
|
130
|
+
BATCH_MAX: Utils.g('LOG_BATCH_MAX', 64),
|
|
131
|
+
RATE_LIMIT_PER_SEC: Utils.g('LOG_RATE_LIMIT_PER_SEC', 0)
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Async tuning for background work.
|
|
135
|
+
this.ASYNC = {
|
|
136
|
+
SLICE_MS: Utils.g('ASYNC_SLICE_MS', 12),
|
|
137
|
+
MIN_YIELD_MS: Utils.g('ASYNC_MIN_YIELD_MS', 0),
|
|
138
|
+
MD_NODES_PER_SLICE: Utils.g('ASYNC_MD_NODES_PER_SLICE', 12)
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// RAF pump tuning (budget per frame).
|
|
142
|
+
this.RAF = {
|
|
143
|
+
FLUSH_BUDGET_MS: Utils.g('RAF_FLUSH_BUDGET_MS', 7),
|
|
144
|
+
MAX_TASKS_PER_FLUSH: Utils.g('RAF_MAX_TASKS_PER_FLUSH', 120)
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Markdown tuning – allow/disallow indented code blocks.
|
|
148
|
+
this.MD = {
|
|
149
|
+
ALLOW_INDENTED_CODE: Utils.g('MD_ALLOW_INDENTED_CODE', false)
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Custom markup rules for simple tags in text.
|
|
153
|
+
// NOTE: added nl2br + allowBr for think rules; rest unchanged.
|
|
154
|
+
this.CUSTOM_MARKUP_RULES = Utils.g('CUSTOM_MARKUP_RULES', [{
|
|
155
|
+
name: 'cmd',
|
|
156
|
+
open: '[!cmd]',
|
|
157
|
+
close: '[/!cmd]',
|
|
158
|
+
tag: 'div',
|
|
159
|
+
className: 'cmd',
|
|
160
|
+
innerMode: 'text'
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// Think (Markdown-style) – convert newlines to <br>, allow real <br> tokens; safe-escape everything else.
|
|
164
|
+
{
|
|
165
|
+
name: 'think_md',
|
|
166
|
+
open: '[!think]',
|
|
167
|
+
close: '[/!think]',
|
|
168
|
+
tag: 'think',
|
|
169
|
+
className: '',
|
|
170
|
+
innerMode: 'text',
|
|
171
|
+
nl2br: true,
|
|
172
|
+
allowBr: true
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
// Think (HTML-style, streaming-friendly)
|
|
176
|
+
{
|
|
177
|
+
name: 'think_html',
|
|
178
|
+
open: '<think>',
|
|
179
|
+
close: '</think>',
|
|
180
|
+
tag: 'think',
|
|
181
|
+
className: '',
|
|
182
|
+
innerMode: 'text',
|
|
183
|
+
stream: true,
|
|
184
|
+
nl2br: true,
|
|
185
|
+
allowBr: true
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
{
|
|
189
|
+
name: 'tool',
|
|
190
|
+
open: '<tool>',
|
|
191
|
+
close: '</tool>',
|
|
192
|
+
tag: 'div',
|
|
193
|
+
className: 'cmd',
|
|
194
|
+
innerMode: 'text',
|
|
195
|
+
stream: true
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
// Streams+final: convert [!exec]... into fenced python code BEFORE markdown-it
|
|
199
|
+
{
|
|
200
|
+
name: 'exec_md',
|
|
201
|
+
open: '[!exec]',
|
|
202
|
+
close: '[/!exec]',
|
|
203
|
+
innerMode: 'text',
|
|
204
|
+
stream: true,
|
|
205
|
+
openReplace: '```python\n',
|
|
206
|
+
closeReplace: '\n```',
|
|
207
|
+
phase: 'source'
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
// Streams+final: convert <execute>...</execute> into fenced python code BEFORE markdown-it
|
|
211
|
+
{
|
|
212
|
+
name: 'exec_html',
|
|
213
|
+
open: '<execute>',
|
|
214
|
+
close: '</execute>',
|
|
215
|
+
innerMode: 'text',
|
|
216
|
+
stream: true,
|
|
217
|
+
openReplace: '```python\n',
|
|
218
|
+
closeReplace: '\n```',
|
|
219
|
+
phase: 'source'
|
|
220
|
+
}
|
|
221
|
+
]);
|
|
222
|
+
}
|
|
223
|
+
}
|