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,1392 @@
1
+ """Dangerous command approval -- detection, prompting, and per-session state.
2
+
3
+ This module is the single source of truth for the dangerous command system:
4
+ - Pattern detection (DANGEROUS_PATTERNS, detect_dangerous_command)
5
+ - Per-session approval state (thread-safe, keyed by session_key)
6
+ - Approval prompting (CLI interactive + gateway async)
7
+ - Smart approval via auxiliary LLM (auto-approve low-risk commands)
8
+ - Permanent allowlist persistence (config.yaml)
9
+ """
10
+
11
+ import contextvars
12
+ import logging
13
+ import os
14
+ import re
15
+ import sys
16
+ import threading
17
+ import time
18
+ import unicodedata
19
+ from typing import Optional
20
+ from hermes_cli.config import cfg_get
21
+
22
+ from utils import env_var_enabled, is_truthy_value
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ # Per-thread/per-task gateway session identity.
27
+ # Gateway runs agent turns concurrently in executor threads, so reading a
28
+ # process-global env var for session identity is racy. Keep env fallback for
29
+ # legacy single-threaded callers, but prefer the context-local value when set.
30
+ _approval_session_key: contextvars.ContextVar[str] = contextvars.ContextVar(
31
+ "approval_session_key",
32
+ default="",
33
+ )
34
+
35
+
36
+ def _fire_approval_hook(hook_name: str, **kwargs) -> None:
37
+ """Invoke a plugin lifecycle hook for the approval system.
38
+
39
+ Lazy-imports the plugin manager to avoid circular imports (approval.py is
40
+ imported very early, long before plugins are discovered). Never raises --
41
+ plugin errors are logged and swallowed.
42
+
43
+ Only fires for the two approval-specific hooks in VALID_HOOKS:
44
+ pre_approval_request, post_approval_response.
45
+ """
46
+ try:
47
+ from hermes_cli.plugins import invoke_hook
48
+ except Exception:
49
+ # Plugin system not available in this execution context
50
+ # (e.g. bare tool-only imports, minimal test environments).
51
+ return
52
+ try:
53
+ invoke_hook(hook_name, **kwargs)
54
+ except Exception as exc:
55
+ # invoke_hook() already swallows per-callback errors, so reaching here
56
+ # means the dispatch layer itself failed. Log and move on -- approval
57
+ # flow is safety-critical, plugin observability is not.
58
+ logger.debug("Approval hook %s dispatch failed: %s", hook_name, exc)
59
+
60
+
61
+
62
+ def set_current_session_key(session_key: str) -> contextvars.Token[str]:
63
+ """Bind the active approval session key to the current context."""
64
+ return _approval_session_key.set(session_key or "")
65
+
66
+
67
+ def reset_current_session_key(token: contextvars.Token[str]) -> None:
68
+ """Restore the prior approval session key context."""
69
+ _approval_session_key.reset(token)
70
+
71
+
72
+ def get_current_session_key(default: str = "default") -> str:
73
+ """Return the active session key, preferring context-local state.
74
+
75
+ Resolution order:
76
+ 1. approval-specific contextvars (set by gateway before agent.run)
77
+ 2. session_context contextvars (set by _set_session_env)
78
+ 3. os.environ fallback (CLI, cron, tests)
79
+ """
80
+ session_key = _approval_session_key.get()
81
+ if session_key:
82
+ return session_key
83
+ from gateway.session_context import get_session_env
84
+ return get_session_env("HERMES_SESSION_KEY", default)
85
+
86
+
87
+ def _get_session_platform() -> str:
88
+ """Return the current gateway platform from contextvars/env fallback."""
89
+ try:
90
+ from gateway.session_context import get_session_env
91
+
92
+ return get_session_env("HERMES_SESSION_PLATFORM", "") or ""
93
+ except Exception:
94
+ return os.getenv("HERMES_SESSION_PLATFORM", "") or ""
95
+
96
+
97
+ def _is_gateway_approval_context() -> bool:
98
+ """True when this call is inside a gateway/API session.
99
+
100
+ Legacy gateway integrations set HERMES_GATEWAY_SESSION in process env.
101
+ Newer concurrent gateway paths bind HERMES_SESSION_PLATFORM via
102
+ contextvars so approval mode does not depend on process-global flags.
103
+
104
+ Cron jobs are NEVER gateway-approval contexts even when they originate
105
+ from a gateway platform (cron binds HERMES_SESSION_PLATFORM via
106
+ contextvars for delivery routing). Cron approvals are governed by
107
+ ``approvals.cron_mode`` config, not interactive resolve — letting cron
108
+ fall through to the gateway branch would submit a pending approval
109
+ with no listener and block the job indefinitely.
110
+ """
111
+ if env_var_enabled("HERMES_CRON_SESSION"):
112
+ return False
113
+ if env_var_enabled("HERMES_GATEWAY_SESSION"):
114
+ return True
115
+ return bool(_get_session_platform())
116
+
117
+ # Sensitive write targets that should trigger approval even when referenced
118
+ # via shell expansions like $HOME or $HERMES_HOME.
119
+ _SSH_SENSITIVE_PATH = r'(?:~|\$home|\$\{home\})/\.ssh(?:/|$)'
120
+ _HERMES_ENV_PATH = (
121
+ r'(?:~\/\.hermes/|'
122
+ r'(?:\$home|\$\{home\})/\.hermes/|'
123
+ r'(?:\$hermes_home|\$\{hermes_home\})/)'
124
+ r'\.env\b'
125
+ )
126
+ _PROJECT_ENV_PATH = r'(?:(?:/|\.{1,2}/)?(?:[^\s/"\'`]+/)*\.env(?:\.[^/\s"\'`]+)*)'
127
+ _PROJECT_CONFIG_PATH = r'(?:(?:/|\.{1,2}/)?(?:[^\s/"\'`]+/)*config\.yaml)'
128
+ _SHELL_RC_FILES = (
129
+ r'(?:~|\$home|\$\{home\})/\.'
130
+ r'(?:bashrc|zshrc|profile|bash_profile|zprofile)\b'
131
+ )
132
+ _CREDENTIAL_FILES = (
133
+ r'(?:~|\$home|\$\{home\})/\.'
134
+ r'(?:netrc|pgpass|npmrc|pypirc)\b'
135
+ )
136
+ # macOS: /etc, /var, /tmp, /home are symlinks to /private/{etc,var,tmp,home}.
137
+ # A command written to target /private/etc/sudoers works identically to
138
+ # /etc/sudoers on macOS but bypasses a plain "/etc/" pattern check. Match
139
+ # both forms. Inspired by Claude Code 2.1.113's "dangerous path protection".
140
+ _MACOS_PRIVATE_SYSTEM_PATH = r'/private/(?:etc|var|tmp|home)/'
141
+ # System-config paths that should trigger approval for any write/edit,
142
+ # collapsing /etc, its macOS /private/etc mirror, and /etc/sudoers.d/ into
143
+ # one shared fragment so new DANGEROUS_PATTERNS stay consistent.
144
+ _SYSTEM_CONFIG_PATH = (
145
+ rf'(?:/etc/|{_MACOS_PRIVATE_SYSTEM_PATH})'
146
+ )
147
+ _SENSITIVE_WRITE_TARGET = (
148
+ rf'(?:{_SYSTEM_CONFIG_PATH}|/dev/sd|'
149
+ rf'{_SSH_SENSITIVE_PATH}|'
150
+ rf'{_HERMES_ENV_PATH}|'
151
+ rf'{_SHELL_RC_FILES}|'
152
+ rf'{_CREDENTIAL_FILES})'
153
+ )
154
+ _PROJECT_SENSITIVE_WRITE_TARGET = rf'(?:{_PROJECT_ENV_PATH}|{_PROJECT_CONFIG_PATH})'
155
+ _COMMAND_TAIL = r'(?:\s*(?:&&|\|\||;).*)?$'
156
+
157
+ # =========================================================================
158
+ # Hardline (unconditional) blocklist
159
+ # =========================================================================
160
+ #
161
+ # Commands so catastrophic they should NEVER run via the agent, regardless
162
+ # of --yolo, /yolo, approvals.mode=off, or cron approve mode. This is a
163
+ # floor below yolo: opting into yolo is the user trusting the agent with
164
+ # their files and services, not trusting it to wipe the disk or power the
165
+ # box off.
166
+ #
167
+ # Hardline only applies to environments that can actually damage the host
168
+ # (local, ssh, container-host cron). Containerized backends (docker,
169
+ # singularity, modal, daytona) already bypass the dangerous-command layer
170
+ # because nothing they do can touch the host, so we leave that behavior
171
+ # alone.
172
+ #
173
+ # The list is deliberately tiny — only things with no recovery path:
174
+ # filesystem destruction rooted at /, raw block device overwrites, kernel
175
+ # shutdown/reboot, and denial-of-service commands that take the host down.
176
+ # Recoverable-but-costly operations (git reset --hard, rm -rf /tmp/x,
177
+ # chmod -R 777, curl|sh) stay in DANGEROUS_PATTERNS where yolo can pass
178
+ # them through — that's what yolo is for.
179
+ #
180
+ # Inspired by Mercury Agent's permission-hardened blocklist
181
+ # (https://github.com/cosmicstack-labs/mercury-agent).
182
+
183
+ # Regex fragment matching the *start* of a command (i.e. positions where
184
+ # a shell would begin parsing a new command). Used by shutdown/reboot
185
+ # patterns so they don't fire on "echo reboot" or "grep 'shutdown' log".
186
+ # Matches: start of string, after command separators (; && || | newline),
187
+ # after subshell openers ( `$(` or backtick ), optionally consuming
188
+ # leading wrapper commands (sudo, env VAR=VAL, exec, nohup, setsid).
189
+ _CMDPOS = (
190
+ r'(?:^|[;&|\n`]|\$\()' # start position
191
+ r'\s*' # optional whitespace
192
+ r'(?:sudo\s+(?:-[^\s]+\s+)*)?' # optional sudo with flags
193
+ r'(?:env\s+(?:\w+=\S*\s+)*)?' # optional env with VAR=VAL pairs
194
+ r'(?:(?:exec|nohup|setsid|time)\s+)*' # optional wrapper commands
195
+ r'\s*'
196
+ )
197
+
198
+ HARDLINE_PATTERNS = [
199
+ # rm recursive targeting the root filesystem or protected roots
200
+ (r'\brm\s+(-[^\s]*\s+)*(/|/\*|/ \*)(\s|$)', "recursive delete of root filesystem"),
201
+ (r'\brm\s+(-[^\s]*\s+)*(/home|/home/\*|/root|/root/\*|/etc|/etc/\*|/usr|/usr/\*|/var|/var/\*|/bin|/bin/\*|/sbin|/sbin/\*|/boot|/boot/\*|/lib|/lib/\*)(\s|$)', "recursive delete of system directory"),
202
+ (r'\brm\s+(-[^\s]*\s+)*(~|\$HOME)(/?|/\*)?(\s|$)', "recursive delete of home directory"),
203
+ # Filesystem format
204
+ (r'\bmkfs(\.[a-z0-9]+)?\b', "format filesystem (mkfs)"),
205
+ # Raw block device overwrites (dd + redirection)
206
+ (r'\bdd\b[^\n]*\bof=/dev/(sd|nvme|hd|mmcblk|vd|xvd)[a-z0-9]*', "dd to raw block device"),
207
+ (r'>\s*/dev/(sd|nvme|hd|mmcblk|vd|xvd)[a-z0-9]*\b', "redirect to raw block device"),
208
+ # Fork bomb (classic shell form)
209
+ (r':\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:', "fork bomb"),
210
+ # Kill every process on the system
211
+ (r'\bkill\s+(-[^\s]+\s+)*-1\b', "kill all processes"),
212
+ # System shutdown / reboot — anchor to command position (start of line,
213
+ # after a command separator, or after sudo/env wrappers) so we don't
214
+ # false-positive on "echo reboot" or "grep 'shutdown' logs".
215
+ # _CMDPOS matches start-of-command positions.
216
+ (_CMDPOS + r'(shutdown|reboot|halt|poweroff)\b', "system shutdown/reboot"),
217
+ (_CMDPOS + r'init\s+[06]\b', "init 0/6 (shutdown/reboot)"),
218
+ (_CMDPOS + r'systemctl\s+(poweroff|reboot|halt|kexec)\b', "systemctl poweroff/reboot"),
219
+ (_CMDPOS + r'telinit\s+[06]\b', "telinit 0/6 (shutdown/reboot)"),
220
+ ]
221
+
222
+ # Pre-compiled variant used by the hot-path matcher. Building these at module
223
+ # load eliminates the ~2.6 ms cold-cache re.compile fan-out on the first
224
+ # terminal() call per process (12 HARDLINE + 47 DANGEROUS patterns, each
225
+ # potentially evicted from Python's 512-entry ``re._cache`` by unrelated
226
+ # regex work elsewhere in the agent). DANGEROUS_PATTERNS_COMPILED is built
227
+ # at the end of this module after DANGEROUS_PATTERNS is defined.
228
+ _RE_FLAGS = re.IGNORECASE | re.DOTALL
229
+ HARDLINE_PATTERNS_COMPILED = [
230
+ (re.compile(pattern, _RE_FLAGS), description)
231
+ for pattern, description in HARDLINE_PATTERNS
232
+ ]
233
+
234
+
235
+ # =========================================================================
236
+ # Sudo stdin guard — block password guessing via "sudo -S"
237
+ # =========================================================================
238
+ # When SUDO_PASSWORD is not configured, any explicit "sudo -S" in the
239
+ # command is the LLM piping a guessed password via stdin. This is a
240
+ # brute-force attack vector: the model iterates through candidate
241
+ # passwords, inspects sudo's "Sorry, try again" output, and refines.
242
+ # Treat this as an unconditional block — there is never a legitimate
243
+ # reason for the agent to pipe passwords to sudo -S when no password
244
+ # has been configured.
245
+ _SUDO_STDIN_RE = re.compile(
246
+ r'(?:^|[;&|`\n]|&&|\|\||\$\()\s*sudo\s+-S\b',
247
+ re.IGNORECASE)
248
+
249
+
250
+ def _check_sudo_stdin_guard(command: str) -> tuple:
251
+ """Detect ``sudo -S`` (stdin password) without configured SUDO_PASSWORD.
252
+
253
+ When SUDO_PASSWORD is set, ``_transform_sudo_command`` injects ``-S``
254
+ internally — that path is legitimate and handled elsewhere. This guard
255
+ only fires when SUDO_PASSWORD is *not* set, meaning the LLM explicitly
256
+ wrote ``sudo -S`` to pipe a guessed password.
257
+
258
+ Returns:
259
+ (is_blocked: bool, description: str | None)
260
+ """
261
+ if "SUDO_PASSWORD" in os.environ:
262
+ return (False, None)
263
+ normalized = _normalize_command_for_detection(command).lower()
264
+ if _SUDO_STDIN_RE.search(normalized):
265
+ return (True, "sudo password guessing via stdin (sudo -S)")
266
+ return (False, None)
267
+
268
+
269
+ def detect_hardline_command(command: str) -> tuple:
270
+ """Check if a command matches the unconditional hardline blocklist.
271
+
272
+ Returns:
273
+ (is_hardline, description) or (False, None)
274
+ """
275
+ normalized = _normalize_command_for_detection(command).lower()
276
+ for pattern_re, description in HARDLINE_PATTERNS_COMPILED:
277
+ if pattern_re.search(normalized):
278
+ return (True, description)
279
+ return (False, None)
280
+
281
+
282
+ def _hardline_block_result(description: str) -> dict:
283
+ """Build the standard block result for a hardline match."""
284
+ return {
285
+ "approved": False,
286
+ "hardline": True,
287
+ "message": (
288
+ f"BLOCKED (hardline): {description}. "
289
+ "This command is on the unconditional blocklist and cannot "
290
+ "be executed via the agent — not even with --yolo, /yolo, "
291
+ "approvals.mode=off, or cron approve mode. If you genuinely "
292
+ "need to run it, run it yourself in a terminal outside the "
293
+ "agent."
294
+ ),
295
+ }
296
+
297
+
298
+ def _sudo_stdin_block_result(description: str) -> dict:
299
+ """Build the standard block result for sudo stdin guard."""
300
+ return {
301
+ "approved": False,
302
+ "message": (
303
+ f"BLOCKED: {description}. "
304
+ "Do not pipe passwords to 'sudo -S' — this is a brute-force "
305
+ "attack vector. Set SUDO_PASSWORD in your .env file if the "
306
+ "agent needs passwordless sudo, or run the sudo command "
307
+ "manually in your own terminal."
308
+ ),
309
+ }
310
+
311
+
312
+ # =========================================================================
313
+ # Dangerous command patterns
314
+ # =========================================================================
315
+
316
+ DANGEROUS_PATTERNS = [
317
+ (r'\brm\s+(-[^\s]*\s+)*/', "delete in root path"),
318
+ (r'\brm\s+-[^\s]*r', "recursive delete"),
319
+ (r'\brm\s+--recursive\b', "recursive delete (long flag)"),
320
+ (r'\bchmod\s+(-[^\s]*\s+)*(777|666|o\+[rwx]*w|a\+[rwx]*w)\b', "world/other-writable permissions"),
321
+ (r'\bchmod\s+--recursive\b.*(777|666|o\+[rwx]*w|a\+[rwx]*w)', "recursive world/other-writable (long flag)"),
322
+ (r'\bchown\s+(-[^\s]*)?R\s+root', "recursive chown to root"),
323
+ (r'\bchown\s+--recursive\b.*root', "recursive chown to root (long flag)"),
324
+ (r'\bmkfs\b', "format filesystem"),
325
+ (r'\bdd\s+.*if=', "disk copy"),
326
+ (r'>\s*/dev/sd', "write to block device"),
327
+ (r'\bDROP\s+(TABLE|DATABASE)\b', "SQL DROP"),
328
+ # Use [^\n]* instead of .* so DOTALL mode does not cause a WHERE clause on the
329
+ # *next* line to satisfy the negative lookahead, silently allowing DELETE without WHERE.
330
+ (r'\bDELETE\s+FROM\b(?![^\n]*\bWHERE\b)', "SQL DELETE without WHERE"),
331
+ (r'\bTRUNCATE\s+(TABLE)?\s*\w', "SQL TRUNCATE"),
332
+ (rf'>\s*{_SYSTEM_CONFIG_PATH}', "overwrite system config"),
333
+ (r'\bsystemctl\s+(-[^\s]+\s+)*(stop|restart|disable|mask)\b', "stop/restart system service"),
334
+ (r'\bkill\s+-9\s+-1\b', "kill all processes"),
335
+ (r'\bpkill\s+-9\b', "force kill processes"),
336
+ # killall with SIGKILL (parallel to pkill -9). Catches -9 / -KILL /
337
+ # -s KILL / -SIGKILL forms, and also `killall -r <regex>` broad sweeps
338
+ # that can wipe out unrelated processes by accident.
339
+ # Inspired by Claude Code 2.1.113 expanded deny rules.
340
+ (r'\bkillall\s+(-[^\s]*\s+)*-(9|KILL|SIGKILL)\b', "force kill processes (killall -KILL)"),
341
+ (r'\bkillall\s+(-[^\s]*\s+)*-s\s+(KILL|SIGKILL|9)\b', "force kill processes (killall -s KILL)"),
342
+ (r'\bkillall\s+(-[^\s]*\s+)*-r\b', "kill processes by regex (killall -r)"),
343
+ (r':\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:', "fork bomb"),
344
+ # Any shell invocation via -c or combined flags like -lc, -ic, etc.
345
+ (r'\b(bash|sh|zsh|ksh)\s+-[^\s]*c(\s+|$)', "shell command via -c/-lc flag"),
346
+ (r'\b(python[23]?|perl|ruby|node)\s+-[ec]\s+', "script execution via -e/-c flag"),
347
+ (r'\b(curl|wget)\b.*\|\s*(ba)?sh\b', "pipe remote content to shell"),
348
+ (r'\b(bash|sh|zsh|ksh)\s+<\s*<?\s*\(\s*(curl|wget)\b', "execute remote script via process substitution"),
349
+ (rf'\btee\b.*["\']?{_SENSITIVE_WRITE_TARGET}', "overwrite system file via tee"),
350
+ (rf'>>?\s*["\']?{_SENSITIVE_WRITE_TARGET}', "overwrite system file via redirection"),
351
+ (rf'\btee\b.*["\']?{_PROJECT_SENSITIVE_WRITE_TARGET}["\']?{_COMMAND_TAIL}', "overwrite project env/config via tee"),
352
+ (rf'>>?\s*["\']?{_PROJECT_SENSITIVE_WRITE_TARGET}["\']?{_COMMAND_TAIL}', "overwrite project env/config via redirection"),
353
+ (r'\bxargs\s+.*\brm\b', "xargs with rm"),
354
+ # find -exec rm / -execdir rm — the -execdir variant (same semantics,
355
+ # runs in the directory of each match) was previously missed. Claude
356
+ # Code 2.1.113 tightened their equivalent find rule to stop auto-
357
+ # approving -exec / -delete flags.
358
+ (r'\bfind\b.*-exec(?:dir)?\s+(/\S*/)?rm\b', "find -exec/-execdir rm"),
359
+ (r'\bfind\b.*-delete\b', "find -delete"),
360
+ # Gateway lifecycle protection: prevent the agent from killing its own
361
+ # gateway process. These commands trigger a gateway restart/stop that
362
+ # terminates all running agents mid-work.
363
+ (r'\bhermes\s+gateway\s+(stop|restart)\b', "stop/restart hermes gateway (kills running agents)"),
364
+ (r'\bhermes\s+update\b', "hermes update (restarts gateway, kills running agents)"),
365
+ # Gateway protection: never start gateway outside systemd management
366
+ (r'gateway\s+run\b.*(&\s*$|&\s*;|\bdisown\b|\bsetsid\b)', "start gateway outside systemd (use 'systemctl --user restart hermes-gateway')"),
367
+ (r'\bnohup\b.*gateway\s+run\b', "start gateway outside systemd (use 'systemctl --user restart hermes-gateway')"),
368
+ # Self-termination protection: prevent agent from killing its own process
369
+ (r'\b(pkill|killall)\b.*\b(hermes|gateway|cli\.py)\b', "kill hermes/gateway process (self-termination)"),
370
+ # Self-termination via kill + command substitution (pgrep/pidof).
371
+ # The name-based pattern above catches `pkill hermes` but not
372
+ # `kill -9 $(pgrep -f hermes)` because the substitution is opaque
373
+ # to regex at detection time. Catch the structural pattern instead.
374
+ (r'\bkill\b.*\$\(\s*pgrep\b', "kill process via pgrep expansion (self-termination)"),
375
+ (r'\bkill\b.*`\s*pgrep\b', "kill process via backtick pgrep expansion (self-termination)"),
376
+ # File copy/move/edit into sensitive system paths (/etc/ and macOS
377
+ # /private/etc/ mirror).
378
+ (rf'\b(cp|mv|install)\b.*\s{_SYSTEM_CONFIG_PATH}', "copy/move file into system config path"),
379
+ (rf'\b(cp|mv|install)\b.*\s["\']?{_PROJECT_SENSITIVE_WRITE_TARGET}["\']?{_COMMAND_TAIL}', "overwrite project env/config file"),
380
+ (rf'\bsed\s+-[^\s]*i.*\s{_SYSTEM_CONFIG_PATH}', "in-place edit of system config"),
381
+ (rf'\bsed\s+--in-place\b.*\s{_SYSTEM_CONFIG_PATH}', "in-place edit of system config (long flag)"),
382
+ # Script execution via heredoc — bypasses the -e/-c flag patterns above.
383
+ # `python3 << 'EOF'` feeds arbitrary code via stdin without -c/-e flags.
384
+ (r'\b(python[23]?|perl|ruby|node)\s+<<', "script execution via heredoc"),
385
+ # Git destructive operations that can lose uncommitted work or rewrite
386
+ # shared history. Not captured by rm/chmod/etc patterns.
387
+ (r'\bgit\s+reset\s+--hard\b', "git reset --hard (destroys uncommitted changes)"),
388
+ (r'\bgit\s+push\b.*--force\b', "git force push (rewrites remote history)"),
389
+ (r'\bgit\s+push\b.*-f\b', "git force push short flag (rewrites remote history)"),
390
+ (r'\bgit\s+clean\s+-[^\s]*f', "git clean with force (deletes untracked files)"),
391
+ (r'\bgit\s+branch\s+-D\b', "git branch force delete"),
392
+ # Script execution after chmod +x — catches the two-step pattern where
393
+ # a script is first made executable then immediately run. The script
394
+ # content may contain dangerous commands that individual patterns miss.
395
+ (r'\bchmod\s+\+x\b.*[;&|]+\s*\./', "chmod +x followed by immediate execution"),
396
+ # Sudo with stdin / askpass / shell / list-privs flags. An LLM-driven
397
+ # agent has no TTY, so sudo invocations that succeed without human
398
+ # interaction are those reading the password from stdin (-S/--stdin)
399
+ # or via an askpass helper (-A/--askpass). The shell-launch (-s) and
400
+ # list-privileges (-a) flags are also gated since they are
401
+ # privilege-relevant invocations the agent can chain after acquiring
402
+ # the password (e.g. read SUDO_PASSWORD from .env -> sudo -S -s ->
403
+ # root shell). Plain `sudo cmd` (no flag) is TTY-bound and excluded.
404
+ # `_normalize_command_for_detection` lowercases input before pattern
405
+ # matching, so case variants of S/s and A/a collapse — both forms
406
+ # are gated below. Lazy `[^;|&\n]*?` allows flag arguments (e.g.
407
+ # `sudo -u root -S whoami`) without spanning command separators. See
408
+ # #17873 category 4.
409
+ (r'\bsudo\b[^;|&\n]*?\s+(?:-s\b|--stdin\b|-a\b|--askpass\b)',
410
+ "sudo with privilege flag (stdin/askpass/shell/list)"),
411
+ # Combined short-flag form: -nS, -ns, -sa, -las — sudo flags packed
412
+ # into a single -X token. Catches the same threat class.
413
+ (r'\bsudo\b[^;|&\n]*?\s+-[a-z]*[sa][a-z]*\b',
414
+ "sudo with combined-flag privilege escalation"),
415
+ ]
416
+
417
+
418
+ # Pre-compiled variant (same rationale as HARDLINE_PATTERNS_COMPILED above).
419
+ DANGEROUS_PATTERNS_COMPILED = [
420
+ (re.compile(pattern, _RE_FLAGS), description)
421
+ for pattern, description in DANGEROUS_PATTERNS
422
+ ]
423
+
424
+
425
+ def _legacy_pattern_key(pattern: str) -> str:
426
+ """Reproduce the old regex-derived approval key for backwards compatibility."""
427
+ return pattern.split(r'\b')[1] if r'\b' in pattern else pattern[:20]
428
+
429
+
430
+ _PATTERN_KEY_ALIASES: dict[str, set[str]] = {}
431
+ for _pattern, _description in DANGEROUS_PATTERNS:
432
+ _legacy_key = _legacy_pattern_key(_pattern)
433
+ _canonical_key = _description
434
+ _PATTERN_KEY_ALIASES.setdefault(_canonical_key, set()).update({_canonical_key, _legacy_key})
435
+ _PATTERN_KEY_ALIASES.setdefault(_legacy_key, set()).update({_legacy_key, _canonical_key})
436
+
437
+
438
+ def _approval_key_aliases(pattern_key: str) -> set[str]:
439
+ """Return all approval keys that should match this pattern.
440
+
441
+ New approvals use the human-readable description string, but older
442
+ command_allowlist entries and session approvals may still contain the
443
+ historical regex-derived key.
444
+ """
445
+ return _PATTERN_KEY_ALIASES.get(pattern_key, {pattern_key})
446
+
447
+
448
+ # =========================================================================
449
+ # Detection
450
+ # =========================================================================
451
+
452
+ def _normalize_command_for_detection(command: str) -> str:
453
+ """Normalize a command string before dangerous-pattern matching.
454
+
455
+ Strips ANSI escape sequences (full ECMA-48 via tools.ansi_strip),
456
+ null bytes, and normalizes Unicode fullwidth characters so that
457
+ obfuscation techniques cannot bypass the pattern-based detection.
458
+ """
459
+ from tools.ansi_strip import strip_ansi
460
+
461
+ # Strip all ANSI escape sequences (CSI, OSC, DCS, 8-bit C1, etc.)
462
+ command = strip_ansi(command)
463
+ # Strip null bytes
464
+ command = command.replace('\x00', '')
465
+ # Normalize Unicode (fullwidth Latin, halfwidth Katakana, etc.)
466
+ command = unicodedata.normalize('NFKC', command)
467
+ return command
468
+
469
+
470
+ def detect_dangerous_command(command: str) -> tuple:
471
+ """Check if a command matches any dangerous patterns.
472
+
473
+ Returns:
474
+ (is_dangerous, pattern_key, description) or (False, None, None)
475
+ """
476
+ command_lower = _normalize_command_for_detection(command).lower()
477
+ for pattern_re, description in DANGEROUS_PATTERNS_COMPILED:
478
+ if pattern_re.search(command_lower):
479
+ pattern_key = description
480
+ return (True, pattern_key, description)
481
+ return (False, None, None)
482
+
483
+
484
+ # =========================================================================
485
+ # Per-session approval state (thread-safe)
486
+ # =========================================================================
487
+
488
+ _lock = threading.Lock()
489
+ _pending: dict[str, dict] = {}
490
+ _session_approved: dict[str, set] = {}
491
+ _session_yolo: set[str] = set()
492
+ _permanent_approved: set = set()
493
+
494
+ # =========================================================================
495
+ # Blocking gateway approval (mirrors CLI's synchronous input() flow)
496
+ # =========================================================================
497
+ # Per-session QUEUE of pending approvals. Multiple threads (parallel
498
+ # subagents, execute_code RPC handlers) can block concurrently — each gets
499
+ # its own threading.Event. /approve resolves the oldest, /approve all
500
+ # resolves every pending approval in the session.
501
+
502
+
503
+ class _ApprovalEntry:
504
+ """One pending dangerous-command approval inside a gateway session."""
505
+ __slots__ = ("event", "data", "result")
506
+
507
+ def __init__(self, data: dict):
508
+ self.event = threading.Event()
509
+ self.data = data # command, description, pattern_keys, …
510
+ self.result: Optional[str] = None # "once"|"session"|"always"|"deny"
511
+
512
+
513
+ _gateway_queues: dict[str, list] = {} # session_key → [_ApprovalEntry, …]
514
+ _gateway_notify_cbs: dict[str, object] = {} # session_key → callable(approval_data)
515
+
516
+
517
+ def register_gateway_notify(session_key: str, cb) -> None:
518
+ """Register a per-session callback for sending approval requests to the user.
519
+
520
+ The callback signature is ``cb(approval_data: dict) -> None`` where
521
+ *approval_data* contains ``command``, ``description``, and
522
+ ``pattern_keys``. The callback bridges sync→async (runs in the agent
523
+ thread, must schedule the actual send on the event loop).
524
+ """
525
+ with _lock:
526
+ _gateway_notify_cbs[session_key] = cb
527
+
528
+
529
+ def unregister_gateway_notify(session_key: str) -> None:
530
+ """Unregister the per-session gateway approval callback.
531
+
532
+ Signals ALL blocked threads for this session so they don't hang forever
533
+ (e.g. when the agent run finishes or is interrupted).
534
+ """
535
+ with _lock:
536
+ _gateway_notify_cbs.pop(session_key, None)
537
+ entries = _gateway_queues.pop(session_key, [])
538
+ for entry in entries:
539
+ entry.event.set()
540
+
541
+
542
+ def resolve_gateway_approval(session_key: str, choice: str,
543
+ resolve_all: bool = False) -> int:
544
+ """Called by the gateway's /approve or /deny handler to unblock
545
+ waiting agent thread(s).
546
+
547
+ When *resolve_all* is True every pending approval in the session is
548
+ resolved at once (``/approve all``). Otherwise only the oldest one
549
+ is resolved (FIFO).
550
+
551
+ Returns the number of approvals resolved (0 means nothing was pending).
552
+ """
553
+ with _lock:
554
+ queue = _gateway_queues.get(session_key)
555
+ if not queue:
556
+ return 0
557
+ if resolve_all:
558
+ targets = list(queue)
559
+ queue.clear()
560
+ else:
561
+ targets = [queue.pop(0)]
562
+ if not queue:
563
+ _gateway_queues.pop(session_key, None)
564
+
565
+ for entry in targets:
566
+ entry.result = choice
567
+ entry.event.set()
568
+ return len(targets)
569
+
570
+
571
+ def has_blocking_approval(session_key: str) -> bool:
572
+ """Check if a session has one or more blocking gateway approvals waiting."""
573
+ with _lock:
574
+ return bool(_gateway_queues.get(session_key))
575
+
576
+
577
+ def submit_pending(session_key: str, approval: dict):
578
+ """Store a pending approval request for a session."""
579
+ with _lock:
580
+ _pending[session_key] = approval
581
+
582
+
583
+ def approve_session(session_key: str, pattern_key: str):
584
+ """Approve a pattern for this session only."""
585
+ with _lock:
586
+ _session_approved.setdefault(session_key, set()).add(pattern_key)
587
+
588
+
589
+ def enable_session_yolo(session_key: str) -> None:
590
+ """Enable YOLO bypass for a single session key."""
591
+ if not session_key:
592
+ return
593
+ with _lock:
594
+ _session_yolo.add(session_key)
595
+
596
+
597
+ def disable_session_yolo(session_key: str) -> None:
598
+ """Disable YOLO bypass for a single session key."""
599
+ if not session_key:
600
+ return
601
+ with _lock:
602
+ _session_yolo.discard(session_key)
603
+
604
+
605
+ def clear_session(session_key: str) -> None:
606
+ """Remove all approval and yolo state for a given session."""
607
+ if not session_key:
608
+ return
609
+ with _lock:
610
+ _session_approved.pop(session_key, None)
611
+ _session_yolo.discard(session_key)
612
+ _pending.pop(session_key, None)
613
+ entries = _gateway_queues.pop(session_key, [])
614
+ for entry in entries:
615
+ # Session-boundary cleanup should cancel any blocked approval waits
616
+ # immediately so the old run can unwind instead of idling until timeout.
617
+ entry.result = "deny"
618
+ entry.event.set()
619
+
620
+
621
+ def is_session_yolo_enabled(session_key: str) -> bool:
622
+ """Return True when YOLO bypass is enabled for a specific session."""
623
+ if not session_key:
624
+ return False
625
+ with _lock:
626
+ return session_key in _session_yolo
627
+
628
+
629
+ def is_current_session_yolo_enabled() -> bool:
630
+ """Return True when the active approval session has YOLO bypass enabled."""
631
+ return is_session_yolo_enabled(get_current_session_key(default=""))
632
+
633
+
634
+ def is_approved(session_key: str, pattern_key: str) -> bool:
635
+ """Check if a pattern is approved (session-scoped or permanent).
636
+
637
+ Accept both the current canonical key and the legacy regex-derived key so
638
+ existing command_allowlist entries continue to work after key migrations.
639
+ """
640
+ aliases = _approval_key_aliases(pattern_key)
641
+ with _lock:
642
+ if any(alias in _permanent_approved for alias in aliases):
643
+ return True
644
+ session_approvals = _session_approved.get(session_key, set())
645
+ return any(alias in session_approvals for alias in aliases)
646
+
647
+
648
+ def approve_permanent(pattern_key: str):
649
+ """Add a pattern to the permanent allowlist."""
650
+ with _lock:
651
+ _permanent_approved.add(pattern_key)
652
+
653
+
654
+ def load_permanent(patterns: set):
655
+ """Bulk-load permanent allowlist entries from config."""
656
+ with _lock:
657
+ _permanent_approved.update(patterns)
658
+
659
+
660
+
661
+ # =========================================================================
662
+ # Config persistence for permanent allowlist
663
+ # =========================================================================
664
+
665
+ def load_permanent_allowlist() -> set:
666
+ """Load permanently allowed command patterns from config.
667
+
668
+ Also syncs them into the approval module so is_approved() works for
669
+ patterns added via 'always' in a previous session.
670
+ """
671
+ try:
672
+ from hermes_cli.config import load_config
673
+ config = load_config()
674
+ patterns = set(config.get("command_allowlist", []) or [])
675
+ if patterns:
676
+ load_permanent(patterns)
677
+ return patterns
678
+ except Exception as e:
679
+ logger.warning("Failed to load permanent allowlist: %s", e)
680
+ return set()
681
+
682
+
683
+ def save_permanent_allowlist(patterns: set):
684
+ """Save permanently allowed command patterns to config."""
685
+ try:
686
+ from hermes_cli.config import load_config, save_config
687
+ config = load_config()
688
+ config["command_allowlist"] = list(patterns)
689
+ save_config(config)
690
+ except Exception as e:
691
+ logger.warning("Could not save allowlist: %s", e)
692
+
693
+
694
+ # =========================================================================
695
+ # Approval prompting + orchestration
696
+ # =========================================================================
697
+
698
+ def prompt_dangerous_approval(command: str, description: str,
699
+ timeout_seconds: int | None = None,
700
+ allow_permanent: bool = True,
701
+ approval_callback=None) -> str:
702
+ """Prompt the user to approve a dangerous command (CLI only).
703
+
704
+ Args:
705
+ allow_permanent: When False, hide the [a]lways option (used when
706
+ tirith warnings are present, since broad permanent allowlisting
707
+ is inappropriate for content-level security findings).
708
+ approval_callback: Optional callback registered by the CLI for
709
+ prompt_toolkit integration. Signature:
710
+ (command, description, *, allow_permanent=True) -> str.
711
+
712
+ Returns: 'once', 'session', 'always', or 'deny'
713
+ """
714
+ if timeout_seconds is None:
715
+ timeout_seconds = _get_approval_timeout()
716
+
717
+ if approval_callback is not None:
718
+ try:
719
+ return approval_callback(command, description,
720
+ allow_permanent=allow_permanent)
721
+ except Exception as e:
722
+ logger.error("Approval callback failed: %s", e, exc_info=True)
723
+ return "deny"
724
+
725
+ # Fail-closed guard: if prompt_toolkit owns the terminal (interactive
726
+ # CLI session) and no approval callback is registered on this thread,
727
+ # the input() fallback below would spawn a daemon thread whose read
728
+ # can never see Enter -- the user's keystrokes go to prompt_toolkit,
729
+ # not input(), producing an invisible 60s deadlock (issue #15216).
730
+ # Deny fast and log loudly instead so the caller can surface a real
731
+ # error to the agent. Any thread that needs interactive approval must
732
+ # install a callback via tools.terminal_tool.set_approval_callback()
733
+ # before reaching this point (see delegate_tool.py, run_agent.py
734
+ # _execute_tool_calls_concurrent / _spawn_background_review for the
735
+ # established pattern).
736
+ try:
737
+ from prompt_toolkit.application.current import get_app_or_none
738
+ if get_app_or_none() is not None:
739
+ logger.warning(
740
+ "Dangerous-command approval requested on a thread with no "
741
+ "approval callback while prompt_toolkit is active; denying "
742
+ "to avoid stdin deadlock. command=%r description=%r",
743
+ command, description,
744
+ )
745
+ return "deny"
746
+ except Exception:
747
+ # prompt_toolkit not installed, or detection failed -- fall through
748
+ # to the legacy input() path (safe in non-TUI contexts: scripts,
749
+ # tests, sshd, etc.).
750
+ pass
751
+
752
+ os.environ["HERMES_SPINNER_PAUSE"] = "1"
753
+ try:
754
+ # Resolve the active UI language once per prompt so we don't re-read
755
+ # config/YAML inside the retry loop below.
756
+ from agent.i18n import t
757
+ while True:
758
+ print()
759
+ print(f" {t('approval.dangerous_header', description=description)}")
760
+ print(f" {command}")
761
+ print()
762
+ if allow_permanent:
763
+ print(t("approval.choose_long"))
764
+ else:
765
+ print(t("approval.choose_short"))
766
+ print()
767
+ sys.stdout.flush()
768
+
769
+ result = {"choice": ""}
770
+
771
+ def get_input():
772
+ try:
773
+ prompt = t("approval.prompt_long") if allow_permanent else t("approval.prompt_short")
774
+ result["choice"] = input(prompt).strip().lower()
775
+ except (EOFError, OSError):
776
+ result["choice"] = ""
777
+
778
+ thread = threading.Thread(target=get_input, daemon=True)
779
+ thread.start()
780
+ thread.join(timeout=timeout_seconds)
781
+
782
+ if thread.is_alive():
783
+ print("\n" + t("approval.timeout"))
784
+ return "deny"
785
+
786
+ choice = result["choice"]
787
+ if choice in {'o', 'once'}:
788
+ print(t("approval.allowed_once"))
789
+ return "once"
790
+ elif choice in {'s', 'session'}:
791
+ print(t("approval.allowed_session"))
792
+ return "session"
793
+ elif choice in {'a', 'always'}:
794
+ if not allow_permanent:
795
+ print(t("approval.allowed_session"))
796
+ return "session"
797
+ print(t("approval.allowed_always"))
798
+ return "always"
799
+ else:
800
+ print(t("approval.denied"))
801
+ return "deny"
802
+
803
+ except (EOFError, KeyboardInterrupt):
804
+ print("\n" + t("approval.cancelled"))
805
+ return "deny"
806
+ finally:
807
+ if "HERMES_SPINNER_PAUSE" in os.environ:
808
+ del os.environ["HERMES_SPINNER_PAUSE"]
809
+ print()
810
+ sys.stdout.flush()
811
+
812
+
813
+ def _normalize_approval_mode(mode) -> str:
814
+ """Normalize approval mode values loaded from YAML/config.
815
+
816
+ YAML 1.1 treats bare words like `off` as booleans, so a config entry like
817
+ `approvals:\n mode: off` is parsed as False unless quoted. Treat that as the
818
+ intended string mode instead of falling back to manual approvals.
819
+ """
820
+ if isinstance(mode, bool):
821
+ return "off" if mode is False else "manual"
822
+ if isinstance(mode, str):
823
+ normalized = mode.strip().lower()
824
+ return normalized or "manual"
825
+ return "manual"
826
+
827
+
828
+ def _get_approval_config() -> dict:
829
+ """Read the approvals config block. Returns a dict with 'mode', 'timeout', etc."""
830
+ try:
831
+ from hermes_cli.config import load_config
832
+ config = load_config()
833
+ return config.get("approvals", {}) or {}
834
+ except Exception as e:
835
+ logger.warning("Failed to load approval config: %s", e)
836
+ return {}
837
+
838
+
839
+ def _get_approval_mode() -> str:
840
+ """Read the approval mode from config. Returns 'manual', 'smart', or 'off'."""
841
+ mode = _get_approval_config().get("mode", "manual")
842
+ return _normalize_approval_mode(mode)
843
+
844
+
845
+ def _get_approval_timeout() -> int:
846
+ """Read the approval timeout from config. Defaults to 60 seconds."""
847
+ try:
848
+ return int(_get_approval_config().get("timeout", 60))
849
+ except (ValueError, TypeError):
850
+ return 60
851
+
852
+
853
+ def _get_cron_approval_mode() -> str:
854
+ """Read the cron approval mode from config. Returns 'deny' or 'approve'."""
855
+ try:
856
+ from hermes_cli.config import load_config
857
+ config = load_config()
858
+ mode = str(cfg_get(config, "approvals", "cron_mode", default="deny")).lower().strip()
859
+ if mode in {"approve", "off", "allow", "yes"}:
860
+ return "approve"
861
+ return "deny"
862
+ except Exception:
863
+ return "deny"
864
+
865
+
866
+ def _smart_approve(command: str, description: str) -> str:
867
+ """Use the auxiliary LLM to assess risk and decide approval.
868
+
869
+ Returns 'approve' if the LLM determines the command is safe,
870
+ 'deny' if genuinely dangerous, or 'escalate' if uncertain.
871
+
872
+ Inspired by OpenAI Codex's Smart Approvals guardian subagent
873
+ (openai/codex#13860).
874
+ """
875
+ try:
876
+ from agent.auxiliary_client import call_llm
877
+
878
+ prompt = f"""You are a security reviewer for an AI coding agent. A terminal command was flagged by pattern matching as potentially dangerous.
879
+
880
+ Command: {command}
881
+ Flagged reason: {description}
882
+
883
+ Assess the ACTUAL risk of this command. Many flagged commands are false positives — for example, `python -c "print('hello')"` is flagged as "script execution via -c flag" but is completely harmless.
884
+
885
+ Rules:
886
+ - APPROVE if the command is clearly safe (benign script execution, safe file operations, development tools, package installs, git operations, etc.)
887
+ - DENY if the command could genuinely damage the system (recursive delete of important paths, overwriting system files, fork bombs, wiping disks, dropping databases, etc.)
888
+ - ESCALATE if you're uncertain
889
+
890
+ Respond with exactly one word: APPROVE, DENY, or ESCALATE"""
891
+
892
+ response = call_llm(
893
+ task="approval",
894
+ messages=[{"role": "user", "content": prompt}],
895
+ temperature=0,
896
+ max_tokens=16,
897
+ )
898
+
899
+ answer = (response.choices[0].message.content or "").strip().upper()
900
+
901
+ if "APPROVE" in answer:
902
+ return "approve"
903
+ elif "DENY" in answer:
904
+ return "deny"
905
+ else:
906
+ return "escalate"
907
+
908
+ except Exception as e:
909
+ logger.debug("Smart approvals: LLM call failed (%s), escalating", e)
910
+ return "escalate"
911
+
912
+
913
+ def check_dangerous_command(command: str, env_type: str,
914
+ approval_callback=None) -> dict:
915
+ """Check if a command is dangerous and handle approval.
916
+
917
+ This is the main entry point called by terminal_tool before executing
918
+ any command. It orchestrates detection, session checks, and prompting.
919
+
920
+ Args:
921
+ command: The shell command to check.
922
+ env_type: Terminal backend type ('local', 'ssh', 'docker', etc.).
923
+ approval_callback: Optional CLI callback for interactive prompts.
924
+
925
+ Returns:
926
+ {"approved": True/False, "message": str or None, ...}
927
+ """
928
+ if env_type in {"docker", "singularity", "modal", "daytona", "vercel_sandbox"}:
929
+ return {"approved": True, "message": None}
930
+
931
+ # Hardline floor: commands with no recovery path (rm -rf /, mkfs, dd
932
+ # to raw device, shutdown/reboot, fork bomb, kill -1) are blocked
933
+ # unconditionally, BEFORE the yolo bypass. Opting into yolo is
934
+ # trusting the agent with your files and services, not trusting it
935
+ # to wipe the disk or power the box off.
936
+ is_hardline, hardline_desc = detect_hardline_command(command)
937
+ if is_hardline:
938
+ logger.warning("Hardline block: %s (command: %s)", hardline_desc, command[:200])
939
+ return _hardline_block_result(hardline_desc)
940
+
941
+ # --yolo: bypass all approval prompts. Gateway /yolo is session-scoped;
942
+ # CLI --yolo remains process-scoped via the env var for local use.
943
+ if is_truthy_value(os.getenv("HERMES_YOLO_MODE")) or is_current_session_yolo_enabled():
944
+ return {"approved": True, "message": None}
945
+
946
+ is_dangerous, pattern_key, description = detect_dangerous_command(command)
947
+ if not is_dangerous:
948
+ return {"approved": True, "message": None}
949
+
950
+ session_key = get_current_session_key()
951
+ if is_approved(session_key, pattern_key):
952
+ return {"approved": True, "message": None}
953
+
954
+ is_cli = env_var_enabled("HERMES_INTERACTIVE")
955
+ is_gateway = _is_gateway_approval_context()
956
+
957
+ if not is_cli and not is_gateway:
958
+ # Cron sessions: respect cron_mode config
959
+ if env_var_enabled("HERMES_CRON_SESSION"):
960
+ if _get_cron_approval_mode() == "deny":
961
+ return {
962
+ "approved": False,
963
+ "message": (
964
+ f"BLOCKED: Command flagged as dangerous ({description}) "
965
+ "but cron jobs run without a user present to approve it. "
966
+ "Find an alternative approach that avoids this command. "
967
+ "To allow dangerous commands in cron jobs, set "
968
+ "approvals.cron_mode: approve in config.yaml."
969
+ ),
970
+ }
971
+ return {"approved": True, "message": None}
972
+
973
+ if is_gateway or env_var_enabled("HERMES_EXEC_ASK"):
974
+ submit_pending(session_key, {
975
+ "command": command,
976
+ "pattern_key": pattern_key,
977
+ "description": description,
978
+ })
979
+ return {
980
+ "approved": False,
981
+ "pattern_key": pattern_key,
982
+ "status": "approval_required",
983
+ "command": command,
984
+ "description": description,
985
+ "message": (
986
+ f"⚠️ This command is potentially dangerous ({description}). "
987
+ f"Asking the user for approval.\n\n**Command:**\n```\n{command}\n```"
988
+ ),
989
+ }
990
+
991
+ choice = prompt_dangerous_approval(command, description,
992
+ approval_callback=approval_callback)
993
+
994
+ if choice == "deny":
995
+ return {
996
+ "approved": False,
997
+ "message": f"BLOCKED: User denied this potentially dangerous command (matched '{description}' pattern). Do NOT retry this command - the user has explicitly rejected it.",
998
+ "pattern_key": pattern_key,
999
+ "description": description,
1000
+ }
1001
+
1002
+ if choice == "session":
1003
+ approve_session(session_key, pattern_key)
1004
+ elif choice == "always":
1005
+ approve_session(session_key, pattern_key)
1006
+ approve_permanent(pattern_key)
1007
+ save_permanent_allowlist(_permanent_approved)
1008
+
1009
+ return {"approved": True, "message": None}
1010
+
1011
+
1012
+ # =========================================================================
1013
+ # Combined pre-exec guard (tirith + dangerous command detection)
1014
+ # =========================================================================
1015
+
1016
+ def _format_tirith_description(tirith_result: dict) -> str:
1017
+ """Build a human-readable description from tirith findings.
1018
+
1019
+ Includes severity, title, and description for each finding so users
1020
+ can make an informed approval decision.
1021
+ """
1022
+ findings = tirith_result.get("findings") or []
1023
+ if not findings:
1024
+ summary = tirith_result.get("summary") or "security issue detected"
1025
+ return f"Security scan: {summary}"
1026
+
1027
+ parts = []
1028
+ for f in findings:
1029
+ severity = f.get("severity", "")
1030
+ title = f.get("title", "")
1031
+ desc = f.get("description", "")
1032
+ if title and desc:
1033
+ parts.append(f"[{severity}] {title}: {desc}" if severity else f"{title}: {desc}")
1034
+ elif title:
1035
+ parts.append(f"[{severity}] {title}" if severity else title)
1036
+ if not parts:
1037
+ summary = tirith_result.get("summary") or "security issue detected"
1038
+ return f"Security scan: {summary}"
1039
+
1040
+ return "Security scan — " + "; ".join(parts)
1041
+
1042
+
1043
+ def check_all_command_guards(command: str, env_type: str,
1044
+ approval_callback=None) -> dict:
1045
+ """Run all pre-exec security checks and return a single approval decision.
1046
+
1047
+ Gathers findings from tirith and dangerous-command detection, then
1048
+ presents them as a single combined approval request. This prevents
1049
+ a gateway force=True replay from bypassing one check when only the
1050
+ other was shown to the user.
1051
+ """
1052
+ # Skip containers for both checks
1053
+ if env_type in {"docker", "singularity", "modal", "daytona", "vercel_sandbox"}:
1054
+ return {"approved": True, "message": None}
1055
+
1056
+ # Hardline floor: unconditional block for catastrophic commands
1057
+ # (rm -rf /, mkfs, dd to raw device, shutdown/reboot, fork bomb,
1058
+ # kill -1). Applies BEFORE yolo / mode=off / cron approve-mode so
1059
+ # no session-level setting can bypass it.
1060
+ is_hardline, hardline_desc = detect_hardline_command(command)
1061
+ if is_hardline:
1062
+ logger.warning("Hardline block: %s (command: %s)", hardline_desc, command[:200])
1063
+ return _hardline_block_result(hardline_desc)
1064
+
1065
+ # == Sudo stdin guard ==
1066
+ # Like the hardline floor above, this is unconditional: there is never a
1067
+ # legitimate reason for the agent to pipe passwords to sudo -S when no
1068
+ # SUDO_PASSWORD has been configured. This must fire BEFORE the yolo
1069
+ # check so even yolo/smart approval/mode=off cannot bypass it.
1070
+ is_sudo_guess, sudo_guess_desc = _check_sudo_stdin_guard(command)
1071
+ if is_sudo_guess:
1072
+ logger.warning("Sudo stdin guard block: %s (command: %s)",
1073
+ sudo_guess_desc, command[:200])
1074
+ return _sudo_stdin_block_result(sudo_guess_desc)
1075
+
1076
+ # --yolo or approvals.mode=off: bypass all approval prompts.
1077
+ # Gateway /yolo is session-scoped; CLI --yolo remains process-scoped.
1078
+ approval_mode = _get_approval_mode()
1079
+ if is_truthy_value(os.getenv("HERMES_YOLO_MODE")) or is_current_session_yolo_enabled() or approval_mode == "off":
1080
+ return {"approved": True, "message": None}
1081
+
1082
+ is_cli = env_var_enabled("HERMES_INTERACTIVE")
1083
+ is_gateway = _is_gateway_approval_context()
1084
+ is_ask = env_var_enabled("HERMES_EXEC_ASK")
1085
+
1086
+ # Preserve the existing non-interactive behavior: outside CLI/gateway/ask
1087
+ # flows, we do not block on approvals and we skip external guard work.
1088
+ if not is_cli and not is_gateway and not is_ask:
1089
+ # Cron sessions: respect cron_mode config
1090
+ if env_var_enabled("HERMES_CRON_SESSION"):
1091
+ if _get_cron_approval_mode() == "deny":
1092
+ # Run detection to get a description for the block message
1093
+ is_dangerous, _pk, description = detect_dangerous_command(command)
1094
+ if is_dangerous:
1095
+ return {
1096
+ "approved": False,
1097
+ "message": (
1098
+ f"BLOCKED: Command flagged as dangerous ({description}) "
1099
+ "but cron jobs run without a user present to approve it. "
1100
+ "Find an alternative approach that avoids this command. "
1101
+ "To allow dangerous commands in cron jobs, set "
1102
+ "approvals.cron_mode: approve in config.yaml."
1103
+ ),
1104
+ }
1105
+ return {"approved": True, "message": None}
1106
+
1107
+ # --- Phase 1: Gather findings from both checks ---
1108
+
1109
+ # Tirith check — wrapper guarantees no raise for expected failures.
1110
+ # Only catch ImportError (module not installed).
1111
+ tirith_result = {"action": "allow", "findings": [], "summary": ""}
1112
+ try:
1113
+ from tools.tirith_security import check_command_security
1114
+ tirith_result = check_command_security(command)
1115
+ except ImportError:
1116
+ pass # tirith module not installed — allow
1117
+
1118
+ # Dangerous command check (detection only, no approval)
1119
+ is_dangerous, pattern_key, description = detect_dangerous_command(command)
1120
+
1121
+ # --- Phase 2: Decide ---
1122
+
1123
+ # Collect warnings that need approval
1124
+ warnings = [] # list of (pattern_key, description, is_tirith)
1125
+
1126
+ session_key = get_current_session_key()
1127
+
1128
+ # Tirith block/warn → approvable warning with rich findings.
1129
+ # Previously, tirith "block" was a hard block with no approval prompt.
1130
+ # Now both block and warn go through the approval flow so users can
1131
+ # inspect the explanation and approve if they understand the risk.
1132
+ if tirith_result["action"] in {"block", "warn"}:
1133
+ findings = tirith_result.get("findings") or []
1134
+ rule_id = findings[0].get("rule_id", "unknown") if findings else "unknown"
1135
+ tirith_key = f"tirith:{rule_id}"
1136
+ tirith_desc = _format_tirith_description(tirith_result)
1137
+ if not is_approved(session_key, tirith_key):
1138
+ warnings.append((tirith_key, tirith_desc, True))
1139
+
1140
+ if is_dangerous:
1141
+ if not is_approved(session_key, pattern_key):
1142
+ warnings.append((pattern_key, description, False))
1143
+
1144
+ # Nothing to warn about
1145
+ if not warnings:
1146
+ return {"approved": True, "message": None}
1147
+
1148
+ # --- Phase 2.5: Smart approval (auxiliary LLM risk assessment) ---
1149
+ # When approvals.mode=smart, ask the aux LLM before prompting the user.
1150
+ # Inspired by OpenAI Codex's Smart Approvals guardian subagent
1151
+ # (openai/codex#13860).
1152
+ if approval_mode == "smart":
1153
+ combined_desc_for_llm = "; ".join(desc for _, desc, _ in warnings)
1154
+ verdict = _smart_approve(command, combined_desc_for_llm)
1155
+ if verdict == "approve":
1156
+ # Auto-approve and grant session-level approval for these patterns
1157
+ for key, _, _ in warnings:
1158
+ approve_session(session_key, key)
1159
+ logger.debug("Smart approval: auto-approved '%s' (%s)",
1160
+ command[:60], combined_desc_for_llm)
1161
+ return {"approved": True, "message": None,
1162
+ "smart_approved": True,
1163
+ "description": combined_desc_for_llm}
1164
+ elif verdict == "deny":
1165
+ combined_desc_for_llm = "; ".join(desc for _, desc, _ in warnings)
1166
+ return {
1167
+ "approved": False,
1168
+ "message": f"BLOCKED by smart approval: {combined_desc_for_llm}. "
1169
+ "The command was assessed as genuinely dangerous. Do NOT retry.",
1170
+ "smart_denied": True,
1171
+ }
1172
+ # verdict == "escalate" → fall through to manual prompt
1173
+
1174
+ # --- Phase 3: Approval ---
1175
+
1176
+ # Combine descriptions for a single approval prompt
1177
+ combined_desc = "; ".join(desc for _, desc, _ in warnings)
1178
+ primary_key = warnings[0][0]
1179
+ all_keys = [key for key, _, _ in warnings]
1180
+ has_tirith = any(is_t for _, _, is_t in warnings)
1181
+
1182
+ # Gateway/async approval — block the agent thread until the user
1183
+ # responds with /approve or /deny, mirroring the CLI's synchronous
1184
+ # input() flow. The agent never sees "approval_required"; it either
1185
+ # gets the command output (approved) or a definitive "BLOCKED" message.
1186
+ if is_gateway or is_ask:
1187
+ notify_cb = None
1188
+ with _lock:
1189
+ notify_cb = _gateway_notify_cbs.get(session_key)
1190
+
1191
+ if notify_cb is not None:
1192
+ # --- Blocking gateway approval (queue-based) ---
1193
+ # Each call gets its own _ApprovalEntry so parallel subagents
1194
+ # and execute_code threads can block concurrently.
1195
+ approval_data = {
1196
+ "command": command,
1197
+ "pattern_key": primary_key,
1198
+ "pattern_keys": all_keys,
1199
+ "description": combined_desc,
1200
+ }
1201
+ entry = _ApprovalEntry(approval_data)
1202
+ with _lock:
1203
+ _gateway_queues.setdefault(session_key, []).append(entry)
1204
+
1205
+ # Notify plugins that an approval is being requested. Fires before
1206
+ # the gateway notify callback so observers (e.g. macOS notifier
1207
+ # plugins, audit logs, Slack alerts) get the event in real time.
1208
+ _fire_approval_hook(
1209
+ "pre_approval_request",
1210
+ command=command,
1211
+ description=combined_desc,
1212
+ pattern_key=primary_key,
1213
+ pattern_keys=list(all_keys),
1214
+ session_key=session_key,
1215
+ surface="gateway",
1216
+ )
1217
+
1218
+ # Notify the user (bridges sync agent thread → async gateway)
1219
+ try:
1220
+ notify_cb(approval_data)
1221
+ except Exception as exc:
1222
+ logger.warning("Gateway approval notify failed: %s", exc)
1223
+ with _lock:
1224
+ queue = _gateway_queues.get(session_key, [])
1225
+ if entry in queue:
1226
+ queue.remove(entry)
1227
+ if not queue:
1228
+ _gateway_queues.pop(session_key, None)
1229
+ return {
1230
+ "approved": False,
1231
+ "message": "BLOCKED: Failed to send approval request to user. Do NOT retry.",
1232
+ "pattern_key": primary_key,
1233
+ "description": combined_desc,
1234
+ }
1235
+
1236
+ # Block until the user responds or timeout (default 5 min).
1237
+ # Poll in short slices so we can fire activity heartbeats every
1238
+ # ~10s to the agent's inactivity tracker. Without this, the
1239
+ # blocking event.wait() never touches activity, and the
1240
+ # gateway's inactivity watchdog (agent.gateway_timeout, default
1241
+ # 1800s) kills the agent while the user is still responding to
1242
+ # the approval prompt. Mirrors the _wait_for_process() cadence
1243
+ # in tools/environments/base.py.
1244
+ timeout = _get_approval_config().get("gateway_timeout", 300)
1245
+ try:
1246
+ timeout = int(timeout)
1247
+ except (ValueError, TypeError):
1248
+ timeout = 300
1249
+
1250
+ try:
1251
+ from tools.environments.base import touch_activity_if_due
1252
+ except Exception: # pragma: no cover
1253
+ touch_activity_if_due = None
1254
+
1255
+ _now = time.monotonic()
1256
+ _deadline = _now + max(timeout, 0)
1257
+ _activity_state = {"last_touch": _now, "start": _now}
1258
+ resolved = False
1259
+ while True:
1260
+ _remaining = _deadline - time.monotonic()
1261
+ if _remaining <= 0:
1262
+ break
1263
+ # 1s poll slice — the event is set immediately when the
1264
+ # user responds, so slice length only controls heartbeat
1265
+ # cadence, not user-visible responsiveness.
1266
+ if entry.event.wait(timeout=min(1.0, _remaining)):
1267
+ resolved = True
1268
+ break
1269
+ if touch_activity_if_due is not None:
1270
+ touch_activity_if_due(
1271
+ _activity_state, "waiting for user approval"
1272
+ )
1273
+
1274
+ # Clean up this entry from the queue
1275
+ with _lock:
1276
+ queue = _gateway_queues.get(session_key, [])
1277
+ if entry in queue:
1278
+ queue.remove(entry)
1279
+ if not queue:
1280
+ _gateway_queues.pop(session_key, None)
1281
+
1282
+ choice = entry.result
1283
+ # Normalize outcome for the post hook. Unresolved (timeout) and
1284
+ # None both mean the user never responded; report that explicitly
1285
+ # so plugins can distinguish timeout from explicit deny.
1286
+ _outcome = (
1287
+ "timeout" if not resolved
1288
+ else (choice if choice else "timeout")
1289
+ )
1290
+ _fire_approval_hook(
1291
+ "post_approval_response",
1292
+ command=command,
1293
+ description=combined_desc,
1294
+ pattern_key=primary_key,
1295
+ pattern_keys=list(all_keys),
1296
+ session_key=session_key,
1297
+ surface="gateway",
1298
+ choice=_outcome,
1299
+ )
1300
+
1301
+ if not resolved or choice is None or choice == "deny":
1302
+ reason = "timed out" if not resolved else "denied by user"
1303
+ return {
1304
+ "approved": False,
1305
+ "message": f"BLOCKED: Command {reason}. Do NOT retry this command.",
1306
+ "pattern_key": primary_key,
1307
+ "description": combined_desc,
1308
+ }
1309
+
1310
+ # User approved — persist based on scope (same logic as CLI)
1311
+ for key, _, is_tirith in warnings:
1312
+ if choice == "session" or (choice == "always" and is_tirith):
1313
+ approve_session(session_key, key)
1314
+ elif choice == "always":
1315
+ approve_session(session_key, key)
1316
+ approve_permanent(key)
1317
+ save_permanent_allowlist(_permanent_approved)
1318
+ # choice == "once": no persistence — command allowed this
1319
+ # single time only, matching the CLI's behavior.
1320
+
1321
+ return {"approved": True, "message": None,
1322
+ "user_approved": True, "description": combined_desc}
1323
+
1324
+ # Fallback: no gateway callback registered (e.g. cron, batch).
1325
+ # Return approval_required for backward compat.
1326
+ submit_pending(session_key, {
1327
+ "command": command,
1328
+ "pattern_key": primary_key,
1329
+ "pattern_keys": all_keys,
1330
+ "description": combined_desc,
1331
+ })
1332
+ return {
1333
+ "approved": False,
1334
+ "pattern_key": primary_key,
1335
+ "status": "approval_required",
1336
+ "command": command,
1337
+ "description": combined_desc,
1338
+ "message": (
1339
+ f"⚠️ {combined_desc}. Asking the user for approval.\n\n**Command:**\n```\n{command}\n```"
1340
+ ),
1341
+ }
1342
+
1343
+ # CLI interactive: single combined prompt
1344
+ # Hide [a]lways when any tirith warning is present
1345
+ _fire_approval_hook(
1346
+ "pre_approval_request",
1347
+ command=command,
1348
+ description=combined_desc,
1349
+ pattern_key=primary_key,
1350
+ pattern_keys=list(all_keys),
1351
+ session_key=session_key,
1352
+ surface="cli",
1353
+ )
1354
+ choice = prompt_dangerous_approval(command, combined_desc,
1355
+ allow_permanent=not has_tirith,
1356
+ approval_callback=approval_callback)
1357
+ _fire_approval_hook(
1358
+ "post_approval_response",
1359
+ command=command,
1360
+ description=combined_desc,
1361
+ pattern_key=primary_key,
1362
+ pattern_keys=list(all_keys),
1363
+ session_key=session_key,
1364
+ surface="cli",
1365
+ choice=choice,
1366
+ )
1367
+
1368
+ if choice == "deny":
1369
+ return {
1370
+ "approved": False,
1371
+ "message": "BLOCKED: User denied. Do NOT retry.",
1372
+ "pattern_key": primary_key,
1373
+ "description": combined_desc,
1374
+ }
1375
+
1376
+ # Persist approval for each warning individually
1377
+ for key, _, is_tirith in warnings:
1378
+ if choice == "session" or (choice == "always" and is_tirith):
1379
+ # tirith: session only (no permanent broad allowlisting)
1380
+ approve_session(session_key, key)
1381
+ elif choice == "always":
1382
+ # dangerous patterns: permanent allowed
1383
+ approve_session(session_key, key)
1384
+ approve_permanent(key)
1385
+ save_permanent_allowlist(_permanent_approved)
1386
+
1387
+ return {"approved": True, "message": None,
1388
+ "user_approved": True, "description": combined_desc}
1389
+
1390
+
1391
+ # Load permanent allowlist from config on module import
1392
+ load_permanent_allowlist()