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,1782 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Code Execution Tool -- Programmatic Tool Calling (PTC)
4
+
5
+ Lets the LLM write a Python script that calls Hermes tools via RPC,
6
+ collapsing multi-step tool chains into a single inference turn.
7
+
8
+ Architecture (two transports):
9
+
10
+ **Local backend (UDS):**
11
+ 1. Parent generates a `hermes_tools.py` stub module with UDS RPC functions
12
+ 2. Parent opens a Unix domain socket and starts an RPC listener thread
13
+ 3. Parent spawns a child process that runs the LLM's script
14
+ 4. Tool calls travel over the UDS back to the parent for dispatch
15
+
16
+ **Remote backends (file-based RPC):**
17
+ 1. Parent generates `hermes_tools.py` with file-based RPC stubs
18
+ 2. Parent ships both files to the remote environment
19
+ 3. Script runs inside the terminal backend (Docker/SSH/Modal/Daytona/etc.)
20
+ 4. Tool calls are written as request files; a polling thread on the parent
21
+ reads them via env.execute(), dispatches, and writes response files
22
+ 5. The script polls for response files and continues
23
+
24
+ In both cases, only the script's stdout is returned to the LLM; intermediate
25
+ tool results never enter the context window.
26
+
27
+ Platform: Linux / macOS only (Unix domain sockets for local). Disabled on Windows.
28
+ Remote execution additionally requires Python 3 in the terminal backend.
29
+ """
30
+
31
+ import base64
32
+ import functools
33
+ import json
34
+ import logging
35
+ import os
36
+ import platform
37
+ import shlex
38
+ import signal
39
+ import socket
40
+ import subprocess
41
+ import sys
42
+ import tempfile
43
+ import threading
44
+ import time
45
+ import uuid
46
+
47
+ _IS_WINDOWS = platform.system() == "Windows"
48
+ from typing import Any, Dict, List, Optional
49
+
50
+ # Availability gate. On Windows we fall back to loopback TCP for the
51
+ # sandbox RPC transport (AF_UNIX is unreliable on Windows Python) — see
52
+ # ``_use_tcp_rpc`` in ``_execute_local`` below. That makes execute_code
53
+ # available on every platform Hermes itself runs on.
54
+ logger = logging.getLogger(__name__)
55
+
56
+ SANDBOX_AVAILABLE = True
57
+
58
+ # The 7 tools allowed inside the sandbox. The intersection of this list
59
+ # and the session's enabled tools determines which stubs are generated.
60
+ SANDBOX_ALLOWED_TOOLS = frozenset([
61
+ "web_search",
62
+ "web_extract",
63
+ "read_file",
64
+ "write_file",
65
+ "search_files",
66
+ "patch",
67
+ "terminal",
68
+ ])
69
+
70
+ # Resource limit defaults (overridable via config.yaml → code_execution.*)
71
+ DEFAULT_TIMEOUT = 300 # 5 minutes
72
+ DEFAULT_MAX_TOOL_CALLS = 50
73
+ MAX_STDOUT_BYTES = 50_000 # 50 KB
74
+ MAX_STDERR_BYTES = 10_000 # 10 KB
75
+
76
+ # Environment variable scrubbing rules (shared between the local + remote
77
+ # backends). Secret-substring block is applied first; anything left must
78
+ # match either a safe prefix or, on Windows, an OS-essential name.
79
+ _SAFE_ENV_PREFIXES = ("PATH", "HOME", "USER", "LANG", "LC_", "TERM",
80
+ "TMPDIR", "TMP", "TEMP", "SHELL", "LOGNAME",
81
+ "XDG_", "PYTHONPATH", "VIRTUAL_ENV", "CONDA",
82
+ "HERMES_")
83
+ _SECRET_SUBSTRINGS = ("KEY", "TOKEN", "SECRET", "PASSWORD", "CREDENTIAL",
84
+ "PASSWD", "AUTH")
85
+
86
+ # Windows-only: a handful of variables are required by the OS/CRT itself.
87
+ # Without them, even stdlib calls like ``socket.socket()`` fail with
88
+ # WinError 10106 (Winsock can't locate mswsock.dll) and ``subprocess``
89
+ # can't resolve cmd.exe. These are well-known OS paths, not secrets, so
90
+ # we allow them through by exact name. The _SECRET_SUBSTRINGS block
91
+ # still runs as a safety net (none of these names match those substrings).
92
+ _WINDOWS_ESSENTIAL_ENV_VARS = frozenset({
93
+ "SYSTEMROOT", # %SYSTEMROOT%\System32 — Winsock needs this
94
+ "SYSTEMDRIVE", # C: (or wherever Windows lives)
95
+ "WINDIR", # usually same as SYSTEMROOT
96
+ "COMSPEC", # cmd.exe path — subprocess shell=True needs it
97
+ "PATHEXT", # .COM;.EXE;.BAT;... — shell lookup
98
+ "OS", # "Windows_NT" — some tools gate on this
99
+ "PROCESSOR_ARCHITECTURE",
100
+ "NUMBER_OF_PROCESSORS",
101
+ "PUBLIC", # C:\Users\Public
102
+ "ALLUSERSPROFILE", # C:\ProgramData — some stdlib paths use it
103
+ "PROGRAMDATA", # C:\ProgramData
104
+ "PROGRAMFILES",
105
+ "PROGRAMFILES(X86)",
106
+ "PROGRAMW6432",
107
+ "APPDATA", # %USERPROFILE%\AppData\Roaming — Python uses it
108
+ "LOCALAPPDATA", # %USERPROFILE%\AppData\Local
109
+ "USERPROFILE", # C:\Users\<name> — Python's expanduser uses it
110
+ "USERDOMAIN",
111
+ "USERNAME",
112
+ "HOMEDRIVE", # C:
113
+ "HOMEPATH", # \Users\<name>
114
+ "COMPUTERNAME",
115
+ })
116
+
117
+
118
+ def _scrub_child_env(source_env, is_passthrough=None, is_windows=None):
119
+ """Produce the scrubbed child-process env for execute_code.
120
+
121
+ Rules (order matters):
122
+ 1. Passthrough vars (skill- or config-declared) always pass.
123
+ 2. Secret-substring names (KEY/TOKEN/etc.) are blocked.
124
+ 3. Names matching a safe prefix pass.
125
+ 4. On Windows, a small OS-essential allowlist passes by exact name
126
+ — without these the child can't even create a socket or spawn a
127
+ subprocess.
128
+
129
+ Extracted into a helper so tests can exercise the logic without
130
+ spawning a subprocess.
131
+ """
132
+ if is_passthrough is None:
133
+ try:
134
+ from tools.env_passthrough import is_env_passthrough as _ep
135
+ except Exception:
136
+ _ep = lambda _: False # noqa: E731
137
+ is_passthrough = _ep
138
+ if is_windows is None:
139
+ is_windows = _IS_WINDOWS
140
+
141
+ scrubbed = {}
142
+ for k, v in source_env.items():
143
+ if is_passthrough(k):
144
+ scrubbed[k] = v
145
+ continue
146
+ if any(s in k.upper() for s in _SECRET_SUBSTRINGS):
147
+ continue
148
+ if any(k.startswith(p) for p in _SAFE_ENV_PREFIXES):
149
+ scrubbed[k] = v
150
+ continue
151
+ if is_windows and k.upper() in _WINDOWS_ESSENTIAL_ENV_VARS:
152
+ scrubbed[k] = v
153
+ return scrubbed
154
+
155
+
156
+ def check_sandbox_requirements() -> bool:
157
+ """Code execution sandbox requires a POSIX OS for Unix domain sockets."""
158
+ if not SANDBOX_AVAILABLE:
159
+ return False
160
+
161
+ try:
162
+ from tools.terminal_tool import (
163
+ _check_vercel_sandbox_requirements,
164
+ _get_env_config,
165
+ )
166
+
167
+ config = _get_env_config()
168
+ except Exception:
169
+ logger.debug("Could not resolve terminal config for execute_code availability", exc_info=True)
170
+ return False
171
+
172
+ if config.get("env_type") == "vercel_sandbox":
173
+ return _check_vercel_sandbox_requirements(config)
174
+
175
+ return True
176
+
177
+
178
+ # ---------------------------------------------------------------------------
179
+ # hermes_tools.py code generator
180
+ # ---------------------------------------------------------------------------
181
+
182
+ # Per-tool stub templates: (function_name, signature, docstring, args_dict_expr)
183
+ # The args_dict_expr builds the JSON payload sent over the RPC socket.
184
+ _TOOL_STUBS = {
185
+ "web_search": (
186
+ "web_search",
187
+ "query: str, limit: int = 5",
188
+ '"""Search the web. Returns dict with data.web list of {url, title, description}."""',
189
+ '{"query": query, "limit": limit}',
190
+ ),
191
+ "web_extract": (
192
+ "web_extract",
193
+ "urls: list",
194
+ '"""Extract content from URLs. Returns dict with results list of {url, title, content, error}."""',
195
+ '{"urls": urls}',
196
+ ),
197
+ "read_file": (
198
+ "read_file",
199
+ "path: str, offset: int = 1, limit: int = 500",
200
+ '"""Read a file (1-indexed lines). Returns dict with "content" and "total_lines"."""',
201
+ '{"path": path, "offset": offset, "limit": limit}',
202
+ ),
203
+ "write_file": (
204
+ "write_file",
205
+ "path: str, content: str",
206
+ '"""Write content to a file (always overwrites). Returns dict with status."""',
207
+ '{"path": path, "content": content}',
208
+ ),
209
+ "search_files": (
210
+ "search_files",
211
+ 'pattern: str, target: str = "content", path: str = ".", file_glob: str = None, limit: int = 50, offset: int = 0, output_mode: str = "content", context: int = 0',
212
+ '"""Search file contents (target="content") or find files by name (target="files"). Returns dict with "matches"."""',
213
+ '{"pattern": pattern, "target": target, "path": path, "file_glob": file_glob, "limit": limit, "offset": offset, "output_mode": output_mode, "context": context}',
214
+ ),
215
+ "patch": (
216
+ "patch",
217
+ 'path: str = None, old_string: str = None, new_string: str = None, replace_all: bool = False, mode: str = "replace", patch: str = None',
218
+ '"""Targeted find-and-replace (mode="replace") or V4A multi-file patches (mode="patch"). Returns dict with status."""',
219
+ '{"path": path, "old_string": old_string, "new_string": new_string, "replace_all": replace_all, "mode": mode, "patch": patch}',
220
+ ),
221
+ "terminal": (
222
+ "terminal",
223
+ "command: str, timeout: int = None, workdir: str = None",
224
+ '"""Run a shell command (foreground only). Returns dict with "output" and "exit_code"."""',
225
+ '{"command": command, "timeout": timeout, "workdir": workdir}',
226
+ ),
227
+ }
228
+
229
+
230
+ def generate_hermes_tools_module(enabled_tools: List[str],
231
+ transport: str = "uds") -> str:
232
+ """
233
+ Build the source code for the hermes_tools.py stub module.
234
+
235
+ Only tools in both SANDBOX_ALLOWED_TOOLS and enabled_tools get stubs.
236
+
237
+ Args:
238
+ enabled_tools: Tool names enabled in the current session.
239
+ transport: ``"uds"`` for Unix domain socket (local backend) or
240
+ ``"file"`` for file-based RPC (remote backends).
241
+ """
242
+ tools_to_generate = sorted(SANDBOX_ALLOWED_TOOLS & set(enabled_tools))
243
+
244
+ stub_functions = []
245
+ export_names = []
246
+ for tool_name in tools_to_generate:
247
+ if tool_name not in _TOOL_STUBS:
248
+ continue
249
+ func_name, sig, doc, args_expr = _TOOL_STUBS[tool_name]
250
+ stub_functions.append(
251
+ f"def {func_name}({sig}):\n"
252
+ f" {doc}\n"
253
+ f" return _call({func_name!r}, {args_expr})\n"
254
+ )
255
+ export_names.append(func_name)
256
+
257
+ if transport == "file":
258
+ header = _FILE_TRANSPORT_HEADER
259
+ else:
260
+ header = _UDS_TRANSPORT_HEADER
261
+
262
+ return header + "\n".join(stub_functions)
263
+
264
+
265
+ # ---- Shared helpers section (embedded in both transport headers) ----------
266
+
267
+ _COMMON_HELPERS = '''\
268
+
269
+ # ---------------------------------------------------------------------------
270
+ # Convenience helpers (avoid common scripting pitfalls)
271
+ # ---------------------------------------------------------------------------
272
+
273
+ def json_parse(text: str):
274
+ """Parse JSON tolerant of control characters (strict=False).
275
+ Use this instead of json.loads() when parsing output from terminal()
276
+ or web_extract() that may contain raw tabs/newlines in strings."""
277
+ return json.loads(text, strict=False)
278
+
279
+
280
+ def shell_quote(s: str) -> str:
281
+ """Shell-escape a string for safe interpolation into commands.
282
+ Use this when inserting dynamic content into terminal() commands:
283
+ terminal(f"echo {shell_quote(user_input)}")
284
+ """
285
+ return shlex.quote(s)
286
+
287
+
288
+ def retry(fn, max_attempts=3, delay=2):
289
+ """Retry a function up to max_attempts times with exponential backoff.
290
+ Use for transient failures (network errors, API rate limits):
291
+ result = retry(lambda: terminal("gh issue list ..."))
292
+ """
293
+ last_err = None
294
+ for attempt in range(max_attempts):
295
+ try:
296
+ return fn()
297
+ except Exception as e:
298
+ last_err = e
299
+ if attempt < max_attempts - 1:
300
+ time.sleep(delay * (2 ** attempt))
301
+ raise last_err
302
+
303
+ '''
304
+
305
+ # ---- UDS transport (local backend) ---------------------------------------
306
+
307
+ _UDS_TRANSPORT_HEADER = '''\
308
+ """Auto-generated Hermes tools RPC stubs."""
309
+ import json, os, socket, shlex, threading, time
310
+
311
+ _sock = None
312
+ # The RPC server handles a single client connection serially and has no
313
+ # request-id in the protocol, so concurrent _call() invocations from multiple
314
+ # threads (e.g. ThreadPoolExecutor) would race on the shared socket and get
315
+ # each other's responses. Serialize the entire send+recv round-trip.
316
+ _call_lock = threading.Lock()
317
+ ''' + _COMMON_HELPERS + '''\
318
+
319
+ def _connect():
320
+ """Connect to the parent's RPC server via the transport it picked.
321
+
322
+ HERMES_RPC_SOCKET can be either:
323
+ - a filesystem path (POSIX Unix domain socket — the default on
324
+ Linux and macOS)
325
+ - a string of the form ``tcp://127.0.0.1:<port>`` (Windows, where
326
+ AF_UNIX is unreliable — the parent falls back to loopback TCP)
327
+ """
328
+ global _sock
329
+ if _sock is None:
330
+ endpoint = os.environ["HERMES_RPC_SOCKET"]
331
+ if endpoint.startswith("tcp://"):
332
+ # tcp://host:port (host is always 127.0.0.1 in practice — we
333
+ # only bind loopback server-side)
334
+ _host_port = endpoint[len("tcp://"):]
335
+ _host, _, _port = _host_port.rpartition(":")
336
+ _sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
337
+ _sock.connect((_host or "127.0.0.1", int(_port)))
338
+ else:
339
+ _sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
340
+ _sock.connect(endpoint)
341
+ _sock.settimeout(300)
342
+ return _sock
343
+
344
+ def _call(tool_name, args):
345
+ """Send a tool call to the parent process and return the parsed result."""
346
+ request = json.dumps({"tool": tool_name, "args": args}) + "\\n"
347
+ with _call_lock:
348
+ conn = _connect()
349
+ conn.sendall(request.encode())
350
+ buf = b""
351
+ while True:
352
+ chunk = conn.recv(65536)
353
+ if not chunk:
354
+ raise RuntimeError("Agent process disconnected")
355
+ buf += chunk
356
+ if buf.endswith(b"\\n"):
357
+ break
358
+ raw = buf.decode().strip()
359
+ result = json.loads(raw)
360
+ if isinstance(result, str):
361
+ try:
362
+ return json.loads(result)
363
+ except (json.JSONDecodeError, TypeError):
364
+ return result
365
+ return result
366
+
367
+ '''
368
+
369
+ # ---- File-based transport (remote backends) -------------------------------
370
+
371
+ _FILE_TRANSPORT_HEADER = '''\
372
+ """Auto-generated Hermes tools RPC stubs (file-based transport)."""
373
+ import json, os, shlex, tempfile, threading, time
374
+
375
+ _RPC_DIR = os.environ.get("HERMES_RPC_DIR") or os.path.join(tempfile.gettempdir(), "hermes_rpc")
376
+ _seq = 0
377
+ # `_seq += 1` is not atomic (read-modify-write), so concurrent _call()
378
+ # invocations from multiple threads could allocate the same sequence number
379
+ # and clobber each other's request files. Guard seq allocation with a lock.
380
+ _seq_lock = threading.Lock()
381
+ ''' + _COMMON_HELPERS + '''\
382
+
383
+ def _call(tool_name, args):
384
+ """Send a tool call request via file-based RPC and wait for response."""
385
+ global _seq
386
+ with _seq_lock:
387
+ _seq += 1
388
+ seq = _seq
389
+ seq_str = f"{seq:06d}"
390
+ req_file = os.path.join(_RPC_DIR, f"req_{seq_str}")
391
+ res_file = os.path.join(_RPC_DIR, f"res_{seq_str}")
392
+
393
+ # Write request atomically (write to .tmp, then rename).
394
+ # encoding="utf-8" is critical: on Windows-hosted remote backends
395
+ # (or any non-UTF-8 locale) the default open() mode would mangle
396
+ # non-ASCII chars in tool args when encoding them as JSON.
397
+ tmp = req_file + ".tmp"
398
+ with open(tmp, "w", encoding="utf-8") as f:
399
+ json.dump({"tool": tool_name, "args": args, "seq": seq}, f)
400
+ os.rename(tmp, req_file)
401
+
402
+ # Wait for response with adaptive polling
403
+ deadline = time.monotonic() + 300 # 5-minute timeout per tool call
404
+ poll_interval = 0.05 # Start at 50ms
405
+ while not os.path.exists(res_file):
406
+ if time.monotonic() > deadline:
407
+ raise RuntimeError(f"RPC timeout: no response for {tool_name} after 300s")
408
+ time.sleep(poll_interval)
409
+ poll_interval = min(poll_interval * 1.2, 0.25) # Back off to 250ms
410
+
411
+ with open(res_file, encoding="utf-8") as f:
412
+ raw = f.read()
413
+
414
+ # Clean up response file
415
+ try:
416
+ os.unlink(res_file)
417
+ except OSError:
418
+ pass
419
+
420
+ result = json.loads(raw)
421
+ if isinstance(result, str):
422
+ try:
423
+ return json.loads(result)
424
+ except (json.JSONDecodeError, TypeError):
425
+ return result
426
+ return result
427
+
428
+ '''
429
+
430
+
431
+ # ---------------------------------------------------------------------------
432
+ # RPC server (runs in a thread inside the parent process)
433
+ # ---------------------------------------------------------------------------
434
+
435
+ # Terminal parameters that must not be used from ephemeral sandbox scripts
436
+ _TERMINAL_BLOCKED_PARAMS = {"background", "pty", "notify_on_complete", "watch_patterns"}
437
+
438
+
439
+ def _rpc_server_loop(
440
+ server_sock: socket.socket,
441
+ task_id: str,
442
+ tool_call_log: list,
443
+ tool_call_counter: list, # mutable [int] so the thread can increment
444
+ max_tool_calls: int,
445
+ allowed_tools: frozenset,
446
+ ):
447
+ """
448
+ Accept one client connection and dispatch tool-call requests until
449
+ the client disconnects or the call limit is reached.
450
+ """
451
+ from model_tools import handle_function_call
452
+
453
+ conn = None
454
+ try:
455
+ server_sock.settimeout(5)
456
+ conn, _ = server_sock.accept()
457
+ conn.settimeout(300)
458
+
459
+ buf = b""
460
+ while True:
461
+ try:
462
+ chunk = conn.recv(65536)
463
+ except socket.timeout:
464
+ break
465
+ if not chunk:
466
+ break
467
+ buf += chunk
468
+
469
+ # Process all complete newline-delimited messages in the buffer
470
+ while b"\n" in buf:
471
+ line, buf = buf.split(b"\n", 1)
472
+ line = line.strip()
473
+ if not line:
474
+ continue
475
+
476
+ call_start = time.monotonic()
477
+ try:
478
+ request = json.loads(line.decode())
479
+ except (json.JSONDecodeError, UnicodeDecodeError) as exc:
480
+ resp = tool_error(f"Invalid RPC request: {exc}")
481
+ conn.sendall((resp + "\n").encode())
482
+ continue
483
+
484
+ tool_name = request.get("tool", "")
485
+ tool_args = request.get("args", {})
486
+
487
+ # Enforce the allow-list
488
+ if tool_name not in allowed_tools:
489
+ available = ", ".join(sorted(allowed_tools))
490
+ resp = json.dumps({
491
+ "error": (
492
+ f"Tool '{tool_name}' is not available in execute_code. "
493
+ f"Available: {available}"
494
+ )
495
+ })
496
+ conn.sendall((resp + "\n").encode())
497
+ continue
498
+
499
+ # Enforce tool call limit
500
+ if tool_call_counter[0] >= max_tool_calls:
501
+ resp = json.dumps({
502
+ "error": (
503
+ f"Tool call limit reached ({max_tool_calls}). "
504
+ "No more tool calls allowed in this execution."
505
+ )
506
+ })
507
+ conn.sendall((resp + "\n").encode())
508
+ continue
509
+
510
+ # Strip forbidden terminal parameters
511
+ if tool_name == "terminal" and isinstance(tool_args, dict):
512
+ for param in _TERMINAL_BLOCKED_PARAMS:
513
+ tool_args.pop(param, None)
514
+
515
+ # Dispatch through the standard tool handler.
516
+ # Suppress stdout/stderr from internal tool handlers so
517
+ # their status prints don't leak into the CLI spinner.
518
+ try:
519
+ _real_stdout, _real_stderr = sys.stdout, sys.stderr
520
+ devnull = open(os.devnull, "w", encoding="utf-8")
521
+ try:
522
+ sys.stdout = devnull
523
+ sys.stderr = devnull
524
+ result = handle_function_call(
525
+ tool_name, tool_args, task_id=task_id
526
+ )
527
+ finally:
528
+ sys.stdout, sys.stderr = _real_stdout, _real_stderr
529
+ devnull.close()
530
+ except Exception as exc:
531
+ logger.error("Tool call failed in sandbox: %s", exc, exc_info=True)
532
+ result = tool_error(str(exc))
533
+
534
+ tool_call_counter[0] += 1
535
+ call_duration = time.monotonic() - call_start
536
+
537
+ # Log for observability
538
+ args_preview = str(tool_args)[:80]
539
+ tool_call_log.append({
540
+ "tool": tool_name,
541
+ "args_preview": args_preview,
542
+ "duration": round(call_duration, 2),
543
+ })
544
+
545
+ conn.sendall((result + "\n").encode())
546
+
547
+ except socket.timeout:
548
+ logger.debug("RPC listener socket timeout")
549
+ except OSError as e:
550
+ logger.debug("RPC listener socket error: %s", e, exc_info=True)
551
+ finally:
552
+ if conn:
553
+ try:
554
+ conn.close()
555
+ except OSError as e:
556
+ logger.debug("RPC conn close error: %s", e)
557
+
558
+
559
+ # ---------------------------------------------------------------------------
560
+ # Remote execution support (file-based RPC via terminal backend)
561
+ # ---------------------------------------------------------------------------
562
+
563
+ def _get_or_create_env(task_id: str):
564
+ """Get or create the terminal environment for *task_id*.
565
+
566
+ Reuses the same environment (container/sandbox/SSH session) that the
567
+ terminal and file tools use, creating one if it doesn't exist yet.
568
+ Returns ``(env, env_type)`` tuple.
569
+ """
570
+ from tools.terminal_tool import (
571
+ _active_environments, _env_lock, _create_environment,
572
+ _get_env_config, _last_activity, _start_cleanup_thread,
573
+ _creation_locks, _creation_locks_lock, _task_env_overrides,
574
+ _resolve_container_task_id,
575
+ )
576
+
577
+ effective_task_id = _resolve_container_task_id(task_id)
578
+
579
+ # Fast path: environment already exists
580
+ with _env_lock:
581
+ if effective_task_id in _active_environments:
582
+ _last_activity[effective_task_id] = time.time()
583
+ return _active_environments[effective_task_id], _get_env_config()["env_type"]
584
+
585
+ # Slow path: create environment (same pattern as file_tools._get_file_ops)
586
+ with _creation_locks_lock:
587
+ if effective_task_id not in _creation_locks:
588
+ _creation_locks[effective_task_id] = threading.Lock()
589
+ task_lock = _creation_locks[effective_task_id]
590
+
591
+ with task_lock:
592
+ with _env_lock:
593
+ if effective_task_id in _active_environments:
594
+ _last_activity[effective_task_id] = time.time()
595
+ return _active_environments[effective_task_id], _get_env_config()["env_type"]
596
+
597
+ config = _get_env_config()
598
+ env_type = config["env_type"]
599
+ overrides = _task_env_overrides.get(effective_task_id, {})
600
+
601
+ if env_type == "docker":
602
+ image = overrides.get("docker_image") or config["docker_image"]
603
+ elif env_type == "singularity":
604
+ image = overrides.get("singularity_image") or config["singularity_image"]
605
+ elif env_type == "modal":
606
+ image = overrides.get("modal_image") or config["modal_image"]
607
+ elif env_type == "daytona":
608
+ image = overrides.get("daytona_image") or config["daytona_image"]
609
+ else:
610
+ image = ""
611
+
612
+ cwd = overrides.get("cwd") or config["cwd"]
613
+
614
+ container_config = None
615
+ if env_type in {"docker", "singularity", "modal", "daytona", "vercel_sandbox"}:
616
+ container_config = {
617
+ "container_cpu": config.get("container_cpu", 1),
618
+ "container_memory": config.get("container_memory", 5120),
619
+ "container_disk": config.get("container_disk", 51200),
620
+ "container_persistent": config.get("container_persistent", True),
621
+ "vercel_runtime": config.get("vercel_runtime", ""),
622
+ "docker_volumes": config.get("docker_volumes", []),
623
+ "docker_run_as_host_user": config.get("docker_run_as_host_user", False),
624
+ }
625
+
626
+ ssh_config = None
627
+ if env_type == "ssh":
628
+ ssh_config = {
629
+ "host": config.get("ssh_host", ""),
630
+ "user": config.get("ssh_user", ""),
631
+ "port": config.get("ssh_port", 22),
632
+ "key": config.get("ssh_key", ""),
633
+ "persistent": config.get("ssh_persistent", False),
634
+ }
635
+
636
+ local_config = None
637
+ if env_type == "local":
638
+ local_config = {
639
+ "persistent": config.get("local_persistent", False),
640
+ }
641
+
642
+ logger.info("Creating new %s environment for execute_code task %s...",
643
+ env_type, effective_task_id[:8])
644
+ env = _create_environment(
645
+ env_type=env_type,
646
+ image=image,
647
+ cwd=cwd,
648
+ timeout=config["timeout"],
649
+ ssh_config=ssh_config,
650
+ container_config=container_config,
651
+ local_config=local_config,
652
+ task_id=effective_task_id,
653
+ host_cwd=config.get("host_cwd"),
654
+ )
655
+
656
+ with _env_lock:
657
+ _active_environments[effective_task_id] = env
658
+ _last_activity[effective_task_id] = time.time()
659
+
660
+ _start_cleanup_thread()
661
+ logger.info("%s environment ready for execute_code task %s",
662
+ env_type, effective_task_id[:8])
663
+ return env, env_type
664
+
665
+
666
+ def _ship_file_to_remote(env, remote_path: str, content: str) -> None:
667
+ """Write *content* to *remote_path* on the remote environment.
668
+
669
+ Uses ``echo … | base64 -d`` rather than stdin piping because some
670
+ backends (Modal) don't reliably deliver stdin_data to chained
671
+ commands. Base64 output is shell-safe ([A-Za-z0-9+/=]) so single
672
+ quotes are fine.
673
+ """
674
+ encoded = base64.b64encode(content.encode("utf-8")).decode("ascii")
675
+ quoted_remote_path = shlex.quote(remote_path)
676
+ env.execute(
677
+ f"echo '{encoded}' | base64 -d > {quoted_remote_path}",
678
+ cwd="/",
679
+ timeout=30,
680
+ )
681
+
682
+
683
+ def _env_temp_dir(env: Any) -> str:
684
+ """Return a writable temp dir for env-backed execute_code sandboxes."""
685
+ get_temp_dir = getattr(env, "get_temp_dir", None)
686
+ if callable(get_temp_dir):
687
+ try:
688
+ temp_dir = get_temp_dir()
689
+ if isinstance(temp_dir, str) and temp_dir.startswith("/"):
690
+ return temp_dir.rstrip("/") or "/"
691
+ except Exception as exc:
692
+ logger.debug("Could not resolve execute_code env temp dir: %s", exc)
693
+ candidate = tempfile.gettempdir()
694
+ if isinstance(candidate, str) and candidate.startswith("/"):
695
+ return candidate.rstrip("/") or "/"
696
+ return "/tmp"
697
+
698
+
699
+ def _rpc_poll_loop(
700
+ env,
701
+ rpc_dir: str,
702
+ task_id: str,
703
+ tool_call_log: list,
704
+ tool_call_counter: list,
705
+ max_tool_calls: int,
706
+ allowed_tools: frozenset,
707
+ stop_event: threading.Event,
708
+ ):
709
+ """Poll the remote filesystem for tool call requests and dispatch them.
710
+
711
+ Runs in a background thread. Each ``env.execute()`` spawns an
712
+ independent process, so these calls run safely concurrent with the
713
+ script-execution thread.
714
+ """
715
+ from model_tools import handle_function_call
716
+
717
+ poll_interval = 0.1 # 100 ms
718
+
719
+ quoted_rpc_dir = shlex.quote(rpc_dir)
720
+ while not stop_event.is_set():
721
+ try:
722
+ # List pending request files (skip .tmp partials)
723
+ ls_result = env.execute(
724
+ f"ls -1 {quoted_rpc_dir}/req_* 2>/dev/null || true",
725
+ cwd="/",
726
+ timeout=10,
727
+ )
728
+ output = ls_result.get("output", "").strip()
729
+ if not output:
730
+ stop_event.wait(poll_interval)
731
+ continue
732
+
733
+ req_files = sorted([
734
+ f.strip() for f in output.split("\n")
735
+ if f.strip()
736
+ and not f.strip().endswith(".tmp")
737
+ and "/req_" in f.strip()
738
+ ])
739
+
740
+ for req_file in req_files:
741
+ if stop_event.is_set():
742
+ break
743
+
744
+ call_start = time.monotonic()
745
+
746
+ quoted_req_file = shlex.quote(req_file)
747
+ # Read request
748
+ read_result = env.execute(
749
+ f"cat {quoted_req_file}",
750
+ cwd="/",
751
+ timeout=10,
752
+ )
753
+ try:
754
+ request = json.loads(read_result.get("output", ""))
755
+ except (json.JSONDecodeError, ValueError):
756
+ logger.debug("Malformed RPC request in %s", req_file)
757
+ # Remove bad request to avoid infinite retry
758
+ env.execute(f"rm -f {quoted_req_file}", cwd="/", timeout=5)
759
+ continue
760
+
761
+ tool_name = request.get("tool", "")
762
+ tool_args = request.get("args", {})
763
+ seq = request.get("seq", 0)
764
+ seq_str = f"{seq:06d}"
765
+ res_file = f"{rpc_dir}/res_{seq_str}"
766
+ quoted_res_file = shlex.quote(res_file)
767
+
768
+ # Enforce allow-list
769
+ if tool_name not in allowed_tools:
770
+ available = ", ".join(sorted(allowed_tools))
771
+ tool_result = json.dumps({
772
+ "error": (
773
+ f"Tool '{tool_name}' is not available in execute_code. "
774
+ f"Available: {available}"
775
+ )
776
+ })
777
+ # Enforce tool call limit
778
+ elif tool_call_counter[0] >= max_tool_calls:
779
+ tool_result = json.dumps({
780
+ "error": (
781
+ f"Tool call limit reached ({max_tool_calls}). "
782
+ "No more tool calls allowed in this execution."
783
+ )
784
+ })
785
+ else:
786
+ # Strip forbidden terminal parameters
787
+ if tool_name == "terminal" and isinstance(tool_args, dict):
788
+ for param in _TERMINAL_BLOCKED_PARAMS:
789
+ tool_args.pop(param, None)
790
+
791
+ # Dispatch through the standard tool handler
792
+ try:
793
+ _real_stdout, _real_stderr = sys.stdout, sys.stderr
794
+ devnull = open(os.devnull, "w", encoding="utf-8")
795
+ try:
796
+ sys.stdout = devnull
797
+ sys.stderr = devnull
798
+ tool_result = handle_function_call(
799
+ tool_name, tool_args, task_id=task_id
800
+ )
801
+ finally:
802
+ sys.stdout, sys.stderr = _real_stdout, _real_stderr
803
+ devnull.close()
804
+ except Exception as exc:
805
+ logger.error("Tool call failed in remote sandbox: %s",
806
+ exc, exc_info=True)
807
+ tool_result = tool_error(str(exc))
808
+
809
+ tool_call_counter[0] += 1
810
+ call_duration = time.monotonic() - call_start
811
+ tool_call_log.append({
812
+ "tool": tool_name,
813
+ "args_preview": str(tool_args)[:80],
814
+ "duration": round(call_duration, 2),
815
+ })
816
+
817
+ # Write response atomically (tmp + rename).
818
+ # Use echo piping (not stdin_data) because Modal doesn't
819
+ # reliably deliver stdin to chained commands.
820
+ encoded_result = base64.b64encode(
821
+ tool_result.encode("utf-8")
822
+ ).decode("ascii")
823
+ env.execute(
824
+ f"echo '{encoded_result}' | base64 -d > {quoted_res_file}.tmp"
825
+ f" && mv {quoted_res_file}.tmp {quoted_res_file}",
826
+ cwd="/",
827
+ timeout=60,
828
+ )
829
+
830
+ # Remove the request file
831
+ env.execute(f"rm -f {quoted_req_file}", cwd="/", timeout=5)
832
+
833
+ except Exception as e:
834
+ if not stop_event.is_set():
835
+ logger.debug("RPC poll error: %s", e, exc_info=True)
836
+
837
+ if not stop_event.is_set():
838
+ stop_event.wait(poll_interval)
839
+
840
+
841
+ def _execute_remote(
842
+ code: str,
843
+ task_id: Optional[str],
844
+ enabled_tools: Optional[List[str]],
845
+ ) -> str:
846
+ """Run a script on the remote terminal backend via file-based RPC.
847
+
848
+ The script and the generated hermes_tools.py module are shipped to
849
+ the remote environment, and tool calls are proxied through a polling
850
+ thread that communicates via request/response files.
851
+ """
852
+
853
+ _cfg = _load_config()
854
+ timeout = _cfg.get("timeout", DEFAULT_TIMEOUT)
855
+ max_tool_calls = _cfg.get("max_tool_calls", DEFAULT_MAX_TOOL_CALLS)
856
+
857
+ session_tools = set(enabled_tools) if enabled_tools else set()
858
+ sandbox_tools = frozenset(SANDBOX_ALLOWED_TOOLS & session_tools)
859
+ if not sandbox_tools:
860
+ sandbox_tools = SANDBOX_ALLOWED_TOOLS
861
+
862
+ effective_task_id = task_id or "default"
863
+ env, env_type = _get_or_create_env(effective_task_id)
864
+
865
+ sandbox_id = uuid.uuid4().hex[:12]
866
+ temp_dir = _env_temp_dir(env)
867
+ sandbox_dir = f"{temp_dir}/hermes_exec_{sandbox_id}"
868
+ quoted_sandbox_dir = shlex.quote(sandbox_dir)
869
+ quoted_rpc_dir = shlex.quote(f"{sandbox_dir}/rpc")
870
+
871
+ tool_call_log: list = []
872
+ tool_call_counter = [0]
873
+ exec_start = time.monotonic()
874
+ stop_event = threading.Event()
875
+ rpc_thread = None
876
+
877
+ try:
878
+ # Verify Python is available on the remote
879
+ py_check = env.execute(
880
+ "command -v python3 >/dev/null 2>&1 && echo OK",
881
+ cwd="/", timeout=15,
882
+ )
883
+ if "OK" not in py_check.get("output", ""):
884
+ return json.dumps({
885
+ "status": "error",
886
+ "error": (
887
+ f"Python 3 is not available in the {env_type} terminal "
888
+ "environment. Install Python to use execute_code with "
889
+ "remote backends."
890
+ ),
891
+ "tool_calls_made": 0,
892
+ "duration_seconds": 0,
893
+ })
894
+
895
+ # Create sandbox directory on remote
896
+ env.execute(
897
+ f"mkdir -p {quoted_rpc_dir}", cwd="/", timeout=10,
898
+ )
899
+
900
+ # Generate and ship files
901
+ tools_src = generate_hermes_tools_module(
902
+ list(sandbox_tools), transport="file",
903
+ )
904
+ _ship_file_to_remote(env, f"{sandbox_dir}/hermes_tools.py", tools_src)
905
+ _ship_file_to_remote(env, f"{sandbox_dir}/script.py", code)
906
+
907
+ # Start RPC polling thread
908
+ rpc_thread = threading.Thread(
909
+ target=_rpc_poll_loop,
910
+ args=(
911
+ env, f"{sandbox_dir}/rpc", effective_task_id,
912
+ tool_call_log, tool_call_counter, max_tool_calls,
913
+ sandbox_tools, stop_event,
914
+ ),
915
+ daemon=True,
916
+ )
917
+ rpc_thread.start()
918
+
919
+ # Build environment variable prefix for the script
920
+ env_prefix = (
921
+ f"HERMES_RPC_DIR={shlex.quote(f'{sandbox_dir}/rpc')} "
922
+ f"PYTHONDONTWRITEBYTECODE=1"
923
+ )
924
+ tz = os.getenv("HERMES_TIMEZONE", "").strip()
925
+ if tz:
926
+ env_prefix += f" TZ={tz}"
927
+
928
+ # Execute the script on the remote backend
929
+ logger.info("Executing code on %s backend (task %s)...",
930
+ env_type, effective_task_id[:8])
931
+ script_result = env.execute(
932
+ f"cd {quoted_sandbox_dir} && {env_prefix} python3 script.py",
933
+ timeout=timeout,
934
+ )
935
+
936
+ stdout_text = script_result.get("output", "")
937
+ exit_code = script_result.get("returncode", -1)
938
+ status = "success"
939
+
940
+ # Check for timeout/interrupt from the backend
941
+ if exit_code == 124:
942
+ status = "timeout"
943
+ elif exit_code == 130:
944
+ status = "interrupted"
945
+
946
+ except Exception as exc:
947
+ duration = round(time.monotonic() - exec_start, 2)
948
+ logger.error(
949
+ "execute_code remote failed after %ss with %d tool calls: %s: %s",
950
+ duration, tool_call_counter[0], type(exc).__name__, exc,
951
+ exc_info=True,
952
+ )
953
+ return json.dumps({
954
+ "status": "error",
955
+ "error": str(exc),
956
+ "tool_calls_made": tool_call_counter[0],
957
+ "duration_seconds": duration,
958
+ }, ensure_ascii=False)
959
+
960
+ finally:
961
+ # Stop the polling thread
962
+ stop_event.set()
963
+ if rpc_thread is not None:
964
+ rpc_thread.join(timeout=5)
965
+
966
+ # Clean up remote sandbox dir
967
+ try:
968
+ env.execute(
969
+ f"rm -rf {quoted_sandbox_dir}", cwd="/", timeout=15,
970
+ )
971
+ except Exception:
972
+ logger.debug("Failed to clean up remote sandbox %s", sandbox_dir)
973
+
974
+ duration = round(time.monotonic() - exec_start, 2)
975
+
976
+ # --- Post-process output (same as local path) ---
977
+
978
+ # Truncate stdout to cap
979
+ if len(stdout_text) > MAX_STDOUT_BYTES:
980
+ head_bytes = int(MAX_STDOUT_BYTES * 0.4)
981
+ tail_bytes = MAX_STDOUT_BYTES - head_bytes
982
+ head = stdout_text[:head_bytes]
983
+ tail = stdout_text[-tail_bytes:]
984
+ omitted = len(stdout_text) - len(head) - len(tail)
985
+ stdout_text = (
986
+ head
987
+ + f"\n\n... [OUTPUT TRUNCATED - {omitted:,} chars omitted "
988
+ f"out of {len(stdout_text):,} total] ...\n\n"
989
+ + tail
990
+ )
991
+
992
+ # Strip ANSI escape sequences
993
+ from tools.ansi_strip import strip_ansi
994
+ stdout_text = strip_ansi(stdout_text)
995
+
996
+ # Redact secrets
997
+ from agent.redact import redact_sensitive_text
998
+ stdout_text = redact_sensitive_text(stdout_text)
999
+
1000
+ # Build response
1001
+ result: Dict[str, Any] = {
1002
+ "status": status,
1003
+ "output": stdout_text,
1004
+ "tool_calls_made": tool_call_counter[0],
1005
+ "duration_seconds": duration,
1006
+ }
1007
+
1008
+ if status == "timeout":
1009
+ timeout_msg = f"Script timed out after {timeout}s and was killed."
1010
+ result["error"] = timeout_msg
1011
+ # Include timeout message in output so the LLM always surfaces it
1012
+ # to the user (see local path comment — same reasoning, #10807).
1013
+ if stdout_text:
1014
+ result["output"] = stdout_text + f"\n\n⏰ {timeout_msg}"
1015
+ else:
1016
+ result["output"] = f"⏰ {timeout_msg}"
1017
+ logger.warning(
1018
+ "execute_code (remote) timed out after %ss (limit %ss) with %d tool calls",
1019
+ duration, timeout, tool_call_counter[0],
1020
+ )
1021
+ elif status == "interrupted":
1022
+ result["output"] = (
1023
+ stdout_text + "\n[execution interrupted — user sent a new message]"
1024
+ )
1025
+ elif exit_code != 0:
1026
+ result["status"] = "error"
1027
+ result["error"] = f"Script exited with code {exit_code}"
1028
+
1029
+ return json.dumps(result, ensure_ascii=False)
1030
+
1031
+
1032
+ # ---------------------------------------------------------------------------
1033
+ # Main entry point
1034
+ # ---------------------------------------------------------------------------
1035
+
1036
+ def execute_code(
1037
+ code: str,
1038
+ task_id: Optional[str] = None,
1039
+ enabled_tools: Optional[List[str]] = None,
1040
+ ) -> str:
1041
+ """
1042
+ Run a Python script in a sandboxed child process with RPC access
1043
+ to a subset of Hermes tools.
1044
+
1045
+ Dispatches to the local (UDS) or remote (file-based RPC) path
1046
+ depending on the configured terminal backend.
1047
+
1048
+ Args:
1049
+ code: Python source code to execute.
1050
+ task_id: Session task ID for tool isolation (terminal env, etc.).
1051
+ enabled_tools: Tool names enabled in the current session. The sandbox
1052
+ gets the intersection with SANDBOX_ALLOWED_TOOLS.
1053
+
1054
+ Returns:
1055
+ JSON string with execution results.
1056
+ """
1057
+ if not SANDBOX_AVAILABLE:
1058
+ return json.dumps({
1059
+ "error": "execute_code sandbox is unavailable in this environment. "
1060
+ "Use normal tool calls (terminal, read_file, write_file, ...) instead."
1061
+ })
1062
+
1063
+ if not code or not code.strip():
1064
+ return tool_error("No code provided.")
1065
+
1066
+ # Dispatch: remote backends use file-based RPC, local uses UDS
1067
+ from tools.terminal_tool import _get_env_config
1068
+ env_type = _get_env_config()["env_type"]
1069
+ if env_type != "local":
1070
+ return _execute_remote(code, task_id, enabled_tools)
1071
+
1072
+ # --- Local execution path (UDS) --- below this line is unchanged ---
1073
+
1074
+ # Import per-thread interrupt check (cooperative cancellation)
1075
+ from tools.interrupt import is_interrupted as _is_interrupted
1076
+
1077
+ # Resolve config
1078
+ _cfg = _load_config()
1079
+ timeout = _cfg.get("timeout", DEFAULT_TIMEOUT)
1080
+ max_tool_calls = _cfg.get("max_tool_calls", DEFAULT_MAX_TOOL_CALLS)
1081
+
1082
+ # Determine which tools the sandbox can call
1083
+ session_tools = set(enabled_tools) if enabled_tools else set()
1084
+ sandbox_tools = frozenset(SANDBOX_ALLOWED_TOOLS & session_tools)
1085
+
1086
+ if not sandbox_tools:
1087
+ sandbox_tools = SANDBOX_ALLOWED_TOOLS
1088
+
1089
+ # --- Set up temp directory with hermes_tools.py and script.py ---
1090
+ tmpdir = tempfile.mkdtemp(prefix="hermes_sandbox_")
1091
+ # Use /tmp on macOS to avoid the long /var/folders/... path that pushes
1092
+ # Unix domain socket paths past the 104-byte macOS AF_UNIX limit.
1093
+ # On Linux, tempfile.gettempdir() already returns /tmp.
1094
+ #
1095
+ # Windows: Python 3.9+ added partial AF_UNIX support but the file-backed
1096
+ # variant is flaky across Windows builds (requires Windows 10 1803+,
1097
+ # still fails under some configurations, and the socket file can't live
1098
+ # on the same temp drive as the script). Fall back to loopback TCP —
1099
+ # same ephemeral port, same 1-connection listen queue, same serialized
1100
+ # request/response framing. The generated client reads the transport
1101
+ # selector from HERMES_RPC_SOCKET (path vs. ``tcp://host:port``).
1102
+ _sock_tmpdir = "/tmp" if sys.platform == "darwin" else tempfile.gettempdir()
1103
+ _use_tcp_rpc = _IS_WINDOWS
1104
+ if _use_tcp_rpc:
1105
+ sock_path = None # not used on Windows; TCP endpoint stored below
1106
+ rpc_endpoint = None # set after bind()
1107
+ else:
1108
+ sock_path = os.path.join(_sock_tmpdir, f"hermes_rpc_{uuid.uuid4().hex}.sock")
1109
+ rpc_endpoint = sock_path
1110
+
1111
+ tool_call_log: list = []
1112
+ tool_call_counter = [0] # mutable so the RPC thread can increment
1113
+ exec_start = time.monotonic()
1114
+ server_sock = None
1115
+
1116
+ try:
1117
+ # Write the auto-generated hermes_tools module.
1118
+ # encoding="utf-8" is required on Windows — the stub and user code
1119
+ # both contain non-ASCII characters (em-dashes in docstrings, plus
1120
+ # whatever the user script carries). Python's default open() uses
1121
+ # the system locale on Windows (cp1252 typically), which corrupts
1122
+ # those bytes; the child then fails to import with a SyntaxError
1123
+ # ("'utf-8' codec can't decode byte 0x97 in position ...") because
1124
+ # Python source files are decoded as UTF-8 by default (PEP 3120).
1125
+ # sandbox_tools is already the correct set (intersection with session
1126
+ # tools, or SANDBOX_ALLOWED_TOOLS as fallback — see lines above).
1127
+ tools_src = generate_hermes_tools_module(list(sandbox_tools))
1128
+ with open(os.path.join(tmpdir, "hermes_tools.py"), "w", encoding="utf-8") as f:
1129
+ f.write(tools_src)
1130
+
1131
+ # Write the user's script
1132
+ with open(os.path.join(tmpdir, "script.py"), "w", encoding="utf-8") as f:
1133
+ f.write(code)
1134
+
1135
+ # --- Start RPC server ---
1136
+ # Two transports:
1137
+ # POSIX: AF_UNIX stream socket on sock_path, chmod 0600 for
1138
+ # owner-only access. Filesystem permissions gate the socket.
1139
+ # Windows: AF_INET stream socket on 127.0.0.1 with an ephemeral
1140
+ # port. No filesystem permission story, but loopback-only bind
1141
+ # means only the current user's processes (not remote) can
1142
+ # connect. HERMES_RPC_SOCKET is set to ``tcp://127.0.0.1:<port>``
1143
+ # which the generated client parses to pick AF_INET.
1144
+ if _use_tcp_rpc:
1145
+ server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1146
+ server_sock.bind(("127.0.0.1", 0)) # ephemeral port
1147
+ _host, _port = server_sock.getsockname()[:2]
1148
+ rpc_endpoint = f"tcp://{_host}:{_port}"
1149
+ else:
1150
+ server_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1151
+ server_sock.bind(sock_path)
1152
+ os.chmod(sock_path, 0o600)
1153
+ server_sock.listen(1)
1154
+
1155
+ rpc_thread = threading.Thread(
1156
+ target=_rpc_server_loop,
1157
+ args=(
1158
+ server_sock, task_id, tool_call_log,
1159
+ tool_call_counter, max_tool_calls, sandbox_tools,
1160
+ ),
1161
+ daemon=True,
1162
+ )
1163
+ rpc_thread.start()
1164
+
1165
+ # --- Spawn child process ---
1166
+ # Build a minimal environment for the child. We intentionally exclude
1167
+ # API keys and tokens to prevent credential exfiltration from LLM-
1168
+ # generated scripts. The child accesses tools via RPC, not direct API.
1169
+ # Exception: env vars declared by loaded skills (via env_passthrough
1170
+ # registry) or explicitly allowed by the user in config.yaml
1171
+ # (terminal.env_passthrough) are passed through. On Windows, a small
1172
+ # OS-essential allowlist (SYSTEMROOT, WINDIR, COMSPEC, ...) is also
1173
+ # passed through — without those, the child can't create a socket
1174
+ # or spawn a subprocess. See ``_scrub_child_env`` for the rules.
1175
+ child_env = _scrub_child_env(os.environ)
1176
+ child_env["HERMES_RPC_SOCKET"] = rpc_endpoint
1177
+ child_env["PYTHONDONTWRITEBYTECODE"] = "1"
1178
+ # Force UTF-8 for the child's stdio and default file encoding.
1179
+ #
1180
+ # Without this, on Windows sys.stdout is bound to the console code
1181
+ # page (cp1252 on US-locale installs), and any script that does
1182
+ # ``print("café")`` or ``print("→")`` crashes with:
1183
+ #
1184
+ # UnicodeEncodeError: 'charmap' codec can't encode character
1185
+ # '\u2192' in position N: character maps to <undefined>
1186
+ #
1187
+ # PYTHONIOENCODING fixes sys.stdin/stdout/stderr.
1188
+ # PYTHONUTF8=1 enables "UTF-8 mode" (PEP 540) which additionally
1189
+ # makes ``open()``'s default encoding UTF-8, so user scripts that
1190
+ # write files without specifying encoding= also work correctly.
1191
+ #
1192
+ # On POSIX both values usually match the locale default already,
1193
+ # so setting them is harmless belt-and-suspenders for environments
1194
+ # with a C/POSIX locale (containers, minimal base images).
1195
+ child_env["PYTHONIOENCODING"] = "utf-8"
1196
+ child_env["PYTHONUTF8"] = "1"
1197
+ # Ensure the hermes-agent root is importable in the sandbox so
1198
+ # repo-root modules are available to child scripts. We also prepend
1199
+ # the staging tmpdir so ``from hermes_tools import ...`` resolves even
1200
+ # when the subprocess CWD is not tmpdir (project mode).
1201
+ _hermes_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1202
+ _existing_pp = child_env.get("PYTHONPATH", "")
1203
+ _pp_parts = [tmpdir, _hermes_root]
1204
+ if _existing_pp:
1205
+ _pp_parts.append(_existing_pp)
1206
+ child_env["PYTHONPATH"] = os.pathsep.join(_pp_parts)
1207
+ # Inject user's configured timezone so datetime.now() in sandboxed
1208
+ # code reflects the correct wall-clock time. Only TZ is set —
1209
+ # HERMES_TIMEZONE is an internal Hermes setting and must not leak
1210
+ # into child processes.
1211
+ _tz_name = os.getenv("HERMES_TIMEZONE", "").strip()
1212
+ if _tz_name:
1213
+ child_env["TZ"] = _tz_name
1214
+ child_env.pop("HERMES_TIMEZONE", None)
1215
+
1216
+ # Per-profile HOME isolation: redirect system tool configs into
1217
+ # {HERMES_HOME}/home/ when that directory exists.
1218
+ from calvyn_constants import get_subprocess_home
1219
+ _profile_home = get_subprocess_home()
1220
+ if _profile_home:
1221
+ child_env["HOME"] = _profile_home
1222
+
1223
+ # Resolve interpreter + CWD based on execute_code mode.
1224
+ # - strict : today's behavior (sys.executable + tmpdir CWD).
1225
+ # - project: user's venv python + session's working directory, so
1226
+ # project deps like pandas and user files resolve.
1227
+ # Env scrubbing and tool whitelist apply identically in both modes.
1228
+ _mode = _get_execution_mode()
1229
+ _child_python = _resolve_child_python(_mode)
1230
+ _child_cwd = _resolve_child_cwd(_mode, tmpdir)
1231
+ _script_path = os.path.join(tmpdir, "script.py")
1232
+
1233
+ proc = subprocess.Popen(
1234
+ [_child_python, _script_path],
1235
+ cwd=_child_cwd,
1236
+ env=child_env,
1237
+ stdout=subprocess.PIPE,
1238
+ stderr=subprocess.PIPE,
1239
+ stdin=subprocess.DEVNULL,
1240
+ preexec_fn=None if _IS_WINDOWS else os.setsid,
1241
+ )
1242
+
1243
+ # --- Poll loop: watch for exit, timeout, and interrupt ---
1244
+ deadline = time.monotonic() + timeout
1245
+ stderr_chunks: list = []
1246
+
1247
+ # Background readers to avoid pipe buffer deadlocks.
1248
+ # For stdout we use a head+tail strategy: keep the first HEAD_BYTES
1249
+ # and a rolling window of the last TAIL_BYTES so the final print()
1250
+ # output is never lost. Stderr keeps head-only (errors appear early).
1251
+ _STDOUT_HEAD_BYTES = int(MAX_STDOUT_BYTES * 0.4) # 40% head
1252
+ _STDOUT_TAIL_BYTES = MAX_STDOUT_BYTES - _STDOUT_HEAD_BYTES # 60% tail
1253
+
1254
+ def _drain(pipe, chunks, max_bytes):
1255
+ """Simple head-only drain (used for stderr)."""
1256
+ total = 0
1257
+ try:
1258
+ while True:
1259
+ data = pipe.read(4096)
1260
+ if not data:
1261
+ break
1262
+ if total < max_bytes:
1263
+ keep = max_bytes - total
1264
+ chunks.append(data[:keep])
1265
+ total += len(data)
1266
+ except (ValueError, OSError) as e:
1267
+ logger.debug("Error reading process output: %s", e, exc_info=True)
1268
+
1269
+ stdout_total_bytes = [0] # mutable ref for total bytes seen
1270
+
1271
+ def _drain_head_tail(pipe, head_chunks, tail_chunks, head_bytes, tail_bytes, total_ref):
1272
+ """Drain stdout keeping both head and tail data."""
1273
+ head_collected = 0
1274
+ from collections import deque
1275
+ tail_buf = deque()
1276
+ tail_collected = 0
1277
+ try:
1278
+ while True:
1279
+ data = pipe.read(4096)
1280
+ if not data:
1281
+ break
1282
+ total_ref[0] += len(data)
1283
+ # Fill head buffer first
1284
+ if head_collected < head_bytes:
1285
+ keep = min(len(data), head_bytes - head_collected)
1286
+ head_chunks.append(data[:keep])
1287
+ head_collected += keep
1288
+ data = data[keep:] # remaining goes to tail
1289
+ if not data:
1290
+ continue
1291
+ # Everything past head goes into rolling tail buffer
1292
+ tail_buf.append(data)
1293
+ tail_collected += len(data)
1294
+ # Evict old tail data to stay within tail_bytes budget
1295
+ while tail_collected > tail_bytes and tail_buf:
1296
+ oldest = tail_buf.popleft()
1297
+ tail_collected -= len(oldest)
1298
+ except (ValueError, OSError):
1299
+ pass
1300
+ # Transfer final tail to output list
1301
+ tail_chunks.extend(tail_buf)
1302
+
1303
+ stdout_head_chunks: list = []
1304
+ stdout_tail_chunks: list = []
1305
+
1306
+ stdout_reader = threading.Thread(
1307
+ target=_drain_head_tail,
1308
+ args=(proc.stdout, stdout_head_chunks, stdout_tail_chunks,
1309
+ _STDOUT_HEAD_BYTES, _STDOUT_TAIL_BYTES, stdout_total_bytes),
1310
+ daemon=True
1311
+ )
1312
+ stderr_reader = threading.Thread(
1313
+ target=_drain, args=(proc.stderr, stderr_chunks, MAX_STDERR_BYTES), daemon=True
1314
+ )
1315
+ stdout_reader.start()
1316
+ stderr_reader.start()
1317
+
1318
+ status = "success"
1319
+ _activity_state = {
1320
+ "last_touch": time.monotonic(),
1321
+ "start": exec_start,
1322
+ }
1323
+ while proc.poll() is None:
1324
+ if _is_interrupted():
1325
+ _kill_process_group(proc)
1326
+ status = "interrupted"
1327
+ break
1328
+ if time.monotonic() > deadline:
1329
+ _kill_process_group(proc, escalate=True)
1330
+ status = "timeout"
1331
+ break
1332
+ # Periodic activity touch so the gateway's inactivity timeout
1333
+ # doesn't kill the agent during long code execution (#10807).
1334
+ try:
1335
+ from tools.environments.base import touch_activity_if_due
1336
+ touch_activity_if_due(_activity_state, "execute_code running")
1337
+ except Exception:
1338
+ pass
1339
+ time.sleep(0.2)
1340
+
1341
+ # Wait for readers to finish draining
1342
+ stdout_reader.join(timeout=3)
1343
+ stderr_reader.join(timeout=3)
1344
+
1345
+ stdout_head = b"".join(stdout_head_chunks).decode("utf-8", errors="replace")
1346
+ stdout_tail = b"".join(stdout_tail_chunks).decode("utf-8", errors="replace")
1347
+ stderr_text = b"".join(stderr_chunks).decode("utf-8", errors="replace")
1348
+
1349
+ # Assemble stdout with head+tail truncation
1350
+ total_stdout = stdout_total_bytes[0]
1351
+ if total_stdout > MAX_STDOUT_BYTES and stdout_tail:
1352
+ omitted = total_stdout - len(stdout_head) - len(stdout_tail)
1353
+ truncated_notice = (
1354
+ f"\n\n... [OUTPUT TRUNCATED - {omitted:,} chars omitted "
1355
+ f"out of {total_stdout:,} total] ...\n\n"
1356
+ )
1357
+ stdout_text = stdout_head + truncated_notice + stdout_tail
1358
+ else:
1359
+ stdout_text = stdout_head + stdout_tail
1360
+
1361
+ exit_code = proc.returncode if proc.returncode is not None else -1
1362
+ duration = round(time.monotonic() - exec_start, 2)
1363
+
1364
+ # Wait for RPC thread to finish
1365
+ server_sock.close() # break accept() so thread exits promptly
1366
+ server_sock = None # prevent double close in finally
1367
+ rpc_thread.join(timeout=3)
1368
+
1369
+ # Strip ANSI escape sequences so the model never sees terminal
1370
+ # formatting — prevents it from copying escapes into file writes.
1371
+ from tools.ansi_strip import strip_ansi
1372
+ stdout_text = strip_ansi(stdout_text)
1373
+ stderr_text = strip_ansi(stderr_text)
1374
+
1375
+ # Redact secrets (API keys, tokens, etc.) from sandbox output.
1376
+ # The sandbox env-var filter (lines 434-454) blocks os.environ access,
1377
+ # but scripts can still read secrets from disk (e.g. open('~/.hermes/.env')).
1378
+ # This ensures leaked secrets never enter the model context.
1379
+ from agent.redact import redact_sensitive_text
1380
+ stdout_text = redact_sensitive_text(stdout_text)
1381
+ stderr_text = redact_sensitive_text(stderr_text)
1382
+
1383
+ # Build response
1384
+ result: Dict[str, Any] = {
1385
+ "status": status,
1386
+ "output": stdout_text,
1387
+ "tool_calls_made": tool_call_counter[0],
1388
+ "duration_seconds": duration,
1389
+ }
1390
+
1391
+ if status == "timeout":
1392
+ timeout_msg = f"Script timed out after {timeout}s and was killed."
1393
+ result["error"] = timeout_msg
1394
+ # Include timeout message in output so the LLM always surfaces it
1395
+ # to the user. When output is empty, models often treat the result
1396
+ # as "nothing happened" and produce an empty response, which the
1397
+ # gateway stream consumer silently drops (#10807).
1398
+ if stdout_text:
1399
+ result["output"] = stdout_text + f"\n\n⏰ {timeout_msg}"
1400
+ else:
1401
+ result["output"] = f"⏰ {timeout_msg}"
1402
+ logger.warning(
1403
+ "execute_code timed out after %ss (limit %ss) with %d tool calls",
1404
+ duration, timeout, tool_call_counter[0],
1405
+ )
1406
+ elif status == "interrupted":
1407
+ result["output"] = stdout_text + "\n[execution interrupted — user sent a new message]"
1408
+ elif exit_code != 0:
1409
+ result["status"] = "error"
1410
+ result["error"] = stderr_text or f"Script exited with code {exit_code}"
1411
+ # Include stderr in output so the LLM sees the traceback
1412
+ if stderr_text:
1413
+ result["output"] = stdout_text + "\n--- stderr ---\n" + stderr_text
1414
+
1415
+ return json.dumps(result, ensure_ascii=False)
1416
+
1417
+ except Exception as exc:
1418
+ duration = round(time.monotonic() - exec_start, 2)
1419
+ logger.error(
1420
+ "execute_code failed after %ss with %d tool calls: %s: %s",
1421
+ duration,
1422
+ tool_call_counter[0],
1423
+ type(exc).__name__,
1424
+ exc,
1425
+ exc_info=True,
1426
+ )
1427
+ return json.dumps({
1428
+ "status": "error",
1429
+ "error": str(exc),
1430
+ "tool_calls_made": tool_call_counter[0],
1431
+ "duration_seconds": duration,
1432
+ }, ensure_ascii=False)
1433
+
1434
+ finally:
1435
+ # Cleanup temp dir and socket
1436
+ if server_sock is not None:
1437
+ try:
1438
+ server_sock.close()
1439
+ except OSError as e:
1440
+ logger.debug("Server socket close error: %s", e)
1441
+ import shutil
1442
+ shutil.rmtree(tmpdir, ignore_errors=True)
1443
+ try:
1444
+ # Only UDS has a filesystem socket to unlink; TCP sockets are
1445
+ # freed by server_sock.close() above.
1446
+ if sock_path:
1447
+ os.unlink(sock_path)
1448
+ except OSError:
1449
+ pass # already cleaned up or never created
1450
+
1451
+
1452
+ def _kill_process_group(proc, escalate: bool = False):
1453
+ """Kill the child and its entire process tree (cross-platform via psutil)."""
1454
+ import psutil
1455
+ try:
1456
+ parent = psutil.Process(proc.pid)
1457
+ children = parent.children(recursive=True)
1458
+ for child in children:
1459
+ try:
1460
+ child.terminate()
1461
+ except psutil.NoSuchProcess:
1462
+ pass
1463
+ try:
1464
+ parent.terminate()
1465
+ except psutil.NoSuchProcess:
1466
+ pass
1467
+ except psutil.NoSuchProcess:
1468
+ pass
1469
+ except (PermissionError, OSError) as e:
1470
+ logger.debug("Could not terminate process tree: %s", e, exc_info=True)
1471
+ try:
1472
+ proc.kill()
1473
+ except Exception as e2:
1474
+ logger.debug("Could not kill process: %s", e2, exc_info=True)
1475
+
1476
+ if escalate:
1477
+ # Give the process 5s to exit after SIGTERM, then SIGKILL
1478
+ try:
1479
+ proc.wait(timeout=5)
1480
+ except subprocess.TimeoutExpired:
1481
+ try:
1482
+ parent = psutil.Process(proc.pid)
1483
+ for child in parent.children(recursive=True):
1484
+ try:
1485
+ child.kill()
1486
+ except psutil.NoSuchProcess:
1487
+ pass
1488
+ try:
1489
+ parent.kill()
1490
+ except psutil.NoSuchProcess:
1491
+ pass
1492
+ except psutil.NoSuchProcess:
1493
+ pass
1494
+ except (PermissionError, OSError) as e:
1495
+ logger.debug("Could not kill process tree: %s", e, exc_info=True)
1496
+ try:
1497
+ proc.kill()
1498
+ except Exception as e2:
1499
+ logger.debug("Could not kill process: %s", e2, exc_info=True)
1500
+
1501
+
1502
+ def _load_config() -> dict:
1503
+ """Load code_execution config without importing the interactive CLI.
1504
+
1505
+ This helper is called while building the module-level execute_code schema
1506
+ during tool discovery. Importing ``cli`` here pulls prompt_toolkit/Rich and
1507
+ a large chunk of the classic REPL onto every agent startup path, including
1508
+ ``hermes --tui`` where it is never used. Read the lightweight raw config
1509
+ instead; the config layer already caches by (mtime, size), and an absent
1510
+ key cleanly falls back to DEFAULT_EXECUTION_MODE.
1511
+ """
1512
+ try:
1513
+ from hermes_cli.config import read_raw_config
1514
+
1515
+ cfg = read_raw_config().get("code_execution", {})
1516
+ return cfg if isinstance(cfg, dict) else {}
1517
+ except Exception:
1518
+ return {}
1519
+
1520
+
1521
+ # ---------------------------------------------------------------------------
1522
+ # Execution mode resolution (strict vs project)
1523
+ # ---------------------------------------------------------------------------
1524
+
1525
+ # Valid values for code_execution.mode. Kept as a module constant so tests
1526
+ # and the config layer can reference the canonical set.
1527
+ EXECUTION_MODES = ("project", "strict")
1528
+ DEFAULT_EXECUTION_MODE = "project"
1529
+
1530
+
1531
+ def _get_execution_mode() -> str:
1532
+ """Return the active execute_code mode — 'project' or 'strict'.
1533
+
1534
+ Reads ``code_execution.mode`` from config.yaml; invalid values fall back
1535
+ to ``DEFAULT_EXECUTION_MODE`` ('project') with a log warning.
1536
+
1537
+ Mode semantics:
1538
+ - ``project`` (default): scripts run in the session's working directory
1539
+ with the active virtual environment's python, so project dependencies
1540
+ (pandas, torch, project packages) and files resolve naturally.
1541
+ - ``strict``: scripts run in an isolated temp directory with
1542
+ ``sys.executable`` (hermes-agent's python). Reproducible and the
1543
+ interpreter is guaranteed to work, but project deps and relative paths
1544
+ won't resolve.
1545
+
1546
+ Env scrubbing and tool whitelist apply identically in both modes.
1547
+ """
1548
+ cfg_value = str(_load_config().get("mode", DEFAULT_EXECUTION_MODE)).strip().lower()
1549
+ if cfg_value in EXECUTION_MODES:
1550
+ return cfg_value
1551
+ logger.warning(
1552
+ "Ignoring code_execution.mode=%r (expected one of %s), falling back to %r",
1553
+ cfg_value, EXECUTION_MODES, DEFAULT_EXECUTION_MODE,
1554
+ )
1555
+ return DEFAULT_EXECUTION_MODE
1556
+
1557
+
1558
+ @functools.lru_cache(maxsize=32)
1559
+ def _is_usable_python(python_path: str) -> bool:
1560
+ """Check whether a candidate Python interpreter is usable for execute_code.
1561
+
1562
+ Requires Python 3.8+ (f-strings and stdlib modules the RPC stubs need).
1563
+ Cached so we don't fork a subprocess on every execute_code call.
1564
+ """
1565
+ try:
1566
+ result = subprocess.run(
1567
+ [python_path, "-c",
1568
+ "import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)"],
1569
+ timeout=5,
1570
+ capture_output=True,
1571
+ )
1572
+ return result.returncode == 0
1573
+ except (OSError, subprocess.TimeoutExpired, subprocess.SubprocessError):
1574
+ return False
1575
+
1576
+
1577
+ def _resolve_child_python(mode: str) -> str:
1578
+ """Pick the Python interpreter for the execute_code subprocess.
1579
+
1580
+ In ``strict`` mode, always ``sys.executable`` — guaranteed to work and
1581
+ keeps behavior fully reproducible across sessions.
1582
+
1583
+ In ``project`` mode, prefer the user's active virtualenv/conda env's
1584
+ python so ``import pandas`` etc. work. Falls back to ``sys.executable``
1585
+ if no venv is detected, the candidate binary is missing/not executable,
1586
+ or it fails a Python 3.8+ version check.
1587
+ """
1588
+ if mode != "project":
1589
+ return sys.executable
1590
+
1591
+ if _IS_WINDOWS:
1592
+ exe_names = ("python.exe", "python3.exe")
1593
+ subdirs = ("Scripts",)
1594
+ else:
1595
+ exe_names = ("python", "python3")
1596
+ subdirs = ("bin",)
1597
+
1598
+ for var in ("VIRTUAL_ENV", "CONDA_PREFIX"):
1599
+ root = os.environ.get(var, "").strip()
1600
+ if not root:
1601
+ continue
1602
+ for subdir in subdirs:
1603
+ for exe in exe_names:
1604
+ candidate = os.path.join(root, subdir, exe)
1605
+ if not (os.path.isfile(candidate) and os.access(candidate, os.X_OK)):
1606
+ continue
1607
+ if _is_usable_python(candidate):
1608
+ return candidate
1609
+ # Found the interpreter but it failed the version check —
1610
+ # log once and fall through to sys.executable.
1611
+ logger.info(
1612
+ "execute_code: skipping %s=%s (Python version < 3.8 or broken). "
1613
+ "Using sys.executable instead.", var, candidate,
1614
+ )
1615
+ return sys.executable
1616
+
1617
+ return sys.executable
1618
+
1619
+
1620
+ def _resolve_child_cwd(mode: str, staging_dir: str) -> str:
1621
+ """Resolve the working directory for the execute_code subprocess.
1622
+
1623
+ - ``strict``: the staging tmpdir (today's behavior).
1624
+ - ``project``: the session's TERMINAL_CWD (same as the terminal tool), or
1625
+ ``os.getcwd()`` if TERMINAL_CWD is unset or doesn't point at a real dir.
1626
+ Falls back to the staging tmpdir as a last resort so we never invoke
1627
+ Popen with a nonexistent cwd.
1628
+ """
1629
+ if mode != "project":
1630
+ return staging_dir
1631
+ raw = os.environ.get("TERMINAL_CWD", "").strip()
1632
+ if raw:
1633
+ expanded = os.path.expanduser(raw)
1634
+ if os.path.isdir(expanded):
1635
+ return expanded
1636
+ here = os.getcwd()
1637
+ if os.path.isdir(here):
1638
+ return here
1639
+ return staging_dir
1640
+
1641
+
1642
+ # ---------------------------------------------------------------------------
1643
+ # OpenAI Function-Calling Schema
1644
+ # ---------------------------------------------------------------------------
1645
+
1646
+ # Per-tool documentation lines for the execute_code description.
1647
+ # Ordered to match the canonical display order.
1648
+ _TOOL_DOC_LINES = [
1649
+ ("web_search",
1650
+ " web_search(query: str, limit: int = 5) -> dict\n"
1651
+ " Returns {\"data\": {\"web\": [{\"url\", \"title\", \"description\"}, ...]}}"),
1652
+ ("web_extract",
1653
+ " web_extract(urls: list[str]) -> dict\n"
1654
+ " Returns {\"results\": [{\"url\", \"title\", \"content\", \"error\"}, ...]} where content is markdown"),
1655
+ ("read_file",
1656
+ " read_file(path: str, offset: int = 1, limit: int = 500) -> dict\n"
1657
+ " Lines are 1-indexed. Returns {\"content\": \"...\", \"total_lines\": N}"),
1658
+ ("write_file",
1659
+ " write_file(path: str, content: str) -> dict\n"
1660
+ " Always overwrites the entire file."),
1661
+ ("search_files",
1662
+ " search_files(pattern: str, target=\"content\", path=\".\", file_glob=None, limit=50) -> dict\n"
1663
+ " target: \"content\" (search inside files) or \"files\" (find files by name). Returns {\"matches\": [...]}"),
1664
+ ("patch",
1665
+ " patch(path: str, old_string: str, new_string: str, replace_all: bool = False) -> dict\n"
1666
+ " Replaces old_string with new_string in the file."),
1667
+ ("terminal",
1668
+ " terminal(command: str, timeout=None, workdir=None) -> dict\n"
1669
+ " Foreground only (no background/pty). Returns {\"output\": \"...\", \"exit_code\": N}"),
1670
+ ]
1671
+
1672
+
1673
+ def build_execute_code_schema(enabled_sandbox_tools: set = None,
1674
+ mode: str = None) -> dict:
1675
+ """Build the execute_code schema with description listing only enabled tools.
1676
+
1677
+ When tools are disabled via ``hermes tools`` (e.g. web is turned off),
1678
+ the schema description should NOT mention web_search / web_extract —
1679
+ otherwise the model thinks they are available and keeps trying to use them.
1680
+
1681
+ ``mode`` controls the working-directory sentence in the description:
1682
+ - ``'strict'``: scripts run in a temp dir (not the session's CWD)
1683
+ - ``'project'`` (default): scripts run in the session's CWD with the
1684
+ active venv's python
1685
+ If ``mode`` is None, the current ``code_execution.mode`` config is read.
1686
+ """
1687
+ if enabled_sandbox_tools is None:
1688
+ enabled_sandbox_tools = SANDBOX_ALLOWED_TOOLS
1689
+ if mode is None:
1690
+ mode = _get_execution_mode()
1691
+
1692
+ # Build tool documentation lines for only the enabled tools
1693
+ tool_lines = "\n".join(
1694
+ doc for name, doc in _TOOL_DOC_LINES if name in enabled_sandbox_tools
1695
+ )
1696
+
1697
+ # Build example import list from enabled tools
1698
+ import_examples = [n for n in ("web_search", "terminal") if n in enabled_sandbox_tools]
1699
+ if not import_examples:
1700
+ import_examples = sorted(enabled_sandbox_tools)[:2]
1701
+ if import_examples:
1702
+ import_str = ", ".join(import_examples) + ", ..."
1703
+ else:
1704
+ import_str = "..."
1705
+
1706
+ # Mode-specific CWD guidance. Project mode is the default and matches
1707
+ # terminal()'s filesystem/interpreter; strict mode retains the isolated
1708
+ # temp-dir staging and hermes-agent's own python.
1709
+ if mode == "strict":
1710
+ cwd_note = (
1711
+ "Scripts run in their own temp dir, not the session's CWD — use absolute paths "
1712
+ "(os.path.expanduser('~/.hermes/.env')) or terminal()/read_file() for user files."
1713
+ )
1714
+ else:
1715
+ cwd_note = (
1716
+ "Scripts run in the session's working directory with the active venv's python, "
1717
+ "so project deps (pandas, etc.) and relative paths work like in terminal()."
1718
+ )
1719
+
1720
+ description = (
1721
+ "Run a Python script that can call Hermes tools programmatically. "
1722
+ "Use this when you need 3+ tool calls with processing logic between them, "
1723
+ "need to filter/reduce large tool outputs before they enter your context, "
1724
+ "need conditional branching (if X then Y else Z), or need to loop "
1725
+ "(fetch N pages, process N files, retry on failure).\n\n"
1726
+ "Use normal tool calls instead when: single tool call with no processing, "
1727
+ "you need to see the full result and apply complex reasoning, "
1728
+ "or the task requires interactive user input.\n\n"
1729
+ f"Available via `from hermes_tools import ...`:\n\n"
1730
+ f"{tool_lines}\n\n"
1731
+ "Limits: 5-minute timeout, 50KB stdout cap, max 50 tool calls per script. "
1732
+ "terminal() is foreground-only (no background or pty).\n\n"
1733
+ f"{cwd_note}\n\n"
1734
+ "Print your final result to stdout. Use Python stdlib (json, re, math, csv, "
1735
+ "datetime, collections, etc.) for processing between tool calls.\n\n"
1736
+ "Also available (no import needed — built into hermes_tools):\n"
1737
+ " json_parse(text: str) — json.loads with strict=False; use for terminal() output with control chars\n"
1738
+ " shell_quote(s: str) — shlex.quote(); use when interpolating dynamic strings into shell commands\n"
1739
+ " retry(fn, max_attempts=3, delay=2) — retry with exponential backoff for transient failures"
1740
+ )
1741
+
1742
+ return {
1743
+ "name": "execute_code",
1744
+ "description": description,
1745
+ "parameters": {
1746
+ "type": "object",
1747
+ "properties": {
1748
+ "code": {
1749
+ "type": "string",
1750
+ "description": (
1751
+ "Python code to execute. Import tools with "
1752
+ f"`from hermes_tools import {import_str}` "
1753
+ "and print your final result to stdout."
1754
+ ),
1755
+ },
1756
+ },
1757
+ "required": ["code"],
1758
+ },
1759
+ }
1760
+
1761
+
1762
+ # Default schema used at registration time (all sandbox tools listed,
1763
+ # current configured mode). model_tools.py rebuilds per-session anyway.
1764
+ EXECUTE_CODE_SCHEMA = build_execute_code_schema()
1765
+
1766
+
1767
+ # --- Registry ---
1768
+ from tools.registry import registry, tool_error
1769
+
1770
+ registry.register(
1771
+ name="execute_code",
1772
+ toolset="code_execution",
1773
+ schema=EXECUTE_CODE_SCHEMA,
1774
+ handler=lambda args, **kw: execute_code(
1775
+ code=args.get("code", ""),
1776
+ task_id=kw.get("task_id"),
1777
+ enabled_tools=kw.get("enabled_tools")),
1778
+ check_fn=check_sandbox_requirements,
1779
+ emoji="🐍",
1780
+ max_result_size_chars=100_000,
1781
+ )
1782
+