calvyn-code 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/README.zh-CN.md +180 -0
- package/acp_adapter/__init__.py +1 -0
- package/acp_adapter/__main__.py +5 -0
- package/acp_adapter/auth.py +68 -0
- package/acp_adapter/bootstrap/__init__.py +0 -0
- package/acp_adapter/bootstrap/bootstrap_browser_tools.ps1 +288 -0
- package/acp_adapter/bootstrap/bootstrap_browser_tools.sh +399 -0
- package/acp_adapter/entry.py +292 -0
- package/acp_adapter/events.py +265 -0
- package/acp_adapter/permissions.py +148 -0
- package/acp_adapter/server.py +1713 -0
- package/acp_adapter/session.py +629 -0
- package/acp_adapter/tools.py +1180 -0
- package/agent/__init__.py +6 -0
- package/agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/agent/__pycache__/account_usage.cpython-312.pyc +0 -0
- package/agent/__pycache__/anthropic_adapter.cpython-312.pyc +0 -0
- package/agent/__pycache__/async_utils.cpython-312.pyc +0 -0
- package/agent/__pycache__/auxiliary_client.cpython-312.pyc +0 -0
- package/agent/__pycache__/codex_responses_adapter.cpython-312.pyc +0 -0
- package/agent/__pycache__/context_compressor.cpython-312.pyc +0 -0
- package/agent/__pycache__/context_engine.cpython-312.pyc +0 -0
- package/agent/__pycache__/context_references.cpython-312.pyc +0 -0
- package/agent/__pycache__/credential_pool.cpython-312.pyc +0 -0
- package/agent/__pycache__/curator.cpython-312.pyc +0 -0
- package/agent/__pycache__/display.cpython-312.pyc +0 -0
- package/agent/__pycache__/error_classifier.cpython-312.pyc +0 -0
- package/agent/__pycache__/file_safety.cpython-312.pyc +0 -0
- package/agent/__pycache__/google_code_assist.cpython-312.pyc +0 -0
- package/agent/__pycache__/google_oauth.cpython-312.pyc +0 -0
- package/agent/__pycache__/i18n.cpython-312.pyc +0 -0
- package/agent/__pycache__/image_gen_provider.cpython-312.pyc +0 -0
- package/agent/__pycache__/image_gen_registry.cpython-312.pyc +0 -0
- package/agent/__pycache__/insights.cpython-312.pyc +0 -0
- package/agent/__pycache__/lmstudio_reasoning.cpython-312.pyc +0 -0
- package/agent/__pycache__/manual_compression_feedback.cpython-312.pyc +0 -0
- package/agent/__pycache__/markdown_tables.cpython-312.pyc +0 -0
- package/agent/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/agent/__pycache__/memory_provider.cpython-312.pyc +0 -0
- package/agent/__pycache__/model_metadata.cpython-312.pyc +0 -0
- package/agent/__pycache__/models_dev.cpython-312.pyc +0 -0
- package/agent/__pycache__/moonshot_schema.cpython-312.pyc +0 -0
- package/agent/__pycache__/onboarding.cpython-312.pyc +0 -0
- package/agent/__pycache__/portal_tags.cpython-312.pyc +0 -0
- package/agent/__pycache__/prompt_builder.cpython-312.pyc +0 -0
- package/agent/__pycache__/prompt_caching.cpython-312.pyc +0 -0
- package/agent/__pycache__/redact.cpython-312.pyc +0 -0
- package/agent/__pycache__/retry_utils.cpython-312.pyc +0 -0
- package/agent/__pycache__/shell_hooks.cpython-312.pyc +0 -0
- package/agent/__pycache__/skill_commands.cpython-312.pyc +0 -0
- package/agent/__pycache__/skill_preprocessing.cpython-312.pyc +0 -0
- package/agent/__pycache__/skill_utils.cpython-312.pyc +0 -0
- package/agent/__pycache__/subdirectory_hints.cpython-312.pyc +0 -0
- package/agent/__pycache__/think_scrubber.cpython-312.pyc +0 -0
- package/agent/__pycache__/title_generator.cpython-312.pyc +0 -0
- package/agent/__pycache__/tool_guardrails.cpython-312.pyc +0 -0
- package/agent/__pycache__/tool_result_classification.cpython-312.pyc +0 -0
- package/agent/__pycache__/trajectory.cpython-312.pyc +0 -0
- package/agent/__pycache__/usage_pricing.cpython-312.pyc +0 -0
- package/agent/__pycache__/video_gen_provider.cpython-312.pyc +0 -0
- package/agent/__pycache__/video_gen_registry.cpython-312.pyc +0 -0
- package/agent/__pycache__/web_search_provider.cpython-312.pyc +0 -0
- package/agent/__pycache__/web_search_registry.cpython-312.pyc +0 -0
- package/agent/account_usage.py +326 -0
- package/agent/anthropic_adapter.py +2087 -0
- package/agent/async_utils.py +68 -0
- package/agent/auxiliary_client.py +4893 -0
- package/agent/bedrock_adapter.py +1276 -0
- package/agent/codex_responses_adapter.py +1084 -0
- package/agent/context_compressor.py +1583 -0
- package/agent/context_engine.py +211 -0
- package/agent/context_references.py +519 -0
- package/agent/copilot_acp_client.py +684 -0
- package/agent/credential_pool.py +1780 -0
- package/agent/credential_sources.py +449 -0
- package/agent/curator.py +1782 -0
- package/agent/curator_backup.py +694 -0
- package/agent/display.py +987 -0
- package/agent/error_classifier.py +1058 -0
- package/agent/file_safety.py +112 -0
- package/agent/gemini_cloudcode_adapter.py +909 -0
- package/agent/gemini_native_adapter.py +971 -0
- package/agent/gemini_schema.py +99 -0
- package/agent/google_code_assist.py +452 -0
- package/agent/google_oauth.py +1062 -0
- package/agent/i18n.py +258 -0
- package/agent/image_gen_provider.py +243 -0
- package/agent/image_gen_registry.py +145 -0
- package/agent/image_routing.py +301 -0
- package/agent/insights.py +931 -0
- package/agent/lmstudio_reasoning.py +48 -0
- package/agent/lsp/__init__.py +106 -0
- package/agent/lsp/__pycache__/__init__.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/cli.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/client.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/eventlog.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/manager.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/protocol.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/servers.cpython-312.pyc +0 -0
- package/agent/lsp/__pycache__/workspace.cpython-312.pyc +0 -0
- package/agent/lsp/cli.py +308 -0
- package/agent/lsp/client.py +930 -0
- package/agent/lsp/eventlog.py +213 -0
- package/agent/lsp/install.py +376 -0
- package/agent/lsp/manager.py +644 -0
- package/agent/lsp/protocol.py +196 -0
- package/agent/lsp/range_shift.py +149 -0
- package/agent/lsp/reporter.py +78 -0
- package/agent/lsp/servers.py +1040 -0
- package/agent/lsp/workspace.py +223 -0
- package/agent/manual_compression_feedback.py +49 -0
- package/agent/markdown_tables.py +309 -0
- package/agent/memory_manager.py +556 -0
- package/agent/memory_provider.py +279 -0
- package/agent/model_metadata.py +1827 -0
- package/agent/models_dev.py +724 -0
- package/agent/moonshot_schema.py +231 -0
- package/agent/nous_rate_guard.py +326 -0
- package/agent/onboarding.py +193 -0
- package/agent/plugin_llm.py +1046 -0
- package/agent/portal_tags.py +64 -0
- package/agent/prompt_builder.py +1457 -0
- package/agent/prompt_caching.py +79 -0
- package/agent/rate_limit_tracker.py +246 -0
- package/agent/redact.py +403 -0
- package/agent/retry_utils.py +57 -0
- package/agent/shell_hooks.py +837 -0
- package/agent/skill_commands.py +502 -0
- package/agent/skill_preprocessing.py +131 -0
- package/agent/skill_utils.py +512 -0
- package/agent/subdirectory_hints.py +224 -0
- package/agent/think_scrubber.py +386 -0
- package/agent/title_generator.py +171 -0
- package/agent/tool_guardrails.py +458 -0
- package/agent/tool_result_classification.py +26 -0
- package/agent/trajectory.py +56 -0
- package/agent/transports/__init__.py +68 -0
- package/agent/transports/__pycache__/__init__.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/anthropic.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/base.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/bedrock.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/chat_completions.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/codex.cpython-312.pyc +0 -0
- package/agent/transports/__pycache__/types.cpython-312.pyc +0 -0
- package/agent/transports/anthropic.py +179 -0
- package/agent/transports/base.py +89 -0
- package/agent/transports/bedrock.py +154 -0
- package/agent/transports/chat_completions.py +614 -0
- package/agent/transports/codex.py +283 -0
- package/agent/transports/codex_app_server.py +368 -0
- package/agent/transports/codex_app_server_session.py +810 -0
- package/agent/transports/codex_event_projector.py +312 -0
- package/agent/transports/hermes_tools_mcp_server.py +233 -0
- package/agent/transports/types.py +162 -0
- package/agent/usage_pricing.py +877 -0
- package/agent/video_gen_provider.py +300 -0
- package/agent/video_gen_registry.py +117 -0
- package/agent/web_search_provider.py +221 -0
- package/agent/web_search_registry.py +262 -0
- package/assets/banner.png +0 -0
- package/batch_runner.py +1303 -0
- package/bin/calvyn.js +67 -0
- package/calvyn_bootstrap.py +130 -0
- package/calvyn_constants.py +346 -0
- package/calvyn_logging.py +390 -0
- package/calvyn_state.py +2967 -0
- package/calvyn_time.py +105 -0
- package/cli.py +14160 -0
- package/cron/__init__.py +42 -0
- package/cron/__pycache__/__init__.cpython-312.pyc +0 -0
- package/cron/__pycache__/jobs.cpython-312.pyc +0 -0
- package/cron/__pycache__/scheduler.cpython-312.pyc +0 -0
- package/cron/jobs.py +1160 -0
- package/cron/scheduler.py +1832 -0
- package/gateway/__init__.py +35 -0
- package/gateway/__pycache__/__init__.cpython-312.pyc +0 -0
- package/gateway/__pycache__/channel_directory.cpython-312.pyc +0 -0
- package/gateway/__pycache__/config.cpython-312.pyc +0 -0
- package/gateway/__pycache__/delivery.cpython-312.pyc +0 -0
- package/gateway/__pycache__/display_config.cpython-312.pyc +0 -0
- package/gateway/__pycache__/hooks.cpython-312.pyc +0 -0
- package/gateway/__pycache__/pairing.cpython-312.pyc +0 -0
- package/gateway/__pycache__/platform_registry.cpython-312.pyc +0 -0
- package/gateway/__pycache__/restart.cpython-312.pyc +0 -0
- package/gateway/__pycache__/run.cpython-312.pyc +0 -0
- package/gateway/__pycache__/runtime_footer.cpython-312.pyc +0 -0
- package/gateway/__pycache__/session.cpython-312.pyc +0 -0
- package/gateway/__pycache__/session_context.cpython-312.pyc +0 -0
- package/gateway/__pycache__/shutdown_forensics.cpython-312.pyc +0 -0
- package/gateway/__pycache__/slash_access.cpython-312.pyc +0 -0
- package/gateway/__pycache__/status.cpython-312.pyc +0 -0
- package/gateway/__pycache__/stream_consumer.cpython-312.pyc +0 -0
- package/gateway/__pycache__/whatsapp_identity.cpython-312.pyc +0 -0
- package/gateway/assets/telegram-botfather-threads-settings.jpg +0 -0
- package/gateway/builtin_hooks/__init__.py +1 -0
- package/gateway/channel_directory.py +357 -0
- package/gateway/config.py +1873 -0
- package/gateway/delivery.py +258 -0
- package/gateway/display_config.py +206 -0
- package/gateway/hooks.py +210 -0
- package/gateway/mirror.py +179 -0
- package/gateway/pairing.py +322 -0
- package/gateway/platform_registry.py +260 -0
- package/gateway/platforms/ADDING_A_PLATFORM.md +374 -0
- package/gateway/platforms/__init__.py +45 -0
- package/gateway/platforms/__pycache__/__init__.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/base.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/helpers.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/telegram.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/telegram_network.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/yuanbao.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/yuanbao_media.cpython-312.pyc +0 -0
- package/gateway/platforms/__pycache__/yuanbao_proto.cpython-312.pyc +0 -0
- package/gateway/platforms/_http_client_limits.py +84 -0
- package/gateway/platforms/api_server.py +3488 -0
- package/gateway/platforms/base.py +3747 -0
- package/gateway/platforms/bluebubbles.py +937 -0
- package/gateway/platforms/dingtalk.py +1473 -0
- package/gateway/platforms/discord.py +5584 -0
- package/gateway/platforms/email.py +773 -0
- package/gateway/platforms/feishu.py +5059 -0
- package/gateway/platforms/feishu_comment.py +1382 -0
- package/gateway/platforms/feishu_comment_rules.py +430 -0
- package/gateway/platforms/helpers.py +279 -0
- package/gateway/platforms/homeassistant.py +449 -0
- package/gateway/platforms/matrix.py +2777 -0
- package/gateway/platforms/mattermost.py +852 -0
- package/gateway/platforms/msgraph_webhook.py +397 -0
- package/gateway/platforms/qqbot/__init__.py +91 -0
- package/gateway/platforms/qqbot/adapter.py +3072 -0
- package/gateway/platforms/qqbot/chunked_upload.py +602 -0
- package/gateway/platforms/qqbot/constants.py +74 -0
- package/gateway/platforms/qqbot/crypto.py +45 -0
- package/gateway/platforms/qqbot/keyboards.py +473 -0
- package/gateway/platforms/qqbot/onboard.py +220 -0
- package/gateway/platforms/qqbot/utils.py +71 -0
- package/gateway/platforms/signal.py +1518 -0
- package/gateway/platforms/signal_rate_limit.py +369 -0
- package/gateway/platforms/slack.py +3028 -0
- package/gateway/platforms/sms.py +377 -0
- package/gateway/platforms/telegram.py +4836 -0
- package/gateway/platforms/telegram_network.py +249 -0
- package/gateway/platforms/webhook.py +806 -0
- package/gateway/platforms/wecom.py +1610 -0
- package/gateway/platforms/wecom_callback.py +403 -0
- package/gateway/platforms/wecom_crypto.py +142 -0
- package/gateway/platforms/weixin.py +2170 -0
- package/gateway/platforms/whatsapp.py +1283 -0
- package/gateway/platforms/yuanbao.py +4873 -0
- package/gateway/platforms/yuanbao_media.py +645 -0
- package/gateway/platforms/yuanbao_proto.py +1209 -0
- package/gateway/platforms/yuanbao_sticker.py +558 -0
- package/gateway/restart.py +20 -0
- package/gateway/run.py +17074 -0
- package/gateway/runtime_footer.py +150 -0
- package/gateway/session.py +1399 -0
- package/gateway/session_context.py +156 -0
- package/gateway/shutdown_forensics.py +462 -0
- package/gateway/slash_access.py +229 -0
- package/gateway/status.py +972 -0
- package/gateway/sticker_cache.py +111 -0
- package/gateway/stream_consumer.py +1286 -0
- package/gateway/whatsapp_identity.py +156 -0
- package/hermes_cli/__init__.py +47 -0
- package/hermes_cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/_parser.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/auth.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/banner.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/browser_connect.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/callbacks.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/checkpoints.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/cli_output.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/codex_models.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/codex_runtime_switch.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/colors.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/commands.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/config.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/copilot_auth.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/curator.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/curses_ui.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/debug.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/default_soul.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/env_loader.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/fallback_cmd.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/gateway.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/gateway_windows.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/goals.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/inventory.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/kanban.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/kanban_db.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/main.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/model_catalog.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/model_normalize.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/model_switch.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/models.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/nous_subscription.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/pairing.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/platforms.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/plugins.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/profiles.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/providers.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/pt_input_extras.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/runtime_provider.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/security_advisories.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/setup.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/skills_hub.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/skin_engine.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/stdio.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/timeouts.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/tips.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/tools_config.cpython-312.pyc +0 -0
- package/hermes_cli/__pycache__/voice.cpython-312.pyc +0 -0
- package/hermes_cli/_parser.py +365 -0
- package/hermes_cli/_subprocess_compat.py +175 -0
- package/hermes_cli/auth.py +6299 -0
- package/hermes_cli/auth_commands.py +749 -0
- package/hermes_cli/azure_detect.py +300 -0
- package/hermes_cli/backup.py +938 -0
- package/hermes_cli/banner.py +703 -0
- package/hermes_cli/browser_connect.py +139 -0
- package/hermes_cli/callbacks.py +243 -0
- package/hermes_cli/checkpoints.py +244 -0
- package/hermes_cli/claw.py +810 -0
- package/hermes_cli/cli_output.py +78 -0
- package/hermes_cli/clipboard.py +495 -0
- package/hermes_cli/codex_models.py +198 -0
- package/hermes_cli/codex_runtime_plugin_migration.py +757 -0
- package/hermes_cli/codex_runtime_switch.py +266 -0
- package/hermes_cli/colors.py +38 -0
- package/hermes_cli/commands.py +1728 -0
- package/hermes_cli/completion.py +315 -0
- package/hermes_cli/config.py +5382 -0
- package/hermes_cli/copilot_auth.py +392 -0
- package/hermes_cli/cron.py +313 -0
- package/hermes_cli/curator.py +598 -0
- package/hermes_cli/curses_ui.py +472 -0
- package/hermes_cli/debug.py +747 -0
- package/hermes_cli/default_soul.py +11 -0
- package/hermes_cli/dep_ensure.py +107 -0
- package/hermes_cli/dingtalk_auth.py +293 -0
- package/hermes_cli/doctor.py +1863 -0
- package/hermes_cli/dump.py +326 -0
- package/hermes_cli/env_loader.py +175 -0
- package/hermes_cli/fallback_cmd.py +361 -0
- package/hermes_cli/gateway.py +5422 -0
- package/hermes_cli/gateway_windows.py +692 -0
- package/hermes_cli/goals.py +757 -0
- package/hermes_cli/hooks.py +385 -0
- package/hermes_cli/inventory.py +240 -0
- package/hermes_cli/kanban.py +2252 -0
- package/hermes_cli/kanban_db.py +4840 -0
- package/hermes_cli/kanban_diagnostics.py +776 -0
- package/hermes_cli/kanban_specify.py +266 -0
- package/hermes_cli/logs.py +391 -0
- package/hermes_cli/main.py +12396 -0
- package/hermes_cli/mcp_config.py +781 -0
- package/hermes_cli/memory_setup.py +465 -0
- package/hermes_cli/model_catalog.py +330 -0
- package/hermes_cli/model_normalize.py +473 -0
- package/hermes_cli/model_switch.py +1777 -0
- package/hermes_cli/models.py +3789 -0
- package/hermes_cli/nous_subscription.py +799 -0
- package/hermes_cli/oneshot.py +351 -0
- package/hermes_cli/pairing.py +115 -0
- package/hermes_cli/platforms.py +83 -0
- package/hermes_cli/plugins.py +1562 -0
- package/hermes_cli/plugins_cmd.py +1587 -0
- package/hermes_cli/profile_distribution.py +703 -0
- package/hermes_cli/profiles.py +1319 -0
- package/hermes_cli/providers.py +720 -0
- package/hermes_cli/proxy/__init__.py +20 -0
- package/hermes_cli/proxy/adapters/__init__.py +35 -0
- package/hermes_cli/proxy/adapters/base.py +94 -0
- package/hermes_cli/proxy/adapters/nous_portal.py +137 -0
- package/hermes_cli/proxy/cli.py +141 -0
- package/hermes_cli/proxy/server.py +265 -0
- package/hermes_cli/pt_input_extras.py +83 -0
- package/hermes_cli/pty_bridge.py +237 -0
- package/hermes_cli/relaunch.py +205 -0
- package/hermes_cli/runtime_provider.py +1428 -0
- package/hermes_cli/security_advisories.py +452 -0
- package/hermes_cli/setup.py +3559 -0
- package/hermes_cli/skills_config.py +177 -0
- package/hermes_cli/skills_hub.py +1595 -0
- package/hermes_cli/skin_engine.py +929 -0
- package/hermes_cli/slack_cli.py +160 -0
- package/hermes_cli/status.py +550 -0
- package/hermes_cli/stdio.py +252 -0
- package/hermes_cli/timeouts.py +82 -0
- package/hermes_cli/tips.py +487 -0
- package/hermes_cli/tools_config.py +3151 -0
- package/hermes_cli/uninstall.py +681 -0
- package/hermes_cli/vercel_auth.py +70 -0
- package/hermes_cli/voice.py +846 -0
- package/hermes_cli/web_server.py +4438 -0
- package/hermes_cli/webhook.py +275 -0
- package/locales/af.yaml +350 -0
- package/locales/de.yaml +350 -0
- package/locales/en.yaml +365 -0
- package/locales/es.yaml +350 -0
- package/locales/fr.yaml +350 -0
- package/locales/ga.yaml +354 -0
- package/locales/hu.yaml +350 -0
- package/locales/it.yaml +350 -0
- package/locales/ja.yaml +350 -0
- package/locales/ko.yaml +350 -0
- package/locales/pt.yaml +350 -0
- package/locales/ru.yaml +350 -0
- package/locales/tr.yaml +350 -0
- package/locales/uk.yaml +350 -0
- package/locales/zh-hant.yaml +350 -0
- package/locales/zh.yaml +350 -0
- package/mcp_serve.py +898 -0
- package/model_tools.py +899 -0
- package/optional-skills/DESCRIPTION.md +24 -0
- package/optional-skills/autonomous-ai-agents/DESCRIPTION.md +2 -0
- package/optional-skills/autonomous-ai-agents/blackbox/SKILL.md +144 -0
- package/optional-skills/autonomous-ai-agents/honcho/SKILL.md +431 -0
- package/optional-skills/blockchain/evm/SKILL.md +211 -0
- package/optional-skills/blockchain/evm/scripts/evm_client.py +1508 -0
- package/optional-skills/blockchain/hyperliquid/SKILL.md +211 -0
- package/optional-skills/blockchain/hyperliquid/scripts/hyperliquid_client.py +1660 -0
- package/optional-skills/blockchain/solana/SKILL.md +208 -0
- package/optional-skills/blockchain/solana/scripts/solana_client.py +698 -0
- package/optional-skills/communication/DESCRIPTION.md +1 -0
- package/optional-skills/communication/one-three-one-rule/SKILL.md +104 -0
- package/optional-skills/creative/blender-mcp/SKILL.md +117 -0
- package/optional-skills/creative/concept-diagrams/SKILL.md +362 -0
- package/optional-skills/creative/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
- package/optional-skills/creative/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
- package/optional-skills/creative/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
- package/optional-skills/creative/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
- package/optional-skills/creative/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
- package/optional-skills/creative/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
- package/optional-skills/creative/concept-diagrams/examples/electricity-grid-flow.md +182 -0
- package/optional-skills/creative/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
- package/optional-skills/creative/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
- package/optional-skills/creative/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
- package/optional-skills/creative/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
- package/optional-skills/creative/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
- package/optional-skills/creative/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
- package/optional-skills/creative/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
- package/optional-skills/creative/concept-diagrams/examples/wind-turbine-structure.md +338 -0
- package/optional-skills/creative/concept-diagrams/references/dashboard-patterns.md +43 -0
- package/optional-skills/creative/concept-diagrams/references/infrastructure-patterns.md +144 -0
- package/optional-skills/creative/concept-diagrams/references/physical-shape-cookbook.md +42 -0
- package/optional-skills/creative/concept-diagrams/templates/template.html +174 -0
- package/optional-skills/creative/hyperframes/SKILL.md +191 -0
- package/optional-skills/creative/hyperframes/references/cli.md +185 -0
- package/optional-skills/creative/hyperframes/references/composition.md +129 -0
- package/optional-skills/creative/hyperframes/references/features.md +289 -0
- package/optional-skills/creative/hyperframes/references/gsap.md +136 -0
- package/optional-skills/creative/hyperframes/references/troubleshooting.md +137 -0
- package/optional-skills/creative/hyperframes/references/website-to-video.md +145 -0
- package/optional-skills/creative/hyperframes/scripts/setup.sh +135 -0
- package/optional-skills/creative/kanban-video-orchestrator/SKILL.md +207 -0
- package/optional-skills/creative/kanban-video-orchestrator/assets/brief.md.tmpl +79 -0
- package/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +185 -0
- package/optional-skills/creative/kanban-video-orchestrator/assets/soul.md.tmpl +38 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/examples.md +227 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/intake.md +166 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +276 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/monitoring.md +180 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md +298 -0
- package/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +317 -0
- package/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py +501 -0
- package/optional-skills/creative/kanban-video-orchestrator/scripts/monitor.py +195 -0
- package/optional-skills/creative/meme-generation/EXAMPLES.md +46 -0
- package/optional-skills/creative/meme-generation/SKILL.md +130 -0
- package/optional-skills/creative/meme-generation/scripts/generate_meme.py +471 -0
- package/optional-skills/creative/meme-generation/scripts/templates.json +97 -0
- package/optional-skills/devops/cli/SKILL.md +156 -0
- package/optional-skills/devops/cli/references/app-discovery.md +112 -0
- package/optional-skills/devops/cli/references/authentication.md +59 -0
- package/optional-skills/devops/cli/references/cli-reference.md +104 -0
- package/optional-skills/devops/cli/references/running-apps.md +171 -0
- package/optional-skills/devops/docker-management/SKILL.md +281 -0
- package/optional-skills/devops/pinggy-tunnel/SKILL.md +309 -0
- package/optional-skills/devops/watchers/SKILL.md +112 -0
- package/optional-skills/devops/watchers/scripts/_watermark.py +148 -0
- package/optional-skills/devops/watchers/scripts/watch_github.py +168 -0
- package/optional-skills/devops/watchers/scripts/watch_http_json.py +131 -0
- package/optional-skills/devops/watchers/scripts/watch_rss.py +121 -0
- package/optional-skills/dogfood/DESCRIPTION.md +3 -0
- package/optional-skills/dogfood/adversarial-ux-test/SKILL.md +191 -0
- package/optional-skills/email/agentmail/SKILL.md +126 -0
- package/optional-skills/finance/3-statement-model/SKILL.md +433 -0
- package/optional-skills/finance/3-statement-model/references/formatting.md +118 -0
- package/optional-skills/finance/3-statement-model/references/formulas.md +292 -0
- package/optional-skills/finance/3-statement-model/references/sec-filings.md +125 -0
- package/optional-skills/finance/comps-analysis/SKILL.md +662 -0
- package/optional-skills/finance/dcf-model/SKILL.md +1270 -0
- package/optional-skills/finance/dcf-model/TROUBLESHOOTING.md +40 -0
- package/optional-skills/finance/dcf-model/requirements.txt +7 -0
- package/optional-skills/finance/dcf-model/scripts/validate_dcf.py +292 -0
- package/optional-skills/finance/excel-author/SKILL.md +244 -0
- package/optional-skills/finance/excel-author/scripts/recalc.py +88 -0
- package/optional-skills/finance/lbo-model/SKILL.md +291 -0
- package/optional-skills/finance/merger-model/SKILL.md +144 -0
- package/optional-skills/finance/pptx-author/SKILL.md +173 -0
- package/optional-skills/finance/stocks/SKILL.md +95 -0
- package/optional-skills/finance/stocks/scripts/stocks_client.py +755 -0
- package/optional-skills/health/DESCRIPTION.md +1 -0
- package/optional-skills/health/fitness-nutrition/SKILL.md +256 -0
- package/optional-skills/health/fitness-nutrition/references/FORMULAS.md +100 -0
- package/optional-skills/health/fitness-nutrition/scripts/body_calc.py +210 -0
- package/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py +86 -0
- package/optional-skills/health/neuroskill-bci/SKILL.md +459 -0
- package/optional-skills/health/neuroskill-bci/references/api.md +286 -0
- package/optional-skills/health/neuroskill-bci/references/metrics.md +220 -0
- package/optional-skills/health/neuroskill-bci/references/protocols.md +452 -0
- package/optional-skills/mcp/DESCRIPTION.md +3 -0
- package/optional-skills/mcp/fastmcp/SKILL.md +300 -0
- package/optional-skills/mcp/fastmcp/references/fastmcp-cli.md +110 -0
- package/optional-skills/mcp/fastmcp/scripts/scaffold_fastmcp.py +56 -0
- package/optional-skills/mcp/fastmcp/templates/api_wrapper.py +54 -0
- package/optional-skills/mcp/fastmcp/templates/database_server.py +77 -0
- package/optional-skills/mcp/fastmcp/templates/file_processor.py +55 -0
- package/optional-skills/mcp/mcporter/SKILL.md +123 -0
- package/optional-skills/migration/DESCRIPTION.md +2 -0
- package/optional-skills/migration/openclaw-migration/SKILL.md +298 -0
- package/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py +3136 -0
- package/optional-skills/mlops/accelerate/SKILL.md +336 -0
- package/optional-skills/mlops/accelerate/references/custom-plugins.md +453 -0
- package/optional-skills/mlops/accelerate/references/megatron-integration.md +489 -0
- package/optional-skills/mlops/accelerate/references/performance.md +525 -0
- package/optional-skills/mlops/chroma/SKILL.md +410 -0
- package/optional-skills/mlops/chroma/references/integration.md +38 -0
- package/optional-skills/mlops/clip/SKILL.md +257 -0
- package/optional-skills/mlops/clip/references/applications.md +207 -0
- package/optional-skills/mlops/faiss/SKILL.md +225 -0
- package/optional-skills/mlops/faiss/references/index_types.md +280 -0
- package/optional-skills/mlops/flash-attention/SKILL.md +367 -0
- package/optional-skills/mlops/flash-attention/references/benchmarks.md +215 -0
- package/optional-skills/mlops/flash-attention/references/transformers-integration.md +293 -0
- package/optional-skills/mlops/guidance/SKILL.md +576 -0
- package/optional-skills/mlops/guidance/references/backends.md +554 -0
- package/optional-skills/mlops/guidance/references/constraints.md +674 -0
- package/optional-skills/mlops/guidance/references/examples.md +767 -0
- package/optional-skills/mlops/huggingface-tokenizers/SKILL.md +520 -0
- package/optional-skills/mlops/huggingface-tokenizers/references/algorithms.md +653 -0
- package/optional-skills/mlops/huggingface-tokenizers/references/integration.md +637 -0
- package/optional-skills/mlops/huggingface-tokenizers/references/pipeline.md +723 -0
- package/optional-skills/mlops/huggingface-tokenizers/references/training.md +565 -0
- package/optional-skills/mlops/inference/outlines/SKILL.md +656 -0
- package/optional-skills/mlops/inference/outlines/references/backends.md +615 -0
- package/optional-skills/mlops/inference/outlines/references/examples.md +773 -0
- package/optional-skills/mlops/inference/outlines/references/json_generation.md +652 -0
- package/optional-skills/mlops/instructor/SKILL.md +744 -0
- package/optional-skills/mlops/instructor/references/examples.md +107 -0
- package/optional-skills/mlops/instructor/references/providers.md +70 -0
- package/optional-skills/mlops/instructor/references/validation.md +606 -0
- package/optional-skills/mlops/lambda-labs/SKILL.md +549 -0
- package/optional-skills/mlops/lambda-labs/references/advanced-usage.md +611 -0
- package/optional-skills/mlops/lambda-labs/references/troubleshooting.md +530 -0
- package/optional-skills/mlops/llava/SKILL.md +308 -0
- package/optional-skills/mlops/llava/references/training.md +197 -0
- package/optional-skills/mlops/modal/SKILL.md +345 -0
- package/optional-skills/mlops/modal/references/advanced-usage.md +503 -0
- package/optional-skills/mlops/modal/references/troubleshooting.md +494 -0
- package/optional-skills/mlops/nemo-curator/SKILL.md +387 -0
- package/optional-skills/mlops/nemo-curator/references/deduplication.md +87 -0
- package/optional-skills/mlops/nemo-curator/references/filtering.md +102 -0
- package/optional-skills/mlops/peft/SKILL.md +435 -0
- package/optional-skills/mlops/peft/references/advanced-usage.md +514 -0
- package/optional-skills/mlops/peft/references/troubleshooting.md +480 -0
- package/optional-skills/mlops/pinecone/SKILL.md +362 -0
- package/optional-skills/mlops/pinecone/references/deployment.md +181 -0
- package/optional-skills/mlops/pytorch-fsdp/SKILL.md +130 -0
- package/optional-skills/mlops/pytorch-fsdp/references/index.md +7 -0
- package/optional-skills/mlops/pytorch-fsdp/references/other.md +4261 -0
- package/optional-skills/mlops/pytorch-lightning/SKILL.md +350 -0
- package/optional-skills/mlops/pytorch-lightning/references/callbacks.md +436 -0
- package/optional-skills/mlops/pytorch-lightning/references/distributed.md +490 -0
- package/optional-skills/mlops/pytorch-lightning/references/hyperparameter-tuning.md +556 -0
- package/optional-skills/mlops/qdrant/SKILL.md +497 -0
- package/optional-skills/mlops/qdrant/references/advanced-usage.md +648 -0
- package/optional-skills/mlops/qdrant/references/troubleshooting.md +631 -0
- package/optional-skills/mlops/saelens/SKILL.md +390 -0
- package/optional-skills/mlops/saelens/references/README.md +69 -0
- package/optional-skills/mlops/saelens/references/api.md +333 -0
- package/optional-skills/mlops/saelens/references/tutorials.md +318 -0
- package/optional-skills/mlops/simpo/SKILL.md +223 -0
- package/optional-skills/mlops/simpo/references/datasets.md +478 -0
- package/optional-skills/mlops/simpo/references/hyperparameters.md +452 -0
- package/optional-skills/mlops/simpo/references/loss-functions.md +350 -0
- package/optional-skills/mlops/slime/SKILL.md +468 -0
- package/optional-skills/mlops/slime/references/api-reference.md +392 -0
- package/optional-skills/mlops/slime/references/troubleshooting.md +386 -0
- package/optional-skills/mlops/stable-diffusion/SKILL.md +523 -0
- package/optional-skills/mlops/stable-diffusion/references/advanced-usage.md +716 -0
- package/optional-skills/mlops/stable-diffusion/references/troubleshooting.md +555 -0
- package/optional-skills/mlops/tensorrt-llm/SKILL.md +191 -0
- package/optional-skills/mlops/tensorrt-llm/references/multi-gpu.md +298 -0
- package/optional-skills/mlops/tensorrt-llm/references/optimization.md +242 -0
- package/optional-skills/mlops/tensorrt-llm/references/serving.md +470 -0
- package/optional-skills/mlops/torchtitan/SKILL.md +362 -0
- package/optional-skills/mlops/torchtitan/references/checkpoint.md +181 -0
- package/optional-skills/mlops/torchtitan/references/custom-models.md +258 -0
- package/optional-skills/mlops/torchtitan/references/float8.md +133 -0
- package/optional-skills/mlops/torchtitan/references/fsdp.md +126 -0
- package/optional-skills/mlops/training/axolotl/SKILL.md +166 -0
- package/optional-skills/mlops/training/axolotl/references/api.md +5548 -0
- package/optional-skills/mlops/training/axolotl/references/dataset-formats.md +1029 -0
- package/optional-skills/mlops/training/axolotl/references/index.md +15 -0
- package/optional-skills/mlops/training/axolotl/references/other.md +3563 -0
- package/optional-skills/mlops/training/trl-fine-tuning/SKILL.md +463 -0
- package/optional-skills/mlops/training/trl-fine-tuning/references/dpo-variants.md +227 -0
- package/optional-skills/mlops/training/trl-fine-tuning/references/grpo-training.md +504 -0
- package/optional-skills/mlops/training/trl-fine-tuning/references/online-rl.md +82 -0
- package/optional-skills/mlops/training/trl-fine-tuning/references/reward-modeling.md +122 -0
- package/optional-skills/mlops/training/trl-fine-tuning/references/sft-training.md +168 -0
- package/optional-skills/mlops/training/trl-fine-tuning/templates/basic_grpo_training.py +228 -0
- package/optional-skills/mlops/training/unsloth/SKILL.md +84 -0
- package/optional-skills/mlops/training/unsloth/references/index.md +7 -0
- package/optional-skills/mlops/training/unsloth/references/llms-full.md +16799 -0
- package/optional-skills/mlops/training/unsloth/references/llms-txt.md +12044 -0
- package/optional-skills/mlops/training/unsloth/references/llms.md +82 -0
- package/optional-skills/mlops/whisper/SKILL.md +321 -0
- package/optional-skills/mlops/whisper/references/languages.md +189 -0
- package/optional-skills/productivity/canvas/SKILL.md +98 -0
- package/optional-skills/productivity/canvas/scripts/canvas_api.py +157 -0
- package/optional-skills/productivity/here-now/SKILL.md +217 -0
- package/optional-skills/productivity/here-now/scripts/drive.sh +406 -0
- package/optional-skills/productivity/here-now/scripts/publish.sh +445 -0
- package/optional-skills/productivity/memento-flashcards/SKILL.md +324 -0
- package/optional-skills/productivity/memento-flashcards/scripts/memento_cards.py +353 -0
- package/optional-skills/productivity/memento-flashcards/scripts/youtube_quiz.py +88 -0
- package/optional-skills/productivity/shop-app/SKILL.md +340 -0
- package/optional-skills/productivity/shopify/SKILL.md +373 -0
- package/optional-skills/productivity/siyuan/SKILL.md +298 -0
- package/optional-skills/productivity/telephony/SKILL.md +418 -0
- package/optional-skills/productivity/telephony/scripts/telephony.py +1343 -0
- package/optional-skills/research/bioinformatics/SKILL.md +235 -0
- package/optional-skills/research/darwinian-evolver/SKILL.md +199 -0
- package/optional-skills/research/darwinian-evolver/scripts/parrot_openrouter.py +218 -0
- package/optional-skills/research/darwinian-evolver/scripts/show_snapshot.py +69 -0
- package/optional-skills/research/darwinian-evolver/templates/custom_problem_template.py +240 -0
- package/optional-skills/research/domain-intel/SKILL.md +97 -0
- package/optional-skills/research/domain-intel/scripts/domain_intel.py +397 -0
- package/optional-skills/research/drug-discovery/SKILL.md +227 -0
- package/optional-skills/research/drug-discovery/references/ADMET_REFERENCE.md +66 -0
- package/optional-skills/research/drug-discovery/scripts/chembl_target.py +53 -0
- package/optional-skills/research/drug-discovery/scripts/ro5_screen.py +44 -0
- package/optional-skills/research/duckduckgo-search/SKILL.md +238 -0
- package/optional-skills/research/duckduckgo-search/scripts/duckduckgo.sh +28 -0
- package/optional-skills/research/gitnexus-explorer/SKILL.md +214 -0
- package/optional-skills/research/gitnexus-explorer/scripts/proxy.mjs +92 -0
- package/optional-skills/research/osint-investigation/SKILL.md +277 -0
- package/optional-skills/research/osint-investigation/references/sources/courtlistener.md +98 -0
- package/optional-skills/research/osint-investigation/references/sources/gdelt.md +104 -0
- package/optional-skills/research/osint-investigation/references/sources/icij-offshore.md +104 -0
- package/optional-skills/research/osint-investigation/references/sources/nyc-acris.md +90 -0
- package/optional-skills/research/osint-investigation/references/sources/ofac-sdn.md +92 -0
- package/optional-skills/research/osint-investigation/references/sources/opencorporates.md +103 -0
- package/optional-skills/research/osint-investigation/references/sources/sec-edgar.md +83 -0
- package/optional-skills/research/osint-investigation/references/sources/senate-ld.md +89 -0
- package/optional-skills/research/osint-investigation/references/sources/usaspending.md +97 -0
- package/optional-skills/research/osint-investigation/references/sources/wayback.md +93 -0
- package/optional-skills/research/osint-investigation/references/sources/wikipedia.md +107 -0
- package/optional-skills/research/osint-investigation/scripts/_http.py +82 -0
- package/optional-skills/research/osint-investigation/scripts/_normalize.py +67 -0
- package/optional-skills/research/osint-investigation/scripts/build_findings.py +221 -0
- package/optional-skills/research/osint-investigation/scripts/entity_resolution.py +228 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_courtlistener.py +149 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py +162 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py +192 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_senate_ld.py +146 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_usaspending.py +170 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_wayback.py +142 -0
- package/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py +267 -0
- package/optional-skills/research/osint-investigation/scripts/timing_analysis.py +253 -0
- package/optional-skills/research/osint-investigation/templates/source-template.md +59 -0
- package/optional-skills/research/parallel-cli/SKILL.md +391 -0
- package/optional-skills/research/qmd/SKILL.md +441 -0
- package/optional-skills/research/scrapling/SKILL.md +336 -0
- package/optional-skills/research/searxng-search/SKILL.md +212 -0
- package/optional-skills/research/searxng-search/scripts/searxng.sh +22 -0
- package/optional-skills/security/1password/SKILL.md +163 -0
- package/optional-skills/security/1password/references/cli-examples.md +31 -0
- package/optional-skills/security/1password/references/get-started.md +21 -0
- package/optional-skills/security/DESCRIPTION.md +3 -0
- package/optional-skills/security/oss-forensics/SKILL.md +423 -0
- package/optional-skills/security/oss-forensics/references/evidence-types.md +89 -0
- package/optional-skills/security/oss-forensics/references/github-archive-guide.md +184 -0
- package/optional-skills/security/oss-forensics/references/investigation-templates.md +131 -0
- package/optional-skills/security/oss-forensics/references/recovery-techniques.md +164 -0
- package/optional-skills/security/oss-forensics/scripts/evidence-store.py +313 -0
- package/optional-skills/security/oss-forensics/templates/forensic-report.md +151 -0
- package/optional-skills/security/oss-forensics/templates/malicious-package-report.md +43 -0
- package/optional-skills/security/sherlock/SKILL.md +193 -0
- package/optional-skills/software-development/rest-graphql-debug/SKILL.md +514 -0
- package/optional-skills/web-development/DESCRIPTION.md +5 -0
- package/optional-skills/web-development/page-agent/SKILL.md +190 -0
- package/package.json +78 -0
- package/plugins/__init__.py +1 -0
- package/plugins/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/context_engine/__init__.py +219 -0
- package/plugins/disk-cleanup/README.md +51 -0
- package/plugins/disk-cleanup/__init__.py +316 -0
- package/plugins/disk-cleanup/disk_cleanup.py +497 -0
- package/plugins/disk-cleanup/plugin.yaml +7 -0
- package/plugins/example-dashboard/dashboard/manifest.json +14 -0
- package/plugins/example-dashboard/dashboard/plugin_api.py +17 -0
- package/plugins/google_meet/README.md +131 -0
- package/plugins/google_meet/SKILL.md +148 -0
- package/plugins/google_meet/__init__.py +103 -0
- package/plugins/google_meet/audio_bridge.py +244 -0
- package/plugins/google_meet/cli.py +479 -0
- package/plugins/google_meet/meet_bot.py +852 -0
- package/plugins/google_meet/node/__init__.py +54 -0
- package/plugins/google_meet/node/cli.py +125 -0
- package/plugins/google_meet/node/client.py +107 -0
- package/plugins/google_meet/node/protocol.py +124 -0
- package/plugins/google_meet/node/registry.py +113 -0
- package/plugins/google_meet/node/server.py +201 -0
- package/plugins/google_meet/plugin.yaml +16 -0
- package/plugins/google_meet/process_manager.py +324 -0
- package/plugins/google_meet/realtime/__init__.py +10 -0
- package/plugins/google_meet/realtime/openai_client.py +332 -0
- package/plugins/google_meet/tools.py +348 -0
- package/plugins/hermes-achievements/LICENSE +21 -0
- package/plugins/hermes-achievements/README.md +150 -0
- package/plugins/hermes-achievements/dashboard/dist/index.js +732 -0
- package/plugins/hermes-achievements/dashboard/dist/style.css +146 -0
- package/plugins/hermes-achievements/dashboard/manifest.json +11 -0
- package/plugins/hermes-achievements/dashboard/plugin_api.py +1062 -0
- package/plugins/hermes-achievements/docs/achievements-performance-implementation-plan.md +157 -0
- package/plugins/hermes-achievements/docs/achievements-performance-implementation-spec.md +219 -0
- package/plugins/hermes-achievements/docs/achievements-performance-spec.md +174 -0
- package/plugins/hermes-achievements/docs/assets/achievements-dashboard-hd.png +0 -0
- package/plugins/hermes-achievements/docs/assets/achievements-tier-showcase-hd.png +0 -0
- package/plugins/hermes-achievements/tests/test_achievement_engine.py +156 -0
- package/plugins/image_gen/openai/__init__.py +303 -0
- package/plugins/image_gen/openai/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/image_gen/openai/plugin.yaml +7 -0
- package/plugins/image_gen/openai-codex/__init__.py +378 -0
- package/plugins/image_gen/openai-codex/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/image_gen/openai-codex/plugin.yaml +5 -0
- package/plugins/image_gen/xai/__init__.py +316 -0
- package/plugins/image_gen/xai/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/image_gen/xai/plugin.yaml +7 -0
- package/plugins/kanban/dashboard/dist/index.js +3143 -0
- package/plugins/kanban/dashboard/dist/style.css +1500 -0
- package/plugins/kanban/dashboard/manifest.json +14 -0
- package/plugins/kanban/dashboard/plugin_api.py +1612 -0
- package/plugins/kanban/systemd/hermes-kanban-dispatcher.service +32 -0
- package/plugins/memory/__init__.py +408 -0
- package/plugins/memory/byterover/README.md +41 -0
- package/plugins/memory/byterover/__init__.py +384 -0
- package/plugins/memory/byterover/plugin.yaml +9 -0
- package/plugins/memory/hindsight/README.md +138 -0
- package/plugins/memory/hindsight/__init__.py +1758 -0
- package/plugins/memory/hindsight/plugin.yaml +8 -0
- package/plugins/memory/holographic/README.md +36 -0
- package/plugins/memory/holographic/__init__.py +409 -0
- package/plugins/memory/holographic/holographic.py +203 -0
- package/plugins/memory/holographic/plugin.yaml +5 -0
- package/plugins/memory/holographic/retrieval.py +593 -0
- package/plugins/memory/holographic/store.py +579 -0
- package/plugins/memory/honcho/README.md +328 -0
- package/plugins/memory/honcho/__init__.py +1329 -0
- package/plugins/memory/honcho/cli.py +1452 -0
- package/plugins/memory/honcho/client.py +784 -0
- package/plugins/memory/honcho/plugin.yaml +7 -0
- package/plugins/memory/honcho/session.py +1255 -0
- package/plugins/memory/mem0/README.md +38 -0
- package/plugins/memory/mem0/__init__.py +374 -0
- package/plugins/memory/mem0/plugin.yaml +5 -0
- package/plugins/memory/openviking/README.md +40 -0
- package/plugins/memory/openviking/__init__.py +945 -0
- package/plugins/memory/openviking/plugin.yaml +9 -0
- package/plugins/memory/retaindb/README.md +40 -0
- package/plugins/memory/retaindb/__init__.py +767 -0
- package/plugins/memory/retaindb/plugin.yaml +7 -0
- package/plugins/memory/supermemory/README.md +99 -0
- package/plugins/memory/supermemory/__init__.py +792 -0
- package/plugins/memory/supermemory/plugin.yaml +5 -0
- package/plugins/model-providers/README.md +70 -0
- package/plugins/model-providers/ai-gateway/__init__.py +43 -0
- package/plugins/model-providers/ai-gateway/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/ai-gateway/plugin.yaml +5 -0
- package/plugins/model-providers/alibaba/__init__.py +13 -0
- package/plugins/model-providers/alibaba/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/alibaba/plugin.yaml +5 -0
- package/plugins/model-providers/alibaba-coding-plan/__init__.py +21 -0
- package/plugins/model-providers/alibaba-coding-plan/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/alibaba-coding-plan/plugin.yaml +5 -0
- package/plugins/model-providers/anthropic/__init__.py +52 -0
- package/plugins/model-providers/anthropic/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/anthropic/plugin.yaml +5 -0
- package/plugins/model-providers/arcee/__init__.py +13 -0
- package/plugins/model-providers/arcee/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/arcee/plugin.yaml +5 -0
- package/plugins/model-providers/azure-foundry/__init__.py +21 -0
- package/plugins/model-providers/azure-foundry/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/azure-foundry/plugin.yaml +5 -0
- package/plugins/model-providers/bedrock/__init__.py +29 -0
- package/plugins/model-providers/bedrock/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/bedrock/plugin.yaml +5 -0
- package/plugins/model-providers/copilot/__init__.py +58 -0
- package/plugins/model-providers/copilot/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/copilot/plugin.yaml +5 -0
- package/plugins/model-providers/copilot-acp/__init__.py +34 -0
- package/plugins/model-providers/copilot-acp/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/copilot-acp/plugin.yaml +5 -0
- package/plugins/model-providers/custom/__init__.py +68 -0
- package/plugins/model-providers/custom/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/custom/plugin.yaml +5 -0
- package/plugins/model-providers/deepseek/__init__.py +99 -0
- package/plugins/model-providers/deepseek/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/deepseek/plugin.yaml +5 -0
- package/plugins/model-providers/gemini/__init__.py +72 -0
- package/plugins/model-providers/gemini/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/gemini/plugin.yaml +5 -0
- package/plugins/model-providers/gmi/__init__.py +31 -0
- package/plugins/model-providers/gmi/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/gmi/plugin.yaml +5 -0
- package/plugins/model-providers/huggingface/__init__.py +20 -0
- package/plugins/model-providers/huggingface/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/huggingface/plugin.yaml +5 -0
- package/plugins/model-providers/kilocode/__init__.py +14 -0
- package/plugins/model-providers/kilocode/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/kilocode/plugin.yaml +5 -0
- package/plugins/model-providers/kimi-coding/__init__.py +71 -0
- package/plugins/model-providers/kimi-coding/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/kimi-coding/plugin.yaml +5 -0
- package/plugins/model-providers/minimax/__init__.py +45 -0
- package/plugins/model-providers/minimax/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/minimax/plugin.yaml +5 -0
- package/plugins/model-providers/nous/__init__.py +54 -0
- package/plugins/model-providers/nous/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/nous/plugin.yaml +5 -0
- package/plugins/model-providers/novita/__init__.py +27 -0
- package/plugins/model-providers/novita/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/novita/plugin.yaml +5 -0
- package/plugins/model-providers/nvidia/__init__.py +21 -0
- package/plugins/model-providers/nvidia/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/nvidia/plugin.yaml +5 -0
- package/plugins/model-providers/ollama-cloud/__init__.py +14 -0
- package/plugins/model-providers/ollama-cloud/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/ollama-cloud/plugin.yaml +5 -0
- package/plugins/model-providers/openai-codex/__init__.py +15 -0
- package/plugins/model-providers/openai-codex/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/openai-codex/plugin.yaml +5 -0
- package/plugins/model-providers/opencode-zen/__init__.py +30 -0
- package/plugins/model-providers/opencode-zen/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/opencode-zen/plugin.yaml +5 -0
- package/plugins/model-providers/openrouter/__init__.py +115 -0
- package/plugins/model-providers/openrouter/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/openrouter/plugin.yaml +5 -0
- package/plugins/model-providers/qwen-oauth/__init__.py +82 -0
- package/plugins/model-providers/qwen-oauth/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/qwen-oauth/plugin.yaml +5 -0
- package/plugins/model-providers/stepfun/__init__.py +14 -0
- package/plugins/model-providers/stepfun/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/stepfun/plugin.yaml +5 -0
- package/plugins/model-providers/xai/__init__.py +15 -0
- package/plugins/model-providers/xai/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/xai/plugin.yaml +5 -0
- package/plugins/model-providers/xiaomi/__init__.py +14 -0
- package/plugins/model-providers/xiaomi/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/xiaomi/plugin.yaml +5 -0
- package/plugins/model-providers/zai/__init__.py +21 -0
- package/plugins/model-providers/zai/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/model-providers/zai/plugin.yaml +5 -0
- package/plugins/observability/langfuse/README.md +53 -0
- package/plugins/observability/langfuse/__init__.py +1004 -0
- package/plugins/observability/langfuse/plugin.yaml +14 -0
- package/plugins/platforms/google_chat/__init__.py +3 -0
- package/plugins/platforms/google_chat/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/platforms/google_chat/__pycache__/adapter.cpython-312.pyc +0 -0
- package/plugins/platforms/google_chat/adapter.py +3343 -0
- package/plugins/platforms/google_chat/oauth.py +639 -0
- package/plugins/platforms/google_chat/plugin.yaml +39 -0
- package/plugins/platforms/irc/__init__.py +3 -0
- package/plugins/platforms/irc/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/platforms/irc/__pycache__/adapter.cpython-312.pyc +0 -0
- package/plugins/platforms/irc/adapter.py +969 -0
- package/plugins/platforms/irc/plugin.yaml +54 -0
- package/plugins/platforms/line/__init__.py +3 -0
- package/plugins/platforms/line/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/platforms/line/__pycache__/adapter.cpython-312.pyc +0 -0
- package/plugins/platforms/line/adapter.py +1639 -0
- package/plugins/platforms/line/plugin.yaml +65 -0
- package/plugins/platforms/simplex/__init__.py +3 -0
- package/plugins/platforms/simplex/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/platforms/simplex/__pycache__/adapter.cpython-312.pyc +0 -0
- package/plugins/platforms/simplex/adapter.py +746 -0
- package/plugins/platforms/simplex/plugin.yaml +37 -0
- package/plugins/platforms/teams/__init__.py +3 -0
- package/plugins/platforms/teams/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/platforms/teams/__pycache__/adapter.cpython-312.pyc +0 -0
- package/plugins/platforms/teams/adapter.py +1188 -0
- package/plugins/platforms/teams/plugin.yaml +48 -0
- package/plugins/spotify/__init__.py +66 -0
- package/plugins/spotify/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/spotify/__pycache__/client.cpython-312.pyc +0 -0
- package/plugins/spotify/__pycache__/tools.cpython-312.pyc +0 -0
- package/plugins/spotify/client.py +435 -0
- package/plugins/spotify/plugin.yaml +13 -0
- package/plugins/spotify/tools.py +454 -0
- package/plugins/teams_pipeline/__init__.py +23 -0
- package/plugins/teams_pipeline/cli.py +463 -0
- package/plugins/teams_pipeline/meetings.py +333 -0
- package/plugins/teams_pipeline/models.py +350 -0
- package/plugins/teams_pipeline/pipeline.py +692 -0
- package/plugins/teams_pipeline/plugin.yaml +9 -0
- package/plugins/teams_pipeline/runtime.py +135 -0
- package/plugins/teams_pipeline/store.py +194 -0
- package/plugins/teams_pipeline/subscriptions.py +249 -0
- package/plugins/video_gen/fal/__init__.py +523 -0
- package/plugins/video_gen/fal/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/video_gen/fal/plugin.yaml +7 -0
- package/plugins/video_gen/xai/__init__.py +441 -0
- package/plugins/video_gen/xai/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/video_gen/xai/plugin.yaml +7 -0
- package/plugins/web/__init__.py +7 -0
- package/plugins/web/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/brave_free/__init__.py +14 -0
- package/plugins/web/brave_free/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/brave_free/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/brave_free/plugin.yaml +7 -0
- package/plugins/web/brave_free/provider.py +137 -0
- package/plugins/web/ddgs/__init__.py +15 -0
- package/plugins/web/ddgs/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/ddgs/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/ddgs/plugin.yaml +7 -0
- package/plugins/web/ddgs/provider.py +104 -0
- package/plugins/web/exa/__init__.py +15 -0
- package/plugins/web/exa/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/exa/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/exa/plugin.yaml +7 -0
- package/plugins/web/exa/provider.py +212 -0
- package/plugins/web/firecrawl/__init__.py +28 -0
- package/plugins/web/firecrawl/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/firecrawl/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/firecrawl/plugin.yaml +7 -0
- package/plugins/web/firecrawl/provider.py +773 -0
- package/plugins/web/parallel/__init__.py +16 -0
- package/plugins/web/parallel/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/parallel/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/parallel/plugin.yaml +7 -0
- package/plugins/web/parallel/provider.py +291 -0
- package/plugins/web/searxng/__init__.py +15 -0
- package/plugins/web/searxng/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/searxng/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/searxng/plugin.yaml +7 -0
- package/plugins/web/searxng/provider.py +140 -0
- package/plugins/web/tavily/__init__.py +15 -0
- package/plugins/web/tavily/__pycache__/__init__.cpython-312.pyc +0 -0
- package/plugins/web/tavily/__pycache__/provider.cpython-312.pyc +0 -0
- package/plugins/web/tavily/plugin.yaml +7 -0
- package/plugins/web/tavily/provider.py +285 -0
- package/providers/README.md +78 -0
- package/providers/__init__.py +192 -0
- package/providers/__pycache__/__init__.cpython-312.pyc +0 -0
- package/providers/__pycache__/base.cpython-312.pyc +0 -0
- package/providers/base.py +184 -0
- package/pyproject.toml +255 -0
- package/run_agent.py +16409 -0
- package/scripts/benchmark_browser_eval.py +138 -0
- package/scripts/build_model_catalog.py +95 -0
- package/scripts/build_skills_index.py +325 -0
- package/scripts/check-windows-footguns.py +624 -0
- package/scripts/contributor_audit.py +473 -0
- package/scripts/discord-voice-doctor.py +396 -0
- package/scripts/hermes-gateway +416 -0
- package/scripts/install.cmd +28 -0
- package/scripts/install.ps1 +1611 -0
- package/scripts/install.sh +2007 -0
- package/scripts/install_psutil_android.py +117 -0
- package/scripts/keystroke_diagnostic.py +81 -0
- package/scripts/kill_modal.sh +34 -0
- package/scripts/lib/node-bootstrap.sh +238 -0
- package/scripts/lint_diff.py +207 -0
- package/scripts/postinstall.js +150 -0
- package/scripts/profile-tui.py +626 -0
- package/scripts/release.py +1680 -0
- package/scripts/run_tests.sh +129 -0
- package/scripts/sample_and_compress.py +409 -0
- package/scripts/setup_open_webui.sh +349 -0
- package/scripts/whatsapp-bridge/allowlist.js +88 -0
- package/scripts/whatsapp-bridge/allowlist.test.mjs +80 -0
- package/scripts/whatsapp-bridge/bridge.js +729 -0
- package/scripts/whatsapp-bridge/package-lock.json +2141 -0
- package/scripts/whatsapp-bridge/package.json +19 -0
- package/skills/apple/DESCRIPTION.md +2 -0
- package/skills/apple/apple-notes/SKILL.md +90 -0
- package/skills/apple/apple-reminders/SKILL.md +98 -0
- package/skills/apple/findmy/SKILL.md +131 -0
- package/skills/apple/imessage/SKILL.md +102 -0
- package/skills/apple/macos-computer-use/SKILL.md +201 -0
- package/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
- package/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
- package/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
- package/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1014 -0
- package/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
- package/skills/creative/DESCRIPTION.md +3 -0
- package/skills/creative/architecture-diagram/SKILL.md +148 -0
- package/skills/creative/architecture-diagram/templates/template.html +319 -0
- package/skills/creative/ascii-art/SKILL.md +322 -0
- package/skills/creative/ascii-video/README.md +290 -0
- package/skills/creative/ascii-video/SKILL.md +241 -0
- package/skills/creative/ascii-video/references/architecture.md +802 -0
- package/skills/creative/ascii-video/references/composition.md +892 -0
- package/skills/creative/ascii-video/references/effects.md +1865 -0
- package/skills/creative/ascii-video/references/inputs.md +685 -0
- package/skills/creative/ascii-video/references/optimization.md +688 -0
- package/skills/creative/ascii-video/references/scenes.md +1011 -0
- package/skills/creative/ascii-video/references/shaders.md +1385 -0
- package/skills/creative/ascii-video/references/troubleshooting.md +367 -0
- package/skills/creative/baoyu-comic/PORT_NOTES.md +77 -0
- package/skills/creative/baoyu-comic/SKILL.md +247 -0
- package/skills/creative/baoyu-comic/references/analysis-framework.md +176 -0
- package/skills/creative/baoyu-comic/references/art-styles/chalk.md +101 -0
- package/skills/creative/baoyu-comic/references/art-styles/ink-brush.md +97 -0
- package/skills/creative/baoyu-comic/references/art-styles/ligne-claire.md +75 -0
- package/skills/creative/baoyu-comic/references/art-styles/manga.md +93 -0
- package/skills/creative/baoyu-comic/references/art-styles/minimalist.md +84 -0
- package/skills/creative/baoyu-comic/references/art-styles/realistic.md +89 -0
- package/skills/creative/baoyu-comic/references/auto-selection.md +71 -0
- package/skills/creative/baoyu-comic/references/base-prompt.md +98 -0
- package/skills/creative/baoyu-comic/references/character-template.md +180 -0
- package/skills/creative/baoyu-comic/references/layouts/cinematic.md +23 -0
- package/skills/creative/baoyu-comic/references/layouts/dense.md +23 -0
- package/skills/creative/baoyu-comic/references/layouts/four-panel.md +40 -0
- package/skills/creative/baoyu-comic/references/layouts/mixed.md +23 -0
- package/skills/creative/baoyu-comic/references/layouts/splash.md +23 -0
- package/skills/creative/baoyu-comic/references/layouts/standard.md +23 -0
- package/skills/creative/baoyu-comic/references/layouts/webtoon.md +30 -0
- package/skills/creative/baoyu-comic/references/ohmsha-guide.md +85 -0
- package/skills/creative/baoyu-comic/references/partial-workflows.md +106 -0
- package/skills/creative/baoyu-comic/references/presets/concept-story.md +121 -0
- package/skills/creative/baoyu-comic/references/presets/four-panel.md +107 -0
- package/skills/creative/baoyu-comic/references/presets/ohmsha.md +114 -0
- package/skills/creative/baoyu-comic/references/presets/shoujo.md +116 -0
- package/skills/creative/baoyu-comic/references/presets/wuxia.md +110 -0
- package/skills/creative/baoyu-comic/references/storyboard-template.md +143 -0
- package/skills/creative/baoyu-comic/references/tones/action.md +110 -0
- package/skills/creative/baoyu-comic/references/tones/dramatic.md +95 -0
- package/skills/creative/baoyu-comic/references/tones/energetic.md +105 -0
- package/skills/creative/baoyu-comic/references/tones/neutral.md +63 -0
- package/skills/creative/baoyu-comic/references/tones/romantic.md +100 -0
- package/skills/creative/baoyu-comic/references/tones/vintage.md +104 -0
- package/skills/creative/baoyu-comic/references/tones/warm.md +94 -0
- package/skills/creative/baoyu-comic/references/workflow.md +401 -0
- package/skills/creative/baoyu-infographic/PORT_NOTES.md +43 -0
- package/skills/creative/baoyu-infographic/SKILL.md +237 -0
- package/skills/creative/baoyu-infographic/references/analysis-framework.md +182 -0
- package/skills/creative/baoyu-infographic/references/base-prompt.md +43 -0
- package/skills/creative/baoyu-infographic/references/layouts/bento-grid.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/binary-comparison.md +48 -0
- package/skills/creative/baoyu-infographic/references/layouts/bridge.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/circular-flow.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/comic-strip.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/comparison-matrix.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/dashboard.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/dense-modules.md +72 -0
- package/skills/creative/baoyu-infographic/references/layouts/funnel.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/hierarchical-layers.md +48 -0
- package/skills/creative/baoyu-infographic/references/layouts/hub-spoke.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/iceberg.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/isometric-map.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/jigsaw.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/linear-progression.md +48 -0
- package/skills/creative/baoyu-infographic/references/layouts/periodic-table.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/story-mountain.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/structural-breakdown.md +48 -0
- package/skills/creative/baoyu-infographic/references/layouts/tree-branching.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/venn-diagram.md +41 -0
- package/skills/creative/baoyu-infographic/references/layouts/winding-roadmap.md +41 -0
- package/skills/creative/baoyu-infographic/references/structured-content-template.md +244 -0
- package/skills/creative/baoyu-infographic/references/styles/aged-academia.md +36 -0
- package/skills/creative/baoyu-infographic/references/styles/bold-graphic.md +36 -0
- package/skills/creative/baoyu-infographic/references/styles/chalkboard.md +61 -0
- package/skills/creative/baoyu-infographic/references/styles/claymation.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/corporate-memphis.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/craft-handmade.md +44 -0
- package/skills/creative/baoyu-infographic/references/styles/cyberpunk-neon.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/hand-drawn-edu.md +63 -0
- package/skills/creative/baoyu-infographic/references/styles/ikea-manual.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/kawaii.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/knolling.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/lego-brick.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/morandi-journal.md +60 -0
- package/skills/creative/baoyu-infographic/references/styles/origami.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/pixel-art.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/pop-laboratory.md +48 -0
- package/skills/creative/baoyu-infographic/references/styles/retro-pop-grid.md +47 -0
- package/skills/creative/baoyu-infographic/references/styles/storybook-watercolor.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/subway-map.md +29 -0
- package/skills/creative/baoyu-infographic/references/styles/technical-schematic.md +36 -0
- package/skills/creative/baoyu-infographic/references/styles/ui-wireframe.md +29 -0
- package/skills/creative/claude-design/SKILL.md +591 -0
- package/skills/creative/comfyui/SKILL.md +612 -0
- package/skills/creative/comfyui/references/official-cli.md +255 -0
- package/skills/creative/comfyui/references/rest-api.md +312 -0
- package/skills/creative/comfyui/references/template-integrity.md +243 -0
- package/skills/creative/comfyui/references/workflow-format.md +226 -0
- package/skills/creative/comfyui/scripts/_common.py +835 -0
- package/skills/creative/comfyui/scripts/auto_fix_deps.py +225 -0
- package/skills/creative/comfyui/scripts/check_deps.py +437 -0
- package/skills/creative/comfyui/scripts/comfyui_setup.sh +286 -0
- package/skills/creative/comfyui/scripts/extract_schema.py +315 -0
- package/skills/creative/comfyui/scripts/fetch_logs.py +158 -0
- package/skills/creative/comfyui/scripts/hardware_check.py +497 -0
- package/skills/creative/comfyui/scripts/health_check.py +223 -0
- package/skills/creative/comfyui/scripts/run_batch.py +243 -0
- package/skills/creative/comfyui/scripts/run_workflow.py +796 -0
- package/skills/creative/comfyui/scripts/ws_monitor.py +267 -0
- package/skills/creative/comfyui/tests/README.md +50 -0
- package/skills/creative/comfyui/tests/conftest.py +64 -0
- package/skills/creative/comfyui/tests/pytest.ini +5 -0
- package/skills/creative/comfyui/tests/test_check_deps.py +68 -0
- package/skills/creative/comfyui/tests/test_cloud_integration.py +95 -0
- package/skills/creative/comfyui/tests/test_common.py +447 -0
- package/skills/creative/comfyui/tests/test_extract_schema.py +185 -0
- package/skills/creative/comfyui/tests/test_run_workflow.py +213 -0
- package/skills/creative/comfyui/workflows/README.md +86 -0
- package/skills/creative/comfyui/workflows/animatediff_video.json +64 -0
- package/skills/creative/comfyui/workflows/flux_dev_txt2img.json +78 -0
- package/skills/creative/comfyui/workflows/sd15_txt2img.json +49 -0
- package/skills/creative/comfyui/workflows/sdxl_img2img.json +54 -0
- package/skills/creative/comfyui/workflows/sdxl_inpaint.json +59 -0
- package/skills/creative/comfyui/workflows/sdxl_txt2img.json +49 -0
- package/skills/creative/comfyui/workflows/upscale_4x.json +27 -0
- package/skills/creative/comfyui/workflows/wan_video_t2v.json +69 -0
- package/skills/creative/creative-ideation/SKILL.md +152 -0
- package/skills/creative/creative-ideation/references/full-prompt-library.md +110 -0
- package/skills/creative/design-md/SKILL.md +199 -0
- package/skills/creative/design-md/templates/starter.md +99 -0
- package/skills/creative/excalidraw/SKILL.md +199 -0
- package/skills/creative/excalidraw/references/colors.md +44 -0
- package/skills/creative/excalidraw/references/dark-mode.md +68 -0
- package/skills/creative/excalidraw/references/examples.md +141 -0
- package/skills/creative/excalidraw/scripts/upload.py +133 -0
- package/skills/creative/humanizer/LICENSE +21 -0
- package/skills/creative/humanizer/SKILL.md +578 -0
- package/skills/creative/manim-video/README.md +23 -0
- package/skills/creative/manim-video/SKILL.md +269 -0
- package/skills/creative/manim-video/references/animation-design-thinking.md +161 -0
- package/skills/creative/manim-video/references/animations.md +282 -0
- package/skills/creative/manim-video/references/camera-and-3d.md +135 -0
- package/skills/creative/manim-video/references/decorations.md +202 -0
- package/skills/creative/manim-video/references/equations.md +216 -0
- package/skills/creative/manim-video/references/graphs-and-data.md +163 -0
- package/skills/creative/manim-video/references/mobjects.md +333 -0
- package/skills/creative/manim-video/references/paper-explainer.md +255 -0
- package/skills/creative/manim-video/references/production-quality.md +190 -0
- package/skills/creative/manim-video/references/rendering.md +185 -0
- package/skills/creative/manim-video/references/scene-planning.md +118 -0
- package/skills/creative/manim-video/references/troubleshooting.md +135 -0
- package/skills/creative/manim-video/references/updaters-and-trackers.md +260 -0
- package/skills/creative/manim-video/references/visual-design.md +124 -0
- package/skills/creative/manim-video/scripts/setup.sh +14 -0
- package/skills/creative/p5js/README.md +64 -0
- package/skills/creative/p5js/SKILL.md +556 -0
- package/skills/creative/p5js/references/animation.md +439 -0
- package/skills/creative/p5js/references/color-systems.md +352 -0
- package/skills/creative/p5js/references/core-api.md +410 -0
- package/skills/creative/p5js/references/export-pipeline.md +566 -0
- package/skills/creative/p5js/references/interaction.md +398 -0
- package/skills/creative/p5js/references/shapes-and-geometry.md +300 -0
- package/skills/creative/p5js/references/troubleshooting.md +532 -0
- package/skills/creative/p5js/references/typography.md +302 -0
- package/skills/creative/p5js/references/visual-effects.md +895 -0
- package/skills/creative/p5js/references/webgl-and-3d.md +423 -0
- package/skills/creative/p5js/scripts/export-frames.js +179 -0
- package/skills/creative/p5js/scripts/render.sh +108 -0
- package/skills/creative/p5js/scripts/serve.sh +28 -0
- package/skills/creative/p5js/scripts/setup.sh +87 -0
- package/skills/creative/p5js/templates/viewer.html +395 -0
- package/skills/creative/pixel-art/ATTRIBUTION.md +54 -0
- package/skills/creative/pixel-art/SKILL.md +218 -0
- package/skills/creative/pixel-art/references/palettes.md +49 -0
- package/skills/creative/pixel-art/scripts/__init__.py +0 -0
- package/skills/creative/pixel-art/scripts/palettes.py +167 -0
- package/skills/creative/pixel-art/scripts/pixel_art.py +162 -0
- package/skills/creative/pixel-art/scripts/pixel_art_video.py +345 -0
- package/skills/creative/popular-web-designs/SKILL.md +214 -0
- package/skills/creative/popular-web-designs/templates/airbnb.md +259 -0
- package/skills/creative/popular-web-designs/templates/airtable.md +102 -0
- package/skills/creative/popular-web-designs/templates/apple.md +326 -0
- package/skills/creative/popular-web-designs/templates/bmw.md +193 -0
- package/skills/creative/popular-web-designs/templates/cal.md +272 -0
- package/skills/creative/popular-web-designs/templates/claude.md +325 -0
- package/skills/creative/popular-web-designs/templates/clay.md +317 -0
- package/skills/creative/popular-web-designs/templates/clickhouse.md +294 -0
- package/skills/creative/popular-web-designs/templates/cohere.md +279 -0
- package/skills/creative/popular-web-designs/templates/coinbase.md +142 -0
- package/skills/creative/popular-web-designs/templates/composio.md +320 -0
- package/skills/creative/popular-web-designs/templates/cursor.md +322 -0
- package/skills/creative/popular-web-designs/templates/elevenlabs.md +278 -0
- package/skills/creative/popular-web-designs/templates/expo.md +294 -0
- package/skills/creative/popular-web-designs/templates/figma.md +233 -0
- package/skills/creative/popular-web-designs/templates/framer.md +259 -0
- package/skills/creative/popular-web-designs/templates/hashicorp.md +291 -0
- package/skills/creative/popular-web-designs/templates/ibm.md +345 -0
- package/skills/creative/popular-web-designs/templates/intercom.md +159 -0
- package/skills/creative/popular-web-designs/templates/kraken.md +138 -0
- package/skills/creative/popular-web-designs/templates/linear.app.md +380 -0
- package/skills/creative/popular-web-designs/templates/lovable.md +311 -0
- package/skills/creative/popular-web-designs/templates/minimax.md +270 -0
- package/skills/creative/popular-web-designs/templates/mintlify.md +339 -0
- package/skills/creative/popular-web-designs/templates/miro.md +121 -0
- package/skills/creative/popular-web-designs/templates/mistral.ai.md +274 -0
- package/skills/creative/popular-web-designs/templates/mongodb.md +279 -0
- package/skills/creative/popular-web-designs/templates/notion.md +322 -0
- package/skills/creative/popular-web-designs/templates/nvidia.md +306 -0
- package/skills/creative/popular-web-designs/templates/ollama.md +280 -0
- package/skills/creative/popular-web-designs/templates/opencode.ai.md +294 -0
- package/skills/creative/popular-web-designs/templates/pinterest.md +243 -0
- package/skills/creative/popular-web-designs/templates/posthog.md +269 -0
- package/skills/creative/popular-web-designs/templates/raycast.md +281 -0
- package/skills/creative/popular-web-designs/templates/replicate.md +274 -0
- package/skills/creative/popular-web-designs/templates/resend.md +316 -0
- package/skills/creative/popular-web-designs/templates/revolut.md +198 -0
- package/skills/creative/popular-web-designs/templates/runwayml.md +257 -0
- package/skills/creative/popular-web-designs/templates/sanity.md +370 -0
- package/skills/creative/popular-web-designs/templates/sentry.md +275 -0
- package/skills/creative/popular-web-designs/templates/spacex.md +207 -0
- package/skills/creative/popular-web-designs/templates/spotify.md +259 -0
- package/skills/creative/popular-web-designs/templates/stripe.md +335 -0
- package/skills/creative/popular-web-designs/templates/supabase.md +268 -0
- package/skills/creative/popular-web-designs/templates/superhuman.md +265 -0
- package/skills/creative/popular-web-designs/templates/together.ai.md +276 -0
- package/skills/creative/popular-web-designs/templates/uber.md +308 -0
- package/skills/creative/popular-web-designs/templates/vercel.md +323 -0
- package/skills/creative/popular-web-designs/templates/voltagent.md +336 -0
- package/skills/creative/popular-web-designs/templates/warp.md +266 -0
- package/skills/creative/popular-web-designs/templates/webflow.md +105 -0
- package/skills/creative/popular-web-designs/templates/wise.md +186 -0
- package/skills/creative/popular-web-designs/templates/x.ai.md +270 -0
- package/skills/creative/popular-web-designs/templates/zapier.md +341 -0
- package/skills/creative/pretext/SKILL.md +220 -0
- package/skills/creative/pretext/references/patterns.md +258 -0
- package/skills/creative/pretext/templates/donut-orbit.html +1468 -0
- package/skills/creative/pretext/templates/hello-orb-flow.html +95 -0
- package/skills/creative/sketch/SKILL.md +218 -0
- package/skills/creative/songwriting-and-ai-music/SKILL.md +287 -0
- package/skills/creative/touchdesigner-mcp/SKILL.md +356 -0
- package/skills/creative/touchdesigner-mcp/references/3d-scene.md +275 -0
- package/skills/creative/touchdesigner-mcp/references/animation.md +221 -0
- package/skills/creative/touchdesigner-mcp/references/audio-reactive.md +175 -0
- package/skills/creative/touchdesigner-mcp/references/dat-scripting.md +352 -0
- package/skills/creative/touchdesigner-mcp/references/external-data.md +322 -0
- package/skills/creative/touchdesigner-mcp/references/geometry-comp.md +121 -0
- package/skills/creative/touchdesigner-mcp/references/glsl.md +151 -0
- package/skills/creative/touchdesigner-mcp/references/layout-compositor.md +131 -0
- package/skills/creative/touchdesigner-mcp/references/mcp-tools.md +382 -0
- package/skills/creative/touchdesigner-mcp/references/midi-osc.md +211 -0
- package/skills/creative/touchdesigner-mcp/references/network-patterns.md +966 -0
- package/skills/creative/touchdesigner-mcp/references/operator-tips.md +106 -0
- package/skills/creative/touchdesigner-mcp/references/operators.md +239 -0
- package/skills/creative/touchdesigner-mcp/references/panel-ui.md +281 -0
- package/skills/creative/touchdesigner-mcp/references/particles.md +245 -0
- package/skills/creative/touchdesigner-mcp/references/pitfalls.md +704 -0
- package/skills/creative/touchdesigner-mcp/references/postfx.md +183 -0
- package/skills/creative/touchdesigner-mcp/references/projection-mapping.md +211 -0
- package/skills/creative/touchdesigner-mcp/references/python-api.md +463 -0
- package/skills/creative/touchdesigner-mcp/references/replicator.md +198 -0
- package/skills/creative/touchdesigner-mcp/references/troubleshooting.md +244 -0
- package/skills/creative/touchdesigner-mcp/scripts/setup.sh +115 -0
- package/skills/data-science/DESCRIPTION.md +3 -0
- package/skills/data-science/jupyter-live-kernel/SKILL.md +167 -0
- package/skills/devops/kanban-orchestrator/SKILL.md +189 -0
- package/skills/devops/kanban-worker/SKILL.md +184 -0
- package/skills/devops/webhook-subscriptions/SKILL.md +204 -0
- package/skills/diagramming/DESCRIPTION.md +3 -0
- package/skills/dogfood/SKILL.md +162 -0
- package/skills/dogfood/references/issue-taxonomy.md +109 -0
- package/skills/dogfood/templates/dogfood-report-template.md +86 -0
- package/skills/domain/DESCRIPTION.md +24 -0
- package/skills/email/DESCRIPTION.md +3 -0
- package/skills/email/himalaya/SKILL.md +299 -0
- package/skills/email/himalaya/references/configuration.md +227 -0
- package/skills/email/himalaya/references/message-composition.md +199 -0
- package/skills/gaming/DESCRIPTION.md +3 -0
- package/skills/gaming/minecraft-modpack-server/SKILL.md +187 -0
- package/skills/gaming/pokemon-player/SKILL.md +216 -0
- package/skills/gifs/DESCRIPTION.md +3 -0
- package/skills/github/DESCRIPTION.md +3 -0
- package/skills/github/codebase-inspection/SKILL.md +116 -0
- package/skills/github/github-auth/SKILL.md +247 -0
- package/skills/github/github-auth/scripts/gh-env.sh +66 -0
- package/skills/github/github-code-review/SKILL.md +481 -0
- package/skills/github/github-code-review/references/review-output-template.md +74 -0
- package/skills/github/github-issues/SKILL.md +370 -0
- package/skills/github/github-issues/templates/bug-report.md +35 -0
- package/skills/github/github-issues/templates/feature-request.md +31 -0
- package/skills/github/github-pr-workflow/SKILL.md +367 -0
- package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
- package/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
- package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
- package/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
- package/skills/github/github-repo-management/SKILL.md +516 -0
- package/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
- package/skills/index-cache/anthropics_skills_skills_.json +1 -0
- package/skills/index-cache/claude_marketplace_anthropics_skills.json +1 -0
- package/skills/index-cache/lobehub_index.json +1 -0
- package/skills/index-cache/openai_skills_skills_.json +1 -0
- package/skills/inference-sh/DESCRIPTION.md +19 -0
- package/skills/mcp/DESCRIPTION.md +3 -0
- package/skills/mcp/native-mcp/SKILL.md +357 -0
- package/skills/media/DESCRIPTION.md +3 -0
- package/skills/media/gif-search/SKILL.md +91 -0
- package/skills/media/heartmula/SKILL.md +171 -0
- package/skills/media/songsee/SKILL.md +83 -0
- package/skills/media/spotify/SKILL.md +135 -0
- package/skills/media/youtube-content/SKILL.md +73 -0
- package/skills/media/youtube-content/references/output-formats.md +56 -0
- package/skills/media/youtube-content/scripts/fetch_transcript.py +124 -0
- package/skills/mlops/DESCRIPTION.md +3 -0
- package/skills/mlops/evaluation/DESCRIPTION.md +3 -0
- package/skills/mlops/evaluation/lm-evaluation-harness/SKILL.md +498 -0
- package/skills/mlops/evaluation/lm-evaluation-harness/references/api-evaluation.md +490 -0
- package/skills/mlops/evaluation/lm-evaluation-harness/references/benchmark-guide.md +488 -0
- package/skills/mlops/evaluation/lm-evaluation-harness/references/custom-tasks.md +602 -0
- package/skills/mlops/evaluation/lm-evaluation-harness/references/distributed-eval.md +519 -0
- package/skills/mlops/evaluation/weights-and-biases/SKILL.md +594 -0
- package/skills/mlops/evaluation/weights-and-biases/references/artifacts.md +584 -0
- package/skills/mlops/evaluation/weights-and-biases/references/integrations.md +700 -0
- package/skills/mlops/evaluation/weights-and-biases/references/sweeps.md +847 -0
- package/skills/mlops/huggingface-hub/SKILL.md +81 -0
- package/skills/mlops/inference/DESCRIPTION.md +3 -0
- package/skills/mlops/inference/llama-cpp/SKILL.md +249 -0
- package/skills/mlops/inference/llama-cpp/references/advanced-usage.md +504 -0
- package/skills/mlops/inference/llama-cpp/references/hub-discovery.md +168 -0
- package/skills/mlops/inference/llama-cpp/references/optimization.md +89 -0
- package/skills/mlops/inference/llama-cpp/references/quantization.md +243 -0
- package/skills/mlops/inference/llama-cpp/references/server.md +150 -0
- package/skills/mlops/inference/llama-cpp/references/troubleshooting.md +442 -0
- package/skills/mlops/inference/obliteratus/SKILL.md +342 -0
- package/skills/mlops/inference/obliteratus/references/analysis-modules.md +166 -0
- package/skills/mlops/inference/obliteratus/references/methods-guide.md +141 -0
- package/skills/mlops/inference/obliteratus/templates/abliteration-config.yaml +33 -0
- package/skills/mlops/inference/obliteratus/templates/analysis-study.yaml +40 -0
- package/skills/mlops/inference/obliteratus/templates/batch-abliteration.yaml +41 -0
- package/skills/mlops/inference/vllm/SKILL.md +372 -0
- package/skills/mlops/inference/vllm/references/optimization.md +226 -0
- package/skills/mlops/inference/vllm/references/quantization.md +284 -0
- package/skills/mlops/inference/vllm/references/server-deployment.md +255 -0
- package/skills/mlops/inference/vllm/references/troubleshooting.md +447 -0
- package/skills/mlops/models/DESCRIPTION.md +3 -0
- package/skills/mlops/models/audiocraft/SKILL.md +568 -0
- package/skills/mlops/models/audiocraft/references/advanced-usage.md +666 -0
- package/skills/mlops/models/audiocraft/references/troubleshooting.md +504 -0
- package/skills/mlops/models/segment-anything/SKILL.md +506 -0
- package/skills/mlops/models/segment-anything/references/advanced-usage.md +589 -0
- package/skills/mlops/models/segment-anything/references/troubleshooting.md +484 -0
- package/skills/mlops/research/DESCRIPTION.md +3 -0
- package/skills/mlops/research/dspy/SKILL.md +594 -0
- package/skills/mlops/research/dspy/references/examples.md +663 -0
- package/skills/mlops/research/dspy/references/modules.md +475 -0
- package/skills/mlops/research/dspy/references/optimizers.md +566 -0
- package/skills/mlops/training/DESCRIPTION.md +3 -0
- package/skills/mlops/vector-databases/DESCRIPTION.md +3 -0
- package/skills/note-taking/DESCRIPTION.md +3 -0
- package/skills/note-taking/obsidian/SKILL.md +61 -0
- package/skills/productivity/DESCRIPTION.md +3 -0
- package/skills/productivity/airtable/SKILL.md +229 -0
- package/skills/productivity/google-workspace/SKILL.md +335 -0
- package/skills/productivity/google-workspace/references/gmail-search-syntax.md +63 -0
- package/skills/productivity/google-workspace/scripts/_hermes_home.py +43 -0
- package/skills/productivity/google-workspace/scripts/google_api.py +1221 -0
- package/skills/productivity/google-workspace/scripts/gws_bridge.py +108 -0
- package/skills/productivity/google-workspace/scripts/setup.py +454 -0
- package/skills/productivity/linear/SKILL.md +380 -0
- package/skills/productivity/linear/scripts/linear_api.py +445 -0
- package/skills/productivity/maps/SKILL.md +195 -0
- package/skills/productivity/maps/scripts/maps_client.py +1298 -0
- package/skills/productivity/nano-pdf/SKILL.md +52 -0
- package/skills/productivity/notion/SKILL.md +448 -0
- package/skills/productivity/notion/references/block-types.md +112 -0
- package/skills/productivity/ocr-and-documents/DESCRIPTION.md +3 -0
- package/skills/productivity/ocr-and-documents/SKILL.md +172 -0
- package/skills/productivity/ocr-and-documents/scripts/extract_marker.py +87 -0
- package/skills/productivity/ocr-and-documents/scripts/extract_pymupdf.py +98 -0
- package/skills/productivity/powerpoint/LICENSE.txt +30 -0
- package/skills/productivity/powerpoint/SKILL.md +237 -0
- package/skills/productivity/powerpoint/editing.md +205 -0
- package/skills/productivity/powerpoint/pptxgenjs.md +420 -0
- package/skills/productivity/powerpoint/scripts/__init__.py +0 -0
- package/skills/productivity/powerpoint/scripts/add_slide.py +195 -0
- package/skills/productivity/powerpoint/scripts/clean.py +286 -0
- package/skills/productivity/powerpoint/scripts/office/helpers/__init__.py +0 -0
- package/skills/productivity/powerpoint/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/productivity/powerpoint/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/productivity/powerpoint/scripts/office/pack.py +159 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-contentTypes.xsd +42 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-coreProperties.xsd +50 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-digSig.xsd +49 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-relationships.xsd +33 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/productivity/teams-meeting-pipeline/SKILL.md +116 -0
- package/skills/red-teaming/godmode/SKILL.md +404 -0
- package/skills/red-teaming/godmode/references/jailbreak-templates.md +128 -0
- package/skills/red-teaming/godmode/references/refusal-detection.md +142 -0
- package/skills/red-teaming/godmode/scripts/auto_jailbreak.py +769 -0
- package/skills/red-teaming/godmode/scripts/godmode_race.py +530 -0
- package/skills/red-teaming/godmode/scripts/load_godmode.py +45 -0
- package/skills/red-teaming/godmode/scripts/parseltongue.py +550 -0
- package/skills/red-teaming/godmode/templates/prefill-subtle.json +10 -0
- package/skills/red-teaming/godmode/templates/prefill.json +18 -0
- package/skills/research/DESCRIPTION.md +3 -0
- package/skills/research/arxiv/SKILL.md +282 -0
- package/skills/research/arxiv/scripts/search_arxiv.py +114 -0
- package/skills/research/blogwatcher/SKILL.md +137 -0
- package/skills/research/llm-wiki/SKILL.md +507 -0
- package/skills/research/polymarket/SKILL.md +77 -0
- package/skills/research/polymarket/references/api-endpoints.md +220 -0
- package/skills/research/polymarket/scripts/polymarket.py +284 -0
- package/skills/research/research-paper-writing/SKILL.md +2377 -0
- package/skills/research/research-paper-writing/references/autoreason-methodology.md +394 -0
- package/skills/research/research-paper-writing/references/checklists.md +434 -0
- package/skills/research/research-paper-writing/references/citation-workflow.md +564 -0
- package/skills/research/research-paper-writing/references/experiment-patterns.md +728 -0
- package/skills/research/research-paper-writing/references/human-evaluation.md +476 -0
- package/skills/research/research-paper-writing/references/paper-types.md +481 -0
- package/skills/research/research-paper-writing/references/reviewer-guidelines.md +433 -0
- package/skills/research/research-paper-writing/references/sources.md +191 -0
- package/skills/research/research-paper-writing/references/writing-guide.md +474 -0
- package/skills/research/research-paper-writing/templates/README.md +251 -0
- package/skills/research/research-paper-writing/templates/aaai2026/README.md +534 -0
- package/skills/research/research-paper-writing/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
- package/skills/research/research-paper-writing/templates/aaai2026/aaai2026-unified-template.tex +952 -0
- package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.bib +111 -0
- package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.bst +1493 -0
- package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.sty +315 -0
- package/skills/research/research-paper-writing/templates/acl/README.md +50 -0
- package/skills/research/research-paper-writing/templates/acl/acl.sty +312 -0
- package/skills/research/research-paper-writing/templates/acl/acl_latex.tex +377 -0
- package/skills/research/research-paper-writing/templates/acl/acl_lualatex.tex +101 -0
- package/skills/research/research-paper-writing/templates/acl/acl_natbib.bst +1940 -0
- package/skills/research/research-paper-writing/templates/acl/anthology.bib.txt +26 -0
- package/skills/research/research-paper-writing/templates/acl/custom.bib +70 -0
- package/skills/research/research-paper-writing/templates/acl/formatting.md +326 -0
- package/skills/research/research-paper-writing/templates/colm2025/README.md +3 -0
- package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.bib +11 -0
- package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.bst +1440 -0
- package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.pdf +0 -0
- package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.sty +218 -0
- package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.tex +305 -0
- package/skills/research/research-paper-writing/templates/colm2025/fancyhdr.sty +485 -0
- package/skills/research/research-paper-writing/templates/colm2025/math_commands.tex +508 -0
- package/skills/research/research-paper-writing/templates/colm2025/natbib.sty +1246 -0
- package/skills/research/research-paper-writing/templates/iclr2026/fancyhdr.sty +485 -0
- package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.bib +24 -0
- package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.bst +1440 -0
- package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.pdf +0 -0
- package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.sty +246 -0
- package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.tex +414 -0
- package/skills/research/research-paper-writing/templates/iclr2026/math_commands.tex +508 -0
- package/skills/research/research-paper-writing/templates/iclr2026/natbib.sty +1246 -0
- package/skills/research/research-paper-writing/templates/icml2026/algorithm.sty +79 -0
- package/skills/research/research-paper-writing/templates/icml2026/algorithmic.sty +201 -0
- package/skills/research/research-paper-writing/templates/icml2026/example_paper.bib +75 -0
- package/skills/research/research-paper-writing/templates/icml2026/example_paper.pdf +0 -0
- package/skills/research/research-paper-writing/templates/icml2026/example_paper.tex +662 -0
- package/skills/research/research-paper-writing/templates/icml2026/fancyhdr.sty +864 -0
- package/skills/research/research-paper-writing/templates/icml2026/icml2026.bst +1443 -0
- package/skills/research/research-paper-writing/templates/icml2026/icml2026.sty +767 -0
- package/skills/research/research-paper-writing/templates/icml2026/icml_numpapers.pdf +0 -0
- package/skills/research/research-paper-writing/templates/neurips2025/Makefile +36 -0
- package/skills/research/research-paper-writing/templates/neurips2025/extra_pkgs.tex +53 -0
- package/skills/research/research-paper-writing/templates/neurips2025/main.tex +38 -0
- package/skills/research/research-paper-writing/templates/neurips2025/neurips.sty +382 -0
- package/skills/smart-home/DESCRIPTION.md +3 -0
- package/skills/smart-home/openhue/SKILL.md +109 -0
- package/skills/social-media/DESCRIPTION.md +3 -0
- package/skills/social-media/xurl/SKILL.md +414 -0
- package/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
- package/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
- package/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
- package/skills/software-development/plan/SKILL.md +58 -0
- package/skills/software-development/python-debugpy/SKILL.md +375 -0
- package/skills/software-development/requesting-code-review/SKILL.md +280 -0
- package/skills/software-development/spike/SKILL.md +197 -0
- package/skills/software-development/subagent-driven-development/SKILL.md +352 -0
- package/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
- package/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
- package/skills/software-development/systematic-debugging/SKILL.md +367 -0
- package/skills/software-development/test-driven-development/SKILL.md +343 -0
- package/skills/software-development/writing-plans/SKILL.md +297 -0
- package/skills/yuanbao/SKILL.md +108 -0
- package/tools/__init__.py +25 -0
- package/tools/__pycache__/__init__.cpython-312.pyc +0 -0
- package/tools/__pycache__/approval.cpython-312.pyc +0 -0
- package/tools/__pycache__/binary_extensions.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_camofox.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_camofox_state.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_cdp_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_dialog_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_supervisor.cpython-312.pyc +0 -0
- package/tools/__pycache__/browser_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/budget_config.cpython-312.pyc +0 -0
- package/tools/__pycache__/checkpoint_manager.cpython-312.pyc +0 -0
- package/tools/__pycache__/clarify_gateway.cpython-312.pyc +0 -0
- package/tools/__pycache__/clarify_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/code_execution_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/computer_use_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/cronjob_tools.cpython-312.pyc +0 -0
- package/tools/__pycache__/debug_helpers.cpython-312.pyc +0 -0
- package/tools/__pycache__/delegate_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/discord_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/feishu_doc_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/feishu_drive_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/file_operations.cpython-312.pyc +0 -0
- package/tools/__pycache__/file_state.cpython-312.pyc +0 -0
- package/tools/__pycache__/file_tools.cpython-312.pyc +0 -0
- package/tools/__pycache__/homeassistant_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/image_generation_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/interrupt.cpython-312.pyc +0 -0
- package/tools/__pycache__/kanban_tools.cpython-312.pyc +0 -0
- package/tools/__pycache__/lazy_deps.cpython-312.pyc +0 -0
- package/tools/__pycache__/managed_tool_gateway.cpython-312.pyc +0 -0
- package/tools/__pycache__/mcp_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/memory_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/mixture_of_agents_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/openrouter_client.cpython-312.pyc +0 -0
- package/tools/__pycache__/process_registry.cpython-312.pyc +0 -0
- package/tools/__pycache__/registry.cpython-312.pyc +0 -0
- package/tools/__pycache__/schema_sanitizer.cpython-312.pyc +0 -0
- package/tools/__pycache__/send_message_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/session_search_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/skill_manager_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/skill_provenance.cpython-312.pyc +0 -0
- package/tools/__pycache__/skill_usage.cpython-312.pyc +0 -0
- package/tools/__pycache__/skills_guard.cpython-312.pyc +0 -0
- package/tools/__pycache__/skills_sync.cpython-312.pyc +0 -0
- package/tools/__pycache__/skills_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/slash_confirm.cpython-312.pyc +0 -0
- package/tools/__pycache__/terminal_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/tirith_security.cpython-312.pyc +0 -0
- package/tools/__pycache__/todo_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/tool_backend_helpers.cpython-312.pyc +0 -0
- package/tools/__pycache__/tool_result_storage.cpython-312.pyc +0 -0
- package/tools/__pycache__/tts_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/url_safety.cpython-312.pyc +0 -0
- package/tools/__pycache__/video_generation_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/vision_tools.cpython-312.pyc +0 -0
- package/tools/__pycache__/voice_mode.cpython-312.pyc +0 -0
- package/tools/__pycache__/web_tools.cpython-312.pyc +0 -0
- package/tools/__pycache__/website_policy.cpython-312.pyc +0 -0
- package/tools/__pycache__/x_search_tool.cpython-312.pyc +0 -0
- package/tools/__pycache__/xai_http.cpython-312.pyc +0 -0
- package/tools/__pycache__/yuanbao_tools.cpython-312.pyc +0 -0
- package/tools/ansi_strip.py +44 -0
- package/tools/approval.py +1392 -0
- package/tools/binary_extensions.py +42 -0
- package/tools/browser_camofox.py +700 -0
- package/tools/browser_camofox_state.py +48 -0
- package/tools/browser_cdp_tool.py +569 -0
- package/tools/browser_dialog_tool.py +148 -0
- package/tools/browser_providers/__init__.py +10 -0
- package/tools/browser_providers/__pycache__/__init__.cpython-312.pyc +0 -0
- package/tools/browser_providers/__pycache__/base.cpython-312.pyc +0 -0
- package/tools/browser_providers/__pycache__/browser_use.cpython-312.pyc +0 -0
- package/tools/browser_providers/__pycache__/browserbase.cpython-312.pyc +0 -0
- package/tools/browser_providers/__pycache__/firecrawl.cpython-312.pyc +0 -0
- package/tools/browser_providers/base.py +59 -0
- package/tools/browser_providers/browser_use.py +225 -0
- package/tools/browser_providers/browserbase.py +222 -0
- package/tools/browser_providers/firecrawl.py +112 -0
- package/tools/browser_supervisor.py +1457 -0
- package/tools/browser_tool.py +3676 -0
- package/tools/budget_config.py +51 -0
- package/tools/checkpoint_manager.py +1639 -0
- package/tools/clarify_gateway.py +278 -0
- package/tools/clarify_tool.py +141 -0
- package/tools/code_execution_tool.py +1782 -0
- package/tools/computer_use/__init__.py +43 -0
- package/tools/computer_use/__pycache__/__init__.cpython-312.pyc +0 -0
- package/tools/computer_use/__pycache__/backend.cpython-312.pyc +0 -0
- package/tools/computer_use/__pycache__/schema.cpython-312.pyc +0 -0
- package/tools/computer_use/__pycache__/tool.cpython-312.pyc +0 -0
- package/tools/computer_use/backend.py +150 -0
- package/tools/computer_use/cua_backend.py +682 -0
- package/tools/computer_use/schema.py +191 -0
- package/tools/computer_use/tool.py +521 -0
- package/tools/computer_use_tool.py +39 -0
- package/tools/credential_files.py +437 -0
- package/tools/cronjob_tools.py +719 -0
- package/tools/debug_helpers.py +106 -0
- package/tools/delegate_tool.py +2797 -0
- package/tools/discord_tool.py +959 -0
- package/tools/env_passthrough.py +145 -0
- package/tools/environments/__init__.py +14 -0
- package/tools/environments/__pycache__/__init__.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/base.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/docker.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/file_sync.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/local.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/managed_modal.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/modal.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/modal_utils.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/singularity.cpython-312.pyc +0 -0
- package/tools/environments/__pycache__/ssh.cpython-312.pyc +0 -0
- package/tools/environments/base.py +844 -0
- package/tools/environments/daytona.py +270 -0
- package/tools/environments/docker.py +656 -0
- package/tools/environments/file_sync.py +400 -0
- package/tools/environments/local.py +658 -0
- package/tools/environments/managed_modal.py +282 -0
- package/tools/environments/modal.py +479 -0
- package/tools/environments/modal_utils.py +199 -0
- package/tools/environments/singularity.py +263 -0
- package/tools/environments/ssh.py +295 -0
- package/tools/environments/vercel_sandbox.py +655 -0
- package/tools/feishu_doc_tool.py +138 -0
- package/tools/feishu_drive_tool.py +431 -0
- package/tools/file_operations.py +1825 -0
- package/tools/file_state.py +332 -0
- package/tools/file_tools.py +1172 -0
- package/tools/fuzzy_match.py +703 -0
- package/tools/homeassistant_tool.py +513 -0
- package/tools/image_generation_tool.py +1098 -0
- package/tools/interrupt.py +98 -0
- package/tools/kanban_tools.py +1139 -0
- package/tools/lazy_deps.py +608 -0
- package/tools/managed_tool_gateway.py +168 -0
- package/tools/mcp_oauth.py +633 -0
- package/tools/mcp_oauth_manager.py +607 -0
- package/tools/mcp_tool.py +3483 -0
- package/tools/memory_tool.py +584 -0
- package/tools/microsoft_graph_auth.py +245 -0
- package/tools/microsoft_graph_client.py +408 -0
- package/tools/mixture_of_agents_tool.py +542 -0
- package/tools/neutts_samples/jo.txt +1 -0
- package/tools/neutts_samples/jo.wav +0 -0
- package/tools/neutts_synth.py +104 -0
- package/tools/openrouter_client.py +33 -0
- package/tools/osv_check.py +155 -0
- package/tools/patch_parser.py +592 -0
- package/tools/path_security.py +43 -0
- package/tools/process_registry.py +1534 -0
- package/tools/registry.py +589 -0
- package/tools/schema_sanitizer.py +370 -0
- package/tools/send_message_tool.py +1900 -0
- package/tools/session_search_tool.py +613 -0
- package/tools/skill_manager_tool.py +932 -0
- package/tools/skill_provenance.py +78 -0
- package/tools/skill_usage.py +610 -0
- package/tools/skills_guard.py +932 -0
- package/tools/skills_hub.py +3263 -0
- package/tools/skills_sync.py +432 -0
- package/tools/skills_tool.py +1569 -0
- package/tools/slash_confirm.py +167 -0
- package/tools/terminal_tool.py +2376 -0
- package/tools/tirith_security.py +775 -0
- package/tools/todo_tool.py +277 -0
- package/tools/tool_backend_helpers.py +144 -0
- package/tools/tool_output_limits.py +92 -0
- package/tools/tool_result_storage.py +232 -0
- package/tools/transcription_tools.py +936 -0
- package/tools/tts_tool.py +2285 -0
- package/tools/url_safety.py +330 -0
- package/tools/video_generation_tool.py +561 -0
- package/tools/vision_tools.py +1422 -0
- package/tools/voice_mode.py +1019 -0
- package/tools/web_tools.py +1551 -0
- package/tools/website_policy.py +283 -0
- package/tools/x_search_tool.py +424 -0
- package/tools/xai_http.py +83 -0
- package/tools/yuanbao_tools.py +736 -0
- package/toolset_distributions.py +364 -0
- package/toolsets.py +866 -0
- package/trajectory_compressor.py +1509 -0
- package/tui_gateway/__init__.py +0 -0
- package/tui_gateway/entry.py +251 -0
- package/tui_gateway/event_publisher.py +126 -0
- package/tui_gateway/render.py +49 -0
- package/tui_gateway/server.py +6623 -0
- package/tui_gateway/slash_worker.py +76 -0
- package/tui_gateway/transport.py +219 -0
- package/tui_gateway/ws.py +178 -0
- package/utils.py +361 -0
|
@@ -0,0 +1,1286 @@
|
|
|
1
|
+
"""Gateway streaming consumer — bridges sync agent callbacks to async platform delivery.
|
|
2
|
+
|
|
3
|
+
The agent fires stream_delta_callback(text) synchronously from its worker thread.
|
|
4
|
+
GatewayStreamConsumer:
|
|
5
|
+
1. Receives deltas via on_delta() (thread-safe, sync)
|
|
6
|
+
2. Queues them to an asyncio task via queue.Queue
|
|
7
|
+
3. The async run() task buffers, rate-limits, and progressively edits
|
|
8
|
+
a single message on the target platform
|
|
9
|
+
|
|
10
|
+
Design: Uses the edit transport (send initial message, then editMessageText).
|
|
11
|
+
This is universally supported across Telegram, Discord, and Slack.
|
|
12
|
+
|
|
13
|
+
Credit: jobless0x (#774, #1312), OutThisLife (#798), clicksingh (#697).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import asyncio
|
|
19
|
+
import logging
|
|
20
|
+
import queue
|
|
21
|
+
import re
|
|
22
|
+
import time
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from typing import Any, Callable, Optional
|
|
25
|
+
|
|
26
|
+
from gateway.platforms.base import BasePlatformAdapter as _BasePlatformAdapter
|
|
27
|
+
from gateway.platforms.base import _custom_unit_to_cp
|
|
28
|
+
from gateway.config import (
|
|
29
|
+
DEFAULT_STREAMING_EDIT_INTERVAL as _DEFAULT_STREAMING_EDIT_INTERVAL,
|
|
30
|
+
DEFAULT_STREAMING_BUFFER_THRESHOLD as _DEFAULT_STREAMING_BUFFER_THRESHOLD,
|
|
31
|
+
DEFAULT_STREAMING_CURSOR as _DEFAULT_STREAMING_CURSOR,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger("gateway.stream_consumer")
|
|
35
|
+
|
|
36
|
+
# Sentinel to signal the stream is complete
|
|
37
|
+
_DONE = object()
|
|
38
|
+
|
|
39
|
+
# Sentinel to signal a tool boundary — finalize current message and start a
|
|
40
|
+
# new one so that subsequent text appears below tool progress messages.
|
|
41
|
+
_NEW_SEGMENT = object()
|
|
42
|
+
|
|
43
|
+
# Queue marker for a completed assistant commentary message emitted between
|
|
44
|
+
# API/tool iterations (for example: "I'll inspect the repo first.").
|
|
45
|
+
_COMMENTARY = object()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class StreamConsumerConfig:
|
|
50
|
+
"""Runtime config for a single stream consumer instance."""
|
|
51
|
+
edit_interval: float = _DEFAULT_STREAMING_EDIT_INTERVAL
|
|
52
|
+
buffer_threshold: int = _DEFAULT_STREAMING_BUFFER_THRESHOLD
|
|
53
|
+
cursor: str = _DEFAULT_STREAMING_CURSOR
|
|
54
|
+
buffer_only: bool = False
|
|
55
|
+
# When >0, the final edit for a streamed response is delivered as a
|
|
56
|
+
# fresh message if the original preview has been visible for at least
|
|
57
|
+
# this many seconds. This makes the platform's visible timestamp
|
|
58
|
+
# reflect completion time instead of first-token time for long-running
|
|
59
|
+
# responses (e.g. reasoning models that stream slowly). Ported from
|
|
60
|
+
# openclaw/openclaw#72038. Default 0 = always edit in place (legacy
|
|
61
|
+
# behavior). The gateway enables this selectively per-platform.
|
|
62
|
+
fresh_final_after_seconds: float = 0.0
|
|
63
|
+
# Streaming transport selection:
|
|
64
|
+
# "auto" — prefer native draft streaming (e.g. Telegram sendMessageDraft)
|
|
65
|
+
# when the adapter + chat supports it; fall back to edit.
|
|
66
|
+
# "draft" — explicitly request native draft streaming; fall back to
|
|
67
|
+
# edit when unsupported.
|
|
68
|
+
# "edit" — progressive editMessageText (legacy behavior).
|
|
69
|
+
# "off" — handled by the gateway before the consumer is even built.
|
|
70
|
+
transport: str = "auto"
|
|
71
|
+
# Hint for the consumer about the originating chat type (e.g. "dm",
|
|
72
|
+
# "group", "supergroup", "forum"). Used to gate native draft streaming,
|
|
73
|
+
# which is platform-specific (Telegram drafts are DM-only).
|
|
74
|
+
chat_type: str = ""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class GatewayStreamConsumer:
|
|
78
|
+
"""Async consumer that progressively edits a platform message with streamed tokens.
|
|
79
|
+
|
|
80
|
+
Usage::
|
|
81
|
+
|
|
82
|
+
consumer = GatewayStreamConsumer(adapter, chat_id, config, metadata=metadata)
|
|
83
|
+
# Pass consumer.on_delta as stream_delta_callback to AIAgent
|
|
84
|
+
agent = AIAgent(..., stream_delta_callback=consumer.on_delta)
|
|
85
|
+
# Start the consumer as an asyncio task
|
|
86
|
+
task = asyncio.create_task(consumer.run())
|
|
87
|
+
# ... run agent in thread pool ...
|
|
88
|
+
consumer.finish() # signal completion
|
|
89
|
+
await task # wait for final edit
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
# After this many consecutive flood-control failures, permanently disable
|
|
93
|
+
# progressive edits for the remainder of the stream.
|
|
94
|
+
_MAX_FLOOD_STRIKES = 3
|
|
95
|
+
|
|
96
|
+
# Reasoning/thinking tags that models emit inline in content.
|
|
97
|
+
# Must stay in sync with cli.py _OPEN_TAGS/_CLOSE_TAGS and
|
|
98
|
+
# run_agent.py _strip_think_blocks() tag variants.
|
|
99
|
+
_OPEN_THINK_TAGS = (
|
|
100
|
+
"<REASONING_SCRATCHPAD>", "<think>", "<reasoning>",
|
|
101
|
+
"<THINKING>", "<thinking>", "<thought>",
|
|
102
|
+
)
|
|
103
|
+
_CLOSE_THINK_TAGS = (
|
|
104
|
+
"</REASONING_SCRATCHPAD>", "</think>", "</reasoning>",
|
|
105
|
+
"</THINKING>", "</thinking>", "</thought>",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Class-wide monotonic counter for native-streaming draft ids. Telegram
|
|
109
|
+
# animates a draft when the same draft_id is reused across consecutive
|
|
110
|
+
# calls in the same chat, so we need a fresh non-zero id per response.
|
|
111
|
+
_draft_id_counter: int = 0
|
|
112
|
+
|
|
113
|
+
def __init__(
|
|
114
|
+
self,
|
|
115
|
+
adapter: Any,
|
|
116
|
+
chat_id: str,
|
|
117
|
+
config: Optional[StreamConsumerConfig] = None,
|
|
118
|
+
metadata: Optional[dict] = None,
|
|
119
|
+
on_new_message: Optional[callable] = None,
|
|
120
|
+
initial_reply_to_id: Optional[str] = None,
|
|
121
|
+
):
|
|
122
|
+
self.adapter = adapter
|
|
123
|
+
self.chat_id = chat_id
|
|
124
|
+
self.cfg = config or StreamConsumerConfig()
|
|
125
|
+
self.metadata = metadata
|
|
126
|
+
# Fired whenever a fresh content bubble is created on the platform
|
|
127
|
+
# (first-send of a new message, commentary, overflow chunk, or
|
|
128
|
+
# fallback continuation). The gateway uses this to linearize the
|
|
129
|
+
# tool-progress bubble: when content resumes after a tool batch,
|
|
130
|
+
# the next tool.started should open a NEW progress bubble below
|
|
131
|
+
# the content, not edit the old bubble above it.
|
|
132
|
+
# Called with no arguments. Exceptions are swallowed.
|
|
133
|
+
self._on_new_message = on_new_message
|
|
134
|
+
self._initial_reply_to_id = initial_reply_to_id
|
|
135
|
+
self._queue: queue.Queue = queue.Queue()
|
|
136
|
+
self._accumulated = ""
|
|
137
|
+
self._message_id: Optional[str] = None
|
|
138
|
+
# Wall-clock timestamp (time.monotonic) when ``_message_id`` was
|
|
139
|
+
# first assigned from a successful first-send. Used by the
|
|
140
|
+
# fresh-final logic to detect long-lived previews whose edit
|
|
141
|
+
# timestamps would be stale by completion time. Ported from
|
|
142
|
+
# openclaw/openclaw#72038.
|
|
143
|
+
self._message_created_ts: Optional[float] = None
|
|
144
|
+
self._already_sent = False
|
|
145
|
+
self._edit_supported = True # Disabled when progressive edits are no longer usable
|
|
146
|
+
self._last_edit_time = 0.0
|
|
147
|
+
self._last_sent_text = "" # Track last-sent text to skip redundant edits
|
|
148
|
+
self._fallback_final_send = False
|
|
149
|
+
self._fallback_prefix = ""
|
|
150
|
+
self._flood_strikes = 0 # Consecutive flood-control edit failures
|
|
151
|
+
self._current_edit_interval = self.cfg.edit_interval # Adaptive backoff
|
|
152
|
+
self._final_response_sent = False
|
|
153
|
+
# Set when the final response content was sent to the user via
|
|
154
|
+
# streaming, even if the final edit (cursor removal etc.)
|
|
155
|
+
# subsequently failed.
|
|
156
|
+
self._final_content_delivered = False
|
|
157
|
+
# Cache adapter lifecycle capability: only platforms that need an
|
|
158
|
+
# explicit finalize call (e.g. DingTalk AI Cards) force us to make
|
|
159
|
+
# a redundant final edit. Everyone else keeps the fast path.
|
|
160
|
+
# Use ``is True`` (not ``bool(...)``) so MagicMock attribute access
|
|
161
|
+
# in tests doesn't incorrectly enable this path.
|
|
162
|
+
self._adapter_requires_finalize: bool = (
|
|
163
|
+
getattr(adapter, "REQUIRES_EDIT_FINALIZE", False) is True
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Think-block filter state (mirrors CLI's _stream_delta tag suppression)
|
|
167
|
+
self._in_think_block = False
|
|
168
|
+
self._think_buffer = ""
|
|
169
|
+
|
|
170
|
+
# Native draft-streaming state. Resolved at the start of run() based
|
|
171
|
+
# on cfg.transport, cfg.chat_type, and the adapter's
|
|
172
|
+
# supports_draft_streaming() probe. When True, the consumer emits
|
|
173
|
+
# animated draft frames via adapter.send_draft instead of progressive
|
|
174
|
+
# edits via adapter.edit_message. The final answer still goes
|
|
175
|
+
# through the normal first-send path so the user gets a real message
|
|
176
|
+
# in their chat history (drafts have no message_id).
|
|
177
|
+
self._use_draft_streaming = False
|
|
178
|
+
self._draft_id: Optional[int] = None
|
|
179
|
+
# Cumulative draft-frame failure count for this consumer. After the
|
|
180
|
+
# first failure we permanently disable drafts for the remainder of
|
|
181
|
+
# this response and route through edit-based for graceful degradation.
|
|
182
|
+
self._draft_failures = 0
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def already_sent(self) -> bool:
|
|
186
|
+
"""True if at least one message was sent or edited during the run."""
|
|
187
|
+
return self._already_sent
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def final_response_sent(self) -> bool:
|
|
191
|
+
"""True when the stream consumer delivered the final assistant reply."""
|
|
192
|
+
return self._final_response_sent
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def final_content_delivered(self) -> bool:
|
|
196
|
+
"""True when the final response content reached the user, even if
|
|
197
|
+
the subsequent cosmetic edit (cursor removal) failed."""
|
|
198
|
+
return self._final_content_delivered
|
|
199
|
+
|
|
200
|
+
def on_segment_break(self) -> None:
|
|
201
|
+
"""Finalize the current stream segment and start a fresh message."""
|
|
202
|
+
self._queue.put(_NEW_SEGMENT)
|
|
203
|
+
|
|
204
|
+
def on_commentary(self, text: str) -> None:
|
|
205
|
+
"""Queue a completed interim assistant commentary message."""
|
|
206
|
+
if text:
|
|
207
|
+
self._queue.put((_COMMENTARY, text))
|
|
208
|
+
|
|
209
|
+
def _notify_new_message(self) -> None:
|
|
210
|
+
"""Fire the on_new_message callback, swallowing any errors."""
|
|
211
|
+
cb = self._on_new_message
|
|
212
|
+
if cb is None:
|
|
213
|
+
return
|
|
214
|
+
try:
|
|
215
|
+
cb()
|
|
216
|
+
except Exception:
|
|
217
|
+
logger.debug("on_new_message callback error", exc_info=True)
|
|
218
|
+
|
|
219
|
+
def _reset_segment_state(self, *, preserve_no_edit: bool = False) -> None:
|
|
220
|
+
if preserve_no_edit and self._message_id == "__no_edit__":
|
|
221
|
+
return
|
|
222
|
+
self._message_id = None
|
|
223
|
+
self._message_created_ts = None
|
|
224
|
+
self._accumulated = ""
|
|
225
|
+
self._last_sent_text = ""
|
|
226
|
+
self._fallback_final_send = False
|
|
227
|
+
self._fallback_prefix = ""
|
|
228
|
+
# Native draft streaming: bump the draft_id so the next text segment
|
|
229
|
+
# animates as a fresh preview below the tool-progress bubbles, not
|
|
230
|
+
# over the prior segment's already-finalized draft. This is how
|
|
231
|
+
# we avoid the "inter-tool-call text leak" failure mode openclaw
|
|
232
|
+
# documented in their issue #32535 — each text block becomes its
|
|
233
|
+
# own visible message via the finalize, then a new draft animates
|
|
234
|
+
# for the next one.
|
|
235
|
+
if self._use_draft_streaming:
|
|
236
|
+
type(self)._draft_id_counter += 1
|
|
237
|
+
self._draft_id = type(self)._draft_id_counter
|
|
238
|
+
|
|
239
|
+
def on_delta(self, text: str) -> None:
|
|
240
|
+
"""Thread-safe callback — called from the agent's worker thread.
|
|
241
|
+
|
|
242
|
+
When *text* is ``None``, signals a tool boundary: the current message
|
|
243
|
+
is finalized and subsequent text will be sent as a new message so it
|
|
244
|
+
appears below any tool-progress messages the gateway sent in between.
|
|
245
|
+
"""
|
|
246
|
+
if text:
|
|
247
|
+
self._queue.put(text)
|
|
248
|
+
elif text is None:
|
|
249
|
+
self.on_segment_break()
|
|
250
|
+
|
|
251
|
+
def finish(self) -> None:
|
|
252
|
+
"""Signal that the stream is complete."""
|
|
253
|
+
self._queue.put(_DONE)
|
|
254
|
+
|
|
255
|
+
# ── Think-block filtering ────────────────────────────────────────
|
|
256
|
+
# Models like MiniMax emit inline <think>...</think> blocks in their
|
|
257
|
+
# content. The CLI's _stream_delta suppresses these via a state
|
|
258
|
+
# machine; we do the same here so gateway users never see raw
|
|
259
|
+
# reasoning tags. The agent also strips them from the final
|
|
260
|
+
# response (run_agent.py _strip_think_blocks), but the stream
|
|
261
|
+
# consumer sends intermediate edits before that stripping happens.
|
|
262
|
+
|
|
263
|
+
def _filter_and_accumulate(self, text: str) -> None:
|
|
264
|
+
"""Add a text delta to the accumulated buffer, suppressing think blocks.
|
|
265
|
+
|
|
266
|
+
Uses a state machine that tracks whether we are inside a
|
|
267
|
+
reasoning/thinking block. Text inside such blocks is silently
|
|
268
|
+
discarded. Partial tags at buffer boundaries are held back in
|
|
269
|
+
``_think_buffer`` until enough characters arrive to decide.
|
|
270
|
+
"""
|
|
271
|
+
buf = self._think_buffer + text
|
|
272
|
+
self._think_buffer = ""
|
|
273
|
+
|
|
274
|
+
while buf:
|
|
275
|
+
if self._in_think_block:
|
|
276
|
+
# Look for the earliest closing tag
|
|
277
|
+
best_idx = -1
|
|
278
|
+
best_len = 0
|
|
279
|
+
for tag in self._CLOSE_THINK_TAGS:
|
|
280
|
+
idx = buf.find(tag)
|
|
281
|
+
if idx != -1 and (best_idx == -1 or idx < best_idx):
|
|
282
|
+
best_idx = idx
|
|
283
|
+
best_len = len(tag)
|
|
284
|
+
|
|
285
|
+
if best_len:
|
|
286
|
+
# Found closing tag — discard block, process remainder
|
|
287
|
+
self._in_think_block = False
|
|
288
|
+
buf = buf[best_idx + best_len:]
|
|
289
|
+
else:
|
|
290
|
+
# No closing tag yet — hold tail that could be a
|
|
291
|
+
# partial closing tag prefix, discard the rest.
|
|
292
|
+
max_tag = max(len(t) for t in self._CLOSE_THINK_TAGS)
|
|
293
|
+
self._think_buffer = buf[-max_tag:] if len(buf) > max_tag else buf
|
|
294
|
+
return
|
|
295
|
+
else:
|
|
296
|
+
# Look for earliest opening tag at a block boundary
|
|
297
|
+
# (start of text / preceded by newline + optional whitespace).
|
|
298
|
+
# This prevents false positives when models *mention* tags
|
|
299
|
+
# in prose (e.g. "the <think> tag is used for…").
|
|
300
|
+
best_idx = -1
|
|
301
|
+
best_len = 0
|
|
302
|
+
for tag in self._OPEN_THINK_TAGS:
|
|
303
|
+
search_start = 0
|
|
304
|
+
while True:
|
|
305
|
+
idx = buf.find(tag, search_start)
|
|
306
|
+
if idx == -1:
|
|
307
|
+
break
|
|
308
|
+
# Block-boundary check (mirrors cli.py logic)
|
|
309
|
+
if idx == 0:
|
|
310
|
+
is_boundary = (
|
|
311
|
+
not self._accumulated
|
|
312
|
+
or self._accumulated.endswith("\n")
|
|
313
|
+
)
|
|
314
|
+
else:
|
|
315
|
+
preceding = buf[:idx]
|
|
316
|
+
last_nl = preceding.rfind("\n")
|
|
317
|
+
if last_nl == -1:
|
|
318
|
+
is_boundary = (
|
|
319
|
+
(not self._accumulated
|
|
320
|
+
or self._accumulated.endswith("\n"))
|
|
321
|
+
and preceding.strip() == ""
|
|
322
|
+
)
|
|
323
|
+
else:
|
|
324
|
+
is_boundary = preceding[last_nl + 1:].strip() == ""
|
|
325
|
+
|
|
326
|
+
if is_boundary and (best_idx == -1 or idx < best_idx):
|
|
327
|
+
best_idx = idx
|
|
328
|
+
best_len = len(tag)
|
|
329
|
+
break # first boundary hit for this tag is enough
|
|
330
|
+
search_start = idx + 1
|
|
331
|
+
|
|
332
|
+
if best_len:
|
|
333
|
+
# Emit text before the tag, enter think block
|
|
334
|
+
self._accumulated += buf[:best_idx]
|
|
335
|
+
self._in_think_block = True
|
|
336
|
+
buf = buf[best_idx + best_len:]
|
|
337
|
+
else:
|
|
338
|
+
# No opening tag — check for a partial tag at the tail
|
|
339
|
+
held_back = 0
|
|
340
|
+
for tag in self._OPEN_THINK_TAGS:
|
|
341
|
+
for i in range(1, len(tag)):
|
|
342
|
+
if buf.endswith(tag[:i]) and i > held_back:
|
|
343
|
+
held_back = i
|
|
344
|
+
if held_back:
|
|
345
|
+
self._accumulated += buf[:-held_back]
|
|
346
|
+
self._think_buffer = buf[-held_back:]
|
|
347
|
+
else:
|
|
348
|
+
self._accumulated += buf
|
|
349
|
+
return
|
|
350
|
+
|
|
351
|
+
def _flush_think_buffer(self) -> None:
|
|
352
|
+
"""Flush any held-back partial-tag buffer into accumulated text.
|
|
353
|
+
|
|
354
|
+
Called when the stream ends (got_done) so that partial text that
|
|
355
|
+
was held back waiting for a possible opening tag is not lost.
|
|
356
|
+
"""
|
|
357
|
+
if self._think_buffer and not self._in_think_block:
|
|
358
|
+
self._accumulated += self._think_buffer
|
|
359
|
+
self._think_buffer = ""
|
|
360
|
+
|
|
361
|
+
async def run(self) -> None:
|
|
362
|
+
"""Async task that drains the queue and edits the platform message."""
|
|
363
|
+
# Platform message length limit — leave room for cursor + formatting.
|
|
364
|
+
# Use the adapter's length function (e.g. utf16_len for Telegram) so
|
|
365
|
+
# overflow detection matches what the platform actually enforces.
|
|
366
|
+
# Gate on isinstance(BasePlatformAdapter) so test MagicMocks (whose
|
|
367
|
+
# auto-attributes return mock objects, not callables) fall back to len.
|
|
368
|
+
_len_fn: "Callable[[str], int]" = (
|
|
369
|
+
self.adapter.message_len_fn
|
|
370
|
+
if isinstance(self.adapter, _BasePlatformAdapter)
|
|
371
|
+
else len
|
|
372
|
+
)
|
|
373
|
+
_raw_limit = getattr(self.adapter, "MAX_MESSAGE_LENGTH", 4096)
|
|
374
|
+
_safe_limit = max(500, _raw_limit - _len_fn(self.cfg.cursor) - 100)
|
|
375
|
+
|
|
376
|
+
# Resolve native draft streaming once per run. When enabled the
|
|
377
|
+
# consumer routes mid-stream frames through adapter.send_draft and
|
|
378
|
+
# leaves _message_id=None so the existing got_done path delivers the
|
|
379
|
+
# final answer as a regular sendMessage (drafts have no message_id
|
|
380
|
+
# to edit).
|
|
381
|
+
self._use_draft_streaming = self._resolve_draft_streaming()
|
|
382
|
+
if self._use_draft_streaming:
|
|
383
|
+
type(self)._draft_id_counter += 1
|
|
384
|
+
self._draft_id = type(self)._draft_id_counter
|
|
385
|
+
logger.debug(
|
|
386
|
+
"Stream consumer using native-draft transport (chat=%s draft_id=%s)",
|
|
387
|
+
self.chat_id, self._draft_id,
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
while True:
|
|
392
|
+
# Drain all available items from the queue
|
|
393
|
+
got_done = False
|
|
394
|
+
got_segment_break = False
|
|
395
|
+
commentary_text = None
|
|
396
|
+
while True:
|
|
397
|
+
try:
|
|
398
|
+
item = self._queue.get_nowait()
|
|
399
|
+
if item is _DONE:
|
|
400
|
+
got_done = True
|
|
401
|
+
break
|
|
402
|
+
if item is _NEW_SEGMENT:
|
|
403
|
+
got_segment_break = True
|
|
404
|
+
break
|
|
405
|
+
if isinstance(item, tuple) and len(item) == 2 and item[0] is _COMMENTARY:
|
|
406
|
+
commentary_text = item[1]
|
|
407
|
+
break
|
|
408
|
+
self._filter_and_accumulate(item)
|
|
409
|
+
except queue.Empty:
|
|
410
|
+
break
|
|
411
|
+
|
|
412
|
+
# Flush any held-back partial-tag buffer on stream end
|
|
413
|
+
# so trailing text that was waiting for a potential open
|
|
414
|
+
# tag is not lost.
|
|
415
|
+
if got_done:
|
|
416
|
+
self._flush_think_buffer()
|
|
417
|
+
|
|
418
|
+
# Decide whether to flush an edit
|
|
419
|
+
now = time.monotonic()
|
|
420
|
+
elapsed = now - self._last_edit_time
|
|
421
|
+
should_edit = (
|
|
422
|
+
got_done
|
|
423
|
+
or got_segment_break
|
|
424
|
+
or commentary_text is not None
|
|
425
|
+
)
|
|
426
|
+
if not self.cfg.buffer_only:
|
|
427
|
+
should_edit = should_edit or (
|
|
428
|
+
(elapsed >= self._current_edit_interval
|
|
429
|
+
and self._accumulated)
|
|
430
|
+
# buffer_threshold is intentionally codepoint-based:
|
|
431
|
+
# it's a debounce heuristic ("send updates roughly
|
|
432
|
+
# every N visible characters"), not a platform-limit
|
|
433
|
+
# check. _len_fn is reserved for overflow detection.
|
|
434
|
+
or len(self._accumulated) >= self.cfg.buffer_threshold
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
current_update_visible = False
|
|
438
|
+
if should_edit and self._accumulated:
|
|
439
|
+
# Split overflow: if accumulated text exceeds the platform
|
|
440
|
+
# limit, split into properly sized chunks.
|
|
441
|
+
if (
|
|
442
|
+
_len_fn(self._accumulated) > _safe_limit
|
|
443
|
+
and self._message_id is None
|
|
444
|
+
):
|
|
445
|
+
# No existing message to edit (first message or after a
|
|
446
|
+
# segment break). Use truncate_message — the same
|
|
447
|
+
# helper the non-streaming path uses — to split with
|
|
448
|
+
# proper word/code-fence boundaries and chunk
|
|
449
|
+
# indicators like "(1/2)".
|
|
450
|
+
chunks = self.adapter.truncate_message(
|
|
451
|
+
self._accumulated, _safe_limit, len_fn=_len_fn,
|
|
452
|
+
)
|
|
453
|
+
chunks_delivered = False
|
|
454
|
+
reply_to = self._message_id or self._initial_reply_to_id
|
|
455
|
+
for chunk in chunks:
|
|
456
|
+
new_id = await self._send_new_chunk(chunk, reply_to)
|
|
457
|
+
if new_id is not None and new_id != reply_to:
|
|
458
|
+
chunks_delivered = True
|
|
459
|
+
self._accumulated = ""
|
|
460
|
+
self._last_sent_text = ""
|
|
461
|
+
self._last_edit_time = time.monotonic()
|
|
462
|
+
if got_done:
|
|
463
|
+
# Only claim final delivery if THESE chunks actually
|
|
464
|
+
# landed. ``_already_sent`` may be True from prior
|
|
465
|
+
# tool-progress edits or fallback-mode promotion (#10748)
|
|
466
|
+
# — that doesn't mean the final answer reached the user.
|
|
467
|
+
self._final_response_sent = chunks_delivered
|
|
468
|
+
if chunks_delivered:
|
|
469
|
+
self._final_content_delivered = True
|
|
470
|
+
return
|
|
471
|
+
if got_segment_break:
|
|
472
|
+
self._message_id = None
|
|
473
|
+
self._fallback_final_send = False
|
|
474
|
+
self._fallback_prefix = ""
|
|
475
|
+
continue
|
|
476
|
+
|
|
477
|
+
# Existing message: edit it with the first chunk, then
|
|
478
|
+
# start a new message for the overflow remainder.
|
|
479
|
+
while (
|
|
480
|
+
_len_fn(self._accumulated) > _safe_limit
|
|
481
|
+
and self._message_id is not None
|
|
482
|
+
and self._edit_supported
|
|
483
|
+
):
|
|
484
|
+
_cp_budget = _custom_unit_to_cp(
|
|
485
|
+
self._accumulated, _safe_limit, _len_fn,
|
|
486
|
+
)
|
|
487
|
+
split_at = self._accumulated.rfind("\n", 0, _cp_budget)
|
|
488
|
+
if split_at < _safe_limit // 2:
|
|
489
|
+
split_at = _safe_limit
|
|
490
|
+
chunk = self._accumulated[:split_at]
|
|
491
|
+
ok = await self._send_or_edit(chunk)
|
|
492
|
+
if self._fallback_final_send or not ok:
|
|
493
|
+
# Edit failed (or backed off due to flood control)
|
|
494
|
+
# while attempting to split an oversized message.
|
|
495
|
+
# Keep the full accumulated text intact so the
|
|
496
|
+
# fallback final-send path can deliver the remaining
|
|
497
|
+
# continuation without dropping content.
|
|
498
|
+
break
|
|
499
|
+
self._accumulated = self._accumulated[split_at:].lstrip("\n")
|
|
500
|
+
self._message_id = None
|
|
501
|
+
self._last_sent_text = ""
|
|
502
|
+
|
|
503
|
+
display_text = self._accumulated
|
|
504
|
+
if not got_done and not got_segment_break and commentary_text is None:
|
|
505
|
+
display_text += self.cfg.cursor
|
|
506
|
+
|
|
507
|
+
# Segment break: finalize the current message so platforms
|
|
508
|
+
# that need explicit closure (e.g. DingTalk AI Cards) don't
|
|
509
|
+
# leave the previous segment stuck in a loading state when
|
|
510
|
+
# the next segment (tool progress, next chunk) creates a
|
|
511
|
+
# new message below it. got_done has its own finalize
|
|
512
|
+
# path below so we don't finalize here for it.
|
|
513
|
+
current_update_visible = await self._send_or_edit(
|
|
514
|
+
display_text,
|
|
515
|
+
finalize=(got_done or got_segment_break),
|
|
516
|
+
)
|
|
517
|
+
self._last_edit_time = time.monotonic()
|
|
518
|
+
|
|
519
|
+
if got_done:
|
|
520
|
+
# Record that the final content reached the user even
|
|
521
|
+
# if the cosmetic final edit below fails.
|
|
522
|
+
if current_update_visible and self._accumulated:
|
|
523
|
+
self._final_content_delivered = True
|
|
524
|
+
|
|
525
|
+
# Final edit without cursor. If progressive editing failed
|
|
526
|
+
# mid-stream, send a single continuation/fallback message
|
|
527
|
+
# here instead of letting the base gateway path send the
|
|
528
|
+
# full response again.
|
|
529
|
+
if self._accumulated:
|
|
530
|
+
if self._fallback_final_send:
|
|
531
|
+
await self._send_fallback_final(self._accumulated)
|
|
532
|
+
elif (
|
|
533
|
+
current_update_visible
|
|
534
|
+
and not self._adapter_requires_finalize
|
|
535
|
+
):
|
|
536
|
+
# Mid-stream edit above already delivered the
|
|
537
|
+
# final accumulated content. Skip the redundant
|
|
538
|
+
# final edit — but only for adapters that don't
|
|
539
|
+
# need an explicit finalize signal.
|
|
540
|
+
self._final_response_sent = True
|
|
541
|
+
elif self._message_id:
|
|
542
|
+
# Either the mid-stream edit didn't run (no
|
|
543
|
+
# visible update this tick) OR the adapter needs
|
|
544
|
+
# explicit finalize=True to close the stream.
|
|
545
|
+
self._final_response_sent = await self._send_or_edit(
|
|
546
|
+
self._accumulated, finalize=True,
|
|
547
|
+
)
|
|
548
|
+
elif not self._already_sent:
|
|
549
|
+
self._final_response_sent = await self._send_or_edit(self._accumulated)
|
|
550
|
+
return
|
|
551
|
+
|
|
552
|
+
if commentary_text is not None:
|
|
553
|
+
self._reset_segment_state()
|
|
554
|
+
await self._send_commentary(commentary_text)
|
|
555
|
+
self._last_edit_time = time.monotonic()
|
|
556
|
+
self._reset_segment_state()
|
|
557
|
+
|
|
558
|
+
# Tool boundary: reset message state so the next text chunk
|
|
559
|
+
# creates a fresh message below any tool-progress messages.
|
|
560
|
+
#
|
|
561
|
+
# Exception: when _message_id is "__no_edit__" the platform
|
|
562
|
+
# never returned a real message ID (e.g. Signal, webhook with
|
|
563
|
+
# github_comment delivery). Resetting to None would re-enter
|
|
564
|
+
# the "first send" path on every tool boundary and post one
|
|
565
|
+
# platform message per tool call — that is what caused 155
|
|
566
|
+
# comments under a single PR. Instead, preserve the sentinel
|
|
567
|
+
# so the full continuation is delivered once via
|
|
568
|
+
# _send_fallback_final.
|
|
569
|
+
# (When editing fails mid-stream due to flood control the id is
|
|
570
|
+
# a real string like "msg_1", not "__no_edit__", so that case
|
|
571
|
+
# still resets and creates a fresh segment as intended.)
|
|
572
|
+
if got_segment_break:
|
|
573
|
+
# If the segment-break edit failed to deliver the
|
|
574
|
+
# accumulated content (flood control that has not yet
|
|
575
|
+
# promoted to fallback mode, or fallback mode itself),
|
|
576
|
+
# _accumulated still holds pre-boundary text the user
|
|
577
|
+
# never saw. Flush that tail as a continuation message
|
|
578
|
+
# before the reset below wipes _accumulated — otherwise
|
|
579
|
+
# text generated before the tool boundary is silently
|
|
580
|
+
# dropped (issue #8124).
|
|
581
|
+
if (
|
|
582
|
+
self._accumulated
|
|
583
|
+
and not current_update_visible
|
|
584
|
+
and self._message_id
|
|
585
|
+
and self._message_id != "__no_edit__"
|
|
586
|
+
):
|
|
587
|
+
await self._flush_segment_tail_on_edit_failure()
|
|
588
|
+
self._reset_segment_state(preserve_no_edit=True)
|
|
589
|
+
|
|
590
|
+
await asyncio.sleep(0.05) # Small yield to not busy-loop
|
|
591
|
+
|
|
592
|
+
except asyncio.CancelledError:
|
|
593
|
+
# Best-effort final edit on cancellation
|
|
594
|
+
_best_effort_ok = False
|
|
595
|
+
if self._accumulated and self._message_id:
|
|
596
|
+
try:
|
|
597
|
+
_best_effort_ok = bool(await self._send_or_edit(self._accumulated))
|
|
598
|
+
except Exception:
|
|
599
|
+
pass
|
|
600
|
+
# Only confirm final delivery if the best-effort send above
|
|
601
|
+
# actually succeeded OR if the final response was already
|
|
602
|
+
# confirmed before we were cancelled. Previously this
|
|
603
|
+
# promoted any partial send (already_sent=True) to
|
|
604
|
+
# final_response_sent — which suppressed the gateway's
|
|
605
|
+
# fallback send even when only intermediate text (e.g.
|
|
606
|
+
# "Let me search…") had been delivered, not the real answer.
|
|
607
|
+
if _best_effort_ok and not self._final_response_sent:
|
|
608
|
+
self._final_response_sent = True
|
|
609
|
+
except Exception as e:
|
|
610
|
+
logger.error("Stream consumer error: %s", e)
|
|
611
|
+
|
|
612
|
+
# Pattern to strip MEDIA:<path> tags (including optional surrounding quotes).
|
|
613
|
+
# Matches the simple cleanup regex used by the non-streaming path in
|
|
614
|
+
# gateway/platforms/base.py for post-processing.
|
|
615
|
+
_MEDIA_RE = re.compile(r'''[`"']?MEDIA:\s*\S+[`"']?''')
|
|
616
|
+
|
|
617
|
+
@staticmethod
|
|
618
|
+
def _clean_for_display(text: str) -> str:
|
|
619
|
+
"""Strip MEDIA: directives and internal markers from text before display.
|
|
620
|
+
|
|
621
|
+
The streaming path delivers raw text chunks that may include
|
|
622
|
+
``MEDIA:<path>`` tags and ``[[audio_as_voice]]`` directives meant for
|
|
623
|
+
the platform adapter's post-processing. The actual media files are
|
|
624
|
+
delivered separately via ``_deliver_media_from_response()`` after the
|
|
625
|
+
stream finishes — we just need to hide the raw directives from the
|
|
626
|
+
user.
|
|
627
|
+
"""
|
|
628
|
+
if "MEDIA:" not in text and "[[audio_as_voice]]" not in text:
|
|
629
|
+
return text
|
|
630
|
+
cleaned = text.replace("[[audio_as_voice]]", "")
|
|
631
|
+
cleaned = GatewayStreamConsumer._MEDIA_RE.sub("", cleaned)
|
|
632
|
+
# Collapse excessive blank lines left behind by removed tags
|
|
633
|
+
cleaned = re.sub(r'\n{3,}', '\n\n', cleaned)
|
|
634
|
+
# Strip trailing whitespace/newlines but preserve leading content
|
|
635
|
+
return cleaned.rstrip()
|
|
636
|
+
|
|
637
|
+
async def _send_new_chunk(self, text: str, reply_to_id: Optional[str]) -> Optional[str]:
|
|
638
|
+
"""Send a new message chunk, optionally threaded to a previous message.
|
|
639
|
+
|
|
640
|
+
Returns the message_id so callers can thread subsequent chunks.
|
|
641
|
+
"""
|
|
642
|
+
text = self._clean_for_display(text)
|
|
643
|
+
if not text.strip():
|
|
644
|
+
return reply_to_id
|
|
645
|
+
try:
|
|
646
|
+
meta = dict(self.metadata) if self.metadata else {}
|
|
647
|
+
result = await self.adapter.send(
|
|
648
|
+
chat_id=self.chat_id,
|
|
649
|
+
content=text,
|
|
650
|
+
reply_to=reply_to_id,
|
|
651
|
+
metadata=meta,
|
|
652
|
+
)
|
|
653
|
+
if result.success and result.message_id:
|
|
654
|
+
self._message_id = str(result.message_id)
|
|
655
|
+
self._already_sent = True
|
|
656
|
+
self._last_sent_text = text
|
|
657
|
+
# Fresh content bubble — close off any stale tool bubble
|
|
658
|
+
# above so the next tool starts a new bubble below.
|
|
659
|
+
self._notify_new_message()
|
|
660
|
+
return str(result.message_id)
|
|
661
|
+
else:
|
|
662
|
+
self._edit_supported = False
|
|
663
|
+
return reply_to_id
|
|
664
|
+
except Exception as e:
|
|
665
|
+
logger.error("Stream send chunk error: %s", e)
|
|
666
|
+
return reply_to_id
|
|
667
|
+
|
|
668
|
+
def _visible_prefix(self) -> str:
|
|
669
|
+
"""Return the visible text already shown in the streamed message."""
|
|
670
|
+
prefix = self._last_sent_text or ""
|
|
671
|
+
if self.cfg.cursor and prefix.endswith(self.cfg.cursor):
|
|
672
|
+
prefix = prefix[:-len(self.cfg.cursor)]
|
|
673
|
+
return self._clean_for_display(prefix)
|
|
674
|
+
|
|
675
|
+
def _continuation_text(self, final_text: str) -> str:
|
|
676
|
+
"""Return only the part of final_text the user has not already seen."""
|
|
677
|
+
prefix = self._fallback_prefix or self._visible_prefix()
|
|
678
|
+
if prefix and final_text.startswith(prefix):
|
|
679
|
+
return final_text[len(prefix):].lstrip()
|
|
680
|
+
return final_text
|
|
681
|
+
|
|
682
|
+
@staticmethod
|
|
683
|
+
def _split_text_chunks(
|
|
684
|
+
text: str, limit: int,
|
|
685
|
+
len_fn: "Callable[[str], int]" = len,
|
|
686
|
+
) -> list[str]:
|
|
687
|
+
"""Split text into reasonably sized chunks for fallback sends."""
|
|
688
|
+
if len_fn(text) <= limit:
|
|
689
|
+
return [text]
|
|
690
|
+
chunks: list[str] = []
|
|
691
|
+
remaining = text
|
|
692
|
+
while len_fn(remaining) > limit:
|
|
693
|
+
_cp_budget = _custom_unit_to_cp(remaining, limit, len_fn)
|
|
694
|
+
split_at = remaining.rfind("\n", 0, _cp_budget)
|
|
695
|
+
if split_at < limit // 2:
|
|
696
|
+
split_at = limit
|
|
697
|
+
chunks.append(remaining[:split_at])
|
|
698
|
+
remaining = remaining[split_at:].lstrip("\n")
|
|
699
|
+
if remaining:
|
|
700
|
+
chunks.append(remaining)
|
|
701
|
+
return chunks
|
|
702
|
+
|
|
703
|
+
async def _send_fallback_final(self, text: str) -> None:
|
|
704
|
+
"""Send the final continuation after streaming edits stop working.
|
|
705
|
+
|
|
706
|
+
Retries each chunk once on flood-control failures with a short delay.
|
|
707
|
+
"""
|
|
708
|
+
final_text = self._clean_for_display(text)
|
|
709
|
+
continuation = self._continuation_text(final_text)
|
|
710
|
+
self._fallback_final_send = False
|
|
711
|
+
if not continuation.strip():
|
|
712
|
+
# Nothing new to send — the visible partial already matches final text.
|
|
713
|
+
# BUT: if final_text itself has meaningful content (e.g. a timeout
|
|
714
|
+
# message after a long tool call), the prefix-based continuation
|
|
715
|
+
# calculation may wrongly conclude "already shown" because the
|
|
716
|
+
# streamed prefix was from a *previous* segment (before the tool
|
|
717
|
+
# boundary). In that case, send the full final_text as-is (#10807).
|
|
718
|
+
if final_text.strip() and final_text != self._visible_prefix():
|
|
719
|
+
continuation = final_text
|
|
720
|
+
else:
|
|
721
|
+
# Defence-in-depth for #7183: the last edit may still show the
|
|
722
|
+
# cursor character because fallback mode was entered after an
|
|
723
|
+
# edit failure left it stuck. Try one final edit to strip it
|
|
724
|
+
# so the message doesn't freeze with a visible ▉. Best-effort
|
|
725
|
+
# — if this edit also fails (flood control still active),
|
|
726
|
+
# _try_strip_cursor has already been called on fallback entry
|
|
727
|
+
# and the adaptive-backoff retries will have had their shot.
|
|
728
|
+
if (
|
|
729
|
+
self._message_id
|
|
730
|
+
and self._last_sent_text
|
|
731
|
+
and self.cfg.cursor
|
|
732
|
+
and self._last_sent_text.endswith(self.cfg.cursor)
|
|
733
|
+
):
|
|
734
|
+
clean_text = self._last_sent_text[:-len(self.cfg.cursor)]
|
|
735
|
+
try:
|
|
736
|
+
result = await self.adapter.edit_message(
|
|
737
|
+
chat_id=self.chat_id,
|
|
738
|
+
message_id=self._message_id,
|
|
739
|
+
content=clean_text,
|
|
740
|
+
)
|
|
741
|
+
if result.success:
|
|
742
|
+
self._last_sent_text = clean_text
|
|
743
|
+
except Exception:
|
|
744
|
+
pass
|
|
745
|
+
self._already_sent = True
|
|
746
|
+
self._final_response_sent = True
|
|
747
|
+
return
|
|
748
|
+
|
|
749
|
+
raw_limit = getattr(self.adapter, "MAX_MESSAGE_LENGTH", 4096)
|
|
750
|
+
_len_fn: "Callable[[str], int]" = (
|
|
751
|
+
self.adapter.message_len_fn
|
|
752
|
+
if isinstance(self.adapter, _BasePlatformAdapter)
|
|
753
|
+
else len
|
|
754
|
+
)
|
|
755
|
+
safe_limit = max(500, raw_limit - 100)
|
|
756
|
+
chunks = self._split_text_chunks(continuation, safe_limit, len_fn=_len_fn)
|
|
757
|
+
|
|
758
|
+
stale_message_id = self._message_id # partial message to clean up
|
|
759
|
+
last_message_id: Optional[str] = None
|
|
760
|
+
last_successful_chunk = ""
|
|
761
|
+
sent_any_chunk = False
|
|
762
|
+
for chunk in chunks:
|
|
763
|
+
# Try sending with one retry on flood-control errors.
|
|
764
|
+
result = None
|
|
765
|
+
for attempt in range(2):
|
|
766
|
+
result = await self.adapter.send(
|
|
767
|
+
chat_id=self.chat_id,
|
|
768
|
+
content=chunk,
|
|
769
|
+
metadata=self.metadata,
|
|
770
|
+
)
|
|
771
|
+
if result.success:
|
|
772
|
+
break
|
|
773
|
+
if attempt == 0 and self._is_flood_error(result):
|
|
774
|
+
logger.debug(
|
|
775
|
+
"Flood control on fallback send, retrying in 3s"
|
|
776
|
+
)
|
|
777
|
+
await asyncio.sleep(3.0)
|
|
778
|
+
else:
|
|
779
|
+
break # non-flood error or second attempt failed
|
|
780
|
+
|
|
781
|
+
if not result or not result.success:
|
|
782
|
+
if sent_any_chunk:
|
|
783
|
+
# Some continuation text already reached the user. Suppress
|
|
784
|
+
# the base gateway final-send path so we don't resend the
|
|
785
|
+
# full response and create another duplicate.
|
|
786
|
+
self._already_sent = True
|
|
787
|
+
self._final_response_sent = True
|
|
788
|
+
self._message_id = last_message_id
|
|
789
|
+
self._last_sent_text = last_successful_chunk
|
|
790
|
+
self._fallback_prefix = ""
|
|
791
|
+
return
|
|
792
|
+
# No fallback chunk reached the user — allow the normal gateway
|
|
793
|
+
# final-send path to try one more time.
|
|
794
|
+
self._already_sent = False
|
|
795
|
+
self._message_id = None
|
|
796
|
+
self._last_sent_text = ""
|
|
797
|
+
self._fallback_prefix = ""
|
|
798
|
+
return
|
|
799
|
+
sent_any_chunk = True
|
|
800
|
+
last_successful_chunk = chunk
|
|
801
|
+
last_message_id = result.message_id or last_message_id
|
|
802
|
+
# Each fallback chunk is a fresh platform message — notify
|
|
803
|
+
# so any stale tool-progress bubble gets closed off.
|
|
804
|
+
self._notify_new_message()
|
|
805
|
+
|
|
806
|
+
# Remove the frozen partial message so the user only sees the
|
|
807
|
+
# complete fallback response. Best-effort — if the platform doesn't
|
|
808
|
+
# implement ``delete_message``, the delete fails (flood control still
|
|
809
|
+
# active, bot lacks permission, message too old to delete), the
|
|
810
|
+
# partial remains but at least the full answer was delivered.
|
|
811
|
+
if stale_message_id and stale_message_id != last_message_id:
|
|
812
|
+
delete_fn = getattr(self.adapter, "delete_message", None)
|
|
813
|
+
if delete_fn is not None:
|
|
814
|
+
try:
|
|
815
|
+
await delete_fn(self.chat_id, stale_message_id)
|
|
816
|
+
except Exception as e:
|
|
817
|
+
logger.debug(
|
|
818
|
+
"Fallback partial cleanup failed (%s): %s",
|
|
819
|
+
stale_message_id, e,
|
|
820
|
+
)
|
|
821
|
+
|
|
822
|
+
self._message_id = last_message_id
|
|
823
|
+
self._already_sent = True
|
|
824
|
+
self._final_response_sent = True
|
|
825
|
+
self._last_sent_text = chunks[-1]
|
|
826
|
+
self._fallback_prefix = ""
|
|
827
|
+
|
|
828
|
+
def _is_flood_error(self, result) -> bool:
|
|
829
|
+
"""Check if a SendResult failure is due to flood control / rate limiting."""
|
|
830
|
+
err = getattr(result, "error", "") or ""
|
|
831
|
+
err_lower = err.lower()
|
|
832
|
+
return "flood" in err_lower or "retry after" in err_lower or "rate" in err_lower
|
|
833
|
+
|
|
834
|
+
def _resolve_draft_streaming(self) -> bool:
|
|
835
|
+
"""Decide whether this run should use native draft streaming.
|
|
836
|
+
|
|
837
|
+
Honors ``cfg.transport``:
|
|
838
|
+
* ``"edit"`` → never use drafts (legacy progressive-edit path).
|
|
839
|
+
* ``"draft"`` → require draft support; gracefully fall back to edit
|
|
840
|
+
when the adapter declines. Logs the downgrade at debug.
|
|
841
|
+
* ``"auto"`` → use drafts when the adapter supports them for this
|
|
842
|
+
chat type; otherwise edit.
|
|
843
|
+
|
|
844
|
+
Adapter eligibility is checked via
|
|
845
|
+
:meth:`BasePlatformAdapter.supports_draft_streaming`, which considers
|
|
846
|
+
the chat type (e.g. Telegram drafts are DM-only) and platform-version
|
|
847
|
+
gates (e.g. python-telegram-bot 22.6+).
|
|
848
|
+
"""
|
|
849
|
+
transport = (self.cfg.transport or "auto").lower()
|
|
850
|
+
if transport == "edit":
|
|
851
|
+
return False
|
|
852
|
+
# "off" is filtered upstream by the gateway; treat as edit defensively.
|
|
853
|
+
if transport == "off":
|
|
854
|
+
return False
|
|
855
|
+
# Test adapters are MagicMocks that don't subclass BasePlatformAdapter;
|
|
856
|
+
# default them to edit so existing test behaviour is preserved.
|
|
857
|
+
if not isinstance(self.adapter, _BasePlatformAdapter):
|
|
858
|
+
return False
|
|
859
|
+
try:
|
|
860
|
+
supported = self.adapter.supports_draft_streaming(
|
|
861
|
+
chat_type=self.cfg.chat_type or None,
|
|
862
|
+
metadata=self.metadata,
|
|
863
|
+
)
|
|
864
|
+
except Exception:
|
|
865
|
+
logger.debug("supports_draft_streaming probe raised", exc_info=True)
|
|
866
|
+
supported = False
|
|
867
|
+
if not supported:
|
|
868
|
+
if transport == "draft":
|
|
869
|
+
logger.debug(
|
|
870
|
+
"Draft streaming requested but unsupported (chat=%s, type=%r) — "
|
|
871
|
+
"falling back to edit",
|
|
872
|
+
self.chat_id, self.cfg.chat_type,
|
|
873
|
+
)
|
|
874
|
+
return False
|
|
875
|
+
return True
|
|
876
|
+
|
|
877
|
+
async def _send_draft_frame(self, text: str) -> bool:
|
|
878
|
+
"""Emit a single animated draft frame for the current accumulated text.
|
|
879
|
+
|
|
880
|
+
Returns True when the frame landed. On any failure, permanently
|
|
881
|
+
disables drafts for the remainder of this run so subsequent frames
|
|
882
|
+
flow through the edit-based path (which can adapt with flood-control
|
|
883
|
+
backoff, etc.). Drafts have no message_id and clear naturally on
|
|
884
|
+
the client when the response finalizes via a regular sendMessage.
|
|
885
|
+
"""
|
|
886
|
+
if self._draft_id is None:
|
|
887
|
+
# Defensive: should never happen — _use_draft_streaming gate is
|
|
888
|
+
# set in tandem with _draft_id in run(). Disable to be safe.
|
|
889
|
+
self._use_draft_streaming = False
|
|
890
|
+
return False
|
|
891
|
+
try:
|
|
892
|
+
result = await self.adapter.send_draft(
|
|
893
|
+
chat_id=self.chat_id,
|
|
894
|
+
draft_id=self._draft_id,
|
|
895
|
+
content=text,
|
|
896
|
+
metadata=self.metadata,
|
|
897
|
+
)
|
|
898
|
+
except Exception as e:
|
|
899
|
+
logger.debug(
|
|
900
|
+
"send_draft raised, disabling draft transport for this run: %s", e,
|
|
901
|
+
)
|
|
902
|
+
self._draft_failures += 1
|
|
903
|
+
self._use_draft_streaming = False
|
|
904
|
+
return False
|
|
905
|
+
if not getattr(result, "success", False):
|
|
906
|
+
logger.debug(
|
|
907
|
+
"send_draft returned success=False, disabling draft transport: %s",
|
|
908
|
+
getattr(result, "error", "unknown"),
|
|
909
|
+
)
|
|
910
|
+
self._draft_failures += 1
|
|
911
|
+
self._use_draft_streaming = False
|
|
912
|
+
return False
|
|
913
|
+
# Frame delivered. Track text for parity with edit-based no-op skip.
|
|
914
|
+
self._last_sent_text = text
|
|
915
|
+
return True
|
|
916
|
+
|
|
917
|
+
async def _flush_segment_tail_on_edit_failure(self) -> None:
|
|
918
|
+
"""Deliver un-sent tail content before a segment-break reset.
|
|
919
|
+
|
|
920
|
+
When an edit fails (flood control, transport error) and a tool
|
|
921
|
+
boundary arrives before the next retry, ``_accumulated`` holds text
|
|
922
|
+
that was generated but never shown to the user. Without this flush,
|
|
923
|
+
the segment reset would discard that tail and leave a frozen cursor
|
|
924
|
+
in the partial message.
|
|
925
|
+
|
|
926
|
+
Sends the tail that sits after the last successfully-delivered
|
|
927
|
+
prefix as a new message, and best-effort strips the stuck cursor
|
|
928
|
+
from the previous partial message.
|
|
929
|
+
"""
|
|
930
|
+
if not self._fallback_final_send:
|
|
931
|
+
await self._try_strip_cursor()
|
|
932
|
+
visible = self._fallback_prefix or self._visible_prefix()
|
|
933
|
+
tail = self._accumulated
|
|
934
|
+
if visible and tail.startswith(visible):
|
|
935
|
+
tail = tail[len(visible):].lstrip()
|
|
936
|
+
tail = self._clean_for_display(tail)
|
|
937
|
+
if not tail.strip():
|
|
938
|
+
return
|
|
939
|
+
try:
|
|
940
|
+
result = await self.adapter.send(
|
|
941
|
+
chat_id=self.chat_id,
|
|
942
|
+
content=tail,
|
|
943
|
+
metadata=self.metadata,
|
|
944
|
+
)
|
|
945
|
+
if result.success:
|
|
946
|
+
self._already_sent = True
|
|
947
|
+
except Exception as e:
|
|
948
|
+
logger.error("Segment-break tail flush error: %s", e)
|
|
949
|
+
|
|
950
|
+
async def _try_strip_cursor(self) -> None:
|
|
951
|
+
"""Best-effort edit to remove the cursor from the last visible message.
|
|
952
|
+
|
|
953
|
+
Called when entering fallback mode so the user doesn't see a stuck
|
|
954
|
+
cursor (▉) in the partial message.
|
|
955
|
+
"""
|
|
956
|
+
if not self._message_id or self._message_id == "__no_edit__":
|
|
957
|
+
return
|
|
958
|
+
prefix = self._visible_prefix()
|
|
959
|
+
if not prefix or not prefix.strip():
|
|
960
|
+
return
|
|
961
|
+
try:
|
|
962
|
+
await self.adapter.edit_message(
|
|
963
|
+
chat_id=self.chat_id,
|
|
964
|
+
message_id=self._message_id,
|
|
965
|
+
content=prefix,
|
|
966
|
+
)
|
|
967
|
+
self._last_sent_text = prefix
|
|
968
|
+
except Exception:
|
|
969
|
+
pass # best-effort — don't let this block the fallback path
|
|
970
|
+
|
|
971
|
+
async def _send_commentary(self, text: str) -> bool:
|
|
972
|
+
"""Send a completed interim assistant commentary message."""
|
|
973
|
+
text = self._clean_for_display(text)
|
|
974
|
+
if not text.strip():
|
|
975
|
+
return False
|
|
976
|
+
try:
|
|
977
|
+
result = await self.adapter.send(
|
|
978
|
+
chat_id=self.chat_id,
|
|
979
|
+
content=text,
|
|
980
|
+
metadata=self.metadata,
|
|
981
|
+
)
|
|
982
|
+
# Note: do NOT set _already_sent = True here.
|
|
983
|
+
# Commentary messages are interim status updates (e.g. "Using browser
|
|
984
|
+
# tool..."), not the final response. Setting already_sent would cause
|
|
985
|
+
# the final response to be incorrectly suppressed when there are
|
|
986
|
+
# multiple tool calls. See: https://github.com/NousResearch/hermes-agent/issues/10454
|
|
987
|
+
if result.success:
|
|
988
|
+
# Commentary counts as fresh content — close off any
|
|
989
|
+
# stale tool bubble above it so the next tool starts a
|
|
990
|
+
# new bubble below.
|
|
991
|
+
self._notify_new_message()
|
|
992
|
+
return result.success
|
|
993
|
+
except Exception as e:
|
|
994
|
+
logger.error("Commentary send error: %s", e)
|
|
995
|
+
return False
|
|
996
|
+
|
|
997
|
+
def _should_send_fresh_final(self) -> bool:
|
|
998
|
+
"""Return True when a long-lived preview should be replaced with a
|
|
999
|
+
fresh final message instead of an edit.
|
|
1000
|
+
|
|
1001
|
+
Conditions:
|
|
1002
|
+
- Fresh-final is enabled (``fresh_final_after_seconds > 0``).
|
|
1003
|
+
- We have a real preview message id (not the ``__no_edit__`` sentinel
|
|
1004
|
+
and not ``None``).
|
|
1005
|
+
- The preview has been visible for at least the configured threshold.
|
|
1006
|
+
|
|
1007
|
+
Ported from openclaw/openclaw#72038.
|
|
1008
|
+
"""
|
|
1009
|
+
threshold = getattr(self.cfg, "fresh_final_after_seconds", 0.0) or 0.0
|
|
1010
|
+
if threshold <= 0:
|
|
1011
|
+
return False
|
|
1012
|
+
if not self._message_id or self._message_id == "__no_edit__":
|
|
1013
|
+
return False
|
|
1014
|
+
if self._message_created_ts is None:
|
|
1015
|
+
return False
|
|
1016
|
+
age = time.monotonic() - self._message_created_ts
|
|
1017
|
+
return age >= threshold
|
|
1018
|
+
|
|
1019
|
+
async def _try_fresh_final(self, text: str) -> bool:
|
|
1020
|
+
"""Send ``text`` as a brand-new message (best-effort delete the old
|
|
1021
|
+
preview) so the platform's visible timestamp reflects completion
|
|
1022
|
+
time. Returns True on successful delivery, False on any failure so
|
|
1023
|
+
the caller falls back to the normal edit path.
|
|
1024
|
+
|
|
1025
|
+
Ported from openclaw/openclaw#72038.
|
|
1026
|
+
"""
|
|
1027
|
+
old_message_id = self._message_id
|
|
1028
|
+
try:
|
|
1029
|
+
result = await self.adapter.send(
|
|
1030
|
+
chat_id=self.chat_id,
|
|
1031
|
+
content=text,
|
|
1032
|
+
metadata=self.metadata,
|
|
1033
|
+
)
|
|
1034
|
+
except Exception as e:
|
|
1035
|
+
logger.debug("Fresh-final send failed, falling back to edit: %s", e)
|
|
1036
|
+
return False
|
|
1037
|
+
if not getattr(result, "success", False):
|
|
1038
|
+
return False
|
|
1039
|
+
# Successful fresh send — try to delete the stale preview so the
|
|
1040
|
+
# user doesn't see the old edit-stuck message underneath. Cleanup
|
|
1041
|
+
# is best-effort; platforms that don't implement ``delete_message``
|
|
1042
|
+
# just leave the preview behind (still an acceptable outcome —
|
|
1043
|
+
# the visible final timestamp is the important part).
|
|
1044
|
+
if old_message_id and old_message_id != "__no_edit__":
|
|
1045
|
+
delete_fn = getattr(self.adapter, "delete_message", None)
|
|
1046
|
+
if delete_fn is not None:
|
|
1047
|
+
try:
|
|
1048
|
+
await delete_fn(self.chat_id, old_message_id)
|
|
1049
|
+
except Exception as e:
|
|
1050
|
+
logger.debug(
|
|
1051
|
+
"Fresh-final preview cleanup failed (%s): %s",
|
|
1052
|
+
old_message_id, e,
|
|
1053
|
+
)
|
|
1054
|
+
# Adopt the new message id as the current message so subsequent
|
|
1055
|
+
# callers (e.g. overflow split loops, finalize retries) see a
|
|
1056
|
+
# consistent state.
|
|
1057
|
+
new_message_id = getattr(result, "message_id", None)
|
|
1058
|
+
if new_message_id:
|
|
1059
|
+
self._message_id = new_message_id
|
|
1060
|
+
self._message_created_ts = time.monotonic()
|
|
1061
|
+
else:
|
|
1062
|
+
# Send succeeded but platform didn't return an id — treat the
|
|
1063
|
+
# delivery as final-only and fall back to "__no_edit__" so we
|
|
1064
|
+
# don't try to edit something we can't address.
|
|
1065
|
+
self._message_id = "__no_edit__"
|
|
1066
|
+
self._message_created_ts = None
|
|
1067
|
+
self._already_sent = True
|
|
1068
|
+
self._last_sent_text = text
|
|
1069
|
+
self._final_response_sent = True
|
|
1070
|
+
return True
|
|
1071
|
+
|
|
1072
|
+
async def _send_or_edit(self, text: str, *, finalize: bool = False) -> bool:
|
|
1073
|
+
"""Send or edit the streaming message.
|
|
1074
|
+
|
|
1075
|
+
Returns True if the text was successfully delivered (sent or edited),
|
|
1076
|
+
False otherwise. Callers like the overflow split loop use this to
|
|
1077
|
+
decide whether to advance past the delivered chunk.
|
|
1078
|
+
|
|
1079
|
+
``finalize`` is True when this is the last edit in a streaming
|
|
1080
|
+
sequence.
|
|
1081
|
+
"""
|
|
1082
|
+
# Strip MEDIA: directives so they don't appear as visible text.
|
|
1083
|
+
# Media files are delivered as native attachments after the stream
|
|
1084
|
+
# finishes (via _deliver_media_from_response in gateway/run.py).
|
|
1085
|
+
text = self._clean_for_display(text)
|
|
1086
|
+
# A bare streaming cursor is not meaningful user-visible content and
|
|
1087
|
+
# can render as a stray tofu/white-box message on some clients.
|
|
1088
|
+
visible_without_cursor = text
|
|
1089
|
+
if self.cfg.cursor:
|
|
1090
|
+
visible_without_cursor = visible_without_cursor.replace(self.cfg.cursor, "")
|
|
1091
|
+
_visible_stripped = visible_without_cursor.strip()
|
|
1092
|
+
if not _visible_stripped:
|
|
1093
|
+
return True # cursor-only / whitespace-only update
|
|
1094
|
+
if not text.strip():
|
|
1095
|
+
return True # nothing to send is "success"
|
|
1096
|
+
# Guard: do not create a brand-new standalone message when the only
|
|
1097
|
+
# visible content is a handful of characters alongside the streaming
|
|
1098
|
+
# cursor. During rapid tool-calling the model often emits 1-2 tokens
|
|
1099
|
+
# before switching to tool calls; the resulting "X ▉" message risks
|
|
1100
|
+
# leaving the cursor permanently visible if the follow-up edit (to
|
|
1101
|
+
# strip the cursor on segment break) is rate-limited by the platform.
|
|
1102
|
+
# This was reported on Telegram, Matrix, and other clients where the
|
|
1103
|
+
# ▉ block character renders as a visible white box ("tofu").
|
|
1104
|
+
# Existing messages (edits) are unaffected — only first sends gated.
|
|
1105
|
+
_MIN_NEW_MSG_CHARS = 4
|
|
1106
|
+
if (self._message_id is None
|
|
1107
|
+
and self.cfg.cursor
|
|
1108
|
+
and self.cfg.cursor in text
|
|
1109
|
+
and len(_visible_stripped) < _MIN_NEW_MSG_CHARS):
|
|
1110
|
+
return True # too short for a standalone message — accumulate more
|
|
1111
|
+
|
|
1112
|
+
# Native draft streaming: route mid-stream frames through send_draft.
|
|
1113
|
+
# The final answer is delivered via the regular sendMessage path
|
|
1114
|
+
# below — drafts have no message_id so we can't finalize them
|
|
1115
|
+
# in-place; the regular sendMessage clears the draft naturally on
|
|
1116
|
+
# the client and gives the user a real message in their history.
|
|
1117
|
+
# Skip when:
|
|
1118
|
+
# * finalize=True (this is the final answer; needs to be a real message)
|
|
1119
|
+
# * an edit path is already established (message_id is set, e.g. after
|
|
1120
|
+
# a tool-boundary segment break where the prior text was finalized
|
|
1121
|
+
# as a real sendMessage and the next text segment continues editing
|
|
1122
|
+
# that one — staying on edit-based for that segment is correct).
|
|
1123
|
+
if (
|
|
1124
|
+
self._use_draft_streaming
|
|
1125
|
+
and not finalize
|
|
1126
|
+
and self._message_id is None
|
|
1127
|
+
):
|
|
1128
|
+
# No-op skip: identical to the last frame we sent.
|
|
1129
|
+
if text == self._last_sent_text:
|
|
1130
|
+
return True
|
|
1131
|
+
ok = await self._send_draft_frame(text)
|
|
1132
|
+
if ok:
|
|
1133
|
+
# Drafts mark "we put something on screen" but DO NOT set
|
|
1134
|
+
# _already_sent — that flag gates the gateway's fallback
|
|
1135
|
+
# final-send path and we still need that to fire so the
|
|
1136
|
+
# user gets a real message (drafts have no message_id).
|
|
1137
|
+
return True
|
|
1138
|
+
# Failure already disabled drafts for this run; fall through to
|
|
1139
|
+
# the regular edit/send path below.
|
|
1140
|
+
try:
|
|
1141
|
+
if self._message_id is not None:
|
|
1142
|
+
if self._edit_supported:
|
|
1143
|
+
# Skip if text is identical to what we last sent.
|
|
1144
|
+
# Exception: adapters that require an explicit finalize
|
|
1145
|
+
# call (REQUIRES_EDIT_FINALIZE) must still receive the
|
|
1146
|
+
# finalize=True edit even when content is unchanged, so
|
|
1147
|
+
# their streaming UI can transition out of the in-
|
|
1148
|
+
# progress state. Everyone else short-circuits.
|
|
1149
|
+
if text == self._last_sent_text and not (
|
|
1150
|
+
finalize and self._adapter_requires_finalize
|
|
1151
|
+
):
|
|
1152
|
+
return True
|
|
1153
|
+
# Fresh-final for long-lived previews: when finalizing
|
|
1154
|
+
# the last edit in a streaming sequence, if the
|
|
1155
|
+
# original preview has been visible for at least
|
|
1156
|
+
# ``fresh_final_after_seconds``, send the completed
|
|
1157
|
+
# reply as a fresh message so the platform's visible
|
|
1158
|
+
# timestamp reflects completion time instead of the
|
|
1159
|
+
# preview creation time. Best-effort cleanup of the
|
|
1160
|
+
# old preview follows. Ported from
|
|
1161
|
+
# openclaw/openclaw#72038. Gated by config so the
|
|
1162
|
+
# legacy edit-in-place path stays the default.
|
|
1163
|
+
if (
|
|
1164
|
+
finalize
|
|
1165
|
+
and self._should_send_fresh_final()
|
|
1166
|
+
and await self._try_fresh_final(text)
|
|
1167
|
+
):
|
|
1168
|
+
return True
|
|
1169
|
+
# Edit existing message
|
|
1170
|
+
result = await self.adapter.edit_message(
|
|
1171
|
+
chat_id=self.chat_id,
|
|
1172
|
+
message_id=self._message_id,
|
|
1173
|
+
content=text,
|
|
1174
|
+
finalize=finalize,
|
|
1175
|
+
)
|
|
1176
|
+
if result.success:
|
|
1177
|
+
self._already_sent = True
|
|
1178
|
+
# Adapter may have split-and-delivered an oversized
|
|
1179
|
+
# edit across the original message + N continuations.
|
|
1180
|
+
# When that happens, ``message_id`` is the LAST visible
|
|
1181
|
+
# continuation and ``_last_sent_text`` no longer reflects
|
|
1182
|
+
# the on-screen content (the new message only holds the
|
|
1183
|
+
# final chunk's text), so subsequent edits must target
|
|
1184
|
+
# the new id and skip-if-same comparisons must reset.
|
|
1185
|
+
# Fire on_new_message so tool-progress bubbles linearize
|
|
1186
|
+
# below the new continuation, not the original.
|
|
1187
|
+
# ``getattr`` with default keeps backwards compat with
|
|
1188
|
+
# SimpleNamespace mocks in tests that pre-date the field.
|
|
1189
|
+
_continuation_ids = getattr(result, "continuation_message_ids", ()) or ()
|
|
1190
|
+
if (
|
|
1191
|
+
_continuation_ids
|
|
1192
|
+
and result.message_id
|
|
1193
|
+
and result.message_id != self._message_id
|
|
1194
|
+
):
|
|
1195
|
+
self._message_id = str(result.message_id)
|
|
1196
|
+
self._message_created_ts = time.monotonic()
|
|
1197
|
+
self._last_sent_text = ""
|
|
1198
|
+
self._notify_new_message()
|
|
1199
|
+
else:
|
|
1200
|
+
self._last_sent_text = text
|
|
1201
|
+
# Successful edit — reset flood strike counter
|
|
1202
|
+
self._flood_strikes = 0
|
|
1203
|
+
return True
|
|
1204
|
+
else:
|
|
1205
|
+
# Edit failed. If this looks like flood control / rate
|
|
1206
|
+
# limiting, use adaptive backoff: double the edit interval
|
|
1207
|
+
# and retry on the next cycle. Only permanently disable
|
|
1208
|
+
# edits after _MAX_FLOOD_STRIKES consecutive failures.
|
|
1209
|
+
if self._is_flood_error(result):
|
|
1210
|
+
self._flood_strikes += 1
|
|
1211
|
+
self._current_edit_interval = min(
|
|
1212
|
+
self._current_edit_interval * 2, 10.0,
|
|
1213
|
+
)
|
|
1214
|
+
logger.debug(
|
|
1215
|
+
"Flood control on edit (strike %d/%d), "
|
|
1216
|
+
"backoff interval → %.1fs",
|
|
1217
|
+
self._flood_strikes,
|
|
1218
|
+
self._MAX_FLOOD_STRIKES,
|
|
1219
|
+
self._current_edit_interval,
|
|
1220
|
+
)
|
|
1221
|
+
if self._flood_strikes < self._MAX_FLOOD_STRIKES:
|
|
1222
|
+
# Don't disable edits yet — just slow down.
|
|
1223
|
+
# Update _last_edit_time so the next edit
|
|
1224
|
+
# respects the new interval.
|
|
1225
|
+
self._last_edit_time = time.monotonic()
|
|
1226
|
+
return False
|
|
1227
|
+
|
|
1228
|
+
# Non-flood error OR flood strikes exhausted: enter
|
|
1229
|
+
# fallback mode — send only the missing tail once the
|
|
1230
|
+
# final response is available.
|
|
1231
|
+
logger.debug(
|
|
1232
|
+
"Edit failed (strikes=%d), entering fallback mode",
|
|
1233
|
+
self._flood_strikes,
|
|
1234
|
+
)
|
|
1235
|
+
self._fallback_prefix = self._visible_prefix()
|
|
1236
|
+
self._fallback_final_send = True
|
|
1237
|
+
self._edit_supported = False
|
|
1238
|
+
self._already_sent = True
|
|
1239
|
+
# Best-effort: strip the cursor from the last visible
|
|
1240
|
+
# message so the user doesn't see a stuck ▉.
|
|
1241
|
+
await self._try_strip_cursor()
|
|
1242
|
+
return False
|
|
1243
|
+
else:
|
|
1244
|
+
# Editing not supported — skip intermediate updates.
|
|
1245
|
+
# The final response will be sent by the fallback path.
|
|
1246
|
+
return False
|
|
1247
|
+
else:
|
|
1248
|
+
# First message — send new, threaded to the original user message
|
|
1249
|
+
# so it lands in the correct topic/thread.
|
|
1250
|
+
result = await self.adapter.send(
|
|
1251
|
+
chat_id=self.chat_id,
|
|
1252
|
+
content=text,
|
|
1253
|
+
reply_to=self._initial_reply_to_id,
|
|
1254
|
+
metadata=self.metadata,
|
|
1255
|
+
)
|
|
1256
|
+
if result.success:
|
|
1257
|
+
if result.message_id:
|
|
1258
|
+
self._message_id = result.message_id
|
|
1259
|
+
# Track when the preview first became visible to
|
|
1260
|
+
# the user so fresh-final logic can detect stale
|
|
1261
|
+
# preview timestamps on long-running responses.
|
|
1262
|
+
self._message_created_ts = time.monotonic()
|
|
1263
|
+
else:
|
|
1264
|
+
self._edit_supported = False
|
|
1265
|
+
self._already_sent = True
|
|
1266
|
+
self._last_sent_text = text
|
|
1267
|
+
if not result.message_id:
|
|
1268
|
+
self._fallback_prefix = self._visible_prefix()
|
|
1269
|
+
self._fallback_final_send = True
|
|
1270
|
+
# Sentinel prevents re-entering the first-send path on
|
|
1271
|
+
# every delta/tool boundary when platforms accept a
|
|
1272
|
+
# message but do not return an editable message id.
|
|
1273
|
+
self._message_id = "__no_edit__"
|
|
1274
|
+
# Notify the gateway that a fresh content bubble was
|
|
1275
|
+
# created so any accumulated tool-progress bubble above
|
|
1276
|
+
# gets closed off — the next tool fires into a new
|
|
1277
|
+
# bubble below, preserving chronological order.
|
|
1278
|
+
self._notify_new_message()
|
|
1279
|
+
return True
|
|
1280
|
+
else:
|
|
1281
|
+
# Initial send failed — disable streaming for this session
|
|
1282
|
+
self._edit_supported = False
|
|
1283
|
+
return False
|
|
1284
|
+
except Exception as e:
|
|
1285
|
+
logger.error("Stream send/edit error: %s", e)
|
|
1286
|
+
return False
|