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,1758 @@
1
+ """Hindsight memory plugin — MemoryProvider interface.
2
+
3
+ Long-term memory with knowledge graph, entity resolution, and multi-strategy
4
+ retrieval. Supports cloud (API key) and local modes.
5
+
6
+ Configurable request timeout via HINDSIGHT_TIMEOUT env var or config.json.
7
+ Configurable embedded daemon idle timeout via HINDSIGHT_IDLE_TIMEOUT env var
8
+ or config.json idle_timeout.
9
+
10
+ Original PR #1811 by benfrank241, adapted to MemoryProvider ABC.
11
+
12
+ Config via environment variables:
13
+ HINDSIGHT_API_KEY — API key for Hindsight Cloud
14
+ HINDSIGHT_BANK_ID — memory bank identifier (default: hermes)
15
+ HINDSIGHT_BUDGET — recall budget: low/mid/high (default: mid)
16
+ HINDSIGHT_API_URL — API endpoint
17
+ HINDSIGHT_MODE — cloud or local (default: cloud)
18
+ HINDSIGHT_TIMEOUT — API request timeout in seconds (default: 120)
19
+ HINDSIGHT_IDLE_TIMEOUT — embedded daemon idle timeout seconds; 0 disables shutdown (default: 300)
20
+ HINDSIGHT_RETAIN_TAGS — comma-separated tags attached to retained memories
21
+ HINDSIGHT_RETAIN_SOURCE — metadata source value attached to retained memories
22
+ HINDSIGHT_RETAIN_USER_PREFIX — label used before user turns in retained transcripts
23
+ HINDSIGHT_RETAIN_ASSISTANT_PREFIX — label used before assistant turns in retained transcripts
24
+
25
+ Or via $HERMES_HOME/hindsight/config.json (profile-scoped), falling back to
26
+ ~/.hindsight/config.json (legacy, shared) for backward compatibility.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import asyncio
32
+ import atexit
33
+ import importlib
34
+ import json
35
+ import logging
36
+ import os
37
+ import queue
38
+ import threading
39
+
40
+ from datetime import datetime, timezone
41
+ from typing import Any, Dict, List
42
+
43
+ from agent.memory_provider import MemoryProvider
44
+ from calvyn_constants import get_hermes_home
45
+ from tools.registry import tool_error
46
+ from hermes_cli.config import cfg_get
47
+
48
+ logger = logging.getLogger(__name__)
49
+
50
+ _DEFAULT_API_URL = "https://api.hindsight.vectorize.io"
51
+ _DEFAULT_LOCAL_URL = "http://localhost:8888"
52
+ _MIN_CLIENT_VERSION = "0.4.22"
53
+ _DEFAULT_TIMEOUT = 120 # seconds — cloud API can take 30-40s per request
54
+ _DEFAULT_IDLE_TIMEOUT = 300 # seconds — Hindsight embedded daemon default
55
+ # Mirrors hindsight-integrations/openclaw — Hindsight 0.5.0 added
56
+ # `update_mode='append'` semantics on retain (vectorize-io/hindsight#932).
57
+ # Without it, reusing a stable session-scoped document_id silently
58
+ # overwrites prior turns server-side, so we keep the per-process
59
+ # unique document_id fallback for older APIs.
60
+ _MIN_VERSION_FOR_UPDATE_MODE_APPEND = "0.5.0"
61
+ _VALID_BUDGETS = {"low", "mid", "high"}
62
+ _PROVIDER_DEFAULT_MODELS = {
63
+ "openai": "gpt-4o-mini",
64
+ "anthropic": "claude-haiku-4-5",
65
+ "gemini": "gemini-2.5-flash",
66
+ "groq": "openai/gpt-oss-120b",
67
+ "openrouter": "qwen/qwen3.5-9b",
68
+ "minimax": "MiniMax-M2.7",
69
+ "ollama": "gemma3:12b",
70
+ "lmstudio": "local-model",
71
+ "openai_compatible": "your-model-name",
72
+ }
73
+
74
+
75
+ def _parse_int_setting(value: Any, default: int) -> int:
76
+ """Parse an integer config/env value, falling back on invalid input."""
77
+ if value is None or value == "":
78
+ return default
79
+ try:
80
+ return int(value)
81
+ except (TypeError, ValueError):
82
+ logger.warning("Invalid integer Hindsight setting %r; using default %s", value, default)
83
+ return default
84
+
85
+
86
+ def _check_local_runtime() -> tuple[bool, str | None]:
87
+ """Return whether local embedded Hindsight imports cleanly.
88
+
89
+ On older CPUs, importing the local Hindsight stack can raise a runtime
90
+ error from NumPy before the daemon starts. Treat that as "unavailable"
91
+ so Hermes can degrade gracefully instead of repeatedly trying to start
92
+ a broken local memory backend.
93
+ """
94
+ try:
95
+ importlib.import_module("hindsight")
96
+ importlib.import_module("hindsight_embed.daemon_embed_manager")
97
+ return True, None
98
+ except Exception as exc:
99
+ return False, str(exc)
100
+
101
+
102
+ # ---------------------------------------------------------------------------
103
+ # Hindsight API capability probe — mirrors hindsight-integrations/openclaw.
104
+ # ---------------------------------------------------------------------------
105
+
106
+ # Cache of API_URL -> bool (whether that API supports update_mode='append').
107
+ # Probed once per URL per process — every provider talking to the same API
108
+ # gets the same answer without re-hitting /version on each initialize().
109
+ _append_capability_cache: Dict[str, bool] = {}
110
+ _append_capability_lock = threading.Lock()
111
+
112
+
113
+ def _meets_minimum_version(actual: str | None, required: str) -> bool:
114
+ """Return True if *actual* ≥ *required* (semver). False on missing/invalid."""
115
+ if not actual:
116
+ return False
117
+ try:
118
+ from packaging.version import Version
119
+ return Version(actual) >= Version(required)
120
+ except Exception:
121
+ return False
122
+
123
+
124
+ def _fetch_hindsight_api_version(api_url: str, api_key: str | None = None,
125
+ timeout: float = 5.0) -> str | None:
126
+ """GET ``<api_url>/version`` and return the version string (or None on failure).
127
+
128
+ Hindsight's `/version` endpoint returns ``{"version": "0.5.6", ...}``.
129
+ Any failure (timeout, 404, malformed JSON, missing key) → None, which
130
+ the caller treats as "legacy API, no update_mode support".
131
+ """
132
+ import urllib.error
133
+ import urllib.request
134
+ if not api_url:
135
+ return None
136
+ url = api_url.rstrip("/") + "/version"
137
+ req = urllib.request.Request(url)
138
+ if api_key:
139
+ req.add_header("Authorization", f"Bearer {api_key}")
140
+ try:
141
+ with urllib.request.urlopen(req, timeout=timeout) as resp: # noqa: S310
142
+ payload = resp.read().decode("utf-8", errors="replace")
143
+ data = json.loads(payload)
144
+ except Exception as exc:
145
+ logger.debug("Hindsight /version probe failed for %s: %s", url, exc)
146
+ return None
147
+ if not isinstance(data, dict):
148
+ return None
149
+ version = data.get("version") or data.get("api_version")
150
+ return str(version) if version else None
151
+
152
+
153
+ def _check_api_supports_update_mode_append(api_url: str,
154
+ api_key: str | None = None) -> bool:
155
+ """Cached capability check for ``update_mode='append'`` on *api_url*.
156
+
157
+ Probes once per URL per process. Returns False on any probe failure —
158
+ that's the safe default: a per-process unique ``document_id`` and no
159
+ ``update_mode`` keeps the resume-overwrite fix (#6654) intact.
160
+ """
161
+ if not api_url:
162
+ return False
163
+ with _append_capability_lock:
164
+ if api_url in _append_capability_cache:
165
+ return _append_capability_cache[api_url]
166
+ version = _fetch_hindsight_api_version(api_url, api_key)
167
+ supported = _meets_minimum_version(version, _MIN_VERSION_FOR_UPDATE_MODE_APPEND)
168
+ with _append_capability_lock:
169
+ # Re-check after acquiring the lock in case a concurrent probe filled it.
170
+ cached = _append_capability_cache.get(api_url)
171
+ if cached is None:
172
+ _append_capability_cache[api_url] = supported
173
+ else:
174
+ supported = cached
175
+ if not supported:
176
+ logger.warning(
177
+ "Hindsight API at %s reports version %r, older than %s. "
178
+ "Falling back to per-process document_id — retains across "
179
+ "processes/sessions create separate documents instead of "
180
+ "appending to a session-scoped one. Upgrade Hindsight to "
181
+ "%s+ to enable update_mode='append' deduplication.",
182
+ api_url, version, _MIN_VERSION_FOR_UPDATE_MODE_APPEND,
183
+ _MIN_VERSION_FOR_UPDATE_MODE_APPEND,
184
+ )
185
+ else:
186
+ logger.debug("Hindsight API %s version %s supports update_mode='append'",
187
+ api_url, version)
188
+ return supported
189
+
190
+
191
+ # ---------------------------------------------------------------------------
192
+ # Dedicated event loop for Hindsight async calls (one per process, reused).
193
+ # Avoids creating ephemeral loops that leak aiohttp sessions.
194
+ # ---------------------------------------------------------------------------
195
+
196
+ _loop: asyncio.AbstractEventLoop | None = None
197
+ _loop_thread: threading.Thread | None = None
198
+ _loop_lock = threading.Lock()
199
+
200
+ # Sentinel pushed to the per-provider retain queue to wake the writer for a
201
+ # clean exit. A unique object so it can never collide with a real job.
202
+ _WRITER_SENTINEL = object()
203
+
204
+
205
+ def _get_loop() -> asyncio.AbstractEventLoop:
206
+ """Return a long-lived event loop running on a background thread."""
207
+ global _loop, _loop_thread
208
+ with _loop_lock:
209
+ if _loop is not None and _loop.is_running():
210
+ return _loop
211
+ _loop = asyncio.new_event_loop()
212
+
213
+ def _run():
214
+ asyncio.set_event_loop(_loop)
215
+ _loop.run_forever()
216
+
217
+ _loop_thread = threading.Thread(target=_run, daemon=True, name="hindsight-loop")
218
+ _loop_thread.start()
219
+ return _loop
220
+
221
+
222
+ def _run_sync(coro, timeout: float = _DEFAULT_TIMEOUT):
223
+ """Schedule *coro* on the shared loop and block until done."""
224
+ from agent.async_utils import safe_schedule_threadsafe
225
+ loop = _get_loop()
226
+ future = safe_schedule_threadsafe(coro, loop)
227
+ if future is None:
228
+ raise RuntimeError("Hindsight loop unavailable")
229
+ return future.result(timeout=timeout)
230
+
231
+
232
+ # ---------------------------------------------------------------------------
233
+ # Backward-compatible alias — instances use self._run_sync() instead.
234
+ # ---------------------------------------------------------------------------
235
+
236
+
237
+ # ---------------------------------------------------------------------------
238
+ # Tool schemas
239
+ # ---------------------------------------------------------------------------
240
+
241
+ RETAIN_SCHEMA = {
242
+ "name": "hindsight_retain",
243
+ "description": (
244
+ "Store information to long-term memory. Hindsight automatically "
245
+ "extracts structured facts, resolves entities, and indexes for retrieval."
246
+ ),
247
+ "parameters": {
248
+ "type": "object",
249
+ "properties": {
250
+ "content": {"type": "string", "description": "The information to store."},
251
+ "context": {"type": "string", "description": "Short label (e.g. 'user preference', 'project decision')."},
252
+ "tags": {
253
+ "type": "array",
254
+ "items": {"type": "string"},
255
+ "description": "Optional per-call tags to merge with configured default retain tags.",
256
+ },
257
+ },
258
+ "required": ["content"],
259
+ },
260
+ }
261
+
262
+ RECALL_SCHEMA = {
263
+ "name": "hindsight_recall",
264
+ "description": (
265
+ "Search long-term memory. Returns memories ranked by relevance using "
266
+ "semantic search, keyword matching, entity graph traversal, and reranking."
267
+ ),
268
+ "parameters": {
269
+ "type": "object",
270
+ "properties": {
271
+ "query": {"type": "string", "description": "What to search for."},
272
+ },
273
+ "required": ["query"],
274
+ },
275
+ }
276
+
277
+ REFLECT_SCHEMA = {
278
+ "name": "hindsight_reflect",
279
+ "description": (
280
+ "Synthesize a reasoned answer from long-term memories. Unlike recall, "
281
+ "this reasons across all stored memories to produce a coherent response."
282
+ ),
283
+ "parameters": {
284
+ "type": "object",
285
+ "properties": {
286
+ "query": {"type": "string", "description": "The question to reflect on."},
287
+ },
288
+ "required": ["query"],
289
+ },
290
+ }
291
+
292
+
293
+ # ---------------------------------------------------------------------------
294
+ # Config
295
+ # ---------------------------------------------------------------------------
296
+
297
+ def _load_config() -> dict:
298
+ """Load config from profile-scoped path, legacy path, or env vars.
299
+
300
+ Resolution order:
301
+ 1. $HERMES_HOME/hindsight/config.json (profile-scoped)
302
+ 2. ~/.hindsight/config.json (legacy, shared)
303
+ 3. Environment variables
304
+ """
305
+ from pathlib import Path
306
+
307
+ # Profile-scoped path (preferred)
308
+ profile_path = get_hermes_home() / "hindsight" / "config.json"
309
+ if profile_path.exists():
310
+ try:
311
+ return json.loads(profile_path.read_text(encoding="utf-8"))
312
+ except Exception:
313
+ pass
314
+
315
+ # Legacy shared path (backward compat)
316
+ legacy_path = Path.home() / ".hindsight" / "config.json"
317
+ if legacy_path.exists():
318
+ try:
319
+ return json.loads(legacy_path.read_text(encoding="utf-8"))
320
+ except Exception:
321
+ pass
322
+
323
+ return {
324
+ "mode": os.environ.get("HINDSIGHT_MODE", "cloud"),
325
+ "apiKey": os.environ.get("HINDSIGHT_API_KEY", ""),
326
+ "timeout": _parse_int_setting(os.environ.get("HINDSIGHT_TIMEOUT"), _DEFAULT_TIMEOUT),
327
+ "idle_timeout": _parse_int_setting(os.environ.get("HINDSIGHT_IDLE_TIMEOUT"), _DEFAULT_IDLE_TIMEOUT),
328
+ "retain_tags": os.environ.get("HINDSIGHT_RETAIN_TAGS", ""),
329
+ "retain_source": os.environ.get("HINDSIGHT_RETAIN_SOURCE", ""),
330
+ "retain_user_prefix": os.environ.get("HINDSIGHT_RETAIN_USER_PREFIX", "User"),
331
+ "retain_assistant_prefix": os.environ.get("HINDSIGHT_RETAIN_ASSISTANT_PREFIX", "Assistant"),
332
+ "banks": {
333
+ "hermes": {
334
+ "bankId": os.environ.get("HINDSIGHT_BANK_ID", "hermes"),
335
+ "budget": os.environ.get("HINDSIGHT_BUDGET", "mid"),
336
+ "enabled": True,
337
+ }
338
+ },
339
+ }
340
+
341
+
342
+ def _normalize_retain_tags(value: Any) -> List[str]:
343
+ """Normalize tag config/tool values to a deduplicated list of strings."""
344
+ if value is None:
345
+ return []
346
+
347
+ raw_items: list[Any]
348
+ if isinstance(value, list):
349
+ raw_items = value
350
+ elif isinstance(value, str):
351
+ text = value.strip()
352
+ if not text:
353
+ return []
354
+ if text.startswith("["):
355
+ try:
356
+ parsed = json.loads(text)
357
+ except Exception:
358
+ parsed = None
359
+ if isinstance(parsed, list):
360
+ raw_items = parsed
361
+ else:
362
+ raw_items = text.split(",")
363
+ else:
364
+ raw_items = text.split(",")
365
+ else:
366
+ raw_items = [value]
367
+
368
+ normalized = []
369
+ seen = set()
370
+ for item in raw_items:
371
+ tag = str(item).strip()
372
+ if not tag or tag in seen:
373
+ continue
374
+ seen.add(tag)
375
+ normalized.append(tag)
376
+ return normalized
377
+
378
+
379
+ def _utc_timestamp() -> str:
380
+ """Return current UTC timestamp in ISO-8601 with milliseconds and Z suffix."""
381
+ return datetime.now(timezone.utc).isoformat(timespec="milliseconds").replace("+00:00", "Z")
382
+
383
+
384
+ def _embedded_profile_name(config: dict[str, Any]) -> str:
385
+ """Return the Hindsight embedded profile name for this Hermes config."""
386
+ profile = config.get("profile", "hermes")
387
+ return str(profile or "hermes")
388
+
389
+
390
+ def _load_simple_env(path) -> dict[str, str]:
391
+ """Parse a simple KEY=VALUE env file, ignoring comments and blank lines."""
392
+ if not path.exists():
393
+ return {}
394
+
395
+ values: dict[str, str] = {}
396
+ for line in path.read_text(encoding="utf-8").splitlines():
397
+ if not line or line.startswith("#") or "=" not in line:
398
+ continue
399
+ key, value = line.split("=", 1)
400
+ values[key.strip()] = value.strip()
401
+ return values
402
+
403
+
404
+ def _build_embedded_profile_env(config: dict[str, Any], *, llm_api_key: str | None = None) -> dict[str, str]:
405
+ """Build the profile-scoped env file that standalone hindsight-embed consumes."""
406
+ current_key = llm_api_key
407
+ if current_key is None:
408
+ current_key = (
409
+ config.get("llmApiKey")
410
+ or config.get("llm_api_key")
411
+ or os.environ.get("HINDSIGHT_LLM_API_KEY", "")
412
+ )
413
+
414
+ current_provider = config.get("llm_provider", "")
415
+ current_model = config.get("llm_model", "")
416
+ current_base_url = config.get("llm_base_url") or os.environ.get("HINDSIGHT_API_LLM_BASE_URL", "")
417
+
418
+ # The embedded daemon expects OpenAI wire format for these providers.
419
+ daemon_provider = "openai" if current_provider in ("openai_compatible", "openrouter") else current_provider
420
+
421
+ env_values = {
422
+ "HINDSIGHT_API_LLM_PROVIDER": str(daemon_provider),
423
+ "HINDSIGHT_API_LLM_API_KEY": str(current_key or ""),
424
+ "HINDSIGHT_API_LLM_MODEL": str(current_model),
425
+ "HINDSIGHT_API_LOG_LEVEL": "info",
426
+ }
427
+ if current_base_url:
428
+ env_values["HINDSIGHT_API_LLM_BASE_URL"] = str(current_base_url)
429
+
430
+ idle_timeout = (
431
+ config.get("idle_timeout")
432
+ if config.get("idle_timeout") is not None
433
+ else os.environ.get("HINDSIGHT_IDLE_TIMEOUT")
434
+ )
435
+ if idle_timeout is not None and idle_timeout != "":
436
+ env_values["HINDSIGHT_EMBED_DAEMON_IDLE_TIMEOUT"] = str(
437
+ _parse_int_setting(idle_timeout, _DEFAULT_IDLE_TIMEOUT)
438
+ )
439
+ return env_values
440
+
441
+
442
+ def _embedded_profile_env_path(config: dict[str, Any]):
443
+ from pathlib import Path
444
+
445
+ return Path.home() / ".hindsight" / "profiles" / f"{_embedded_profile_name(config)}.env"
446
+
447
+
448
+ def _materialize_embedded_profile_env(config: dict[str, Any], *, llm_api_key: str | None = None):
449
+ """Write the profile-scoped env file that standalone hindsight-embed uses."""
450
+ profile_env = _embedded_profile_env_path(config)
451
+ profile_env.parent.mkdir(parents=True, exist_ok=True)
452
+ env_values = _build_embedded_profile_env(config, llm_api_key=llm_api_key)
453
+ profile_env.write_text(
454
+ "".join(f"{key}={value}\n" for key, value in env_values.items()),
455
+ encoding="utf-8",
456
+ )
457
+ return profile_env
458
+
459
+ def _sanitize_bank_segment(value: str) -> str:
460
+ """Sanitize a bank_id_template placeholder value.
461
+
462
+ Bank IDs should be safe for URL paths and filesystem use. Replaces any
463
+ character that isn't alphanumeric, dash, or underscore with a dash, and
464
+ collapses runs of dashes.
465
+ """
466
+ if not value:
467
+ return ""
468
+ out = []
469
+ prev_dash = False
470
+ for ch in str(value):
471
+ if ch.isalnum() or ch == "-" or ch == "_":
472
+ out.append(ch)
473
+ prev_dash = False
474
+ else:
475
+ if not prev_dash:
476
+ out.append("-")
477
+ prev_dash = True
478
+ return "".join(out).strip("-_")
479
+
480
+
481
+ def _resolve_bank_id_template(template: str, fallback: str, **placeholders: str) -> str:
482
+ """Resolve a bank_id template string with the given placeholders.
483
+
484
+ Supported placeholders (each is sanitized before substitution):
485
+ {profile} — active Hermes profile name (from agent_identity)
486
+ {workspace} — Hermes workspace name (from agent_workspace)
487
+ {platform} — "cli", "telegram", "discord", etc.
488
+ {user} — platform user id (gateway sessions)
489
+ {session} — current session id
490
+
491
+ Missing/empty placeholders are rendered as the empty string and then
492
+ collapsed — e.g. ``hermes-{user}`` with no user becomes ``hermes``.
493
+
494
+ If the template is empty, resolution falls back to *fallback*.
495
+ Returns the sanitized bank id.
496
+ """
497
+ if not template:
498
+ return fallback
499
+ sanitized = {k: _sanitize_bank_segment(v) for k, v in placeholders.items()}
500
+ try:
501
+ rendered = template.format(**sanitized)
502
+ except (KeyError, IndexError) as exc:
503
+ logger.warning("Invalid bank_id_template %r: %s — using fallback %r",
504
+ template, exc, fallback)
505
+ return fallback
506
+ while "--" in rendered:
507
+ rendered = rendered.replace("--", "-")
508
+ while "__" in rendered:
509
+ rendered = rendered.replace("__", "_")
510
+ rendered = rendered.strip("-_")
511
+ return rendered or fallback
512
+
513
+
514
+ # ---------------------------------------------------------------------------
515
+ # MemoryProvider implementation
516
+ # ---------------------------------------------------------------------------
517
+
518
+ class HindsightMemoryProvider(MemoryProvider):
519
+ """Hindsight long-term memory with knowledge graph and multi-strategy retrieval."""
520
+
521
+ def __init__(self):
522
+ self._config = None
523
+ self._api_key = None
524
+ self._api_url = _DEFAULT_API_URL
525
+ self._bank_id = "hermes"
526
+ self._budget = "mid"
527
+ self._mode = "cloud"
528
+ self._llm_base_url = ""
529
+ self._memory_mode = "hybrid" # "context", "tools", or "hybrid"
530
+ self._prefetch_method = "recall" # "recall" or "reflect"
531
+ self._retain_tags: List[str] = []
532
+ self._retain_source = ""
533
+ self._retain_user_prefix = "User"
534
+ self._retain_assistant_prefix = "Assistant"
535
+ self._platform = ""
536
+ self._user_id = ""
537
+ self._user_name = ""
538
+ self._chat_id = ""
539
+ self._chat_name = ""
540
+ self._chat_type = ""
541
+ self._thread_id = ""
542
+ self._agent_identity = ""
543
+ self._agent_workspace = ""
544
+ self._turn_index = 0
545
+ self._client = None
546
+ self._timeout = _DEFAULT_TIMEOUT
547
+ self._idle_timeout = _DEFAULT_IDLE_TIMEOUT
548
+ self._prefetch_result = ""
549
+ self._prefetch_lock = threading.Lock()
550
+ self._prefetch_thread = None
551
+ # Single-writer model for retain. sync_turn() enqueues; the writer
552
+ # thread drains sequentially. Avoids spawning ad-hoc threads that
553
+ # can race the interpreter shutdown and emit "cannot schedule new
554
+ # futures after interpreter shutdown" / "Unclosed client session".
555
+ self._retain_queue: queue.Queue = queue.Queue()
556
+ self._writer_thread: threading.Thread | None = None
557
+ self._shutting_down = threading.Event()
558
+ self._atexit_registered = False
559
+ # Legacy alias — older tests/callers reference _sync_thread directly.
560
+ # Points at _writer_thread once the writer is running.
561
+ self._sync_thread = None
562
+ self._session_id = ""
563
+ self._parent_session_id = ""
564
+ self._document_id = ""
565
+
566
+ # Tags
567
+ self._tags: list[str] | None = None
568
+ self._recall_tags: list[str] | None = None
569
+ self._recall_tags_match = "any"
570
+
571
+ # Retain controls
572
+ self._auto_retain = True
573
+ self._retain_every_n_turns = 1
574
+ self._retain_async = True
575
+ self._retain_context = "conversation between Hermes Agent and the User"
576
+ self._turn_counter = 0
577
+ self._session_turns: list[str] = [] # accumulates ALL turns for the session
578
+
579
+ # Recall controls
580
+ self._auto_recall = True
581
+ self._recall_max_tokens = 4096
582
+ self._recall_types: list[str] | None = None
583
+ self._recall_prompt_preamble = ""
584
+ self._recall_max_input_chars = 800
585
+
586
+ # Bank
587
+ self._bank_mission = ""
588
+ self._bank_retain_mission: str | None = None
589
+ self._bank_id_template = ""
590
+
591
+ @property
592
+ def name(self) -> str:
593
+ return "hindsight"
594
+
595
+ def is_available(self) -> bool:
596
+ try:
597
+ cfg = _load_config()
598
+ mode = cfg.get("mode", "cloud")
599
+ if mode in ("local", "local_embedded"):
600
+ available, _ = _check_local_runtime()
601
+ return available
602
+ if mode == "local_external":
603
+ return True
604
+ has_key = bool(
605
+ cfg.get("apiKey")
606
+ or cfg.get("api_key")
607
+ or os.environ.get("HINDSIGHT_API_KEY", "")
608
+ )
609
+ has_url = bool(cfg.get("api_url") or os.environ.get("HINDSIGHT_API_URL", ""))
610
+ return has_key or has_url
611
+ except Exception:
612
+ return False
613
+
614
+ def save_config(self, values, hermes_home):
615
+ """Write config to $HERMES_HOME/hindsight/config.json."""
616
+ import json
617
+ from pathlib import Path
618
+ config_dir = Path(hermes_home) / "hindsight"
619
+ config_dir.mkdir(parents=True, exist_ok=True)
620
+ config_path = config_dir / "config.json"
621
+ existing = {}
622
+ if config_path.exists():
623
+ try:
624
+ existing = json.loads(config_path.read_text())
625
+ except Exception:
626
+ pass
627
+ existing.update(values)
628
+ config_path.write_text(json.dumps(existing, indent=2))
629
+
630
+ def post_setup(self, hermes_home: str, config: dict) -> None:
631
+ """Custom setup wizard — installs only the deps needed for the selected mode."""
632
+ import getpass
633
+ import subprocess
634
+ import shutil
635
+ import sys
636
+ from pathlib import Path
637
+
638
+ from hermes_cli.config import save_config
639
+
640
+ from hermes_cli.memory_setup import _curses_select
641
+
642
+ print("\n Configuring Hindsight memory:\n")
643
+
644
+ existing_config = self._config if isinstance(self._config, dict) else _load_config()
645
+ if not isinstance(existing_config, dict):
646
+ existing_config = {}
647
+
648
+ # Step 1: Mode selection
649
+ mode_values = ["cloud", "local_embedded", "local_external"]
650
+ mode_items = [
651
+ ("Cloud", "Hindsight Cloud API (lightweight, just needs an API key)"),
652
+ ("Local Embedded", "Run Hindsight locally (downloads ~200MB, needs LLM key)"),
653
+ ("Local External", "Connect to an existing Hindsight instance"),
654
+ ]
655
+ existing_mode = existing_config.get("mode")
656
+ mode_default_idx = mode_values.index(existing_mode) if existing_mode in mode_values else 0
657
+ mode_idx = _curses_select(" Select mode", mode_items, default=mode_default_idx)
658
+ mode = mode_values[mode_idx]
659
+
660
+ provider_config: dict = dict(existing_config)
661
+ provider_config["mode"] = mode
662
+ env_writes: dict = {}
663
+
664
+ # Step 2: Install/upgrade deps for selected mode
665
+ _MIN_CLIENT_VERSION = "0.4.22"
666
+ cloud_dep = f"hindsight-client>={_MIN_CLIENT_VERSION}"
667
+ local_dep = "hindsight-all"
668
+ if mode == "local_embedded":
669
+ deps_to_install = [local_dep]
670
+ elif mode == "local_external":
671
+ deps_to_install = [cloud_dep]
672
+ else:
673
+ deps_to_install = [cloud_dep]
674
+
675
+ print("\n Checking dependencies...")
676
+ uv_path = shutil.which("uv")
677
+ if not uv_path:
678
+ print(" ⚠ uv not found — install it: curl -LsSf https://astral.sh/uv/install.sh | sh")
679
+ print(f" Then run manually: uv pip install --python {sys.executable} {' '.join(deps_to_install)}")
680
+ else:
681
+ try:
682
+ subprocess.run(
683
+ [uv_path, "pip", "install", "--python", sys.executable, "--quiet", "--upgrade"] + deps_to_install,
684
+ check=True, timeout=120, capture_output=True,
685
+ )
686
+ print(" ✓ Dependencies up to date")
687
+ except Exception as e:
688
+ print(f" ⚠ Install failed: {e}")
689
+ print(f" Run manually: uv pip install --python {sys.executable} {' '.join(deps_to_install)}")
690
+
691
+ # Step 3: Mode-specific config
692
+ if mode == "cloud":
693
+ print("\n Get your API key at https://ui.hindsight.vectorize.io\n")
694
+ existing_key = os.environ.get("HINDSIGHT_API_KEY", "")
695
+ if existing_key:
696
+ masked = f"...{existing_key[-4:]}" if len(existing_key) > 4 else "set"
697
+ sys.stdout.write(f" API key (current: {masked}, blank to keep): ")
698
+ sys.stdout.flush()
699
+ api_key = getpass.getpass(prompt="") if sys.stdin.isatty() else sys.stdin.readline().strip()
700
+ else:
701
+ sys.stdout.write(" API key: ")
702
+ sys.stdout.flush()
703
+ api_key = getpass.getpass(prompt="") if sys.stdin.isatty() else sys.stdin.readline().strip()
704
+ if api_key:
705
+ env_writes["HINDSIGHT_API_KEY"] = api_key
706
+
707
+ val = input(f" API URL [{_DEFAULT_API_URL}]: ").strip()
708
+ if val:
709
+ provider_config["api_url"] = val
710
+
711
+ elif mode == "local_external":
712
+ val = input(f" Hindsight API URL [{_DEFAULT_LOCAL_URL}]: ").strip()
713
+ provider_config["api_url"] = val or _DEFAULT_LOCAL_URL
714
+
715
+ sys.stdout.write(" API key (optional, blank to skip): ")
716
+ sys.stdout.flush()
717
+ api_key = getpass.getpass(prompt="") if sys.stdin.isatty() else sys.stdin.readline().strip()
718
+ if api_key:
719
+ env_writes["HINDSIGHT_API_KEY"] = api_key
720
+
721
+ else: # local_embedded
722
+ providers_list = list(_PROVIDER_DEFAULT_MODELS.keys())
723
+ llm_items = [
724
+ (p, f"default model: {_PROVIDER_DEFAULT_MODELS[p]}")
725
+ for p in providers_list
726
+ ]
727
+ existing_llm_provider = provider_config.get("llm_provider")
728
+ llm_default_idx = providers_list.index(existing_llm_provider) if existing_llm_provider in providers_list else 0
729
+ llm_idx = _curses_select(" Select LLM provider", llm_items, default=llm_default_idx)
730
+ llm_provider = providers_list[llm_idx]
731
+
732
+ provider_config["llm_provider"] = llm_provider
733
+
734
+ if llm_provider == "openai_compatible":
735
+ existing_base_url = provider_config.get("llm_base_url", "")
736
+ prompt = " LLM endpoint URL (e.g. http://192.168.1.10:8080/v1)"
737
+ if existing_base_url:
738
+ prompt += f" [{existing_base_url}]"
739
+ prompt += ": "
740
+ val = input(prompt).strip()
741
+ if val:
742
+ provider_config["llm_base_url"] = val
743
+ elif llm_provider == "openrouter":
744
+ provider_config["llm_base_url"] = "https://openrouter.ai/api/v1"
745
+
746
+ provider_default_model = _PROVIDER_DEFAULT_MODELS.get(llm_provider, "gpt-4o-mini")
747
+ current_model = provider_config.get("llm_model") or provider_default_model
748
+ val = input(f" LLM model [{current_model}]: ").strip()
749
+ provider_config["llm_model"] = val or current_model
750
+
751
+ sys.stdout.write(" LLM API key: ")
752
+ sys.stdout.flush()
753
+ llm_key = getpass.getpass(prompt="") if sys.stdin.isatty() else sys.stdin.readline().strip()
754
+ if llm_key:
755
+ env_writes["HINDSIGHT_LLM_API_KEY"] = llm_key
756
+ else:
757
+ env_path = Path(hermes_home) / ".env"
758
+ existing_llm_key = ""
759
+ if env_path.exists():
760
+ for line in env_path.read_text().splitlines():
761
+ if line.startswith("HINDSIGHT_LLM_API_KEY="):
762
+ existing_llm_key = line.split("=", 1)[1]
763
+ break
764
+ env_writes["HINDSIGHT_LLM_API_KEY"] = existing_llm_key
765
+
766
+ # Step 4: Save everything
767
+ provider_config.setdefault("bank_id", "hermes")
768
+ provider_config.setdefault("recall_budget", "mid")
769
+ # Read existing timeout from config if present, otherwise use default.
770
+ # Preserve explicit 0 values instead of treating them as blank.
771
+ existing_timeout = provider_config.get("timeout")
772
+ timeout_val = existing_timeout if existing_timeout is not None else _DEFAULT_TIMEOUT
773
+ provider_config["timeout"] = timeout_val
774
+ env_writes["HINDSIGHT_TIMEOUT"] = str(timeout_val)
775
+ if mode == "local_embedded":
776
+ existing_idle_timeout = provider_config.get("idle_timeout")
777
+ idle_timeout_val = existing_idle_timeout if existing_idle_timeout is not None else _DEFAULT_IDLE_TIMEOUT
778
+ provider_config["idle_timeout"] = idle_timeout_val
779
+ env_writes["HINDSIGHT_IDLE_TIMEOUT"] = str(idle_timeout_val)
780
+ config["memory"]["provider"] = "hindsight"
781
+ save_config(config)
782
+
783
+ self.save_config(provider_config, hermes_home)
784
+
785
+ if env_writes:
786
+ env_path = Path(hermes_home) / ".env"
787
+ env_path.parent.mkdir(parents=True, exist_ok=True)
788
+ existing_lines = []
789
+ if env_path.exists():
790
+ existing_lines = env_path.read_text().splitlines()
791
+ updated_keys = set()
792
+ new_lines = []
793
+ for line in existing_lines:
794
+ key_match = line.split("=", 1)[0].strip() if "=" in line and not line.startswith("#") else None
795
+ if key_match and key_match in env_writes:
796
+ new_lines.append(f"{key_match}={env_writes[key_match]}")
797
+ updated_keys.add(key_match)
798
+ else:
799
+ new_lines.append(line)
800
+ for k, v in env_writes.items():
801
+ if k not in updated_keys:
802
+ new_lines.append(f"{k}={v}")
803
+ env_path.write_text("\n".join(new_lines) + "\n")
804
+
805
+ if mode == "local_embedded":
806
+ materialized_config = dict(provider_config)
807
+ config_path = Path(hermes_home) / "hindsight" / "config.json"
808
+ try:
809
+ materialized_config = json.loads(config_path.read_text(encoding="utf-8"))
810
+ except Exception:
811
+ pass
812
+
813
+ llm_api_key = env_writes.get("HINDSIGHT_LLM_API_KEY", "")
814
+ if not llm_api_key:
815
+ llm_api_key = _load_simple_env(Path(hermes_home) / ".env").get("HINDSIGHT_LLM_API_KEY", "")
816
+ if not llm_api_key:
817
+ llm_api_key = _load_simple_env(_embedded_profile_env_path(materialized_config)).get(
818
+ "HINDSIGHT_API_LLM_API_KEY",
819
+ "",
820
+ )
821
+
822
+ _materialize_embedded_profile_env(
823
+ materialized_config,
824
+ llm_api_key=llm_api_key or None,
825
+ )
826
+
827
+ print(f"\n ✓ Hindsight memory configured ({mode} mode)")
828
+ if env_writes:
829
+ print(" API keys saved to .env")
830
+ print("\n Start a new session to activate.\n")
831
+
832
+ def get_config_schema(self):
833
+ return [
834
+ {"key": "mode", "description": "Connection mode", "default": "cloud", "choices": ["cloud", "local_embedded", "local_external"]},
835
+ # Cloud mode
836
+ {"key": "api_url", "description": "Hindsight Cloud API URL", "default": _DEFAULT_API_URL, "when": {"mode": "cloud"}},
837
+ {"key": "api_key", "description": "Hindsight Cloud API key", "secret": True, "env_var": "HINDSIGHT_API_KEY", "url": "https://ui.hindsight.vectorize.io", "when": {"mode": "cloud"}},
838
+ # Local external mode
839
+ {"key": "api_url", "description": "Hindsight API URL", "default": _DEFAULT_LOCAL_URL, "when": {"mode": "local_external"}},
840
+ {"key": "api_key", "description": "API key (optional)", "secret": True, "env_var": "HINDSIGHT_API_KEY", "when": {"mode": "local_external"}},
841
+ # Local embedded mode
842
+ {"key": "llm_provider", "description": "LLM provider", "default": "openai", "choices": ["openai", "anthropic", "gemini", "groq", "openrouter", "minimax", "ollama", "lmstudio", "openai_compatible"], "when": {"mode": "local_embedded"}},
843
+ {"key": "llm_base_url", "description": "Endpoint URL (e.g. http://192.168.1.10:8080/v1)", "default": "", "when": {"mode": "local_embedded", "llm_provider": "openai_compatible"}},
844
+ {"key": "llm_api_key", "description": "LLM API key (optional for openai_compatible)", "secret": True, "env_var": "HINDSIGHT_LLM_API_KEY", "when": {"mode": "local_embedded"}},
845
+ {"key": "llm_model", "description": "LLM model", "default": "gpt-4o-mini", "default_from": {"field": "llm_provider", "map": _PROVIDER_DEFAULT_MODELS}, "when": {"mode": "local_embedded"}},
846
+ {"key": "bank_id", "description": "Memory bank name (static fallback when bank_id_template is unset)", "default": "hermes"},
847
+ {"key": "bank_id_template", "description": "Optional template to derive bank_id dynamically. Placeholders: {profile}, {workspace}, {platform}, {user}, {session}. Example: hermes-{profile}", "default": ""},
848
+ {"key": "bank_mission", "description": "Mission/purpose description for the memory bank"},
849
+ {"key": "bank_retain_mission", "description": "Custom extraction prompt for memory retention"},
850
+ {"key": "recall_budget", "description": "Recall thoroughness", "default": "mid", "choices": ["low", "mid", "high"]},
851
+ {"key": "memory_mode", "description": "Memory integration mode", "default": "hybrid", "choices": ["hybrid", "context", "tools"]},
852
+ {"key": "recall_prefetch_method", "description": "Auto-recall method", "default": "recall", "choices": ["recall", "reflect"]},
853
+ {"key": "retain_tags", "description": "Default tags applied to retained memories (comma-separated)", "default": ""},
854
+ {"key": "retain_source", "description": "Metadata source value attached to retained memories", "default": ""},
855
+ {"key": "retain_user_prefix", "description": "Label used before user turns in retained transcripts", "default": "User"},
856
+ {"key": "retain_assistant_prefix", "description": "Label used before assistant turns in retained transcripts", "default": "Assistant"},
857
+ {"key": "recall_tags", "description": "Tags to filter when searching memories (comma-separated)", "default": ""},
858
+ {"key": "recall_tags_match", "description": "Tag matching mode for recall", "default": "any", "choices": ["any", "all", "any_strict", "all_strict"]},
859
+ {"key": "auto_recall", "description": "Automatically recall memories before each turn", "default": True},
860
+ {"key": "auto_retain", "description": "Automatically retain conversation turns", "default": True},
861
+ {"key": "retain_every_n_turns", "description": "Retain every N turns (1 = every turn)", "default": 1},
862
+ {"key": "retain_async","description": "Process retain asynchronously on the Hindsight server", "default": True},
863
+ {"key": "retain_context", "description": "Context label for retained memories", "default": "conversation between Hermes Agent and the User"},
864
+ {"key": "recall_max_tokens", "description": "Maximum tokens for recall results", "default": 4096},
865
+ {"key": "recall_max_input_chars", "description": "Maximum input query length for auto-recall", "default": 800},
866
+ {"key": "recall_prompt_preamble", "description": "Custom preamble for recalled memories in context"},
867
+ {"key": "timeout", "description": "API request timeout in seconds", "default": _DEFAULT_TIMEOUT},
868
+ {"key": "idle_timeout", "description": "Embedded daemon idle timeout in seconds (0 disables auto-shutdown)", "default": _DEFAULT_IDLE_TIMEOUT, "when": {"mode": "local_embedded"}},
869
+ ]
870
+
871
+ def _get_client(self):
872
+ """Return the cached Hindsight client (created once, reused)."""
873
+ if self._client is None:
874
+ if self._mode == "local_embedded":
875
+ available, reason = _check_local_runtime()
876
+ if not available:
877
+ raise RuntimeError(
878
+ "Hindsight local runtime is unavailable"
879
+ + (f": {reason}" if reason else "")
880
+ )
881
+ try:
882
+ from tools.lazy_deps import ensure as _lazy_ensure
883
+ _lazy_ensure("memory.hindsight", prompt=False)
884
+ except ImportError:
885
+ pass
886
+ except Exception as _e:
887
+ raise ImportError(str(_e))
888
+ from hindsight import HindsightEmbedded
889
+ HindsightEmbedded.__del__ = lambda self: None
890
+ llm_provider = self._config.get("llm_provider", "")
891
+ if llm_provider in ("openai_compatible", "openrouter"):
892
+ llm_provider = "openai"
893
+ logger.debug("Creating HindsightEmbedded client (profile=%s, provider=%s)",
894
+ self._config.get("profile", "hermes"), llm_provider)
895
+ kwargs = dict(
896
+ profile=self._config.get("profile", "hermes"),
897
+ llm_provider=llm_provider,
898
+ llm_api_key=self._config.get("llmApiKey") or self._config.get("llm_api_key") or os.environ.get("HINDSIGHT_LLM_API_KEY", ""),
899
+ llm_model=self._config.get("llm_model", ""),
900
+ )
901
+ if self._llm_base_url:
902
+ kwargs["llm_base_url"] = self._llm_base_url
903
+ idle_timeout = _parse_int_setting(
904
+ self._config.get("idle_timeout")
905
+ if self._config.get("idle_timeout") is not None
906
+ else os.environ.get("HINDSIGHT_IDLE_TIMEOUT", self._idle_timeout),
907
+ _DEFAULT_IDLE_TIMEOUT,
908
+ )
909
+ self._idle_timeout = idle_timeout
910
+ kwargs["idle_timeout"] = idle_timeout
911
+ self._client = HindsightEmbedded(**kwargs)
912
+ else:
913
+ from hindsight_client import Hindsight
914
+ timeout = self._timeout or _DEFAULT_TIMEOUT
915
+ kwargs = {"base_url": self._api_url, "timeout": float(timeout)}
916
+ if self._api_key:
917
+ kwargs["api_key"] = self._api_key
918
+ logger.debug("Creating Hindsight cloud client (url=%s, has_key=%s, timeout=%s)",
919
+ self._api_url, bool(self._api_key), kwargs["timeout"])
920
+ self._client = Hindsight(**kwargs)
921
+ return self._client
922
+
923
+ def _run_sync(self, coro):
924
+ """Schedule *coro* on the shared loop using the configured timeout."""
925
+ return _run_sync(coro, timeout=self._timeout)
926
+
927
+ def _is_retriable_embedded_connection_error(self, exc: Exception) -> bool:
928
+ """Return True for stale embedded-daemon connection failures."""
929
+ if self._mode != "local_embedded":
930
+ return False
931
+ text = f"{type(exc).__name__}: {exc}".lower()
932
+ return any(
933
+ marker in text
934
+ for marker in (
935
+ "cannot connect to host",
936
+ "connection refused",
937
+ "connect call failed",
938
+ "clientconnectorerror",
939
+ )
940
+ )
941
+
942
+ def _ensure_writer(self) -> None:
943
+ """Lazy-start the single retain-writer thread.
944
+
945
+ We don't start the writer in initialize() so providers that never
946
+ retain (e.g. tools-only mode) don't pay for an idle thread.
947
+ """
948
+ thread = self._writer_thread
949
+ if thread is not None and thread.is_alive():
950
+ return
951
+ # If the previous writer exited (e.g. after a prior shutdown), reset
952
+ # the flag so this fresh writer is allowed to drain new jobs.
953
+ self._shutting_down.clear()
954
+ thread = threading.Thread(
955
+ target=self._writer_loop,
956
+ daemon=True,
957
+ name="hindsight-writer",
958
+ )
959
+ self._writer_thread = thread
960
+ # Keep the legacy _sync_thread alias pointing at the writer so any
961
+ # external code that joins _sync_thread keeps working.
962
+ self._sync_thread = thread
963
+ thread.start()
964
+
965
+ def _writer_loop(self) -> None:
966
+ """Drain the retain queue serially. Exits on sentinel.
967
+
968
+ Each job() is wrapped so a single failure can't kill the writer.
969
+ task_done() always fires so queue.join() works in tests.
970
+ """
971
+ while True:
972
+ try:
973
+ job = self._retain_queue.get(timeout=1.0)
974
+ except queue.Empty:
975
+ if self._shutting_down.is_set():
976
+ return
977
+ continue
978
+ try:
979
+ if job is _WRITER_SENTINEL:
980
+ return
981
+ try:
982
+ job()
983
+ except Exception as exc:
984
+ logger.warning("Hindsight retain failed: %s", exc, exc_info=True)
985
+ finally:
986
+ self._retain_queue.task_done()
987
+
988
+ def _register_atexit(self) -> None:
989
+ """Register an idempotent atexit hook to drain the writer.
990
+
991
+ Without this, a CLI exit that doesn't go through MemoryManager.
992
+ shutdown_all() would leave in-flight retain jobs racing interpreter
993
+ teardown, producing "cannot schedule new futures" warnings and
994
+ unclosed aiohttp sessions.
995
+ """
996
+ if self._atexit_registered:
997
+ return
998
+ self._atexit_registered = True
999
+ atexit.register(self._atexit_shutdown)
1000
+
1001
+ def _atexit_shutdown(self) -> None:
1002
+ if self._shutting_down.is_set():
1003
+ return
1004
+ try:
1005
+ self.shutdown()
1006
+ except Exception as exc:
1007
+ logger.debug("Hindsight atexit shutdown failed: %s", exc)
1008
+
1009
+ def _run_hindsight_operation(self, operation):
1010
+ """Run an async Hindsight client operation, retrying once after idle shutdown."""
1011
+ client = self._get_client()
1012
+ try:
1013
+ return self._run_sync(operation(client))
1014
+ except Exception as exc:
1015
+ if not self._is_retriable_embedded_connection_error(exc):
1016
+ raise
1017
+ logger.info(
1018
+ "Hindsight embedded daemon appears unreachable; recreating client and retrying once: %s",
1019
+ exc,
1020
+ )
1021
+ self._client = None
1022
+ client = self._get_client()
1023
+ self._client = client
1024
+ return self._run_sync(operation(client))
1025
+
1026
+ def _probe_url(self) -> str:
1027
+ """Return the URL to probe /version on.
1028
+
1029
+ For local_embedded the daemon is on a per-profile dynamic port,
1030
+ so we prefer the running client's URL when available; otherwise
1031
+ fall back to the configured api_url.
1032
+ """
1033
+ if self._mode == "local_embedded" and self._client is not None:
1034
+ url = getattr(self._client, "url", None)
1035
+ if url:
1036
+ return str(url)
1037
+ return self._api_url or ""
1038
+
1039
+ def _resolve_retain_target(self, fallback_document_id: str) -> tuple[str, str | None]:
1040
+ """Pick (document_id, update_mode) based on live API capability.
1041
+
1042
+ On Hindsight ≥ 0.5.0 the API supports ``update_mode='append'``,
1043
+ which lets us reuse a stable session-scoped ``document_id`` across
1044
+ process lifecycles without overwriting prior turns. On older APIs
1045
+ we fall back to *fallback_document_id* (the per-process unique
1046
+ ``f"{session_id}-{start_ts}"`` minted at initialize / switch time)
1047
+ and don't pass ``update_mode`` at all — that's the only way the
1048
+ resume-overwrite fix (#6654) keeps working on legacy servers.
1049
+
1050
+ Probe is cached at module level per API URL, so this is one HTTP
1051
+ round-trip per (process, api_url) pair regardless of how many
1052
+ retains fire.
1053
+ """
1054
+ if not self._session_id:
1055
+ return fallback_document_id, None
1056
+ if _check_api_supports_update_mode_append(self._probe_url(), self._api_key):
1057
+ return self._session_id, "append"
1058
+ return fallback_document_id, None
1059
+
1060
+ def initialize(self, session_id: str, **kwargs) -> None:
1061
+ self._session_id = str(session_id or "").strip()
1062
+ self._parent_session_id = str(kwargs.get("parent_session_id", "") or "").strip()
1063
+
1064
+ # Each process lifecycle gets its own document_id. Reusing session_id
1065
+ # alone caused overwrites on /resume — the reloaded session starts
1066
+ # with an empty _session_turns, so the next retain would replace the
1067
+ # previously stored content. session_id stays in tags so processes
1068
+ # for the same session remain filterable together.
1069
+ start_ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
1070
+ self._document_id = f"{self._session_id}-{start_ts}"
1071
+
1072
+ # Check client version and auto-upgrade if needed
1073
+ try:
1074
+ from importlib.metadata import version as pkg_version
1075
+ from packaging.version import Version
1076
+ installed = pkg_version("hindsight-client")
1077
+ if Version(installed) < Version(_MIN_CLIENT_VERSION):
1078
+ logger.warning("hindsight-client %s is outdated (need >=%s), attempting upgrade...",
1079
+ installed, _MIN_CLIENT_VERSION)
1080
+ import shutil
1081
+ import subprocess
1082
+ import sys
1083
+ uv_path = shutil.which("uv")
1084
+ if uv_path:
1085
+ try:
1086
+ subprocess.run(
1087
+ [uv_path, "pip", "install", "--python", sys.executable,
1088
+ "--quiet", "--upgrade", f"hindsight-client>={_MIN_CLIENT_VERSION}"],
1089
+ check=True, timeout=120, capture_output=True,
1090
+ )
1091
+ logger.info("hindsight-client upgraded to >=%s", _MIN_CLIENT_VERSION)
1092
+ except Exception as e:
1093
+ logger.warning("Auto-upgrade failed: %s. Run: uv pip install 'hindsight-client>=%s'",
1094
+ e, _MIN_CLIENT_VERSION)
1095
+ else:
1096
+ logger.warning("uv not found. Run: pip install 'hindsight-client>=%s'", _MIN_CLIENT_VERSION)
1097
+ except Exception:
1098
+ pass # packaging not available or other issue — proceed anyway
1099
+
1100
+ self._config = _load_config()
1101
+ self._platform = str(kwargs.get("platform") or "").strip()
1102
+ self._user_id = str(kwargs.get("user_id") or "").strip()
1103
+ self._user_name = str(kwargs.get("user_name") or "").strip()
1104
+ self._chat_id = str(kwargs.get("chat_id") or "").strip()
1105
+ self._chat_name = str(kwargs.get("chat_name") or "").strip()
1106
+ self._chat_type = str(kwargs.get("chat_type") or "").strip()
1107
+ self._thread_id = str(kwargs.get("thread_id") or "").strip()
1108
+ self._agent_identity = str(kwargs.get("agent_identity") or "").strip()
1109
+ self._agent_workspace = str(kwargs.get("agent_workspace") or "").strip()
1110
+ self._turn_index = 0
1111
+ self._session_turns = []
1112
+ self._mode = self._config.get("mode", "cloud")
1113
+ # Read timeout from config or env var, fall back to default
1114
+ self._timeout = _parse_int_setting(
1115
+ self._config.get("timeout") if self._config.get("timeout") is not None else os.environ.get("HINDSIGHT_TIMEOUT"),
1116
+ _DEFAULT_TIMEOUT,
1117
+ )
1118
+ self._idle_timeout = _parse_int_setting(
1119
+ self._config.get("idle_timeout") if self._config.get("idle_timeout") is not None else os.environ.get("HINDSIGHT_IDLE_TIMEOUT"),
1120
+ _DEFAULT_IDLE_TIMEOUT,
1121
+ )
1122
+ # "local" is a legacy alias for "local_embedded"
1123
+ if self._mode == "local":
1124
+ self._mode = "local_embedded"
1125
+ if self._mode == "local_embedded":
1126
+ available, reason = _check_local_runtime()
1127
+ if not available:
1128
+ logger.warning(
1129
+ "Hindsight local mode disabled because its runtime could not be imported: %s",
1130
+ reason,
1131
+ )
1132
+ self._mode = "disabled"
1133
+ return
1134
+ self._api_key = self._config.get("apiKey") or self._config.get("api_key") or os.environ.get("HINDSIGHT_API_KEY", "")
1135
+ default_url = _DEFAULT_LOCAL_URL if self._mode in ("local_embedded", "local_external") else _DEFAULT_API_URL
1136
+ self._api_url = self._config.get("api_url") or os.environ.get("HINDSIGHT_API_URL", default_url)
1137
+ self._llm_base_url = self._config.get("llm_base_url", "")
1138
+
1139
+ banks = cfg_get(self._config, "banks", "hermes", default={})
1140
+ static_bank_id = self._config.get("bank_id") or banks.get("bankId", "hermes")
1141
+ self._bank_id_template = self._config.get("bank_id_template", "") or ""
1142
+ self._bank_id = _resolve_bank_id_template(
1143
+ self._bank_id_template,
1144
+ fallback=static_bank_id,
1145
+ profile=self._agent_identity,
1146
+ workspace=self._agent_workspace,
1147
+ platform=self._platform,
1148
+ user=self._user_id,
1149
+ session=self._session_id,
1150
+ )
1151
+ budget = self._config.get("recall_budget") or self._config.get("budget") or banks.get("budget", "mid")
1152
+ self._budget = budget if budget in _VALID_BUDGETS else "mid"
1153
+
1154
+ memory_mode = self._config.get("memory_mode", "hybrid")
1155
+ self._memory_mode = memory_mode if memory_mode in ("context", "tools", "hybrid") else "hybrid"
1156
+
1157
+ prefetch_method = self._config.get("recall_prefetch_method") or self._config.get("prefetch_method", "recall")
1158
+ self._prefetch_method = prefetch_method if prefetch_method in ("recall", "reflect") else "recall"
1159
+
1160
+ # Bank options
1161
+ self._bank_mission = self._config.get("bank_mission", "")
1162
+ self._bank_retain_mission = self._config.get("bank_retain_mission") or None
1163
+
1164
+ # Tags
1165
+ self._retain_tags = _normalize_retain_tags(
1166
+ self._config.get("retain_tags")
1167
+ or os.environ.get("HINDSIGHT_RETAIN_TAGS", "")
1168
+ )
1169
+ self._tags = self._retain_tags or None
1170
+ self._recall_tags = self._config.get("recall_tags") or None
1171
+ self._recall_tags_match = self._config.get("recall_tags_match", "any")
1172
+ self._retain_source = str(
1173
+ self._config.get("retain_source") or os.environ.get("HINDSIGHT_RETAIN_SOURCE", "")
1174
+ ).strip()
1175
+ self._retain_user_prefix = str(
1176
+ self._config.get("retain_user_prefix") or os.environ.get("HINDSIGHT_RETAIN_USER_PREFIX", "User")
1177
+ ).strip() or "User"
1178
+ self._retain_assistant_prefix = str(
1179
+ self._config.get("retain_assistant_prefix") or os.environ.get("HINDSIGHT_RETAIN_ASSISTANT_PREFIX", "Assistant")
1180
+ ).strip() or "Assistant"
1181
+
1182
+ # Retain controls
1183
+ self._auto_retain = self._config.get("auto_retain", True)
1184
+ self._retain_every_n_turns = max(1, int(self._config.get("retain_every_n_turns", 1)))
1185
+ self._retain_context = self._config.get("retain_context", "conversation between Hermes Agent and the User")
1186
+
1187
+ # Recall controls
1188
+ self._auto_recall = self._config.get("auto_recall", True)
1189
+ self._recall_max_tokens = int(self._config.get("recall_max_tokens", 4096))
1190
+ self._recall_types = self._config.get("recall_types") or None
1191
+ self._recall_prompt_preamble = self._config.get("recall_prompt_preamble", "")
1192
+ self._recall_max_input_chars = int(self._config.get("recall_max_input_chars", 800))
1193
+ self._retain_async = self._config.get("retain_async", True)
1194
+
1195
+ _client_version = "unknown"
1196
+ try:
1197
+ from importlib.metadata import version as pkg_version
1198
+ _client_version = pkg_version("hindsight-client")
1199
+ except Exception:
1200
+ pass
1201
+ logger.info("Hindsight initialized: mode=%s, api_url=%s, bank=%s, budget=%s, memory_mode=%s, prefetch_method=%s, client=%s",
1202
+ self._mode, self._api_url, self._bank_id, self._budget, self._memory_mode, self._prefetch_method, _client_version)
1203
+ if self._bank_id_template:
1204
+ logger.debug("Hindsight bank resolved from template %r: profile=%s workspace=%s platform=%s user=%s -> bank=%s",
1205
+ self._bank_id_template, self._agent_identity, self._agent_workspace,
1206
+ self._platform, self._user_id, self._bank_id)
1207
+ logger.debug("Hindsight config: auto_retain=%s, auto_recall=%s, retain_every_n=%d, "
1208
+ "retain_async=%s, retain_context=%s, recall_max_tokens=%d, recall_max_input_chars=%d, tags=%s, recall_tags=%s",
1209
+ self._auto_retain, self._auto_recall, self._retain_every_n_turns,
1210
+ self._retain_async, self._retain_context, self._recall_max_tokens, self._recall_max_input_chars,
1211
+ self._tags, self._recall_tags)
1212
+
1213
+ # For local mode, start the embedded daemon in the background so it
1214
+ # doesn't block the chat. Redirect stdout/stderr to a log file to
1215
+ # prevent rich startup output from spamming the terminal.
1216
+ if self._mode == "local_embedded":
1217
+ def _start_daemon():
1218
+ import traceback
1219
+ log_dir = get_hermes_home() / "logs"
1220
+ log_dir.mkdir(parents=True, exist_ok=True)
1221
+ log_path = log_dir / "hindsight-embed.log"
1222
+ try:
1223
+ # Redirect the daemon manager's Rich console to our log file
1224
+ # instead of stderr. This avoids global fd redirects that
1225
+ # would capture output from other threads.
1226
+ import hindsight_embed.daemon_embed_manager as dem
1227
+ from rich.console import Console
1228
+ dem.console = Console(file=open(log_path, "a", encoding="utf-8"), force_terminal=False)
1229
+
1230
+ client = self._get_client()
1231
+ profile = self._config.get("profile", "hermes")
1232
+
1233
+ # Update the profile .env to match our current config so
1234
+ # the daemon always starts with the right settings.
1235
+ # If the config changed and the daemon is running, stop it.
1236
+ profile_env = _embedded_profile_env_path(self._config)
1237
+ expected_env = _build_embedded_profile_env(self._config)
1238
+ saved = _load_simple_env(profile_env)
1239
+ config_changed = saved != expected_env
1240
+
1241
+ if config_changed:
1242
+ profile_env = _materialize_embedded_profile_env(self._config)
1243
+ if client._manager.is_running(profile):
1244
+ with open(log_path, "a", encoding="utf-8") as f:
1245
+ f.write("\n=== Config changed, restarting daemon ===\n")
1246
+ client._manager.stop(profile)
1247
+
1248
+ client._ensure_started()
1249
+ with open(log_path, "a", encoding="utf-8") as f:
1250
+ f.write("\n=== Daemon started successfully ===\n")
1251
+ except Exception as e:
1252
+ with open(log_path, "a", encoding="utf-8") as f:
1253
+ f.write(f"\n=== Daemon startup failed: {e} ===\n")
1254
+ traceback.print_exc(file=f)
1255
+
1256
+ t = threading.Thread(target=_start_daemon, daemon=True, name="hindsight-daemon-start")
1257
+ t.start()
1258
+
1259
+ def system_prompt_block(self) -> str:
1260
+ if self._memory_mode == "context":
1261
+ return (
1262
+ f"# Hindsight Memory\n"
1263
+ f"Active (context mode). Bank: {self._bank_id}, budget: {self._budget}.\n"
1264
+ f"Relevant memories are automatically injected into context."
1265
+ )
1266
+ if self._memory_mode == "tools":
1267
+ return (
1268
+ f"# Hindsight Memory\n"
1269
+ f"Active (tools mode). Bank: {self._bank_id}, budget: {self._budget}.\n"
1270
+ f"Use hindsight_recall to search, hindsight_reflect for synthesis, "
1271
+ f"hindsight_retain to store facts."
1272
+ )
1273
+ return (
1274
+ f"# Hindsight Memory\n"
1275
+ f"Active. Bank: {self._bank_id}, budget: {self._budget}.\n"
1276
+ f"Relevant memories are automatically injected into context. "
1277
+ f"Use hindsight_recall to search, hindsight_reflect for synthesis, "
1278
+ f"hindsight_retain to store facts."
1279
+ )
1280
+
1281
+ def prefetch(self, query: str, *, session_id: str = "") -> str:
1282
+ if self._prefetch_thread and self._prefetch_thread.is_alive():
1283
+ logger.debug("Prefetch: waiting for background thread to complete")
1284
+ self._prefetch_thread.join(timeout=3.0)
1285
+ with self._prefetch_lock:
1286
+ result = self._prefetch_result
1287
+ self._prefetch_result = ""
1288
+ if not result:
1289
+ logger.debug("Prefetch: no results available")
1290
+ return ""
1291
+ logger.debug("Prefetch: returning %d chars of context", len(result))
1292
+ header = self._recall_prompt_preamble or (
1293
+ "# Hindsight Memory (persistent cross-session context)\n"
1294
+ "Use this to answer questions about the user and prior sessions. "
1295
+ "Do not call tools to look up information that is already present here."
1296
+ )
1297
+ return f"{header}\n\n{result}"
1298
+
1299
+ def queue_prefetch(self, query: str, *, session_id: str = "") -> None:
1300
+ if self._memory_mode == "tools":
1301
+ logger.debug("Prefetch: skipped (tools-only mode)")
1302
+ return
1303
+ if not self._auto_recall:
1304
+ logger.debug("Prefetch: skipped (auto_recall disabled)")
1305
+ return
1306
+ if self._shutting_down.is_set():
1307
+ logger.debug("Prefetch: skipped (shutting down)")
1308
+ return
1309
+ # Truncate query to max chars
1310
+ if self._recall_max_input_chars and len(query) > self._recall_max_input_chars:
1311
+ query = query[:self._recall_max_input_chars]
1312
+
1313
+ def _run():
1314
+ try:
1315
+ if self._prefetch_method == "reflect":
1316
+ logger.debug("Prefetch: calling reflect (bank=%s, query_len=%d)", self._bank_id, len(query))
1317
+ resp = self._run_hindsight_operation(lambda client: client.areflect(bank_id=self._bank_id, query=query, budget=self._budget))
1318
+ text = resp.text or ""
1319
+ else:
1320
+ recall_kwargs: dict = {
1321
+ "bank_id": self._bank_id, "query": query,
1322
+ "budget": self._budget, "max_tokens": self._recall_max_tokens,
1323
+ }
1324
+ if self._recall_tags:
1325
+ recall_kwargs["tags"] = self._recall_tags
1326
+ recall_kwargs["tags_match"] = self._recall_tags_match
1327
+ if self._recall_types:
1328
+ recall_kwargs["types"] = self._recall_types
1329
+ logger.debug("Prefetch: calling recall (bank=%s, query_len=%d, budget=%s)",
1330
+ self._bank_id, len(query), self._budget)
1331
+ resp = self._run_hindsight_operation(lambda client: client.arecall(**recall_kwargs))
1332
+ num_results = len(resp.results) if resp.results else 0
1333
+ logger.debug("Prefetch: recall returned %d results", num_results)
1334
+ text = "\n".join(f"- {r.text}" for r in resp.results if r.text) if resp.results else ""
1335
+ if text:
1336
+ with self._prefetch_lock:
1337
+ self._prefetch_result = text
1338
+ except Exception as e:
1339
+ logger.debug("Hindsight prefetch failed: %s", e, exc_info=True)
1340
+
1341
+ self._prefetch_thread = threading.Thread(target=_run, daemon=True, name="hindsight-prefetch")
1342
+ self._prefetch_thread.start()
1343
+
1344
+ def _build_turn_messages(self, user_content: str, assistant_content: str) -> List[Dict[str, str]]:
1345
+ now = datetime.now(timezone.utc).isoformat()
1346
+ return [
1347
+ {
1348
+ "role": "user",
1349
+ "content": f"{self._retain_user_prefix}: {user_content}",
1350
+ "timestamp": now,
1351
+ },
1352
+ {
1353
+ "role": "assistant",
1354
+ "content": f"{self._retain_assistant_prefix}: {assistant_content}",
1355
+ "timestamp": now,
1356
+ },
1357
+ ]
1358
+
1359
+ def _build_metadata(self, *, message_count: int, turn_index: int) -> Dict[str, str]:
1360
+ metadata: Dict[str, str] = {
1361
+ "retained_at": _utc_timestamp(),
1362
+ "message_count": str(message_count),
1363
+ "turn_index": str(turn_index),
1364
+ }
1365
+ if self._retain_source:
1366
+ metadata["source"] = self._retain_source
1367
+ if self._session_id:
1368
+ metadata["session_id"] = self._session_id
1369
+ if self._platform:
1370
+ metadata["platform"] = self._platform
1371
+ if self._user_id:
1372
+ metadata["user_id"] = self._user_id
1373
+ if self._user_name:
1374
+ metadata["user_name"] = self._user_name
1375
+ if self._chat_id:
1376
+ metadata["chat_id"] = self._chat_id
1377
+ if self._chat_name:
1378
+ metadata["chat_name"] = self._chat_name
1379
+ if self._chat_type:
1380
+ metadata["chat_type"] = self._chat_type
1381
+ if self._thread_id:
1382
+ metadata["thread_id"] = self._thread_id
1383
+ if self._agent_identity:
1384
+ metadata["agent_identity"] = self._agent_identity
1385
+ return metadata
1386
+
1387
+ def _build_retain_kwargs(
1388
+ self,
1389
+ content: str,
1390
+ *,
1391
+ context: str | None = None,
1392
+ document_id: str | None = None,
1393
+ metadata: Dict[str, str] | None = None,
1394
+ tags: List[str] | None = None,
1395
+ retain_async: bool | None = None,
1396
+ ) -> Dict[str, Any]:
1397
+ kwargs: Dict[str, Any] = {
1398
+ "bank_id": self._bank_id,
1399
+ "content": content,
1400
+ "metadata": metadata or self._build_metadata(message_count=1, turn_index=self._turn_index),
1401
+ }
1402
+ if context is not None:
1403
+ kwargs["context"] = context
1404
+ if document_id:
1405
+ kwargs["document_id"] = document_id
1406
+ if retain_async is not None:
1407
+ kwargs["retain_async"] = retain_async
1408
+ merged_tags = _normalize_retain_tags(self._retain_tags)
1409
+ for tag in _normalize_retain_tags(tags):
1410
+ if tag not in merged_tags:
1411
+ merged_tags.append(tag)
1412
+ if merged_tags:
1413
+ kwargs["tags"] = merged_tags
1414
+ return kwargs
1415
+
1416
+ def sync_turn(self, user_content: str, assistant_content: str, *, session_id: str = "") -> None:
1417
+ """Enqueue a retain for the current turn. Non-blocking.
1418
+
1419
+ The actual aretain_batch runs on a single long-lived writer thread
1420
+ that drains an in-memory queue. Once shutdown() has been called,
1421
+ further sync_turn() calls are dropped — this prevents post-exit
1422
+ retains from reaching aiohttp after interpreter shutdown begins.
1423
+ """
1424
+ if not self._auto_retain:
1425
+ logger.debug("sync_turn: skipped (auto_retain disabled)")
1426
+ return
1427
+ if self._shutting_down.is_set():
1428
+ logger.debug("sync_turn: skipped (shutting down)")
1429
+ return
1430
+
1431
+ if session_id:
1432
+ self._session_id = str(session_id).strip()
1433
+
1434
+ turn = json.dumps(self._build_turn_messages(user_content, assistant_content), ensure_ascii=False)
1435
+ self._session_turns.append(turn)
1436
+ self._turn_counter += 1
1437
+ self._turn_index = self._turn_counter
1438
+
1439
+ if self._turn_counter % self._retain_every_n_turns != 0:
1440
+ logger.debug("sync_turn: buffered turn %d (will retain at turn %d)",
1441
+ self._turn_counter, self._turn_counter + (self._retain_every_n_turns - self._turn_counter % self._retain_every_n_turns))
1442
+ return
1443
+
1444
+ logger.debug("sync_turn: retaining %d turns, total session content %d chars",
1445
+ len(self._session_turns), sum(len(t) for t in self._session_turns))
1446
+ content = "[" + ",".join(self._session_turns) + "]"
1447
+
1448
+ lineage_tags: list[str] = []
1449
+ if self._session_id:
1450
+ lineage_tags.append(f"session:{self._session_id}")
1451
+ if self._parent_session_id:
1452
+ lineage_tags.append(f"parent:{self._parent_session_id}")
1453
+
1454
+ # Snapshot the state needed for the retain. The writer may run after
1455
+ # _session_turns / _turn_index are mutated by a later sync_turn().
1456
+ metadata_snapshot = self._build_metadata(
1457
+ message_count=len(self._session_turns) * 2,
1458
+ turn_index=self._turn_index,
1459
+ )
1460
+ num_turns = len(self._session_turns)
1461
+ document_id, update_mode = self._resolve_retain_target(self._document_id)
1462
+ bank_id = self._bank_id
1463
+ retain_async_flag = self._retain_async
1464
+ retain_context = self._retain_context
1465
+
1466
+ def _do_retain() -> None:
1467
+ item = self._build_retain_kwargs(
1468
+ content,
1469
+ context=retain_context,
1470
+ metadata=metadata_snapshot,
1471
+ tags=lineage_tags or None,
1472
+ )
1473
+ item.pop("bank_id", None)
1474
+ item.pop("retain_async", None)
1475
+ if update_mode is not None:
1476
+ item["update_mode"] = update_mode
1477
+ logger.debug("Hindsight retain: bank=%s, doc=%s, mode=%s, async=%s, content_len=%d, num_turns=%d",
1478
+ bank_id, document_id, update_mode, retain_async_flag, len(content), num_turns)
1479
+ self._run_hindsight_operation(
1480
+ lambda client: client.aretain_batch(
1481
+ bank_id=bank_id,
1482
+ items=[item],
1483
+ document_id=document_id,
1484
+ retain_async=retain_async_flag,
1485
+ )
1486
+ )
1487
+ logger.debug("Hindsight retain succeeded")
1488
+
1489
+ self._ensure_writer()
1490
+ self._register_atexit()
1491
+ self._retain_queue.put(_do_retain)
1492
+
1493
+ def get_tool_schemas(self) -> List[Dict[str, Any]]:
1494
+ if self._memory_mode == "context":
1495
+ return []
1496
+ return [RETAIN_SCHEMA, RECALL_SCHEMA, REFLECT_SCHEMA]
1497
+
1498
+ def handle_tool_call(self, tool_name: str, args: dict, **kwargs) -> str:
1499
+ if tool_name == "hindsight_retain":
1500
+ content = args.get("content", "")
1501
+ if not content:
1502
+ return tool_error("Missing required parameter: content")
1503
+ context = args.get("context")
1504
+ try:
1505
+ retain_kwargs = self._build_retain_kwargs(
1506
+ content,
1507
+ context=context,
1508
+ tags=args.get("tags"),
1509
+ )
1510
+ logger.debug("Tool hindsight_retain: bank=%s, content_len=%d, context=%s",
1511
+ self._bank_id, len(content), context)
1512
+ self._run_hindsight_operation(lambda client: client.aretain(**retain_kwargs))
1513
+ logger.debug("Tool hindsight_retain: success")
1514
+ return json.dumps({"result": "Memory stored successfully."})
1515
+ except Exception as e:
1516
+ logger.warning("hindsight_retain failed: %s", e, exc_info=True)
1517
+ return tool_error(f"Failed to store memory: {e}")
1518
+
1519
+ elif tool_name == "hindsight_recall":
1520
+ query = args.get("query", "")
1521
+ if not query:
1522
+ return tool_error("Missing required parameter: query")
1523
+ try:
1524
+ recall_kwargs: dict = {
1525
+ "bank_id": self._bank_id, "query": query, "budget": self._budget,
1526
+ "max_tokens": self._recall_max_tokens,
1527
+ }
1528
+ if self._recall_tags:
1529
+ recall_kwargs["tags"] = self._recall_tags
1530
+ recall_kwargs["tags_match"] = self._recall_tags_match
1531
+ if self._recall_types:
1532
+ recall_kwargs["types"] = self._recall_types
1533
+ logger.debug("Tool hindsight_recall: bank=%s, query_len=%d, budget=%s",
1534
+ self._bank_id, len(query), self._budget)
1535
+ resp = self._run_hindsight_operation(lambda client: client.arecall(**recall_kwargs))
1536
+ num_results = len(resp.results) if resp.results else 0
1537
+ logger.debug("Tool hindsight_recall: %d results", num_results)
1538
+ if not resp.results:
1539
+ return json.dumps({"result": "No relevant memories found."})
1540
+ lines = [f"{i}. {r.text}" for i, r in enumerate(resp.results, 1)]
1541
+ return json.dumps({"result": "\n".join(lines)})
1542
+ except Exception as e:
1543
+ logger.warning("hindsight_recall failed: %s", e, exc_info=True)
1544
+ return tool_error(f"Failed to search memory: {e}")
1545
+
1546
+ elif tool_name == "hindsight_reflect":
1547
+ query = args.get("query", "")
1548
+ if not query:
1549
+ return tool_error("Missing required parameter: query")
1550
+ try:
1551
+ logger.debug("Tool hindsight_reflect: bank=%s, query_len=%d, budget=%s",
1552
+ self._bank_id, len(query), self._budget)
1553
+ resp = self._run_hindsight_operation(
1554
+ lambda client: client.areflect(
1555
+ bank_id=self._bank_id, query=query, budget=self._budget
1556
+ )
1557
+ )
1558
+ logger.debug("Tool hindsight_reflect: response_len=%d", len(resp.text or ""))
1559
+ return json.dumps({"result": resp.text or "No relevant memories found."})
1560
+ except Exception as e:
1561
+ logger.warning("hindsight_reflect failed: %s", e, exc_info=True)
1562
+ return tool_error(f"Failed to reflect: {e}")
1563
+
1564
+ return tool_error(f"Unknown tool: {tool_name}")
1565
+
1566
+ def on_session_switch(
1567
+ self,
1568
+ new_session_id: str,
1569
+ *,
1570
+ parent_session_id: str = "",
1571
+ reset: bool = False,
1572
+ **kwargs,
1573
+ ) -> None:
1574
+ """Refresh cached per-session state when the agent rotates session_id.
1575
+
1576
+ Fires on /resume, /branch, /reset, /new, and context compression.
1577
+ Without this hook, initialize()-cached state (``_session_id``,
1578
+ ``_document_id``, ``_session_turns``, ``_turn_counter``) would keep
1579
+ pointing at the previous session and writes would land in the wrong
1580
+ document. See hermes-agent#6672.
1581
+
1582
+ Always update ``_session_id`` so metadata and tags on subsequent
1583
+ retains reflect the active session. Always mint a fresh
1584
+ ``_document_id`` so the new session's retain doesn't overwrite the
1585
+ old session's document on vectorize-io/hindsight#1303. Always clear
1586
+ the accumulated batch buffers (``_session_turns``, ``_turn_counter``,
1587
+ ``_turn_index``) — even for /resume and /branch, the new session's
1588
+ batching must start from zero so an in-flight retain doesn't flush
1589
+ under the wrong ``_document_id``.
1590
+
1591
+ Before clearing, flush any buffered turns under the *old*
1592
+ ``_document_id``. Users who set ``retain_every_n_turns > 1`` would
1593
+ otherwise silently lose whatever's in ``_session_turns`` at the
1594
+ moment of switch — the same data-loss class as the shutdown race,
1595
+ just at a different lifecycle event.
1596
+
1597
+ Also wait for any in-flight prefetch from the old session and drop
1598
+ its cached result; otherwise the new session's first ``prefetch()``
1599
+ could read stale recall text from before the switch.
1600
+
1601
+ ``parent_session_id`` is recorded for lineage tags on future retains.
1602
+ ``reset`` is accepted but not needed for Hindsight's state model —
1603
+ buffer clearing is correct for every session switch, not only /reset.
1604
+ """
1605
+ new_id = str(new_session_id or "").strip()
1606
+ if not new_id:
1607
+ return
1608
+
1609
+ # 1. Flush any buffered turns under the OLD identifiers. Snapshot
1610
+ # everything before mutating self._* so metadata + tags + doc_id
1611
+ # all reference the old session consistently.
1612
+ if self._session_turns:
1613
+ old_turns = list(self._session_turns)
1614
+ old_session_id = self._session_id
1615
+ old_parent_session_id = self._parent_session_id
1616
+ old_turn_index = self._turn_index
1617
+ old_metadata = self._build_metadata(
1618
+ message_count=len(old_turns) * 2,
1619
+ turn_index=old_turn_index,
1620
+ )
1621
+ old_lineage_tags: list[str] = []
1622
+ if old_session_id:
1623
+ old_lineage_tags.append(f"session:{old_session_id}")
1624
+ if old_parent_session_id:
1625
+ old_lineage_tags.append(f"parent:{old_parent_session_id}")
1626
+ old_content = "[" + ",".join(old_turns) + "]"
1627
+ # Resolve doc_id + update_mode against the OLD session BEFORE
1628
+ # we rotate _session_id, so the flush lands in the old
1629
+ # session's document either way (legacy: per-process unique;
1630
+ # ≥0.5.0: stable session-scoped + append).
1631
+ old_document_id, old_update_mode = self._resolve_retain_target(
1632
+ self._document_id
1633
+ )
1634
+
1635
+ def _flush():
1636
+ try:
1637
+ item = self._build_retain_kwargs(
1638
+ old_content,
1639
+ context=self._retain_context,
1640
+ metadata=old_metadata,
1641
+ tags=old_lineage_tags or None,
1642
+ )
1643
+ item.pop("bank_id", None)
1644
+ item.pop("retain_async", None)
1645
+ if old_update_mode is not None:
1646
+ item["update_mode"] = old_update_mode
1647
+ logger.debug(
1648
+ "Hindsight flush-on-switch: bank=%s, doc=%s, mode=%s, num_turns=%d",
1649
+ self._bank_id, old_document_id, old_update_mode, len(old_turns),
1650
+ )
1651
+ self._run_hindsight_operation(
1652
+ lambda client: client.aretain_batch(
1653
+ bank_id=self._bank_id,
1654
+ items=[item],
1655
+ document_id=old_document_id,
1656
+ retain_async=self._retain_async,
1657
+ )
1658
+ )
1659
+ except Exception as e:
1660
+ logger.warning("Hindsight flush-on-switch failed: %s", e, exc_info=True)
1661
+
1662
+ # Route the flush through the same writer queue sync_turn
1663
+ # uses. That serializes it behind any still-queued retains
1664
+ # from the old session (FIFO by document_id), avoids racing
1665
+ # two threads on aretain_batch against the same document, and
1666
+ # keeps shutdown's drain semantics intact. Skip enqueue if
1667
+ # shutdown has already fired — the writer is draining/gone.
1668
+ if not self._shutting_down.is_set():
1669
+ self._ensure_writer()
1670
+ self._register_atexit()
1671
+ self._retain_queue.put(_flush)
1672
+
1673
+ # 2. Drain any in-flight prefetch from the old session and drop
1674
+ # its cached result so the new session doesn't see stale recall.
1675
+ if self._prefetch_thread and self._prefetch_thread.is_alive():
1676
+ self._prefetch_thread.join(timeout=3.0)
1677
+ with self._prefetch_lock:
1678
+ self._prefetch_result = ""
1679
+
1680
+ # 3. Now rotate to the new session.
1681
+ if parent_session_id:
1682
+ self._parent_session_id = str(parent_session_id).strip()
1683
+ self._session_id = new_id
1684
+ start_ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
1685
+ self._document_id = f"{self._session_id}-{start_ts}"
1686
+ self._session_turns = []
1687
+ self._turn_counter = 0
1688
+ self._turn_index = 0
1689
+ logger.debug(
1690
+ "Hindsight on_session_switch: new_session=%s parent=%s reset=%s doc=%s",
1691
+ self._session_id, self._parent_session_id, reset, self._document_id,
1692
+ )
1693
+
1694
+ def shutdown(self) -> None:
1695
+ logger.debug("Hindsight shutdown: stopping writer + waiting for background threads")
1696
+ # Stop accepting new retain jobs first so anyone still calling
1697
+ # sync_turn() during teardown is dropped, not enqueued.
1698
+ self._shutting_down.set()
1699
+ # Drain the writer: it will finish in-flight work, then exit on
1700
+ # the sentinel. Bounded join keeps shutdown predictable even if
1701
+ # the daemon is wedged.
1702
+ writer = self._writer_thread
1703
+ if writer is not None and writer.is_alive():
1704
+ try:
1705
+ self._retain_queue.put(_WRITER_SENTINEL)
1706
+ except Exception:
1707
+ pass
1708
+ writer.join(timeout=10.0)
1709
+ if writer.is_alive():
1710
+ logger.warning(
1711
+ "Hindsight writer did not stop within 10s; "
1712
+ "abandoning %d pending retain(s)",
1713
+ self._retain_queue.qsize(),
1714
+ )
1715
+ if self._prefetch_thread and self._prefetch_thread.is_alive():
1716
+ self._prefetch_thread.join(timeout=5.0)
1717
+ if self._client is not None:
1718
+ try:
1719
+ if self._mode == "local_embedded":
1720
+ # HindsightEmbedded.close() delegates to its sync client.close().
1721
+ # When Hermes created/used that client on the shared async loop,
1722
+ # closing it from this thread can raise "attached to a different
1723
+ # loop" before aiohttp releases the session. Close the embedded
1724
+ # inner async client on the shared loop first, then let the
1725
+ # wrapper clean up daemon/UI bookkeeping.
1726
+ inner_client = getattr(self._client, "_client", None)
1727
+ if inner_client is not None and hasattr(inner_client, "aclose"):
1728
+ _run_sync(inner_client.aclose())
1729
+ try:
1730
+ self._client._client = None
1731
+ except Exception:
1732
+ pass
1733
+ try:
1734
+ self._client.close()
1735
+ except RuntimeError:
1736
+ pass
1737
+ else:
1738
+ self._run_sync(self._client.aclose())
1739
+ except Exception:
1740
+ pass
1741
+ self._client = None
1742
+ # The module-global background event loop (_loop / _loop_thread)
1743
+ # is intentionally NOT stopped here. It is shared across every
1744
+ # HindsightMemoryProvider instance in the process — the plugin
1745
+ # loader creates a new provider per AIAgent, and the gateway
1746
+ # creates one AIAgent per concurrent chat session. Stopping the
1747
+ # loop from one provider's shutdown() strands the aiohttp
1748
+ # ClientSession + TCPConnector owned by every sibling provider
1749
+ # on a dead loop, which surfaces as the "Unclosed client session"
1750
+ # / "Unclosed connector" warnings reported in #11923. The loop
1751
+ # runs on a daemon thread and is reclaimed on process exit;
1752
+ # per-session cleanup happens via self._client.aclose() above.
1753
+
1754
+
1755
+ def register(ctx) -> None:
1756
+ """Register Hindsight as a memory provider plugin."""
1757
+ ctx.register_memory_provider(HindsightMemoryProvider())
1758
+