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,1827 @@
1
+ """Model metadata, context lengths, and token estimation utilities.
2
+
3
+ Pure utility functions with no AIAgent dependency. Used by ContextCompressor
4
+ and run_agent.py for pre-flight context checks.
5
+ """
6
+
7
+ import ipaddress
8
+ import logging
9
+ import os
10
+ import re
11
+ import time
12
+ from pathlib import Path
13
+ from typing import Any, Dict, List, Optional, Tuple
14
+ from urllib.parse import urlparse
15
+
16
+ import requests
17
+ import yaml
18
+
19
+ from utils import base_url_host_matches, base_url_hostname
20
+
21
+ from calvyn_constants import OPENROUTER_MODELS_URL
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ def _resolve_requests_verify() -> bool | str:
27
+ """Resolve SSL verify setting for `requests` calls from env vars.
28
+
29
+ The `requests` library only honours REQUESTS_CA_BUNDLE / CURL_CA_BUNDLE
30
+ by default. Hermes also honours HERMES_CA_BUNDLE (its own convention)
31
+ and SSL_CERT_FILE (used by the stdlib `ssl` module and by httpx), so
32
+ that a single env var can cover both `requests` and `httpx` callsites
33
+ inside the same process.
34
+
35
+ Returns either a filesystem path to a CA bundle, or True to defer to
36
+ the requests default (certifi).
37
+ """
38
+ for env_var in ("HERMES_CA_BUNDLE", "REQUESTS_CA_BUNDLE", "SSL_CERT_FILE"):
39
+ val = os.getenv(env_var)
40
+ if val and os.path.isfile(val):
41
+ return val
42
+ return True
43
+
44
+ # Provider names that can appear as a "provider:" prefix before a model ID.
45
+ # Only these are stripped — Ollama-style "model:tag" colons (e.g. "qwen3.5:27b")
46
+ # are preserved so the full model name reaches cache lookups and server queries.
47
+ _PROVIDER_PREFIXES: frozenset[str] = frozenset({
48
+ "openrouter", "nous", "openai-codex", "copilot", "copilot-acp",
49
+ "gemini", "ollama-cloud", "zai", "kimi-coding", "kimi-coding-cn", "stepfun", "minimax", "minimax-oauth", "minimax-cn", "anthropic", "deepseek",
50
+ "opencode-zen", "opencode-go", "ai-gateway", "kilocode", "alibaba", "novita",
51
+ "qwen-oauth",
52
+ "xiaomi",
53
+ "arcee",
54
+ "gmi",
55
+ "tencent-tokenhub",
56
+ "custom", "local",
57
+ # Common aliases
58
+ "google", "google-gemini", "google-ai-studio",
59
+ "glm", "z-ai", "z.ai", "zhipu", "github", "github-copilot",
60
+ "github-models", "kimi", "moonshot", "kimi-cn", "moonshot-cn", "claude", "deep-seek",
61
+ "ollama",
62
+ "stepfun", "opencode", "zen", "go", "vercel", "kilo", "dashscope", "aliyun", "qwen",
63
+ "mimo", "xiaomi-mimo",
64
+ "tencent", "tokenhub", "tencent-cloud", "tencentmaas",
65
+ "arcee-ai", "arceeai",
66
+ "gmi-cloud", "gmicloud",
67
+ "xai", "x-ai", "x.ai", "grok",
68
+ "nvidia", "nim", "nvidia-nim", "nemotron",
69
+ "qwen-portal", "novita-ai", "novitaai",
70
+ })
71
+
72
+
73
+ _OLLAMA_TAG_PATTERN = re.compile(
74
+ r"^(\d+\.?\d*b|latest|stable|q\d|fp?\d|instruct|chat|coder|vision|text)",
75
+ re.IGNORECASE,
76
+ )
77
+
78
+
79
+ # Tailscale's CGNAT range (RFC 6598). `ipaddress.is_private` excludes this
80
+ # block, so without an explicit check Ollama reached over Tailscale (e.g.
81
+ # `http://100.77.243.5:11434`) wouldn't be treated as local and its stream
82
+ # read / stale timeouts wouldn't get auto-bumped. Built once at import time.
83
+ _TAILSCALE_CGNAT = ipaddress.IPv4Network("100.64.0.0/10")
84
+
85
+
86
+ def _strip_provider_prefix(model: str) -> str:
87
+ """Strip a recognised provider prefix from a model string.
88
+
89
+ ``"local:my-model"`` → ``"my-model"``
90
+ ``"qwen3.5:27b"`` → ``"qwen3.5:27b"`` (unchanged — not a provider prefix)
91
+ ``"qwen:0.5b"`` → ``"qwen:0.5b"`` (unchanged — Ollama model:tag)
92
+ ``"deepseek:latest"``→ ``"deepseek:latest"``(unchanged — Ollama model:tag)
93
+ """
94
+ if ":" not in model or model.startswith("http"):
95
+ return model
96
+ prefix, suffix = model.split(":", 1)
97
+ prefix_lower = prefix.strip().lower()
98
+ if prefix_lower in _PROVIDER_PREFIXES:
99
+ # Don't strip if suffix looks like an Ollama tag (e.g. "7b", "latest", "q4_0")
100
+ if _OLLAMA_TAG_PATTERN.match(suffix.strip()):
101
+ return model
102
+ return suffix
103
+ return model
104
+
105
+ _model_metadata_cache: Dict[str, Dict[str, Any]] = {}
106
+ _model_metadata_cache_time: float = 0
107
+ _novita_metadata_cache: Dict[str, Dict[str, Any]] = {}
108
+ _novita_metadata_cache_time: float = 0
109
+ _MODEL_CACHE_TTL = 3600
110
+ _endpoint_model_metadata_cache: Dict[str, Dict[str, Dict[str, Any]]] = {}
111
+ _endpoint_model_metadata_cache_time: Dict[str, float] = {}
112
+ _ENDPOINT_MODEL_CACHE_TTL = 300
113
+
114
+ # Descending tiers for context length probing when the model is unknown.
115
+ # We start at 256K (covers GPT-5.x, many current large-context models) and
116
+ # step down on context-length errors until one works. Tier[0] is also the
117
+ # default fallback when no detection method succeeds.
118
+ CONTEXT_PROBE_TIERS = [
119
+ 256_000,
120
+ 128_000,
121
+ 64_000,
122
+ 32_000,
123
+ 16_000,
124
+ 8_000,
125
+ ]
126
+
127
+ # Default context length when no detection method succeeds.
128
+ DEFAULT_FALLBACK_CONTEXT = CONTEXT_PROBE_TIERS[0]
129
+
130
+ # Minimum context length required to run Hermes Agent. Models with fewer
131
+ # tokens cannot maintain enough working memory for tool-calling workflows.
132
+ # Sessions, model switches, and cron jobs should reject models below this.
133
+ MINIMUM_CONTEXT_LENGTH = 64_000
134
+
135
+ # Thin fallback defaults — only broad model family patterns.
136
+ # These fire only when provider is unknown AND models.dev/OpenRouter/Anthropic
137
+ # all miss. Replaced the previous 80+ entry dict.
138
+ # For provider-specific context lengths, models.dev is the primary source.
139
+ DEFAULT_CONTEXT_LENGTHS = {
140
+ # Anthropic Claude 4.6 (1M context) — bare IDs only to avoid
141
+ # fuzzy-match collisions (e.g. "anthropic/claude-sonnet-4" is a
142
+ # substring of "anthropic/claude-sonnet-4.6").
143
+ # OpenRouter-prefixed models resolve via OpenRouter live API or models.dev.
144
+ "claude-opus-4-7": 1000000,
145
+ "claude-opus-4.7": 1000000,
146
+ "claude-opus-4-6": 1000000,
147
+ "claude-sonnet-4-6": 1000000,
148
+ "claude-opus-4.6": 1000000,
149
+ "claude-sonnet-4.6": 1000000,
150
+ # Catch-all for older Claude models (must sort after specific entries)
151
+ "claude": 200000,
152
+ # OpenAI — GPT-5 family (most have 400k; specific overrides first)
153
+ # Source: https://developers.openai.com/api/docs/models
154
+ # GPT-5.5 (launched Apr 23 2026) is 1.05M on the direct OpenAI API and
155
+ # ChatGPT Codex OAuth caps it at 272K; both paths resolve via their own
156
+ # provider-aware branches (_resolve_codex_oauth_context_length + models.dev).
157
+ # This hardcoded value is only reached when every probe misses.
158
+ "gpt-5.5": 1050000,
159
+ "gpt-5.4-nano": 400000, # 400k (not 1.05M like full 5.4)
160
+ "gpt-5.4-mini": 400000, # 400k (not 1.05M like full 5.4)
161
+ "gpt-5.4": 1050000, # GPT-5.4, GPT-5.4 Pro (1.05M context)
162
+ # gpt-5.3-codex-spark is Codex-OAuth-only (ChatGPT Pro entitlement) and
163
+ # uses a smaller 128k window than other gpt-5.x slugs. Listed here as
164
+ # a defensive override so the longest-substring fallback doesn't match
165
+ # the generic "gpt-5" entry below (400k) and report the wrong limit if
166
+ # Spark's context ever needs to be resolved through this path. Real
167
+ # usage flows through _CODEX_OAUTH_CONTEXT_FALLBACK at line ~1113.
168
+ "gpt-5.3-codex-spark": 128000,
169
+ "gpt-5.1-chat": 128000, # Chat variant has 128k context
170
+ "gpt-5": 400000, # GPT-5.x base, mini, codex variants (400k)
171
+ "gpt-4.1": 1047576,
172
+ "gpt-4": 128000,
173
+ # Google
174
+ "gemini": 1048576,
175
+ # Gemma (open models served via AI Studio)
176
+ "gemma-4": 256000, # Gemma 4 family
177
+ "gemma4": 256000, # Ollama-style naming (e.g. gemma4:31b-cloud)
178
+ "gemma-4-31b": 256000,
179
+ "gemma-3": 131072,
180
+ "gemma": 8192, # fallback for older gemma models
181
+ # DeepSeek — V4 family ships with a 1M context window. The legacy
182
+ # aliases ``deepseek-chat`` / ``deepseek-reasoner`` are server-side
183
+ # mapped to the non-thinking / thinking modes of ``deepseek-v4-flash``
184
+ # and inherit the same 1M window. The ``deepseek`` substring entry
185
+ # below remains as a 128K fallback for older / unknown DeepSeek model
186
+ # ids (e.g. via custom endpoints).
187
+ # https://api-docs.deepseek.com/zh-cn/quick_start/pricing
188
+ "deepseek-v4-pro": 1_000_000,
189
+ "deepseek-v4-flash": 1_000_000,
190
+ "deepseek-chat": 1_000_000,
191
+ "deepseek-reasoner": 1_000_000,
192
+ "deepseek": 128000,
193
+ # Meta
194
+ "llama": 131072,
195
+ # Qwen — specific model families before the catch-all.
196
+ # Official docs: https://help.aliyun.com/zh/model-studio/developer-reference/
197
+ "qwen3-coder-plus": 1000000, # 1M context
198
+ "qwen3-coder": 262144, # 256K context
199
+ "qwen": 131072,
200
+ # MiniMax — official docs: 204,800 context for all models
201
+ # https://platform.minimax.io/docs/api-reference/text-anthropic-api
202
+ "minimax": 204800,
203
+ # GLM
204
+ "glm": 202752,
205
+ # xAI Grok — xAI /v1/models does not return context_length metadata,
206
+ # so these hardcoded fallbacks prevent Hermes from probing-down to
207
+ # the default 128k when the user points at https://api.x.ai/v1
208
+ # via a custom provider. Values sourced from models.dev (2026-04).
209
+ # Keys use substring matching (longest-first), so e.g. "grok-4.20"
210
+ # matches "grok-4.20-0309-reasoning" / "-non-reasoning" / "-multi-agent-0309".
211
+ "grok-code-fast": 256000, # grok-code-fast-1
212
+ "grok-4-1-fast": 2000000, # grok-4-1-fast-(non-)reasoning
213
+ "grok-2-vision": 8192, # grok-2-vision, -1212, -latest
214
+ "grok-4-fast": 2000000, # grok-4-fast-(non-)reasoning
215
+ "grok-4.20": 2000000, # grok-4.20-0309-(non-)reasoning, -multi-agent-0309
216
+ "grok-4.3": 1000000, # grok-4.3, grok-4.3-latest — 1M context per docs.x.ai
217
+ "grok-4": 256000, # grok-4, grok-4-0709
218
+ "grok-3": 131072, # grok-3, grok-3-mini, grok-3-fast, grok-3-mini-fast
219
+ "grok-2": 131072, # grok-2, grok-2-1212, grok-2-latest
220
+ "grok": 131072, # catch-all (grok-beta, unknown grok-*)
221
+ # Kimi
222
+ "kimi": 262144,
223
+ # Tencent — Hy3 Preview (Hunyuan) with 256K context window.
224
+ # OpenRouter live metadata reports 262144 (256 × 1024); align the
225
+ # static fallback so cache and offline both agree (issue #22268).
226
+ "hy3-preview": 262144,
227
+ # Nemotron — NVIDIA's open-weights series (128K context across all sizes)
228
+ "nemotron": 131072,
229
+ # Arcee
230
+ "trinity": 262144,
231
+ # OpenRouter
232
+ "elephant": 262144,
233
+ # Hugging Face Inference Providers — model IDs use org/name format
234
+ "Qwen/Qwen3.5-397B-A17B": 131072,
235
+ "Qwen/Qwen3.5-35B-A3B": 131072,
236
+ "deepseek-ai/DeepSeek-V3.2": 65536,
237
+ "moonshotai/Kimi-K2.5": 262144,
238
+ "moonshotai/Kimi-K2.6": 262144,
239
+ "moonshotai/Kimi-K2-Thinking": 262144,
240
+ "MiniMaxAI/MiniMax-M2.5": 204800,
241
+ "XiaomiMiMo/MiMo-V2-Flash": 262144,
242
+ "mimo-v2-pro": 1048576,
243
+ "mimo-v2.5-pro": 1048576,
244
+ "mimo-v2.5": 1048576,
245
+ "mimo-v2-omni": 262144,
246
+ "mimo-v2-flash": 262144,
247
+ "zai-org/GLM-5": 202752,
248
+ }
249
+
250
+ # xAI Grok models that ACCEPT the `reasoning.effort` parameter on
251
+ # api.x.ai. Verified live against /v1/responses 2026-05-10:
252
+ #
253
+ # ACCEPTS effort: grok-3-mini, grok-3-mini-fast, grok-4.20-multi-agent-0309,
254
+ # grok-4.3
255
+ # REJECTS effort: grok-3, grok-4, grok-4-0709, grok-4-fast-(non-)reasoning,
256
+ # grok-4-1-fast-(non-)reasoning, grok-4.20-0309-(non-)reasoning,
257
+ # grok-code-fast-1
258
+ #
259
+ # REJECTS-side models still reason natively — they just don't expose an
260
+ # effort dial — so callers should send no `reasoning` key at all rather
261
+ # than a default `medium` (which 400s with "Model X does not support
262
+ # parameter reasoningEffort").
263
+ _GROK_EFFORT_CAPABLE_PREFIXES = (
264
+ "grok-3-mini",
265
+ "grok-4.20-multi-agent",
266
+ "grok-4.3",
267
+ )
268
+
269
+
270
+ def grok_supports_reasoning_effort(model: str) -> bool:
271
+ """Return True when an xAI Grok model accepts ``reasoning.effort``.
272
+
273
+ Allowlist by substring (matches both bare ``grok-3-mini`` and
274
+ aggregator-prefixed ``x-ai/grok-3-mini``). Conservative by design:
275
+ if a future Grok model isn't listed, we send no effort dial rather
276
+ than 400.
277
+ """
278
+ name = (model or "").strip().lower()
279
+ if not name:
280
+ return False
281
+ # Strip common aggregator prefixes (x-ai/, openrouter/x-ai/, xai/, ...)
282
+ for sep in ("/",):
283
+ if sep in name:
284
+ name = name.rsplit(sep, 1)[-1]
285
+ return any(name.startswith(prefix) for prefix in _GROK_EFFORT_CAPABLE_PREFIXES)
286
+
287
+
288
+ _CONTEXT_LENGTH_KEYS = (
289
+ "context_length",
290
+ "context_window",
291
+ "context_size",
292
+ "max_context_length",
293
+ "max_position_embeddings",
294
+ "max_model_len",
295
+ "max_input_tokens",
296
+ "max_sequence_length",
297
+ "max_seq_len",
298
+ "n_ctx_train",
299
+ "n_ctx",
300
+ "ctx_size",
301
+ )
302
+
303
+ _MAX_COMPLETION_KEYS = (
304
+ "max_completion_tokens",
305
+ "max_output_tokens",
306
+ "max_tokens",
307
+ )
308
+
309
+ # Local server hostnames / address patterns
310
+ _LOCAL_HOSTS = ("localhost", "127.0.0.1", "::1", "0.0.0.0")
311
+ # Docker / Podman / Lima DNS names that resolve to the host machine
312
+ _CONTAINER_LOCAL_SUFFIXES = (
313
+ ".docker.internal",
314
+ ".containers.internal",
315
+ ".lima.internal",
316
+ )
317
+
318
+
319
+ def _normalize_base_url(base_url: str) -> str:
320
+ return (base_url or "").strip().rstrip("/")
321
+
322
+
323
+ def _auth_headers(api_key: str = "") -> Dict[str, str]:
324
+ token = str(api_key or "").strip()
325
+ if not token:
326
+ return {}
327
+ return {"Authorization": f"Bearer {token}"}
328
+
329
+
330
+ def _is_openrouter_base_url(base_url: str) -> bool:
331
+ return base_url_host_matches(base_url, "openrouter.ai")
332
+
333
+
334
+ def _is_custom_endpoint(base_url: str) -> bool:
335
+ normalized = _normalize_base_url(base_url)
336
+ return bool(normalized) and not _is_openrouter_base_url(normalized)
337
+
338
+
339
+ _URL_TO_PROVIDER: Dict[str, str] = {
340
+ "api.openai.com": "openai",
341
+ "chatgpt.com": "openai",
342
+ "api.anthropic.com": "anthropic",
343
+ "api.z.ai": "zai",
344
+ "open.bigmodel.cn": "zai",
345
+ "api.moonshot.ai": "kimi-coding",
346
+ "api.moonshot.cn": "kimi-coding-cn",
347
+ "api.kimi.com": "kimi-coding",
348
+ "api.stepfun.ai": "stepfun",
349
+ "api.stepfun.com": "stepfun",
350
+ "api.arcee.ai": "arcee",
351
+ "api.minimax": "minimax",
352
+ "dashscope.aliyuncs.com": "alibaba",
353
+ "dashscope-intl.aliyuncs.com": "alibaba",
354
+ "portal.qwen.ai": "qwen-oauth",
355
+ "openrouter.ai": "openrouter",
356
+ "generativelanguage.googleapis.com": "gemini",
357
+ "inference-api.nousresearch.com": "nous",
358
+ "api.deepseek.com": "deepseek",
359
+ "api.githubcopilot.com": "copilot",
360
+ "models.github.ai": "copilot",
361
+ # GitHub Models free tier (Azure-hosted prototyping endpoint) — same
362
+ # canonical provider as the Copilot API. Hard per-request token cap
363
+ # (often 8K) makes it unusable for Hermes' system prompt, but mapping
364
+ # it here lets us recognize the endpoint and emit a targeted hint
365
+ # instead of falling through the unknown-custom-endpoint path.
366
+ "models.inference.ai.azure.com": "copilot",
367
+ "api.fireworks.ai": "fireworks",
368
+ "opencode.ai": "opencode-go",
369
+ "api.x.ai": "xai",
370
+ "integrate.api.nvidia.com": "nvidia",
371
+ "api.xiaomimimo.com": "xiaomi",
372
+ "xiaomimimo.com": "xiaomi",
373
+ "api.gmi-serving.com": "gmi",
374
+ "api.novita.ai": "novita",
375
+ "tokenhub.tencentmaas.com": "tencent-tokenhub",
376
+ "ollama.com": "ollama-cloud",
377
+ }
378
+
379
+ # Auto-extend with hostnames derived from provider profiles.
380
+ # Any provider with a base_url not already in the map gets added automatically.
381
+ try:
382
+ from providers import list_providers as _list_providers
383
+ for _pp in _list_providers():
384
+ _host = _pp.get_hostname()
385
+ if _host and _host not in _URL_TO_PROVIDER:
386
+ _URL_TO_PROVIDER[_host] = _pp.name
387
+ except Exception:
388
+ pass
389
+
390
+
391
+ def _infer_provider_from_url(base_url: str) -> Optional[str]:
392
+ """Infer the models.dev provider name from a base URL.
393
+
394
+ This allows context length resolution via models.dev for custom endpoints
395
+ like DashScope (Alibaba), Z.AI, Kimi, etc. without requiring the user to
396
+ explicitly set the provider name in config.
397
+ """
398
+ normalized = _normalize_base_url(base_url)
399
+ if not normalized:
400
+ return None
401
+ parsed = urlparse(normalized if "://" in normalized else f"https://{normalized}")
402
+ host = parsed.netloc.lower() or parsed.path.lower()
403
+ for url_part, provider in _URL_TO_PROVIDER.items():
404
+ if url_part in host:
405
+ return provider
406
+ return None
407
+
408
+
409
+ def _is_known_provider_base_url(base_url: str) -> bool:
410
+ return _infer_provider_from_url(base_url) is not None
411
+
412
+
413
+ def is_local_endpoint(base_url: str) -> bool:
414
+ """Return True if base_url points to a local machine.
415
+
416
+ Recognises loopback (``localhost``, ``127.0.0.0/8``, ``::1``),
417
+ container-internal DNS names (``host.docker.internal`` et al.),
418
+ RFC-1918 private ranges (``10/8``, ``172.16/12``, ``192.168/16``),
419
+ link-local, and Tailscale CGNAT (``100.64.0.0/10``). Tailscale CGNAT
420
+ is included so remote-but-trusted Ollama boxes reached over a
421
+ Tailscale mesh get the same timeout auto-bumps as localhost Ollama.
422
+ """
423
+ normalized = _normalize_base_url(base_url)
424
+ if not normalized:
425
+ return False
426
+ url = normalized if "://" in normalized else f"http://{normalized}"
427
+ try:
428
+ parsed = urlparse(url)
429
+ host = parsed.hostname or ""
430
+ except Exception:
431
+ return False
432
+ if host in _LOCAL_HOSTS:
433
+ return True
434
+ # Docker / Podman / Lima internal DNS names (e.g. host.docker.internal)
435
+ if any(host.endswith(suffix) for suffix in _CONTAINER_LOCAL_SUFFIXES):
436
+ return True
437
+ # RFC-1918 private ranges, link-local, and Tailscale CGNAT
438
+ try:
439
+ addr = ipaddress.ip_address(host)
440
+ if addr.is_private or addr.is_loopback or addr.is_link_local:
441
+ return True
442
+ if isinstance(addr, ipaddress.IPv4Address) and addr in _TAILSCALE_CGNAT:
443
+ return True
444
+ except ValueError:
445
+ pass
446
+ # Bare IP that looks like a private range (e.g. 172.26.x.x for WSL)
447
+ # or Tailscale CGNAT (100.64.x.x–100.127.x.x).
448
+ parts = host.split(".")
449
+ if len(parts) == 4:
450
+ try:
451
+ first, second = int(parts[0]), int(parts[1])
452
+ if first == 10:
453
+ return True
454
+ if first == 172 and 16 <= second <= 31:
455
+ return True
456
+ if first == 192 and second == 168:
457
+ return True
458
+ if first == 100 and 64 <= second <= 127:
459
+ return True
460
+ except ValueError:
461
+ pass
462
+ return False
463
+
464
+
465
+ def detect_local_server_type(base_url: str, api_key: str = "") -> Optional[str]:
466
+ """Detect which local server is running at base_url by probing known endpoints.
467
+
468
+ Returns one of: "ollama", "lm-studio", "vllm", "llamacpp", or None.
469
+ """
470
+ import httpx
471
+
472
+ normalized = _normalize_base_url(base_url)
473
+ server_url = normalized
474
+ if server_url.endswith("/v1"):
475
+ server_url = server_url[:-3]
476
+
477
+ headers = _auth_headers(api_key)
478
+
479
+ try:
480
+ with httpx.Client(timeout=2.0, headers=headers) as client:
481
+ # LM Studio exposes /api/v1/models — check first (most specific)
482
+ try:
483
+ r = client.get(f"{server_url}/api/v1/models")
484
+ if r.status_code == 200:
485
+ return "lm-studio"
486
+ except Exception:
487
+ pass
488
+ # Ollama exposes /api/tags and responds with {"models": [...]}
489
+ # LM Studio returns {"error": "Unexpected endpoint"} with status 200
490
+ # on this path, so we must verify the response contains "models".
491
+ try:
492
+ r = client.get(f"{server_url}/api/tags")
493
+ if r.status_code == 200:
494
+ try:
495
+ data = r.json()
496
+ if "models" in data:
497
+ return "ollama"
498
+ except Exception:
499
+ pass
500
+ except Exception:
501
+ pass
502
+ # llama.cpp exposes /v1/props (older builds used /props without the /v1 prefix)
503
+ try:
504
+ r = client.get(f"{server_url}/v1/props")
505
+ if r.status_code != 200:
506
+ r = client.get(f"{server_url}/props") # fallback for older builds
507
+ if r.status_code == 200 and "default_generation_settings" in r.text:
508
+ return "llamacpp"
509
+ except Exception:
510
+ pass
511
+ # vLLM: /version
512
+ try:
513
+ r = client.get(f"{server_url}/version")
514
+ if r.status_code == 200:
515
+ data = r.json()
516
+ if "version" in data:
517
+ return "vllm"
518
+ except Exception:
519
+ pass
520
+ except Exception:
521
+ pass
522
+
523
+ return None
524
+
525
+
526
+ def _iter_nested_dicts(value: Any):
527
+ if isinstance(value, dict):
528
+ yield value
529
+ for nested in value.values():
530
+ yield from _iter_nested_dicts(nested)
531
+ elif isinstance(value, list):
532
+ for item in value:
533
+ yield from _iter_nested_dicts(item)
534
+
535
+
536
+ def _coerce_reasonable_int(value: Any, minimum: int = 1024, maximum: int = 10_000_000) -> Optional[int]:
537
+ try:
538
+ if isinstance(value, bool):
539
+ return None
540
+ if isinstance(value, str):
541
+ value = value.strip().replace(",", "")
542
+ result = int(value)
543
+ except (TypeError, ValueError):
544
+ return None
545
+ if minimum <= result <= maximum:
546
+ return result
547
+ return None
548
+
549
+
550
+ def _extract_first_int(payload: Dict[str, Any], keys: tuple[str, ...]) -> Optional[int]:
551
+ keyset = {key.lower() for key in keys}
552
+ for mapping in _iter_nested_dicts(payload):
553
+ for key, value in mapping.items():
554
+ if str(key).lower() not in keyset:
555
+ continue
556
+ coerced = _coerce_reasonable_int(value)
557
+ if coerced is not None:
558
+ return coerced
559
+ return None
560
+
561
+
562
+ def _extract_context_length(payload: Dict[str, Any]) -> Optional[int]:
563
+ return _extract_first_int(payload, _CONTEXT_LENGTH_KEYS)
564
+
565
+
566
+ def _extract_max_completion_tokens(payload: Dict[str, Any]) -> Optional[int]:
567
+ return _extract_first_int(payload, _MAX_COMPLETION_KEYS)
568
+
569
+
570
+ def _extract_pricing(payload: Dict[str, Any]) -> Dict[str, Any]:
571
+ novita_input = payload.get("input_token_price_per_m")
572
+ novita_output = payload.get("output_token_price_per_m")
573
+ if novita_input is not None or novita_output is not None:
574
+ pricing: Dict[str, Any] = {}
575
+ if novita_input is not None:
576
+ pricing["prompt"] = str(float(novita_input) / 10_000 / 1_000_000)
577
+ if novita_output is not None:
578
+ pricing["completion"] = str(float(novita_output) / 10_000 / 1_000_000)
579
+ return pricing
580
+
581
+ alias_map = {
582
+ "prompt": ("prompt", "input", "input_cost_per_token", "prompt_token_cost"),
583
+ "completion": ("completion", "output", "output_cost_per_token", "completion_token_cost"),
584
+ "request": ("request", "request_cost"),
585
+ "cache_read": ("cache_read", "cached_prompt", "input_cache_read", "cache_read_cost_per_token"),
586
+ "cache_write": ("cache_write", "cache_creation", "input_cache_write", "cache_write_cost_per_token"),
587
+ }
588
+ for mapping in _iter_nested_dicts(payload):
589
+ normalized = {str(key).lower(): value for key, value in mapping.items()}
590
+ if not any(any(alias in normalized for alias in aliases) for aliases in alias_map.values()):
591
+ continue
592
+ pricing: Dict[str, Any] = {}
593
+ for target, aliases in alias_map.items():
594
+ for alias in aliases:
595
+ if alias in normalized and normalized[alias] not in {None, ""}:
596
+ pricing[target] = normalized[alias]
597
+ break
598
+ if pricing:
599
+ return pricing
600
+ return {}
601
+
602
+
603
+ def _add_model_aliases(cache: Dict[str, Dict[str, Any]], model_id: str, entry: Dict[str, Any]) -> None:
604
+ cache[model_id] = entry
605
+ if "/" in model_id:
606
+ bare_model = model_id.split("/", 1)[1]
607
+ cache.setdefault(bare_model, entry)
608
+
609
+
610
+ def fetch_model_metadata(force_refresh: bool = False) -> Dict[str, Dict[str, Any]]:
611
+ """Fetch model metadata from OpenRouter (cached for 1 hour)."""
612
+ global _model_metadata_cache, _model_metadata_cache_time
613
+
614
+ if not force_refresh and _model_metadata_cache and (time.time() - _model_metadata_cache_time) < _MODEL_CACHE_TTL:
615
+ return _model_metadata_cache
616
+
617
+ try:
618
+ response = requests.get(OPENROUTER_MODELS_URL, timeout=10, verify=_resolve_requests_verify())
619
+ response.raise_for_status()
620
+ data = response.json()
621
+
622
+ cache = {}
623
+ for model in data.get("data", []):
624
+ model_id = model.get("id", "")
625
+ entry = {
626
+ "context_length": model.get("context_length", 128000),
627
+ "max_completion_tokens": model.get("top_provider", {}).get("max_completion_tokens", 4096),
628
+ "name": model.get("name", model_id),
629
+ "pricing": model.get("pricing", {}),
630
+ }
631
+ _add_model_aliases(cache, model_id, entry)
632
+ canonical = model.get("canonical_slug", "")
633
+ if canonical and canonical != model_id:
634
+ _add_model_aliases(cache, canonical, entry)
635
+
636
+ _model_metadata_cache = cache
637
+ _model_metadata_cache_time = time.time()
638
+ logger.debug("Fetched metadata for %s models from OpenRouter", len(cache))
639
+ return cache
640
+
641
+ except Exception as e:
642
+ logging.warning(f"Failed to fetch model metadata from OpenRouter: {e}")
643
+ return _model_metadata_cache or {}
644
+
645
+
646
+ def fetch_endpoint_model_metadata(
647
+ base_url: str,
648
+ api_key: str = "",
649
+ force_refresh: bool = False,
650
+ ) -> Dict[str, Dict[str, Any]]:
651
+ """Fetch model metadata from an OpenAI-compatible ``/models`` endpoint.
652
+
653
+ This is used for explicit custom endpoints where hardcoded global model-name
654
+ defaults are unreliable. Results are cached in memory per base URL.
655
+ """
656
+ normalized = _normalize_base_url(base_url)
657
+ if not normalized or _is_openrouter_base_url(normalized):
658
+ return {}
659
+
660
+ if not force_refresh:
661
+ cached = _endpoint_model_metadata_cache.get(normalized)
662
+ cached_at = _endpoint_model_metadata_cache_time.get(normalized, 0)
663
+ if cached is not None and (time.time() - cached_at) < _ENDPOINT_MODEL_CACHE_TTL:
664
+ return cached
665
+
666
+ candidates = [normalized]
667
+ if normalized.endswith("/v1"):
668
+ alternate = normalized[:-3].rstrip("/")
669
+ else:
670
+ alternate = normalized + "/v1"
671
+ if alternate and alternate not in candidates:
672
+ candidates.append(alternate)
673
+
674
+ headers = {"Authorization": f"Bearer {api_key}"} if api_key else {}
675
+ last_error: Optional[Exception] = None
676
+
677
+ if is_local_endpoint(normalized):
678
+ try:
679
+ if detect_local_server_type(normalized, api_key=api_key) == "lm-studio":
680
+ server_url = normalized[:-3].rstrip("/") if normalized.endswith("/v1") else normalized
681
+ response = requests.get(
682
+ server_url.rstrip("/") + "/api/v1/models",
683
+ headers=headers,
684
+ timeout=10,
685
+ verify=_resolve_requests_verify(),
686
+ )
687
+ response.raise_for_status()
688
+ payload = response.json()
689
+ cache: Dict[str, Dict[str, Any]] = {}
690
+ for model in payload.get("models", []):
691
+ if not isinstance(model, dict):
692
+ continue
693
+ model_id = model.get("key") or model.get("id")
694
+ if not model_id:
695
+ continue
696
+ entry: Dict[str, Any] = {"name": model.get("name", model_id)}
697
+
698
+ context_length = None
699
+ for inst in model.get("loaded_instances", []) or []:
700
+ if not isinstance(inst, dict):
701
+ continue
702
+ cfg = inst.get("config", {})
703
+ ctx = cfg.get("context_length") if isinstance(cfg, dict) else None
704
+ if isinstance(ctx, int) and ctx > 0:
705
+ context_length = ctx
706
+ break
707
+ if context_length is not None:
708
+ entry["context_length"] = context_length
709
+
710
+ max_completion_tokens = _extract_max_completion_tokens(model)
711
+ if max_completion_tokens is not None:
712
+ entry["max_completion_tokens"] = max_completion_tokens
713
+
714
+ pricing = _extract_pricing(model)
715
+ if pricing:
716
+ entry["pricing"] = pricing
717
+
718
+ _add_model_aliases(cache, model_id, entry)
719
+ alt_id = model.get("id")
720
+ if isinstance(alt_id, str) and alt_id and alt_id != model_id:
721
+ _add_model_aliases(cache, alt_id, entry)
722
+
723
+ _endpoint_model_metadata_cache[normalized] = cache
724
+ _endpoint_model_metadata_cache_time[normalized] = time.time()
725
+ return cache
726
+ except Exception as exc:
727
+ last_error = exc
728
+
729
+ for candidate in candidates:
730
+ url = candidate.rstrip("/") + "/models"
731
+ try:
732
+ response = requests.get(url, headers=headers, timeout=10, verify=_resolve_requests_verify())
733
+ response.raise_for_status()
734
+ payload = response.json()
735
+ cache: Dict[str, Dict[str, Any]] = {}
736
+ for model in payload.get("data", []):
737
+ if not isinstance(model, dict):
738
+ continue
739
+ model_id = model.get("id")
740
+ if not model_id:
741
+ continue
742
+ entry: Dict[str, Any] = {"name": model.get("name", model_id)}
743
+ context_length = _extract_context_length(model)
744
+ if context_length is not None:
745
+ entry["context_length"] = context_length
746
+ max_completion_tokens = _extract_max_completion_tokens(model)
747
+ if max_completion_tokens is not None:
748
+ entry["max_completion_tokens"] = max_completion_tokens
749
+ pricing = _extract_pricing(model)
750
+ if pricing:
751
+ entry["pricing"] = pricing
752
+ _add_model_aliases(cache, model_id, entry)
753
+
754
+ # If this is a llama.cpp server, query /props for actual allocated context
755
+ is_llamacpp = any(
756
+ m.get("owned_by") == "llamacpp"
757
+ for m in payload.get("data", []) if isinstance(m, dict)
758
+ )
759
+ if is_llamacpp:
760
+ try:
761
+ # Try /v1/props first (current llama.cpp); fall back to /props for older builds
762
+ base = candidate.rstrip("/").replace("/v1", "")
763
+ _verify = _resolve_requests_verify()
764
+ props_resp = requests.get(base + "/v1/props", headers=headers, timeout=5, verify=_verify)
765
+ if not props_resp.ok:
766
+ props_resp = requests.get(base + "/props", headers=headers, timeout=5, verify=_verify)
767
+ if props_resp.ok:
768
+ props = props_resp.json()
769
+ gen_settings = props.get("default_generation_settings", {})
770
+ n_ctx = gen_settings.get("n_ctx")
771
+ model_alias = props.get("model_alias", "")
772
+ if n_ctx and model_alias and model_alias in cache:
773
+ cache[model_alias]["context_length"] = n_ctx
774
+ except Exception:
775
+ pass
776
+
777
+ _endpoint_model_metadata_cache[normalized] = cache
778
+ _endpoint_model_metadata_cache_time[normalized] = time.time()
779
+ return cache
780
+ except Exception as exc:
781
+ last_error = exc
782
+
783
+ if last_error:
784
+ logger.debug("Failed to fetch model metadata from %s/models: %s", normalized, last_error)
785
+ _endpoint_model_metadata_cache[normalized] = {}
786
+ _endpoint_model_metadata_cache_time[normalized] = time.time()
787
+ return {}
788
+
789
+
790
+ def _resolve_endpoint_context_length(
791
+ model: str,
792
+ base_url: str,
793
+ api_key: str = "",
794
+ ) -> Optional[int]:
795
+ """Resolve context length from an endpoint's live ``/models`` metadata."""
796
+ endpoint_metadata = fetch_endpoint_model_metadata(base_url, api_key=api_key)
797
+ matched = endpoint_metadata.get(model)
798
+ if not matched:
799
+ if len(endpoint_metadata) == 1:
800
+ matched = next(iter(endpoint_metadata.values()))
801
+ else:
802
+ for key, entry in endpoint_metadata.items():
803
+ if model in key or key in model:
804
+ matched = entry
805
+ break
806
+ if matched:
807
+ context_length = matched.get("context_length")
808
+ if isinstance(context_length, int):
809
+ return context_length
810
+ return None
811
+
812
+
813
+ def _get_context_cache_path() -> Path:
814
+ """Return path to the persistent context length cache file."""
815
+ from calvyn_constants import get_hermes_home
816
+ return get_hermes_home() / "context_length_cache.yaml"
817
+
818
+
819
+ def _load_context_cache() -> Dict[str, int]:
820
+ """Load the model+provider -> context_length cache from disk."""
821
+ path = _get_context_cache_path()
822
+ if not path.exists():
823
+ return {}
824
+ try:
825
+ with open(path, encoding="utf-8") as f:
826
+ data = yaml.safe_load(f) or {}
827
+ return data.get("context_lengths", {})
828
+ except Exception as e:
829
+ logger.debug("Failed to load context length cache: %s", e)
830
+ return {}
831
+
832
+
833
+ def save_context_length(model: str, base_url: str, length: int) -> None:
834
+ """Persist a discovered context length for a model+provider combo.
835
+
836
+ Cache key is ``model@base_url`` so the same model name served from
837
+ different providers can have different limits.
838
+ """
839
+ key = f"{model}@{base_url}"
840
+ cache = _load_context_cache()
841
+ if cache.get(key) == length:
842
+ return # already stored
843
+ cache[key] = length
844
+ path = _get_context_cache_path()
845
+ try:
846
+ path.parent.mkdir(parents=True, exist_ok=True)
847
+ with open(path, "w", encoding="utf-8") as f:
848
+ yaml.dump({"context_lengths": cache}, f, default_flow_style=False)
849
+ logger.info("Cached context length %s -> %s tokens", key, f"{length:,}")
850
+ except Exception as e:
851
+ logger.debug("Failed to save context length cache: %s", e)
852
+
853
+
854
+ def get_cached_context_length(model: str, base_url: str) -> Optional[int]:
855
+ """Look up a previously discovered context length for model+provider."""
856
+ key = f"{model}@{base_url}"
857
+ cache = _load_context_cache()
858
+ return cache.get(key)
859
+
860
+
861
+ def _invalidate_cached_context_length(model: str, base_url: str) -> None:
862
+ """Drop a stale cache entry so it gets re-resolved on the next lookup."""
863
+ key = f"{model}@{base_url}"
864
+ cache = _load_context_cache()
865
+ if key not in cache:
866
+ return
867
+ del cache[key]
868
+ path = _get_context_cache_path()
869
+ try:
870
+ path.parent.mkdir(parents=True, exist_ok=True)
871
+ with open(path, "w", encoding="utf-8") as f:
872
+ yaml.dump({"context_lengths": cache}, f, default_flow_style=False)
873
+ except Exception as e:
874
+ logger.debug("Failed to invalidate context length cache entry %s: %s", key, e)
875
+
876
+
877
+ def get_next_probe_tier(current_length: int) -> Optional[int]:
878
+ """Return the next lower probe tier, or None if already at minimum."""
879
+ for tier in CONTEXT_PROBE_TIERS:
880
+ if tier < current_length:
881
+ return tier
882
+ return None
883
+
884
+
885
+ def parse_context_limit_from_error(error_msg: str) -> Optional[int]:
886
+ """Try to extract the actual context limit from an API error message.
887
+
888
+ Many providers include the limit in their error text, e.g.:
889
+ - "maximum context length is 32768 tokens"
890
+ - "context_length_exceeded: 131072"
891
+ - "Maximum context size 32768 exceeded"
892
+ - "model's max context length is 65536"
893
+ """
894
+ error_lower = error_msg.lower()
895
+ # Pattern: look for numbers near context-related keywords
896
+ patterns = [
897
+ r'(?:max(?:imum)?|limit)\s*(?:context\s*)?(?:length|size|window)?\s*(?:is|of|:)?\s*(\d{4,})',
898
+ r'context\s*(?:length|size|window)\s*(?:is|of|:)?\s*(\d{4,})',
899
+ r'(\d{4,})\s*(?:token)?\s*(?:context|limit)',
900
+ r'>\s*(\d{4,})\s*(?:max|limit|token)', # "250000 tokens > 200000 maximum"
901
+ r'(\d{4,})\s*(?:max(?:imum)?)\b', # "200000 maximum"
902
+ ]
903
+ for pattern in patterns:
904
+ match = re.search(pattern, error_lower)
905
+ if match:
906
+ limit = int(match.group(1))
907
+ # Sanity check: must be a reasonable context length
908
+ if 1024 <= limit <= 10_000_000:
909
+ return limit
910
+ return None
911
+
912
+
913
+ def parse_available_output_tokens_from_error(error_msg: str) -> Optional[int]:
914
+ """Detect an "output cap too large" error and return how many output tokens are available.
915
+
916
+ Background — two distinct context errors exist:
917
+ 1. "Prompt too long" — the INPUT itself exceeds the context window.
918
+ Fix: compress history and/or halve context_length.
919
+ 2. "max_tokens too large" — input is fine, but input + requested_output > window.
920
+ Fix: reduce max_tokens (the output cap) for this call.
921
+ Do NOT touch context_length — the window hasn't shrunk.
922
+
923
+ Anthropic's API returns errors like:
924
+ "max_tokens: 32768 > context_window: 200000 - input_tokens: 190000 = available_tokens: 10000"
925
+
926
+ Returns the number of output tokens that would fit (e.g. 10000 above), or None if
927
+ the error does not look like a max_tokens-too-large error.
928
+ """
929
+ error_lower = error_msg.lower()
930
+
931
+ # Must look like an output-cap error, not a prompt-length error.
932
+ is_output_cap_error = (
933
+ "max_tokens" in error_lower
934
+ and ("available_tokens" in error_lower or "available tokens" in error_lower)
935
+ )
936
+ if not is_output_cap_error:
937
+ return None
938
+
939
+ # Extract the available_tokens figure.
940
+ # Anthropic format: "… = available_tokens: 10000"
941
+ patterns = [
942
+ r'available_tokens[:\s]+(\d+)',
943
+ r'available\s+tokens[:\s]+(\d+)',
944
+ # fallback: last number after "=" in expressions like "200000 - 190000 = 10000"
945
+ r'=\s*(\d+)\s*$',
946
+ ]
947
+ for pattern in patterns:
948
+ match = re.search(pattern, error_lower)
949
+ if match:
950
+ tokens = int(match.group(1))
951
+ if tokens >= 1:
952
+ return tokens
953
+ return None
954
+
955
+
956
+ def _model_id_matches(candidate_id: str, lookup_model: str) -> bool:
957
+ """Return True if *candidate_id* (from server) matches *lookup_model* (configured).
958
+
959
+ Supports two forms:
960
+ - Exact match: "nvidia-nemotron-super-49b-v1" == "nvidia-nemotron-super-49b-v1"
961
+ - Slug match: "nvidia/nvidia-nemotron-super-49b-v1" matches "nvidia-nemotron-super-49b-v1"
962
+ (the part after the last "/" equals lookup_model)
963
+
964
+ This covers LM Studio's native API which stores models as "publisher/slug"
965
+ while users typically configure only the slug after the "local:" prefix.
966
+ """
967
+ if candidate_id == lookup_model:
968
+ return True
969
+ # Slug match: basename of candidate equals the lookup name
970
+ if "/" in candidate_id and candidate_id.rsplit("/", 1)[1] == lookup_model:
971
+ return True
972
+ return False
973
+
974
+
975
+ def query_ollama_num_ctx(model: str, base_url: str, api_key: str = "") -> Optional[int]:
976
+ """Query an Ollama server for the model's context length.
977
+
978
+ Returns the model's maximum context from GGUF metadata via ``/api/show``,
979
+ or the explicit ``num_ctx`` from the Modelfile if set. Returns None if
980
+ the server is unreachable or not Ollama.
981
+
982
+ This is the value that should be passed as ``num_ctx`` in Ollama chat
983
+ requests to override the default 2048.
984
+ """
985
+ import httpx
986
+
987
+ bare_model = _strip_provider_prefix(model)
988
+ server_url = base_url.rstrip("/")
989
+ if server_url.endswith("/v1"):
990
+ server_url = server_url[:-3]
991
+
992
+ try:
993
+ server_type = detect_local_server_type(base_url, api_key=api_key)
994
+ except Exception:
995
+ return None
996
+ if server_type != "ollama":
997
+ return None
998
+
999
+ headers = _auth_headers(api_key)
1000
+
1001
+ try:
1002
+ with httpx.Client(timeout=3.0, headers=headers) as client:
1003
+ resp = client.post(f"{server_url}/api/show", json={"name": bare_model})
1004
+ if resp.status_code != 200:
1005
+ return None
1006
+ data = resp.json()
1007
+
1008
+ # Prefer explicit num_ctx from Modelfile parameters (user override)
1009
+ params = data.get("parameters", "")
1010
+ if "num_ctx" in params:
1011
+ for line in params.split("\n"):
1012
+ if "num_ctx" in line:
1013
+ parts = line.strip().split()
1014
+ if len(parts) >= 2:
1015
+ try:
1016
+ return int(parts[-1])
1017
+ except ValueError:
1018
+ pass
1019
+
1020
+ # Fall back to GGUF model_info context_length (training max)
1021
+ model_info = data.get("model_info", {})
1022
+ for key, value in model_info.items():
1023
+ if "context_length" in key and isinstance(value, (int, float)):
1024
+ return int(value)
1025
+ except Exception:
1026
+ pass
1027
+ return None
1028
+
1029
+
1030
+ def _query_ollama_api_show(model: str, base_url: str, api_key: str = "") -> Optional[int]:
1031
+ """Query an Ollama server's native ``/api/show`` for context length.
1032
+
1033
+ Provider-agnostic: works against ANY Ollama-compatible server regardless
1034
+ of hostname — local Ollama, Ollama Cloud (``ollama.com``), custom Ollama
1035
+ hosting behind a reverse proxy, etc. For non-Ollama servers the POST
1036
+ returns 404/405 quickly; the function handles errors gracefully.
1037
+
1038
+ For hosted servers the GGUF ``model_info.*.context_length`` is the
1039
+ authoritative source: the user can't set their own ``num_ctx``, and the
1040
+ OpenAI-compat ``/v1/models`` endpoint correctly omits ``context_length``
1041
+ per the OpenAI schema.
1042
+
1043
+ Resolution order for hosted Ollama:
1044
+ 1. ``model_info.*.context_length`` — GGUF training max (authoritative)
1045
+ 2. ``parameters`` → ``num_ctx`` — server-side Modelfile override
1046
+ The order is flipped vs ``query_ollama_num_ctx()`` because local users
1047
+ control ``num_ctx`` themselves; hosted users can't.
1048
+ """
1049
+ import httpx
1050
+
1051
+ server_url = base_url.rstrip("/")
1052
+ if server_url.endswith("/v1"):
1053
+ server_url = server_url[:-3]
1054
+
1055
+ headers = _auth_headers(api_key)
1056
+
1057
+ try:
1058
+ with httpx.Client(timeout=5.0, headers=headers) as client:
1059
+ resp = client.post(f"{server_url}/api/show", json={"name": model})
1060
+ if resp.status_code != 200:
1061
+ return None
1062
+ data = resp.json()
1063
+
1064
+ # Hosted Ollama: GGUF model_info is the real max — prefer it over
1065
+ # num_ctx which the Cloud operator may have capped arbitrarily.
1066
+ model_info = data.get("model_info", {})
1067
+ for key, value in model_info.items():
1068
+ if "context_length" in key and isinstance(value, (int, float)):
1069
+ ctx = int(value)
1070
+ if ctx >= 1024:
1071
+ return ctx
1072
+
1073
+ # Fall back to num_ctx from Modelfile parameters (rare on Cloud)
1074
+ params = data.get("parameters", "")
1075
+ if "num_ctx" in params:
1076
+ for line in params.split("\n"):
1077
+ if "num_ctx" in line:
1078
+ parts = line.strip().split()
1079
+ if len(parts) >= 2:
1080
+ try:
1081
+ ctx = int(parts[-1])
1082
+ if ctx >= 1024:
1083
+ return ctx
1084
+ except ValueError:
1085
+ pass
1086
+ except Exception:
1087
+ pass
1088
+ return None
1089
+
1090
+
1091
+ def _model_name_suggests_kimi(model: str) -> bool:
1092
+ """Return True if the model name looks like a Kimi-family model.
1093
+
1094
+ Catches ``kimi-k2.6``, ``kimi-k2.5``, ``kimi-k2-thinking``,
1095
+ ``moonshotai/Kimi-K2.6``, and similar variants. Used as a guard
1096
+ against stale OpenRouter metadata that underreports these models
1097
+ as 32K context when they actually support 262K+.
1098
+ """
1099
+ lower = model.lower()
1100
+ return lower.startswith("kimi") or "moonshot" in lower
1101
+
1102
+
1103
+ def _query_local_context_length(model: str, base_url: str, api_key: str = "") -> Optional[int]:
1104
+ """Query a local server for the model's context length."""
1105
+ import httpx
1106
+
1107
+ # Strip recognised provider prefix (e.g., "local:model-name" → "model-name").
1108
+ # Ollama "model:tag" colons (e.g. "qwen3.5:27b") are intentionally preserved.
1109
+ model = _strip_provider_prefix(model)
1110
+
1111
+ # Strip /v1 suffix to get the server root
1112
+ server_url = base_url.rstrip("/")
1113
+ if server_url.endswith("/v1"):
1114
+ server_url = server_url[:-3]
1115
+
1116
+ headers = _auth_headers(api_key)
1117
+
1118
+ try:
1119
+ server_type = detect_local_server_type(base_url, api_key=api_key)
1120
+ except Exception:
1121
+ server_type = None
1122
+
1123
+ try:
1124
+ with httpx.Client(timeout=3.0, headers=headers) as client:
1125
+ # Ollama: /api/show returns model details with context info
1126
+ if server_type == "ollama":
1127
+ resp = client.post(f"{server_url}/api/show", json={"name": model})
1128
+ if resp.status_code == 200:
1129
+ data = resp.json()
1130
+ # Prefer explicit num_ctx from Modelfile parameters: this is
1131
+ # the *runtime* context Ollama will actually allocate KV cache
1132
+ # for. The GGUF model_info.context_length is the training max,
1133
+ # which can be larger than num_ctx — using it here would let
1134
+ # Hermes grow conversations past the runtime limit and Ollama
1135
+ # would silently truncate. Matches query_ollama_num_ctx().
1136
+ params = data.get("parameters", "")
1137
+ if "num_ctx" in params:
1138
+ for line in params.split("\n"):
1139
+ if "num_ctx" in line:
1140
+ parts = line.strip().split()
1141
+ if len(parts) >= 2:
1142
+ try:
1143
+ return int(parts[-1])
1144
+ except ValueError:
1145
+ pass
1146
+ # Fall back to GGUF model_info context_length (training max)
1147
+ model_info = data.get("model_info", {})
1148
+ for key, value in model_info.items():
1149
+ if "context_length" in key and isinstance(value, (int, float)):
1150
+ return int(value)
1151
+
1152
+ # LM Studio native API: /api/v1/models returns max_context_length.
1153
+ # This is more reliable than the OpenAI-compat /v1/models which
1154
+ # doesn't include context window information for LM Studio servers.
1155
+ # Use _model_id_matches for fuzzy matching: LM Studio stores models as
1156
+ # "publisher/slug" but users configure only "slug" after "local:" prefix.
1157
+ if server_type == "lm-studio":
1158
+ resp = client.get(f"{server_url}/api/v1/models")
1159
+ if resp.status_code == 200:
1160
+ data = resp.json()
1161
+ for m in data.get("models", []):
1162
+ if _model_id_matches(m.get("key", ""), model) or _model_id_matches(m.get("id", ""), model):
1163
+ # Prefer loaded instance context (actual runtime value)
1164
+ for inst in m.get("loaded_instances", []):
1165
+ cfg = inst.get("config", {})
1166
+ ctx = cfg.get("context_length")
1167
+ if ctx and isinstance(ctx, (int, float)):
1168
+ return int(ctx)
1169
+ break
1170
+
1171
+ # LM Studio / vLLM / llama.cpp: try /v1/models/{model}
1172
+ resp = client.get(f"{server_url}/v1/models/{model}")
1173
+ if resp.status_code == 200:
1174
+ data = resp.json()
1175
+ # vLLM returns max_model_len
1176
+ ctx = data.get("max_model_len") or data.get("context_length") or data.get("max_tokens")
1177
+ if ctx and isinstance(ctx, (int, float)):
1178
+ return int(ctx)
1179
+
1180
+ # Try /v1/models and find the model in the list.
1181
+ # Use _model_id_matches to handle "publisher/slug" vs bare "slug".
1182
+ resp = client.get(f"{server_url}/v1/models")
1183
+ if resp.status_code == 200:
1184
+ data = resp.json()
1185
+ models_list = data.get("data", [])
1186
+ for m in models_list:
1187
+ if _model_id_matches(m.get("id", ""), model):
1188
+ ctx = m.get("max_model_len") or m.get("context_length") or m.get("max_tokens")
1189
+ if ctx and isinstance(ctx, (int, float)):
1190
+ return int(ctx)
1191
+ except Exception:
1192
+ pass
1193
+
1194
+ return None
1195
+
1196
+
1197
+ def _normalize_model_version(model: str) -> str:
1198
+ """Normalize version separators for matching.
1199
+
1200
+ Nous uses dashes: claude-opus-4-6, claude-sonnet-4-5
1201
+ OpenRouter uses dots: claude-opus-4.6, claude-sonnet-4.5
1202
+ Normalize both to dashes for comparison.
1203
+ """
1204
+ return model.replace(".", "-")
1205
+
1206
+
1207
+ def _query_anthropic_context_length(model: str, base_url: str, api_key: str) -> Optional[int]:
1208
+ """Query Anthropic's /v1/models endpoint for context length.
1209
+
1210
+ Only works with regular ANTHROPIC_API_KEY (sk-ant-api*).
1211
+ OAuth tokens (sk-ant-oat*) from Claude Code return 401.
1212
+ """
1213
+ if not api_key or api_key.startswith("sk-ant-oat"):
1214
+ return None # OAuth tokens can't access /v1/models
1215
+ try:
1216
+ base = base_url.rstrip("/")
1217
+ if base.endswith("/v1"):
1218
+ base = base[:-3]
1219
+ url = f"{base}/v1/models?limit=1000"
1220
+ headers = {
1221
+ "x-api-key": api_key,
1222
+ "anthropic-version": "2023-06-01",
1223
+ }
1224
+ resp = requests.get(url, headers=headers, timeout=10, verify=_resolve_requests_verify())
1225
+ if resp.status_code != 200:
1226
+ return None
1227
+ data = resp.json()
1228
+ for m in data.get("data", []):
1229
+ if m.get("id") == model:
1230
+ ctx = m.get("max_input_tokens")
1231
+ if isinstance(ctx, int) and ctx > 0:
1232
+ return ctx
1233
+ except Exception as e:
1234
+ logger.debug("Anthropic /v1/models query failed: %s", e)
1235
+ return None
1236
+
1237
+
1238
+ # Known ChatGPT Codex OAuth context windows (observed via live
1239
+ # chatgpt.com/backend-api/codex/models probe, Apr 2026). These are the
1240
+ # `context_window` values, which are what Codex actually enforces — the
1241
+ # direct OpenAI API has larger limits for the same slugs, but Codex OAuth
1242
+ # caps lower (e.g. gpt-5.5 is 1.05M on the API, 272K on Codex).
1243
+ #
1244
+ # Used as a fallback when the live probe fails (no token, network error).
1245
+ # Longest keys first so substring match picks the most specific entry.
1246
+ _CODEX_OAUTH_CONTEXT_FALLBACK: Dict[str, int] = {
1247
+ "gpt-5.1-codex-max": 272_000,
1248
+ "gpt-5.1-codex-mini": 272_000,
1249
+ "gpt-5.3-codex": 272_000,
1250
+ # Spark runs on specialised low-latency hardware and exposes a smaller
1251
+ # 128k window than other Codex OAuth slugs. Listed explicitly so the
1252
+ # longest-key-first fallback resolves it correctly — substring match
1253
+ # on "gpt-5.3-codex" otherwise wins and reports 272k. Availability is
1254
+ # gated by ChatGPT Pro entitlement on the Codex backend.
1255
+ "gpt-5.3-codex-spark": 128_000,
1256
+ "gpt-5.2-codex": 272_000,
1257
+ "gpt-5.4-mini": 272_000,
1258
+ "gpt-5.5": 272_000,
1259
+ "gpt-5.4": 272_000,
1260
+ "gpt-5.2": 272_000,
1261
+ "gpt-5": 272_000,
1262
+ }
1263
+
1264
+
1265
+ _codex_oauth_context_cache: Dict[str, int] = {}
1266
+ _codex_oauth_context_cache_time: float = 0.0
1267
+ _CODEX_OAUTH_CONTEXT_CACHE_TTL = 3600 # 1 hour
1268
+
1269
+
1270
+ def _fetch_codex_oauth_context_lengths(access_token: str) -> Dict[str, int]:
1271
+ """Probe the ChatGPT Codex /models endpoint for per-slug context windows.
1272
+
1273
+ Codex OAuth imposes its own context limits that differ from the direct
1274
+ OpenAI API (e.g. gpt-5.5 is 1.05M on the API, 272K on Codex). The
1275
+ `context_window` field in each model entry is the authoritative source.
1276
+
1277
+ Returns a ``{slug: context_window}`` dict. Empty on failure.
1278
+ """
1279
+ global _codex_oauth_context_cache, _codex_oauth_context_cache_time
1280
+ now = time.time()
1281
+ if (
1282
+ _codex_oauth_context_cache
1283
+ and now - _codex_oauth_context_cache_time < _CODEX_OAUTH_CONTEXT_CACHE_TTL
1284
+ ):
1285
+ return _codex_oauth_context_cache
1286
+
1287
+ try:
1288
+ resp = requests.get(
1289
+ "https://chatgpt.com/backend-api/codex/models?client_version=1.0.0",
1290
+ headers={"Authorization": f"Bearer {access_token}"},
1291
+ timeout=10,
1292
+ verify=_resolve_requests_verify(),
1293
+ )
1294
+ if resp.status_code != 200:
1295
+ logger.debug(
1296
+ "Codex /models probe returned HTTP %s; falling back to hardcoded defaults",
1297
+ resp.status_code,
1298
+ )
1299
+ return {}
1300
+ data = resp.json()
1301
+ except Exception as exc:
1302
+ logger.debug("Codex /models probe failed: %s", exc)
1303
+ return {}
1304
+
1305
+ entries = data.get("models", []) if isinstance(data, dict) else []
1306
+ result: Dict[str, int] = {}
1307
+ for item in entries:
1308
+ if not isinstance(item, dict):
1309
+ continue
1310
+ slug = item.get("slug")
1311
+ ctx = item.get("context_window")
1312
+ if isinstance(slug, str) and isinstance(ctx, int) and ctx > 0:
1313
+ result[slug.strip()] = ctx
1314
+
1315
+ if result:
1316
+ _codex_oauth_context_cache = result
1317
+ _codex_oauth_context_cache_time = now
1318
+ return result
1319
+
1320
+
1321
+ def _resolve_codex_oauth_context_length(
1322
+ model: str, access_token: str = ""
1323
+ ) -> Optional[int]:
1324
+ """Resolve a Codex OAuth model's real context window.
1325
+
1326
+ Prefers a live probe of chatgpt.com/backend-api/codex/models (when we
1327
+ have a bearer token), then falls back to ``_CODEX_OAUTH_CONTEXT_FALLBACK``.
1328
+ """
1329
+ model_bare = _strip_provider_prefix(model).strip()
1330
+ if not model_bare:
1331
+ return None
1332
+
1333
+ if access_token:
1334
+ live = _fetch_codex_oauth_context_lengths(access_token)
1335
+ if model_bare in live:
1336
+ return live[model_bare]
1337
+ # Case-insensitive match in case casing drifts
1338
+ model_lower = model_bare.lower()
1339
+ for slug, ctx in live.items():
1340
+ if slug.lower() == model_lower:
1341
+ return ctx
1342
+
1343
+ # Fallback: longest-key-first substring match over hardcoded defaults.
1344
+ model_lower = model_bare.lower()
1345
+ for slug, ctx in sorted(
1346
+ _CODEX_OAUTH_CONTEXT_FALLBACK.items(), key=lambda x: len(x[0]), reverse=True
1347
+ ):
1348
+ if slug in model_lower:
1349
+ return ctx
1350
+
1351
+ return None
1352
+
1353
+
1354
+ def _resolve_nous_context_length(
1355
+ model: str,
1356
+ base_url: str = "",
1357
+ api_key: str = "",
1358
+ ) -> Tuple[Optional[int], str]:
1359
+ """Resolve Nous Portal model context length.
1360
+
1361
+ Tries the live Nous inference endpoint first (authoritative), then falls
1362
+ back to OpenRouter metadata with suffix/version matching.
1363
+
1364
+ Nous model IDs are bare after prefix-stripping (e.g. 'qwen3.6-plus',
1365
+ 'claude-opus-4-6') while OpenRouter uses prefixed IDs (e.g.
1366
+ 'qwen/qwen3.6-plus', 'anthropic/claude-opus-4.6'). Version
1367
+ normalization (dot↔dash) is applied to handle name drifts.
1368
+
1369
+ Returns ``(context_length, source)`` where ``source`` is one of:
1370
+ - ``"portal"`` — live /v1/models response (authoritative)
1371
+ - ``"openrouter"`` — OpenRouter cache fallback (non-authoritative;
1372
+ callers must NOT persist this to the on-disk cache or a single
1373
+ portal blip will freeze the wrong value in forever)
1374
+ - ``""`` — could not resolve
1375
+ """
1376
+ # Portal first — the Nous /models endpoint is authoritative for what our
1377
+ # infrastructure enforces and may differ from OR (e.g. OR reports 1M for
1378
+ # qwen3.6-plus; the portal correctly says 262144). Fall back to the OR
1379
+ # catalog only if the portal doesn't list the model.
1380
+ if base_url:
1381
+ portal_ctx = _resolve_endpoint_context_length(model, base_url, api_key=api_key)
1382
+ if portal_ctx is not None:
1383
+ return portal_ctx, "portal"
1384
+
1385
+ metadata = fetch_model_metadata()
1386
+
1387
+ def _safe_ctx(or_id: str, entry: dict) -> Optional[int]:
1388
+ ctx = entry.get("context_length")
1389
+ if ctx is None:
1390
+ return None
1391
+ if ctx <= 32768 and _model_name_suggests_kimi(or_id):
1392
+ logger.info(
1393
+ "Rejecting OpenRouter metadata context=%s for %r "
1394
+ "(Kimi-family underreport, Nous path); falling through to hardcoded defaults",
1395
+ ctx, or_id,
1396
+ )
1397
+ return None
1398
+ return ctx
1399
+
1400
+ if model in metadata:
1401
+ ctx = _safe_ctx(model, metadata[model])
1402
+ if ctx is not None:
1403
+ return ctx, "openrouter"
1404
+
1405
+ normalized = _normalize_model_version(model).lower()
1406
+
1407
+ for or_id, entry in metadata.items():
1408
+ bare = or_id.split("/", 1)[1] if "/" in or_id else or_id
1409
+ if bare.lower() == model.lower() or _normalize_model_version(bare).lower() == normalized:
1410
+ ctx = _safe_ctx(or_id, entry)
1411
+ if ctx is not None:
1412
+ return ctx, "openrouter"
1413
+
1414
+ model_lower = model.lower()
1415
+ for or_id, entry in metadata.items():
1416
+ bare = or_id.split("/", 1)[1] if "/" in or_id else or_id
1417
+ for candidate, query in [(bare.lower(), model_lower), (_normalize_model_version(bare).lower(), normalized)]:
1418
+ if candidate.startswith(query) and (
1419
+ len(candidate) == len(query) or candidate[len(query)] in "-:."
1420
+ ):
1421
+ ctx = _safe_ctx(or_id, entry)
1422
+ if ctx is not None:
1423
+ return ctx, "openrouter"
1424
+
1425
+ return None, ""
1426
+
1427
+
1428
+ def get_model_context_length(
1429
+ model: str,
1430
+ base_url: str = "",
1431
+ api_key: str = "",
1432
+ config_context_length: int | None = None,
1433
+ provider: str = "",
1434
+ custom_providers: list | None = None,
1435
+ ) -> int:
1436
+ """Get the context length for a model.
1437
+
1438
+ Resolution order:
1439
+ 0. Explicit config override (model.context_length or custom_providers per-model)
1440
+ 1. Persistent cache (previously discovered via probing). Nous URLs
1441
+ bypass the cache here so step 5b can always reconcile against
1442
+ the authoritative portal /v1/models response.
1443
+ 1b. AWS Bedrock static table (must precede custom-endpoint probe)
1444
+ 2. Active endpoint metadata (/models for explicit custom endpoints)
1445
+ 3. Local server query (for local endpoints)
1446
+ 4. Anthropic /v1/models API (API-key users only, not OAuth)
1447
+ 5. Provider-aware lookups (before generic OpenRouter cache):
1448
+ a. Copilot live /models API
1449
+ b. Nous: live /v1/models probe first (authoritative), then OR
1450
+ cache fallback with suffix/version normalisation. Only
1451
+ portal-derived values are persisted to disk.
1452
+ c. Codex OAuth /models probe
1453
+ d. GMI /models endpoint
1454
+ e. Ollama native /api/show probe (any base_url, provider-agnostic)
1455
+ f. models.dev registry lookup (with :cloud/-cloud suffix fallback)
1456
+ 6. OpenRouter live API metadata (Kimi-family 32k guard)
1457
+ 7. Hardcoded defaults (broad family patterns, longest-key-first)
1458
+ 8. Local server query (last resort)
1459
+ 9. Default fallback (256K)"""
1460
+ # 0. Explicit config override — user knows best
1461
+ if config_context_length is not None and isinstance(config_context_length, int) and config_context_length > 0:
1462
+ return config_context_length
1463
+
1464
+ # 0b. custom_providers per-model override — check before any probe.
1465
+ # This closes the gap where /model switch and display paths used to fall
1466
+ # back to 128K despite the user having a per-model context_length set.
1467
+ # See #15779.
1468
+ if custom_providers and base_url and model:
1469
+ try:
1470
+ from hermes_cli.config import get_custom_provider_context_length
1471
+ cp_ctx = get_custom_provider_context_length(
1472
+ model=model,
1473
+ base_url=base_url,
1474
+ custom_providers=custom_providers,
1475
+ )
1476
+ if cp_ctx:
1477
+ return cp_ctx
1478
+ except Exception:
1479
+ pass # fall through to probing
1480
+
1481
+ # Normalise provider-prefixed model names (e.g. "local:model-name" →
1482
+ # "model-name") so cache lookups and server queries use the bare ID that
1483
+ # local servers actually know about. Ollama "model:tag" colons are preserved.
1484
+ model = _strip_provider_prefix(model)
1485
+
1486
+ # 1. Check persistent cache (model+provider)
1487
+ # LM Studio is excluded — its loaded context length is transient (the
1488
+ # user can reload the model with a different context_length at any time
1489
+ # via /api/v1/models/load), so a stale cached value would mask reloads.
1490
+ if base_url and provider != "lmstudio":
1491
+ cached = get_cached_context_length(model, base_url)
1492
+ if cached is not None:
1493
+ # Invalidate stale Codex OAuth cache entries: pre-PR #14935 builds
1494
+ # resolved gpt-5.x to the direct-API value (e.g. 1.05M) via
1495
+ # models.dev and persisted it. Codex OAuth caps at 272K for every
1496
+ # slug, so any cached Codex entry at or above 400K is a leftover
1497
+ # from the old resolution path. Drop it and fall through to the
1498
+ # live /models probe in step 5 below.
1499
+ if provider == "openai-codex" and cached >= 400_000:
1500
+ logger.info(
1501
+ "Dropping stale Codex cache entry %s@%s -> %s (pre-fix value); "
1502
+ "re-resolving via live /models probe",
1503
+ model, base_url, f"{cached:,}",
1504
+ )
1505
+ _invalidate_cached_context_length(model, base_url)
1506
+ # Invalidate stale 32k cache entries for Kimi-family models.
1507
+ elif cached <= 32768 and _model_name_suggests_kimi(model):
1508
+ logger.info(
1509
+ "Dropping stale Kimi cache entry %s@%s -> %s (OpenRouter underreport); "
1510
+ "re-resolving via hardcoded defaults",
1511
+ model, base_url, f"{cached:,}",
1512
+ )
1513
+ _invalidate_cached_context_length(model, base_url)
1514
+ # Nous Portal: the portal /v1/models endpoint is authoritative.
1515
+ # Bypass the persistent cache so step 5b can always reconcile
1516
+ # against it — this corrects pre-fix entries seeded from the
1517
+ # OR catalog (the same OR underreport class that the Kimi/Qwen
1518
+ # DEFAULT_CONTEXT_LENGTHS overrides exist to mitigate) without
1519
+ # touching the on-disk file when the portal is unreachable.
1520
+ # The in-memory 300s endpoint metadata cache makes the per-call
1521
+ # cost amortise to ~0 within a process.
1522
+ elif _infer_provider_from_url(base_url) == "nous":
1523
+ logger.debug(
1524
+ "Bypassing persistent cache for %s@%s (Nous portal authoritative)",
1525
+ model, base_url,
1526
+ )
1527
+ # Fall through; step 5b reconciles and overwrites if portal responds.
1528
+ else:
1529
+ return cached
1530
+
1531
+ # 1b. AWS Bedrock — use static context length table.
1532
+ # Bedrock's ListFoundationModels API doesn't expose context window sizes,
1533
+ # so we maintain a curated table in bedrock_adapter.py that reflects
1534
+ # AWS-imposed limits (e.g. 200K for Claude models vs 1M on the native
1535
+ # Anthropic API). This must run BEFORE the custom-endpoint probe at
1536
+ # step 2 — bedrock-runtime.<region>.amazonaws.com is not in
1537
+ # _URL_TO_PROVIDER, so it would otherwise be treated as a custom endpoint,
1538
+ # fail the /models probe (Bedrock doesn't expose that shape), and fall
1539
+ # back to the 128K default before reaching the original step 4b branch.
1540
+ if provider == "bedrock" or (
1541
+ base_url
1542
+ and base_url_hostname(base_url).startswith("bedrock-runtime.")
1543
+ and base_url_host_matches(base_url, "amazonaws.com")
1544
+ ):
1545
+ try:
1546
+ from agent.bedrock_adapter import get_bedrock_context_length
1547
+ return get_bedrock_context_length(model)
1548
+ except ImportError:
1549
+ pass # boto3 not installed — fall through to generic resolution
1550
+
1551
+ if provider == "novita" or (base_url and base_url_host_matches(base_url, "api.novita.ai")):
1552
+ ctx = _resolve_endpoint_context_length(model, base_url or "https://api.novita.ai/openai/v1", api_key=api_key)
1553
+ if ctx is not None:
1554
+ if base_url:
1555
+ save_context_length(model, base_url, ctx)
1556
+ return ctx
1557
+
1558
+ # 2. Active endpoint metadata for truly custom/unknown endpoints.
1559
+ # Known providers (Copilot, OpenAI, Anthropic, etc.) skip this — their
1560
+ # /models endpoint may report a provider-imposed limit (e.g. Copilot
1561
+ # returns 128k) instead of the model's full context (400k). models.dev
1562
+ # has the correct per-provider values and is checked at step 5+.
1563
+ if _is_custom_endpoint(base_url) and not _is_known_provider_base_url(base_url):
1564
+ context_length = _resolve_endpoint_context_length(model, base_url, api_key=api_key)
1565
+ if context_length is not None:
1566
+ return context_length
1567
+ if not _is_known_provider_base_url(base_url):
1568
+ # 2b. Ollama native /api/show — any URL might be an Ollama server
1569
+ # (local, cloud, or custom hosting). Non-Ollama servers return
1570
+ # 404/405 quickly. Fall through on failure.
1571
+ ctx = _query_ollama_api_show(model, base_url, api_key=api_key)
1572
+ if ctx is not None:
1573
+ save_context_length(model, base_url, ctx)
1574
+ return ctx
1575
+ # 3. Try querying local server directly
1576
+ if is_local_endpoint(base_url):
1577
+ local_ctx = _query_local_context_length(model, base_url, api_key=api_key)
1578
+ if local_ctx and local_ctx > 0:
1579
+ if provider != "lmstudio":
1580
+ save_context_length(model, base_url, local_ctx)
1581
+ return local_ctx
1582
+ logger.info(
1583
+ "Could not detect context length for model %r at %s — "
1584
+ "defaulting to %s tokens (probe-down). Set model.context_length "
1585
+ "in config.yaml to override.",
1586
+ model, base_url, f"{DEFAULT_FALLBACK_CONTEXT:,}",
1587
+ )
1588
+ return DEFAULT_FALLBACK_CONTEXT
1589
+
1590
+ # 4. Anthropic /v1/models API (only for regular API keys, not OAuth)
1591
+ if provider == "anthropic" or (
1592
+ base_url and base_url_hostname(base_url) == "api.anthropic.com"
1593
+ ):
1594
+ ctx = _query_anthropic_context_length(model, base_url or "https://api.anthropic.com", api_key)
1595
+ if ctx:
1596
+ return ctx
1597
+
1598
+ # 4b. (Bedrock handled earlier at step 1b — before custom-endpoint probe.)
1599
+
1600
+ # 5. Provider-aware lookups (before generic OpenRouter cache)
1601
+ # These are provider-specific and take priority over the generic OR cache,
1602
+ # since the same model can have different context limits per provider
1603
+ # (e.g. claude-opus-4.6 is 1M on Anthropic but 128K on GitHub Copilot).
1604
+ # If provider is generic (openrouter/custom/empty), try to infer from URL.
1605
+ effective_provider = provider
1606
+ if not effective_provider or effective_provider in {"openrouter", "custom"}:
1607
+ if base_url:
1608
+ inferred = _infer_provider_from_url(base_url)
1609
+ if inferred:
1610
+ effective_provider = inferred
1611
+
1612
+ # 5a. Copilot live /models API — max_prompt_tokens from the user's account.
1613
+ # This catches account-specific models (e.g. claude-opus-4.6-1m) that
1614
+ # don't exist in models.dev. For models that ARE in models.dev, this
1615
+ # returns the provider-enforced limit which is what users can actually use.
1616
+ if effective_provider in {"copilot", "copilot-acp", "github-copilot"}:
1617
+ try:
1618
+ from hermes_cli.models import get_copilot_model_context
1619
+ ctx = get_copilot_model_context(model, api_key=api_key)
1620
+ if ctx:
1621
+ return ctx
1622
+ except Exception:
1623
+ pass # Fall through to models.dev
1624
+
1625
+ if effective_provider == "nous":
1626
+ ctx, source = _resolve_nous_context_length(
1627
+ model, base_url=base_url or "", api_key=api_key or ""
1628
+ )
1629
+ if ctx:
1630
+ # Persist ONLY portal-derived values. Caching an OR-fallback
1631
+ # value here would freeze in a wrong number on the first portal
1632
+ # blip / auth glitch and step-1 would short-circuit it forever.
1633
+ # OR's catalog is community-maintained and is precisely why the
1634
+ # Kimi/Qwen DEFAULT_CONTEXT_LENGTHS overrides exist — we don't
1635
+ # want it leaking into the persistent cache for Nous URLs.
1636
+ if base_url and source == "portal":
1637
+ save_context_length(model, base_url, ctx)
1638
+ return ctx
1639
+ if effective_provider == "openai-codex":
1640
+ # Codex OAuth enforces lower context limits than the direct OpenAI
1641
+ # API for the same slug (e.g. gpt-5.5 is 1.05M on the API but 272K
1642
+ # on Codex). Authoritative source is Codex's own /models endpoint.
1643
+ codex_ctx = _resolve_codex_oauth_context_length(model, access_token=api_key or "")
1644
+ if codex_ctx:
1645
+ if base_url:
1646
+ save_context_length(model, base_url, codex_ctx)
1647
+ return codex_ctx
1648
+ if effective_provider == "gmi" and base_url:
1649
+ # GMI exposes authoritative context_length via /models, but it is not
1650
+ # in models.dev yet. Preserve that higher-fidelity endpoint lookup.
1651
+ ctx = _resolve_endpoint_context_length(model, base_url, api_key=api_key)
1652
+ if ctx is not None:
1653
+ return ctx
1654
+ # 5e. Ollama native /api/show probe — runs for ANY provider with a
1655
+ # base_url, not just ollama-cloud. Ollama-compatible servers expose
1656
+ # this endpoint regardless of hostname (local Ollama, Ollama Cloud,
1657
+ # custom Ollama hosting). The OpenAI-compat /v1/models endpoint
1658
+ # correctly omits context_length per the OpenAI schema, but /api/show
1659
+ # returns the authoritative GGUF model_info.context_length.
1660
+ # For non-Ollama servers (OpenAI, Anthropic, etc.), the POST returns
1661
+ # 404/405 quickly. Results are cached, so the hit is per-model+URL,
1662
+ # once per hour.
1663
+ if base_url:
1664
+ ctx = _query_ollama_api_show(model, base_url, api_key=api_key)
1665
+ if ctx is not None:
1666
+ save_context_length(model, base_url, ctx)
1667
+ return ctx
1668
+ if effective_provider:
1669
+ from agent.models_dev import lookup_models_dev_context
1670
+ ctx = lookup_models_dev_context(effective_provider, model)
1671
+ if ctx:
1672
+ return ctx
1673
+
1674
+ # 6. OpenRouter live API metadata — provider-unaware fallback.
1675
+ # Only consulted when the provider is unknown (no effective_provider),
1676
+ # because OpenRouter data is community-maintained and can be incorrect
1677
+ # for models that belong to known providers with curated defaults.
1678
+ if not effective_provider:
1679
+ metadata = fetch_model_metadata()
1680
+ if model in metadata:
1681
+ or_ctx = metadata[model].get("context_length", DEFAULT_FALLBACK_CONTEXT)
1682
+ # Guard against stale OpenRouter metadata for Kimi-family models.
1683
+ if or_ctx == 32768 and _model_name_suggests_kimi(model):
1684
+ logger.info(
1685
+ "Rejecting OpenRouter metadata context=%s for %r "
1686
+ "(Kimi-family underreport); falling through to hardcoded defaults",
1687
+ or_ctx, model,
1688
+ )
1689
+ else:
1690
+ return or_ctx
1691
+
1692
+ # 7. (reserved)
1693
+
1694
+ # 8. Hardcoded defaults (fuzzy match — longest key first for specificity)
1695
+ # Only check `default_model in model` (is the key a substring of the input).
1696
+ # The reverse (`model in default_model`) causes shorter names like
1697
+ # "claude-sonnet-4" to incorrectly match "claude-sonnet-4-6" and return 1M.
1698
+ model_lower = model.lower()
1699
+ for default_model, length in sorted(
1700
+ DEFAULT_CONTEXT_LENGTHS.items(), key=lambda x: len(x[0]), reverse=True
1701
+ ):
1702
+ if default_model in model_lower:
1703
+ return length
1704
+
1705
+ # 9. Query local server as last resort
1706
+ if base_url and is_local_endpoint(base_url):
1707
+ local_ctx = _query_local_context_length(model, base_url, api_key=api_key)
1708
+ if local_ctx and local_ctx > 0:
1709
+ if provider != "lmstudio":
1710
+ save_context_length(model, base_url, local_ctx)
1711
+ return local_ctx
1712
+
1713
+ # 10. Default fallback — 256K
1714
+ return DEFAULT_FALLBACK_CONTEXT
1715
+
1716
+
1717
+ def estimate_tokens_rough(text: str) -> int:
1718
+ """Rough token estimate (~4 chars/token) for pre-flight checks.
1719
+
1720
+ Uses ceiling division so short texts (1-3 chars) never estimate as
1721
+ 0 tokens, which would cause the compressor and pre-flight checks to
1722
+ systematically undercount when many short tool results are present.
1723
+ """
1724
+ if not text:
1725
+ return 0
1726
+ return (len(text) + 3) // 4
1727
+
1728
+
1729
+ def estimate_messages_tokens_rough(messages: List[Dict[str, Any]]) -> int:
1730
+ """Rough token estimate for a message list (pre-flight only).
1731
+
1732
+ Image parts (base64 PNG/JPEG) are counted as a flat ~1500 tokens per
1733
+ image — the Anthropic pricing model — instead of counting raw base64
1734
+ character length. Without this, a single ~1MB screenshot would be
1735
+ estimated at ~250K tokens and trigger premature context compression.
1736
+ """
1737
+ _IMAGE_TOKEN_COST = 1500
1738
+ total_chars = 0
1739
+ image_tokens = 0
1740
+ for msg in messages:
1741
+ total_chars += _estimate_message_chars(msg)
1742
+ image_tokens += _count_image_tokens(msg, _IMAGE_TOKEN_COST)
1743
+ return ((total_chars + 3) // 4) + image_tokens
1744
+
1745
+
1746
+ def _count_image_tokens(msg: Dict[str, Any], cost_per_image: int) -> int:
1747
+ """Count image-like content parts in a message; return their token cost."""
1748
+ count = 0
1749
+ content = msg.get("content") if isinstance(msg, dict) else None
1750
+ if isinstance(content, list):
1751
+ for part in content:
1752
+ if not isinstance(part, dict):
1753
+ continue
1754
+ ptype = part.get("type")
1755
+ if ptype in {"image", "image_url", "input_image"}:
1756
+ count += 1
1757
+ stashed = msg.get("_anthropic_content_blocks") if isinstance(msg, dict) else None
1758
+ if isinstance(stashed, list):
1759
+ for part in stashed:
1760
+ if isinstance(part, dict) and part.get("type") == "image":
1761
+ count += 1
1762
+ # Multimodal tool results that haven't been converted yet.
1763
+ if isinstance(content, dict) and content.get("_multimodal"):
1764
+ inner = content.get("content")
1765
+ if isinstance(inner, list):
1766
+ for part in inner:
1767
+ if isinstance(part, dict) and part.get("type") in {"image", "image_url"}:
1768
+ count += 1
1769
+ return count * cost_per_image
1770
+
1771
+
1772
+ def _estimate_message_chars(msg: Dict[str, Any]) -> int:
1773
+ """Char count for token estimation, excluding base64 image data.
1774
+
1775
+ Base64 images are counted via `_count_image_tokens` instead; including
1776
+ their raw chars here would massively overestimate token usage.
1777
+ """
1778
+ if not isinstance(msg, dict):
1779
+ return len(str(msg))
1780
+ shadow: Dict[str, Any] = {}
1781
+ for k, v in msg.items():
1782
+ if k == "_anthropic_content_blocks":
1783
+ continue
1784
+ if k == "content":
1785
+ if isinstance(v, list):
1786
+ cleaned = []
1787
+ for part in v:
1788
+ if isinstance(part, dict):
1789
+ if part.get("type") in {"image", "image_url", "input_image"}:
1790
+ cleaned.append({"type": part.get("type"), "image": "[stripped]"})
1791
+ else:
1792
+ cleaned.append(part)
1793
+ else:
1794
+ cleaned.append(part)
1795
+ shadow[k] = cleaned
1796
+ elif isinstance(v, dict) and v.get("_multimodal"):
1797
+ shadow[k] = v.get("text_summary", "")
1798
+ else:
1799
+ shadow[k] = v
1800
+ else:
1801
+ shadow[k] = v
1802
+ return len(str(shadow))
1803
+
1804
+
1805
+ def estimate_request_tokens_rough(
1806
+ messages: List[Dict[str, Any]],
1807
+ *,
1808
+ system_prompt: str = "",
1809
+ tools: Optional[List[Dict[str, Any]]] = None,
1810
+ ) -> int:
1811
+ """Rough token estimate for a full chat-completions request.
1812
+
1813
+ Includes the major payload buckets Hermes sends to providers:
1814
+ system prompt, conversation messages, and tool schemas. With 50+
1815
+ tools enabled, schemas alone can add 20-30K tokens — a significant
1816
+ blind spot when only counting messages. Image content is counted
1817
+ at a flat per-image cost (see estimate_messages_tokens_rough).
1818
+ """
1819
+ total = 0
1820
+ if system_prompt:
1821
+ total += (len(system_prompt) + 3) // 4
1822
+ if messages:
1823
+ total += estimate_messages_tokens_rough(messages)
1824
+ if tools:
1825
+ total += (len(str(tools)) + 3) // 4
1826
+ return total
1827
+