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,1863 @@
1
+ """
2
+ Doctor command for hermes CLI.
3
+
4
+ Diagnoses issues with Hermes Agent setup.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import subprocess
10
+ import shutil
11
+ import importlib.util
12
+ from pathlib import Path
13
+
14
+ from hermes_cli.config import get_project_root, get_hermes_home, get_env_path
15
+ from hermes_cli.env_loader import load_hermes_dotenv
16
+ from calvyn_constants import display_hermes_home
17
+
18
+ PROJECT_ROOT = get_project_root()
19
+ HERMES_HOME = get_hermes_home()
20
+ _DHH = display_hermes_home() # user-facing display path (e.g. ~/.hermes or ~/.hermes/profiles/coder)
21
+
22
+ # Load environment variables from ~/.hermes/.env so API key checks work
23
+ _env_path = get_env_path()
24
+ load_hermes_dotenv(hermes_home=_env_path.parent, project_env=PROJECT_ROOT / ".env")
25
+
26
+ from hermes_cli.colors import Colors, color
27
+ from hermes_cli.models import _HERMES_USER_AGENT
28
+ from hermes_cli.vercel_auth import describe_vercel_auth
29
+ from calvyn_constants import OPENROUTER_MODELS_URL
30
+ from utils import base_url_host_matches
31
+
32
+
33
+ _PROVIDER_ENV_HINTS = (
34
+ "OPENROUTER_API_KEY",
35
+ "OPENAI_API_KEY",
36
+ "ANTHROPIC_API_KEY",
37
+ "ANTHROPIC_TOKEN",
38
+ "OPENAI_BASE_URL",
39
+ "NOUS_API_KEY",
40
+ "GLM_API_KEY",
41
+ "ZAI_API_KEY",
42
+ "Z_AI_API_KEY",
43
+ "KIMI_API_KEY",
44
+ "KIMI_CN_API_KEY",
45
+ "GMI_API_KEY",
46
+ "MINIMAX_API_KEY",
47
+ "MINIMAX_CN_API_KEY",
48
+ "KILOCODE_API_KEY",
49
+ "DEEPSEEK_API_KEY",
50
+ "DASHSCOPE_API_KEY",
51
+ "HF_TOKEN",
52
+ "AI_GATEWAY_API_KEY",
53
+ "OPENCODE_ZEN_API_KEY",
54
+ "OPENCODE_GO_API_KEY",
55
+ "XIAOMI_API_KEY",
56
+ "TOKENHUB_API_KEY",
57
+ )
58
+
59
+
60
+ from calvyn_constants import is_termux as _is_termux
61
+
62
+
63
+ def _python_install_cmd() -> str:
64
+ return "python -m pip install" if _is_termux() else "uv pip install"
65
+
66
+
67
+ def _system_package_install_cmd(pkg: str) -> str:
68
+ if _is_termux():
69
+ return f"pkg install {pkg}"
70
+ if sys.platform == "darwin":
71
+ return f"brew install {pkg}"
72
+ return f"sudo apt install {pkg}"
73
+
74
+
75
+ def _safe_which(cmd: str) -> str | None:
76
+ """shutil.which wrapper resilient to platform monkeypatching in tests."""
77
+ try:
78
+ return shutil.which(cmd)
79
+ except Exception:
80
+ return None
81
+
82
+
83
+ def _termux_browser_setup_steps(node_installed: bool) -> list[str]:
84
+ steps: list[str] = []
85
+ step = 1
86
+ if not node_installed:
87
+ steps.append(f"{step}) pkg install nodejs")
88
+ step += 1
89
+ steps.append(f"{step}) npm install -g agent-browser")
90
+ steps.append(f"{step + 1}) agent-browser install")
91
+ return steps
92
+
93
+
94
+ def _termux_install_all_fallback_notes() -> list[str]:
95
+ return [
96
+ "Termux install profile: use .[termux-all] for broad compatibility (installer default on Termux).",
97
+ "Matrix E2EE extra is excluded on Termux (python-olm currently fails to build).",
98
+ "Local faster-whisper extra is excluded on Termux (ctranslate2/av build path unavailable).",
99
+ "STT fallback: use Groq Whisper (set GROQ_API_KEY) or OpenAI Whisper (set VOICE_TOOLS_OPENAI_KEY).",
100
+ ]
101
+
102
+
103
+ def _has_provider_env_config(content: str) -> bool:
104
+ """Return True when ~/.hermes/.env contains provider auth/base URL settings."""
105
+ return any(key in content for key in _PROVIDER_ENV_HINTS)
106
+
107
+
108
+ def _honcho_is_configured_for_doctor() -> bool:
109
+ """Return True when Honcho is configured, even if this process has no active session."""
110
+ try:
111
+ from plugins.memory.honcho.client import HonchoClientConfig
112
+
113
+ cfg = HonchoClientConfig.from_global_config()
114
+ return bool(cfg.enabled and (cfg.api_key or cfg.base_url))
115
+ except Exception:
116
+ return False
117
+
118
+
119
+ def _is_kanban_worker_env_gate(item: dict) -> bool:
120
+ """Return True when Kanban is unavailable only because this is not a worker process."""
121
+ if item.get("name") != "kanban":
122
+ return False
123
+ if os.environ.get("HERMES_KANBAN_TASK"):
124
+ return False
125
+
126
+ tools = item.get("tools") or []
127
+ return bool(tools) and all(str(tool).startswith("kanban_") for tool in tools)
128
+
129
+
130
+ def _doctor_tool_availability_detail(toolset: str) -> str:
131
+ """Optional explanatory suffix for toolsets whose doctor status needs context."""
132
+ if toolset == "kanban" and not os.environ.get("HERMES_KANBAN_TASK"):
133
+ return "(runtime-gated; loaded only for dispatcher-spawned workers)"
134
+ return ""
135
+
136
+
137
+ def _apply_doctor_tool_availability_overrides(available: list[str], unavailable: list[dict]) -> tuple[list[str], list[dict]]:
138
+ """Adjust runtime-gated tool availability for doctor diagnostics."""
139
+ updated_available = list(available)
140
+ updated_unavailable = []
141
+ for item in unavailable:
142
+ name = item.get("name")
143
+ if _is_kanban_worker_env_gate(item):
144
+ if "kanban" not in updated_available:
145
+ updated_available.append("kanban")
146
+ continue
147
+ if name == "honcho" and _honcho_is_configured_for_doctor():
148
+ if "honcho" not in updated_available:
149
+ updated_available.append("honcho")
150
+ continue
151
+ updated_unavailable.append(item)
152
+ return updated_available, updated_unavailable
153
+
154
+
155
+ def _has_healthy_oauth_fallback_for_apikey_provider(provider_label: str) -> bool:
156
+ """Return True when a direct API-key probe failure is non-blocking.
157
+
158
+ Some provider families support both a direct API-key path and a separate
159
+ OAuth runtime path. When the OAuth path is already healthy, doctor should
160
+ still show a failed API-key connectivity row, but it should not promote
161
+ that direct-key problem into the final blocking summary.
162
+ """
163
+ try:
164
+ from hermes_cli.auth import (
165
+ get_gemini_oauth_auth_status,
166
+ get_minimax_oauth_auth_status,
167
+ )
168
+ except Exception:
169
+ return False
170
+
171
+ normalized = (provider_label or "").strip().lower()
172
+ if normalized in {"google / gemini", "gemini"}:
173
+ return bool((get_gemini_oauth_auth_status() or {}).get("logged_in"))
174
+ if normalized == "minimax":
175
+ return bool((get_minimax_oauth_auth_status() or {}).get("logged_in"))
176
+ return False
177
+
178
+
179
+ def check_ok(text: str, detail: str = ""):
180
+ print(f" {color('✓', Colors.GREEN)} {text}" + (f" {color(detail, Colors.DIM)}" if detail else ""))
181
+
182
+ def check_warn(text: str, detail: str = ""):
183
+ print(f" {color('⚠', Colors.YELLOW)} {text}" + (f" {color(detail, Colors.DIM)}" if detail else ""))
184
+
185
+ def check_fail(text: str, detail: str = ""):
186
+ print(f" {color('✗', Colors.RED)} {text}" + (f" {color(detail, Colors.DIM)}" if detail else ""))
187
+
188
+ def check_info(text: str):
189
+ print(f" {color('→', Colors.CYAN)} {text}")
190
+
191
+
192
+ def _check_gateway_service_linger(issues: list[str]) -> None:
193
+ """Warn when a systemd user gateway service will stop after logout."""
194
+ try:
195
+ from hermes_cli.gateway import (
196
+ get_systemd_linger_status,
197
+ get_systemd_unit_path,
198
+ is_linux,
199
+ )
200
+ except Exception as e:
201
+ check_warn("Gateway service linger", f"(could not import gateway helpers: {e})")
202
+ return
203
+
204
+ if not is_linux():
205
+ return
206
+
207
+ unit_path = get_systemd_unit_path()
208
+ if not unit_path.exists():
209
+ return
210
+
211
+ print()
212
+ print(color("◆ Gateway Service", Colors.CYAN, Colors.BOLD))
213
+
214
+ linger_enabled, linger_detail = get_systemd_linger_status()
215
+ if linger_enabled is True:
216
+ check_ok("Systemd linger enabled", "(gateway service survives logout)")
217
+ elif linger_enabled is False:
218
+ check_warn("Systemd linger disabled", "(gateway may stop after logout)")
219
+ check_info("Run: sudo loginctl enable-linger $USER")
220
+ issues.append("Enable linger for the gateway user service: sudo loginctl enable-linger $USER")
221
+ else:
222
+ check_warn("Could not verify systemd linger", f"({linger_detail})")
223
+
224
+
225
+ _APIKEY_PROVIDERS_CACHE: list | None = None
226
+
227
+
228
+ def _build_apikey_providers_list() -> list:
229
+ """Build the API-key provider health-check list once and cache it.
230
+
231
+ Tuple format: (name, env_vars, default_url, base_env, supports_models_endpoint)
232
+ Base list augmented with any ProviderProfile with auth_type="api_key" not
233
+ already present — adding plugins/model-providers/<name>/ is sufficient to get into doctor.
234
+ """
235
+ _static = [
236
+ ("Z.AI / GLM", ("GLM_API_KEY", "ZAI_API_KEY", "Z_AI_API_KEY"), "https://api.z.ai/api/paas/v4/models", "GLM_BASE_URL", True),
237
+ ("Kimi / Moonshot", ("KIMI_API_KEY",), "https://api.moonshot.ai/v1/models", "KIMI_BASE_URL", True),
238
+ ("StepFun Step Plan", ("STEPFUN_API_KEY",), "https://api.stepfun.ai/step_plan/v1/models", "STEPFUN_BASE_URL", True),
239
+ ("Kimi / Moonshot (China)", ("KIMI_CN_API_KEY",), "https://api.moonshot.cn/v1/models", None, True),
240
+ ("Arcee AI", ("ARCEEAI_API_KEY",), "https://api.arcee.ai/api/v1/models", "ARCEE_BASE_URL", True),
241
+ ("GMI Cloud", ("GMI_API_KEY",), "https://api.gmi-serving.com/v1/models", "GMI_BASE_URL", True),
242
+ ("DeepSeek", ("DEEPSEEK_API_KEY",), "https://api.deepseek.com/v1/models", "DEEPSEEK_BASE_URL", True),
243
+ ("Hugging Face", ("HF_TOKEN",), "https://router.huggingface.co/v1/models", "HF_BASE_URL", True),
244
+ ("NVIDIA NIM", ("NVIDIA_API_KEY",), "https://integrate.api.nvidia.com/v1/models", "NVIDIA_BASE_URL", True),
245
+ ("Alibaba/DashScope", ("DASHSCOPE_API_KEY",), "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/models", "DASHSCOPE_BASE_URL", True),
246
+ # MiniMax global: /v1 endpoint supports /models.
247
+ ("MiniMax", ("MINIMAX_API_KEY",), "https://api.minimax.io/v1/models", "MINIMAX_BASE_URL", True),
248
+ # MiniMax CN: /v1 endpoint does NOT support /models (returns 404).
249
+ ("MiniMax (China)", ("MINIMAX_CN_API_KEY",), "https://api.minimaxi.com/v1/models", "MINIMAX_CN_BASE_URL", False),
250
+ ("Vercel AI Gateway", ("AI_GATEWAY_API_KEY",), "https://ai-gateway.vercel.sh/v1/models", "AI_GATEWAY_BASE_URL", True),
251
+ ("Kilo Code", ("KILOCODE_API_KEY",), "https://api.kilo.ai/api/gateway/models", "KILOCODE_BASE_URL", True),
252
+ ("OpenCode Zen", ("OPENCODE_ZEN_API_KEY",), "https://opencode.ai/zen/v1/models", "OPENCODE_ZEN_BASE_URL", True),
253
+ # OpenCode Go has no shared /models endpoint; skip the health check.
254
+ ("OpenCode Go", ("OPENCODE_GO_API_KEY",), None, "OPENCODE_GO_BASE_URL", False),
255
+ ]
256
+ _known_names = {t[0] for t in _static}
257
+ # Also index by profile canonical name so profiles without display_name
258
+ # don't create duplicate entries for providers already in the static list.
259
+ _known_canonical: set[str] = set()
260
+ _name_to_canonical = {
261
+ "Z.AI / GLM": "zai", "Kimi / Moonshot": "kimi-coding",
262
+ "StepFun Step Plan": "stepfun", "Kimi / Moonshot (China)": "kimi-coding-cn",
263
+ "Arcee AI": "arcee", "GMI Cloud": "gmi", "DeepSeek": "deepseek",
264
+ "Hugging Face": "huggingface", "NVIDIA NIM": "nvidia",
265
+ "Alibaba/DashScope": "alibaba", "MiniMax": "minimax",
266
+ "MiniMax (China)": "minimax-cn", "Vercel AI Gateway": "ai-gateway",
267
+ "Kilo Code": "kilocode", "OpenCode Zen": "opencode-zen",
268
+ "OpenCode Go": "opencode-go",
269
+ }
270
+ for _label, _canonical in _name_to_canonical.items():
271
+ _known_canonical.add(_canonical)
272
+ # Providers that already have a dedicated health check above the generic
273
+ # API-key loop (with custom headers/auth). Skip their pluggable profiles
274
+ # here so the generic Bearer-auth loop doesn't run a duplicate, broken
275
+ # check (e.g. Anthropic native API requires x-api-key, not Bearer).
276
+ _dedicated_canonical = {"anthropic", "openrouter", "bedrock"}
277
+ _known_canonical.update(_dedicated_canonical)
278
+ try:
279
+ from providers import list_providers
280
+ from providers.base import ProviderProfile as _PP
281
+ try:
282
+ from hermes_cli.providers import normalize_provider as _normalize_provider
283
+ except Exception: # pragma: no cover - normalization is best-effort
284
+ def _normalize_provider(_name: str) -> str:
285
+ return (_name or "").strip().lower()
286
+ for _pp in list_providers():
287
+ if not isinstance(_pp, _PP) or _pp.auth_type != "api_key" or not _pp.env_vars:
288
+ continue
289
+ _label = _pp.display_name or _pp.name
290
+ if _label in _known_names or _pp.name in _known_canonical:
291
+ continue
292
+ _candidates = {_normalize_provider(_pp.name)}
293
+ for _alias in (_pp.aliases or ()):
294
+ _candidates.add(_normalize_provider(_alias))
295
+ if _candidates & _dedicated_canonical:
296
+ continue
297
+ # Separate API-key vars from base-URL override vars — the health-check
298
+ # loop sends the first found value as Authorization: Bearer, so a URL
299
+ # string must never be picked.
300
+ _key_vars = tuple(
301
+ v for v in _pp.env_vars
302
+ if not v.endswith("_BASE_URL") and not v.endswith("_URL")
303
+ )
304
+ _base_var = next(
305
+ (v for v in _pp.env_vars if v.endswith("_BASE_URL") or v.endswith("_URL")),
306
+ None,
307
+ )
308
+ if not _key_vars:
309
+ continue
310
+ _models_url = (
311
+ (_pp.models_url or (_pp.base_url.rstrip("/") + "/models"))
312
+ if _pp.base_url else None
313
+ )
314
+ _hc = getattr(_pp, "supports_health_check", True)
315
+ _static.append((_label, _key_vars, _models_url, _base_var, _hc))
316
+ except Exception:
317
+ pass
318
+ return _static
319
+
320
+
321
+ def run_doctor(args):
322
+ """Run diagnostic checks."""
323
+ should_fix = getattr(args, 'fix', False)
324
+ ack_target = getattr(args, 'ack', None)
325
+
326
+ # Doctor runs from the interactive CLI, so CLI-gated tool availability
327
+ # checks (like cronjob management) should see the same context as `hermes`.
328
+ os.environ.setdefault("HERMES_INTERACTIVE", "1")
329
+
330
+ # Handle `hermes doctor --ack <id>` as a fast path. Persist the ack and
331
+ # return without running the rest of the diagnostics — the user has
332
+ # already seen the advisory and just wants to silence it.
333
+ if ack_target:
334
+ from hermes_cli.security_advisories import (
335
+ ADVISORIES,
336
+ ack_advisory,
337
+ )
338
+ valid_ids = {a.id for a in ADVISORIES}
339
+ if ack_target not in valid_ids:
340
+ print(color(
341
+ f"Unknown advisory ID: {ack_target!r}. Known IDs: "
342
+ f"{', '.join(sorted(valid_ids)) or '(none)'}",
343
+ Colors.RED,
344
+ ))
345
+ sys.exit(2)
346
+ if ack_advisory(ack_target):
347
+ print(color(
348
+ f" ✓ Acknowledged advisory {ack_target}. "
349
+ f"It will no longer trigger startup banners.",
350
+ Colors.GREEN,
351
+ ))
352
+ else:
353
+ print(color(
354
+ f" ✗ Failed to persist ack for {ack_target}. "
355
+ f"Check ~/.hermes/config.yaml is writable.",
356
+ Colors.RED,
357
+ ))
358
+ sys.exit(1)
359
+ return
360
+
361
+ issues = []
362
+ manual_issues = [] # issues that can't be auto-fixed
363
+ fixed_count = 0
364
+
365
+ print()
366
+ print(color("┌─────────────────────────────────────────────────────────┐", Colors.CYAN))
367
+ print(color("│ 🩺 Hermes Doctor │", Colors.CYAN))
368
+ print(color("└─────────────────────────────────────────────────────────┘", Colors.CYAN))
369
+
370
+ # =========================================================================
371
+ # Check: Security advisories (RUNS FIRST — these are the most urgent)
372
+ # =========================================================================
373
+ print()
374
+ print(color("◆ Security Advisories", Colors.CYAN, Colors.BOLD))
375
+ try:
376
+ from hermes_cli.security_advisories import (
377
+ detect_compromised,
378
+ filter_unacked,
379
+ full_remediation_text,
380
+ get_acked_ids,
381
+ )
382
+ all_hits = detect_compromised()
383
+ fresh_hits = filter_unacked(all_hits)
384
+ if fresh_hits:
385
+ for hit in fresh_hits:
386
+ check_fail(
387
+ f"{hit.advisory.title}",
388
+ f"({hit.package}=={hit.installed_version})",
389
+ )
390
+ # Print the full remediation block, indented under the
391
+ # check_fail header so it reads as a single section.
392
+ for line in full_remediation_text(hit):
393
+ if line:
394
+ print(f" {color(line, Colors.YELLOW)}")
395
+ else:
396
+ print()
397
+ # Funnel into the action list so the summary block surfaces it
398
+ # for users who scroll past the section.
399
+ manual_issues.append(
400
+ f"Resolve security advisory {hit.advisory.id}: "
401
+ f"uninstall {hit.package}=={hit.installed_version} and "
402
+ f"rotate credentials, then run "
403
+ f"`hermes doctor --ack {hit.advisory.id}`."
404
+ )
405
+ # Acked-but-still-installed: show as informational so the user
406
+ # knows the package is still on disk after the ack.
407
+ acked_ids = get_acked_ids()
408
+ for h in all_hits:
409
+ if h.advisory.id in acked_ids:
410
+ check_warn(
411
+ f"{h.package}=={h.installed_version} still installed "
412
+ f"(advisory {h.advisory.id} acknowledged)",
413
+ )
414
+ else:
415
+ check_ok("No active security advisories")
416
+ except Exception as e:
417
+ # Never let a bug in the advisory check block the rest of doctor.
418
+ check_warn(f"Security advisory check failed: {e}")
419
+
420
+ # =========================================================================
421
+ # Check: Python version
422
+ # =========================================================================
423
+ print()
424
+ print(color("◆ Python Environment", Colors.CYAN, Colors.BOLD))
425
+
426
+ py_version = sys.version_info
427
+ if py_version >= (3, 11):
428
+ check_ok(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}")
429
+ elif py_version >= (3, 10):
430
+ check_ok(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}")
431
+ check_warn("Python 3.11+ recommended for RL Training tools (tinker requires >= 3.11)")
432
+ elif py_version >= (3, 8):
433
+ check_warn(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}", "(3.10+ recommended)")
434
+ else:
435
+ check_fail(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}", "(3.10+ required)")
436
+ issues.append("Upgrade Python to 3.10+")
437
+
438
+ # Check if in virtual environment
439
+ in_venv = sys.prefix != sys.base_prefix
440
+ if in_venv:
441
+ check_ok("Virtual environment active")
442
+ else:
443
+ check_warn("Not in virtual environment", "(recommended)")
444
+
445
+ # =========================================================================
446
+ # Check: Required packages
447
+ # =========================================================================
448
+ print()
449
+ print(color("◆ Required Packages", Colors.CYAN, Colors.BOLD))
450
+
451
+ required_packages = [
452
+ ("openai", "OpenAI SDK"),
453
+ ("rich", "Rich (terminal UI)"),
454
+ ("dotenv", "python-dotenv"),
455
+ ("yaml", "PyYAML"),
456
+ ("httpx", "HTTPX"),
457
+ ]
458
+
459
+ optional_packages = [
460
+ ("croniter", "Croniter (cron expressions)"),
461
+ ("telegram", "python-telegram-bot"),
462
+ ("discord", "discord.py"),
463
+ ]
464
+
465
+ for module, name in required_packages:
466
+ try:
467
+ __import__(module)
468
+ check_ok(name)
469
+ except ImportError:
470
+ check_fail(name, "(missing)")
471
+ issues.append(f"Install {name}: {_python_install_cmd()} {module}")
472
+
473
+ for module, name in optional_packages:
474
+ try:
475
+ __import__(module)
476
+ check_ok(name, "(optional)")
477
+ except ImportError:
478
+ check_warn(name, "(optional, not installed)")
479
+
480
+ # =========================================================================
481
+ # Check: Configuration files
482
+ # =========================================================================
483
+ print()
484
+ print(color("◆ Configuration Files", Colors.CYAN, Colors.BOLD))
485
+
486
+ # Check ~/.hermes/.env (primary location for user config)
487
+ env_path = HERMES_HOME / '.env'
488
+ if env_path.exists():
489
+ check_ok(f"{_DHH}/.env file exists")
490
+
491
+ # Check for common issues. Pin encoding to UTF-8 because .env files are
492
+ # written as UTF-8 everywhere in the codebase, while Path.read_text()
493
+ # defaults to the system locale — which crashes on non-UTF-8 Windows
494
+ # locales (e.g. GBK) as soon as the file contains any non-ASCII byte.
495
+ content = env_path.read_text(encoding="utf-8")
496
+ if _has_provider_env_config(content):
497
+ check_ok("API key or custom endpoint configured")
498
+ else:
499
+ check_warn(f"No API key found in {_DHH}/.env")
500
+ issues.append("Run 'hermes setup' to configure API keys")
501
+ else:
502
+ # Also check project root as fallback
503
+ fallback_env = PROJECT_ROOT / '.env'
504
+ if fallback_env.exists():
505
+ check_ok(".env file exists (in project directory)")
506
+ else:
507
+ check_fail(f"{_DHH}/.env file missing")
508
+ if should_fix:
509
+ env_path.parent.mkdir(parents=True, exist_ok=True)
510
+ env_path.touch()
511
+ check_ok(f"Created empty {_DHH}/.env")
512
+ check_info("Run 'hermes setup' to configure API keys")
513
+ fixed_count += 1
514
+ else:
515
+ check_info("Run 'hermes setup' to create one")
516
+ issues.append("Run 'hermes setup' to create .env")
517
+
518
+ # Check ~/.hermes/config.yaml (primary) or project cli-config.yaml (fallback)
519
+ config_path = HERMES_HOME / 'config.yaml'
520
+ if config_path.exists():
521
+ check_ok(f"{_DHH}/config.yaml exists")
522
+
523
+ # Validate model.provider and model.default values
524
+ try:
525
+ import yaml as _yaml
526
+ cfg = _yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
527
+ model_section = cfg.get("model") or {}
528
+ provider_raw = (model_section.get("provider") or "").strip()
529
+ provider = provider_raw.lower()
530
+ default_model = (model_section.get("default") or model_section.get("model") or "").strip()
531
+
532
+ known_providers: set = set()
533
+ try:
534
+ from hermes_cli.auth import (
535
+ PROVIDER_REGISTRY,
536
+ resolve_provider as _resolve_auth_provider,
537
+ )
538
+ known_providers = set(PROVIDER_REGISTRY.keys()) | {"openrouter", "custom", "auto"}
539
+ except Exception:
540
+ _resolve_auth_provider = None
541
+ pass
542
+ try:
543
+ from hermes_cli.config import get_compatible_custom_providers as _compatible_custom_providers
544
+ from hermes_cli.providers import (
545
+ normalize_provider as _normalize_catalog_provider,
546
+ resolve_provider_full as _resolve_provider_full,
547
+ )
548
+ except Exception:
549
+ _compatible_custom_providers = None
550
+ _normalize_catalog_provider = None
551
+ _resolve_provider_full = None
552
+
553
+ custom_providers = []
554
+ if _compatible_custom_providers is not None:
555
+ try:
556
+ custom_providers = _compatible_custom_providers(cfg)
557
+ except Exception:
558
+ custom_providers = []
559
+
560
+ user_providers = cfg.get("providers")
561
+ if isinstance(user_providers, dict):
562
+ known_providers.update(str(name).strip().lower() for name in user_providers if str(name).strip())
563
+ for entry in custom_providers:
564
+ if not isinstance(entry, dict):
565
+ continue
566
+ name = str(entry.get("name") or "").strip()
567
+ if name:
568
+ known_providers.add("custom:" + name.lower().replace(" ", "-"))
569
+
570
+ valid_provider_ids = set(known_providers)
571
+ provider_ids_to_accept = {provider} if provider else set()
572
+ if _normalize_catalog_provider is not None:
573
+ for known_provider in known_providers:
574
+ try:
575
+ valid_provider_ids.add(_normalize_catalog_provider(known_provider))
576
+ except Exception:
577
+ continue
578
+
579
+ runtime_provider = provider
580
+ if (
581
+ provider
582
+ and _resolve_auth_provider is not None
583
+ and provider not in {"auto", "custom"}
584
+ ):
585
+ try:
586
+ runtime_provider = _resolve_auth_provider(provider)
587
+ provider_ids_to_accept.add(runtime_provider)
588
+ except Exception:
589
+ runtime_provider = provider
590
+
591
+ catalog_provider = provider
592
+ if (
593
+ provider
594
+ and _resolve_provider_full is not None
595
+ and provider not in {"auto", "custom"}
596
+ ):
597
+ provider_def = _resolve_provider_full(provider, user_providers, custom_providers)
598
+ catalog_provider = provider_def.id if provider_def is not None else None
599
+ if catalog_provider is not None:
600
+ provider_ids_to_accept.add(catalog_provider)
601
+
602
+ if provider and provider != "auto":
603
+ if catalog_provider is None or (
604
+ known_providers
605
+ and not (provider_ids_to_accept & valid_provider_ids)
606
+ ):
607
+ known_list = ", ".join(sorted(known_providers)) if known_providers else "(unavailable)"
608
+ check_fail(
609
+ f"model.provider '{provider_raw}' is not a recognised provider",
610
+ f"(known: {known_list})",
611
+ )
612
+ issues.append(
613
+ f"model.provider '{provider_raw}' is unknown. "
614
+ f"Valid providers: {known_list}. "
615
+ f"Fix: run 'hermes config set model.provider <valid_provider>'"
616
+ )
617
+
618
+ # Warn if model is set to a provider-prefixed name on a provider that doesn't use them
619
+ provider_for_policy = runtime_provider or catalog_provider
620
+ providers_accepting_vendor_slugs = {
621
+ "openrouter",
622
+ "custom",
623
+ "auto",
624
+ "ai-gateway",
625
+ "kilocode",
626
+ "opencode-zen",
627
+ "huggingface",
628
+ "lmstudio",
629
+ "nous",
630
+ }
631
+ if (
632
+ default_model
633
+ and "/" in default_model
634
+ and provider_for_policy
635
+ and provider_for_policy not in providers_accepting_vendor_slugs
636
+ ):
637
+ check_warn(
638
+ f"model.default '{default_model}' uses a vendor/model slug but provider is '{provider_raw}'",
639
+ "(vendor-prefixed slugs belong to aggregators like openrouter)",
640
+ )
641
+ issues.append(
642
+ f"model.default '{default_model}' is vendor-prefixed but model.provider is '{provider_raw}'. "
643
+ "Either set model.provider to 'openrouter', or drop the vendor prefix."
644
+ )
645
+
646
+ # Check credentials for the configured provider.
647
+ # Limit to API-key providers in PROVIDER_REGISTRY — other provider
648
+ # types (OAuth, SDK, openrouter/anthropic/custom/auto) have their
649
+ # own env-var checks elsewhere in doctor, and get_auth_status()
650
+ # returns a bare {logged_in: False} for anything it doesn't
651
+ # explicitly dispatch, which would produce false positives.
652
+ if runtime_provider and runtime_provider not in {"auto", "custom", "openrouter"}:
653
+ try:
654
+ from hermes_cli.auth import PROVIDER_REGISTRY, get_auth_status
655
+ pconfig = PROVIDER_REGISTRY.get(runtime_provider)
656
+ if pconfig and getattr(pconfig, "auth_type", "") == "api_key":
657
+ status = get_auth_status(runtime_provider) or {}
658
+ configured = bool(
659
+ status.get("configured")
660
+ or status.get("logged_in")
661
+ or status.get("api_key")
662
+ )
663
+ if not configured:
664
+ check_fail(
665
+ f"model.provider '{runtime_provider}' is set but no API key is configured",
666
+ "(check ~/.hermes/.env or run 'hermes setup')",
667
+ )
668
+ issues.append(
669
+ f"No credentials found for provider '{runtime_provider}'. "
670
+ f"Run 'hermes setup' or set the provider's API key in {_DHH}/.env, "
671
+ f"or switch providers with 'hermes config set model.provider <name>'"
672
+ )
673
+ except Exception:
674
+ pass
675
+
676
+ except Exception as e:
677
+ check_warn("Could not validate model/provider config", f"({e})")
678
+ else:
679
+ fallback_config = PROJECT_ROOT / 'cli-config.yaml'
680
+ if fallback_config.exists():
681
+ check_ok("cli-config.yaml exists (in project directory)")
682
+ else:
683
+ if should_fix:
684
+ config_path.parent.mkdir(parents=True, exist_ok=True)
685
+ example_config = PROJECT_ROOT / 'cli-config.yaml.example'
686
+ if example_config.exists():
687
+ shutil.copy2(str(example_config), str(config_path))
688
+ check_ok(f"Created {_DHH}/config.yaml from cli-config.yaml.example")
689
+ else:
690
+ from hermes_cli.config import DEFAULT_CONFIG, save_config
691
+ save_config(DEFAULT_CONFIG)
692
+ check_ok(f"Created {_DHH}/config.yaml from defaults")
693
+ fixed_count += 1
694
+ else:
695
+ check_warn("config.yaml not found", "(using defaults)")
696
+
697
+ # Check config version and stale keys
698
+ config_path = HERMES_HOME / 'config.yaml'
699
+ if config_path.exists():
700
+ try:
701
+ from hermes_cli.config import check_config_version, migrate_config
702
+ current_ver, latest_ver = check_config_version()
703
+ if current_ver < latest_ver:
704
+ check_warn(
705
+ f"Config version outdated (v{current_ver} → v{latest_ver})",
706
+ "(new settings available)"
707
+ )
708
+ if should_fix:
709
+ try:
710
+ migrate_config(interactive=False, quiet=False)
711
+ check_ok("Config migrated to latest version")
712
+ fixed_count += 1
713
+ except Exception as mig_err:
714
+ check_warn(f"Auto-migration failed: {mig_err}")
715
+ issues.append("Run 'hermes setup' to migrate config")
716
+ else:
717
+ issues.append("Run 'hermes doctor --fix' or 'hermes setup' to migrate config")
718
+ else:
719
+ check_ok(f"Config version up to date (v{current_ver})")
720
+ except Exception:
721
+ pass
722
+
723
+ # Detect stale root-level model keys (known bug source — PR #4329)
724
+ try:
725
+ import yaml
726
+ with open(config_path, encoding="utf-8") as f:
727
+ raw_config = yaml.safe_load(f) or {}
728
+ stale_root_keys = [k for k in ("provider", "base_url") if k in raw_config and isinstance(raw_config[k], str)]
729
+ if stale_root_keys:
730
+ check_warn(
731
+ f"Stale root-level config keys: {', '.join(stale_root_keys)}",
732
+ "(should be under 'model:' section)"
733
+ )
734
+ if should_fix:
735
+ model_section = raw_config.setdefault("model", {})
736
+ for k in stale_root_keys:
737
+ if not model_section.get(k):
738
+ model_section[k] = raw_config.pop(k)
739
+ else:
740
+ raw_config.pop(k)
741
+ from utils import atomic_yaml_write
742
+ atomic_yaml_write(config_path, raw_config)
743
+ check_ok("Migrated stale root-level keys into model section")
744
+ fixed_count += 1
745
+ else:
746
+ issues.append("Stale root-level provider/base_url in config.yaml — run 'hermes doctor --fix'")
747
+ except Exception:
748
+ pass
749
+
750
+ # Validate config structure (catches malformed custom_providers, etc.)
751
+ try:
752
+ from hermes_cli.config import validate_config_structure
753
+ config_issues = validate_config_structure()
754
+ if config_issues:
755
+ print()
756
+ print(color("◆ Config Structure", Colors.CYAN, Colors.BOLD))
757
+ for ci in config_issues:
758
+ if ci.severity == "error":
759
+ check_fail(ci.message)
760
+ else:
761
+ check_warn(ci.message)
762
+ # Show the hint indented
763
+ for hint_line in ci.hint.splitlines():
764
+ check_info(hint_line)
765
+ issues.append(ci.message)
766
+ except Exception:
767
+ pass
768
+
769
+ # =========================================================================
770
+ # Check: Auth providers
771
+ # =========================================================================
772
+ print()
773
+ print(color("◆ Auth Providers", Colors.CYAN, Colors.BOLD))
774
+
775
+ try:
776
+ from hermes_cli.auth import (
777
+ get_nous_auth_status,
778
+ get_codex_auth_status,
779
+ get_gemini_oauth_auth_status,
780
+ get_minimax_oauth_auth_status,
781
+ )
782
+
783
+ nous_status = get_nous_auth_status()
784
+ if nous_status.get("logged_in"):
785
+ check_ok("Nous Portal auth", "(logged in)")
786
+ else:
787
+ check_warn("Nous Portal auth", "(not logged in)")
788
+
789
+ codex_status = get_codex_auth_status()
790
+ if codex_status.get("logged_in"):
791
+ check_ok("OpenAI Codex auth", "(logged in)")
792
+ else:
793
+ check_warn("OpenAI Codex auth", "(not logged in)")
794
+ if codex_status.get("error"):
795
+ check_info(codex_status["error"])
796
+
797
+ gemini_status = get_gemini_oauth_auth_status()
798
+ if gemini_status.get("logged_in"):
799
+ email = gemini_status.get("email") or ""
800
+ project = gemini_status.get("project_id") or ""
801
+ pieces = []
802
+ if email:
803
+ pieces.append(email)
804
+ if project:
805
+ pieces.append(f"project={project}")
806
+ suffix = f" ({', '.join(pieces)})" if pieces else ""
807
+ check_ok("Google Gemini OAuth", f"(logged in{suffix})")
808
+ else:
809
+ check_warn("Google Gemini OAuth", "(not logged in)")
810
+
811
+ minimax_status = get_minimax_oauth_auth_status()
812
+ if minimax_status.get("logged_in"):
813
+ region = minimax_status.get("region", "global")
814
+ check_ok("MiniMax OAuth", f"(logged in, region={region})")
815
+ else:
816
+ check_warn("MiniMax OAuth", "(not logged in)")
817
+ except Exception as e:
818
+ check_warn("Auth provider status", f"(could not check: {e})")
819
+
820
+ if _safe_which("codex"):
821
+ check_ok("codex CLI")
822
+ else:
823
+ # Native OAuth uses Hermes' own device-code flow — the Codex CLI is
824
+ # only needed if you want to import existing tokens from
825
+ # ~/.codex/auth.json. Downgrade to info so users running
826
+ # `hermes auth openai-codex` aren't told they're missing something.
827
+ check_info(
828
+ "codex CLI not installed "
829
+ "(optional — only required to import tokens from an existing Codex CLI login)"
830
+ )
831
+
832
+ # =========================================================================
833
+ # Check: Directory structure
834
+ # =========================================================================
835
+ print()
836
+ print(color("◆ Directory Structure", Colors.CYAN, Colors.BOLD))
837
+
838
+ hermes_home = HERMES_HOME
839
+ if hermes_home.exists():
840
+ check_ok(f"{_DHH} directory exists")
841
+ elif should_fix:
842
+ hermes_home.mkdir(parents=True, exist_ok=True)
843
+ check_ok(f"Created {_DHH} directory")
844
+ fixed_count += 1
845
+ else:
846
+ check_warn(f"{_DHH} not found", "(will be created on first use)")
847
+
848
+ # Check expected subdirectories
849
+ expected_subdirs = ["cron", "sessions", "logs", "skills", "memories"]
850
+ for subdir_name in expected_subdirs:
851
+ subdir_path = hermes_home / subdir_name
852
+ if subdir_path.exists():
853
+ check_ok(f"{_DHH}/{subdir_name}/ exists")
854
+ elif should_fix:
855
+ subdir_path.mkdir(parents=True, exist_ok=True)
856
+ check_ok(f"Created {_DHH}/{subdir_name}/")
857
+ fixed_count += 1
858
+ else:
859
+ check_warn(f"{_DHH}/{subdir_name}/ not found", "(will be created on first use)")
860
+
861
+ # Check for SOUL.md persona file
862
+ soul_path = hermes_home / "SOUL.md"
863
+ if soul_path.exists():
864
+ content = soul_path.read_text(encoding="utf-8").strip()
865
+ # Check if it's just the template comments (no real content)
866
+ lines = [l for l in content.splitlines() if l.strip() and not l.strip().startswith(("<!--", "-->", "#"))]
867
+ if lines:
868
+ check_ok(f"{_DHH}/SOUL.md exists (persona configured)")
869
+ else:
870
+ check_info(f"{_DHH}/SOUL.md exists but is empty — edit it to customize personality")
871
+ else:
872
+ check_warn(f"{_DHH}/SOUL.md not found", "(create it to give Hermes a custom personality)")
873
+ if should_fix:
874
+ soul_path.parent.mkdir(parents=True, exist_ok=True)
875
+ soul_path.write_text(
876
+ "# Hermes Agent Persona\n\n"
877
+ "<!-- Edit this file to customize how Hermes communicates. -->\n\n"
878
+ "You are Hermes, a helpful AI assistant.\n",
879
+ encoding="utf-8",
880
+ )
881
+ check_ok(f"Created {_DHH}/SOUL.md with basic template")
882
+ fixed_count += 1
883
+
884
+ # Check memory directory
885
+ memories_dir = hermes_home / "memories"
886
+ if memories_dir.exists():
887
+ check_ok(f"{_DHH}/memories/ directory exists")
888
+ memory_file = memories_dir / "MEMORY.md"
889
+ user_file = memories_dir / "USER.md"
890
+ if memory_file.exists():
891
+ size = len(memory_file.read_text(encoding="utf-8").strip())
892
+ check_ok(f"MEMORY.md exists ({size} chars)")
893
+ else:
894
+ check_info("MEMORY.md not created yet (will be created when the agent first writes a memory)")
895
+ if user_file.exists():
896
+ size = len(user_file.read_text(encoding="utf-8").strip())
897
+ check_ok(f"USER.md exists ({size} chars)")
898
+ else:
899
+ check_info("USER.md not created yet (will be created when the agent first writes a memory)")
900
+ else:
901
+ check_warn(f"{_DHH}/memories/ not found", "(will be created on first use)")
902
+ if should_fix:
903
+ memories_dir.mkdir(parents=True, exist_ok=True)
904
+ check_ok(f"Created {_DHH}/memories/")
905
+ fixed_count += 1
906
+
907
+ # Check SQLite session store
908
+ state_db_path = hermes_home / "state.db"
909
+ if state_db_path.exists():
910
+ try:
911
+ import sqlite3
912
+ conn = sqlite3.connect(str(state_db_path))
913
+ cursor = conn.execute("SELECT COUNT(*) FROM sessions")
914
+ count = cursor.fetchone()[0]
915
+ conn.close()
916
+ check_ok(f"{_DHH}/state.db exists ({count} sessions)")
917
+ except Exception as e:
918
+ check_warn(f"{_DHH}/state.db exists but has issues: {e}")
919
+ else:
920
+ check_info(f"{_DHH}/state.db not created yet (will be created on first session)")
921
+
922
+ # Check WAL file size (unbounded growth indicates missed checkpoints)
923
+ wal_path = hermes_home / "state.db-wal"
924
+ if wal_path.exists():
925
+ try:
926
+ wal_size = wal_path.stat().st_size
927
+ if wal_size > 50 * 1024 * 1024: # 50 MB
928
+ check_warn(
929
+ f"WAL file is large ({wal_size // (1024*1024)} MB)",
930
+ "(may indicate missed checkpoints)"
931
+ )
932
+ if should_fix:
933
+ import sqlite3
934
+ conn = sqlite3.connect(str(state_db_path))
935
+ conn.execute("PRAGMA wal_checkpoint(PASSIVE)")
936
+ conn.close()
937
+ new_size = wal_path.stat().st_size if wal_path.exists() else 0
938
+ check_ok(f"WAL checkpoint performed ({wal_size // 1024}K → {new_size // 1024}K)")
939
+ fixed_count += 1
940
+ else:
941
+ issues.append("Large WAL file — run 'hermes doctor --fix' to checkpoint")
942
+ elif wal_size > 10 * 1024 * 1024: # 10 MB
943
+ check_info(f"WAL file is {wal_size // (1024*1024)} MB (normal for active sessions)")
944
+ except Exception:
945
+ pass
946
+
947
+ _check_gateway_service_linger(issues)
948
+
949
+ # =========================================================================
950
+ # Check: Command installation (hermes bin symlink)
951
+ # =========================================================================
952
+ if sys.platform != "win32":
953
+ print()
954
+ print(color("◆ Command Installation", Colors.CYAN, Colors.BOLD))
955
+
956
+ # Determine the venv entry point location
957
+ _venv_bin = None
958
+ for _venv_name in ("venv", ".venv"):
959
+ _candidate = PROJECT_ROOT / _venv_name / "bin" / "hermes"
960
+ if _candidate.exists():
961
+ _venv_bin = _candidate
962
+ break
963
+
964
+ # Determine the expected command link directory (mirrors install.sh logic)
965
+ _prefix = os.environ.get("PREFIX", "")
966
+ _is_termux_env = bool(os.environ.get("TERMUX_VERSION")) or "com.termux/files/usr" in _prefix
967
+ if _is_termux_env and _prefix:
968
+ _cmd_link_dir = Path(_prefix) / "bin"
969
+ _cmd_link_display = "$PREFIX/bin"
970
+ else:
971
+ _cmd_link_dir = Path.home() / ".local" / "bin"
972
+ _cmd_link_display = "~/.local/bin"
973
+ _cmd_link = _cmd_link_dir / "hermes"
974
+
975
+ if _venv_bin is None:
976
+ check_warn(
977
+ "Venv entry point not found",
978
+ "(hermes not in venv/bin/ or .venv/bin/ — reinstall with pip install -e '.[all]')"
979
+ )
980
+ manual_issues.append(
981
+ f"Reinstall entry point: cd {PROJECT_ROOT} && source venv/bin/activate && pip install -e '.[all]'"
982
+ )
983
+ else:
984
+ check_ok(f"Venv entry point exists ({_venv_bin.relative_to(PROJECT_ROOT)})")
985
+
986
+ # Check the symlink at the command link location
987
+ if _cmd_link.is_symlink():
988
+ _target = _cmd_link.resolve()
989
+ _expected = _venv_bin.resolve()
990
+ if _target == _expected:
991
+ check_ok(f"{_cmd_link_display}/hermes → correct target")
992
+ else:
993
+ check_warn(
994
+ f"{_cmd_link_display}/hermes points to wrong target",
995
+ f"(→ {_target}, expected → {_expected})"
996
+ )
997
+ if should_fix:
998
+ _cmd_link.unlink()
999
+ _cmd_link.symlink_to(_venv_bin)
1000
+ check_ok(f"Fixed symlink: {_cmd_link_display}/hermes → {_venv_bin}")
1001
+ fixed_count += 1
1002
+ else:
1003
+ issues.append(f"Broken symlink at {_cmd_link_display}/hermes — run 'hermes doctor --fix'")
1004
+ elif _cmd_link.exists():
1005
+ # It's a regular file, not a symlink — possibly a wrapper script
1006
+ check_ok(f"{_cmd_link_display}/hermes exists (non-symlink)")
1007
+ else:
1008
+ check_fail(
1009
+ f"{_cmd_link_display}/hermes not found",
1010
+ "(hermes command may not work outside the venv)"
1011
+ )
1012
+ if should_fix:
1013
+ _cmd_link_dir.mkdir(parents=True, exist_ok=True)
1014
+ _cmd_link.symlink_to(_venv_bin)
1015
+ check_ok(f"Created symlink: {_cmd_link_display}/hermes → {_venv_bin}")
1016
+ fixed_count += 1
1017
+
1018
+ # Check if the link dir is on PATH
1019
+ _path_dirs = os.environ.get("PATH", "").split(os.pathsep)
1020
+ if str(_cmd_link_dir) not in _path_dirs:
1021
+ check_warn(
1022
+ f"{_cmd_link_display} is not on your PATH",
1023
+ "(add it to your shell config: export PATH=\"$HOME/.local/bin:$PATH\")"
1024
+ )
1025
+ manual_issues.append(f"Add {_cmd_link_display} to your PATH")
1026
+ else:
1027
+ issues.append(f"Missing {_cmd_link_display}/hermes symlink — run 'hermes doctor --fix'")
1028
+
1029
+ # =========================================================================
1030
+ # Check: External tools
1031
+ # =========================================================================
1032
+ print()
1033
+ print(color("◆ External Tools", Colors.CYAN, Colors.BOLD))
1034
+
1035
+ # Git
1036
+ if _safe_which("git"):
1037
+ check_ok("git")
1038
+ else:
1039
+ check_warn("git not found", "(optional)")
1040
+
1041
+ # ripgrep (optional, for faster file search)
1042
+ if _safe_which("rg"):
1043
+ check_ok("ripgrep (rg)", "(faster file search)")
1044
+ else:
1045
+ check_warn("ripgrep (rg) not found", "(file search uses grep fallback)")
1046
+ check_info(f"Install for faster search: {_system_package_install_cmd('ripgrep')}")
1047
+
1048
+ # Docker (optional)
1049
+ terminal_env = os.getenv("TERMINAL_ENV", "local")
1050
+ if terminal_env == "docker":
1051
+ if _safe_which("docker"):
1052
+ # Check if docker daemon is running
1053
+ try:
1054
+ result = subprocess.run(["docker", "info"], capture_output=True, timeout=10)
1055
+ except subprocess.TimeoutExpired:
1056
+ result = None
1057
+ if result is not None and result.returncode == 0:
1058
+ check_ok("docker", "(daemon running)")
1059
+ else:
1060
+ check_fail("docker daemon not running")
1061
+ issues.append("Start Docker daemon")
1062
+ else:
1063
+ check_fail("docker not found", "(required for TERMINAL_ENV=docker)")
1064
+ issues.append("Install Docker or change TERMINAL_ENV")
1065
+ elif _safe_which("docker"):
1066
+ check_ok("docker", "(optional)")
1067
+ elif _is_termux():
1068
+ check_info("Docker backend is not available inside Termux (expected on Android)")
1069
+ else:
1070
+ check_warn("docker not found", "(optional)")
1071
+
1072
+ # SSH (if using ssh backend)
1073
+ if terminal_env == "ssh":
1074
+ ssh_host = os.getenv("TERMINAL_SSH_HOST")
1075
+ if ssh_host:
1076
+ # Try to connect
1077
+ try:
1078
+ result = subprocess.run(
1079
+ ["ssh", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", ssh_host, "echo ok"],
1080
+ capture_output=True,
1081
+ text=True,
1082
+ timeout=15
1083
+ )
1084
+ except subprocess.TimeoutExpired:
1085
+ result = None
1086
+ if result is not None and result.returncode == 0:
1087
+ check_ok(f"SSH connection to {ssh_host}")
1088
+ else:
1089
+ check_fail(f"SSH connection to {ssh_host}")
1090
+ issues.append(f"Check SSH configuration for {ssh_host}")
1091
+ else:
1092
+ check_fail("TERMINAL_SSH_HOST not set", "(required for TERMINAL_ENV=ssh)")
1093
+ issues.append("Set TERMINAL_SSH_HOST in .env")
1094
+
1095
+ # Daytona (if using daytona backend)
1096
+ if terminal_env == "daytona":
1097
+ daytona_key = os.getenv("DAYTONA_API_KEY")
1098
+ if daytona_key:
1099
+ check_ok("Daytona API key", "(configured)")
1100
+ else:
1101
+ check_fail("DAYTONA_API_KEY not set", "(required for TERMINAL_ENV=daytona)")
1102
+ issues.append("Set DAYTONA_API_KEY environment variable")
1103
+ try:
1104
+ from daytona import Daytona # noqa: F401 — SDK presence check
1105
+ check_ok("daytona SDK", "(installed)")
1106
+ except ImportError:
1107
+ check_fail("daytona SDK not installed", "(pip install daytona)")
1108
+ issues.append("Install daytona SDK: pip install daytona")
1109
+
1110
+ # Vercel Sandbox (if using vercel_sandbox backend)
1111
+ if terminal_env == "vercel_sandbox":
1112
+ runtime = os.getenv("TERMINAL_VERCEL_RUNTIME", "node24").strip() or "node24"
1113
+ from tools.terminal_tool import _SUPPORTED_VERCEL_RUNTIMES
1114
+ if runtime in _SUPPORTED_VERCEL_RUNTIMES:
1115
+ check_ok("Vercel runtime", f"({runtime})")
1116
+ else:
1117
+ supported = ", ".join(_SUPPORTED_VERCEL_RUNTIMES)
1118
+ check_fail("Vercel runtime unsupported", f"({runtime}; use {supported})")
1119
+ issues.append(f"Set TERMINAL_VERCEL_RUNTIME to one of: {supported}")
1120
+
1121
+ disk = os.getenv("TERMINAL_CONTAINER_DISK", "51200").strip()
1122
+ if disk in {"", "0", "51200"}:
1123
+ check_ok("Vercel disk setting", "(uses platform default)")
1124
+ else:
1125
+ check_fail("Vercel custom disk unsupported", "(reset terminal.container_disk to 51200)")
1126
+ issues.append("Vercel Sandbox does not support custom container_disk; use the shared default 51200")
1127
+
1128
+ if importlib.util.find_spec("vercel") is not None:
1129
+ check_ok("vercel SDK", "(installed)")
1130
+ else:
1131
+ check_fail("vercel SDK not installed", "(pip install 'hermes-agent[vercel]')")
1132
+ issues.append("Install the Vercel optional dependency: pip install 'hermes-agent[vercel]'")
1133
+
1134
+ auth_status = describe_vercel_auth()
1135
+ if auth_status.ok:
1136
+ check_ok("Vercel auth", f"({auth_status.label})")
1137
+ elif auth_status.label.startswith("partial"):
1138
+ check_fail("Vercel auth incomplete", f"({auth_status.label})")
1139
+ issues.append("Set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID together")
1140
+ else:
1141
+ check_fail("Vercel auth not configured", f"({auth_status.label})")
1142
+ issues.append(
1143
+ "Configure Vercel Sandbox auth with VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID"
1144
+ )
1145
+ for line in auth_status.detail_lines:
1146
+ check_info(f"Vercel auth {line}")
1147
+
1148
+ persistent = os.getenv("TERMINAL_CONTAINER_PERSISTENT", "true").lower() in {"1", "true", "yes", "on"}
1149
+ if persistent:
1150
+ check_info("Vercel persistence: snapshot filesystem only; live processes do not survive sandbox recreation")
1151
+ else:
1152
+ check_info("Vercel persistence: ephemeral filesystem")
1153
+
1154
+ # Node.js + agent-browser (for browser automation tools)
1155
+ if _safe_which("node"):
1156
+ check_ok("Node.js")
1157
+ # Check if agent-browser is installed
1158
+ agent_browser_path = PROJECT_ROOT / "node_modules" / "agent-browser"
1159
+ agent_browser_ok = False
1160
+ if agent_browser_path.exists():
1161
+ check_ok("agent-browser (Node.js)", "(browser automation)")
1162
+ agent_browser_ok = True
1163
+ elif shutil.which("agent-browser"):
1164
+ check_ok("agent-browser", "(browser automation)")
1165
+ agent_browser_ok = True
1166
+ elif _is_termux():
1167
+ check_info("agent-browser is not installed (expected in the tested Termux path)")
1168
+ check_info("Install it manually later with: npm install -g agent-browser && agent-browser install")
1169
+ check_info("Termux browser setup:")
1170
+ for step in _termux_browser_setup_steps(node_installed=True):
1171
+ check_info(step)
1172
+ else:
1173
+ check_warn("agent-browser not installed", "(run: npm install)")
1174
+
1175
+ # Chromium presence — the browser tools silently fail to register when
1176
+ # agent-browser is found but no Playwright-managed Chromium is on disk
1177
+ # (tools/browser_tool.py::check_browser_requirements filters them out
1178
+ # before the agent ever sees them). Reuse the exact predicate it uses
1179
+ # so the two checks cannot diverge. Skip on Termux (not a tested
1180
+ # path).
1181
+ if agent_browser_ok and not _is_termux():
1182
+ try:
1183
+ # Lazy import: browser_tool is a ~150KB module we don't want
1184
+ # to eagerly load in every `hermes doctor` invocation.
1185
+ from tools.browser_tool import (
1186
+ _chromium_installed,
1187
+ _is_camofox_mode,
1188
+ _get_cloud_provider,
1189
+ _get_cdp_override,
1190
+ _using_lightpanda_engine,
1191
+ )
1192
+ except Exception:
1193
+ # If browser_tool can't even import, that's a separate bug
1194
+ # surfaced elsewhere; don't crash doctor.
1195
+ pass
1196
+ else:
1197
+ # Only warn about Chromium if the installed engine actually
1198
+ # requires it: Camofox, CDP override, a cloud provider, or
1199
+ # Lightpanda all bypass the local Chromium requirement.
1200
+ skip_chromium_check = (
1201
+ _is_camofox_mode()
1202
+ or bool(_get_cdp_override())
1203
+ or _get_cloud_provider() is not None
1204
+ or _using_lightpanda_engine()
1205
+ )
1206
+ if not skip_chromium_check:
1207
+ if _chromium_installed():
1208
+ check_ok("Playwright Chromium", "(browser engine)")
1209
+ else:
1210
+ check_warn(
1211
+ "Playwright Chromium not installed",
1212
+ "(browser_* tools will be hidden from the agent)",
1213
+ )
1214
+ if sys.platform == "win32":
1215
+ check_info(
1216
+ f"Install with: cd {PROJECT_ROOT} && "
1217
+ "npx playwright install chromium"
1218
+ )
1219
+ else:
1220
+ check_info(
1221
+ f"Install with: cd {PROJECT_ROOT} && "
1222
+ "npx playwright install --with-deps chromium"
1223
+ )
1224
+ elif _is_termux():
1225
+ check_info("Node.js not found (browser tools are optional in the tested Termux path)")
1226
+ check_info("Install Node.js on Termux with: pkg install nodejs")
1227
+ check_info("Termux browser setup:")
1228
+ for step in _termux_browser_setup_steps(node_installed=False):
1229
+ check_info(step)
1230
+ else:
1231
+ check_warn("Node.js not found", "(optional, needed for browser tools)")
1232
+
1233
+ # npm audit for all Node.js packages
1234
+ _npm_bin = _safe_which("npm")
1235
+ if _npm_bin:
1236
+ npm_dirs = [
1237
+ (PROJECT_ROOT, "Browser tools (agent-browser)"),
1238
+ (PROJECT_ROOT / "scripts" / "whatsapp-bridge", "WhatsApp bridge"),
1239
+ ]
1240
+ for npm_dir, label in npm_dirs:
1241
+ if not (npm_dir / "node_modules").exists():
1242
+ continue
1243
+ try:
1244
+ # Use resolved absolute path so Windows can execute
1245
+ # npm.cmd (CreateProcessW can't run bare .cmd names).
1246
+ audit_result = subprocess.run(
1247
+ [_npm_bin, "audit", "--json"],
1248
+ cwd=str(npm_dir),
1249
+ capture_output=True, text=True, timeout=30,
1250
+ )
1251
+ import json as _json
1252
+ audit_data = _json.loads(audit_result.stdout) if audit_result.stdout.strip() else {}
1253
+ vuln_count = audit_data.get("metadata", {}).get("vulnerabilities", {})
1254
+ critical = vuln_count.get("critical", 0)
1255
+ high = vuln_count.get("high", 0)
1256
+ moderate = vuln_count.get("moderate", 0)
1257
+ total = critical + high + moderate
1258
+ if total == 0:
1259
+ check_ok(f"{label} deps", "(no known vulnerabilities)")
1260
+ elif critical > 0 or high > 0:
1261
+ check_warn(
1262
+ f"{label} deps",
1263
+ f"({critical} critical, {high} high, {moderate} moderate — run: cd {npm_dir} && npm audit fix)"
1264
+ )
1265
+ issues.append(
1266
+ f"{label} has {total} npm "
1267
+ f"{'vulnerability' if total == 1 else 'vulnerabilities'}"
1268
+ )
1269
+ else:
1270
+ check_ok(
1271
+ f"{label} deps",
1272
+ f"({moderate} moderate "
1273
+ f"{'vulnerability' if moderate == 1 else 'vulnerabilities'})",
1274
+ )
1275
+ except Exception:
1276
+ pass
1277
+
1278
+ if _is_termux():
1279
+ check_info("Termux compatibility fallbacks:")
1280
+ for note in _termux_install_all_fallback_notes():
1281
+ check_info(note)
1282
+
1283
+ # =========================================================================
1284
+ # Check: API connectivity
1285
+ # =========================================================================
1286
+ print()
1287
+ print(color("◆ API Connectivity", Colors.CYAN, Colors.BOLD))
1288
+
1289
+ # Refactor: every connectivity probe below is HTTP-bound and fully
1290
+ # independent. Running them in series spent ~5s wall on a typical
1291
+ # workstation (2s of that was boto3's IMDS lookup for AWS credentials,
1292
+ # which times out unless you're actually on EC2). Threading them with
1293
+ # a small executor pool collapses the section to roughly the slowest
1294
+ # single probe — about 2s — without changing the output format.
1295
+ #
1296
+ # Each ``_probe_*`` helper is a pure function: takes its inputs,
1297
+ # makes one HTTP/SDK call, returns a ``_ConnectivityResult`` carrying
1298
+ # the line(s) to print and any issue strings to append. No globals,
1299
+ # no shared mutable state, no printing inside the workers.
1300
+ import concurrent.futures as _futures
1301
+ from collections import namedtuple as _namedtuple
1302
+
1303
+ _ConnectivityResult = _namedtuple(
1304
+ "_ConnectivityResult", ["label", "lines", "issues"]
1305
+ )
1306
+ _probes: list = [] # list of (label, callable) submitted in display order
1307
+
1308
+ def _probe_openrouter() -> _ConnectivityResult:
1309
+ key = os.getenv("OPENROUTER_API_KEY")
1310
+ if not key:
1311
+ return _ConnectivityResult(
1312
+ "OpenRouter API",
1313
+ [(color("⚠", Colors.YELLOW), "OpenRouter API",
1314
+ color("(not configured)", Colors.DIM))],
1315
+ [],
1316
+ )
1317
+ try:
1318
+ import httpx
1319
+ r = httpx.get(
1320
+ OPENROUTER_MODELS_URL,
1321
+ headers={"Authorization": f"Bearer {key}"},
1322
+ timeout=10,
1323
+ )
1324
+ if r.status_code == 200:
1325
+ return _ConnectivityResult(
1326
+ "OpenRouter API",
1327
+ [(color("✓", Colors.GREEN), "OpenRouter API", "")],
1328
+ [],
1329
+ )
1330
+ if r.status_code == 401:
1331
+ return _ConnectivityResult(
1332
+ "OpenRouter API",
1333
+ [(color("✗", Colors.RED), "OpenRouter API",
1334
+ color("(invalid API key)", Colors.DIM))],
1335
+ ["Check OPENROUTER_API_KEY in .env"],
1336
+ )
1337
+ if r.status_code == 402:
1338
+ return _ConnectivityResult(
1339
+ "OpenRouter API",
1340
+ [(color("✗", Colors.RED), "OpenRouter API",
1341
+ color("(out of credits — payment required)", Colors.DIM))],
1342
+ ["OpenRouter account has insufficient credits. "
1343
+ "Fix: run 'hermes config set model.provider <provider>' "
1344
+ "to switch providers, or fund your OpenRouter account "
1345
+ "at https://openrouter.ai/settings/credits"],
1346
+ )
1347
+ if r.status_code == 429:
1348
+ return _ConnectivityResult(
1349
+ "OpenRouter API",
1350
+ [(color("✗", Colors.RED), "OpenRouter API",
1351
+ color("(rate limited)", Colors.DIM))],
1352
+ ["OpenRouter rate limit hit — consider switching to "
1353
+ "a different provider or waiting"],
1354
+ )
1355
+ return _ConnectivityResult(
1356
+ "OpenRouter API",
1357
+ [(color("✗", Colors.RED), "OpenRouter API",
1358
+ color(f"(HTTP {r.status_code})", Colors.DIM))],
1359
+ [],
1360
+ )
1361
+ except Exception as e:
1362
+ return _ConnectivityResult(
1363
+ "OpenRouter API",
1364
+ [(color("✗", Colors.RED), "OpenRouter API",
1365
+ color(f"({e})", Colors.DIM))],
1366
+ ["Check network connectivity"],
1367
+ )
1368
+
1369
+ def _probe_anthropic() -> _ConnectivityResult:
1370
+ from hermes_cli.auth import get_anthropic_key
1371
+ key = get_anthropic_key()
1372
+ if not key:
1373
+ return _ConnectivityResult("Anthropic API", [], [])
1374
+ try:
1375
+ import httpx
1376
+ from agent.anthropic_adapter import (
1377
+ _is_oauth_token,
1378
+ _COMMON_BETAS,
1379
+ _OAUTH_ONLY_BETAS,
1380
+ _CONTEXT_1M_BETA,
1381
+ )
1382
+ headers = {"anthropic-version": "2023-06-01"}
1383
+ is_oauth = _is_oauth_token(key)
1384
+ if is_oauth:
1385
+ headers["Authorization"] = f"Bearer {key}"
1386
+ headers["anthropic-beta"] = ",".join(_COMMON_BETAS + _OAUTH_ONLY_BETAS)
1387
+ else:
1388
+ headers["x-api-key"] = key
1389
+ r = httpx.get(
1390
+ "https://api.anthropic.com/v1/models",
1391
+ headers=headers, timeout=10,
1392
+ )
1393
+ # Reactive recovery: OAuth subscriptions without 1M context reject the
1394
+ # request with 400 "long context beta is not yet available for this
1395
+ # subscription". Retry once with that beta stripped so the doctor
1396
+ # check doesn't falsely report Anthropic as unreachable.
1397
+ if (
1398
+ is_oauth
1399
+ and r.status_code == 400
1400
+ and "long context beta" in r.text.lower()
1401
+ and "not yet available" in r.text.lower()
1402
+ ):
1403
+ headers["anthropic-beta"] = ",".join(
1404
+ [b for b in _COMMON_BETAS if b != _CONTEXT_1M_BETA]
1405
+ + list(_OAUTH_ONLY_BETAS)
1406
+ )
1407
+ r = httpx.get(
1408
+ "https://api.anthropic.com/v1/models",
1409
+ headers=headers, timeout=10,
1410
+ )
1411
+ if r.status_code == 200:
1412
+ return _ConnectivityResult(
1413
+ "Anthropic API",
1414
+ [(color("✓", Colors.GREEN), "Anthropic API", "")],
1415
+ [],
1416
+ )
1417
+ if r.status_code == 401:
1418
+ return _ConnectivityResult(
1419
+ "Anthropic API",
1420
+ [(color("✗", Colors.RED), "Anthropic API",
1421
+ color("(invalid API key)", Colors.DIM))],
1422
+ [],
1423
+ )
1424
+ return _ConnectivityResult(
1425
+ "Anthropic API",
1426
+ [(color("⚠", Colors.YELLOW), "Anthropic API",
1427
+ color("(couldn't verify)", Colors.DIM))],
1428
+ [],
1429
+ )
1430
+ except Exception as e:
1431
+ return _ConnectivityResult(
1432
+ "Anthropic API",
1433
+ [(color("⚠", Colors.YELLOW), "Anthropic API",
1434
+ color(f"({e})", Colors.DIM))],
1435
+ [],
1436
+ )
1437
+
1438
+ def _probe_apikey_provider(pname, env_vars, default_url, base_env,
1439
+ supports_health_check) -> _ConnectivityResult:
1440
+ key = ""
1441
+ for ev in env_vars:
1442
+ key = os.getenv(ev, "")
1443
+ if key:
1444
+ break
1445
+ if not key:
1446
+ return _ConnectivityResult(pname, [], [])
1447
+ label = pname.ljust(20)
1448
+ if not supports_health_check:
1449
+ return _ConnectivityResult(
1450
+ pname,
1451
+ [(color("✓", Colors.GREEN), label,
1452
+ color("(key configured)", Colors.DIM))],
1453
+ [],
1454
+ )
1455
+ try:
1456
+ import httpx
1457
+ base = os.getenv(base_env, "") if base_env else ""
1458
+ # Auto-detect Kimi Code keys (sk-kimi-) → api.kimi.com/coding/v1
1459
+ # (OpenAI-compat surface, which exposes /models for health check).
1460
+ if not base and key.startswith("sk-kimi-"):
1461
+ base = "https://api.kimi.com/coding/v1"
1462
+ # Anthropic-compat endpoints (/anthropic, api.kimi.com/coding
1463
+ # with no /v1) don't support /models. Rewrite to OpenAI-compat
1464
+ # /v1 surface for health checks.
1465
+ if base and base.rstrip("/").endswith("/anthropic"):
1466
+ from agent.auxiliary_client import _to_openai_base_url
1467
+ base = _to_openai_base_url(base)
1468
+ if base_url_host_matches(base, "api.kimi.com") and base.rstrip("/").endswith("/coding"):
1469
+ base = base.rstrip("/") + "/v1"
1470
+ url = (base.rstrip("/") + "/models") if base else default_url
1471
+ headers = {
1472
+ "Authorization": f"Bearer {key}",
1473
+ "User-Agent": _HERMES_USER_AGENT,
1474
+ }
1475
+ if base_url_host_matches(base, "api.kimi.com"):
1476
+ headers["User-Agent"] = "claude-code/0.1.0"
1477
+ r = httpx.get(url, headers=headers, timeout=10)
1478
+ if (
1479
+ pname == "Alibaba/DashScope"
1480
+ and not base
1481
+ and r.status_code == 401
1482
+ ):
1483
+ r = httpx.get(
1484
+ "https://dashscope.aliyuncs.com/compatible-mode/v1/models",
1485
+ headers=headers, timeout=10,
1486
+ )
1487
+ if r.status_code == 200:
1488
+ return _ConnectivityResult(
1489
+ pname,
1490
+ [(color("✓", Colors.GREEN), label, "")],
1491
+ [],
1492
+ )
1493
+ if r.status_code == 401:
1494
+ return _ConnectivityResult(
1495
+ pname,
1496
+ [(color("✗", Colors.RED), label,
1497
+ color("(invalid API key)", Colors.DIM))],
1498
+ [f"Check {env_vars[0]} in .env"],
1499
+ )
1500
+ return _ConnectivityResult(
1501
+ pname,
1502
+ [(color("⚠", Colors.YELLOW), label,
1503
+ color(f"(HTTP {r.status_code})", Colors.DIM))],
1504
+ [],
1505
+ )
1506
+ except Exception as e:
1507
+ return _ConnectivityResult(
1508
+ pname,
1509
+ [(color("⚠", Colors.YELLOW), label,
1510
+ color(f"({e})", Colors.DIM))],
1511
+ [],
1512
+ )
1513
+
1514
+ def _probe_bedrock() -> _ConnectivityResult:
1515
+ try:
1516
+ from agent.bedrock_adapter import (
1517
+ has_aws_credentials,
1518
+ resolve_aws_auth_env_var,
1519
+ resolve_bedrock_region,
1520
+ )
1521
+ except ImportError:
1522
+ return _ConnectivityResult("AWS Bedrock", [], [])
1523
+ if not has_aws_credentials():
1524
+ return _ConnectivityResult("AWS Bedrock", [], [])
1525
+ auth_var = resolve_aws_auth_env_var()
1526
+ region = resolve_bedrock_region()
1527
+ label = "AWS Bedrock".ljust(20)
1528
+ try:
1529
+ import boto3
1530
+ from botocore.config import Config as _BotoConfig
1531
+ # Trim retries on the actual Bedrock API call so a transient
1532
+ # failure doesn't pad the doctor run by 30+ seconds.
1533
+ cfg = _BotoConfig(
1534
+ connect_timeout=5,
1535
+ read_timeout=10,
1536
+ retries={"max_attempts": 1},
1537
+ )
1538
+ client = boto3.client("bedrock", region_name=region, config=cfg)
1539
+ resp = client.list_foundation_models()
1540
+ n = len(resp.get("modelSummaries", []))
1541
+ return _ConnectivityResult(
1542
+ "AWS Bedrock",
1543
+ [(color("✓", Colors.GREEN), label,
1544
+ color(f"({auth_var}, {region}, {n} models)", Colors.DIM))],
1545
+ [],
1546
+ )
1547
+ except ImportError:
1548
+ return _ConnectivityResult(
1549
+ "AWS Bedrock",
1550
+ [(color("⚠", Colors.YELLOW), label,
1551
+ color(f"(boto3 not installed — {sys.executable} -m pip install boto3)",
1552
+ Colors.DIM))],
1553
+ [f"Install boto3 for Bedrock: {sys.executable} -m pip install boto3"],
1554
+ )
1555
+ except Exception as e:
1556
+ err_name = type(e).__name__
1557
+ return _ConnectivityResult(
1558
+ "AWS Bedrock",
1559
+ [(color("⚠", Colors.YELLOW), label,
1560
+ color(f"({err_name}: {e})", Colors.DIM))],
1561
+ [f"AWS Bedrock: {err_name} — check IAM permissions for "
1562
+ f"bedrock:ListFoundationModels"],
1563
+ )
1564
+
1565
+ # Build the probe submission list in display order
1566
+ _probes.append(("OpenRouter API", _probe_openrouter))
1567
+ _probes.append(("Anthropic API", _probe_anthropic))
1568
+
1569
+ global _APIKEY_PROVIDERS_CACHE
1570
+ if _APIKEY_PROVIDERS_CACHE is None:
1571
+ _APIKEY_PROVIDERS_CACHE = _build_apikey_providers_list()
1572
+ for _entry in _APIKEY_PROVIDERS_CACHE:
1573
+ _pname, _env_vars, _default_url, _base_env, _supports = _entry
1574
+ # Capture loop vars by binding default args — without this, all closures
1575
+ # would share the final iteration's values and every probe would hit
1576
+ # the last provider's URL.
1577
+ _probes.append((_pname, lambda p=_pname, e=_env_vars, u=_default_url,
1578
+ b=_base_env, s=_supports:
1579
+ _probe_apikey_provider(p, e, u, b, s)))
1580
+
1581
+ _probes.append(("AWS Bedrock", _probe_bedrock))
1582
+
1583
+ # Print a single status line so users see something happening, then
1584
+ # fan out. ``\r`` clears it once the first real result line lands.
1585
+ print(f" {color(f'Running {len(_probes)} connectivity checks in parallel…', Colors.DIM)}",
1586
+ end="", flush=True)
1587
+
1588
+ # Disable boto3's EC2 instance-metadata-service probe for the duration
1589
+ # of the parallel block. boto's default credential chain tries
1590
+ # 169.254.169.254 with a multi-second timeout when we're not on EC2,
1591
+ # which dominated the section's wall time before this fix
1592
+ # (~2s on a developer laptop, even with the rest parallelized).
1593
+ # Set on the parent thread before submitting work so the env-var
1594
+ # mutation never races with another worker. has_aws_credentials() in
1595
+ # the bedrock probe already gates on real env-var creds, so IMDS is
1596
+ # never the legitimate source for `hermes doctor`.
1597
+ _imds_prev = os.environ.get("AWS_EC2_METADATA_DISABLED")
1598
+ os.environ["AWS_EC2_METADATA_DISABLED"] = "true"
1599
+ try:
1600
+ # 8 workers is plenty — each probe is a single HTTP call plus a TLS
1601
+ # handshake. More than that wastes thread-startup cost and risks
1602
+ # noisy output if anything ever printed from inside a worker.
1603
+ with _futures.ThreadPoolExecutor(max_workers=8,
1604
+ thread_name_prefix="doctor-probe") as _ex:
1605
+ _futures_in_order = [_ex.submit(_fn) for _, _fn in _probes]
1606
+ _results = [_f.result() for _f in _futures_in_order]
1607
+ finally:
1608
+ if _imds_prev is None:
1609
+ os.environ.pop("AWS_EC2_METADATA_DISABLED", None)
1610
+ else:
1611
+ os.environ["AWS_EC2_METADATA_DISABLED"] = _imds_prev
1612
+
1613
+ # Clear the "Running …" line and print all results in submission order.
1614
+ print("\r" + " " * 70 + "\r", end="")
1615
+ for _r in _results:
1616
+ for _glyph, _label, _detail in _r.lines:
1617
+ if _detail:
1618
+ print(f" {_glyph} {_label} {_detail}")
1619
+ else:
1620
+ print(f" {_glyph} {_label}")
1621
+ _issues_to_add = list(_r.issues)
1622
+ if _issues_to_add and _has_healthy_oauth_fallback_for_apikey_provider(_r.label):
1623
+ _issues_to_add = []
1624
+ for _issue in _issues_to_add:
1625
+ issues.append(_issue)
1626
+
1627
+ # =========================================================================
1628
+ # Check: Tool Availability
1629
+ # =========================================================================
1630
+ print()
1631
+ print(color("◆ Tool Availability", Colors.CYAN, Colors.BOLD))
1632
+
1633
+ try:
1634
+ # Add project root to path for imports
1635
+ sys.path.insert(0, str(PROJECT_ROOT))
1636
+ from model_tools import check_tool_availability, TOOLSET_REQUIREMENTS
1637
+
1638
+ available, unavailable = check_tool_availability()
1639
+ available, unavailable = _apply_doctor_tool_availability_overrides(available, unavailable)
1640
+
1641
+ for tid in available:
1642
+ info = TOOLSET_REQUIREMENTS.get(tid, {})
1643
+ check_ok(info.get("name", tid), _doctor_tool_availability_detail(tid))
1644
+
1645
+ for item in unavailable:
1646
+ env_vars = item.get("missing_vars") or item.get("env_vars") or []
1647
+ if env_vars:
1648
+ vars_str = ", ".join(env_vars)
1649
+ check_warn(item["name"], f"(missing {vars_str})")
1650
+ else:
1651
+ check_warn(item["name"], "(system dependency not met)")
1652
+
1653
+ # Count disabled tools with API key requirements
1654
+ api_disabled = [u for u in unavailable if (u.get("missing_vars") or u.get("env_vars"))]
1655
+ if api_disabled:
1656
+ issues.append("Run 'hermes setup' to configure missing API keys for full tool access")
1657
+ except Exception as e:
1658
+ check_warn("Could not check tool availability", f"({e})")
1659
+
1660
+ # =========================================================================
1661
+ # Check: Skills Hub
1662
+ # =========================================================================
1663
+ print()
1664
+ print(color("◆ Skills Hub", Colors.CYAN, Colors.BOLD))
1665
+
1666
+ hub_dir = HERMES_HOME / "skills" / ".hub"
1667
+ if hub_dir.exists():
1668
+ check_ok("Skills Hub directory exists")
1669
+ lock_file = hub_dir / "lock.json"
1670
+ if lock_file.exists():
1671
+ try:
1672
+ import json
1673
+ lock_data = json.loads(lock_file.read_text())
1674
+ count = len(lock_data.get("installed", {}))
1675
+ check_ok(f"Lock file OK ({count} hub-installed skill(s))")
1676
+ except Exception:
1677
+ check_warn("Lock file", "(corrupted or unreadable)")
1678
+ quarantine = hub_dir / "quarantine"
1679
+ q_count = sum(1 for d in quarantine.iterdir() if d.is_dir()) if quarantine.exists() else 0
1680
+ if q_count > 0:
1681
+ check_warn(f"{q_count} skill(s) in quarantine", "(pending review)")
1682
+ else:
1683
+ check_warn("Skills Hub directory not initialized", "(run: hermes skills list)")
1684
+
1685
+ from hermes_cli.config import get_env_value
1686
+
1687
+ def _gh_authenticated() -> bool:
1688
+ """Check if gh CLI is authenticated via token file or device flow."""
1689
+ try:
1690
+ result = subprocess.run(
1691
+ ["gh", "auth", "status", "--json", "authenticated"],
1692
+ capture_output=True, timeout=10,
1693
+ )
1694
+ return result.returncode == 0
1695
+ except (FileNotFoundError, subprocess.TimeoutExpired):
1696
+ return False
1697
+
1698
+ github_token = get_env_value("GITHUB_TOKEN") or get_env_value("GH_TOKEN")
1699
+ if github_token:
1700
+ check_ok("GitHub token configured (authenticated API access)")
1701
+ elif _gh_authenticated():
1702
+ check_ok("GitHub authenticated via gh CLI", "(full API access — no GITHUB_TOKEN needed)")
1703
+ else:
1704
+ check_warn("No GITHUB_TOKEN", f"(60 req/hr rate limit — set in {_DHH}/.env for better rates)")
1705
+
1706
+ # =========================================================================
1707
+ # Memory Provider (only check the active provider, if any)
1708
+ # =========================================================================
1709
+ print()
1710
+ print(color("◆ Memory Provider", Colors.CYAN, Colors.BOLD))
1711
+
1712
+ _active_memory_provider = ""
1713
+ try:
1714
+ import yaml as _yaml
1715
+ _mem_cfg_path = HERMES_HOME / "config.yaml"
1716
+ if _mem_cfg_path.exists():
1717
+ with open(_mem_cfg_path, encoding="utf-8") as _f:
1718
+ _raw_cfg = _yaml.safe_load(_f) or {}
1719
+ _active_memory_provider = (_raw_cfg.get("memory") or {}).get("provider", "")
1720
+ except Exception:
1721
+ pass
1722
+
1723
+ if not _active_memory_provider:
1724
+ check_ok("Built-in memory active", "(no external provider configured — this is fine)")
1725
+ elif _active_memory_provider == "honcho":
1726
+ try:
1727
+ from plugins.memory.honcho.client import HonchoClientConfig, resolve_config_path
1728
+ hcfg = HonchoClientConfig.from_global_config()
1729
+ _honcho_cfg_path = resolve_config_path()
1730
+
1731
+ if not _honcho_cfg_path.exists():
1732
+ check_warn("Honcho config not found", "run: hermes memory setup")
1733
+ elif not hcfg.enabled:
1734
+ check_info(f"Honcho disabled (set enabled: true in {_honcho_cfg_path} to activate)")
1735
+ elif not (hcfg.api_key or hcfg.base_url):
1736
+ check_fail("Honcho API key or base URL not set", "run: hermes memory setup")
1737
+ issues.append("No Honcho API key — run 'hermes memory setup'")
1738
+ else:
1739
+ from plugins.memory.honcho.client import get_honcho_client, reset_honcho_client
1740
+ reset_honcho_client()
1741
+ try:
1742
+ get_honcho_client(hcfg)
1743
+ check_ok(
1744
+ "Honcho connected",
1745
+ f"workspace={hcfg.workspace_id} mode={hcfg.recall_mode} freq={hcfg.write_frequency}",
1746
+ )
1747
+ except Exception as _e:
1748
+ check_fail("Honcho connection failed", str(_e))
1749
+ issues.append(f"Honcho unreachable: {_e}")
1750
+ except ImportError:
1751
+ check_fail("honcho-ai not installed", "pip install honcho-ai")
1752
+ issues.append("Honcho is set as memory provider but honcho-ai is not installed")
1753
+ except Exception as _e:
1754
+ check_warn("Honcho check failed", str(_e))
1755
+ elif _active_memory_provider == "mem0":
1756
+ try:
1757
+ from plugins.memory.mem0 import _load_config as _load_mem0_config
1758
+ mem0_cfg = _load_mem0_config()
1759
+ mem0_key = mem0_cfg.get("api_key", "")
1760
+ if mem0_key:
1761
+ check_ok("Mem0 API key configured")
1762
+ check_info(f"user_id={mem0_cfg.get('user_id', '?')} agent_id={mem0_cfg.get('agent_id', '?')}")
1763
+ else:
1764
+ check_fail("Mem0 API key not set", "(set MEM0_API_KEY in .env or run hermes memory setup)")
1765
+ issues.append("Mem0 is set as memory provider but API key is missing")
1766
+ except ImportError:
1767
+ check_fail("Mem0 plugin not loadable", "pip install mem0ai")
1768
+ issues.append("Mem0 is set as memory provider but mem0ai is not installed")
1769
+ except Exception as _e:
1770
+ check_warn("Mem0 check failed", str(_e))
1771
+ else:
1772
+ # Generic check for other memory providers (openviking, hindsight, etc.)
1773
+ try:
1774
+ from plugins.memory import load_memory_provider
1775
+ _provider = load_memory_provider(_active_memory_provider)
1776
+ if _provider and _provider.is_available():
1777
+ check_ok(f"{_active_memory_provider} provider active")
1778
+ elif _provider:
1779
+ check_warn(f"{_active_memory_provider} configured but not available", "run: hermes memory status")
1780
+ else:
1781
+ check_warn(f"{_active_memory_provider} plugin not found", "run: hermes memory setup")
1782
+ except Exception as _e:
1783
+ check_warn(f"{_active_memory_provider} check failed", str(_e))
1784
+
1785
+ # =========================================================================
1786
+ # Profiles
1787
+ # =========================================================================
1788
+ try:
1789
+ from hermes_cli.profiles import list_profiles, _get_wrapper_dir, profile_exists
1790
+ import re as _re
1791
+
1792
+ named_profiles = [p for p in list_profiles() if not p.is_default]
1793
+ if named_profiles:
1794
+ print()
1795
+ print(color("◆ Profiles", Colors.CYAN, Colors.BOLD))
1796
+ check_ok(f"{len(named_profiles)} profile(s) found")
1797
+ wrapper_dir = _get_wrapper_dir()
1798
+ for p in named_profiles:
1799
+ parts = []
1800
+ if p.gateway_running:
1801
+ parts.append("gateway running")
1802
+ if p.model:
1803
+ parts.append(p.model[:30])
1804
+ if not (p.path / "config.yaml").exists():
1805
+ parts.append("⚠ missing config")
1806
+ if not (p.path / ".env").exists():
1807
+ parts.append("no .env")
1808
+ wrapper = wrapper_dir / p.name
1809
+ if not wrapper.exists():
1810
+ parts.append("no alias")
1811
+ status = ", ".join(parts) if parts else "configured"
1812
+ check_ok(f" {p.name}: {status}")
1813
+
1814
+ # Check for orphan wrappers
1815
+ if wrapper_dir.is_dir():
1816
+ for wrapper in wrapper_dir.iterdir():
1817
+ if not wrapper.is_file():
1818
+ continue
1819
+ try:
1820
+ content = wrapper.read_text()
1821
+ if "hermes -p" in content:
1822
+ _m = _re.search(r"hermes -p (\S+)", content)
1823
+ if _m and not profile_exists(_m.group(1)):
1824
+ check_warn(f"Orphan alias: {wrapper.name} → profile '{_m.group(1)}' no longer exists")
1825
+ except Exception:
1826
+ pass
1827
+ except ImportError:
1828
+ pass
1829
+ except Exception:
1830
+ pass
1831
+
1832
+ # =========================================================================
1833
+ # Summary
1834
+ # =========================================================================
1835
+ print()
1836
+ remaining_issues = issues + manual_issues
1837
+ if should_fix and fixed_count > 0:
1838
+ print(color("─" * 60, Colors.GREEN))
1839
+ print(color(f" Fixed {fixed_count} issue(s).", Colors.GREEN, Colors.BOLD), end="")
1840
+ if remaining_issues:
1841
+ print(color(f" {len(remaining_issues)} issue(s) require manual intervention.", Colors.YELLOW, Colors.BOLD))
1842
+ else:
1843
+ print()
1844
+ print()
1845
+ if remaining_issues:
1846
+ for i, issue in enumerate(remaining_issues, 1):
1847
+ print(f" {i}. {issue}")
1848
+ print()
1849
+ elif remaining_issues:
1850
+ print(color("─" * 60, Colors.YELLOW))
1851
+ print(color(f" Found {len(remaining_issues)} issue(s) to address:", Colors.YELLOW, Colors.BOLD))
1852
+ print()
1853
+ for i, issue in enumerate(remaining_issues, 1):
1854
+ print(f" {i}. {issue}")
1855
+ print()
1856
+ if not should_fix:
1857
+ print(color(" Tip: run 'hermes doctor --fix' to auto-fix what's possible.", Colors.DIM))
1858
+ else:
1859
+ print(color("─" * 60, Colors.GREEN))
1860
+ print(color(" All checks passed! 🎉", Colors.GREEN, Colors.BOLD))
1861
+
1862
+ print()
1863
+