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.
Files changed (1718) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/README.zh-CN.md +180 -0
  4. package/acp_adapter/__init__.py +1 -0
  5. package/acp_adapter/__main__.py +5 -0
  6. package/acp_adapter/auth.py +68 -0
  7. package/acp_adapter/bootstrap/__init__.py +0 -0
  8. package/acp_adapter/bootstrap/bootstrap_browser_tools.ps1 +288 -0
  9. package/acp_adapter/bootstrap/bootstrap_browser_tools.sh +399 -0
  10. package/acp_adapter/entry.py +292 -0
  11. package/acp_adapter/events.py +265 -0
  12. package/acp_adapter/permissions.py +148 -0
  13. package/acp_adapter/server.py +1713 -0
  14. package/acp_adapter/session.py +629 -0
  15. package/acp_adapter/tools.py +1180 -0
  16. package/agent/__init__.py +6 -0
  17. package/agent/__pycache__/__init__.cpython-312.pyc +0 -0
  18. package/agent/__pycache__/account_usage.cpython-312.pyc +0 -0
  19. package/agent/__pycache__/anthropic_adapter.cpython-312.pyc +0 -0
  20. package/agent/__pycache__/async_utils.cpython-312.pyc +0 -0
  21. package/agent/__pycache__/auxiliary_client.cpython-312.pyc +0 -0
  22. package/agent/__pycache__/codex_responses_adapter.cpython-312.pyc +0 -0
  23. package/agent/__pycache__/context_compressor.cpython-312.pyc +0 -0
  24. package/agent/__pycache__/context_engine.cpython-312.pyc +0 -0
  25. package/agent/__pycache__/context_references.cpython-312.pyc +0 -0
  26. package/agent/__pycache__/credential_pool.cpython-312.pyc +0 -0
  27. package/agent/__pycache__/curator.cpython-312.pyc +0 -0
  28. package/agent/__pycache__/display.cpython-312.pyc +0 -0
  29. package/agent/__pycache__/error_classifier.cpython-312.pyc +0 -0
  30. package/agent/__pycache__/file_safety.cpython-312.pyc +0 -0
  31. package/agent/__pycache__/google_code_assist.cpython-312.pyc +0 -0
  32. package/agent/__pycache__/google_oauth.cpython-312.pyc +0 -0
  33. package/agent/__pycache__/i18n.cpython-312.pyc +0 -0
  34. package/agent/__pycache__/image_gen_provider.cpython-312.pyc +0 -0
  35. package/agent/__pycache__/image_gen_registry.cpython-312.pyc +0 -0
  36. package/agent/__pycache__/insights.cpython-312.pyc +0 -0
  37. package/agent/__pycache__/lmstudio_reasoning.cpython-312.pyc +0 -0
  38. package/agent/__pycache__/manual_compression_feedback.cpython-312.pyc +0 -0
  39. package/agent/__pycache__/markdown_tables.cpython-312.pyc +0 -0
  40. package/agent/__pycache__/memory_manager.cpython-312.pyc +0 -0
  41. package/agent/__pycache__/memory_provider.cpython-312.pyc +0 -0
  42. package/agent/__pycache__/model_metadata.cpython-312.pyc +0 -0
  43. package/agent/__pycache__/models_dev.cpython-312.pyc +0 -0
  44. package/agent/__pycache__/moonshot_schema.cpython-312.pyc +0 -0
  45. package/agent/__pycache__/onboarding.cpython-312.pyc +0 -0
  46. package/agent/__pycache__/portal_tags.cpython-312.pyc +0 -0
  47. package/agent/__pycache__/prompt_builder.cpython-312.pyc +0 -0
  48. package/agent/__pycache__/prompt_caching.cpython-312.pyc +0 -0
  49. package/agent/__pycache__/redact.cpython-312.pyc +0 -0
  50. package/agent/__pycache__/retry_utils.cpython-312.pyc +0 -0
  51. package/agent/__pycache__/shell_hooks.cpython-312.pyc +0 -0
  52. package/agent/__pycache__/skill_commands.cpython-312.pyc +0 -0
  53. package/agent/__pycache__/skill_preprocessing.cpython-312.pyc +0 -0
  54. package/agent/__pycache__/skill_utils.cpython-312.pyc +0 -0
  55. package/agent/__pycache__/subdirectory_hints.cpython-312.pyc +0 -0
  56. package/agent/__pycache__/think_scrubber.cpython-312.pyc +0 -0
  57. package/agent/__pycache__/title_generator.cpython-312.pyc +0 -0
  58. package/agent/__pycache__/tool_guardrails.cpython-312.pyc +0 -0
  59. package/agent/__pycache__/tool_result_classification.cpython-312.pyc +0 -0
  60. package/agent/__pycache__/trajectory.cpython-312.pyc +0 -0
  61. package/agent/__pycache__/usage_pricing.cpython-312.pyc +0 -0
  62. package/agent/__pycache__/video_gen_provider.cpython-312.pyc +0 -0
  63. package/agent/__pycache__/video_gen_registry.cpython-312.pyc +0 -0
  64. package/agent/__pycache__/web_search_provider.cpython-312.pyc +0 -0
  65. package/agent/__pycache__/web_search_registry.cpython-312.pyc +0 -0
  66. package/agent/account_usage.py +326 -0
  67. package/agent/anthropic_adapter.py +2087 -0
  68. package/agent/async_utils.py +68 -0
  69. package/agent/auxiliary_client.py +4893 -0
  70. package/agent/bedrock_adapter.py +1276 -0
  71. package/agent/codex_responses_adapter.py +1084 -0
  72. package/agent/context_compressor.py +1583 -0
  73. package/agent/context_engine.py +211 -0
  74. package/agent/context_references.py +519 -0
  75. package/agent/copilot_acp_client.py +684 -0
  76. package/agent/credential_pool.py +1780 -0
  77. package/agent/credential_sources.py +449 -0
  78. package/agent/curator.py +1782 -0
  79. package/agent/curator_backup.py +694 -0
  80. package/agent/display.py +987 -0
  81. package/agent/error_classifier.py +1058 -0
  82. package/agent/file_safety.py +112 -0
  83. package/agent/gemini_cloudcode_adapter.py +909 -0
  84. package/agent/gemini_native_adapter.py +971 -0
  85. package/agent/gemini_schema.py +99 -0
  86. package/agent/google_code_assist.py +452 -0
  87. package/agent/google_oauth.py +1062 -0
  88. package/agent/i18n.py +258 -0
  89. package/agent/image_gen_provider.py +243 -0
  90. package/agent/image_gen_registry.py +145 -0
  91. package/agent/image_routing.py +301 -0
  92. package/agent/insights.py +931 -0
  93. package/agent/lmstudio_reasoning.py +48 -0
  94. package/agent/lsp/__init__.py +106 -0
  95. package/agent/lsp/__pycache__/__init__.cpython-312.pyc +0 -0
  96. package/agent/lsp/__pycache__/cli.cpython-312.pyc +0 -0
  97. package/agent/lsp/__pycache__/client.cpython-312.pyc +0 -0
  98. package/agent/lsp/__pycache__/eventlog.cpython-312.pyc +0 -0
  99. package/agent/lsp/__pycache__/manager.cpython-312.pyc +0 -0
  100. package/agent/lsp/__pycache__/protocol.cpython-312.pyc +0 -0
  101. package/agent/lsp/__pycache__/servers.cpython-312.pyc +0 -0
  102. package/agent/lsp/__pycache__/workspace.cpython-312.pyc +0 -0
  103. package/agent/lsp/cli.py +308 -0
  104. package/agent/lsp/client.py +930 -0
  105. package/agent/lsp/eventlog.py +213 -0
  106. package/agent/lsp/install.py +376 -0
  107. package/agent/lsp/manager.py +644 -0
  108. package/agent/lsp/protocol.py +196 -0
  109. package/agent/lsp/range_shift.py +149 -0
  110. package/agent/lsp/reporter.py +78 -0
  111. package/agent/lsp/servers.py +1040 -0
  112. package/agent/lsp/workspace.py +223 -0
  113. package/agent/manual_compression_feedback.py +49 -0
  114. package/agent/markdown_tables.py +309 -0
  115. package/agent/memory_manager.py +556 -0
  116. package/agent/memory_provider.py +279 -0
  117. package/agent/model_metadata.py +1827 -0
  118. package/agent/models_dev.py +724 -0
  119. package/agent/moonshot_schema.py +231 -0
  120. package/agent/nous_rate_guard.py +326 -0
  121. package/agent/onboarding.py +193 -0
  122. package/agent/plugin_llm.py +1046 -0
  123. package/agent/portal_tags.py +64 -0
  124. package/agent/prompt_builder.py +1457 -0
  125. package/agent/prompt_caching.py +79 -0
  126. package/agent/rate_limit_tracker.py +246 -0
  127. package/agent/redact.py +403 -0
  128. package/agent/retry_utils.py +57 -0
  129. package/agent/shell_hooks.py +837 -0
  130. package/agent/skill_commands.py +502 -0
  131. package/agent/skill_preprocessing.py +131 -0
  132. package/agent/skill_utils.py +512 -0
  133. package/agent/subdirectory_hints.py +224 -0
  134. package/agent/think_scrubber.py +386 -0
  135. package/agent/title_generator.py +171 -0
  136. package/agent/tool_guardrails.py +458 -0
  137. package/agent/tool_result_classification.py +26 -0
  138. package/agent/trajectory.py +56 -0
  139. package/agent/transports/__init__.py +68 -0
  140. package/agent/transports/__pycache__/__init__.cpython-312.pyc +0 -0
  141. package/agent/transports/__pycache__/anthropic.cpython-312.pyc +0 -0
  142. package/agent/transports/__pycache__/base.cpython-312.pyc +0 -0
  143. package/agent/transports/__pycache__/bedrock.cpython-312.pyc +0 -0
  144. package/agent/transports/__pycache__/chat_completions.cpython-312.pyc +0 -0
  145. package/agent/transports/__pycache__/codex.cpython-312.pyc +0 -0
  146. package/agent/transports/__pycache__/types.cpython-312.pyc +0 -0
  147. package/agent/transports/anthropic.py +179 -0
  148. package/agent/transports/base.py +89 -0
  149. package/agent/transports/bedrock.py +154 -0
  150. package/agent/transports/chat_completions.py +614 -0
  151. package/agent/transports/codex.py +283 -0
  152. package/agent/transports/codex_app_server.py +368 -0
  153. package/agent/transports/codex_app_server_session.py +810 -0
  154. package/agent/transports/codex_event_projector.py +312 -0
  155. package/agent/transports/hermes_tools_mcp_server.py +233 -0
  156. package/agent/transports/types.py +162 -0
  157. package/agent/usage_pricing.py +877 -0
  158. package/agent/video_gen_provider.py +300 -0
  159. package/agent/video_gen_registry.py +117 -0
  160. package/agent/web_search_provider.py +221 -0
  161. package/agent/web_search_registry.py +262 -0
  162. package/assets/banner.png +0 -0
  163. package/batch_runner.py +1303 -0
  164. package/bin/calvyn.js +67 -0
  165. package/calvyn_bootstrap.py +130 -0
  166. package/calvyn_constants.py +346 -0
  167. package/calvyn_logging.py +390 -0
  168. package/calvyn_state.py +2967 -0
  169. package/calvyn_time.py +105 -0
  170. package/cli.py +14160 -0
  171. package/cron/__init__.py +42 -0
  172. package/cron/__pycache__/__init__.cpython-312.pyc +0 -0
  173. package/cron/__pycache__/jobs.cpython-312.pyc +0 -0
  174. package/cron/__pycache__/scheduler.cpython-312.pyc +0 -0
  175. package/cron/jobs.py +1160 -0
  176. package/cron/scheduler.py +1832 -0
  177. package/gateway/__init__.py +35 -0
  178. package/gateway/__pycache__/__init__.cpython-312.pyc +0 -0
  179. package/gateway/__pycache__/channel_directory.cpython-312.pyc +0 -0
  180. package/gateway/__pycache__/config.cpython-312.pyc +0 -0
  181. package/gateway/__pycache__/delivery.cpython-312.pyc +0 -0
  182. package/gateway/__pycache__/display_config.cpython-312.pyc +0 -0
  183. package/gateway/__pycache__/hooks.cpython-312.pyc +0 -0
  184. package/gateway/__pycache__/pairing.cpython-312.pyc +0 -0
  185. package/gateway/__pycache__/platform_registry.cpython-312.pyc +0 -0
  186. package/gateway/__pycache__/restart.cpython-312.pyc +0 -0
  187. package/gateway/__pycache__/run.cpython-312.pyc +0 -0
  188. package/gateway/__pycache__/runtime_footer.cpython-312.pyc +0 -0
  189. package/gateway/__pycache__/session.cpython-312.pyc +0 -0
  190. package/gateway/__pycache__/session_context.cpython-312.pyc +0 -0
  191. package/gateway/__pycache__/shutdown_forensics.cpython-312.pyc +0 -0
  192. package/gateway/__pycache__/slash_access.cpython-312.pyc +0 -0
  193. package/gateway/__pycache__/status.cpython-312.pyc +0 -0
  194. package/gateway/__pycache__/stream_consumer.cpython-312.pyc +0 -0
  195. package/gateway/__pycache__/whatsapp_identity.cpython-312.pyc +0 -0
  196. package/gateway/assets/telegram-botfather-threads-settings.jpg +0 -0
  197. package/gateway/builtin_hooks/__init__.py +1 -0
  198. package/gateway/channel_directory.py +357 -0
  199. package/gateway/config.py +1873 -0
  200. package/gateway/delivery.py +258 -0
  201. package/gateway/display_config.py +206 -0
  202. package/gateway/hooks.py +210 -0
  203. package/gateway/mirror.py +179 -0
  204. package/gateway/pairing.py +322 -0
  205. package/gateway/platform_registry.py +260 -0
  206. package/gateway/platforms/ADDING_A_PLATFORM.md +374 -0
  207. package/gateway/platforms/__init__.py +45 -0
  208. package/gateway/platforms/__pycache__/__init__.cpython-312.pyc +0 -0
  209. package/gateway/platforms/__pycache__/base.cpython-312.pyc +0 -0
  210. package/gateway/platforms/__pycache__/helpers.cpython-312.pyc +0 -0
  211. package/gateway/platforms/__pycache__/telegram.cpython-312.pyc +0 -0
  212. package/gateway/platforms/__pycache__/telegram_network.cpython-312.pyc +0 -0
  213. package/gateway/platforms/__pycache__/yuanbao.cpython-312.pyc +0 -0
  214. package/gateway/platforms/__pycache__/yuanbao_media.cpython-312.pyc +0 -0
  215. package/gateway/platforms/__pycache__/yuanbao_proto.cpython-312.pyc +0 -0
  216. package/gateway/platforms/_http_client_limits.py +84 -0
  217. package/gateway/platforms/api_server.py +3488 -0
  218. package/gateway/platforms/base.py +3747 -0
  219. package/gateway/platforms/bluebubbles.py +937 -0
  220. package/gateway/platforms/dingtalk.py +1473 -0
  221. package/gateway/platforms/discord.py +5584 -0
  222. package/gateway/platforms/email.py +773 -0
  223. package/gateway/platforms/feishu.py +5059 -0
  224. package/gateway/platforms/feishu_comment.py +1382 -0
  225. package/gateway/platforms/feishu_comment_rules.py +430 -0
  226. package/gateway/platforms/helpers.py +279 -0
  227. package/gateway/platforms/homeassistant.py +449 -0
  228. package/gateway/platforms/matrix.py +2777 -0
  229. package/gateway/platforms/mattermost.py +852 -0
  230. package/gateway/platforms/msgraph_webhook.py +397 -0
  231. package/gateway/platforms/qqbot/__init__.py +91 -0
  232. package/gateway/platforms/qqbot/adapter.py +3072 -0
  233. package/gateway/platforms/qqbot/chunked_upload.py +602 -0
  234. package/gateway/platforms/qqbot/constants.py +74 -0
  235. package/gateway/platforms/qqbot/crypto.py +45 -0
  236. package/gateway/platforms/qqbot/keyboards.py +473 -0
  237. package/gateway/platforms/qqbot/onboard.py +220 -0
  238. package/gateway/platforms/qqbot/utils.py +71 -0
  239. package/gateway/platforms/signal.py +1518 -0
  240. package/gateway/platforms/signal_rate_limit.py +369 -0
  241. package/gateway/platforms/slack.py +3028 -0
  242. package/gateway/platforms/sms.py +377 -0
  243. package/gateway/platforms/telegram.py +4836 -0
  244. package/gateway/platforms/telegram_network.py +249 -0
  245. package/gateway/platforms/webhook.py +806 -0
  246. package/gateway/platforms/wecom.py +1610 -0
  247. package/gateway/platforms/wecom_callback.py +403 -0
  248. package/gateway/platforms/wecom_crypto.py +142 -0
  249. package/gateway/platforms/weixin.py +2170 -0
  250. package/gateway/platforms/whatsapp.py +1283 -0
  251. package/gateway/platforms/yuanbao.py +4873 -0
  252. package/gateway/platforms/yuanbao_media.py +645 -0
  253. package/gateway/platforms/yuanbao_proto.py +1209 -0
  254. package/gateway/platforms/yuanbao_sticker.py +558 -0
  255. package/gateway/restart.py +20 -0
  256. package/gateway/run.py +17074 -0
  257. package/gateway/runtime_footer.py +150 -0
  258. package/gateway/session.py +1399 -0
  259. package/gateway/session_context.py +156 -0
  260. package/gateway/shutdown_forensics.py +462 -0
  261. package/gateway/slash_access.py +229 -0
  262. package/gateway/status.py +972 -0
  263. package/gateway/sticker_cache.py +111 -0
  264. package/gateway/stream_consumer.py +1286 -0
  265. package/gateway/whatsapp_identity.py +156 -0
  266. package/hermes_cli/__init__.py +47 -0
  267. package/hermes_cli/__pycache__/__init__.cpython-312.pyc +0 -0
  268. package/hermes_cli/__pycache__/_parser.cpython-312.pyc +0 -0
  269. package/hermes_cli/__pycache__/auth.cpython-312.pyc +0 -0
  270. package/hermes_cli/__pycache__/banner.cpython-312.pyc +0 -0
  271. package/hermes_cli/__pycache__/browser_connect.cpython-312.pyc +0 -0
  272. package/hermes_cli/__pycache__/callbacks.cpython-312.pyc +0 -0
  273. package/hermes_cli/__pycache__/checkpoints.cpython-312.pyc +0 -0
  274. package/hermes_cli/__pycache__/cli_output.cpython-312.pyc +0 -0
  275. package/hermes_cli/__pycache__/codex_models.cpython-312.pyc +0 -0
  276. package/hermes_cli/__pycache__/codex_runtime_switch.cpython-312.pyc +0 -0
  277. package/hermes_cli/__pycache__/colors.cpython-312.pyc +0 -0
  278. package/hermes_cli/__pycache__/commands.cpython-312.pyc +0 -0
  279. package/hermes_cli/__pycache__/config.cpython-312.pyc +0 -0
  280. package/hermes_cli/__pycache__/copilot_auth.cpython-312.pyc +0 -0
  281. package/hermes_cli/__pycache__/curator.cpython-312.pyc +0 -0
  282. package/hermes_cli/__pycache__/curses_ui.cpython-312.pyc +0 -0
  283. package/hermes_cli/__pycache__/debug.cpython-312.pyc +0 -0
  284. package/hermes_cli/__pycache__/default_soul.cpython-312.pyc +0 -0
  285. package/hermes_cli/__pycache__/env_loader.cpython-312.pyc +0 -0
  286. package/hermes_cli/__pycache__/fallback_cmd.cpython-312.pyc +0 -0
  287. package/hermes_cli/__pycache__/gateway.cpython-312.pyc +0 -0
  288. package/hermes_cli/__pycache__/gateway_windows.cpython-312.pyc +0 -0
  289. package/hermes_cli/__pycache__/goals.cpython-312.pyc +0 -0
  290. package/hermes_cli/__pycache__/inventory.cpython-312.pyc +0 -0
  291. package/hermes_cli/__pycache__/kanban.cpython-312.pyc +0 -0
  292. package/hermes_cli/__pycache__/kanban_db.cpython-312.pyc +0 -0
  293. package/hermes_cli/__pycache__/main.cpython-312.pyc +0 -0
  294. package/hermes_cli/__pycache__/model_catalog.cpython-312.pyc +0 -0
  295. package/hermes_cli/__pycache__/model_normalize.cpython-312.pyc +0 -0
  296. package/hermes_cli/__pycache__/model_switch.cpython-312.pyc +0 -0
  297. package/hermes_cli/__pycache__/models.cpython-312.pyc +0 -0
  298. package/hermes_cli/__pycache__/nous_subscription.cpython-312.pyc +0 -0
  299. package/hermes_cli/__pycache__/pairing.cpython-312.pyc +0 -0
  300. package/hermes_cli/__pycache__/platforms.cpython-312.pyc +0 -0
  301. package/hermes_cli/__pycache__/plugins.cpython-312.pyc +0 -0
  302. package/hermes_cli/__pycache__/profiles.cpython-312.pyc +0 -0
  303. package/hermes_cli/__pycache__/providers.cpython-312.pyc +0 -0
  304. package/hermes_cli/__pycache__/pt_input_extras.cpython-312.pyc +0 -0
  305. package/hermes_cli/__pycache__/runtime_provider.cpython-312.pyc +0 -0
  306. package/hermes_cli/__pycache__/security_advisories.cpython-312.pyc +0 -0
  307. package/hermes_cli/__pycache__/setup.cpython-312.pyc +0 -0
  308. package/hermes_cli/__pycache__/skills_hub.cpython-312.pyc +0 -0
  309. package/hermes_cli/__pycache__/skin_engine.cpython-312.pyc +0 -0
  310. package/hermes_cli/__pycache__/stdio.cpython-312.pyc +0 -0
  311. package/hermes_cli/__pycache__/timeouts.cpython-312.pyc +0 -0
  312. package/hermes_cli/__pycache__/tips.cpython-312.pyc +0 -0
  313. package/hermes_cli/__pycache__/tools_config.cpython-312.pyc +0 -0
  314. package/hermes_cli/__pycache__/voice.cpython-312.pyc +0 -0
  315. package/hermes_cli/_parser.py +365 -0
  316. package/hermes_cli/_subprocess_compat.py +175 -0
  317. package/hermes_cli/auth.py +6299 -0
  318. package/hermes_cli/auth_commands.py +749 -0
  319. package/hermes_cli/azure_detect.py +300 -0
  320. package/hermes_cli/backup.py +938 -0
  321. package/hermes_cli/banner.py +703 -0
  322. package/hermes_cli/browser_connect.py +139 -0
  323. package/hermes_cli/callbacks.py +243 -0
  324. package/hermes_cli/checkpoints.py +244 -0
  325. package/hermes_cli/claw.py +810 -0
  326. package/hermes_cli/cli_output.py +78 -0
  327. package/hermes_cli/clipboard.py +495 -0
  328. package/hermes_cli/codex_models.py +198 -0
  329. package/hermes_cli/codex_runtime_plugin_migration.py +757 -0
  330. package/hermes_cli/codex_runtime_switch.py +266 -0
  331. package/hermes_cli/colors.py +38 -0
  332. package/hermes_cli/commands.py +1728 -0
  333. package/hermes_cli/completion.py +315 -0
  334. package/hermes_cli/config.py +5382 -0
  335. package/hermes_cli/copilot_auth.py +392 -0
  336. package/hermes_cli/cron.py +313 -0
  337. package/hermes_cli/curator.py +598 -0
  338. package/hermes_cli/curses_ui.py +472 -0
  339. package/hermes_cli/debug.py +747 -0
  340. package/hermes_cli/default_soul.py +11 -0
  341. package/hermes_cli/dep_ensure.py +107 -0
  342. package/hermes_cli/dingtalk_auth.py +293 -0
  343. package/hermes_cli/doctor.py +1863 -0
  344. package/hermes_cli/dump.py +326 -0
  345. package/hermes_cli/env_loader.py +175 -0
  346. package/hermes_cli/fallback_cmd.py +361 -0
  347. package/hermes_cli/gateway.py +5422 -0
  348. package/hermes_cli/gateway_windows.py +692 -0
  349. package/hermes_cli/goals.py +757 -0
  350. package/hermes_cli/hooks.py +385 -0
  351. package/hermes_cli/inventory.py +240 -0
  352. package/hermes_cli/kanban.py +2252 -0
  353. package/hermes_cli/kanban_db.py +4840 -0
  354. package/hermes_cli/kanban_diagnostics.py +776 -0
  355. package/hermes_cli/kanban_specify.py +266 -0
  356. package/hermes_cli/logs.py +391 -0
  357. package/hermes_cli/main.py +12396 -0
  358. package/hermes_cli/mcp_config.py +781 -0
  359. package/hermes_cli/memory_setup.py +465 -0
  360. package/hermes_cli/model_catalog.py +330 -0
  361. package/hermes_cli/model_normalize.py +473 -0
  362. package/hermes_cli/model_switch.py +1777 -0
  363. package/hermes_cli/models.py +3789 -0
  364. package/hermes_cli/nous_subscription.py +799 -0
  365. package/hermes_cli/oneshot.py +351 -0
  366. package/hermes_cli/pairing.py +115 -0
  367. package/hermes_cli/platforms.py +83 -0
  368. package/hermes_cli/plugins.py +1562 -0
  369. package/hermes_cli/plugins_cmd.py +1587 -0
  370. package/hermes_cli/profile_distribution.py +703 -0
  371. package/hermes_cli/profiles.py +1319 -0
  372. package/hermes_cli/providers.py +720 -0
  373. package/hermes_cli/proxy/__init__.py +20 -0
  374. package/hermes_cli/proxy/adapters/__init__.py +35 -0
  375. package/hermes_cli/proxy/adapters/base.py +94 -0
  376. package/hermes_cli/proxy/adapters/nous_portal.py +137 -0
  377. package/hermes_cli/proxy/cli.py +141 -0
  378. package/hermes_cli/proxy/server.py +265 -0
  379. package/hermes_cli/pt_input_extras.py +83 -0
  380. package/hermes_cli/pty_bridge.py +237 -0
  381. package/hermes_cli/relaunch.py +205 -0
  382. package/hermes_cli/runtime_provider.py +1428 -0
  383. package/hermes_cli/security_advisories.py +452 -0
  384. package/hermes_cli/setup.py +3559 -0
  385. package/hermes_cli/skills_config.py +177 -0
  386. package/hermes_cli/skills_hub.py +1595 -0
  387. package/hermes_cli/skin_engine.py +929 -0
  388. package/hermes_cli/slack_cli.py +160 -0
  389. package/hermes_cli/status.py +550 -0
  390. package/hermes_cli/stdio.py +252 -0
  391. package/hermes_cli/timeouts.py +82 -0
  392. package/hermes_cli/tips.py +487 -0
  393. package/hermes_cli/tools_config.py +3151 -0
  394. package/hermes_cli/uninstall.py +681 -0
  395. package/hermes_cli/vercel_auth.py +70 -0
  396. package/hermes_cli/voice.py +846 -0
  397. package/hermes_cli/web_server.py +4438 -0
  398. package/hermes_cli/webhook.py +275 -0
  399. package/locales/af.yaml +350 -0
  400. package/locales/de.yaml +350 -0
  401. package/locales/en.yaml +365 -0
  402. package/locales/es.yaml +350 -0
  403. package/locales/fr.yaml +350 -0
  404. package/locales/ga.yaml +354 -0
  405. package/locales/hu.yaml +350 -0
  406. package/locales/it.yaml +350 -0
  407. package/locales/ja.yaml +350 -0
  408. package/locales/ko.yaml +350 -0
  409. package/locales/pt.yaml +350 -0
  410. package/locales/ru.yaml +350 -0
  411. package/locales/tr.yaml +350 -0
  412. package/locales/uk.yaml +350 -0
  413. package/locales/zh-hant.yaml +350 -0
  414. package/locales/zh.yaml +350 -0
  415. package/mcp_serve.py +898 -0
  416. package/model_tools.py +899 -0
  417. package/optional-skills/DESCRIPTION.md +24 -0
  418. package/optional-skills/autonomous-ai-agents/DESCRIPTION.md +2 -0
  419. package/optional-skills/autonomous-ai-agents/blackbox/SKILL.md +144 -0
  420. package/optional-skills/autonomous-ai-agents/honcho/SKILL.md +431 -0
  421. package/optional-skills/blockchain/evm/SKILL.md +211 -0
  422. package/optional-skills/blockchain/evm/scripts/evm_client.py +1508 -0
  423. package/optional-skills/blockchain/hyperliquid/SKILL.md +211 -0
  424. package/optional-skills/blockchain/hyperliquid/scripts/hyperliquid_client.py +1660 -0
  425. package/optional-skills/blockchain/solana/SKILL.md +208 -0
  426. package/optional-skills/blockchain/solana/scripts/solana_client.py +698 -0
  427. package/optional-skills/communication/DESCRIPTION.md +1 -0
  428. package/optional-skills/communication/one-three-one-rule/SKILL.md +104 -0
  429. package/optional-skills/creative/blender-mcp/SKILL.md +117 -0
  430. package/optional-skills/creative/concept-diagrams/SKILL.md +362 -0
  431. package/optional-skills/creative/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
  432. package/optional-skills/creative/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
  433. package/optional-skills/creative/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
  434. package/optional-skills/creative/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
  435. package/optional-skills/creative/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
  436. package/optional-skills/creative/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
  437. package/optional-skills/creative/concept-diagrams/examples/electricity-grid-flow.md +182 -0
  438. package/optional-skills/creative/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
  439. package/optional-skills/creative/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
  440. package/optional-skills/creative/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
  441. package/optional-skills/creative/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
  442. package/optional-skills/creative/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
  443. package/optional-skills/creative/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
  444. package/optional-skills/creative/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
  445. package/optional-skills/creative/concept-diagrams/examples/wind-turbine-structure.md +338 -0
  446. package/optional-skills/creative/concept-diagrams/references/dashboard-patterns.md +43 -0
  447. package/optional-skills/creative/concept-diagrams/references/infrastructure-patterns.md +144 -0
  448. package/optional-skills/creative/concept-diagrams/references/physical-shape-cookbook.md +42 -0
  449. package/optional-skills/creative/concept-diagrams/templates/template.html +174 -0
  450. package/optional-skills/creative/hyperframes/SKILL.md +191 -0
  451. package/optional-skills/creative/hyperframes/references/cli.md +185 -0
  452. package/optional-skills/creative/hyperframes/references/composition.md +129 -0
  453. package/optional-skills/creative/hyperframes/references/features.md +289 -0
  454. package/optional-skills/creative/hyperframes/references/gsap.md +136 -0
  455. package/optional-skills/creative/hyperframes/references/troubleshooting.md +137 -0
  456. package/optional-skills/creative/hyperframes/references/website-to-video.md +145 -0
  457. package/optional-skills/creative/hyperframes/scripts/setup.sh +135 -0
  458. package/optional-skills/creative/kanban-video-orchestrator/SKILL.md +207 -0
  459. package/optional-skills/creative/kanban-video-orchestrator/assets/brief.md.tmpl +79 -0
  460. package/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +185 -0
  461. package/optional-skills/creative/kanban-video-orchestrator/assets/soul.md.tmpl +38 -0
  462. package/optional-skills/creative/kanban-video-orchestrator/references/examples.md +227 -0
  463. package/optional-skills/creative/kanban-video-orchestrator/references/intake.md +166 -0
  464. package/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +276 -0
  465. package/optional-skills/creative/kanban-video-orchestrator/references/monitoring.md +180 -0
  466. package/optional-skills/creative/kanban-video-orchestrator/references/role-archetypes.md +298 -0
  467. package/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +317 -0
  468. package/optional-skills/creative/kanban-video-orchestrator/scripts/bootstrap_pipeline.py +501 -0
  469. package/optional-skills/creative/kanban-video-orchestrator/scripts/monitor.py +195 -0
  470. package/optional-skills/creative/meme-generation/EXAMPLES.md +46 -0
  471. package/optional-skills/creative/meme-generation/SKILL.md +130 -0
  472. package/optional-skills/creative/meme-generation/scripts/generate_meme.py +471 -0
  473. package/optional-skills/creative/meme-generation/scripts/templates.json +97 -0
  474. package/optional-skills/devops/cli/SKILL.md +156 -0
  475. package/optional-skills/devops/cli/references/app-discovery.md +112 -0
  476. package/optional-skills/devops/cli/references/authentication.md +59 -0
  477. package/optional-skills/devops/cli/references/cli-reference.md +104 -0
  478. package/optional-skills/devops/cli/references/running-apps.md +171 -0
  479. package/optional-skills/devops/docker-management/SKILL.md +281 -0
  480. package/optional-skills/devops/pinggy-tunnel/SKILL.md +309 -0
  481. package/optional-skills/devops/watchers/SKILL.md +112 -0
  482. package/optional-skills/devops/watchers/scripts/_watermark.py +148 -0
  483. package/optional-skills/devops/watchers/scripts/watch_github.py +168 -0
  484. package/optional-skills/devops/watchers/scripts/watch_http_json.py +131 -0
  485. package/optional-skills/devops/watchers/scripts/watch_rss.py +121 -0
  486. package/optional-skills/dogfood/DESCRIPTION.md +3 -0
  487. package/optional-skills/dogfood/adversarial-ux-test/SKILL.md +191 -0
  488. package/optional-skills/email/agentmail/SKILL.md +126 -0
  489. package/optional-skills/finance/3-statement-model/SKILL.md +433 -0
  490. package/optional-skills/finance/3-statement-model/references/formatting.md +118 -0
  491. package/optional-skills/finance/3-statement-model/references/formulas.md +292 -0
  492. package/optional-skills/finance/3-statement-model/references/sec-filings.md +125 -0
  493. package/optional-skills/finance/comps-analysis/SKILL.md +662 -0
  494. package/optional-skills/finance/dcf-model/SKILL.md +1270 -0
  495. package/optional-skills/finance/dcf-model/TROUBLESHOOTING.md +40 -0
  496. package/optional-skills/finance/dcf-model/requirements.txt +7 -0
  497. package/optional-skills/finance/dcf-model/scripts/validate_dcf.py +292 -0
  498. package/optional-skills/finance/excel-author/SKILL.md +244 -0
  499. package/optional-skills/finance/excel-author/scripts/recalc.py +88 -0
  500. package/optional-skills/finance/lbo-model/SKILL.md +291 -0
  501. package/optional-skills/finance/merger-model/SKILL.md +144 -0
  502. package/optional-skills/finance/pptx-author/SKILL.md +173 -0
  503. package/optional-skills/finance/stocks/SKILL.md +95 -0
  504. package/optional-skills/finance/stocks/scripts/stocks_client.py +755 -0
  505. package/optional-skills/health/DESCRIPTION.md +1 -0
  506. package/optional-skills/health/fitness-nutrition/SKILL.md +256 -0
  507. package/optional-skills/health/fitness-nutrition/references/FORMULAS.md +100 -0
  508. package/optional-skills/health/fitness-nutrition/scripts/body_calc.py +210 -0
  509. package/optional-skills/health/fitness-nutrition/scripts/nutrition_search.py +86 -0
  510. package/optional-skills/health/neuroskill-bci/SKILL.md +459 -0
  511. package/optional-skills/health/neuroskill-bci/references/api.md +286 -0
  512. package/optional-skills/health/neuroskill-bci/references/metrics.md +220 -0
  513. package/optional-skills/health/neuroskill-bci/references/protocols.md +452 -0
  514. package/optional-skills/mcp/DESCRIPTION.md +3 -0
  515. package/optional-skills/mcp/fastmcp/SKILL.md +300 -0
  516. package/optional-skills/mcp/fastmcp/references/fastmcp-cli.md +110 -0
  517. package/optional-skills/mcp/fastmcp/scripts/scaffold_fastmcp.py +56 -0
  518. package/optional-skills/mcp/fastmcp/templates/api_wrapper.py +54 -0
  519. package/optional-skills/mcp/fastmcp/templates/database_server.py +77 -0
  520. package/optional-skills/mcp/fastmcp/templates/file_processor.py +55 -0
  521. package/optional-skills/mcp/mcporter/SKILL.md +123 -0
  522. package/optional-skills/migration/DESCRIPTION.md +2 -0
  523. package/optional-skills/migration/openclaw-migration/SKILL.md +298 -0
  524. package/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py +3136 -0
  525. package/optional-skills/mlops/accelerate/SKILL.md +336 -0
  526. package/optional-skills/mlops/accelerate/references/custom-plugins.md +453 -0
  527. package/optional-skills/mlops/accelerate/references/megatron-integration.md +489 -0
  528. package/optional-skills/mlops/accelerate/references/performance.md +525 -0
  529. package/optional-skills/mlops/chroma/SKILL.md +410 -0
  530. package/optional-skills/mlops/chroma/references/integration.md +38 -0
  531. package/optional-skills/mlops/clip/SKILL.md +257 -0
  532. package/optional-skills/mlops/clip/references/applications.md +207 -0
  533. package/optional-skills/mlops/faiss/SKILL.md +225 -0
  534. package/optional-skills/mlops/faiss/references/index_types.md +280 -0
  535. package/optional-skills/mlops/flash-attention/SKILL.md +367 -0
  536. package/optional-skills/mlops/flash-attention/references/benchmarks.md +215 -0
  537. package/optional-skills/mlops/flash-attention/references/transformers-integration.md +293 -0
  538. package/optional-skills/mlops/guidance/SKILL.md +576 -0
  539. package/optional-skills/mlops/guidance/references/backends.md +554 -0
  540. package/optional-skills/mlops/guidance/references/constraints.md +674 -0
  541. package/optional-skills/mlops/guidance/references/examples.md +767 -0
  542. package/optional-skills/mlops/huggingface-tokenizers/SKILL.md +520 -0
  543. package/optional-skills/mlops/huggingface-tokenizers/references/algorithms.md +653 -0
  544. package/optional-skills/mlops/huggingface-tokenizers/references/integration.md +637 -0
  545. package/optional-skills/mlops/huggingface-tokenizers/references/pipeline.md +723 -0
  546. package/optional-skills/mlops/huggingface-tokenizers/references/training.md +565 -0
  547. package/optional-skills/mlops/inference/outlines/SKILL.md +656 -0
  548. package/optional-skills/mlops/inference/outlines/references/backends.md +615 -0
  549. package/optional-skills/mlops/inference/outlines/references/examples.md +773 -0
  550. package/optional-skills/mlops/inference/outlines/references/json_generation.md +652 -0
  551. package/optional-skills/mlops/instructor/SKILL.md +744 -0
  552. package/optional-skills/mlops/instructor/references/examples.md +107 -0
  553. package/optional-skills/mlops/instructor/references/providers.md +70 -0
  554. package/optional-skills/mlops/instructor/references/validation.md +606 -0
  555. package/optional-skills/mlops/lambda-labs/SKILL.md +549 -0
  556. package/optional-skills/mlops/lambda-labs/references/advanced-usage.md +611 -0
  557. package/optional-skills/mlops/lambda-labs/references/troubleshooting.md +530 -0
  558. package/optional-skills/mlops/llava/SKILL.md +308 -0
  559. package/optional-skills/mlops/llava/references/training.md +197 -0
  560. package/optional-skills/mlops/modal/SKILL.md +345 -0
  561. package/optional-skills/mlops/modal/references/advanced-usage.md +503 -0
  562. package/optional-skills/mlops/modal/references/troubleshooting.md +494 -0
  563. package/optional-skills/mlops/nemo-curator/SKILL.md +387 -0
  564. package/optional-skills/mlops/nemo-curator/references/deduplication.md +87 -0
  565. package/optional-skills/mlops/nemo-curator/references/filtering.md +102 -0
  566. package/optional-skills/mlops/peft/SKILL.md +435 -0
  567. package/optional-skills/mlops/peft/references/advanced-usage.md +514 -0
  568. package/optional-skills/mlops/peft/references/troubleshooting.md +480 -0
  569. package/optional-skills/mlops/pinecone/SKILL.md +362 -0
  570. package/optional-skills/mlops/pinecone/references/deployment.md +181 -0
  571. package/optional-skills/mlops/pytorch-fsdp/SKILL.md +130 -0
  572. package/optional-skills/mlops/pytorch-fsdp/references/index.md +7 -0
  573. package/optional-skills/mlops/pytorch-fsdp/references/other.md +4261 -0
  574. package/optional-skills/mlops/pytorch-lightning/SKILL.md +350 -0
  575. package/optional-skills/mlops/pytorch-lightning/references/callbacks.md +436 -0
  576. package/optional-skills/mlops/pytorch-lightning/references/distributed.md +490 -0
  577. package/optional-skills/mlops/pytorch-lightning/references/hyperparameter-tuning.md +556 -0
  578. package/optional-skills/mlops/qdrant/SKILL.md +497 -0
  579. package/optional-skills/mlops/qdrant/references/advanced-usage.md +648 -0
  580. package/optional-skills/mlops/qdrant/references/troubleshooting.md +631 -0
  581. package/optional-skills/mlops/saelens/SKILL.md +390 -0
  582. package/optional-skills/mlops/saelens/references/README.md +69 -0
  583. package/optional-skills/mlops/saelens/references/api.md +333 -0
  584. package/optional-skills/mlops/saelens/references/tutorials.md +318 -0
  585. package/optional-skills/mlops/simpo/SKILL.md +223 -0
  586. package/optional-skills/mlops/simpo/references/datasets.md +478 -0
  587. package/optional-skills/mlops/simpo/references/hyperparameters.md +452 -0
  588. package/optional-skills/mlops/simpo/references/loss-functions.md +350 -0
  589. package/optional-skills/mlops/slime/SKILL.md +468 -0
  590. package/optional-skills/mlops/slime/references/api-reference.md +392 -0
  591. package/optional-skills/mlops/slime/references/troubleshooting.md +386 -0
  592. package/optional-skills/mlops/stable-diffusion/SKILL.md +523 -0
  593. package/optional-skills/mlops/stable-diffusion/references/advanced-usage.md +716 -0
  594. package/optional-skills/mlops/stable-diffusion/references/troubleshooting.md +555 -0
  595. package/optional-skills/mlops/tensorrt-llm/SKILL.md +191 -0
  596. package/optional-skills/mlops/tensorrt-llm/references/multi-gpu.md +298 -0
  597. package/optional-skills/mlops/tensorrt-llm/references/optimization.md +242 -0
  598. package/optional-skills/mlops/tensorrt-llm/references/serving.md +470 -0
  599. package/optional-skills/mlops/torchtitan/SKILL.md +362 -0
  600. package/optional-skills/mlops/torchtitan/references/checkpoint.md +181 -0
  601. package/optional-skills/mlops/torchtitan/references/custom-models.md +258 -0
  602. package/optional-skills/mlops/torchtitan/references/float8.md +133 -0
  603. package/optional-skills/mlops/torchtitan/references/fsdp.md +126 -0
  604. package/optional-skills/mlops/training/axolotl/SKILL.md +166 -0
  605. package/optional-skills/mlops/training/axolotl/references/api.md +5548 -0
  606. package/optional-skills/mlops/training/axolotl/references/dataset-formats.md +1029 -0
  607. package/optional-skills/mlops/training/axolotl/references/index.md +15 -0
  608. package/optional-skills/mlops/training/axolotl/references/other.md +3563 -0
  609. package/optional-skills/mlops/training/trl-fine-tuning/SKILL.md +463 -0
  610. package/optional-skills/mlops/training/trl-fine-tuning/references/dpo-variants.md +227 -0
  611. package/optional-skills/mlops/training/trl-fine-tuning/references/grpo-training.md +504 -0
  612. package/optional-skills/mlops/training/trl-fine-tuning/references/online-rl.md +82 -0
  613. package/optional-skills/mlops/training/trl-fine-tuning/references/reward-modeling.md +122 -0
  614. package/optional-skills/mlops/training/trl-fine-tuning/references/sft-training.md +168 -0
  615. package/optional-skills/mlops/training/trl-fine-tuning/templates/basic_grpo_training.py +228 -0
  616. package/optional-skills/mlops/training/unsloth/SKILL.md +84 -0
  617. package/optional-skills/mlops/training/unsloth/references/index.md +7 -0
  618. package/optional-skills/mlops/training/unsloth/references/llms-full.md +16799 -0
  619. package/optional-skills/mlops/training/unsloth/references/llms-txt.md +12044 -0
  620. package/optional-skills/mlops/training/unsloth/references/llms.md +82 -0
  621. package/optional-skills/mlops/whisper/SKILL.md +321 -0
  622. package/optional-skills/mlops/whisper/references/languages.md +189 -0
  623. package/optional-skills/productivity/canvas/SKILL.md +98 -0
  624. package/optional-skills/productivity/canvas/scripts/canvas_api.py +157 -0
  625. package/optional-skills/productivity/here-now/SKILL.md +217 -0
  626. package/optional-skills/productivity/here-now/scripts/drive.sh +406 -0
  627. package/optional-skills/productivity/here-now/scripts/publish.sh +445 -0
  628. package/optional-skills/productivity/memento-flashcards/SKILL.md +324 -0
  629. package/optional-skills/productivity/memento-flashcards/scripts/memento_cards.py +353 -0
  630. package/optional-skills/productivity/memento-flashcards/scripts/youtube_quiz.py +88 -0
  631. package/optional-skills/productivity/shop-app/SKILL.md +340 -0
  632. package/optional-skills/productivity/shopify/SKILL.md +373 -0
  633. package/optional-skills/productivity/siyuan/SKILL.md +298 -0
  634. package/optional-skills/productivity/telephony/SKILL.md +418 -0
  635. package/optional-skills/productivity/telephony/scripts/telephony.py +1343 -0
  636. package/optional-skills/research/bioinformatics/SKILL.md +235 -0
  637. package/optional-skills/research/darwinian-evolver/SKILL.md +199 -0
  638. package/optional-skills/research/darwinian-evolver/scripts/parrot_openrouter.py +218 -0
  639. package/optional-skills/research/darwinian-evolver/scripts/show_snapshot.py +69 -0
  640. package/optional-skills/research/darwinian-evolver/templates/custom_problem_template.py +240 -0
  641. package/optional-skills/research/domain-intel/SKILL.md +97 -0
  642. package/optional-skills/research/domain-intel/scripts/domain_intel.py +397 -0
  643. package/optional-skills/research/drug-discovery/SKILL.md +227 -0
  644. package/optional-skills/research/drug-discovery/references/ADMET_REFERENCE.md +66 -0
  645. package/optional-skills/research/drug-discovery/scripts/chembl_target.py +53 -0
  646. package/optional-skills/research/drug-discovery/scripts/ro5_screen.py +44 -0
  647. package/optional-skills/research/duckduckgo-search/SKILL.md +238 -0
  648. package/optional-skills/research/duckduckgo-search/scripts/duckduckgo.sh +28 -0
  649. package/optional-skills/research/gitnexus-explorer/SKILL.md +214 -0
  650. package/optional-skills/research/gitnexus-explorer/scripts/proxy.mjs +92 -0
  651. package/optional-skills/research/osint-investigation/SKILL.md +277 -0
  652. package/optional-skills/research/osint-investigation/references/sources/courtlistener.md +98 -0
  653. package/optional-skills/research/osint-investigation/references/sources/gdelt.md +104 -0
  654. package/optional-skills/research/osint-investigation/references/sources/icij-offshore.md +104 -0
  655. package/optional-skills/research/osint-investigation/references/sources/nyc-acris.md +90 -0
  656. package/optional-skills/research/osint-investigation/references/sources/ofac-sdn.md +92 -0
  657. package/optional-skills/research/osint-investigation/references/sources/opencorporates.md +103 -0
  658. package/optional-skills/research/osint-investigation/references/sources/sec-edgar.md +83 -0
  659. package/optional-skills/research/osint-investigation/references/sources/senate-ld.md +89 -0
  660. package/optional-skills/research/osint-investigation/references/sources/usaspending.md +97 -0
  661. package/optional-skills/research/osint-investigation/references/sources/wayback.md +93 -0
  662. package/optional-skills/research/osint-investigation/references/sources/wikipedia.md +107 -0
  663. package/optional-skills/research/osint-investigation/scripts/_http.py +82 -0
  664. package/optional-skills/research/osint-investigation/scripts/_normalize.py +67 -0
  665. package/optional-skills/research/osint-investigation/scripts/build_findings.py +221 -0
  666. package/optional-skills/research/osint-investigation/scripts/entity_resolution.py +228 -0
  667. package/optional-skills/research/osint-investigation/scripts/fetch_courtlistener.py +149 -0
  668. package/optional-skills/research/osint-investigation/scripts/fetch_gdelt.py +162 -0
  669. package/optional-skills/research/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
  670. package/optional-skills/research/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
  671. package/optional-skills/research/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
  672. package/optional-skills/research/osint-investigation/scripts/fetch_opencorporates.py +192 -0
  673. package/optional-skills/research/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
  674. package/optional-skills/research/osint-investigation/scripts/fetch_senate_ld.py +146 -0
  675. package/optional-skills/research/osint-investigation/scripts/fetch_usaspending.py +170 -0
  676. package/optional-skills/research/osint-investigation/scripts/fetch_wayback.py +142 -0
  677. package/optional-skills/research/osint-investigation/scripts/fetch_wikipedia.py +267 -0
  678. package/optional-skills/research/osint-investigation/scripts/timing_analysis.py +253 -0
  679. package/optional-skills/research/osint-investigation/templates/source-template.md +59 -0
  680. package/optional-skills/research/parallel-cli/SKILL.md +391 -0
  681. package/optional-skills/research/qmd/SKILL.md +441 -0
  682. package/optional-skills/research/scrapling/SKILL.md +336 -0
  683. package/optional-skills/research/searxng-search/SKILL.md +212 -0
  684. package/optional-skills/research/searxng-search/scripts/searxng.sh +22 -0
  685. package/optional-skills/security/1password/SKILL.md +163 -0
  686. package/optional-skills/security/1password/references/cli-examples.md +31 -0
  687. package/optional-skills/security/1password/references/get-started.md +21 -0
  688. package/optional-skills/security/DESCRIPTION.md +3 -0
  689. package/optional-skills/security/oss-forensics/SKILL.md +423 -0
  690. package/optional-skills/security/oss-forensics/references/evidence-types.md +89 -0
  691. package/optional-skills/security/oss-forensics/references/github-archive-guide.md +184 -0
  692. package/optional-skills/security/oss-forensics/references/investigation-templates.md +131 -0
  693. package/optional-skills/security/oss-forensics/references/recovery-techniques.md +164 -0
  694. package/optional-skills/security/oss-forensics/scripts/evidence-store.py +313 -0
  695. package/optional-skills/security/oss-forensics/templates/forensic-report.md +151 -0
  696. package/optional-skills/security/oss-forensics/templates/malicious-package-report.md +43 -0
  697. package/optional-skills/security/sherlock/SKILL.md +193 -0
  698. package/optional-skills/software-development/rest-graphql-debug/SKILL.md +514 -0
  699. package/optional-skills/web-development/DESCRIPTION.md +5 -0
  700. package/optional-skills/web-development/page-agent/SKILL.md +190 -0
  701. package/package.json +78 -0
  702. package/plugins/__init__.py +1 -0
  703. package/plugins/__pycache__/__init__.cpython-312.pyc +0 -0
  704. package/plugins/context_engine/__init__.py +219 -0
  705. package/plugins/disk-cleanup/README.md +51 -0
  706. package/plugins/disk-cleanup/__init__.py +316 -0
  707. package/plugins/disk-cleanup/disk_cleanup.py +497 -0
  708. package/plugins/disk-cleanup/plugin.yaml +7 -0
  709. package/plugins/example-dashboard/dashboard/manifest.json +14 -0
  710. package/plugins/example-dashboard/dashboard/plugin_api.py +17 -0
  711. package/plugins/google_meet/README.md +131 -0
  712. package/plugins/google_meet/SKILL.md +148 -0
  713. package/plugins/google_meet/__init__.py +103 -0
  714. package/plugins/google_meet/audio_bridge.py +244 -0
  715. package/plugins/google_meet/cli.py +479 -0
  716. package/plugins/google_meet/meet_bot.py +852 -0
  717. package/plugins/google_meet/node/__init__.py +54 -0
  718. package/plugins/google_meet/node/cli.py +125 -0
  719. package/plugins/google_meet/node/client.py +107 -0
  720. package/plugins/google_meet/node/protocol.py +124 -0
  721. package/plugins/google_meet/node/registry.py +113 -0
  722. package/plugins/google_meet/node/server.py +201 -0
  723. package/plugins/google_meet/plugin.yaml +16 -0
  724. package/plugins/google_meet/process_manager.py +324 -0
  725. package/plugins/google_meet/realtime/__init__.py +10 -0
  726. package/plugins/google_meet/realtime/openai_client.py +332 -0
  727. package/plugins/google_meet/tools.py +348 -0
  728. package/plugins/hermes-achievements/LICENSE +21 -0
  729. package/plugins/hermes-achievements/README.md +150 -0
  730. package/plugins/hermes-achievements/dashboard/dist/index.js +732 -0
  731. package/plugins/hermes-achievements/dashboard/dist/style.css +146 -0
  732. package/plugins/hermes-achievements/dashboard/manifest.json +11 -0
  733. package/plugins/hermes-achievements/dashboard/plugin_api.py +1062 -0
  734. package/plugins/hermes-achievements/docs/achievements-performance-implementation-plan.md +157 -0
  735. package/plugins/hermes-achievements/docs/achievements-performance-implementation-spec.md +219 -0
  736. package/plugins/hermes-achievements/docs/achievements-performance-spec.md +174 -0
  737. package/plugins/hermes-achievements/docs/assets/achievements-dashboard-hd.png +0 -0
  738. package/plugins/hermes-achievements/docs/assets/achievements-tier-showcase-hd.png +0 -0
  739. package/plugins/hermes-achievements/tests/test_achievement_engine.py +156 -0
  740. package/plugins/image_gen/openai/__init__.py +303 -0
  741. package/plugins/image_gen/openai/__pycache__/__init__.cpython-312.pyc +0 -0
  742. package/plugins/image_gen/openai/plugin.yaml +7 -0
  743. package/plugins/image_gen/openai-codex/__init__.py +378 -0
  744. package/plugins/image_gen/openai-codex/__pycache__/__init__.cpython-312.pyc +0 -0
  745. package/plugins/image_gen/openai-codex/plugin.yaml +5 -0
  746. package/plugins/image_gen/xai/__init__.py +316 -0
  747. package/plugins/image_gen/xai/__pycache__/__init__.cpython-312.pyc +0 -0
  748. package/plugins/image_gen/xai/plugin.yaml +7 -0
  749. package/plugins/kanban/dashboard/dist/index.js +3143 -0
  750. package/plugins/kanban/dashboard/dist/style.css +1500 -0
  751. package/plugins/kanban/dashboard/manifest.json +14 -0
  752. package/plugins/kanban/dashboard/plugin_api.py +1612 -0
  753. package/plugins/kanban/systemd/hermes-kanban-dispatcher.service +32 -0
  754. package/plugins/memory/__init__.py +408 -0
  755. package/plugins/memory/byterover/README.md +41 -0
  756. package/plugins/memory/byterover/__init__.py +384 -0
  757. package/plugins/memory/byterover/plugin.yaml +9 -0
  758. package/plugins/memory/hindsight/README.md +138 -0
  759. package/plugins/memory/hindsight/__init__.py +1758 -0
  760. package/plugins/memory/hindsight/plugin.yaml +8 -0
  761. package/plugins/memory/holographic/README.md +36 -0
  762. package/plugins/memory/holographic/__init__.py +409 -0
  763. package/plugins/memory/holographic/holographic.py +203 -0
  764. package/plugins/memory/holographic/plugin.yaml +5 -0
  765. package/plugins/memory/holographic/retrieval.py +593 -0
  766. package/plugins/memory/holographic/store.py +579 -0
  767. package/plugins/memory/honcho/README.md +328 -0
  768. package/plugins/memory/honcho/__init__.py +1329 -0
  769. package/plugins/memory/honcho/cli.py +1452 -0
  770. package/plugins/memory/honcho/client.py +784 -0
  771. package/plugins/memory/honcho/plugin.yaml +7 -0
  772. package/plugins/memory/honcho/session.py +1255 -0
  773. package/plugins/memory/mem0/README.md +38 -0
  774. package/plugins/memory/mem0/__init__.py +374 -0
  775. package/plugins/memory/mem0/plugin.yaml +5 -0
  776. package/plugins/memory/openviking/README.md +40 -0
  777. package/plugins/memory/openviking/__init__.py +945 -0
  778. package/plugins/memory/openviking/plugin.yaml +9 -0
  779. package/plugins/memory/retaindb/README.md +40 -0
  780. package/plugins/memory/retaindb/__init__.py +767 -0
  781. package/plugins/memory/retaindb/plugin.yaml +7 -0
  782. package/plugins/memory/supermemory/README.md +99 -0
  783. package/plugins/memory/supermemory/__init__.py +792 -0
  784. package/plugins/memory/supermemory/plugin.yaml +5 -0
  785. package/plugins/model-providers/README.md +70 -0
  786. package/plugins/model-providers/ai-gateway/__init__.py +43 -0
  787. package/plugins/model-providers/ai-gateway/__pycache__/__init__.cpython-312.pyc +0 -0
  788. package/plugins/model-providers/ai-gateway/plugin.yaml +5 -0
  789. package/plugins/model-providers/alibaba/__init__.py +13 -0
  790. package/plugins/model-providers/alibaba/__pycache__/__init__.cpython-312.pyc +0 -0
  791. package/plugins/model-providers/alibaba/plugin.yaml +5 -0
  792. package/plugins/model-providers/alibaba-coding-plan/__init__.py +21 -0
  793. package/plugins/model-providers/alibaba-coding-plan/__pycache__/__init__.cpython-312.pyc +0 -0
  794. package/plugins/model-providers/alibaba-coding-plan/plugin.yaml +5 -0
  795. package/plugins/model-providers/anthropic/__init__.py +52 -0
  796. package/plugins/model-providers/anthropic/__pycache__/__init__.cpython-312.pyc +0 -0
  797. package/plugins/model-providers/anthropic/plugin.yaml +5 -0
  798. package/plugins/model-providers/arcee/__init__.py +13 -0
  799. package/plugins/model-providers/arcee/__pycache__/__init__.cpython-312.pyc +0 -0
  800. package/plugins/model-providers/arcee/plugin.yaml +5 -0
  801. package/plugins/model-providers/azure-foundry/__init__.py +21 -0
  802. package/plugins/model-providers/azure-foundry/__pycache__/__init__.cpython-312.pyc +0 -0
  803. package/plugins/model-providers/azure-foundry/plugin.yaml +5 -0
  804. package/plugins/model-providers/bedrock/__init__.py +29 -0
  805. package/plugins/model-providers/bedrock/__pycache__/__init__.cpython-312.pyc +0 -0
  806. package/plugins/model-providers/bedrock/plugin.yaml +5 -0
  807. package/plugins/model-providers/copilot/__init__.py +58 -0
  808. package/plugins/model-providers/copilot/__pycache__/__init__.cpython-312.pyc +0 -0
  809. package/plugins/model-providers/copilot/plugin.yaml +5 -0
  810. package/plugins/model-providers/copilot-acp/__init__.py +34 -0
  811. package/plugins/model-providers/copilot-acp/__pycache__/__init__.cpython-312.pyc +0 -0
  812. package/plugins/model-providers/copilot-acp/plugin.yaml +5 -0
  813. package/plugins/model-providers/custom/__init__.py +68 -0
  814. package/plugins/model-providers/custom/__pycache__/__init__.cpython-312.pyc +0 -0
  815. package/plugins/model-providers/custom/plugin.yaml +5 -0
  816. package/plugins/model-providers/deepseek/__init__.py +99 -0
  817. package/plugins/model-providers/deepseek/__pycache__/__init__.cpython-312.pyc +0 -0
  818. package/plugins/model-providers/deepseek/plugin.yaml +5 -0
  819. package/plugins/model-providers/gemini/__init__.py +72 -0
  820. package/plugins/model-providers/gemini/__pycache__/__init__.cpython-312.pyc +0 -0
  821. package/plugins/model-providers/gemini/plugin.yaml +5 -0
  822. package/plugins/model-providers/gmi/__init__.py +31 -0
  823. package/plugins/model-providers/gmi/__pycache__/__init__.cpython-312.pyc +0 -0
  824. package/plugins/model-providers/gmi/plugin.yaml +5 -0
  825. package/plugins/model-providers/huggingface/__init__.py +20 -0
  826. package/plugins/model-providers/huggingface/__pycache__/__init__.cpython-312.pyc +0 -0
  827. package/plugins/model-providers/huggingface/plugin.yaml +5 -0
  828. package/plugins/model-providers/kilocode/__init__.py +14 -0
  829. package/plugins/model-providers/kilocode/__pycache__/__init__.cpython-312.pyc +0 -0
  830. package/plugins/model-providers/kilocode/plugin.yaml +5 -0
  831. package/plugins/model-providers/kimi-coding/__init__.py +71 -0
  832. package/plugins/model-providers/kimi-coding/__pycache__/__init__.cpython-312.pyc +0 -0
  833. package/plugins/model-providers/kimi-coding/plugin.yaml +5 -0
  834. package/plugins/model-providers/minimax/__init__.py +45 -0
  835. package/plugins/model-providers/minimax/__pycache__/__init__.cpython-312.pyc +0 -0
  836. package/plugins/model-providers/minimax/plugin.yaml +5 -0
  837. package/plugins/model-providers/nous/__init__.py +54 -0
  838. package/plugins/model-providers/nous/__pycache__/__init__.cpython-312.pyc +0 -0
  839. package/plugins/model-providers/nous/plugin.yaml +5 -0
  840. package/plugins/model-providers/novita/__init__.py +27 -0
  841. package/plugins/model-providers/novita/__pycache__/__init__.cpython-312.pyc +0 -0
  842. package/plugins/model-providers/novita/plugin.yaml +5 -0
  843. package/plugins/model-providers/nvidia/__init__.py +21 -0
  844. package/plugins/model-providers/nvidia/__pycache__/__init__.cpython-312.pyc +0 -0
  845. package/plugins/model-providers/nvidia/plugin.yaml +5 -0
  846. package/plugins/model-providers/ollama-cloud/__init__.py +14 -0
  847. package/plugins/model-providers/ollama-cloud/__pycache__/__init__.cpython-312.pyc +0 -0
  848. package/plugins/model-providers/ollama-cloud/plugin.yaml +5 -0
  849. package/plugins/model-providers/openai-codex/__init__.py +15 -0
  850. package/plugins/model-providers/openai-codex/__pycache__/__init__.cpython-312.pyc +0 -0
  851. package/plugins/model-providers/openai-codex/plugin.yaml +5 -0
  852. package/plugins/model-providers/opencode-zen/__init__.py +30 -0
  853. package/plugins/model-providers/opencode-zen/__pycache__/__init__.cpython-312.pyc +0 -0
  854. package/plugins/model-providers/opencode-zen/plugin.yaml +5 -0
  855. package/plugins/model-providers/openrouter/__init__.py +115 -0
  856. package/plugins/model-providers/openrouter/__pycache__/__init__.cpython-312.pyc +0 -0
  857. package/plugins/model-providers/openrouter/plugin.yaml +5 -0
  858. package/plugins/model-providers/qwen-oauth/__init__.py +82 -0
  859. package/plugins/model-providers/qwen-oauth/__pycache__/__init__.cpython-312.pyc +0 -0
  860. package/plugins/model-providers/qwen-oauth/plugin.yaml +5 -0
  861. package/plugins/model-providers/stepfun/__init__.py +14 -0
  862. package/plugins/model-providers/stepfun/__pycache__/__init__.cpython-312.pyc +0 -0
  863. package/plugins/model-providers/stepfun/plugin.yaml +5 -0
  864. package/plugins/model-providers/xai/__init__.py +15 -0
  865. package/plugins/model-providers/xai/__pycache__/__init__.cpython-312.pyc +0 -0
  866. package/plugins/model-providers/xai/plugin.yaml +5 -0
  867. package/plugins/model-providers/xiaomi/__init__.py +14 -0
  868. package/plugins/model-providers/xiaomi/__pycache__/__init__.cpython-312.pyc +0 -0
  869. package/plugins/model-providers/xiaomi/plugin.yaml +5 -0
  870. package/plugins/model-providers/zai/__init__.py +21 -0
  871. package/plugins/model-providers/zai/__pycache__/__init__.cpython-312.pyc +0 -0
  872. package/plugins/model-providers/zai/plugin.yaml +5 -0
  873. package/plugins/observability/langfuse/README.md +53 -0
  874. package/plugins/observability/langfuse/__init__.py +1004 -0
  875. package/plugins/observability/langfuse/plugin.yaml +14 -0
  876. package/plugins/platforms/google_chat/__init__.py +3 -0
  877. package/plugins/platforms/google_chat/__pycache__/__init__.cpython-312.pyc +0 -0
  878. package/plugins/platforms/google_chat/__pycache__/adapter.cpython-312.pyc +0 -0
  879. package/plugins/platforms/google_chat/adapter.py +3343 -0
  880. package/plugins/platforms/google_chat/oauth.py +639 -0
  881. package/plugins/platforms/google_chat/plugin.yaml +39 -0
  882. package/plugins/platforms/irc/__init__.py +3 -0
  883. package/plugins/platforms/irc/__pycache__/__init__.cpython-312.pyc +0 -0
  884. package/plugins/platforms/irc/__pycache__/adapter.cpython-312.pyc +0 -0
  885. package/plugins/platforms/irc/adapter.py +969 -0
  886. package/plugins/platforms/irc/plugin.yaml +54 -0
  887. package/plugins/platforms/line/__init__.py +3 -0
  888. package/plugins/platforms/line/__pycache__/__init__.cpython-312.pyc +0 -0
  889. package/plugins/platforms/line/__pycache__/adapter.cpython-312.pyc +0 -0
  890. package/plugins/platforms/line/adapter.py +1639 -0
  891. package/plugins/platforms/line/plugin.yaml +65 -0
  892. package/plugins/platforms/simplex/__init__.py +3 -0
  893. package/plugins/platforms/simplex/__pycache__/__init__.cpython-312.pyc +0 -0
  894. package/plugins/platforms/simplex/__pycache__/adapter.cpython-312.pyc +0 -0
  895. package/plugins/platforms/simplex/adapter.py +746 -0
  896. package/plugins/platforms/simplex/plugin.yaml +37 -0
  897. package/plugins/platforms/teams/__init__.py +3 -0
  898. package/plugins/platforms/teams/__pycache__/__init__.cpython-312.pyc +0 -0
  899. package/plugins/platforms/teams/__pycache__/adapter.cpython-312.pyc +0 -0
  900. package/plugins/platforms/teams/adapter.py +1188 -0
  901. package/plugins/platforms/teams/plugin.yaml +48 -0
  902. package/plugins/spotify/__init__.py +66 -0
  903. package/plugins/spotify/__pycache__/__init__.cpython-312.pyc +0 -0
  904. package/plugins/spotify/__pycache__/client.cpython-312.pyc +0 -0
  905. package/plugins/spotify/__pycache__/tools.cpython-312.pyc +0 -0
  906. package/plugins/spotify/client.py +435 -0
  907. package/plugins/spotify/plugin.yaml +13 -0
  908. package/plugins/spotify/tools.py +454 -0
  909. package/plugins/teams_pipeline/__init__.py +23 -0
  910. package/plugins/teams_pipeline/cli.py +463 -0
  911. package/plugins/teams_pipeline/meetings.py +333 -0
  912. package/plugins/teams_pipeline/models.py +350 -0
  913. package/plugins/teams_pipeline/pipeline.py +692 -0
  914. package/plugins/teams_pipeline/plugin.yaml +9 -0
  915. package/plugins/teams_pipeline/runtime.py +135 -0
  916. package/plugins/teams_pipeline/store.py +194 -0
  917. package/plugins/teams_pipeline/subscriptions.py +249 -0
  918. package/plugins/video_gen/fal/__init__.py +523 -0
  919. package/plugins/video_gen/fal/__pycache__/__init__.cpython-312.pyc +0 -0
  920. package/plugins/video_gen/fal/plugin.yaml +7 -0
  921. package/plugins/video_gen/xai/__init__.py +441 -0
  922. package/plugins/video_gen/xai/__pycache__/__init__.cpython-312.pyc +0 -0
  923. package/plugins/video_gen/xai/plugin.yaml +7 -0
  924. package/plugins/web/__init__.py +7 -0
  925. package/plugins/web/__pycache__/__init__.cpython-312.pyc +0 -0
  926. package/plugins/web/brave_free/__init__.py +14 -0
  927. package/plugins/web/brave_free/__pycache__/__init__.cpython-312.pyc +0 -0
  928. package/plugins/web/brave_free/__pycache__/provider.cpython-312.pyc +0 -0
  929. package/plugins/web/brave_free/plugin.yaml +7 -0
  930. package/plugins/web/brave_free/provider.py +137 -0
  931. package/plugins/web/ddgs/__init__.py +15 -0
  932. package/plugins/web/ddgs/__pycache__/__init__.cpython-312.pyc +0 -0
  933. package/plugins/web/ddgs/__pycache__/provider.cpython-312.pyc +0 -0
  934. package/plugins/web/ddgs/plugin.yaml +7 -0
  935. package/plugins/web/ddgs/provider.py +104 -0
  936. package/plugins/web/exa/__init__.py +15 -0
  937. package/plugins/web/exa/__pycache__/__init__.cpython-312.pyc +0 -0
  938. package/plugins/web/exa/__pycache__/provider.cpython-312.pyc +0 -0
  939. package/plugins/web/exa/plugin.yaml +7 -0
  940. package/plugins/web/exa/provider.py +212 -0
  941. package/plugins/web/firecrawl/__init__.py +28 -0
  942. package/plugins/web/firecrawl/__pycache__/__init__.cpython-312.pyc +0 -0
  943. package/plugins/web/firecrawl/__pycache__/provider.cpython-312.pyc +0 -0
  944. package/plugins/web/firecrawl/plugin.yaml +7 -0
  945. package/plugins/web/firecrawl/provider.py +773 -0
  946. package/plugins/web/parallel/__init__.py +16 -0
  947. package/plugins/web/parallel/__pycache__/__init__.cpython-312.pyc +0 -0
  948. package/plugins/web/parallel/__pycache__/provider.cpython-312.pyc +0 -0
  949. package/plugins/web/parallel/plugin.yaml +7 -0
  950. package/plugins/web/parallel/provider.py +291 -0
  951. package/plugins/web/searxng/__init__.py +15 -0
  952. package/plugins/web/searxng/__pycache__/__init__.cpython-312.pyc +0 -0
  953. package/plugins/web/searxng/__pycache__/provider.cpython-312.pyc +0 -0
  954. package/plugins/web/searxng/plugin.yaml +7 -0
  955. package/plugins/web/searxng/provider.py +140 -0
  956. package/plugins/web/tavily/__init__.py +15 -0
  957. package/plugins/web/tavily/__pycache__/__init__.cpython-312.pyc +0 -0
  958. package/plugins/web/tavily/__pycache__/provider.cpython-312.pyc +0 -0
  959. package/plugins/web/tavily/plugin.yaml +7 -0
  960. package/plugins/web/tavily/provider.py +285 -0
  961. package/providers/README.md +78 -0
  962. package/providers/__init__.py +192 -0
  963. package/providers/__pycache__/__init__.cpython-312.pyc +0 -0
  964. package/providers/__pycache__/base.cpython-312.pyc +0 -0
  965. package/providers/base.py +184 -0
  966. package/pyproject.toml +255 -0
  967. package/run_agent.py +16409 -0
  968. package/scripts/benchmark_browser_eval.py +138 -0
  969. package/scripts/build_model_catalog.py +95 -0
  970. package/scripts/build_skills_index.py +325 -0
  971. package/scripts/check-windows-footguns.py +624 -0
  972. package/scripts/contributor_audit.py +473 -0
  973. package/scripts/discord-voice-doctor.py +396 -0
  974. package/scripts/hermes-gateway +416 -0
  975. package/scripts/install.cmd +28 -0
  976. package/scripts/install.ps1 +1611 -0
  977. package/scripts/install.sh +2007 -0
  978. package/scripts/install_psutil_android.py +117 -0
  979. package/scripts/keystroke_diagnostic.py +81 -0
  980. package/scripts/kill_modal.sh +34 -0
  981. package/scripts/lib/node-bootstrap.sh +238 -0
  982. package/scripts/lint_diff.py +207 -0
  983. package/scripts/postinstall.js +150 -0
  984. package/scripts/profile-tui.py +626 -0
  985. package/scripts/release.py +1680 -0
  986. package/scripts/run_tests.sh +129 -0
  987. package/scripts/sample_and_compress.py +409 -0
  988. package/scripts/setup_open_webui.sh +349 -0
  989. package/scripts/whatsapp-bridge/allowlist.js +88 -0
  990. package/scripts/whatsapp-bridge/allowlist.test.mjs +80 -0
  991. package/scripts/whatsapp-bridge/bridge.js +729 -0
  992. package/scripts/whatsapp-bridge/package-lock.json +2141 -0
  993. package/scripts/whatsapp-bridge/package.json +19 -0
  994. package/skills/apple/DESCRIPTION.md +2 -0
  995. package/skills/apple/apple-notes/SKILL.md +90 -0
  996. package/skills/apple/apple-reminders/SKILL.md +98 -0
  997. package/skills/apple/findmy/SKILL.md +131 -0
  998. package/skills/apple/imessage/SKILL.md +102 -0
  999. package/skills/apple/macos-computer-use/SKILL.md +201 -0
  1000. package/skills/autonomous-ai-agents/DESCRIPTION.md +3 -0
  1001. package/skills/autonomous-ai-agents/claude-code/SKILL.md +745 -0
  1002. package/skills/autonomous-ai-agents/codex/SKILL.md +130 -0
  1003. package/skills/autonomous-ai-agents/hermes-agent/SKILL.md +1014 -0
  1004. package/skills/autonomous-ai-agents/opencode/SKILL.md +219 -0
  1005. package/skills/creative/DESCRIPTION.md +3 -0
  1006. package/skills/creative/architecture-diagram/SKILL.md +148 -0
  1007. package/skills/creative/architecture-diagram/templates/template.html +319 -0
  1008. package/skills/creative/ascii-art/SKILL.md +322 -0
  1009. package/skills/creative/ascii-video/README.md +290 -0
  1010. package/skills/creative/ascii-video/SKILL.md +241 -0
  1011. package/skills/creative/ascii-video/references/architecture.md +802 -0
  1012. package/skills/creative/ascii-video/references/composition.md +892 -0
  1013. package/skills/creative/ascii-video/references/effects.md +1865 -0
  1014. package/skills/creative/ascii-video/references/inputs.md +685 -0
  1015. package/skills/creative/ascii-video/references/optimization.md +688 -0
  1016. package/skills/creative/ascii-video/references/scenes.md +1011 -0
  1017. package/skills/creative/ascii-video/references/shaders.md +1385 -0
  1018. package/skills/creative/ascii-video/references/troubleshooting.md +367 -0
  1019. package/skills/creative/baoyu-comic/PORT_NOTES.md +77 -0
  1020. package/skills/creative/baoyu-comic/SKILL.md +247 -0
  1021. package/skills/creative/baoyu-comic/references/analysis-framework.md +176 -0
  1022. package/skills/creative/baoyu-comic/references/art-styles/chalk.md +101 -0
  1023. package/skills/creative/baoyu-comic/references/art-styles/ink-brush.md +97 -0
  1024. package/skills/creative/baoyu-comic/references/art-styles/ligne-claire.md +75 -0
  1025. package/skills/creative/baoyu-comic/references/art-styles/manga.md +93 -0
  1026. package/skills/creative/baoyu-comic/references/art-styles/minimalist.md +84 -0
  1027. package/skills/creative/baoyu-comic/references/art-styles/realistic.md +89 -0
  1028. package/skills/creative/baoyu-comic/references/auto-selection.md +71 -0
  1029. package/skills/creative/baoyu-comic/references/base-prompt.md +98 -0
  1030. package/skills/creative/baoyu-comic/references/character-template.md +180 -0
  1031. package/skills/creative/baoyu-comic/references/layouts/cinematic.md +23 -0
  1032. package/skills/creative/baoyu-comic/references/layouts/dense.md +23 -0
  1033. package/skills/creative/baoyu-comic/references/layouts/four-panel.md +40 -0
  1034. package/skills/creative/baoyu-comic/references/layouts/mixed.md +23 -0
  1035. package/skills/creative/baoyu-comic/references/layouts/splash.md +23 -0
  1036. package/skills/creative/baoyu-comic/references/layouts/standard.md +23 -0
  1037. package/skills/creative/baoyu-comic/references/layouts/webtoon.md +30 -0
  1038. package/skills/creative/baoyu-comic/references/ohmsha-guide.md +85 -0
  1039. package/skills/creative/baoyu-comic/references/partial-workflows.md +106 -0
  1040. package/skills/creative/baoyu-comic/references/presets/concept-story.md +121 -0
  1041. package/skills/creative/baoyu-comic/references/presets/four-panel.md +107 -0
  1042. package/skills/creative/baoyu-comic/references/presets/ohmsha.md +114 -0
  1043. package/skills/creative/baoyu-comic/references/presets/shoujo.md +116 -0
  1044. package/skills/creative/baoyu-comic/references/presets/wuxia.md +110 -0
  1045. package/skills/creative/baoyu-comic/references/storyboard-template.md +143 -0
  1046. package/skills/creative/baoyu-comic/references/tones/action.md +110 -0
  1047. package/skills/creative/baoyu-comic/references/tones/dramatic.md +95 -0
  1048. package/skills/creative/baoyu-comic/references/tones/energetic.md +105 -0
  1049. package/skills/creative/baoyu-comic/references/tones/neutral.md +63 -0
  1050. package/skills/creative/baoyu-comic/references/tones/romantic.md +100 -0
  1051. package/skills/creative/baoyu-comic/references/tones/vintage.md +104 -0
  1052. package/skills/creative/baoyu-comic/references/tones/warm.md +94 -0
  1053. package/skills/creative/baoyu-comic/references/workflow.md +401 -0
  1054. package/skills/creative/baoyu-infographic/PORT_NOTES.md +43 -0
  1055. package/skills/creative/baoyu-infographic/SKILL.md +237 -0
  1056. package/skills/creative/baoyu-infographic/references/analysis-framework.md +182 -0
  1057. package/skills/creative/baoyu-infographic/references/base-prompt.md +43 -0
  1058. package/skills/creative/baoyu-infographic/references/layouts/bento-grid.md +41 -0
  1059. package/skills/creative/baoyu-infographic/references/layouts/binary-comparison.md +48 -0
  1060. package/skills/creative/baoyu-infographic/references/layouts/bridge.md +41 -0
  1061. package/skills/creative/baoyu-infographic/references/layouts/circular-flow.md +41 -0
  1062. package/skills/creative/baoyu-infographic/references/layouts/comic-strip.md +41 -0
  1063. package/skills/creative/baoyu-infographic/references/layouts/comparison-matrix.md +41 -0
  1064. package/skills/creative/baoyu-infographic/references/layouts/dashboard.md +41 -0
  1065. package/skills/creative/baoyu-infographic/references/layouts/dense-modules.md +72 -0
  1066. package/skills/creative/baoyu-infographic/references/layouts/funnel.md +41 -0
  1067. package/skills/creative/baoyu-infographic/references/layouts/hierarchical-layers.md +48 -0
  1068. package/skills/creative/baoyu-infographic/references/layouts/hub-spoke.md +41 -0
  1069. package/skills/creative/baoyu-infographic/references/layouts/iceberg.md +41 -0
  1070. package/skills/creative/baoyu-infographic/references/layouts/isometric-map.md +41 -0
  1071. package/skills/creative/baoyu-infographic/references/layouts/jigsaw.md +41 -0
  1072. package/skills/creative/baoyu-infographic/references/layouts/linear-progression.md +48 -0
  1073. package/skills/creative/baoyu-infographic/references/layouts/periodic-table.md +41 -0
  1074. package/skills/creative/baoyu-infographic/references/layouts/story-mountain.md +41 -0
  1075. package/skills/creative/baoyu-infographic/references/layouts/structural-breakdown.md +48 -0
  1076. package/skills/creative/baoyu-infographic/references/layouts/tree-branching.md +41 -0
  1077. package/skills/creative/baoyu-infographic/references/layouts/venn-diagram.md +41 -0
  1078. package/skills/creative/baoyu-infographic/references/layouts/winding-roadmap.md +41 -0
  1079. package/skills/creative/baoyu-infographic/references/structured-content-template.md +244 -0
  1080. package/skills/creative/baoyu-infographic/references/styles/aged-academia.md +36 -0
  1081. package/skills/creative/baoyu-infographic/references/styles/bold-graphic.md +36 -0
  1082. package/skills/creative/baoyu-infographic/references/styles/chalkboard.md +61 -0
  1083. package/skills/creative/baoyu-infographic/references/styles/claymation.md +29 -0
  1084. package/skills/creative/baoyu-infographic/references/styles/corporate-memphis.md +29 -0
  1085. package/skills/creative/baoyu-infographic/references/styles/craft-handmade.md +44 -0
  1086. package/skills/creative/baoyu-infographic/references/styles/cyberpunk-neon.md +29 -0
  1087. package/skills/creative/baoyu-infographic/references/styles/hand-drawn-edu.md +63 -0
  1088. package/skills/creative/baoyu-infographic/references/styles/ikea-manual.md +29 -0
  1089. package/skills/creative/baoyu-infographic/references/styles/kawaii.md +29 -0
  1090. package/skills/creative/baoyu-infographic/references/styles/knolling.md +29 -0
  1091. package/skills/creative/baoyu-infographic/references/styles/lego-brick.md +29 -0
  1092. package/skills/creative/baoyu-infographic/references/styles/morandi-journal.md +60 -0
  1093. package/skills/creative/baoyu-infographic/references/styles/origami.md +29 -0
  1094. package/skills/creative/baoyu-infographic/references/styles/pixel-art.md +29 -0
  1095. package/skills/creative/baoyu-infographic/references/styles/pop-laboratory.md +48 -0
  1096. package/skills/creative/baoyu-infographic/references/styles/retro-pop-grid.md +47 -0
  1097. package/skills/creative/baoyu-infographic/references/styles/storybook-watercolor.md +29 -0
  1098. package/skills/creative/baoyu-infographic/references/styles/subway-map.md +29 -0
  1099. package/skills/creative/baoyu-infographic/references/styles/technical-schematic.md +36 -0
  1100. package/skills/creative/baoyu-infographic/references/styles/ui-wireframe.md +29 -0
  1101. package/skills/creative/claude-design/SKILL.md +591 -0
  1102. package/skills/creative/comfyui/SKILL.md +612 -0
  1103. package/skills/creative/comfyui/references/official-cli.md +255 -0
  1104. package/skills/creative/comfyui/references/rest-api.md +312 -0
  1105. package/skills/creative/comfyui/references/template-integrity.md +243 -0
  1106. package/skills/creative/comfyui/references/workflow-format.md +226 -0
  1107. package/skills/creative/comfyui/scripts/_common.py +835 -0
  1108. package/skills/creative/comfyui/scripts/auto_fix_deps.py +225 -0
  1109. package/skills/creative/comfyui/scripts/check_deps.py +437 -0
  1110. package/skills/creative/comfyui/scripts/comfyui_setup.sh +286 -0
  1111. package/skills/creative/comfyui/scripts/extract_schema.py +315 -0
  1112. package/skills/creative/comfyui/scripts/fetch_logs.py +158 -0
  1113. package/skills/creative/comfyui/scripts/hardware_check.py +497 -0
  1114. package/skills/creative/comfyui/scripts/health_check.py +223 -0
  1115. package/skills/creative/comfyui/scripts/run_batch.py +243 -0
  1116. package/skills/creative/comfyui/scripts/run_workflow.py +796 -0
  1117. package/skills/creative/comfyui/scripts/ws_monitor.py +267 -0
  1118. package/skills/creative/comfyui/tests/README.md +50 -0
  1119. package/skills/creative/comfyui/tests/conftest.py +64 -0
  1120. package/skills/creative/comfyui/tests/pytest.ini +5 -0
  1121. package/skills/creative/comfyui/tests/test_check_deps.py +68 -0
  1122. package/skills/creative/comfyui/tests/test_cloud_integration.py +95 -0
  1123. package/skills/creative/comfyui/tests/test_common.py +447 -0
  1124. package/skills/creative/comfyui/tests/test_extract_schema.py +185 -0
  1125. package/skills/creative/comfyui/tests/test_run_workflow.py +213 -0
  1126. package/skills/creative/comfyui/workflows/README.md +86 -0
  1127. package/skills/creative/comfyui/workflows/animatediff_video.json +64 -0
  1128. package/skills/creative/comfyui/workflows/flux_dev_txt2img.json +78 -0
  1129. package/skills/creative/comfyui/workflows/sd15_txt2img.json +49 -0
  1130. package/skills/creative/comfyui/workflows/sdxl_img2img.json +54 -0
  1131. package/skills/creative/comfyui/workflows/sdxl_inpaint.json +59 -0
  1132. package/skills/creative/comfyui/workflows/sdxl_txt2img.json +49 -0
  1133. package/skills/creative/comfyui/workflows/upscale_4x.json +27 -0
  1134. package/skills/creative/comfyui/workflows/wan_video_t2v.json +69 -0
  1135. package/skills/creative/creative-ideation/SKILL.md +152 -0
  1136. package/skills/creative/creative-ideation/references/full-prompt-library.md +110 -0
  1137. package/skills/creative/design-md/SKILL.md +199 -0
  1138. package/skills/creative/design-md/templates/starter.md +99 -0
  1139. package/skills/creative/excalidraw/SKILL.md +199 -0
  1140. package/skills/creative/excalidraw/references/colors.md +44 -0
  1141. package/skills/creative/excalidraw/references/dark-mode.md +68 -0
  1142. package/skills/creative/excalidraw/references/examples.md +141 -0
  1143. package/skills/creative/excalidraw/scripts/upload.py +133 -0
  1144. package/skills/creative/humanizer/LICENSE +21 -0
  1145. package/skills/creative/humanizer/SKILL.md +578 -0
  1146. package/skills/creative/manim-video/README.md +23 -0
  1147. package/skills/creative/manim-video/SKILL.md +269 -0
  1148. package/skills/creative/manim-video/references/animation-design-thinking.md +161 -0
  1149. package/skills/creative/manim-video/references/animations.md +282 -0
  1150. package/skills/creative/manim-video/references/camera-and-3d.md +135 -0
  1151. package/skills/creative/manim-video/references/decorations.md +202 -0
  1152. package/skills/creative/manim-video/references/equations.md +216 -0
  1153. package/skills/creative/manim-video/references/graphs-and-data.md +163 -0
  1154. package/skills/creative/manim-video/references/mobjects.md +333 -0
  1155. package/skills/creative/manim-video/references/paper-explainer.md +255 -0
  1156. package/skills/creative/manim-video/references/production-quality.md +190 -0
  1157. package/skills/creative/manim-video/references/rendering.md +185 -0
  1158. package/skills/creative/manim-video/references/scene-planning.md +118 -0
  1159. package/skills/creative/manim-video/references/troubleshooting.md +135 -0
  1160. package/skills/creative/manim-video/references/updaters-and-trackers.md +260 -0
  1161. package/skills/creative/manim-video/references/visual-design.md +124 -0
  1162. package/skills/creative/manim-video/scripts/setup.sh +14 -0
  1163. package/skills/creative/p5js/README.md +64 -0
  1164. package/skills/creative/p5js/SKILL.md +556 -0
  1165. package/skills/creative/p5js/references/animation.md +439 -0
  1166. package/skills/creative/p5js/references/color-systems.md +352 -0
  1167. package/skills/creative/p5js/references/core-api.md +410 -0
  1168. package/skills/creative/p5js/references/export-pipeline.md +566 -0
  1169. package/skills/creative/p5js/references/interaction.md +398 -0
  1170. package/skills/creative/p5js/references/shapes-and-geometry.md +300 -0
  1171. package/skills/creative/p5js/references/troubleshooting.md +532 -0
  1172. package/skills/creative/p5js/references/typography.md +302 -0
  1173. package/skills/creative/p5js/references/visual-effects.md +895 -0
  1174. package/skills/creative/p5js/references/webgl-and-3d.md +423 -0
  1175. package/skills/creative/p5js/scripts/export-frames.js +179 -0
  1176. package/skills/creative/p5js/scripts/render.sh +108 -0
  1177. package/skills/creative/p5js/scripts/serve.sh +28 -0
  1178. package/skills/creative/p5js/scripts/setup.sh +87 -0
  1179. package/skills/creative/p5js/templates/viewer.html +395 -0
  1180. package/skills/creative/pixel-art/ATTRIBUTION.md +54 -0
  1181. package/skills/creative/pixel-art/SKILL.md +218 -0
  1182. package/skills/creative/pixel-art/references/palettes.md +49 -0
  1183. package/skills/creative/pixel-art/scripts/__init__.py +0 -0
  1184. package/skills/creative/pixel-art/scripts/palettes.py +167 -0
  1185. package/skills/creative/pixel-art/scripts/pixel_art.py +162 -0
  1186. package/skills/creative/pixel-art/scripts/pixel_art_video.py +345 -0
  1187. package/skills/creative/popular-web-designs/SKILL.md +214 -0
  1188. package/skills/creative/popular-web-designs/templates/airbnb.md +259 -0
  1189. package/skills/creative/popular-web-designs/templates/airtable.md +102 -0
  1190. package/skills/creative/popular-web-designs/templates/apple.md +326 -0
  1191. package/skills/creative/popular-web-designs/templates/bmw.md +193 -0
  1192. package/skills/creative/popular-web-designs/templates/cal.md +272 -0
  1193. package/skills/creative/popular-web-designs/templates/claude.md +325 -0
  1194. package/skills/creative/popular-web-designs/templates/clay.md +317 -0
  1195. package/skills/creative/popular-web-designs/templates/clickhouse.md +294 -0
  1196. package/skills/creative/popular-web-designs/templates/cohere.md +279 -0
  1197. package/skills/creative/popular-web-designs/templates/coinbase.md +142 -0
  1198. package/skills/creative/popular-web-designs/templates/composio.md +320 -0
  1199. package/skills/creative/popular-web-designs/templates/cursor.md +322 -0
  1200. package/skills/creative/popular-web-designs/templates/elevenlabs.md +278 -0
  1201. package/skills/creative/popular-web-designs/templates/expo.md +294 -0
  1202. package/skills/creative/popular-web-designs/templates/figma.md +233 -0
  1203. package/skills/creative/popular-web-designs/templates/framer.md +259 -0
  1204. package/skills/creative/popular-web-designs/templates/hashicorp.md +291 -0
  1205. package/skills/creative/popular-web-designs/templates/ibm.md +345 -0
  1206. package/skills/creative/popular-web-designs/templates/intercom.md +159 -0
  1207. package/skills/creative/popular-web-designs/templates/kraken.md +138 -0
  1208. package/skills/creative/popular-web-designs/templates/linear.app.md +380 -0
  1209. package/skills/creative/popular-web-designs/templates/lovable.md +311 -0
  1210. package/skills/creative/popular-web-designs/templates/minimax.md +270 -0
  1211. package/skills/creative/popular-web-designs/templates/mintlify.md +339 -0
  1212. package/skills/creative/popular-web-designs/templates/miro.md +121 -0
  1213. package/skills/creative/popular-web-designs/templates/mistral.ai.md +274 -0
  1214. package/skills/creative/popular-web-designs/templates/mongodb.md +279 -0
  1215. package/skills/creative/popular-web-designs/templates/notion.md +322 -0
  1216. package/skills/creative/popular-web-designs/templates/nvidia.md +306 -0
  1217. package/skills/creative/popular-web-designs/templates/ollama.md +280 -0
  1218. package/skills/creative/popular-web-designs/templates/opencode.ai.md +294 -0
  1219. package/skills/creative/popular-web-designs/templates/pinterest.md +243 -0
  1220. package/skills/creative/popular-web-designs/templates/posthog.md +269 -0
  1221. package/skills/creative/popular-web-designs/templates/raycast.md +281 -0
  1222. package/skills/creative/popular-web-designs/templates/replicate.md +274 -0
  1223. package/skills/creative/popular-web-designs/templates/resend.md +316 -0
  1224. package/skills/creative/popular-web-designs/templates/revolut.md +198 -0
  1225. package/skills/creative/popular-web-designs/templates/runwayml.md +257 -0
  1226. package/skills/creative/popular-web-designs/templates/sanity.md +370 -0
  1227. package/skills/creative/popular-web-designs/templates/sentry.md +275 -0
  1228. package/skills/creative/popular-web-designs/templates/spacex.md +207 -0
  1229. package/skills/creative/popular-web-designs/templates/spotify.md +259 -0
  1230. package/skills/creative/popular-web-designs/templates/stripe.md +335 -0
  1231. package/skills/creative/popular-web-designs/templates/supabase.md +268 -0
  1232. package/skills/creative/popular-web-designs/templates/superhuman.md +265 -0
  1233. package/skills/creative/popular-web-designs/templates/together.ai.md +276 -0
  1234. package/skills/creative/popular-web-designs/templates/uber.md +308 -0
  1235. package/skills/creative/popular-web-designs/templates/vercel.md +323 -0
  1236. package/skills/creative/popular-web-designs/templates/voltagent.md +336 -0
  1237. package/skills/creative/popular-web-designs/templates/warp.md +266 -0
  1238. package/skills/creative/popular-web-designs/templates/webflow.md +105 -0
  1239. package/skills/creative/popular-web-designs/templates/wise.md +186 -0
  1240. package/skills/creative/popular-web-designs/templates/x.ai.md +270 -0
  1241. package/skills/creative/popular-web-designs/templates/zapier.md +341 -0
  1242. package/skills/creative/pretext/SKILL.md +220 -0
  1243. package/skills/creative/pretext/references/patterns.md +258 -0
  1244. package/skills/creative/pretext/templates/donut-orbit.html +1468 -0
  1245. package/skills/creative/pretext/templates/hello-orb-flow.html +95 -0
  1246. package/skills/creative/sketch/SKILL.md +218 -0
  1247. package/skills/creative/songwriting-and-ai-music/SKILL.md +287 -0
  1248. package/skills/creative/touchdesigner-mcp/SKILL.md +356 -0
  1249. package/skills/creative/touchdesigner-mcp/references/3d-scene.md +275 -0
  1250. package/skills/creative/touchdesigner-mcp/references/animation.md +221 -0
  1251. package/skills/creative/touchdesigner-mcp/references/audio-reactive.md +175 -0
  1252. package/skills/creative/touchdesigner-mcp/references/dat-scripting.md +352 -0
  1253. package/skills/creative/touchdesigner-mcp/references/external-data.md +322 -0
  1254. package/skills/creative/touchdesigner-mcp/references/geometry-comp.md +121 -0
  1255. package/skills/creative/touchdesigner-mcp/references/glsl.md +151 -0
  1256. package/skills/creative/touchdesigner-mcp/references/layout-compositor.md +131 -0
  1257. package/skills/creative/touchdesigner-mcp/references/mcp-tools.md +382 -0
  1258. package/skills/creative/touchdesigner-mcp/references/midi-osc.md +211 -0
  1259. package/skills/creative/touchdesigner-mcp/references/network-patterns.md +966 -0
  1260. package/skills/creative/touchdesigner-mcp/references/operator-tips.md +106 -0
  1261. package/skills/creative/touchdesigner-mcp/references/operators.md +239 -0
  1262. package/skills/creative/touchdesigner-mcp/references/panel-ui.md +281 -0
  1263. package/skills/creative/touchdesigner-mcp/references/particles.md +245 -0
  1264. package/skills/creative/touchdesigner-mcp/references/pitfalls.md +704 -0
  1265. package/skills/creative/touchdesigner-mcp/references/postfx.md +183 -0
  1266. package/skills/creative/touchdesigner-mcp/references/projection-mapping.md +211 -0
  1267. package/skills/creative/touchdesigner-mcp/references/python-api.md +463 -0
  1268. package/skills/creative/touchdesigner-mcp/references/replicator.md +198 -0
  1269. package/skills/creative/touchdesigner-mcp/references/troubleshooting.md +244 -0
  1270. package/skills/creative/touchdesigner-mcp/scripts/setup.sh +115 -0
  1271. package/skills/data-science/DESCRIPTION.md +3 -0
  1272. package/skills/data-science/jupyter-live-kernel/SKILL.md +167 -0
  1273. package/skills/devops/kanban-orchestrator/SKILL.md +189 -0
  1274. package/skills/devops/kanban-worker/SKILL.md +184 -0
  1275. package/skills/devops/webhook-subscriptions/SKILL.md +204 -0
  1276. package/skills/diagramming/DESCRIPTION.md +3 -0
  1277. package/skills/dogfood/SKILL.md +162 -0
  1278. package/skills/dogfood/references/issue-taxonomy.md +109 -0
  1279. package/skills/dogfood/templates/dogfood-report-template.md +86 -0
  1280. package/skills/domain/DESCRIPTION.md +24 -0
  1281. package/skills/email/DESCRIPTION.md +3 -0
  1282. package/skills/email/himalaya/SKILL.md +299 -0
  1283. package/skills/email/himalaya/references/configuration.md +227 -0
  1284. package/skills/email/himalaya/references/message-composition.md +199 -0
  1285. package/skills/gaming/DESCRIPTION.md +3 -0
  1286. package/skills/gaming/minecraft-modpack-server/SKILL.md +187 -0
  1287. package/skills/gaming/pokemon-player/SKILL.md +216 -0
  1288. package/skills/gifs/DESCRIPTION.md +3 -0
  1289. package/skills/github/DESCRIPTION.md +3 -0
  1290. package/skills/github/codebase-inspection/SKILL.md +116 -0
  1291. package/skills/github/github-auth/SKILL.md +247 -0
  1292. package/skills/github/github-auth/scripts/gh-env.sh +66 -0
  1293. package/skills/github/github-code-review/SKILL.md +481 -0
  1294. package/skills/github/github-code-review/references/review-output-template.md +74 -0
  1295. package/skills/github/github-issues/SKILL.md +370 -0
  1296. package/skills/github/github-issues/templates/bug-report.md +35 -0
  1297. package/skills/github/github-issues/templates/feature-request.md +31 -0
  1298. package/skills/github/github-pr-workflow/SKILL.md +367 -0
  1299. package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +183 -0
  1300. package/skills/github/github-pr-workflow/references/conventional-commits.md +71 -0
  1301. package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
  1302. package/skills/github/github-pr-workflow/templates/pr-body-feature.md +33 -0
  1303. package/skills/github/github-repo-management/SKILL.md +516 -0
  1304. package/skills/github/github-repo-management/references/github-api-cheatsheet.md +161 -0
  1305. package/skills/index-cache/anthropics_skills_skills_.json +1 -0
  1306. package/skills/index-cache/claude_marketplace_anthropics_skills.json +1 -0
  1307. package/skills/index-cache/lobehub_index.json +1 -0
  1308. package/skills/index-cache/openai_skills_skills_.json +1 -0
  1309. package/skills/inference-sh/DESCRIPTION.md +19 -0
  1310. package/skills/mcp/DESCRIPTION.md +3 -0
  1311. package/skills/mcp/native-mcp/SKILL.md +357 -0
  1312. package/skills/media/DESCRIPTION.md +3 -0
  1313. package/skills/media/gif-search/SKILL.md +91 -0
  1314. package/skills/media/heartmula/SKILL.md +171 -0
  1315. package/skills/media/songsee/SKILL.md +83 -0
  1316. package/skills/media/spotify/SKILL.md +135 -0
  1317. package/skills/media/youtube-content/SKILL.md +73 -0
  1318. package/skills/media/youtube-content/references/output-formats.md +56 -0
  1319. package/skills/media/youtube-content/scripts/fetch_transcript.py +124 -0
  1320. package/skills/mlops/DESCRIPTION.md +3 -0
  1321. package/skills/mlops/evaluation/DESCRIPTION.md +3 -0
  1322. package/skills/mlops/evaluation/lm-evaluation-harness/SKILL.md +498 -0
  1323. package/skills/mlops/evaluation/lm-evaluation-harness/references/api-evaluation.md +490 -0
  1324. package/skills/mlops/evaluation/lm-evaluation-harness/references/benchmark-guide.md +488 -0
  1325. package/skills/mlops/evaluation/lm-evaluation-harness/references/custom-tasks.md +602 -0
  1326. package/skills/mlops/evaluation/lm-evaluation-harness/references/distributed-eval.md +519 -0
  1327. package/skills/mlops/evaluation/weights-and-biases/SKILL.md +594 -0
  1328. package/skills/mlops/evaluation/weights-and-biases/references/artifacts.md +584 -0
  1329. package/skills/mlops/evaluation/weights-and-biases/references/integrations.md +700 -0
  1330. package/skills/mlops/evaluation/weights-and-biases/references/sweeps.md +847 -0
  1331. package/skills/mlops/huggingface-hub/SKILL.md +81 -0
  1332. package/skills/mlops/inference/DESCRIPTION.md +3 -0
  1333. package/skills/mlops/inference/llama-cpp/SKILL.md +249 -0
  1334. package/skills/mlops/inference/llama-cpp/references/advanced-usage.md +504 -0
  1335. package/skills/mlops/inference/llama-cpp/references/hub-discovery.md +168 -0
  1336. package/skills/mlops/inference/llama-cpp/references/optimization.md +89 -0
  1337. package/skills/mlops/inference/llama-cpp/references/quantization.md +243 -0
  1338. package/skills/mlops/inference/llama-cpp/references/server.md +150 -0
  1339. package/skills/mlops/inference/llama-cpp/references/troubleshooting.md +442 -0
  1340. package/skills/mlops/inference/obliteratus/SKILL.md +342 -0
  1341. package/skills/mlops/inference/obliteratus/references/analysis-modules.md +166 -0
  1342. package/skills/mlops/inference/obliteratus/references/methods-guide.md +141 -0
  1343. package/skills/mlops/inference/obliteratus/templates/abliteration-config.yaml +33 -0
  1344. package/skills/mlops/inference/obliteratus/templates/analysis-study.yaml +40 -0
  1345. package/skills/mlops/inference/obliteratus/templates/batch-abliteration.yaml +41 -0
  1346. package/skills/mlops/inference/vllm/SKILL.md +372 -0
  1347. package/skills/mlops/inference/vllm/references/optimization.md +226 -0
  1348. package/skills/mlops/inference/vllm/references/quantization.md +284 -0
  1349. package/skills/mlops/inference/vllm/references/server-deployment.md +255 -0
  1350. package/skills/mlops/inference/vllm/references/troubleshooting.md +447 -0
  1351. package/skills/mlops/models/DESCRIPTION.md +3 -0
  1352. package/skills/mlops/models/audiocraft/SKILL.md +568 -0
  1353. package/skills/mlops/models/audiocraft/references/advanced-usage.md +666 -0
  1354. package/skills/mlops/models/audiocraft/references/troubleshooting.md +504 -0
  1355. package/skills/mlops/models/segment-anything/SKILL.md +506 -0
  1356. package/skills/mlops/models/segment-anything/references/advanced-usage.md +589 -0
  1357. package/skills/mlops/models/segment-anything/references/troubleshooting.md +484 -0
  1358. package/skills/mlops/research/DESCRIPTION.md +3 -0
  1359. package/skills/mlops/research/dspy/SKILL.md +594 -0
  1360. package/skills/mlops/research/dspy/references/examples.md +663 -0
  1361. package/skills/mlops/research/dspy/references/modules.md +475 -0
  1362. package/skills/mlops/research/dspy/references/optimizers.md +566 -0
  1363. package/skills/mlops/training/DESCRIPTION.md +3 -0
  1364. package/skills/mlops/vector-databases/DESCRIPTION.md +3 -0
  1365. package/skills/note-taking/DESCRIPTION.md +3 -0
  1366. package/skills/note-taking/obsidian/SKILL.md +61 -0
  1367. package/skills/productivity/DESCRIPTION.md +3 -0
  1368. package/skills/productivity/airtable/SKILL.md +229 -0
  1369. package/skills/productivity/google-workspace/SKILL.md +335 -0
  1370. package/skills/productivity/google-workspace/references/gmail-search-syntax.md +63 -0
  1371. package/skills/productivity/google-workspace/scripts/_hermes_home.py +43 -0
  1372. package/skills/productivity/google-workspace/scripts/google_api.py +1221 -0
  1373. package/skills/productivity/google-workspace/scripts/gws_bridge.py +108 -0
  1374. package/skills/productivity/google-workspace/scripts/setup.py +454 -0
  1375. package/skills/productivity/linear/SKILL.md +380 -0
  1376. package/skills/productivity/linear/scripts/linear_api.py +445 -0
  1377. package/skills/productivity/maps/SKILL.md +195 -0
  1378. package/skills/productivity/maps/scripts/maps_client.py +1298 -0
  1379. package/skills/productivity/nano-pdf/SKILL.md +52 -0
  1380. package/skills/productivity/notion/SKILL.md +448 -0
  1381. package/skills/productivity/notion/references/block-types.md +112 -0
  1382. package/skills/productivity/ocr-and-documents/DESCRIPTION.md +3 -0
  1383. package/skills/productivity/ocr-and-documents/SKILL.md +172 -0
  1384. package/skills/productivity/ocr-and-documents/scripts/extract_marker.py +87 -0
  1385. package/skills/productivity/ocr-and-documents/scripts/extract_pymupdf.py +98 -0
  1386. package/skills/productivity/powerpoint/LICENSE.txt +30 -0
  1387. package/skills/productivity/powerpoint/SKILL.md +237 -0
  1388. package/skills/productivity/powerpoint/editing.md +205 -0
  1389. package/skills/productivity/powerpoint/pptxgenjs.md +420 -0
  1390. package/skills/productivity/powerpoint/scripts/__init__.py +0 -0
  1391. package/skills/productivity/powerpoint/scripts/add_slide.py +195 -0
  1392. package/skills/productivity/powerpoint/scripts/clean.py +286 -0
  1393. package/skills/productivity/powerpoint/scripts/office/helpers/__init__.py +0 -0
  1394. package/skills/productivity/powerpoint/scripts/office/helpers/merge_runs.py +199 -0
  1395. package/skills/productivity/powerpoint/scripts/office/helpers/simplify_redlines.py +197 -0
  1396. package/skills/productivity/powerpoint/scripts/office/pack.py +159 -0
  1397. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  1398. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  1399. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  1400. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  1401. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  1402. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  1403. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  1404. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  1405. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  1406. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  1407. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  1408. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  1409. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  1410. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  1411. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  1412. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  1413. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  1414. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  1415. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  1416. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  1417. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  1418. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  1419. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  1420. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  1421. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  1422. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  1423. package/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  1424. package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-contentTypes.xsd +42 -0
  1425. package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-coreProperties.xsd +50 -0
  1426. package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-digSig.xsd +49 -0
  1427. package/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-relationships.xsd +33 -0
  1428. package/skills/productivity/powerpoint/scripts/office/schemas/mce/mc.xsd +75 -0
  1429. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  1430. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  1431. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  1432. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  1433. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  1434. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  1435. package/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  1436. package/skills/productivity/teams-meeting-pipeline/SKILL.md +116 -0
  1437. package/skills/red-teaming/godmode/SKILL.md +404 -0
  1438. package/skills/red-teaming/godmode/references/jailbreak-templates.md +128 -0
  1439. package/skills/red-teaming/godmode/references/refusal-detection.md +142 -0
  1440. package/skills/red-teaming/godmode/scripts/auto_jailbreak.py +769 -0
  1441. package/skills/red-teaming/godmode/scripts/godmode_race.py +530 -0
  1442. package/skills/red-teaming/godmode/scripts/load_godmode.py +45 -0
  1443. package/skills/red-teaming/godmode/scripts/parseltongue.py +550 -0
  1444. package/skills/red-teaming/godmode/templates/prefill-subtle.json +10 -0
  1445. package/skills/red-teaming/godmode/templates/prefill.json +18 -0
  1446. package/skills/research/DESCRIPTION.md +3 -0
  1447. package/skills/research/arxiv/SKILL.md +282 -0
  1448. package/skills/research/arxiv/scripts/search_arxiv.py +114 -0
  1449. package/skills/research/blogwatcher/SKILL.md +137 -0
  1450. package/skills/research/llm-wiki/SKILL.md +507 -0
  1451. package/skills/research/polymarket/SKILL.md +77 -0
  1452. package/skills/research/polymarket/references/api-endpoints.md +220 -0
  1453. package/skills/research/polymarket/scripts/polymarket.py +284 -0
  1454. package/skills/research/research-paper-writing/SKILL.md +2377 -0
  1455. package/skills/research/research-paper-writing/references/autoreason-methodology.md +394 -0
  1456. package/skills/research/research-paper-writing/references/checklists.md +434 -0
  1457. package/skills/research/research-paper-writing/references/citation-workflow.md +564 -0
  1458. package/skills/research/research-paper-writing/references/experiment-patterns.md +728 -0
  1459. package/skills/research/research-paper-writing/references/human-evaluation.md +476 -0
  1460. package/skills/research/research-paper-writing/references/paper-types.md +481 -0
  1461. package/skills/research/research-paper-writing/references/reviewer-guidelines.md +433 -0
  1462. package/skills/research/research-paper-writing/references/sources.md +191 -0
  1463. package/skills/research/research-paper-writing/references/writing-guide.md +474 -0
  1464. package/skills/research/research-paper-writing/templates/README.md +251 -0
  1465. package/skills/research/research-paper-writing/templates/aaai2026/README.md +534 -0
  1466. package/skills/research/research-paper-writing/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
  1467. package/skills/research/research-paper-writing/templates/aaai2026/aaai2026-unified-template.tex +952 -0
  1468. package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.bib +111 -0
  1469. package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.bst +1493 -0
  1470. package/skills/research/research-paper-writing/templates/aaai2026/aaai2026.sty +315 -0
  1471. package/skills/research/research-paper-writing/templates/acl/README.md +50 -0
  1472. package/skills/research/research-paper-writing/templates/acl/acl.sty +312 -0
  1473. package/skills/research/research-paper-writing/templates/acl/acl_latex.tex +377 -0
  1474. package/skills/research/research-paper-writing/templates/acl/acl_lualatex.tex +101 -0
  1475. package/skills/research/research-paper-writing/templates/acl/acl_natbib.bst +1940 -0
  1476. package/skills/research/research-paper-writing/templates/acl/anthology.bib.txt +26 -0
  1477. package/skills/research/research-paper-writing/templates/acl/custom.bib +70 -0
  1478. package/skills/research/research-paper-writing/templates/acl/formatting.md +326 -0
  1479. package/skills/research/research-paper-writing/templates/colm2025/README.md +3 -0
  1480. package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.bib +11 -0
  1481. package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.bst +1440 -0
  1482. package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.pdf +0 -0
  1483. package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.sty +218 -0
  1484. package/skills/research/research-paper-writing/templates/colm2025/colm2025_conference.tex +305 -0
  1485. package/skills/research/research-paper-writing/templates/colm2025/fancyhdr.sty +485 -0
  1486. package/skills/research/research-paper-writing/templates/colm2025/math_commands.tex +508 -0
  1487. package/skills/research/research-paper-writing/templates/colm2025/natbib.sty +1246 -0
  1488. package/skills/research/research-paper-writing/templates/iclr2026/fancyhdr.sty +485 -0
  1489. package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.bib +24 -0
  1490. package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.bst +1440 -0
  1491. package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.pdf +0 -0
  1492. package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.sty +246 -0
  1493. package/skills/research/research-paper-writing/templates/iclr2026/iclr2026_conference.tex +414 -0
  1494. package/skills/research/research-paper-writing/templates/iclr2026/math_commands.tex +508 -0
  1495. package/skills/research/research-paper-writing/templates/iclr2026/natbib.sty +1246 -0
  1496. package/skills/research/research-paper-writing/templates/icml2026/algorithm.sty +79 -0
  1497. package/skills/research/research-paper-writing/templates/icml2026/algorithmic.sty +201 -0
  1498. package/skills/research/research-paper-writing/templates/icml2026/example_paper.bib +75 -0
  1499. package/skills/research/research-paper-writing/templates/icml2026/example_paper.pdf +0 -0
  1500. package/skills/research/research-paper-writing/templates/icml2026/example_paper.tex +662 -0
  1501. package/skills/research/research-paper-writing/templates/icml2026/fancyhdr.sty +864 -0
  1502. package/skills/research/research-paper-writing/templates/icml2026/icml2026.bst +1443 -0
  1503. package/skills/research/research-paper-writing/templates/icml2026/icml2026.sty +767 -0
  1504. package/skills/research/research-paper-writing/templates/icml2026/icml_numpapers.pdf +0 -0
  1505. package/skills/research/research-paper-writing/templates/neurips2025/Makefile +36 -0
  1506. package/skills/research/research-paper-writing/templates/neurips2025/extra_pkgs.tex +53 -0
  1507. package/skills/research/research-paper-writing/templates/neurips2025/main.tex +38 -0
  1508. package/skills/research/research-paper-writing/templates/neurips2025/neurips.sty +382 -0
  1509. package/skills/smart-home/DESCRIPTION.md +3 -0
  1510. package/skills/smart-home/openhue/SKILL.md +109 -0
  1511. package/skills/social-media/DESCRIPTION.md +3 -0
  1512. package/skills/social-media/xurl/SKILL.md +414 -0
  1513. package/skills/software-development/debugging-hermes-tui-commands/SKILL.md +152 -0
  1514. package/skills/software-development/hermes-agent-skill-authoring/SKILL.md +165 -0
  1515. package/skills/software-development/node-inspect-debugger/SKILL.md +319 -0
  1516. package/skills/software-development/plan/SKILL.md +58 -0
  1517. package/skills/software-development/python-debugpy/SKILL.md +375 -0
  1518. package/skills/software-development/requesting-code-review/SKILL.md +280 -0
  1519. package/skills/software-development/spike/SKILL.md +197 -0
  1520. package/skills/software-development/subagent-driven-development/SKILL.md +352 -0
  1521. package/skills/software-development/subagent-driven-development/references/context-budget-discipline.md +53 -0
  1522. package/skills/software-development/subagent-driven-development/references/gates-taxonomy.md +93 -0
  1523. package/skills/software-development/systematic-debugging/SKILL.md +367 -0
  1524. package/skills/software-development/test-driven-development/SKILL.md +343 -0
  1525. package/skills/software-development/writing-plans/SKILL.md +297 -0
  1526. package/skills/yuanbao/SKILL.md +108 -0
  1527. package/tools/__init__.py +25 -0
  1528. package/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  1529. package/tools/__pycache__/approval.cpython-312.pyc +0 -0
  1530. package/tools/__pycache__/binary_extensions.cpython-312.pyc +0 -0
  1531. package/tools/__pycache__/browser_camofox.cpython-312.pyc +0 -0
  1532. package/tools/__pycache__/browser_camofox_state.cpython-312.pyc +0 -0
  1533. package/tools/__pycache__/browser_cdp_tool.cpython-312.pyc +0 -0
  1534. package/tools/__pycache__/browser_dialog_tool.cpython-312.pyc +0 -0
  1535. package/tools/__pycache__/browser_supervisor.cpython-312.pyc +0 -0
  1536. package/tools/__pycache__/browser_tool.cpython-312.pyc +0 -0
  1537. package/tools/__pycache__/budget_config.cpython-312.pyc +0 -0
  1538. package/tools/__pycache__/checkpoint_manager.cpython-312.pyc +0 -0
  1539. package/tools/__pycache__/clarify_gateway.cpython-312.pyc +0 -0
  1540. package/tools/__pycache__/clarify_tool.cpython-312.pyc +0 -0
  1541. package/tools/__pycache__/code_execution_tool.cpython-312.pyc +0 -0
  1542. package/tools/__pycache__/computer_use_tool.cpython-312.pyc +0 -0
  1543. package/tools/__pycache__/cronjob_tools.cpython-312.pyc +0 -0
  1544. package/tools/__pycache__/debug_helpers.cpython-312.pyc +0 -0
  1545. package/tools/__pycache__/delegate_tool.cpython-312.pyc +0 -0
  1546. package/tools/__pycache__/discord_tool.cpython-312.pyc +0 -0
  1547. package/tools/__pycache__/feishu_doc_tool.cpython-312.pyc +0 -0
  1548. package/tools/__pycache__/feishu_drive_tool.cpython-312.pyc +0 -0
  1549. package/tools/__pycache__/file_operations.cpython-312.pyc +0 -0
  1550. package/tools/__pycache__/file_state.cpython-312.pyc +0 -0
  1551. package/tools/__pycache__/file_tools.cpython-312.pyc +0 -0
  1552. package/tools/__pycache__/homeassistant_tool.cpython-312.pyc +0 -0
  1553. package/tools/__pycache__/image_generation_tool.cpython-312.pyc +0 -0
  1554. package/tools/__pycache__/interrupt.cpython-312.pyc +0 -0
  1555. package/tools/__pycache__/kanban_tools.cpython-312.pyc +0 -0
  1556. package/tools/__pycache__/lazy_deps.cpython-312.pyc +0 -0
  1557. package/tools/__pycache__/managed_tool_gateway.cpython-312.pyc +0 -0
  1558. package/tools/__pycache__/mcp_tool.cpython-312.pyc +0 -0
  1559. package/tools/__pycache__/memory_tool.cpython-312.pyc +0 -0
  1560. package/tools/__pycache__/mixture_of_agents_tool.cpython-312.pyc +0 -0
  1561. package/tools/__pycache__/openrouter_client.cpython-312.pyc +0 -0
  1562. package/tools/__pycache__/process_registry.cpython-312.pyc +0 -0
  1563. package/tools/__pycache__/registry.cpython-312.pyc +0 -0
  1564. package/tools/__pycache__/schema_sanitizer.cpython-312.pyc +0 -0
  1565. package/tools/__pycache__/send_message_tool.cpython-312.pyc +0 -0
  1566. package/tools/__pycache__/session_search_tool.cpython-312.pyc +0 -0
  1567. package/tools/__pycache__/skill_manager_tool.cpython-312.pyc +0 -0
  1568. package/tools/__pycache__/skill_provenance.cpython-312.pyc +0 -0
  1569. package/tools/__pycache__/skill_usage.cpython-312.pyc +0 -0
  1570. package/tools/__pycache__/skills_guard.cpython-312.pyc +0 -0
  1571. package/tools/__pycache__/skills_sync.cpython-312.pyc +0 -0
  1572. package/tools/__pycache__/skills_tool.cpython-312.pyc +0 -0
  1573. package/tools/__pycache__/slash_confirm.cpython-312.pyc +0 -0
  1574. package/tools/__pycache__/terminal_tool.cpython-312.pyc +0 -0
  1575. package/tools/__pycache__/tirith_security.cpython-312.pyc +0 -0
  1576. package/tools/__pycache__/todo_tool.cpython-312.pyc +0 -0
  1577. package/tools/__pycache__/tool_backend_helpers.cpython-312.pyc +0 -0
  1578. package/tools/__pycache__/tool_result_storage.cpython-312.pyc +0 -0
  1579. package/tools/__pycache__/tts_tool.cpython-312.pyc +0 -0
  1580. package/tools/__pycache__/url_safety.cpython-312.pyc +0 -0
  1581. package/tools/__pycache__/video_generation_tool.cpython-312.pyc +0 -0
  1582. package/tools/__pycache__/vision_tools.cpython-312.pyc +0 -0
  1583. package/tools/__pycache__/voice_mode.cpython-312.pyc +0 -0
  1584. package/tools/__pycache__/web_tools.cpython-312.pyc +0 -0
  1585. package/tools/__pycache__/website_policy.cpython-312.pyc +0 -0
  1586. package/tools/__pycache__/x_search_tool.cpython-312.pyc +0 -0
  1587. package/tools/__pycache__/xai_http.cpython-312.pyc +0 -0
  1588. package/tools/__pycache__/yuanbao_tools.cpython-312.pyc +0 -0
  1589. package/tools/ansi_strip.py +44 -0
  1590. package/tools/approval.py +1392 -0
  1591. package/tools/binary_extensions.py +42 -0
  1592. package/tools/browser_camofox.py +700 -0
  1593. package/tools/browser_camofox_state.py +48 -0
  1594. package/tools/browser_cdp_tool.py +569 -0
  1595. package/tools/browser_dialog_tool.py +148 -0
  1596. package/tools/browser_providers/__init__.py +10 -0
  1597. package/tools/browser_providers/__pycache__/__init__.cpython-312.pyc +0 -0
  1598. package/tools/browser_providers/__pycache__/base.cpython-312.pyc +0 -0
  1599. package/tools/browser_providers/__pycache__/browser_use.cpython-312.pyc +0 -0
  1600. package/tools/browser_providers/__pycache__/browserbase.cpython-312.pyc +0 -0
  1601. package/tools/browser_providers/__pycache__/firecrawl.cpython-312.pyc +0 -0
  1602. package/tools/browser_providers/base.py +59 -0
  1603. package/tools/browser_providers/browser_use.py +225 -0
  1604. package/tools/browser_providers/browserbase.py +222 -0
  1605. package/tools/browser_providers/firecrawl.py +112 -0
  1606. package/tools/browser_supervisor.py +1457 -0
  1607. package/tools/browser_tool.py +3676 -0
  1608. package/tools/budget_config.py +51 -0
  1609. package/tools/checkpoint_manager.py +1639 -0
  1610. package/tools/clarify_gateway.py +278 -0
  1611. package/tools/clarify_tool.py +141 -0
  1612. package/tools/code_execution_tool.py +1782 -0
  1613. package/tools/computer_use/__init__.py +43 -0
  1614. package/tools/computer_use/__pycache__/__init__.cpython-312.pyc +0 -0
  1615. package/tools/computer_use/__pycache__/backend.cpython-312.pyc +0 -0
  1616. package/tools/computer_use/__pycache__/schema.cpython-312.pyc +0 -0
  1617. package/tools/computer_use/__pycache__/tool.cpython-312.pyc +0 -0
  1618. package/tools/computer_use/backend.py +150 -0
  1619. package/tools/computer_use/cua_backend.py +682 -0
  1620. package/tools/computer_use/schema.py +191 -0
  1621. package/tools/computer_use/tool.py +521 -0
  1622. package/tools/computer_use_tool.py +39 -0
  1623. package/tools/credential_files.py +437 -0
  1624. package/tools/cronjob_tools.py +719 -0
  1625. package/tools/debug_helpers.py +106 -0
  1626. package/tools/delegate_tool.py +2797 -0
  1627. package/tools/discord_tool.py +959 -0
  1628. package/tools/env_passthrough.py +145 -0
  1629. package/tools/environments/__init__.py +14 -0
  1630. package/tools/environments/__pycache__/__init__.cpython-312.pyc +0 -0
  1631. package/tools/environments/__pycache__/base.cpython-312.pyc +0 -0
  1632. package/tools/environments/__pycache__/docker.cpython-312.pyc +0 -0
  1633. package/tools/environments/__pycache__/file_sync.cpython-312.pyc +0 -0
  1634. package/tools/environments/__pycache__/local.cpython-312.pyc +0 -0
  1635. package/tools/environments/__pycache__/managed_modal.cpython-312.pyc +0 -0
  1636. package/tools/environments/__pycache__/modal.cpython-312.pyc +0 -0
  1637. package/tools/environments/__pycache__/modal_utils.cpython-312.pyc +0 -0
  1638. package/tools/environments/__pycache__/singularity.cpython-312.pyc +0 -0
  1639. package/tools/environments/__pycache__/ssh.cpython-312.pyc +0 -0
  1640. package/tools/environments/base.py +844 -0
  1641. package/tools/environments/daytona.py +270 -0
  1642. package/tools/environments/docker.py +656 -0
  1643. package/tools/environments/file_sync.py +400 -0
  1644. package/tools/environments/local.py +658 -0
  1645. package/tools/environments/managed_modal.py +282 -0
  1646. package/tools/environments/modal.py +479 -0
  1647. package/tools/environments/modal_utils.py +199 -0
  1648. package/tools/environments/singularity.py +263 -0
  1649. package/tools/environments/ssh.py +295 -0
  1650. package/tools/environments/vercel_sandbox.py +655 -0
  1651. package/tools/feishu_doc_tool.py +138 -0
  1652. package/tools/feishu_drive_tool.py +431 -0
  1653. package/tools/file_operations.py +1825 -0
  1654. package/tools/file_state.py +332 -0
  1655. package/tools/file_tools.py +1172 -0
  1656. package/tools/fuzzy_match.py +703 -0
  1657. package/tools/homeassistant_tool.py +513 -0
  1658. package/tools/image_generation_tool.py +1098 -0
  1659. package/tools/interrupt.py +98 -0
  1660. package/tools/kanban_tools.py +1139 -0
  1661. package/tools/lazy_deps.py +608 -0
  1662. package/tools/managed_tool_gateway.py +168 -0
  1663. package/tools/mcp_oauth.py +633 -0
  1664. package/tools/mcp_oauth_manager.py +607 -0
  1665. package/tools/mcp_tool.py +3483 -0
  1666. package/tools/memory_tool.py +584 -0
  1667. package/tools/microsoft_graph_auth.py +245 -0
  1668. package/tools/microsoft_graph_client.py +408 -0
  1669. package/tools/mixture_of_agents_tool.py +542 -0
  1670. package/tools/neutts_samples/jo.txt +1 -0
  1671. package/tools/neutts_samples/jo.wav +0 -0
  1672. package/tools/neutts_synth.py +104 -0
  1673. package/tools/openrouter_client.py +33 -0
  1674. package/tools/osv_check.py +155 -0
  1675. package/tools/patch_parser.py +592 -0
  1676. package/tools/path_security.py +43 -0
  1677. package/tools/process_registry.py +1534 -0
  1678. package/tools/registry.py +589 -0
  1679. package/tools/schema_sanitizer.py +370 -0
  1680. package/tools/send_message_tool.py +1900 -0
  1681. package/tools/session_search_tool.py +613 -0
  1682. package/tools/skill_manager_tool.py +932 -0
  1683. package/tools/skill_provenance.py +78 -0
  1684. package/tools/skill_usage.py +610 -0
  1685. package/tools/skills_guard.py +932 -0
  1686. package/tools/skills_hub.py +3263 -0
  1687. package/tools/skills_sync.py +432 -0
  1688. package/tools/skills_tool.py +1569 -0
  1689. package/tools/slash_confirm.py +167 -0
  1690. package/tools/terminal_tool.py +2376 -0
  1691. package/tools/tirith_security.py +775 -0
  1692. package/tools/todo_tool.py +277 -0
  1693. package/tools/tool_backend_helpers.py +144 -0
  1694. package/tools/tool_output_limits.py +92 -0
  1695. package/tools/tool_result_storage.py +232 -0
  1696. package/tools/transcription_tools.py +936 -0
  1697. package/tools/tts_tool.py +2285 -0
  1698. package/tools/url_safety.py +330 -0
  1699. package/tools/video_generation_tool.py +561 -0
  1700. package/tools/vision_tools.py +1422 -0
  1701. package/tools/voice_mode.py +1019 -0
  1702. package/tools/web_tools.py +1551 -0
  1703. package/tools/website_policy.py +283 -0
  1704. package/tools/x_search_tool.py +424 -0
  1705. package/tools/xai_http.py +83 -0
  1706. package/tools/yuanbao_tools.py +736 -0
  1707. package/toolset_distributions.py +364 -0
  1708. package/toolsets.py +866 -0
  1709. package/trajectory_compressor.py +1509 -0
  1710. package/tui_gateway/__init__.py +0 -0
  1711. package/tui_gateway/entry.py +251 -0
  1712. package/tui_gateway/event_publisher.py +126 -0
  1713. package/tui_gateway/render.py +49 -0
  1714. package/tui_gateway/server.py +6623 -0
  1715. package/tui_gateway/slash_worker.py +76 -0
  1716. package/tui_gateway/transport.py +219 -0
  1717. package/tui_gateway/ws.py +178 -0
  1718. package/utils.py +361 -0
@@ -0,0 +1,1473 @@
1
+ """
2
+ DingTalk platform adapter using Stream Mode.
3
+
4
+ Uses dingtalk-stream SDK (>=0.20) for real-time message reception without webhooks.
5
+ Responses are sent via DingTalk's session webhook (markdown format).
6
+ Supports: text, images, audio, video, rich text, files, and group @mentions.
7
+
8
+ Requires:
9
+ pip install "dingtalk-stream>=0.20" httpx
10
+ DINGTALK_CLIENT_ID and DINGTALK_CLIENT_SECRET env vars
11
+
12
+ Configuration in config.yaml:
13
+ platforms:
14
+ dingtalk:
15
+ enabled: true
16
+ # Optional group-chat gating (mirrors Slack/Telegram/Discord):
17
+ require_mention: true # or DINGTALK_REQUIRE_MENTION env var
18
+ # free_response_chats: # conversations that skip require_mention
19
+ # - cidABC==
20
+ # mention_patterns: # regex wake-words (e.g. Chinese bot names)
21
+ # - "^小马"
22
+ # allowed_users: # staff_id or sender_id list; "*" = any
23
+ # - "manager1234"
24
+ extra:
25
+ client_id: "your-app-key" # or DINGTALK_CLIENT_ID env var
26
+ client_secret: "your-secret" # or DINGTALK_CLIENT_SECRET env var
27
+ """
28
+
29
+ import asyncio
30
+ import json
31
+ import logging
32
+ import os
33
+ import re
34
+ import traceback
35
+ import uuid
36
+ from datetime import datetime, timezone
37
+ from typing import Any, Dict, List, Optional, Set
38
+
39
+ try:
40
+ import dingtalk_stream
41
+ from dingtalk_stream import ChatbotMessage
42
+ from dingtalk_stream.frames import CallbackMessage, AckMessage
43
+
44
+ DINGTALK_STREAM_AVAILABLE = True
45
+ except ImportError:
46
+ DINGTALK_STREAM_AVAILABLE = False
47
+ dingtalk_stream = None # type: ignore[assignment]
48
+ ChatbotMessage = None # type: ignore[assignment]
49
+ CallbackMessage = None # type: ignore[assignment]
50
+ AckMessage = type(
51
+ "AckMessage",
52
+ (),
53
+ {
54
+ "STATUS_OK": 200,
55
+ "STATUS_SYSTEM_EXCEPTION": 500,
56
+ },
57
+ ) # type: ignore[assignment]
58
+
59
+ try:
60
+ import httpx
61
+
62
+ HTTPX_AVAILABLE = True
63
+ except ImportError:
64
+ HTTPX_AVAILABLE = False
65
+ httpx = None # type: ignore[assignment]
66
+
67
+ # Card SDK for AI Cards (following QwenPaw pattern)
68
+ try:
69
+ from alibabacloud_dingtalk.card_1_0 import (
70
+ client as dingtalk_card_client,
71
+ models as dingtalk_card_models,
72
+ )
73
+ from alibabacloud_dingtalk.robot_1_0 import (
74
+ client as dingtalk_robot_client,
75
+ models as dingtalk_robot_models,
76
+ )
77
+ from alibabacloud_tea_openapi import models as open_api_models
78
+ from alibabacloud_tea_util import models as tea_util_models
79
+
80
+ CARD_SDK_AVAILABLE = True
81
+ except ImportError:
82
+ CARD_SDK_AVAILABLE = False
83
+ dingtalk_card_client = None
84
+ dingtalk_card_models = None
85
+ dingtalk_robot_client = None
86
+ dingtalk_robot_models = None
87
+ open_api_models = None
88
+ tea_util_models = None
89
+
90
+ from gateway.config import Platform, PlatformConfig
91
+ from gateway.platforms.helpers import MessageDeduplicator
92
+ from gateway.platforms.base import (
93
+ BasePlatformAdapter,
94
+ MessageEvent,
95
+ MessageType,
96
+ SendResult,
97
+ )
98
+
99
+ logger = logging.getLogger(__name__)
100
+
101
+ MAX_MESSAGE_LENGTH = 20000
102
+ RECONNECT_BACKOFF = [2, 5, 10, 30, 60]
103
+ _SESSION_WEBHOOKS_MAX = 500
104
+ _DINGTALK_WEBHOOK_RE = re.compile(r'^https://(?:api|oapi)\.dingtalk\.com/')
105
+
106
+ # DingTalk message type → runtime content type
107
+ DINGTALK_TYPE_MAPPING = {
108
+ "picture": "image",
109
+ "voice": "audio",
110
+ }
111
+
112
+
113
+ def check_dingtalk_requirements() -> bool:
114
+ """Check if DingTalk dependencies are available and configured.
115
+
116
+ Lazy-installs dingtalk-stream via ``tools.lazy_deps.ensure("platform.dingtalk")``
117
+ on first call if not present.
118
+ """
119
+ global DINGTALK_STREAM_AVAILABLE, dingtalk_stream, ChatbotMessage, CallbackMessage, AckMessage
120
+ global HTTPX_AVAILABLE, httpx
121
+ if not DINGTALK_STREAM_AVAILABLE or not HTTPX_AVAILABLE:
122
+ try:
123
+ from tools.lazy_deps import ensure as _lazy_ensure
124
+ _lazy_ensure("platform.dingtalk", prompt=False)
125
+ except Exception:
126
+ return False
127
+ try:
128
+ import dingtalk_stream as _ds
129
+ from dingtalk_stream import ChatbotMessage as _CM
130
+ from dingtalk_stream.frames import CallbackMessage as _CBM, AckMessage as _AM
131
+ import httpx as _httpx
132
+ except ImportError:
133
+ return False
134
+ dingtalk_stream = _ds
135
+ ChatbotMessage = _CM
136
+ CallbackMessage = _CBM
137
+ AckMessage = _AM
138
+ httpx = _httpx
139
+ DINGTALK_STREAM_AVAILABLE = True
140
+ HTTPX_AVAILABLE = True
141
+ if not os.getenv("DINGTALK_CLIENT_ID") or not os.getenv("DINGTALK_CLIENT_SECRET"):
142
+ return False
143
+ return True
144
+
145
+
146
+ class DingTalkAdapter(BasePlatformAdapter):
147
+ """DingTalk chatbot adapter using Stream Mode.
148
+
149
+ The dingtalk-stream SDK maintains a long-lived WebSocket connection.
150
+ Incoming messages arrive via a ChatbotHandler callback. Replies are
151
+ sent via the incoming message's session_webhook URL using httpx.
152
+
153
+ Features:
154
+ - Text messages (plain + rich text)
155
+ - Images, audio, video, files (via download codes)
156
+ - Group chat @mention detection
157
+ - Session webhook caching with expiry tracking
158
+ - Markdown formatted replies
159
+ """
160
+
161
+ MAX_MESSAGE_LENGTH = MAX_MESSAGE_LENGTH
162
+
163
+ @property
164
+ def SUPPORTS_MESSAGE_EDITING(self) -> bool: # noqa: N802
165
+ """Edits only meaningful when AI Cards are configured.
166
+
167
+ The gateway gates streaming cursor + edit behaviour on this flag,
168
+ so we must reflect the actual adapter capability at runtime.
169
+ """
170
+ return bool(self._card_template_id and self._card_sdk)
171
+
172
+ @property
173
+ def REQUIRES_EDIT_FINALIZE(self) -> bool: # noqa: N802
174
+ """AI Card lifecycle requires an explicit ``finalize=True`` edit
175
+ to close the streaming indicator, even when the final content is
176
+ identical to the last streamed update. Enabled only when cards
177
+ are configured — webhook-only DingTalk doesn't need it.
178
+ """
179
+ return bool(self._card_template_id and self._card_sdk)
180
+
181
+ def __init__(self, config: PlatformConfig):
182
+ super().__init__(config, Platform.DINGTALK)
183
+
184
+ extra = config.extra or {}
185
+ self._client_id: str = extra.get("client_id") or os.getenv(
186
+ "DINGTALK_CLIENT_ID", ""
187
+ )
188
+ self._client_secret: str = extra.get("client_secret") or os.getenv(
189
+ "DINGTALK_CLIENT_SECRET", ""
190
+ )
191
+
192
+ # Group-chat gating (mirrors Slack/Telegram/Discord/WhatsApp conventions).
193
+ # Mention state is the structured ``is_in_at_list`` attribute from the
194
+ # dingtalk-stream SDK (set from the callback's ``isInAtList`` flag),
195
+ # not text parsing.
196
+ self._mention_patterns: List[re.Pattern] = self._compile_mention_patterns()
197
+ self._allowed_users: Set[str] = self._load_allowed_users()
198
+
199
+ self._stream_client: Any = None
200
+ self._stream_task: Optional[asyncio.Task] = None
201
+ self._http_client: Optional["httpx.AsyncClient"] = None
202
+ self._card_sdk: Optional[Any] = None
203
+ self._robot_sdk: Optional[Any] = None
204
+ self._robot_code: str = extra.get("robot_code") or self._client_id
205
+
206
+ # Message deduplication
207
+ self._dedup = MessageDeduplicator(max_size=1000)
208
+ # Map chat_id -> (session_webhook, expired_time_ms) for reply routing
209
+ self._session_webhooks: Dict[str, tuple[str, int]] = {}
210
+ # Map chat_id -> last inbound ChatbotMessage. Keyed by chat_id instead
211
+ # of a single class attribute to avoid cross-message clobbering when
212
+ # multiple conversations run concurrently.
213
+ self._message_contexts: Dict[str, Any] = {}
214
+ self._card_template_id: Optional[str] = extra.get("card_template_id")
215
+
216
+ # Chats for which we've already fired the Done reaction — prevents
217
+ # double-firing across segment boundaries or parallel flows
218
+ # (tool-progress + stream-consumer both finalizing their cards).
219
+ # Reset each inbound message.
220
+ self._done_emoji_fired: Set[str] = set()
221
+ # Cards in streaming state per chat: chat_id -> { out_track_id -> last_content }.
222
+ # Every `send()` creates+finalizes a card (closed state). A subsequent
223
+ # `edit_message(finalize=False)` re-opens the card (DingTalk's API
224
+ # allows streaming_update on a finalized card — it flips back to
225
+ # streaming). We track those reopened cards so the next `send()` can
226
+ # auto-close them as siblings — otherwise tool-progress cards get
227
+ # stuck in streaming state forever.
228
+ self._streaming_cards: Dict[str, Dict[str, str]] = {}
229
+ # Track fire-and-forget emoji/reaction coroutines so Python's GC
230
+ # doesn't drop them mid-flight, and we can cancel them on disconnect.
231
+ self._bg_tasks: Set[asyncio.Task] = set()
232
+
233
+ # -- Connection lifecycle -----------------------------------------------
234
+
235
+ async def connect(self) -> bool:
236
+ """Connect to DingTalk via Stream Mode."""
237
+ if not DINGTALK_STREAM_AVAILABLE:
238
+ logger.warning(
239
+ "[%s] dingtalk-stream not installed. Run: pip install 'dingtalk-stream>=0.20'",
240
+ self.name,
241
+ )
242
+ return False
243
+ if not HTTPX_AVAILABLE:
244
+ logger.warning(
245
+ "[%s] httpx not installed. Run: pip install httpx", self.name
246
+ )
247
+ return False
248
+ if not self._client_id or not self._client_secret:
249
+ logger.warning(
250
+ "[%s] DINGTALK_CLIENT_ID and DINGTALK_CLIENT_SECRET required", self.name
251
+ )
252
+ return False
253
+
254
+ try:
255
+ # Tighter keepalive so idle CLOSE_WAIT drains promptly (#18451).
256
+ from gateway.platforms._http_client_limits import platform_httpx_limits
257
+ self._http_client = httpx.AsyncClient(
258
+ timeout=30.0, limits=platform_httpx_limits(),
259
+ )
260
+
261
+ credential = dingtalk_stream.Credential(
262
+ self._client_id, self._client_secret
263
+ )
264
+ self._stream_client = dingtalk_stream.DingTalkStreamClient(credential)
265
+
266
+ # Initialize card SDK if available and configured
267
+ if CARD_SDK_AVAILABLE and self._card_template_id:
268
+ sdk_config = open_api_models.Config()
269
+ sdk_config.protocol = "https"
270
+ sdk_config.region_id = "central"
271
+ self._card_sdk = dingtalk_card_client.Client(sdk_config)
272
+ self._robot_sdk = dingtalk_robot_client.Client(sdk_config)
273
+ logger.info(
274
+ "[%s] Card SDK initialized with template: %s",
275
+ self.name,
276
+ self._card_template_id,
277
+ )
278
+ elif CARD_SDK_AVAILABLE:
279
+ # Initialize robot SDK even without card template (for media download)
280
+ sdk_config = open_api_models.Config()
281
+ sdk_config.protocol = "https"
282
+ sdk_config.region_id = "central"
283
+ self._robot_sdk = dingtalk_robot_client.Client(sdk_config)
284
+ logger.info("[%s] Robot SDK initialized (media download)", self.name)
285
+
286
+ # Capture the current event loop for cross-thread dispatch
287
+ loop = asyncio.get_running_loop()
288
+ handler = _IncomingHandler(self, loop)
289
+ self._stream_client.register_callback_handler(
290
+ dingtalk_stream.ChatbotMessage.TOPIC, handler
291
+ )
292
+
293
+ self._stream_task = asyncio.create_task(self._run_stream())
294
+ self._mark_connected()
295
+ logger.info("[%s] Connected via Stream Mode", self.name)
296
+ return True
297
+ except Exception as e:
298
+ logger.error("[%s] Failed to connect: %s", self.name, e)
299
+ return False
300
+
301
+ async def _run_stream(self) -> None:
302
+ """Run the async stream client with auto-reconnection."""
303
+ backoff_idx = 0
304
+ while self._running:
305
+ try:
306
+ logger.debug("[%s] Starting stream client...", self.name)
307
+ await self._stream_client.start()
308
+ except asyncio.CancelledError:
309
+ return
310
+ except Exception as e:
311
+ if not self._running:
312
+ return
313
+ logger.warning("[%s] Stream client error: %s", self.name, e)
314
+
315
+ if not self._running:
316
+ return
317
+
318
+ delay = RECONNECT_BACKOFF[min(backoff_idx, len(RECONNECT_BACKOFF) - 1)]
319
+ logger.info("[%s] Reconnecting in %ds...", self.name, delay)
320
+ await asyncio.sleep(delay)
321
+ backoff_idx += 1
322
+
323
+ async def disconnect(self) -> None:
324
+ """Disconnect from DingTalk."""
325
+ self._running = False
326
+ self._mark_disconnected()
327
+
328
+ # Close the active websocket first so the stream task sees the
329
+ # disconnection and exits cleanly, rather than getting stuck
330
+ # awaiting frames that will never arrive.
331
+ websocket = getattr(self._stream_client, "websocket", None) if self._stream_client else None
332
+ if websocket is not None:
333
+ try:
334
+ await websocket.close()
335
+ except Exception as e:
336
+ logger.debug("[%s] websocket close during disconnect failed: %s", self.name, e)
337
+
338
+ if self._stream_task:
339
+ # Try graceful close first if SDK supports it. The SDK's close()
340
+ # is sync and may block on network I/O, so offload to a thread.
341
+ if hasattr(self._stream_client, "close"):
342
+ try:
343
+ await asyncio.to_thread(self._stream_client.close)
344
+ except Exception:
345
+ pass
346
+
347
+ self._stream_task.cancel()
348
+ try:
349
+ await asyncio.wait_for(self._stream_task, timeout=5.0)
350
+ except (asyncio.CancelledError, asyncio.TimeoutError):
351
+ logger.debug("[%s] stream task did not exit cleanly during disconnect", self.name)
352
+ self._stream_task = None
353
+
354
+ # Cancel any in-flight background tasks (emoji reactions, etc.)
355
+ if self._bg_tasks:
356
+ for task in list(self._bg_tasks):
357
+ task.cancel()
358
+ await asyncio.gather(*self._bg_tasks, return_exceptions=True)
359
+ self._bg_tasks.clear()
360
+
361
+ if self._http_client:
362
+ await self._http_client.aclose()
363
+ self._http_client = None
364
+
365
+ self._stream_client = None
366
+ self._session_webhooks.clear()
367
+ self._message_contexts.clear()
368
+ self._streaming_cards.clear()
369
+ self._done_emoji_fired.clear()
370
+ self._dedup.clear()
371
+ logger.info("[%s] Disconnected", self.name)
372
+
373
+ # -- Group gating --------------------------------------------------------
374
+
375
+ def _dingtalk_require_mention(self) -> bool:
376
+ """Return whether group chats should require an explicit bot trigger."""
377
+ configured = self.config.extra.get("require_mention")
378
+ if configured is not None:
379
+ if isinstance(configured, str):
380
+ return configured.lower() in {"true", "1", "yes", "on"}
381
+ return bool(configured)
382
+ return os.getenv("DINGTALK_REQUIRE_MENTION", "false").lower() in {"true", "1", "yes", "on"}
383
+
384
+ def _dingtalk_free_response_chats(self) -> Set[str]:
385
+ raw = self.config.extra.get("free_response_chats")
386
+ if raw is None:
387
+ raw = os.getenv("DINGTALK_FREE_RESPONSE_CHATS", "")
388
+ if isinstance(raw, list):
389
+ return {str(part).strip() for part in raw if str(part).strip()}
390
+ return {part.strip() for part in str(raw).split(",") if part.strip()}
391
+
392
+ def _dingtalk_allowed_chats(self) -> Set[str]:
393
+ """Return the whitelist of group chat IDs the bot will respond in.
394
+
395
+ When non-empty, group messages from chats NOT in this set are silently
396
+ ignored — even if the bot is @mentioned. DMs are never filtered.
397
+ Empty set means no restriction (fully backward compatible).
398
+ """
399
+ raw = self.config.extra.get("allowed_chats") if self.config.extra else None
400
+ if raw is None:
401
+ raw = os.getenv("DINGTALK_ALLOWED_CHATS", "")
402
+ if isinstance(raw, list):
403
+ return {str(part).strip() for part in raw if str(part).strip()}
404
+ return {part.strip() for part in str(raw).split(",") if part.strip()}
405
+
406
+ def _compile_mention_patterns(self) -> List[re.Pattern]:
407
+ """Compile optional regex wake-word patterns for group triggers."""
408
+ patterns = self.config.extra.get("mention_patterns") if self.config.extra else None
409
+ if patterns is None:
410
+ raw = os.getenv("DINGTALK_MENTION_PATTERNS", "").strip()
411
+ if raw:
412
+ try:
413
+ loaded = json.loads(raw)
414
+ except Exception:
415
+ loaded = [part.strip() for part in raw.splitlines() if part.strip()]
416
+ if not loaded:
417
+ loaded = [part.strip() for part in raw.split(",") if part.strip()]
418
+ patterns = loaded
419
+
420
+ if patterns is None:
421
+ return []
422
+ if isinstance(patterns, str):
423
+ patterns = [patterns]
424
+ if not isinstance(patterns, list):
425
+ logger.warning(
426
+ "[%s] dingtalk mention_patterns must be a list or string; got %s",
427
+ self.name,
428
+ type(patterns).__name__,
429
+ )
430
+ return []
431
+
432
+ compiled: List[re.Pattern] = []
433
+ for pattern in patterns:
434
+ if not isinstance(pattern, str) or not pattern.strip():
435
+ continue
436
+ try:
437
+ compiled.append(re.compile(pattern, re.IGNORECASE))
438
+ except re.error as exc:
439
+ logger.warning("[%s] Invalid DingTalk mention pattern %r: %s", self.name, pattern, exc)
440
+ if compiled:
441
+ logger.info("[%s] Loaded %d DingTalk mention pattern(s)", self.name, len(compiled))
442
+ return compiled
443
+
444
+ def _load_allowed_users(self) -> Set[str]:
445
+ """Load allowed-users list from config.extra or env var.
446
+
447
+ IDs are matched case-insensitively against the sender's ``staff_id`` and
448
+ ``sender_id``. A wildcard ``*`` disables the check.
449
+ """
450
+ raw = self.config.extra.get("allowed_users") if self.config.extra else None
451
+ if raw is None:
452
+ raw = os.getenv("DINGTALK_ALLOWED_USERS", "")
453
+ if isinstance(raw, list):
454
+ items = [str(part).strip() for part in raw if str(part).strip()]
455
+ else:
456
+ items = [part.strip() for part in str(raw).split(",") if part.strip()]
457
+ return {item.lower() for item in items}
458
+
459
+ def _is_user_allowed(self, sender_id: str, sender_staff_id: str) -> bool:
460
+ if not self._allowed_users or "*" in self._allowed_users:
461
+ return True
462
+ candidates = {(sender_id or "").lower(), (sender_staff_id or "").lower()}
463
+ candidates.discard("")
464
+ return bool(candidates & self._allowed_users)
465
+
466
+ def _message_mentions_bot(self, message: "ChatbotMessage") -> bool:
467
+ """True if the bot was @-mentioned in a group message.
468
+
469
+ dingtalk-stream sets ``is_in_at_list`` on the incoming ChatbotMessage
470
+ when the bot is addressed via @-mention.
471
+ """
472
+ return bool(getattr(message, "is_in_at_list", False))
473
+
474
+ def _message_matches_mention_patterns(self, text: str) -> bool:
475
+ if not text or not self._mention_patterns:
476
+ return False
477
+ return any(pattern.search(text) for pattern in self._mention_patterns)
478
+
479
+ def _should_process_message(self, message: "ChatbotMessage", text: str, is_group: bool, chat_id: str) -> bool:
480
+ """Apply DingTalk group trigger rules.
481
+
482
+ DMs remain unrestricted (subject to ``allowed_users`` which is enforced
483
+ earlier). Group messages are accepted when:
484
+ - the chat passes the ``allowed_chats`` whitelist (when set)
485
+ - the chat is explicitly allowlisted in ``free_response_chats``
486
+ - ``require_mention`` is disabled
487
+ - the bot is @mentioned (``is_in_at_list``)
488
+ - the text matches a configured regex wake-word pattern
489
+
490
+ When ``allowed_chats`` is non-empty, it acts as a hard gate — messages
491
+ from any group chat not in the list are ignored regardless of the
492
+ other rules.
493
+ """
494
+ if not is_group:
495
+ return True
496
+ allowed = self._dingtalk_allowed_chats()
497
+ if allowed and chat_id and chat_id not in allowed:
498
+ return False
499
+ if chat_id and chat_id in self._dingtalk_free_response_chats():
500
+ return True
501
+ if not self._dingtalk_require_mention():
502
+ return True
503
+ if self._message_mentions_bot(message):
504
+ return True
505
+ return self._message_matches_mention_patterns(text)
506
+
507
+ def _spawn_bg(self, coro) -> None:
508
+ """Start a fire-and-forget coroutine and track it for cleanup."""
509
+ task = asyncio.create_task(coro)
510
+ self._bg_tasks.add(task)
511
+ task.add_done_callback(self._bg_tasks.discard)
512
+
513
+ # -- AI Card lifecycle helpers ------------------------------------------
514
+
515
+ async def _close_streaming_siblings(self, chat_id: str) -> None:
516
+ """Finalize any previously-open streaming cards for this chat.
517
+
518
+ Called at the start of every ``send()`` so lingering tool-progress
519
+ cards that were reopened by ``edit_message(finalize=False)`` get
520
+ cleanly closed before the next card is created. Without this,
521
+ tool-progress cards stay stuck in streaming state after the agent
522
+ moves on (there is no explicit "turn end" signal from the gateway).
523
+ """
524
+ cards = self._streaming_cards.pop(chat_id, None)
525
+ if not cards:
526
+ return
527
+ token = await self._get_access_token()
528
+ if not token:
529
+ return
530
+ for out_track_id, last_content in list(cards.items()):
531
+ try:
532
+ await self._stream_card_content(
533
+ out_track_id, token, last_content, finalize=True,
534
+ )
535
+ logger.debug(
536
+ "[%s] AI Card sibling closed: %s",
537
+ self.name, out_track_id,
538
+ )
539
+ except Exception as e:
540
+ logger.debug(
541
+ "[%s] Sibling close failed for %s: %s",
542
+ self.name, out_track_id, e,
543
+ )
544
+
545
+ def _fire_done_reaction(self, chat_id: str) -> None:
546
+ """Swap 🤔Thinking → 🥳Done on the original user message.
547
+
548
+ Idempotent per chat_id — safe to call from segment-break flushes
549
+ and final-done flushes without double-firing.
550
+ """
551
+ if chat_id in self._done_emoji_fired:
552
+ return
553
+ self._done_emoji_fired.add(chat_id)
554
+ msg = self._message_contexts.get(chat_id)
555
+ if not msg:
556
+ return
557
+ msg_id = getattr(msg, "message_id", "") or ""
558
+ conversation_id = getattr(msg, "conversation_id", "") or ""
559
+ if not (msg_id and conversation_id):
560
+ return
561
+
562
+ async def _swap() -> None:
563
+ await self._send_emotion(
564
+ msg_id, conversation_id, "🤔Thinking", recall=True,
565
+ )
566
+ await self._send_emotion(
567
+ msg_id, conversation_id, "🥳Done", recall=False,
568
+ )
569
+
570
+ self._spawn_bg(_swap())
571
+
572
+ # -- Inbound message processing -----------------------------------------
573
+
574
+ async def _on_message(
575
+ self,
576
+ message: "ChatbotMessage",
577
+ ) -> None:
578
+ """Process an incoming DingTalk chatbot message."""
579
+ msg_id = getattr(message, "message_id", None) or uuid.uuid4().hex
580
+ if self._dedup.is_duplicate(msg_id):
581
+ logger.debug("[%s] Duplicate message %s, skipping", self.name, msg_id)
582
+ return
583
+
584
+ # Chat context
585
+ conversation_id = getattr(message, "conversation_id", "") or ""
586
+ conversation_type = getattr(message, "conversation_type", "1")
587
+ is_group = str(conversation_type) == "2"
588
+ sender_id = getattr(message, "sender_id", "") or ""
589
+ sender_nick = getattr(message, "sender_nick", "") or sender_id
590
+ sender_staff_id = getattr(message, "sender_staff_id", "") or ""
591
+
592
+ chat_id = conversation_id or sender_id
593
+ chat_type = "group" if is_group else "dm"
594
+
595
+ # Allowed-users gate (applies to both DM and group)
596
+ if not self._is_user_allowed(sender_id, sender_staff_id):
597
+ logger.debug(
598
+ "[%s] Dropping message from non-allowlisted user staff_id=%s sender_id=%s",
599
+ self.name, sender_staff_id, sender_id,
600
+ )
601
+ return
602
+
603
+ # Group mention/pattern gate. DMs pass through unconditionally.
604
+ # We need the message text for regex wake-word matching; extract it
605
+ # early but don't consume the rest of the pipeline until after the
606
+ # gate decides whether to process.
607
+ _early_text = self._extract_text(message) or ""
608
+ if not self._should_process_message(message, _early_text, is_group, chat_id):
609
+ logger.debug(
610
+ "[%s] Dropping group message that failed mention gate message_id=%s chat_id=%s",
611
+ self.name, msg_id, chat_id,
612
+ )
613
+ return
614
+
615
+ # Stash the incoming message keyed by chat_id so concurrent
616
+ # conversations don't clobber each other's context. Also reset
617
+ # the per-chat "Done emoji fired" marker so a new inbound message
618
+ # gets its own Thinking→Done cycle.
619
+ if chat_id:
620
+ self._message_contexts[chat_id] = message
621
+ self._done_emoji_fired.discard(chat_id)
622
+
623
+ # Store session webhook
624
+ session_webhook = getattr(message, "session_webhook", None) or ""
625
+ session_webhook_expired_time = (
626
+ getattr(message, "session_webhook_expired_time", 0) or 0
627
+ )
628
+ if session_webhook and chat_id and _DINGTALK_WEBHOOK_RE.match(session_webhook):
629
+ if len(self._session_webhooks) >= _SESSION_WEBHOOKS_MAX:
630
+ try:
631
+ self._session_webhooks.pop(next(iter(self._session_webhooks)))
632
+ except StopIteration:
633
+ pass
634
+ self._session_webhooks[chat_id] = (
635
+ session_webhook,
636
+ session_webhook_expired_time,
637
+ )
638
+
639
+ # Resolve media download codes to URLs so vision tools can use them
640
+ await self._resolve_media_codes(message)
641
+
642
+ # Extract text content
643
+ text = self._extract_text(message)
644
+
645
+ # Determine message type and build media list
646
+ msg_type, media_urls, media_types = self._extract_media(message)
647
+
648
+ if not text and not media_urls:
649
+ logger.debug("[%s] Empty message, skipping", self.name)
650
+ return
651
+
652
+ source = self.build_source(
653
+ chat_id=chat_id,
654
+ chat_name=getattr(message, "conversation_title", None),
655
+ chat_type=chat_type,
656
+ user_id=sender_id,
657
+ user_name=sender_nick,
658
+ user_id_alt=sender_staff_id if sender_staff_id else None,
659
+ )
660
+
661
+ # Parse timestamp
662
+ create_at = getattr(message, "create_at", None)
663
+ try:
664
+ timestamp = (
665
+ datetime.fromtimestamp(int(create_at) / 1000, tz=timezone.utc)
666
+ if create_at
667
+ else datetime.now(tz=timezone.utc)
668
+ )
669
+ except (ValueError, OSError, TypeError):
670
+ timestamp = datetime.now(tz=timezone.utc)
671
+
672
+ event = MessageEvent(
673
+ text=text,
674
+ message_type=msg_type,
675
+ source=source,
676
+ message_id=msg_id,
677
+ raw_message=message,
678
+ media_urls=media_urls,
679
+ media_types=media_types,
680
+ timestamp=timestamp,
681
+ )
682
+
683
+ logger.debug(
684
+ "[%s] Message from %s in %s: %s",
685
+ self.name,
686
+ sender_nick,
687
+ chat_id[:20] if chat_id else "?",
688
+ text[:80] if text else "(media)",
689
+ )
690
+ await self.handle_message(event)
691
+
692
+ @staticmethod
693
+ def _extract_text(message: "ChatbotMessage") -> str:
694
+ """Extract plain text from a DingTalk chatbot message.
695
+
696
+ Handles both legacy and current dingtalk-stream SDK payload shapes:
697
+ * legacy: ``message.text`` was a dict ``{"content": "..."}``
698
+ * >= 0.20: ``message.text`` is a ``TextContent`` dataclass whose
699
+ ``__str__`` returns ``"TextContent(content=...)"`` — never fall
700
+ back to ``str(text)`` without extracting ``.content`` first.
701
+ * rich text moved from ``message.rich_text`` (list) to
702
+ ``message.rich_text_content.rich_text_list`` (list of dicts).
703
+ """
704
+ text = getattr(message, "text", None) or ""
705
+
706
+ # Handle TextContent object (SDK style)
707
+ if hasattr(text, "content"):
708
+ content = (text.content or "").strip()
709
+ elif isinstance(text, dict):
710
+ content = text.get("content", "").strip()
711
+ else:
712
+ content = str(text).strip()
713
+
714
+ if not content:
715
+ rich_text = getattr(message, "rich_text_content", None) or getattr(
716
+ message, "rich_text", None
717
+ )
718
+ if rich_text:
719
+ rich_list = getattr(rich_text, "rich_text_list", None) or rich_text
720
+ if isinstance(rich_list, list):
721
+ parts = []
722
+ for item in rich_list:
723
+ if isinstance(item, dict):
724
+ t = item.get("text") or item.get("content") or ""
725
+ if t:
726
+ parts.append(t)
727
+ elif hasattr(item, "text") and item.text:
728
+ parts.append(item.text)
729
+ content = " ".join(parts).strip()
730
+
731
+ # Do NOT strip "@bot" from the text. The mention is a routing
732
+ # signal (delivered structurally via callback `isInAtList`), and
733
+ # regex-stripping @handles would collateral-damage e-mails
734
+ # (alice@example.com), SSH URLs (git@github.com), and literal
735
+ # references the user wrote ("what does @openai think"). Let the
736
+ # LLM see the raw text — it handles "@bot hello" cleanly.
737
+ return content
738
+
739
+ def _extract_media(self, message: "ChatbotMessage"):
740
+ """Extract media info from message. Returns (MessageType, [urls], [mime_types])."""
741
+ msg_type = MessageType.TEXT
742
+ media_urls = []
743
+ media_types = []
744
+
745
+ # Check for image/picture
746
+ image_content = getattr(message, "image_content", None)
747
+ if image_content:
748
+ download_code = getattr(image_content, "download_code", None)
749
+ if download_code:
750
+ media_urls.append(download_code)
751
+ media_types.append("image")
752
+ msg_type = MessageType.PHOTO
753
+
754
+ # Check for rich text with mixed content
755
+ rich_text = getattr(message, "rich_text_content", None) or getattr(
756
+ message, "rich_text", None
757
+ )
758
+ if rich_text:
759
+ rich_list = getattr(rich_text, "rich_text_list", None) or rich_text
760
+ if isinstance(rich_list, list):
761
+ for item in rich_list:
762
+ if isinstance(item, dict):
763
+ dl_code = (
764
+ item.get("downloadCode") or item.get("download_code") or ""
765
+ )
766
+ item_type = item.get("type", "")
767
+ if dl_code:
768
+ mapped = DINGTALK_TYPE_MAPPING.get(item_type, "file")
769
+ media_urls.append(dl_code)
770
+ if mapped == "image":
771
+ media_types.append("image")
772
+ if msg_type == MessageType.TEXT:
773
+ msg_type = MessageType.PHOTO
774
+ elif mapped == "audio":
775
+ media_types.append("audio")
776
+ if msg_type == MessageType.TEXT:
777
+ msg_type = MessageType.AUDIO
778
+ elif mapped == "video":
779
+ media_types.append("video")
780
+ if msg_type == MessageType.TEXT:
781
+ msg_type = MessageType.VIDEO
782
+ else:
783
+ media_types.append("application/octet-stream")
784
+ if msg_type == MessageType.TEXT:
785
+ msg_type = MessageType.DOCUMENT
786
+
787
+ msg_type_str = getattr(message, "message_type", "") or ""
788
+ if msg_type_str == "picture" and not media_urls:
789
+ msg_type = MessageType.PHOTO
790
+ elif msg_type_str == "richText":
791
+ msg_type = (
792
+ MessageType.PHOTO
793
+ if any("image" in t for t in media_types)
794
+ else MessageType.TEXT
795
+ )
796
+
797
+ return msg_type, media_urls, media_types
798
+
799
+ # -- Outbound messaging -------------------------------------------------
800
+
801
+ async def send(
802
+ self,
803
+ chat_id: str,
804
+ content: str,
805
+ reply_to: Optional[str] = None,
806
+ metadata: Optional[Dict[str, Any]] = None,
807
+ ) -> SendResult:
808
+ """Send a markdown reply via DingTalk session webhook."""
809
+ metadata = metadata or {}
810
+ logger.debug(
811
+ "[%s] send() chat_id=%s card_enabled=%s",
812
+ self.name,
813
+ chat_id,
814
+ bool(self._card_template_id and self._card_sdk),
815
+ )
816
+
817
+ # Check metadata first (for direct webhook sends)
818
+ session_webhook = metadata.get("session_webhook")
819
+ if not session_webhook:
820
+ webhook_info = self._get_valid_webhook(chat_id)
821
+ if not webhook_info:
822
+ logger.warning(
823
+ "[%s] No valid session_webhook for chat_id=%s",
824
+ self.name, chat_id,
825
+ )
826
+ return SendResult(
827
+ success=False,
828
+ error="No valid session_webhook available. Reply must follow an incoming message.",
829
+ )
830
+ session_webhook, _ = webhook_info
831
+
832
+ if not self._http_client:
833
+ return SendResult(success=False, error="HTTP client not initialized")
834
+
835
+ # Look up the inbound message for this chat (for AI Card routing)
836
+ current_message = self._message_contexts.get(chat_id)
837
+
838
+ # ``reply_to`` is the signal that this send is the FINAL response
839
+ # to an inbound user message — only `base.py:_send_with_retry` sets
840
+ # it. Tool-progress, commentary, and stream-consumer first-sends
841
+ # all leave it None. We use it for two orthogonal decisions:
842
+ # 1. finalize on create? Yes if final reply, No if intermediate
843
+ # (intermediate cards stay in streaming state so edit_message
844
+ # updates don't flicker closed→streaming→closed repeatedly).
845
+ # 2. fire Done reaction? Only when this is the final reply.
846
+ is_final_reply = reply_to is not None
847
+
848
+ # Try AI Card first (using alibabacloud_dingtalk.card_1_0 SDK).
849
+ if self._card_template_id and current_message and self._card_sdk:
850
+ # Close any previously-open streaming cards for this chat
851
+ # before creating a new one (handles tool-progress → final-
852
+ # response handoff; also cleans up lingering commentary cards).
853
+ await self._close_streaming_siblings(chat_id)
854
+
855
+ result = await self._create_and_stream_card(
856
+ chat_id, current_message, content,
857
+ finalize=is_final_reply,
858
+ )
859
+ if result and result.success:
860
+ if is_final_reply:
861
+ # Final reply: card closed, swap Thinking → Done.
862
+ self._fire_done_reaction(chat_id)
863
+ else:
864
+ # Intermediate (tool progress / commentary / streaming
865
+ # first chunk): keep the card open and track it so the
866
+ # next send() auto-closes it as a sibling, or
867
+ # edit_message(finalize=True) closes it explicitly.
868
+ self._streaming_cards.setdefault(chat_id, {})[
869
+ result.message_id
870
+ ] = content
871
+ return result
872
+
873
+ logger.warning("[%s] AI Card send failed, falling back to webhook", self.name)
874
+
875
+ logger.debug("[%s] Sending via webhook", self.name)
876
+ # Normalize markdown for DingTalk
877
+ normalized = self._normalize_markdown(content[: self.MAX_MESSAGE_LENGTH])
878
+
879
+ payload = {
880
+ "msgtype": "markdown",
881
+ "markdown": {"title": "Hermes", "text": normalized},
882
+ }
883
+
884
+ try:
885
+ resp = await self._http_client.post(
886
+ session_webhook, json=payload, timeout=15.0
887
+ )
888
+ if resp.status_code < 300:
889
+ # Webhook path: fire Done only for final replies, same as
890
+ # the card path.
891
+ if is_final_reply:
892
+ self._fire_done_reaction(chat_id)
893
+ return SendResult(success=True, message_id=uuid.uuid4().hex[:12])
894
+ body = resp.text
895
+ logger.warning(
896
+ "[%s] Send failed HTTP %d: %s", self.name, resp.status_code, body[:200]
897
+ )
898
+ return SendResult(
899
+ success=False, error=f"HTTP {resp.status_code}: {body[:200]}"
900
+ )
901
+ except httpx.TimeoutException:
902
+ return SendResult(
903
+ success=False, error="Timeout sending message to DingTalk"
904
+ )
905
+ except Exception as e:
906
+ logger.error("[%s] Send error: %s", self.name, e)
907
+ return SendResult(success=False, error=str(e))
908
+
909
+ async def send_typing(self, chat_id: str, metadata=None) -> None:
910
+ """DingTalk does not support typing indicators."""
911
+ pass
912
+
913
+ async def send_image(
914
+ self,
915
+ chat_id: str,
916
+ image_url: str,
917
+ caption: Optional[str] = None,
918
+ reply_to: Optional[str] = None,
919
+ metadata: Optional[Dict[str, Any]] = None,
920
+ ) -> SendResult:
921
+ """Send an image via DingTalk markdown.
922
+
923
+ DingTalk's session webhook only supports text/markdown payloads, not
924
+ native image/file attachments. For remote image URLs, render the image
925
+ inline with markdown so the user still sees the image. Local files need
926
+ OpenAPI media upload and are handled separately.
927
+ """
928
+ image_block = f"![image]({image_url})"
929
+ content = f"{caption}\n\n{image_block}" if caption else image_block
930
+ return await self.send(
931
+ chat_id=chat_id,
932
+ content=content,
933
+ reply_to=reply_to,
934
+ metadata=metadata,
935
+ )
936
+
937
+ async def send_image_file(
938
+ self,
939
+ chat_id: str,
940
+ image_path: str,
941
+ caption: Optional[str] = None,
942
+ reply_to: Optional[str] = None,
943
+ metadata: Optional[Dict[str, Any]] = None,
944
+ **kwargs,
945
+ ) -> SendResult:
946
+ """DingTalk webhook replies cannot send local image files directly."""
947
+ return SendResult(
948
+ success=False,
949
+ error=(
950
+ "DingTalk session webhook replies do not support local image uploads. "
951
+ "Only markdown/text replies are supported without OpenAPI media upload."
952
+ ),
953
+ )
954
+
955
+ async def send_document(
956
+ self,
957
+ chat_id: str,
958
+ file_path: str,
959
+ caption: Optional[str] = None,
960
+ file_name: Optional[str] = None,
961
+ reply_to: Optional[str] = None,
962
+ metadata: Optional[Dict[str, Any]] = None,
963
+ **kwargs,
964
+ ) -> SendResult:
965
+ """DingTalk webhook replies cannot send local file attachments directly."""
966
+ return SendResult(
967
+ success=False,
968
+ error=(
969
+ "DingTalk session webhook replies do not support local file attachments. "
970
+ "Only markdown/text replies are supported without OpenAPI message send."
971
+ ),
972
+ )
973
+
974
+ async def get_chat_info(self, chat_id: str) -> Dict[str, Any]:
975
+ """Return basic info about a DingTalk conversation."""
976
+ return {
977
+ "name": chat_id,
978
+ "type": "group" if "group" in chat_id.lower() else "dm",
979
+ }
980
+
981
+ def _get_valid_webhook(self, chat_id: str) -> Optional[tuple[str, int]]:
982
+ """Get a valid (non-expired) session webhook for the given chat_id."""
983
+ info = self._session_webhooks.get(chat_id)
984
+ if not info:
985
+ return None
986
+ webhook, expired_time_ms = info
987
+ # Check expiry with 5-minute safety margin
988
+ if expired_time_ms and expired_time_ms > 0:
989
+ now_ms = int(datetime.now(tz=timezone.utc).timestamp() * 1000)
990
+ safety_margin_ms = 5 * 60 * 1000
991
+ if now_ms + safety_margin_ms >= expired_time_ms:
992
+ # Expired, remove from cache
993
+ self._session_webhooks.pop(chat_id, None)
994
+ return None
995
+ return info
996
+
997
+ async def _create_and_stream_card(
998
+ self,
999
+ chat_id: str,
1000
+ message: Any,
1001
+ content: str,
1002
+ *,
1003
+ finalize: bool = True,
1004
+ ) -> Optional[SendResult]:
1005
+ """Create an AI Card, deliver it to the conversation, and stream initial content.
1006
+
1007
+ Always called with ``finalize=True`` from ``send()`` (closed state).
1008
+ If the caller later issues ``edit_message(finalize=False)``, the
1009
+ DingTalk streaming_update API reopens the card into streaming
1010
+ state, and we track that in ``_streaming_cards`` for sibling
1011
+ cleanup on the next send.
1012
+ """
1013
+ try:
1014
+ token = await self._get_access_token()
1015
+ if not token:
1016
+ return None
1017
+
1018
+ out_track_id = f"hermes_{uuid.uuid4().hex[:12]}"
1019
+
1020
+ conversation_id = getattr(message, "conversation_id", "") or ""
1021
+ conversation_type = getattr(message, "conversation_type", "1")
1022
+ is_group = str(conversation_type) == "2"
1023
+ sender_staff_id = getattr(message, "sender_staff_id", "") or ""
1024
+
1025
+ runtime = tea_util_models.RuntimeOptions()
1026
+
1027
+ # Step 1: Create card with STREAM callback type
1028
+ create_request = dingtalk_card_models.CreateCardRequest(
1029
+ card_template_id=self._card_template_id,
1030
+ out_track_id=out_track_id,
1031
+ card_data=dingtalk_card_models.CreateCardRequestCardData(
1032
+ card_param_map={"content": ""},
1033
+ ),
1034
+ callback_type="STREAM",
1035
+ im_group_open_space_model=(
1036
+ dingtalk_card_models.CreateCardRequestImGroupOpenSpaceModel(
1037
+ support_forward=True,
1038
+ )
1039
+ ),
1040
+ im_robot_open_space_model=(
1041
+ dingtalk_card_models.CreateCardRequestImRobotOpenSpaceModel(
1042
+ support_forward=True,
1043
+ )
1044
+ ),
1045
+ )
1046
+
1047
+ create_headers = dingtalk_card_models.CreateCardHeaders(
1048
+ x_acs_dingtalk_access_token=token,
1049
+ )
1050
+
1051
+ await self._card_sdk.create_card_with_options_async(
1052
+ create_request, create_headers, runtime
1053
+ )
1054
+
1055
+ # Step 2: Deliver card to the conversation
1056
+ if is_group:
1057
+ open_space_id = f"dtv1.card//IM_GROUP.{conversation_id}"
1058
+ deliver_request = dingtalk_card_models.DeliverCardRequest(
1059
+ out_track_id=out_track_id,
1060
+ user_id_type=1,
1061
+ open_space_id=open_space_id,
1062
+ im_group_open_deliver_model=(
1063
+ dingtalk_card_models.DeliverCardRequestImGroupOpenDeliverModel(
1064
+ robot_code=self._robot_code,
1065
+ )
1066
+ ),
1067
+ )
1068
+ else:
1069
+ if not sender_staff_id:
1070
+ logger.warning(
1071
+ "[%s] AI Card skipped: missing sender_staff_id for DM",
1072
+ self.name,
1073
+ )
1074
+ return None
1075
+ open_space_id = f"dtv1.card//IM_ROBOT.{sender_staff_id}"
1076
+ deliver_request = dingtalk_card_models.DeliverCardRequest(
1077
+ out_track_id=out_track_id,
1078
+ user_id_type=1,
1079
+ open_space_id=open_space_id,
1080
+ im_robot_open_deliver_model=(
1081
+ dingtalk_card_models.DeliverCardRequestImRobotOpenDeliverModel(
1082
+ space_type="IM_ROBOT",
1083
+ )
1084
+ ),
1085
+ )
1086
+
1087
+ deliver_headers = dingtalk_card_models.DeliverCardHeaders(
1088
+ x_acs_dingtalk_access_token=token,
1089
+ )
1090
+
1091
+ await self._card_sdk.deliver_card_with_options_async(
1092
+ deliver_request, deliver_headers, runtime
1093
+ )
1094
+
1095
+ # Step 3: Stream initial content. finalize=True closes the
1096
+ # card immediately (one-shot); finalize=False keeps it open
1097
+ # for streaming edit_message updates by out_track_id.
1098
+ await self._stream_card_content(
1099
+ out_track_id, token, content, finalize=finalize,
1100
+ )
1101
+
1102
+ logger.info(
1103
+ "[%s] AI Card %s: %s",
1104
+ self.name,
1105
+ "created+finalized" if finalize else "created (streaming)",
1106
+ out_track_id,
1107
+ )
1108
+ return SendResult(success=True, message_id=out_track_id)
1109
+
1110
+ except Exception as e:
1111
+ logger.warning(
1112
+ "[%s] AI Card create failed: %s\n%s",
1113
+ self.name, e, traceback.format_exc(),
1114
+ )
1115
+ return None
1116
+
1117
+ async def edit_message(
1118
+ self,
1119
+ chat_id: str,
1120
+ message_id: str,
1121
+ content: str,
1122
+ *,
1123
+ finalize: bool = False,
1124
+ ) -> SendResult:
1125
+ """Edit an AI Card by streaming updated content.
1126
+
1127
+ ``message_id`` is the out_track_id returned by the initial ``send()``
1128
+ call that created this card. Callers (stream_consumer, tool
1129
+ progress) track their own ids independently so two parallel flows
1130
+ on the same chat_id don't interfere.
1131
+ """
1132
+ if not message_id:
1133
+ return SendResult(success=False, error="message_id required")
1134
+ token = await self._get_access_token()
1135
+ if not token:
1136
+ return SendResult(success=False, error="No access token")
1137
+
1138
+ try:
1139
+ await self._stream_card_content(
1140
+ message_id, token, content, finalize=finalize,
1141
+ )
1142
+ if finalize:
1143
+ # Remove from streaming-cards tracking and fire Done. This
1144
+ # is the canonical "response ended" signal from stream
1145
+ # consumer's final edit.
1146
+ self._streaming_cards.get(chat_id, {}).pop(message_id, None)
1147
+ if not self._streaming_cards.get(chat_id):
1148
+ self._streaming_cards.pop(chat_id, None)
1149
+ logger.debug(
1150
+ "[%s] AI Card finalized (edit): %s",
1151
+ self.name, message_id,
1152
+ )
1153
+ self._fire_done_reaction(chat_id)
1154
+ else:
1155
+ # Non-final edit reopens the card into streaming state —
1156
+ # track it so the next send() can auto-close it as a
1157
+ # sibling.
1158
+ self._streaming_cards.setdefault(chat_id, {})[message_id] = content
1159
+ return SendResult(success=True, message_id=message_id)
1160
+ except Exception as e:
1161
+ logger.warning("[%s] Card edit failed: %s", self.name, e)
1162
+ return SendResult(success=False, error=str(e))
1163
+
1164
+ async def _stream_card_content(
1165
+ self,
1166
+ out_track_id: str,
1167
+ token: str,
1168
+ content: str,
1169
+ finalize: bool = False,
1170
+ ) -> None:
1171
+ """Stream content to an existing AI Card."""
1172
+ stream_request = dingtalk_card_models.StreamingUpdateRequest(
1173
+ out_track_id=out_track_id,
1174
+ guid=str(uuid.uuid4()),
1175
+ key="content",
1176
+ content=content[: self.MAX_MESSAGE_LENGTH],
1177
+ is_full=True,
1178
+ is_finalize=finalize,
1179
+ is_error=False,
1180
+ )
1181
+
1182
+ stream_headers = dingtalk_card_models.StreamingUpdateHeaders(
1183
+ x_acs_dingtalk_access_token=token,
1184
+ )
1185
+
1186
+ runtime = tea_util_models.RuntimeOptions()
1187
+ await self._card_sdk.streaming_update_with_options_async(
1188
+ stream_request, stream_headers, runtime
1189
+ )
1190
+
1191
+ async def _get_access_token(self) -> Optional[str]:
1192
+ """Get access token using SDK's cached token."""
1193
+ if not self._stream_client:
1194
+ return None
1195
+ try:
1196
+ # SDK's get_access_token is sync and uses requests
1197
+ token = await asyncio.to_thread(self._stream_client.get_access_token)
1198
+ return token
1199
+ except Exception as e:
1200
+ logger.error("[%s] Failed to get access token: %s", self.name, e)
1201
+ return None
1202
+
1203
+ async def _send_emotion(
1204
+ self,
1205
+ open_msg_id: str,
1206
+ open_conversation_id: str,
1207
+ emoji_name: str,
1208
+ *,
1209
+ recall: bool = False,
1210
+ ) -> None:
1211
+ """Add or recall an emoji reaction on a message."""
1212
+ if not self._robot_sdk or not open_msg_id or not open_conversation_id:
1213
+ return
1214
+ action = "recall" if recall else "reply"
1215
+ try:
1216
+ token = await self._get_access_token()
1217
+ if not token:
1218
+ return
1219
+
1220
+ emotion_kwargs = {
1221
+ "robot_code": self._robot_code,
1222
+ "open_msg_id": open_msg_id,
1223
+ "open_conversation_id": open_conversation_id,
1224
+ "emotion_type": 2,
1225
+ "emotion_name": emoji_name,
1226
+ }
1227
+ runtime = tea_util_models.RuntimeOptions()
1228
+
1229
+ if recall:
1230
+ emotion_kwargs["text_emotion"] = (
1231
+ dingtalk_robot_models.RobotRecallEmotionRequestTextEmotion(
1232
+ emotion_id="2659900",
1233
+ emotion_name=emoji_name,
1234
+ text=emoji_name,
1235
+ background_id="im_bg_1",
1236
+ )
1237
+ )
1238
+ request = dingtalk_robot_models.RobotRecallEmotionRequest(
1239
+ **emotion_kwargs,
1240
+ )
1241
+ sdk_headers = dingtalk_robot_models.RobotRecallEmotionHeaders(
1242
+ x_acs_dingtalk_access_token=token,
1243
+ )
1244
+ await self._robot_sdk.robot_recall_emotion_with_options_async(
1245
+ request, sdk_headers, runtime
1246
+ )
1247
+ else:
1248
+ emotion_kwargs["text_emotion"] = (
1249
+ dingtalk_robot_models.RobotReplyEmotionRequestTextEmotion(
1250
+ emotion_id="2659900",
1251
+ emotion_name=emoji_name,
1252
+ text=emoji_name,
1253
+ background_id="im_bg_1",
1254
+ )
1255
+ )
1256
+ request = dingtalk_robot_models.RobotReplyEmotionRequest(
1257
+ **emotion_kwargs,
1258
+ )
1259
+ sdk_headers = dingtalk_robot_models.RobotReplyEmotionHeaders(
1260
+ x_acs_dingtalk_access_token=token,
1261
+ )
1262
+ await self._robot_sdk.robot_reply_emotion_with_options_async(
1263
+ request, sdk_headers, runtime
1264
+ )
1265
+ logger.info(
1266
+ "[%s] _send_emotion: %s %s on msg=%s",
1267
+ self.name, action, emoji_name, open_msg_id[:24],
1268
+ )
1269
+ except Exception:
1270
+ logger.debug(
1271
+ "[%s] _send_emotion %s failed", self.name, action, exc_info=True
1272
+ )
1273
+
1274
+ async def _resolve_media_codes(self, message: "ChatbotMessage") -> None:
1275
+ """Resolve download codes in message to actual URLs."""
1276
+ token = await self._get_access_token()
1277
+ if not token:
1278
+ return
1279
+
1280
+ robot_code = getattr(message, "robot_code", None) or self._client_id
1281
+ codes_to_resolve = []
1282
+
1283
+ # Collect codes and references to update
1284
+ # 1. Single image content
1285
+ img_content = getattr(message, "image_content", None)
1286
+ if img_content and getattr(img_content, "download_code", None):
1287
+ codes_to_resolve.append((img_content, "download_code"))
1288
+
1289
+ # 2. Rich text list
1290
+ rich_text = getattr(message, "rich_text_content", None)
1291
+ if rich_text:
1292
+ rich_list = getattr(rich_text, "rich_text_list", []) or []
1293
+ for item in rich_list:
1294
+ if isinstance(item, dict):
1295
+ for key in ("downloadCode", "pictureDownloadCode", "download_code"):
1296
+ if item.get(key):
1297
+ codes_to_resolve.append((item, key))
1298
+
1299
+ if not codes_to_resolve:
1300
+ return
1301
+
1302
+ # Resolve all codes in parallel
1303
+ tasks = []
1304
+ for obj, key in codes_to_resolve:
1305
+ code = getattr(obj, key, None) if hasattr(obj, key) else obj.get(key)
1306
+ if code:
1307
+ tasks.append(
1308
+ self._fetch_download_url(code, robot_code, token, obj, key)
1309
+ )
1310
+
1311
+ await asyncio.gather(*tasks, return_exceptions=True)
1312
+
1313
+ async def _fetch_download_url(
1314
+ self, code: str, robot_code: str, token: str, obj, key: str
1315
+ ) -> None:
1316
+ """Fetch download URL for a single code using the robot SDK."""
1317
+ if not self._robot_sdk:
1318
+ logger.warning(
1319
+ "[%s] Robot SDK not initialized, cannot resolve media code",
1320
+ self.name,
1321
+ )
1322
+ return
1323
+ try:
1324
+ request = dingtalk_robot_models.RobotMessageFileDownloadRequest(
1325
+ download_code=code,
1326
+ robot_code=robot_code,
1327
+ )
1328
+ headers = dingtalk_robot_models.RobotMessageFileDownloadHeaders(
1329
+ x_acs_dingtalk_access_token=token,
1330
+ )
1331
+ runtime = tea_util_models.RuntimeOptions()
1332
+ response = await self._robot_sdk.robot_message_file_download_with_options_async(
1333
+ request, headers, runtime
1334
+ )
1335
+ body = response.body if response else None
1336
+ if body:
1337
+ url = getattr(body, "download_url", None)
1338
+ if url:
1339
+ if hasattr(obj, key):
1340
+ setattr(obj, key, url)
1341
+ elif isinstance(obj, dict):
1342
+ obj[key] = url
1343
+ else:
1344
+ logger.warning(
1345
+ "[%s] Failed to download media: empty response for code %s",
1346
+ self.name,
1347
+ code,
1348
+ )
1349
+ except Exception as e:
1350
+ logger.error("[%s] Error resolving media code %s: %s", self.name, code, e)
1351
+
1352
+ @staticmethod
1353
+ def _normalize_markdown(text: str) -> str:
1354
+ """Normalize markdown for DingTalk's parser.
1355
+
1356
+ DingTalk's markdown renderer has quirks:
1357
+ - Numbered lists need blank line before them
1358
+ - Indented code blocks may render incorrectly
1359
+ """
1360
+ lines = text.split("\n")
1361
+ out = []
1362
+ for i, line in enumerate(lines):
1363
+ # Ensure blank line before numbered list items
1364
+ is_numbered = re.match(r"^\d+\.\s", line.strip())
1365
+ if is_numbered and i > 0:
1366
+ prev = lines[i - 1]
1367
+ if prev.strip() and not re.match(r"^\d+\.\s", prev.strip()):
1368
+ out.append("")
1369
+ # Dedent fenced code blocks
1370
+ if line.strip().startswith("```") and line != line.lstrip():
1371
+ indent = len(line) - len(line.lstrip())
1372
+ line = line[indent:]
1373
+ out.append(line)
1374
+ return "\n".join(out)
1375
+
1376
+
1377
+ # ---------------------------------------------------------------------------
1378
+ # Internal stream handler
1379
+ # ---------------------------------------------------------------------------
1380
+
1381
+
1382
+ class _IncomingHandler(
1383
+ dingtalk_stream.ChatbotHandler if DINGTALK_STREAM_AVAILABLE else object
1384
+ ):
1385
+ """dingtalk-stream ChatbotHandler that forwards messages to the adapter.
1386
+
1387
+ SDK >= 0.20 changed process() from sync to async, and the message
1388
+ parameter from ChatbotMessage to CallbackMessage. We parse the
1389
+ CallbackMessage.data dict into a ChatbotMessage before forwarding.
1390
+ """
1391
+
1392
+ def __init__(self, adapter: DingTalkAdapter, loop: Optional[asyncio.AbstractEventLoop] = None):
1393
+ if DINGTALK_STREAM_AVAILABLE:
1394
+ super().__init__()
1395
+ self._adapter = adapter
1396
+ self._loop = loop
1397
+
1398
+ async def process(self, message: "CallbackMessage"):
1399
+ """Called by dingtalk-stream (>=0.20) when a message arrives.
1400
+
1401
+ dingtalk-stream >= 0.24 passes a CallbackMessage whose ``.data`` contains
1402
+ the chatbot payload. Convert it to ChatbotMessage via
1403
+ ``ChatbotMessage.from_dict()``.
1404
+
1405
+ Message processing is dispatched as a background task so that this
1406
+ method returns the ACK immediately — blocking here would prevent the
1407
+ SDK from sending heartbeats, eventually causing a disconnect.
1408
+ """
1409
+ try:
1410
+ # CallbackMessage.data is a dict containing the raw DingTalk payload
1411
+ data = message.data
1412
+ if isinstance(data, str):
1413
+ data = json.loads(data)
1414
+
1415
+ # Parse dict into ChatbotMessage using SDK's from_dict
1416
+ chatbot_msg = ChatbotMessage.from_dict(data)
1417
+
1418
+ # Ensure session_webhook is populated even if the SDK's
1419
+ # from_dict() did not map it (field name mismatch across
1420
+ # SDK versions).
1421
+ if not getattr(chatbot_msg, "session_webhook", None):
1422
+ webhook = (
1423
+ data.get("sessionWebhook")
1424
+ or data.get("session_webhook")
1425
+ or ""
1426
+ ) if isinstance(data, dict) else ""
1427
+ if webhook:
1428
+ chatbot_msg.session_webhook = webhook
1429
+
1430
+ # Ensure is_in_at_list is populated from the structured callback
1431
+ # flag even if from_dict() did not map it. DingTalk sends
1432
+ # ``isInAtList`` in the raw payload; the adapter's mention check
1433
+ # reads the ChatbotMessage attribute ``is_in_at_list``.
1434
+ if not getattr(chatbot_msg, "is_in_at_list", False):
1435
+ raw_flag = (
1436
+ data.get("isInAtList") if isinstance(data, dict) else False
1437
+ )
1438
+ if raw_flag:
1439
+ chatbot_msg.is_in_at_list = True
1440
+
1441
+ msg_id = getattr(chatbot_msg, "message_id", None) or ""
1442
+ conversation_id = getattr(chatbot_msg, "conversation_id", None) or ""
1443
+
1444
+ # Thinking reaction — fire-and-forget, tracked
1445
+ if msg_id and conversation_id:
1446
+ self._adapter._spawn_bg(
1447
+ self._adapter._send_emotion(
1448
+ msg_id, conversation_id, "🤔Thinking", recall=False,
1449
+ )
1450
+ )
1451
+
1452
+ # Fire-and-forget: return ACK immediately, process in background.
1453
+ # Blocking here would prevent the SDK from sending heartbeats,
1454
+ # eventually causing a disconnect. _on_message is wrapped so
1455
+ # exceptions inside the task surface in logs instead of
1456
+ # disappearing into the event loop.
1457
+ asyncio.create_task(self._safe_on_message(chatbot_msg))
1458
+ except Exception:
1459
+ logger.exception(
1460
+ "[%s] Error preparing incoming message", self._adapter.name
1461
+ )
1462
+ return AckMessage.STATUS_SYSTEM_EXCEPTION, "error"
1463
+
1464
+ return AckMessage.STATUS_OK, "OK"
1465
+
1466
+ async def _safe_on_message(self, chatbot_msg: "ChatbotMessage") -> None:
1467
+ """Wrapper that catches exceptions from _on_message."""
1468
+ try:
1469
+ await self._adapter._on_message(chatbot_msg)
1470
+ except Exception:
1471
+ logger.exception(
1472
+ "[%s] Error processing incoming message", self._adapter.name
1473
+ )