simplicio-agent 0.25.0__py3-none-any.whl

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 (1148) hide show
  1. acp_adapter/__init__.py +1 -0
  2. acp_adapter/__main__.py +5 -0
  3. acp_adapter/auth.py +79 -0
  4. acp_adapter/edit_approval.py +338 -0
  5. acp_adapter/entry.py +280 -0
  6. acp_adapter/events.py +279 -0
  7. acp_adapter/permissions.py +175 -0
  8. acp_adapter/provenance.py +127 -0
  9. acp_adapter/server.py +2065 -0
  10. acp_adapter/session.py +627 -0
  11. acp_adapter/tools.py +1329 -0
  12. agent/__init__.py +8 -0
  13. agent/_fastjson.py +167 -0
  14. agent/_hermes_fast.py +182 -0
  15. agent/account_usage.py +890 -0
  16. agent/adapter_contract.py +35 -0
  17. agent/adaptive_controller.py +379 -0
  18. agent/agent_init.py +2182 -0
  19. agent/agent_runtime_helpers.py +3375 -0
  20. agent/ai_memory/__init__.py +1 -0
  21. agent/ai_memory/cross_vendor.py +148 -0
  22. agent/algorithms/__init__.py +0 -0
  23. agent/algorithms/addressing.py +223 -0
  24. agent/anthropic_adapter.py +2790 -0
  25. agent/asolaria_pattern_contract.py +477 -0
  26. agent/async_dag/__init__.py +15 -0
  27. agent/async_dag/executor.py +166 -0
  28. agent/async_dag/uvloop_runner.py +169 -0
  29. agent/async_utils.py +68 -0
  30. agent/attention_schema.py +370 -0
  31. agent/autobiographical_memory.py +218 -0
  32. agent/autonomy_policy.py +315 -0
  33. agent/auxiliary_client.py +7905 -0
  34. agent/azure_identity_adapter.py +555 -0
  35. agent/background_review.py +988 -0
  36. agent/backlog_ref/__init__.py +0 -0
  37. agent/backlog_ref/issue_315_self_mod_kernel.py +122 -0
  38. agent/bedrock_adapter.py +1351 -0
  39. agent/belief_state.py +696 -0
  40. agent/benchmark_manifest.py +59 -0
  41. agent/benchmarks/__init__.py +1 -0
  42. agent/benchmarks/e2e_comparison.py +162 -0
  43. agent/billing_view.py +295 -0
  44. agent/bounded_response.py +148 -0
  45. agent/browser_provider.py +187 -0
  46. agent/browser_provider_contract.py +31 -0
  47. agent/browser_registry.py +192 -0
  48. agent/capability_inventory.py +86 -0
  49. agent/capability_registry.py +574 -0
  50. agent/capability_registry_contract.py +553 -0
  51. agent/chat_completion_helpers.py +3429 -0
  52. agent/closed_loop_controller.py +1381 -0
  53. agent/coarse_graining_contract.py +100 -0
  54. agent/codex_responses_adapter.py +1468 -0
  55. agent/codex_runtime.py +954 -0
  56. agent/coding_context.py +892 -0
  57. agent/computer_use_provider_contract.py +34 -0
  58. agent/context/__init__.py +33 -0
  59. agent/context/incremental.py +61 -0
  60. agent/context/retrieval.py +83 -0
  61. agent/context/token_cache.py +104 -0
  62. agent/context/working_set.py +263 -0
  63. agent/context_breakdown.py +156 -0
  64. agent/context_compressor.py +3455 -0
  65. agent/context_engine.py +238 -0
  66. agent/context_references.py +616 -0
  67. agent/conversation_compression.py +1194 -0
  68. agent/conversation_loop.py +5821 -0
  69. agent/copilot_acp_client.py +751 -0
  70. agent/credential_persistence.py +174 -0
  71. agent/credential_pool.py +2461 -0
  72. agent/credential_sources.py +447 -0
  73. agent/credits_tracker.py +794 -0
  74. agent/cron/__init__.py +5 -0
  75. agent/cron/unified_scheduler.py +247 -0
  76. agent/curator.py +2016 -0
  77. agent/curator_backup.py +711 -0
  78. agent/delivery_certificate.py +599 -0
  79. agent/desktop_first_run_contract.py +567 -0
  80. agent/desktop_layout_contract.py +596 -0
  81. agent/desktop_security_contract.py +571 -0
  82. agent/display.py +1464 -0
  83. agent/distributed/__init__.py +53 -0
  84. agent/distributed/protocol.py +271 -0
  85. agent/distribution/__init__.py +6 -0
  86. agent/distribution/manifest.py +36 -0
  87. agent/distribution/publisher.py +121 -0
  88. agent/env_alias.py +97 -0
  89. agent/error_classifier.py +1621 -0
  90. agent/errors.py +9 -0
  91. agent/event_store.py +360 -0
  92. agent/fanout_governor_contract.py +536 -0
  93. agent/file_safety.py +679 -0
  94. agent/gemini_native_adapter.py +1040 -0
  95. agent/gemini_schema.py +99 -0
  96. agent/goal_contract.py +727 -0
  97. agent/golden_path.py +435 -0
  98. agent/host.py +451 -0
  99. agent/hrm_controller_contract.py +687 -0
  100. agent/hyper_bechs/__init__.py +11 -0
  101. agent/hyper_bechs/host8.py +253 -0
  102. agent/hypothesis_ensemble.py +225 -0
  103. agent/i18n.py +302 -0
  104. agent/image_gen_provider.py +393 -0
  105. agent/image_gen_registry.py +145 -0
  106. agent/image_routing.py +765 -0
  107. agent/insights.py +1080 -0
  108. agent/issue_claim_lease.py +454 -0
  109. agent/iteration_budget.py +95 -0
  110. agent/jiter_preload.py +39 -0
  111. agent/jspace_contract.py +416 -0
  112. agent/kanban_stop.py +108 -0
  113. agent/learn_prompt.py +150 -0
  114. agent/learning_graph.py +328 -0
  115. agent/learning_graph_render.py +659 -0
  116. agent/learning_mutations.py +206 -0
  117. agent/lmstudio_reasoning.py +48 -0
  118. agent/lsp/__init__.py +106 -0
  119. agent/lsp/cli.py +299 -0
  120. agent/lsp/client.py +964 -0
  121. agent/lsp/eventlog.py +213 -0
  122. agent/lsp/install.py +406 -0
  123. agent/lsp/manager.py +639 -0
  124. agent/lsp/protocol.py +196 -0
  125. agent/lsp/range_shift.py +149 -0
  126. agent/lsp/reporter.py +130 -0
  127. agent/lsp/servers.py +1187 -0
  128. agent/lsp/workspace.py +223 -0
  129. agent/manual_compression_feedback.py +49 -0
  130. agent/markdown_tables.py +309 -0
  131. agent/mcp_agent_gateway.py +194 -0
  132. agent/mcp_cli_compatibility_contract.py +388 -0
  133. agent/media_goal_contract.py +35 -0
  134. agent/memory_manager.py +1135 -0
  135. agent/memory_provider.py +315 -0
  136. agent/message_content.py +50 -0
  137. agent/message_sanitization.py +477 -0
  138. agent/metacognition_contract.py +87 -0
  139. agent/moa_loop.py +1176 -0
  140. agent/moa_trace.py +167 -0
  141. agent/model_metadata.py +2352 -0
  142. agent/models_dev.py +725 -0
  143. agent/modes/__init__.py +1 -0
  144. agent/modes/provider_mode.py +85 -0
  145. agent/moonshot_schema.py +238 -0
  146. agent/multirate_scheduler.py +441 -0
  147. agent/net/__init__.py +5 -0
  148. agent/net/http_pool.py +143 -0
  149. agent/nous_rate_guard.py +325 -0
  150. agent/onboarding.py +253 -0
  151. agent/oneshot.py +158 -0
  152. agent/operational_awareness_contract.py +66 -0
  153. agent/operational_cycle.py +180 -0
  154. agent/operational_metrics.py +260 -0
  155. agent/operational_now.py +527 -0
  156. agent/operational_self_model.py +508 -0
  157. agent/perception_action_feedback_contract.py +74 -0
  158. agent/perf_probe.py +102 -0
  159. agent/persistent_run.py +425 -0
  160. agent/pet/__init__.py +51 -0
  161. agent/pet/constants.py +167 -0
  162. agent/pet/generate/__init__.py +29 -0
  163. agent/pet/generate/atlas.py +1183 -0
  164. agent/pet/generate/imagegen.py +251 -0
  165. agent/pet/generate/orchestrate.py +358 -0
  166. agent/pet/generate/prompts.py +183 -0
  167. agent/pet/manifest.py +165 -0
  168. agent/pet/render.py +682 -0
  169. agent/pet/state.py +81 -0
  170. agent/pet/store.py +503 -0
  171. agent/plugin_llm.py +1046 -0
  172. agent/plugins/__init__.py +1 -0
  173. agent/plugins/unified_registry.py +121 -0
  174. agent/portal_tags.py +64 -0
  175. agent/possibility_ledger.py +385 -0
  176. agent/prediction_receipts.py +941 -0
  177. agent/process_bootstrap.py +227 -0
  178. agent/profiles/__init__.py +4 -0
  179. agent/profiles/multi_profile.py +91 -0
  180. agent/project_mapper/__init__.py +16 -0
  181. agent/project_mapper/fingerprint.py +264 -0
  182. agent/prompt_builder.py +2021 -0
  183. agent/prompt_caching.py +132 -0
  184. agent/prompt_economy.py +941 -0
  185. agent/prompt_microkernel.py +309 -0
  186. agent/protocol.py +155 -0
  187. agent/protocol_v1.py +1173 -0
  188. agent/provider_mode.py +160 -0
  189. agent/providers/__init__.py +17 -0
  190. agent/providers/fallback_chain.py +202 -0
  191. agent/providers/router.py +96 -0
  192. agent/providers/runtime.py +504 -0
  193. agent/rate_distortion_context.py +550 -0
  194. agent/rate_limit_tracker.py +246 -0
  195. agent/reactions.py +56 -0
  196. agent/reasoning_timeouts.py +224 -0
  197. agent/redact.py +811 -0
  198. agent/registry/__init__.py +16 -0
  199. agent/registry/lazy_schema.py +85 -0
  200. agent/registry/skill_meta.py +95 -0
  201. agent/release_evidence_contract.py +481 -0
  202. agent/release_handoff_contract.py +357 -0
  203. agent/replay_cleanup.py +317 -0
  204. agent/resource_homeostasis.py +598 -0
  205. agent/restart_recovery.py +578 -0
  206. agent/retry_utils.py +154 -0
  207. agent/reversible_path.py +520 -0
  208. agent/router/__init__.py +21 -0
  209. agent/router/cost_aware.py +213 -0
  210. agent/router/deterministic.py +94 -0
  211. agent/router/fallback.py +54 -0
  212. agent/runtime_bridge.py +65 -0
  213. agent/runtime_bundle_contract.py +431 -0
  214. agent/runtime_cwd.py +62 -0
  215. agent/scientific_integrity_gate.py +181 -0
  216. agent/secret_scope.py +205 -0
  217. agent/secret_sources/__init__.py +41 -0
  218. agent/secret_sources/_cache.py +213 -0
  219. agent/secret_sources/base.py +274 -0
  220. agent/secret_sources/bitwarden.py +729 -0
  221. agent/secret_sources/onepassword.py +643 -0
  222. agent/secret_sources/registry.py +370 -0
  223. agent/security/__init__.py +14 -0
  224. agent/security/unified_auth.py +93 -0
  225. agent/self_model.py +399 -0
  226. agent/serde/__init__.py +19 -0
  227. agent/serde/fast_json.py +111 -0
  228. agent/session.py +255 -0
  229. agent/session_repositories.py +126 -0
  230. agent/shannon/__init__.py +21 -0
  231. agent/shannon/pipeline.py +525 -0
  232. agent/shell_hooks.py +928 -0
  233. agent/simplicio_prompt.py +60 -0
  234. agent/skill_bundles.py +438 -0
  235. agent/skill_commands.py +964 -0
  236. agent/skill_preprocessing.py +144 -0
  237. agent/skill_utils.py +829 -0
  238. agent/software_delivery_contract.py +35 -0
  239. agent/ssl_guard.py +94 -0
  240. agent/ssl_verify.py +63 -0
  241. agent/state_migration.py +670 -0
  242. agent/stream_diag.py +280 -0
  243. agent/subdirectory_hints.py +270 -0
  244. agent/supervisor_registry.py +188 -0
  245. agent/support_bundle_contract.py +484 -0
  246. agent/system_prompt.py +682 -0
  247. agent/task_envelope.py +870 -0
  248. agent/task_envelope_bridge.py +144 -0
  249. agent/telemetry/__init__.py +39 -0
  250. agent/telemetry/dashboard.py +137 -0
  251. agent/telemetry/gain_analytics.py +108 -0
  252. agent/telemetry/lane_readiness.py +278 -0
  253. agent/telemetry/mcp_session.py +361 -0
  254. agent/telemetry/receipts.py +248 -0
  255. agent/telemetry/savings_report.py +321 -0
  256. agent/telemetry/stage_timer.py +126 -0
  257. agent/telemetry/token_savings.py +108 -0
  258. agent/telemetry/tool_replay.py +259 -0
  259. agent/telemetry/turn_metrics.py +164 -0
  260. agent/testing/__init__.py +5 -0
  261. agent/testing/unified_harness.py +183 -0
  262. agent/think_scrubber.py +399 -0
  263. agent/thinking_timeout_guidance.py +136 -0
  264. agent/thread_scoped_output.py +147 -0
  265. agent/tier_rate_limiter.py +262 -0
  266. agent/title_generator.py +204 -0
  267. agent/token_economy.py +338 -0
  268. agent/token_governor.py +248 -0
  269. agent/tokens/__init__.py +17 -0
  270. agent/tokens/fast_estimator.py +146 -0
  271. agent/tokens/message_estimator.py +80 -0
  272. agent/tool_call_json.py +76 -0
  273. agent/tool_dispatch_helpers.py +626 -0
  274. agent/tool_executor.py +1873 -0
  275. agent/tool_guardrails.py +475 -0
  276. agent/tool_invocation_pipeline.py +868 -0
  277. agent/tool_result_classification.py +43 -0
  278. agent/toon_boundary.py +137 -0
  279. agent/toon_codec.py +679 -0
  280. agent/trace_upload.py +398 -0
  281. agent/tracing/__init__.py +19 -0
  282. agent/tracing/spans.py +165 -0
  283. agent/trajectory.py +56 -0
  284. agent/trajectory_skill_contract.py +42 -0
  285. agent/transcription_provider.py +193 -0
  286. agent/transcription_registry.py +124 -0
  287. agent/transports/__init__.py +99 -0
  288. agent/transports/anthropic.py +251 -0
  289. agent/transports/base.py +89 -0
  290. agent/transports/bedrock.py +154 -0
  291. agent/transports/chat_completions.py +796 -0
  292. agent/transports/codex.py +499 -0
  293. agent/transports/codex_app_server.py +413 -0
  294. agent/transports/codex_app_server_session.py +1078 -0
  295. agent/transports/codex_event_projector.py +335 -0
  296. agent/transports/hermes_tools_mcp_server.py +261 -0
  297. agent/transports/types.py +174 -0
  298. agent/trust_boundary.py +812 -0
  299. agent/tts_provider.py +274 -0
  300. agent/tts_registry.py +134 -0
  301. agent/turn_context.py +623 -0
  302. agent/turn_engine.py +140 -0
  303. agent/turn_envelope.py +242 -0
  304. agent/turn_finalizer.py +612 -0
  305. agent/turn_prep.py +72 -0
  306. agent/turn_retry_state.py +80 -0
  307. agent/update_rollback_contract.py +387 -0
  308. agent/usage_pricing.py +1042 -0
  309. agent/uvloop_utils.py +40 -0
  310. agent/value_of_information_contract.py +105 -0
  311. agent/verification_evidence.py +655 -0
  312. agent/verification_stop.py +313 -0
  313. agent/verify_hooks.py +69 -0
  314. agent/vertex_adapter.py +228 -0
  315. agent/video_gen_provider.py +590 -0
  316. agent/video_gen_registry.py +133 -0
  317. agent/web_search_provider.py +211 -0
  318. agent/web_search_registry.py +304 -0
  319. batch_runner.py +1323 -0
  320. cli.py +16505 -0
  321. cron/__init__.py +42 -0
  322. cron/blueprint_catalog.py +713 -0
  323. cron/jobs.py +2341 -0
  324. cron/lifecycle_guard.py +141 -0
  325. cron/scheduler.py +3940 -0
  326. cron/scheduler_provider.py +205 -0
  327. cron/scripts/__init__.py +1 -0
  328. cron/scripts/classify_items.py +264 -0
  329. cron/suggestion_catalog.py +154 -0
  330. cron/suggestions.py +260 -0
  331. gateway/__init__.py +35 -0
  332. gateway/assets/status_phrases.yaml +52 -0
  333. gateway/assets/telegram-botfather-threads-settings.jpg +0 -0
  334. gateway/authz_mixin.py +710 -0
  335. gateway/builtin_hooks/__init__.py +1 -0
  336. gateway/cgroup_cleanup.py +81 -0
  337. gateway/channel_directory.py +497 -0
  338. gateway/code_skew.py +64 -0
  339. gateway/config.py +2321 -0
  340. gateway/cwd_placeholder.py +49 -0
  341. gateway/dead_targets.py +143 -0
  342. gateway/delivery.py +742 -0
  343. gateway/display_config.py +277 -0
  344. gateway/drain_control.py +273 -0
  345. gateway/hooks.py +227 -0
  346. gateway/kanban_watchers.py +1286 -0
  347. gateway/memory_monitor.py +230 -0
  348. gateway/message_timestamps.py +166 -0
  349. gateway/mirror.py +206 -0
  350. gateway/native_bridge.py +500 -0
  351. gateway/pairing.py +661 -0
  352. gateway/platform_registry.py +332 -0
  353. gateway/platforms/__init__.py +45 -0
  354. gateway/platforms/_http_client_limits.py +84 -0
  355. gateway/platforms/api_server.py +4641 -0
  356. gateway/platforms/base.py +5735 -0
  357. gateway/platforms/bluebubbles.py +1048 -0
  358. gateway/platforms/helpers.py +403 -0
  359. gateway/platforms/msgraph_webhook.py +441 -0
  360. gateway/platforms/qqbot/__init__.py +91 -0
  361. gateway/platforms/qqbot/adapter.py +3237 -0
  362. gateway/platforms/qqbot/chunked_upload.py +602 -0
  363. gateway/platforms/qqbot/constants.py +74 -0
  364. gateway/platforms/qqbot/crypto.py +45 -0
  365. gateway/platforms/qqbot/keyboards.py +461 -0
  366. gateway/platforms/qqbot/onboard.py +220 -0
  367. gateway/platforms/qqbot/utils.py +70 -0
  368. gateway/platforms/signal.py +1701 -0
  369. gateway/platforms/signal_format.py +140 -0
  370. gateway/platforms/signal_rate_limit.py +369 -0
  371. gateway/platforms/webhook.py +1266 -0
  372. gateway/platforms/webhook_filters.py +302 -0
  373. gateway/platforms/weixin.py +2380 -0
  374. gateway/platforms/whatsapp_cloud.py +2067 -0
  375. gateway/platforms/whatsapp_common.py +510 -0
  376. gateway/platforms/yuanbao.py +5557 -0
  377. gateway/platforms/yuanbao_media.py +665 -0
  378. gateway/platforms/yuanbao_proto.py +1418 -0
  379. gateway/platforms/yuanbao_sticker.py +558 -0
  380. gateway/profile_routing.py +166 -0
  381. gateway/readiness.py +117 -0
  382. gateway/relay/__init__.py +836 -0
  383. gateway/relay/adapter.py +546 -0
  384. gateway/relay/auth.py +168 -0
  385. gateway/relay/descriptor.py +124 -0
  386. gateway/relay/transport.py +143 -0
  387. gateway/relay/ws_transport.py +809 -0
  388. gateway/response_filters.py +106 -0
  389. gateway/restart.py +492 -0
  390. gateway/restart_loop_guard.py +150 -0
  391. gateway/rich_sent_store.py +83 -0
  392. gateway/run.py +21689 -0
  393. gateway/runtime_footer.py +149 -0
  394. gateway/scale_to_zero.py +124 -0
  395. gateway/session.py +2603 -0
  396. gateway/session_context.py +346 -0
  397. gateway/shutdown_forensics.py +462 -0
  398. gateway/slash_access.py +229 -0
  399. gateway/slash_commands.py +4742 -0
  400. gateway/status.py +1554 -0
  401. gateway/status_phrases.py +227 -0
  402. gateway/sticker_cache.py +124 -0
  403. gateway/stream_consumer.py +1964 -0
  404. gateway/stream_dispatch.py +132 -0
  405. gateway/stream_events.py +171 -0
  406. gateway/whatsapp_identity.py +206 -0
  407. hermes_bootstrap.py +195 -0
  408. hermes_cli/__init__.py +105 -0
  409. hermes_cli/_parser.py +452 -0
  410. hermes_cli/_subprocess_compat.py +234 -0
  411. hermes_cli/active_sessions.py +357 -0
  412. hermes_cli/auth.py +8411 -0
  413. hermes_cli/auth_commands.py +780 -0
  414. hermes_cli/azure_detect.py +408 -0
  415. hermes_cli/backup.py +1376 -0
  416. hermes_cli/banner.py +742 -0
  417. hermes_cli/blueprint_cmd.py +318 -0
  418. hermes_cli/browser_connect.py +349 -0
  419. hermes_cli/build_info.py +51 -0
  420. hermes_cli/bundles.py +229 -0
  421. hermes_cli/callbacks.py +242 -0
  422. hermes_cli/checkpoints.py +244 -0
  423. hermes_cli/claw.py +809 -0
  424. hermes_cli/cli_agent_setup_mixin.py +690 -0
  425. hermes_cli/cli_commands_mixin.py +2738 -0
  426. hermes_cli/cli_output.py +77 -0
  427. hermes_cli/clipboard.py +494 -0
  428. hermes_cli/codex_models.py +220 -0
  429. hermes_cli/codex_runtime_plugin_migration.py +766 -0
  430. hermes_cli/codex_runtime_switch.py +288 -0
  431. hermes_cli/colors.py +38 -0
  432. hermes_cli/commands.py +2148 -0
  433. hermes_cli/completion.py +319 -0
  434. hermes_cli/config.py +7866 -0
  435. hermes_cli/console_engine.py +1876 -0
  436. hermes_cli/container_boot.py +576 -0
  437. hermes_cli/context_switch_guard.py +169 -0
  438. hermes_cli/copilot_auth.py +458 -0
  439. hermes_cli/cron.py +481 -0
  440. hermes_cli/curator.py +698 -0
  441. hermes_cli/curses_ui.py +872 -0
  442. hermes_cli/daemon.py +466 -0
  443. hermes_cli/dashboard_auth/__init__.py +48 -0
  444. hermes_cli/dashboard_auth/audit.py +89 -0
  445. hermes_cli/dashboard_auth/base.py +306 -0
  446. hermes_cli/dashboard_auth/cookies.py +338 -0
  447. hermes_cli/dashboard_auth/login_page.py +534 -0
  448. hermes_cli/dashboard_auth/middleware.py +516 -0
  449. hermes_cli/dashboard_auth/prefix.py +232 -0
  450. hermes_cli/dashboard_auth/public_paths.py +55 -0
  451. hermes_cli/dashboard_auth/registry.py +81 -0
  452. hermes_cli/dashboard_auth/routes.py +644 -0
  453. hermes_cli/dashboard_auth/token_auth.py +194 -0
  454. hermes_cli/dashboard_auth/ws_tickets.py +161 -0
  455. hermes_cli/dashboard_register.py +427 -0
  456. hermes_cli/debug.py +1017 -0
  457. hermes_cli/default_soul.py +161 -0
  458. hermes_cli/dep_ensure.py +163 -0
  459. hermes_cli/diagnostics_upload.py +138 -0
  460. hermes_cli/dingtalk_auth.py +291 -0
  461. hermes_cli/doctor.py +3156 -0
  462. hermes_cli/dump.py +444 -0
  463. hermes_cli/env_loader.py +403 -0
  464. hermes_cli/fallback_cmd.py +354 -0
  465. hermes_cli/fallback_config.py +135 -0
  466. hermes_cli/gateway.py +6847 -0
  467. hermes_cli/gateway_enroll.py +277 -0
  468. hermes_cli/gateway_windows.py +1682 -0
  469. hermes_cli/goals.py +1749 -0
  470. hermes_cli/gui_uninstall.py +285 -0
  471. hermes_cli/hooks.py +394 -0
  472. hermes_cli/input_sanitize.py +70 -0
  473. hermes_cli/inventory.py +627 -0
  474. hermes_cli/journey.py +357 -0
  475. hermes_cli/kanban.py +2845 -0
  476. hermes_cli/kanban_db.py +9135 -0
  477. hermes_cli/kanban_decompose.py +468 -0
  478. hermes_cli/kanban_diagnostics.py +1133 -0
  479. hermes_cli/kanban_specify.py +264 -0
  480. hermes_cli/kanban_swarm.py +278 -0
  481. hermes_cli/local_change_staging.py +574 -0
  482. hermes_cli/logs.py +397 -0
  483. hermes_cli/main.py +13832 -0
  484. hermes_cli/managed_scope.py +214 -0
  485. hermes_cli/managed_uv.py +254 -0
  486. hermes_cli/mcp_catalog.py +796 -0
  487. hermes_cli/mcp_config.py +1104 -0
  488. hermes_cli/mcp_picker.py +322 -0
  489. hermes_cli/mcp_security.py +181 -0
  490. hermes_cli/mcp_startup.py +130 -0
  491. hermes_cli/memory_oauth.py +83 -0
  492. hermes_cli/memory_providers.py +149 -0
  493. hermes_cli/memory_setup.py +518 -0
  494. hermes_cli/middleware.py +313 -0
  495. hermes_cli/migrate.py +115 -0
  496. hermes_cli/moa_cmd.py +141 -0
  497. hermes_cli/moa_config.py +367 -0
  498. hermes_cli/model_catalog.py +430 -0
  499. hermes_cli/model_cost_guard.py +134 -0
  500. hermes_cli/model_normalize.py +473 -0
  501. hermes_cli/model_setup_flows.py +3063 -0
  502. hermes_cli/model_switch.py +2498 -0
  503. hermes_cli/models.py +4210 -0
  504. hermes_cli/nous_account.py +789 -0
  505. hermes_cli/nous_auth_keepalive.py +189 -0
  506. hermes_cli/nous_billing.py +406 -0
  507. hermes_cli/nous_subscription.py +1285 -0
  508. hermes_cli/onepassword_secrets_cli.py +432 -0
  509. hermes_cli/oneshot.py +440 -0
  510. hermes_cli/pairing.py +115 -0
  511. hermes_cli/partial_compress.py +324 -0
  512. hermes_cli/pets.py +502 -0
  513. hermes_cli/platforms.py +84 -0
  514. hermes_cli/plugins.py +2466 -0
  515. hermes_cli/plugins_cmd.py +2017 -0
  516. hermes_cli/portal_cli.py +245 -0
  517. hermes_cli/profile_describer.py +288 -0
  518. hermes_cli/profile_distribution.py +726 -0
  519. hermes_cli/profiles.py +2238 -0
  520. hermes_cli/projects_cmd.py +335 -0
  521. hermes_cli/projects_db.py +727 -0
  522. hermes_cli/prompt_size.py +161 -0
  523. hermes_cli/provider_catalog.py +181 -0
  524. hermes_cli/providers.py +789 -0
  525. hermes_cli/proxy/__init__.py +20 -0
  526. hermes_cli/proxy/adapters/__init__.py +37 -0
  527. hermes_cli/proxy/adapters/base.py +108 -0
  528. hermes_cli/proxy/adapters/nous_portal.py +199 -0
  529. hermes_cli/proxy/adapters/xai.py +145 -0
  530. hermes_cli/proxy/cli.py +141 -0
  531. hermes_cli/proxy/server.py +304 -0
  532. hermes_cli/psutil_android.py +108 -0
  533. hermes_cli/pt_input_extras.py +120 -0
  534. hermes_cli/pty_bridge.py +286 -0
  535. hermes_cli/pty_session.py +195 -0
  536. hermes_cli/relaunch.py +205 -0
  537. hermes_cli/runtime_mcp_matrix.py +466 -0
  538. hermes_cli/runtime_provider.py +2097 -0
  539. hermes_cli/secret_prompt.py +126 -0
  540. hermes_cli/secrets_cli.py +600 -0
  541. hermes_cli/security_advisories.py +453 -0
  542. hermes_cli/security_audit.py +576 -0
  543. hermes_cli/security_audit_startup.py +282 -0
  544. hermes_cli/send_cmd.py +471 -0
  545. hermes_cli/service_manager.py +1123 -0
  546. hermes_cli/session_export.py +317 -0
  547. hermes_cli/session_export_html.py +871 -0
  548. hermes_cli/session_export_md.py +279 -0
  549. hermes_cli/session_filters.py +208 -0
  550. hermes_cli/session_listing.py +113 -0
  551. hermes_cli/session_recap.py +316 -0
  552. hermes_cli/setup.py +3405 -0
  553. hermes_cli/setup_whatsapp_cloud.py +541 -0
  554. hermes_cli/skills_config.py +202 -0
  555. hermes_cli/skills_hub.py +2013 -0
  556. hermes_cli/skin_engine.py +926 -0
  557. hermes_cli/slack_cli.py +224 -0
  558. hermes_cli/sqlite_util.py +49 -0
  559. hermes_cli/staging_activation.py +601 -0
  560. hermes_cli/status.py +622 -0
  561. hermes_cli/stdio.py +251 -0
  562. hermes_cli/subcommands/__init__.py +18 -0
  563. hermes_cli/subcommands/_shared.py +29 -0
  564. hermes_cli/subcommands/acp.py +52 -0
  565. hermes_cli/subcommands/auth.py +98 -0
  566. hermes_cli/subcommands/backup.py +38 -0
  567. hermes_cli/subcommands/claw.py +92 -0
  568. hermes_cli/subcommands/config.py +49 -0
  569. hermes_cli/subcommands/console.py +18 -0
  570. hermes_cli/subcommands/cron.py +163 -0
  571. hermes_cli/subcommands/daemon.py +67 -0
  572. hermes_cli/subcommands/dashboard.py +200 -0
  573. hermes_cli/subcommands/debug.py +100 -0
  574. hermes_cli/subcommands/doctor.py +35 -0
  575. hermes_cli/subcommands/dump.py +28 -0
  576. hermes_cli/subcommands/gateway.py +345 -0
  577. hermes_cli/subcommands/gui.py +63 -0
  578. hermes_cli/subcommands/hooks.py +77 -0
  579. hermes_cli/subcommands/import_cmd.py +31 -0
  580. hermes_cli/subcommands/insights.py +25 -0
  581. hermes_cli/subcommands/login.py +78 -0
  582. hermes_cli/subcommands/logout.py +28 -0
  583. hermes_cli/subcommands/logs.py +78 -0
  584. hermes_cli/subcommands/mcp.py +126 -0
  585. hermes_cli/subcommands/memory.py +53 -0
  586. hermes_cli/subcommands/model.py +62 -0
  587. hermes_cli/subcommands/pairing.py +36 -0
  588. hermes_cli/subcommands/plugins.py +106 -0
  589. hermes_cli/subcommands/postinstall.py +23 -0
  590. hermes_cli/subcommands/profile.py +203 -0
  591. hermes_cli/subcommands/prompt_size.py +36 -0
  592. hermes_cli/subcommands/report.py +50 -0
  593. hermes_cli/subcommands/security.py +62 -0
  594. hermes_cli/subcommands/setup.py +58 -0
  595. hermes_cli/subcommands/skills.py +315 -0
  596. hermes_cli/subcommands/slack.py +77 -0
  597. hermes_cli/subcommands/status.py +28 -0
  598. hermes_cli/subcommands/tools.py +95 -0
  599. hermes_cli/subcommands/uninstall.py +46 -0
  600. hermes_cli/subcommands/update.py +76 -0
  601. hermes_cli/subcommands/version.py +18 -0
  602. hermes_cli/subcommands/webhook.py +83 -0
  603. hermes_cli/subcommands/whatsapp.py +22 -0
  604. hermes_cli/suggestions_cmd.py +153 -0
  605. hermes_cli/telegram_managed_bot.py +358 -0
  606. hermes_cli/timeouts.py +82 -0
  607. hermes_cli/tips.py +485 -0
  608. hermes_cli/tools_config.py +4521 -0
  609. hermes_cli/toolset_validation.py +74 -0
  610. hermes_cli/transactional_updater.py +453 -0
  611. hermes_cli/uninstall.py +962 -0
  612. hermes_cli/update_contract.py +1011 -0
  613. hermes_cli/update_preflight.py +389 -0
  614. hermes_cli/urllib_security.py +139 -0
  615. hermes_cli/voice.py +846 -0
  616. hermes_cli/web_git.py +697 -0
  617. hermes_cli/web_server.py +14270 -0
  618. hermes_cli/webhook.py +306 -0
  619. hermes_cli/win_pty_bridge.py +179 -0
  620. hermes_cli/write_approval_commands.py +209 -0
  621. hermes_cli/xai_retirement.py +256 -0
  622. hermes_constants.py +1333 -0
  623. hermes_logging.py +791 -0
  624. hermes_state.py +7369 -0
  625. hermes_time.py +135 -0
  626. mcp_serve.py +1680 -0
  627. model_tools.py +1410 -0
  628. plugins/__init__.py +1 -0
  629. plugins/browser/browser_use/__init__.py +14 -0
  630. plugins/browser/browser_use/plugin.yaml +7 -0
  631. plugins/browser/browser_use/provider.py +317 -0
  632. plugins/browser/browserbase/__init__.py +15 -0
  633. plugins/browser/browserbase/plugin.yaml +7 -0
  634. plugins/browser/browserbase/provider.py +301 -0
  635. plugins/browser/firecrawl/__init__.py +16 -0
  636. plugins/browser/firecrawl/plugin.yaml +7 -0
  637. plugins/browser/firecrawl/provider.py +171 -0
  638. plugins/context_engine/__init__.py +285 -0
  639. plugins/cron_providers/__init__.py +356 -0
  640. plugins/cron_providers/chronos/__init__.py +241 -0
  641. plugins/cron_providers/chronos/_nas_client.py +123 -0
  642. plugins/cron_providers/chronos/plugin.yaml +9 -0
  643. plugins/cron_providers/chronos/verify.py +145 -0
  644. plugins/dashboard_auth/basic/__init__.py +491 -0
  645. plugins/dashboard_auth/basic/plugin.yaml +7 -0
  646. plugins/dashboard_auth/drain/__init__.py +291 -0
  647. plugins/dashboard_auth/drain/plugin.yaml +7 -0
  648. plugins/dashboard_auth/nous/__init__.py +667 -0
  649. plugins/dashboard_auth/nous/plugin.yaml +7 -0
  650. plugins/dashboard_auth/self_hosted/__init__.py +858 -0
  651. plugins/dashboard_auth/self_hosted/plugin.yaml +8 -0
  652. plugins/disk-cleanup/README.md +51 -0
  653. plugins/disk-cleanup/__init__.py +316 -0
  654. plugins/disk-cleanup/disk_cleanup.py +588 -0
  655. plugins/disk-cleanup/plugin.yaml +7 -0
  656. plugins/google_meet/README.md +131 -0
  657. plugins/google_meet/__init__.py +103 -0
  658. plugins/google_meet/audio_bridge.py +248 -0
  659. plugins/google_meet/cli.py +476 -0
  660. plugins/google_meet/meet_bot.py +858 -0
  661. plugins/google_meet/node/__init__.py +54 -0
  662. plugins/google_meet/node/cli.py +134 -0
  663. plugins/google_meet/node/client.py +107 -0
  664. plugins/google_meet/node/protocol.py +124 -0
  665. plugins/google_meet/node/registry.py +112 -0
  666. plugins/google_meet/node/server.py +200 -0
  667. plugins/google_meet/plugin.yaml +16 -0
  668. plugins/google_meet/process_manager.py +323 -0
  669. plugins/google_meet/realtime/__init__.py +10 -0
  670. plugins/google_meet/realtime/openai_client.py +332 -0
  671. plugins/google_meet/tools.py +348 -0
  672. plugins/hermes-achievements/README.md +150 -0
  673. plugins/hermes-achievements/dashboard/dist/index.js +726 -0
  674. plugins/hermes-achievements/dashboard/dist/style.css +146 -0
  675. plugins/hermes-achievements/dashboard/manifest.json +11 -0
  676. plugins/hermes-achievements/dashboard/plugin_api.py +1061 -0
  677. plugins/hermes-achievements/tests/test_achievement_engine.py +156 -0
  678. plugins/image_gen/deepinfra/__init__.py +335 -0
  679. plugins/image_gen/deepinfra/plugin.yaml +7 -0
  680. plugins/image_gen/fal/__init__.py +211 -0
  681. plugins/image_gen/fal/plugin.yaml +7 -0
  682. plugins/image_gen/krea/__init__.py +743 -0
  683. plugins/image_gen/krea/plugin.yaml +7 -0
  684. plugins/image_gen/openai/__init__.py +417 -0
  685. plugins/image_gen/openai/plugin.yaml +7 -0
  686. plugins/image_gen/openai-codex/__init__.py +641 -0
  687. plugins/image_gen/openai-codex/plugin.yaml +5 -0
  688. plugins/image_gen/openrouter/__init__.py +529 -0
  689. plugins/image_gen/openrouter/plugin.yaml +7 -0
  690. plugins/image_gen/xai/__init__.py +494 -0
  691. plugins/image_gen/xai/plugin.yaml +7 -0
  692. plugins/kanban/dashboard/dist/index.js +4108 -0
  693. plugins/kanban/dashboard/dist/style.css +1592 -0
  694. plugins/kanban/dashboard/manifest.json +14 -0
  695. plugins/kanban/dashboard/plugin_api.py +2499 -0
  696. plugins/memory/__init__.py +461 -0
  697. plugins/memory/byterover/README.md +41 -0
  698. plugins/memory/byterover/__init__.py +449 -0
  699. plugins/memory/byterover/plugin.yaml +9 -0
  700. plugins/memory/hindsight/README.md +147 -0
  701. plugins/memory/hindsight/__init__.py +1968 -0
  702. plugins/memory/hindsight/plugin.yaml +8 -0
  703. plugins/memory/holographic/README.md +36 -0
  704. plugins/memory/holographic/__init__.py +419 -0
  705. plugins/memory/holographic/holographic.py +203 -0
  706. plugins/memory/holographic/plugin.yaml +5 -0
  707. plugins/memory/holographic/retrieval.py +654 -0
  708. plugins/memory/holographic/store.py +644 -0
  709. plugins/memory/honcho/README.md +388 -0
  710. plugins/memory/honcho/__init__.py +1432 -0
  711. plugins/memory/honcho/cli.py +1868 -0
  712. plugins/memory/honcho/client.py +920 -0
  713. plugins/memory/honcho/oauth.py +371 -0
  714. plugins/memory/honcho/oauth_flow.py +431 -0
  715. plugins/memory/honcho/plugin.yaml +7 -0
  716. plugins/memory/honcho/session.py +1344 -0
  717. plugins/memory/mem0/README.md +187 -0
  718. plugins/memory/mem0/__init__.py +627 -0
  719. plugins/memory/mem0/_backend.py +298 -0
  720. plugins/memory/mem0/_oss_providers.py +84 -0
  721. plugins/memory/mem0/_setup.py +981 -0
  722. plugins/memory/mem0/plugin.yaml +5 -0
  723. plugins/memory/openviking/README.md +83 -0
  724. plugins/memory/openviking/__init__.py +3725 -0
  725. plugins/memory/openviking/plugin.yaml +8 -0
  726. plugins/memory/retaindb/README.md +40 -0
  727. plugins/memory/retaindb/__init__.py +771 -0
  728. plugins/memory/retaindb/plugin.yaml +7 -0
  729. plugins/memory/supermemory/README.md +111 -0
  730. plugins/memory/supermemory/__init__.py +1021 -0
  731. plugins/memory/supermemory/plugin.yaml +5 -0
  732. plugins/model-providers/README.md +70 -0
  733. plugins/model-providers/alibaba/__init__.py +13 -0
  734. plugins/model-providers/alibaba/plugin.yaml +5 -0
  735. plugins/model-providers/alibaba-coding-plan/__init__.py +21 -0
  736. plugins/model-providers/alibaba-coding-plan/plugin.yaml +5 -0
  737. plugins/model-providers/anthropic/__init__.py +54 -0
  738. plugins/model-providers/anthropic/plugin.yaml +5 -0
  739. plugins/model-providers/arcee/__init__.py +13 -0
  740. plugins/model-providers/arcee/plugin.yaml +5 -0
  741. plugins/model-providers/azure-foundry/__init__.py +21 -0
  742. plugins/model-providers/azure-foundry/plugin.yaml +5 -0
  743. plugins/model-providers/bedrock/__init__.py +30 -0
  744. plugins/model-providers/bedrock/plugin.yaml +5 -0
  745. plugins/model-providers/copilot/__init__.py +58 -0
  746. plugins/model-providers/copilot/plugin.yaml +5 -0
  747. plugins/model-providers/copilot-acp/__init__.py +35 -0
  748. plugins/model-providers/copilot-acp/plugin.yaml +5 -0
  749. plugins/model-providers/custom/__init__.py +103 -0
  750. plugins/model-providers/custom/plugin.yaml +5 -0
  751. plugins/model-providers/deepinfra/__init__.py +81 -0
  752. plugins/model-providers/deepinfra/plugin.yaml +5 -0
  753. plugins/model-providers/deepseek/__init__.py +100 -0
  754. plugins/model-providers/deepseek/plugin.yaml +5 -0
  755. plugins/model-providers/fireworks/__init__.py +36 -0
  756. plugins/model-providers/fireworks/plugin.yaml +5 -0
  757. plugins/model-providers/gemini/__init__.py +61 -0
  758. plugins/model-providers/gemini/plugin.yaml +5 -0
  759. plugins/model-providers/gmi/__init__.py +31 -0
  760. plugins/model-providers/gmi/plugin.yaml +5 -0
  761. plugins/model-providers/huggingface/__init__.py +20 -0
  762. plugins/model-providers/huggingface/plugin.yaml +5 -0
  763. plugins/model-providers/kilocode/__init__.py +14 -0
  764. plugins/model-providers/kilocode/plugin.yaml +5 -0
  765. plugins/model-providers/kimi-coding/__init__.py +80 -0
  766. plugins/model-providers/kimi-coding/plugin.yaml +5 -0
  767. plugins/model-providers/minimax/__init__.py +97 -0
  768. plugins/model-providers/minimax/plugin.yaml +5 -0
  769. plugins/model-providers/nous/__init__.py +58 -0
  770. plugins/model-providers/nous/plugin.yaml +5 -0
  771. plugins/model-providers/novita/__init__.py +27 -0
  772. plugins/model-providers/novita/plugin.yaml +5 -0
  773. plugins/model-providers/nvidia/__init__.py +21 -0
  774. plugins/model-providers/nvidia/plugin.yaml +5 -0
  775. plugins/model-providers/ollama-cloud/__init__.py +73 -0
  776. plugins/model-providers/ollama-cloud/plugin.yaml +5 -0
  777. plugins/model-providers/openai-codex/__init__.py +15 -0
  778. plugins/model-providers/openai-codex/plugin.yaml +5 -0
  779. plugins/model-providers/opencode-zen/__init__.py +147 -0
  780. plugins/model-providers/opencode-zen/plugin.yaml +5 -0
  781. plugins/model-providers/openrouter/__init__.py +188 -0
  782. plugins/model-providers/openrouter/plugin.yaml +5 -0
  783. plugins/model-providers/qwen-oauth/__init__.py +108 -0
  784. plugins/model-providers/qwen-oauth/plugin.yaml +5 -0
  785. plugins/model-providers/stepfun/__init__.py +14 -0
  786. plugins/model-providers/stepfun/plugin.yaml +5 -0
  787. plugins/model-providers/upstage/__init__.py +115 -0
  788. plugins/model-providers/upstage/plugin.yaml +5 -0
  789. plugins/model-providers/vertex/__init__.py +75 -0
  790. plugins/model-providers/vertex/plugin.yaml +5 -0
  791. plugins/model-providers/xai/__init__.py +15 -0
  792. plugins/model-providers/xai/plugin.yaml +5 -0
  793. plugins/model-providers/xiaomi/__init__.py +16 -0
  794. plugins/model-providers/xiaomi/plugin.yaml +5 -0
  795. plugins/model-providers/zai/__init__.py +127 -0
  796. plugins/model-providers/zai/plugin.yaml +5 -0
  797. plugins/observability/langfuse/README.md +53 -0
  798. plugins/observability/langfuse/__init__.py +1137 -0
  799. plugins/observability/langfuse/plugin.yaml +14 -0
  800. plugins/observability/nemo_relay/README.md +559 -0
  801. plugins/observability/nemo_relay/__init__.py +1238 -0
  802. plugins/observability/nemo_relay/plugin.yaml +20 -0
  803. plugins/platforms/dingtalk/__init__.py +3 -0
  804. plugins/platforms/dingtalk/adapter.py +1707 -0
  805. plugins/platforms/dingtalk/plugin.yaml +39 -0
  806. plugins/platforms/discord/__init__.py +3 -0
  807. plugins/platforms/discord/adapter.py +7805 -0
  808. plugins/platforms/discord/plugin.yaml +34 -0
  809. plugins/platforms/discord/voice_mixer.py +379 -0
  810. plugins/platforms/email/__init__.py +3 -0
  811. plugins/platforms/email/adapter.py +1273 -0
  812. plugins/platforms/email/plugin.yaml +39 -0
  813. plugins/platforms/feishu/__init__.py +3 -0
  814. plugins/platforms/feishu/adapter.py +5673 -0
  815. plugins/platforms/feishu/feishu_comment.py +1382 -0
  816. plugins/platforms/feishu/feishu_comment_rules.py +429 -0
  817. plugins/platforms/feishu/feishu_meeting_invite.py +212 -0
  818. plugins/platforms/feishu/plugin.yaml +44 -0
  819. plugins/platforms/google_chat/__init__.py +3 -0
  820. plugins/platforms/google_chat/adapter.py +3348 -0
  821. plugins/platforms/google_chat/oauth.py +668 -0
  822. plugins/platforms/google_chat/plugin.yaml +39 -0
  823. plugins/platforms/homeassistant/__init__.py +3 -0
  824. plugins/platforms/homeassistant/adapter.py +577 -0
  825. plugins/platforms/homeassistant/plugin.yaml +22 -0
  826. plugins/platforms/irc/__init__.py +3 -0
  827. plugins/platforms/irc/adapter.py +971 -0
  828. plugins/platforms/irc/plugin.yaml +54 -0
  829. plugins/platforms/line/__init__.py +3 -0
  830. plugins/platforms/line/adapter.py +1652 -0
  831. plugins/platforms/line/plugin.yaml +65 -0
  832. plugins/platforms/matrix/__init__.py +3 -0
  833. plugins/platforms/matrix/adapter.py +4623 -0
  834. plugins/platforms/matrix/plugin.yaml +41 -0
  835. plugins/platforms/mattermost/__init__.py +3 -0
  836. plugins/platforms/mattermost/adapter.py +1281 -0
  837. plugins/platforms/mattermost/plugin.yaml +49 -0
  838. plugins/platforms/ntfy/__init__.py +3 -0
  839. plugins/platforms/ntfy/adapter.py +593 -0
  840. plugins/platforms/ntfy/plugin.yaml +56 -0
  841. plugins/platforms/photon/README.md +190 -0
  842. plugins/platforms/photon/__init__.py +4 -0
  843. plugins/platforms/photon/adapter.py +1795 -0
  844. plugins/platforms/photon/auth.py +1046 -0
  845. plugins/platforms/photon/cli.py +440 -0
  846. plugins/platforms/photon/plugin.yaml +88 -0
  847. plugins/platforms/photon/sidecar/README.md +52 -0
  848. plugins/platforms/raft/__init__.py +3 -0
  849. plugins/platforms/raft/adapter.py +850 -0
  850. plugins/platforms/raft/plugin.yaml +19 -0
  851. plugins/platforms/simplex/__init__.py +3 -0
  852. plugins/platforms/simplex/adapter.py +1313 -0
  853. plugins/platforms/simplex/plugin.yaml +56 -0
  854. plugins/platforms/slack/__init__.py +3 -0
  855. plugins/platforms/slack/adapter.py +5148 -0
  856. plugins/platforms/slack/block_kit.py +512 -0
  857. plugins/platforms/slack/plugin.yaml +39 -0
  858. plugins/platforms/sms/__init__.py +3 -0
  859. plugins/platforms/sms/adapter.py +510 -0
  860. plugins/platforms/sms/plugin.yaml +32 -0
  861. plugins/platforms/teams/__init__.py +3 -0
  862. plugins/platforms/teams/adapter.py +1448 -0
  863. plugins/platforms/teams/plugin.yaml +48 -0
  864. plugins/platforms/telegram/__init__.py +3 -0
  865. plugins/platforms/telegram/adapter.py +9108 -0
  866. plugins/platforms/telegram/plugin.yaml +35 -0
  867. plugins/platforms/telegram/telegram_ids.py +51 -0
  868. plugins/platforms/telegram/telegram_network.py +269 -0
  869. plugins/platforms/wecom/__init__.py +3 -0
  870. plugins/platforms/wecom/adapter.py +1889 -0
  871. plugins/platforms/wecom/callback_adapter.py +444 -0
  872. plugins/platforms/wecom/plugin.yaml +52 -0
  873. plugins/platforms/wecom/wecom_crypto.py +142 -0
  874. plugins/platforms/whatsapp/__init__.py +3 -0
  875. plugins/platforms/whatsapp/adapter.py +1795 -0
  876. plugins/platforms/whatsapp/plugin.yaml +33 -0
  877. plugins/plugin_utils.py +135 -0
  878. plugins/security-guidance/README.md +88 -0
  879. plugins/security-guidance/__init__.py +259 -0
  880. plugins/security-guidance/patterns.py +368 -0
  881. plugins/security-guidance/plugin.yaml +7 -0
  882. plugins/simplicio/__init__.py +245 -0
  883. plugins/simplicio/plugin.yaml +9 -0
  884. plugins/simplicio/skill_recall.py +233 -0
  885. plugins/spotify/__init__.py +66 -0
  886. plugins/spotify/client.py +435 -0
  887. plugins/spotify/plugin.yaml +13 -0
  888. plugins/spotify/tools.py +454 -0
  889. plugins/teams_pipeline/__init__.py +23 -0
  890. plugins/teams_pipeline/cli.py +470 -0
  891. plugins/teams_pipeline/meetings.py +333 -0
  892. plugins/teams_pipeline/models.py +350 -0
  893. plugins/teams_pipeline/pipeline.py +699 -0
  894. plugins/teams_pipeline/plugin.yaml +9 -0
  895. plugins/teams_pipeline/runtime.py +135 -0
  896. plugins/teams_pipeline/store.py +193 -0
  897. plugins/teams_pipeline/subscriptions.py +249 -0
  898. plugins/token_saver/__init__.py +42 -0
  899. plugins/token_saver/plugin.yaml +7 -0
  900. plugins/token_saver/token_saver.py +228 -0
  901. plugins/video_gen/deepinfra/__init__.py +90 -0
  902. plugins/video_gen/deepinfra/plugin.yaml +7 -0
  903. plugins/video_gen/fal/__init__.py +620 -0
  904. plugins/video_gen/fal/plugin.yaml +7 -0
  905. plugins/video_gen/xai/__init__.py +925 -0
  906. plugins/video_gen/xai/plugin.yaml +7 -0
  907. plugins/web/__init__.py +7 -0
  908. plugins/web/brave_free/__init__.py +14 -0
  909. plugins/web/brave_free/plugin.yaml +7 -0
  910. plugins/web/brave_free/provider.py +141 -0
  911. plugins/web/ddgs/__init__.py +15 -0
  912. plugins/web/ddgs/plugin.yaml +7 -0
  913. plugins/web/ddgs/provider.py +158 -0
  914. plugins/web/exa/__init__.py +15 -0
  915. plugins/web/exa/plugin.yaml +7 -0
  916. plugins/web/exa/provider.py +216 -0
  917. plugins/web/firecrawl/__init__.py +28 -0
  918. plugins/web/firecrawl/plugin.yaml +7 -0
  919. plugins/web/firecrawl/provider.py +617 -0
  920. plugins/web/parallel/__init__.py +16 -0
  921. plugins/web/parallel/plugin.yaml +7 -0
  922. plugins/web/parallel/provider.py +297 -0
  923. plugins/web/searxng/__init__.py +15 -0
  924. plugins/web/searxng/plugin.yaml +7 -0
  925. plugins/web/searxng/provider.py +153 -0
  926. plugins/web/tavily/__init__.py +10 -0
  927. plugins/web/tavily/plugin.yaml +7 -0
  928. plugins/web/tavily/provider.py +224 -0
  929. plugins/web/xai/__init__.py +14 -0
  930. plugins/web/xai/plugin.yaml +7 -0
  931. plugins/web/xai/provider.py +557 -0
  932. providers/__init__.py +191 -0
  933. providers/base.py +232 -0
  934. run_agent.py +5734 -0
  935. simplicio_agent/__init__.py +44 -0
  936. simplicio_agent/__init__.pyi +10 -0
  937. simplicio_agent/__main__.py +12 -0
  938. simplicio_agent/asolaria.py +158 -0
  939. simplicio_agent/attention_schema.py +88 -0
  940. simplicio_agent/compat.py +39 -0
  941. simplicio_agent/compat.pyi +6 -0
  942. simplicio_agent/entry.py +15 -0
  943. simplicio_agent/product_identity.py +39 -0
  944. simplicio_agent/public_contract.py +85 -0
  945. simplicio_agent/py.typed +1 -0
  946. simplicio_agent-0.25.0.data/data/locales/af.yaml +408 -0
  947. simplicio_agent-0.25.0.data/data/locales/de.yaml +408 -0
  948. simplicio_agent-0.25.0.data/data/locales/en.yaml +420 -0
  949. simplicio_agent-0.25.0.data/data/locales/es.yaml +405 -0
  950. simplicio_agent-0.25.0.data/data/locales/fr.yaml +408 -0
  951. simplicio_agent-0.25.0.data/data/locales/ga.yaml +412 -0
  952. simplicio_agent-0.25.0.data/data/locales/hu.yaml +408 -0
  953. simplicio_agent-0.25.0.data/data/locales/it.yaml +408 -0
  954. simplicio_agent-0.25.0.data/data/locales/ja.yaml +408 -0
  955. simplicio_agent-0.25.0.data/data/locales/ko.yaml +408 -0
  956. simplicio_agent-0.25.0.data/data/locales/pt.yaml +408 -0
  957. simplicio_agent-0.25.0.data/data/locales/ru.yaml +408 -0
  958. simplicio_agent-0.25.0.data/data/locales/tr.yaml +408 -0
  959. simplicio_agent-0.25.0.data/data/locales/uk.yaml +408 -0
  960. simplicio_agent-0.25.0.data/data/locales/zh-hant.yaml +408 -0
  961. simplicio_agent-0.25.0.data/data/locales/zh.yaml +408 -0
  962. simplicio_agent-0.25.0.data/data/optional-mcps/linear/manifest.yaml +38 -0
  963. simplicio_agent-0.25.0.data/data/optional-mcps/n8n/manifest.yaml +81 -0
  964. simplicio_agent-0.25.0.data/data/runtime/runtime.lock +22 -0
  965. simplicio_agent-0.25.0.dist-info/METADATA +458 -0
  966. simplicio_agent-0.25.0.dist-info/RECORD +1148 -0
  967. simplicio_agent-0.25.0.dist-info/WHEEL +5 -0
  968. simplicio_agent-0.25.0.dist-info/entry_points.txt +6 -0
  969. simplicio_agent-0.25.0.dist-info/licenses/LICENSE +21 -0
  970. simplicio_agent-0.25.0.dist-info/top_level.txt +24 -0
  971. tools/__init__.py +25 -0
  972. tools/_fastjson.py +142 -0
  973. tools/alias_registry.py +490 -0
  974. tools/ansi_strip.py +44 -0
  975. tools/approval.py +3436 -0
  976. tools/async_delegation.py +1037 -0
  977. tools/bench_latency.py +83 -0
  978. tools/benchmark_gate.py +506 -0
  979. tools/benchmark_program.py +474 -0
  980. tools/binary_extensions.py +42 -0
  981. tools/blueprints.py +325 -0
  982. tools/bootstrap_transaction_client.py +181 -0
  983. tools/browser_camofox.py +949 -0
  984. tools/browser_camofox_state.py +47 -0
  985. tools/browser_cdp_tool.py +681 -0
  986. tools/browser_dialog_tool.py +148 -0
  987. tools/browser_interaction_contract.py +104 -0
  988. tools/browser_supervisor.py +1517 -0
  989. tools/browser_tool.py +4805 -0
  990. tools/budget_config.py +114 -0
  991. tools/bundle_manifest.py +128 -0
  992. tools/checkpoint_manager.py +1691 -0
  993. tools/clarify_gateway.py +315 -0
  994. tools/clarify_tool.py +191 -0
  995. tools/cli_surface_contract.py +428 -0
  996. tools/close_terminal_tool.py +71 -0
  997. tools/code_execution_tool.py +1910 -0
  998. tools/command_invocation_manifest.py +457 -0
  999. tools/computer_use/__init__.py +48 -0
  1000. tools/computer_use/backend.py +210 -0
  1001. tools/computer_use/cua_backend.py +2346 -0
  1002. tools/computer_use/doctor.py +288 -0
  1003. tools/computer_use/killswitch.py +65 -0
  1004. tools/computer_use/permissions.py +200 -0
  1005. tools/computer_use/schema.py +238 -0
  1006. tools/computer_use/tool.py +1174 -0
  1007. tools/computer_use/vision_routing.py +204 -0
  1008. tools/computer_use_tool.py +39 -0
  1009. tools/credential_files.py +481 -0
  1010. tools/cronjob_tools.py +1147 -0
  1011. tools/daemon_hot_path.py +538 -0
  1012. tools/daemon_pool.py +64 -0
  1013. tools/debug_helpers.py +105 -0
  1014. tools/delegate_tool.py +3528 -0
  1015. tools/desktop_layout_contract.py +310 -0
  1016. tools/discord_tool.py +1119 -0
  1017. tools/discovery_cache.py +153 -0
  1018. tools/env_passthrough.py +184 -0
  1019. tools/env_probe.py +275 -0
  1020. tools/environments/__init__.py +14 -0
  1021. tools/environments/base.py +1128 -0
  1022. tools/environments/daytona.py +270 -0
  1023. tools/environments/docker.py +1460 -0
  1024. tools/environments/file_sync.py +465 -0
  1025. tools/environments/local.py +1385 -0
  1026. tools/environments/managed_modal.py +282 -0
  1027. tools/environments/modal.py +478 -0
  1028. tools/environments/modal_utils.py +210 -0
  1029. tools/environments/singularity.py +265 -0
  1030. tools/environments/ssh.py +375 -0
  1031. tools/equivalence_gate.py +569 -0
  1032. tools/fal_common.py +163 -0
  1033. tools/feishu_doc_tool.py +138 -0
  1034. tools/feishu_drive_tool.py +431 -0
  1035. tools/file_operations.py +2514 -0
  1036. tools/file_state.py +332 -0
  1037. tools/file_tools.py +1952 -0
  1038. tools/fuzzy_match.py +950 -0
  1039. tools/golden_path.py +371 -0
  1040. tools/homeassistant_tool.py +513 -0
  1041. tools/hook_output_spill.py +236 -0
  1042. tools/identity_scan.py +243 -0
  1043. tools/image_generation_tool.py +1668 -0
  1044. tools/image_source.py +338 -0
  1045. tools/interrupt.py +113 -0
  1046. tools/kanban_tools.py +1681 -0
  1047. tools/kernel_binding.py +1255 -0
  1048. tools/lazy_deps.py +970 -0
  1049. tools/live_commit_attestation.py +303 -0
  1050. tools/locale_contract.py +223 -0
  1051. tools/machine_contracts.py +332 -0
  1052. tools/managed_tool_gateway.py +192 -0
  1053. tools/mcp_capability_matrix.py +83 -0
  1054. tools/mcp_oauth.py +948 -0
  1055. tools/mcp_oauth_manager.py +720 -0
  1056. tools/mcp_stdio_watchdog.py +184 -0
  1057. tools/mcp_tool.py +5832 -0
  1058. tools/memory_tool.py +1153 -0
  1059. tools/microsoft_graph_auth.py +245 -0
  1060. tools/microsoft_graph_client.py +408 -0
  1061. tools/namespace_identity_audit.py +524 -0
  1062. tools/neutts_synth.py +104 -0
  1063. tools/openrouter_client.py +33 -0
  1064. tools/osv_check.py +169 -0
  1065. tools/patch_parser.py +637 -0
  1066. tools/path_security.py +43 -0
  1067. tools/perf_gate/__init__.py +12 -0
  1068. tools/perf_gate/bootstrap_baseline.py +62 -0
  1069. tools/perf_gate/compare.py +163 -0
  1070. tools/perf_gate/runner.py +95 -0
  1071. tools/perf_integration_manifest.py +814 -0
  1072. tools/process_registry.py +2329 -0
  1073. tools/project_tools.py +189 -0
  1074. tools/promotion_controller.py +471 -0
  1075. tools/prompt_microkernel_integration_receipt.py +144 -0
  1076. tools/public_docs_audit.py +563 -0
  1077. tools/read_extract.py +248 -0
  1078. tools/read_terminal_tool.py +94 -0
  1079. tools/registry.py +821 -0
  1080. tools/release_gate.py +897 -0
  1081. tools/release_gate_scan.py +494 -0
  1082. tools/release_handoff.py +107 -0
  1083. tools/release_manifest.py +202 -0
  1084. tools/rename_guard/__init__.py +7 -0
  1085. tools/rename_guard/artifact_scan.py +257 -0
  1086. tools/rename_guard/bootstrap_baseline.py +78 -0
  1087. tools/rename_guard/scanner.py +188 -0
  1088. tools/runtime_handshake.py +256 -0
  1089. tools/runtime_lifecycle.py +589 -0
  1090. tools/runtime_lock_contract.py +212 -0
  1091. tools/runtime_manager.py +1084 -0
  1092. tools/schema_sanitizer.py +501 -0
  1093. tools/self_mutation_kernel.py +298 -0
  1094. tools/send_message_tool.py +1965 -0
  1095. tools/session_search_tool.py +923 -0
  1096. tools/shadow_effects.py +601 -0
  1097. tools/simplicio_bridge.py +716 -0
  1098. tools/simplicio_transport.py +680 -0
  1099. tools/skill_manager_tool.py +1559 -0
  1100. tools/skill_provenance.py +78 -0
  1101. tools/skill_usage.py +947 -0
  1102. tools/skills_ast_audit.py +133 -0
  1103. tools/skills_guard.py +1153 -0
  1104. tools/skills_hub.py +4071 -0
  1105. tools/skills_sync.py +1182 -0
  1106. tools/skills_tool.py +1760 -0
  1107. tools/slash_confirm.py +167 -0
  1108. tools/software_builder_manifest.py +349 -0
  1109. tools/terminal_tool.py +3062 -0
  1110. tools/thread_context.py +120 -0
  1111. tools/threat_patterns.py +284 -0
  1112. tools/tirith_security.py +871 -0
  1113. tools/todo_tool.py +403 -0
  1114. tools/tool_backend_helpers.py +182 -0
  1115. tools/tool_output_limits.py +110 -0
  1116. tools/tool_result_storage.py +254 -0
  1117. tools/tool_search.py +735 -0
  1118. tools/transaction_primitives.py +1085 -0
  1119. tools/transcription_tools.py +1893 -0
  1120. tools/tts_tool.py +3152 -0
  1121. tools/url_safety.py +503 -0
  1122. tools/video_generation_tool.py +575 -0
  1123. tools/vision_tools.py +1897 -0
  1124. tools/voice_mode.py +1218 -0
  1125. tools/wake_word.py +182 -0
  1126. tools/watcher_gate.py +481 -0
  1127. tools/web_tools.py +1240 -0
  1128. tools/website_policy.py +283 -0
  1129. tools/write_approval.py +493 -0
  1130. tools/x_search_tool.py +525 -0
  1131. tools/xai_http.py +277 -0
  1132. tools/xai_video_tools.py +209 -0
  1133. tools/yuanbao_tools.py +737 -0
  1134. toolset_distributions.py +358 -0
  1135. toolsets.py +971 -0
  1136. trajectory_compressor.py +1574 -0
  1137. tui_gateway/__init__.py +0 -0
  1138. tui_gateway/entry.py +381 -0
  1139. tui_gateway/event_publisher.py +126 -0
  1140. tui_gateway/git_probe.py +193 -0
  1141. tui_gateway/loop_noise.py +83 -0
  1142. tui_gateway/project_tree.py +640 -0
  1143. tui_gateway/render.py +49 -0
  1144. tui_gateway/server.py +14516 -0
  1145. tui_gateway/slash_worker.py +179 -0
  1146. tui_gateway/transport.py +219 -0
  1147. tui_gateway/ws.py +466 -0
  1148. utils.py +546 -0
@@ -0,0 +1,871 @@
1
+ """
2
+ HTML Export generator for Hermes sessions.
3
+ Generates a standalone, beautiful HTML file with all messages embedded.
4
+ Supports single and multi-session exports with a professional sidebar.
5
+ No remote dependencies.
6
+ Enhanced with UI-UX-PRO-MAX design intelligence.
7
+ """
8
+
9
+ import json
10
+ import datetime
11
+ import secrets
12
+ from typing import Any, Dict, List
13
+ from urllib.parse import quote
14
+
15
+ # --- Icons (Lucide-style SVGs) ---
16
+ ICON_USER = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>'
17
+ ICON_BOT = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bot"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg>'
18
+ ICON_TERMINAL = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-terminal"><polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/></svg>'
19
+ ICON_WRENCH = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wrench"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>'
20
+ ICON_SPARKLES = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles"><path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/><path d="M5 3v4"/><path d="M19 17v4"/><path d="M3 5h4"/><path d="M17 19h4"/></svg>'
21
+ ICON_CHEVRON_RIGHT = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg>'
22
+ ICON_SEARCH = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>'
23
+ ICON_SHIELD = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.5 3.8 17 5 19 5a1 1 0 0 1 1 1z"/></svg>'
24
+ ICON_HERMES = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#FFD700" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="m9 12 2 2 4-4"/></svg>'
25
+
26
+ HTML_TEMPLATE = """<!DOCTYPE html>
27
+ <html lang="en">
28
+ <head>
29
+ <meta charset="UTF-8">
30
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
31
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-{script_nonce}'; style-src 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; object-src 'none'">
32
+ <title>{page_title}</title>
33
+ <link rel="preconnect" href="https://fonts.googleapis.com">
34
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
35
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
36
+ <style>
37
+ :root {{
38
+ --bg-color: #F8FAFC;
39
+ --text-color: #0F172A;
40
+ --secondary-text: #475569;
41
+ --user-bg: #FFFFFF;
42
+ --assistant-bg: #F1F5F9;
43
+ --border-color: #E2E8F0;
44
+ --accent-color: #CD7F32;
45
+ --accent-foreground: #FFFFFF;
46
+ --code-bg: #1E293B;
47
+ --code-text: #F8FAFC;
48
+ --reasoning-bg: #FFFBEB;
49
+ --reasoning-border: #FEF3C7;
50
+ --tool-bg: #F0F9FF;
51
+ --tool-border: #E0F2FE;
52
+ --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
53
+ --sidebar-bg: #FFFFFF;
54
+ --sidebar-width: 320px;
55
+ }}
56
+
57
+ @media (prefers-color-scheme: dark) {{
58
+ :root {{
59
+ --bg-color: #000101;
60
+ --text-color: #FFF8DC;
61
+ --secondary-text: #94A3B8;
62
+ --user-bg: #041c1c;
63
+ --assistant-bg: #0c1a1a;
64
+ --border-color: #CD7F32;
65
+ --accent-color: #FFD700;
66
+ --code-bg: #000000;
67
+ --reasoning-bg: #1a1a1a;
68
+ --reasoning-border: #CD7F32;
69
+ --tool-bg: #0c4a6e;
70
+ --tool-border: #075985;
71
+ --shadow: 0 4px 6px -1px rgb(0 0 0 / 0.3), 0 2px 4px -2px rgb(0 0 0 / 0.3);
72
+ --sidebar-bg: #041c1c;
73
+ }}
74
+ }}
75
+
76
+ * {{
77
+ box-sizing: border-box;
78
+ margin: 0;
79
+ padding: 0;
80
+ }}
81
+
82
+ body {{
83
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
84
+ line-height: 1.6;
85
+ color: var(--text-color);
86
+ background-color: var(--bg-color);
87
+ -webkit-font-smoothing: antialiased;
88
+ overflow-x: hidden;
89
+ }}
90
+
91
+ .layout {{
92
+ display: flex;
93
+ min-height: 100vh;
94
+ }}
95
+
96
+ /* Sidebar */
97
+ .sidebar {{
98
+ width: var(--sidebar-width);
99
+ background-color: var(--sidebar-bg);
100
+ border-right: 1px solid var(--border-color);
101
+ display: flex;
102
+ flex-direction: column;
103
+ position: fixed;
104
+ height: 100vh;
105
+ z-index: 100;
106
+ transition: transform 0.3s ease;
107
+ }}
108
+
109
+ @media (max-width: 768px) {{
110
+ .sidebar {{
111
+ transform: translateX(-100%);
112
+ }}
113
+ .sidebar.open {{
114
+ transform: translateX(0);
115
+ }}
116
+ .main-content {{
117
+ margin-left: 0 !important;
118
+ }}
119
+ }}
120
+
121
+ .sidebar-header {{
122
+ padding: 1.5rem;
123
+ border-bottom: 1px solid var(--border-color);
124
+ }}
125
+
126
+ .sidebar-brand {{
127
+ display: flex;
128
+ align-items: center;
129
+ gap: 0.75rem;
130
+ font-weight: 700;
131
+ font-size: 1.25rem;
132
+ color: var(--accent-color);
133
+ margin-bottom: 1rem;
134
+ }}
135
+
136
+ .search-container {{
137
+ position: relative;
138
+ }}
139
+
140
+ .search-container input {{
141
+ width: 100%;
142
+ padding: 0.5rem 1rem 0.5rem 2.25rem;
143
+ border-radius: 0.5rem;
144
+ border: 1px solid var(--border-color);
145
+ background-color: var(--bg-color);
146
+ color: var(--text-color);
147
+ font-size: 0.875rem;
148
+ outline: none;
149
+ }}
150
+
151
+ .search-container svg {{
152
+ position: absolute;
153
+ left: 0.75rem;
154
+ top: 50%;
155
+ transform: translateY(-50%);
156
+ color: var(--secondary-text);
157
+ }}
158
+
159
+ .session-list {{
160
+ flex: 1;
161
+ overflow-y: auto;
162
+ padding: 1rem;
163
+ }}
164
+
165
+ .session-item {{
166
+ display: block;
167
+ padding: 0.75rem 1rem;
168
+ border-radius: 0.5rem;
169
+ margin-bottom: 0.5rem;
170
+ cursor: pointer;
171
+ transition: all 0.2s ease;
172
+ text-decoration: none;
173
+ color: inherit;
174
+ border: 1px solid transparent;
175
+ }}
176
+
177
+ .session-item:hover {{
178
+ background-color: rgba(0, 0, 0, 0.05);
179
+ }}
180
+
181
+ @media (prefers-color-scheme: dark) {{
182
+ .session-item:hover {{
183
+ background-color: rgba(255, 255, 255, 0.05);
184
+ }}
185
+ }}
186
+
187
+ .session-item.active {{
188
+ background-color: var(--user-bg);
189
+ border-color: var(--accent-color);
190
+ box-shadow: var(--shadow);
191
+ }}
192
+
193
+ .session-item-title {{
194
+ font-weight: 600;
195
+ font-size: 0.875rem;
196
+ white-space: nowrap;
197
+ overflow: hidden;
198
+ text-overflow: ellipsis;
199
+ margin-bottom: 0.25rem;
200
+ }}
201
+
202
+ .session-item-meta {{
203
+ font-size: 0.75rem;
204
+ color: var(--secondary-text);
205
+ display: flex;
206
+ justify-content: space-between;
207
+ }}
208
+
209
+ /* Main Content */
210
+ .main-content {{
211
+ flex: 1;
212
+ margin-left: {main_margin};
213
+ padding: 3rem 2rem;
214
+ max-width: 100%;
215
+ transition: margin-left 0.3s ease;
216
+ }}
217
+
218
+ .session-view {{
219
+ display: none;
220
+ width: 100%;
221
+ margin: 0 auto;
222
+ }}
223
+
224
+ .layout-single .session-view {{
225
+ max-width: 90%;
226
+ margin: 0 auto;
227
+ }}
228
+
229
+ .layout-multi .session-view {{
230
+ max-width: 100%;
231
+ margin: 0;
232
+ }}
233
+
234
+ .layout-multi .main-content {{
235
+ width: 0;
236
+ }}
237
+
238
+ .session-view.active {{
239
+ display: block;
240
+ }}
241
+
242
+ header {{
243
+ margin-bottom: 3rem;
244
+ text-align: center;
245
+ }}
246
+
247
+ .meta {{
248
+ display: flex;
249
+ justify-content: center;
250
+ flex-wrap: wrap;
251
+ gap: 1.5rem;
252
+ margin-top: 1rem;
253
+ font-size: 0.875rem;
254
+ color: var(--secondary-text);
255
+ }}
256
+
257
+ .meta-item strong {{
258
+ color: var(--text-color);
259
+ }}
260
+
261
+ /* Messages */
262
+ .message {{
263
+ margin-bottom: 1.5rem;
264
+ border-radius: 0.75rem;
265
+ background-color: var(--user-bg);
266
+ border: 1px solid var(--border-color);
267
+ box-shadow: var(--shadow);
268
+ overflow: hidden;
269
+ }}
270
+
271
+ .message-user {{
272
+ background-color: #f0fdf4;
273
+ }}
274
+
275
+ .message-assistant {{
276
+ background-color: var(--assistant-bg);
277
+ border-left: 4px solid var(--accent-color);
278
+ }}
279
+
280
+ .message-system {{
281
+ background-color: var(--bg-color);
282
+ border-left: 4px solid var(--secondary-text);
283
+ opacity: 0.9;
284
+ }}
285
+
286
+ .message-tool {{
287
+ background-color: #f8fafc;
288
+ border-style: dotted;
289
+ }}
290
+
291
+ @media (prefers-color-scheme: dark) {{
292
+ .message-user {{
293
+ background-color: #0c2121;
294
+ }}
295
+
296
+ .message-assistant {{
297
+ background-color: #041c1c;
298
+ }}
299
+
300
+ .message-system {{
301
+ background-color: #020617;
302
+ border-left: 4px solid var(--secondary-text);
303
+ }}
304
+
305
+ .message-tool {{
306
+ background-color: #0f172a;
307
+ }}
308
+ }}
309
+
310
+ .message-header {{
311
+ display: flex;
312
+ align-items: center;
313
+ justify-content: space-between;
314
+ padding: 1rem 1.5rem;
315
+ cursor: pointer;
316
+ user-select: none;
317
+ transition: background-color 0.2s ease;
318
+ }}
319
+
320
+ .message-header:hover {{
321
+ background-color: rgba(0,0,0,0.02);
322
+ }}
323
+
324
+ .message-header svg.chevron {{
325
+ transition: transform 0.2s ease;
326
+ color: var(--secondary-text);
327
+ }}
328
+
329
+ .message.active svg.chevron {{
330
+ transform: rotate(90deg);
331
+ }}
332
+
333
+ .role-badge {{
334
+ display: flex;
335
+ align-items: center;
336
+ gap: 0.5rem;
337
+ font-size: 0.75rem;
338
+ font-weight: 700;
339
+ text-transform: uppercase;
340
+ letter-spacing: 0.05em;
341
+ color: var(--secondary-text);
342
+ }}
343
+
344
+ .role-badge svg {{
345
+ color: var(--accent-color);
346
+ }}
347
+
348
+ .timestamp {{
349
+ font-size: 0.75rem;
350
+ color: var(--secondary-text);
351
+ font-variant-numeric: tabular-nums;
352
+ }}
353
+
354
+ .message-body {{
355
+ display: none;
356
+ padding: 0 1.5rem 1.5rem 1.5rem;
357
+ border-top: 1px solid var(--border-color);
358
+ padding-top: 1.5rem;
359
+ }}
360
+
361
+ .message.active .message-body {{
362
+ display: block;
363
+ }}
364
+
365
+ .content {{
366
+ white-space: pre-wrap;
367
+ word-break: break-word;
368
+ font-size: 1rem;
369
+ }}
370
+
371
+ /* Code Blocks */
372
+ code {{
373
+ font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
374
+ background-color: rgba(0,0,0,0.05);
375
+ padding: 0.2rem 0.4rem;
376
+ border-radius: 0.375rem;
377
+ font-size: 0.9em;
378
+ }}
379
+
380
+ pre {{
381
+ background-color: var(--code-bg);
382
+ color: var(--code-text);
383
+ padding: 1.25rem;
384
+ border-radius: 0.75rem;
385
+ overflow-x: auto;
386
+ margin: 1.25rem 0;
387
+ font-size: 0.9rem;
388
+ line-height: 1.5;
389
+ box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.1);
390
+ }}
391
+
392
+ pre code {{
393
+ background-color: transparent;
394
+ padding: 0;
395
+ border-radius: 0;
396
+ color: inherit;
397
+ }}
398
+
399
+ /* Tool Calls */
400
+ .tool-call {{
401
+ margin: 1rem 0;
402
+ border-radius: 0.5rem;
403
+ overflow: hidden;
404
+ border: 1px solid var(--tool-border);
405
+ background-color: var(--tool-bg);
406
+ }}
407
+
408
+ .tool-call-header {{
409
+ padding: 0.75rem 1rem;
410
+ display: flex;
411
+ align-items: center;
412
+ gap: 0.5rem;
413
+ cursor: pointer;
414
+ user-select: none;
415
+ font-size: 0.875rem;
416
+ font-weight: 600;
417
+ }}
418
+
419
+ .tool-call-header:hover {{
420
+ background-color: rgba(0,0,0,0.03);
421
+ }}
422
+
423
+ .tool-call-header svg.chevron {{
424
+ transition: transform 0.2s ease;
425
+ color: var(--secondary-text);
426
+ }}
427
+
428
+ .tool-call.active svg.chevron {{
429
+ transform: rotate(90deg);
430
+ }}
431
+
432
+ .tool-call-content {{
433
+ display: none;
434
+ padding: 0 1rem 1rem 1rem;
435
+ }}
436
+
437
+ .tool-call.active .tool-call-content {{
438
+ display: block;
439
+ }}
440
+
441
+ /* Reasoning */
442
+ .reasoning {{
443
+ margin-top: 1.5rem;
444
+ border-radius: 0.75rem;
445
+ border: 1px solid var(--reasoning-border);
446
+ background-color: var(--reasoning-bg);
447
+ overflow: hidden;
448
+ }}
449
+
450
+ .reasoning-header {{
451
+ padding: 0.75rem 1rem;
452
+ display: flex;
453
+ align-items: center;
454
+ gap: 0.5rem;
455
+ cursor: pointer;
456
+ user-select: none;
457
+ font-size: 0.875rem;
458
+ font-weight: 600;
459
+ }}
460
+
461
+ .reasoning-header:hover {{
462
+ background-color: rgba(0,0,0,0.02);
463
+ }}
464
+
465
+ .reasoning-header svg.chevron {{
466
+ transition: transform 0.2s ease;
467
+ color: var(--secondary-text);
468
+ }}
469
+
470
+ .reasoning.active svg.chevron {{
471
+ transform: rotate(90deg);
472
+ }}
473
+
474
+ .reasoning-content {{
475
+ display: none;
476
+ padding: 0 1rem 1rem 1rem;
477
+ font-size: 0.925rem;
478
+ color: var(--secondary-text);
479
+ border-top: 1px solid var(--reasoning-border);
480
+ padding-top: 1rem;
481
+ }}
482
+
483
+ .reasoning.active .reasoning-content {{
484
+ display: block;
485
+ }}
486
+
487
+ /* System Prompt Section */
488
+ .system-prompt-section {{
489
+ margin-top: 2rem;
490
+ border-radius: 0.75rem;
491
+ border: 1px solid var(--border-color);
492
+ background-color: var(--user-bg);
493
+ overflow: hidden;
494
+ text-align: left;
495
+ max-width: 800px;
496
+ margin-left: auto;
497
+ margin-right: auto;
498
+ }}
499
+
500
+ .system-prompt-header {{
501
+ padding: 0.75rem 1.25rem;
502
+ display: flex;
503
+ align-items: center;
504
+ gap: 0.6rem;
505
+ cursor: pointer;
506
+ user-select: none;
507
+ font-size: 0.875rem;
508
+ font-weight: 600;
509
+ color: var(--secondary-text);
510
+ }}
511
+
512
+ .system-prompt-header:hover {{
513
+ background-color: rgba(0,0,0,0.02);
514
+ }}
515
+
516
+ .system-prompt-header svg.chevron {{
517
+ transition: transform 0.2s ease;
518
+ }}
519
+
520
+ .system-prompt-section.active svg.chevron {{
521
+ transform: rotate(90deg);
522
+ }}
523
+
524
+ .system-prompt-content {{
525
+ display: none;
526
+ padding: 0 1.25rem 1.25rem 1.25rem;
527
+ font-size: 0.9rem;
528
+ border-top: 1px solid var(--border-color);
529
+ padding-top: 1rem;
530
+ }}
531
+
532
+ .system-prompt-section.active .system-prompt-content {{
533
+ display: block;
534
+ }}
535
+
536
+ footer {{
537
+ margin-top: 5rem;
538
+ padding-top: 2rem;
539
+ border-top: 1px solid var(--border-color);
540
+ text-align: center;
541
+ font-size: 0.875rem;
542
+ color: var(--secondary-text);
543
+ }}
544
+
545
+ /* Animation */
546
+ .fade-in {{
547
+ animation: fadeIn 0.4s ease-out backwards;
548
+ }}
549
+
550
+ @keyframes fadeIn {{
551
+ from {{ opacity: 0; transform: translateY(10px); }}
552
+ to {{ opacity: 1; transform: translateY(0); }}
553
+ }}
554
+
555
+ /* Utilities */
556
+ .hidden {{ display: none !important; }}
557
+ </style>
558
+ </head>
559
+ <body>
560
+ <div class="layout {layout_class}">
561
+ {sidebar_html}
562
+
563
+ <div class="main-content">
564
+ {sessions_html}
565
+
566
+ <footer>
567
+ Built with ☤ Hermes Agent • Generated on {generated_at}
568
+ </footer>
569
+ </div>
570
+ </div>
571
+
572
+ <script nonce="{script_nonce}">
573
+ // Session Switching
574
+ function showSession(id) {{
575
+ // Update Sidebar
576
+ document.querySelectorAll('.session-item').forEach(el => {{
577
+ el.classList.toggle('active', el.dataset.id === id);
578
+ }});
579
+
580
+ // Update View
581
+ document.querySelectorAll('.session-view').forEach(el => {{
582
+ el.classList.remove('active');
583
+ }});
584
+ const activeView = document.getElementById(`view-${{id}}`);
585
+ if (activeView) activeView.classList.add('active');
586
+
587
+ // Store in URL hash
588
+ window.location.hash = encodeURIComponent(id);
589
+ }}
590
+
591
+ document.querySelectorAll('.session-item').forEach(item => {{
592
+ item.addEventListener('click', (e) => {{
593
+ e.preventDefault();
594
+ showSession(item.dataset.id || '');
595
+ }});
596
+ }});
597
+
598
+ // Search Filter
599
+ const searchInput = document.getElementById('session-search');
600
+ if (searchInput) {{
601
+ searchInput.addEventListener('input', (e) => {{
602
+ const term = e.target.value.toLowerCase();
603
+ document.querySelectorAll('.session-item').forEach(item => {{
604
+ const text = item.innerText.toLowerCase();
605
+ if (text.includes(term)) {{
606
+ item.classList.remove('hidden');
607
+ }} else {{
608
+ item.classList.add('hidden');
609
+ }}
610
+ }});
611
+ }});
612
+ }}
613
+
614
+ // Card Toggles
615
+ document.addEventListener('click', function(e) {{
616
+ const header = e.target.closest('.message-header, .tool-call-header, .reasoning-header, .system-prompt-header');
617
+ if (header) {{
618
+ header.parentElement.classList.toggle('active');
619
+ }}
620
+ }});
621
+
622
+ // Initialization
623
+ window.addEventListener('load', () => {{
624
+ const hash = decodeURIComponent(window.location.hash.slice(1));
625
+ if (hash) {{
626
+ showSession(hash);
627
+ }} else {{
628
+ // Show first session by default if none selected
629
+ const first = document.querySelector('.session-item');
630
+ if (first) showSession(first.getAttribute('data-id'));
631
+ }}
632
+ }});
633
+
634
+ // Intersection Observer for scroll animations
635
+ if ('IntersectionObserver' in window) {{
636
+ var observer = new IntersectionObserver(function(entries) {{
637
+ entries.forEach(function(entry) {{
638
+ if (entry.isIntersecting) {{
639
+ entry.target.classList.add('fade-in');
640
+ observer.unobserve(entry.target);
641
+ }}
642
+ }});
643
+ }}, {{ threshold: 0.1 }});
644
+
645
+ document.querySelectorAll('.message').forEach(function(m) {{ observer.observe(m); }});
646
+ }}
647
+ </script>
648
+ </body>
649
+ </html>
650
+ """
651
+
652
+ def _escape_html(text: str) -> str:
653
+ if not isinstance(text, str):
654
+ text = str(text)
655
+ return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace("'", "&#39;")
656
+
657
+ def _format_timestamp(ts: float) -> str:
658
+ if not ts: return "N/A"
659
+ return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
660
+
661
+ def _generate_messages_html(messages: List[Dict[str, Any]]) -> str:
662
+ html_list = []
663
+ for i, msg in enumerate(messages):
664
+ role = msg.get("role", "unknown")
665
+
666
+ # Skip internal metadata messages
667
+ if role == "session_meta":
668
+ continue
669
+
670
+ content = msg.get("content") or ""
671
+ timestamp = _format_timestamp(msg.get("timestamp", 0))
672
+
673
+ # Icon selection
674
+ role_icon = ICON_TERMINAL
675
+ if role == "user":
676
+ role_icon = ICON_USER
677
+ elif role == "assistant":
678
+ role_icon = ICON_BOT
679
+ elif role == "system":
680
+ role_icon = ICON_SHIELD
681
+
682
+ # Handle multimodal or complex content
683
+ if isinstance(content, list):
684
+ content_parts = []
685
+ for part in content:
686
+ if isinstance(part, dict):
687
+ if part.get("type") == "text":
688
+ content_parts.append(part.get("text", ""))
689
+ elif part.get("type") == "image_url":
690
+ content_parts.append("[Image Attachment]")
691
+ else:
692
+ content_parts.append(str(part))
693
+ content = "\n".join(content_parts)
694
+
695
+ # Build message HTML. The role feeds two sinks and for tool/MCP messages
696
+ # is externally influenced, so treat each sink on its own terms:
697
+ # - display text: HTML-escape (prevents markup/JS injection).
698
+ # - class attribute: reduce to a single safe CSS token (alnum/-/_),
699
+ # so a crafted role can neither break out of the attribute nor split
700
+ # into several unintended classes. Real roles (user/assistant/system/
701
+ # tool) are unchanged, so the `.message-<role>` rules still match.
702
+ safe_role = _escape_html(role)
703
+ role_class = "".join(c if c.isalnum() or c in "-_" else "-" for c in str(role).lower())
704
+ msg_class = f"message message-{role_class} active"
705
+ # Delay animation for initial items
706
+ delay_style = f' style="animation-delay: {min(i * 0.05, 1.0)}s"' if i < 10 else ""
707
+
708
+ chevron_html = ICON_CHEVRON_RIGHT.replace('class="', 'class="chevron ')
709
+
710
+ html = f'<div class="{msg_class}"{delay_style}>'
711
+ html += f' <div class="message-header">'
712
+ html += f' <div class="role-badge">{chevron_html} {role_icon} {safe_role}</div>'
713
+ html += f' <div class="timestamp">{timestamp}</div>'
714
+ html += ' </div>'
715
+ html += ' <div class="message-body">'
716
+
717
+ # Tool Calls
718
+ tool_calls = msg.get("tool_calls")
719
+ if tool_calls:
720
+ for tc in tool_calls:
721
+ fn_name = tc.get("function", {}).get("name", "unknown")
722
+ args = tc.get("function", {}).get("arguments", "{}")
723
+ html += f'''
724
+ <div class="tool-call">
725
+ <div class="tool-call-header">
726
+ {ICON_CHEVRON_RIGHT.replace('class="', 'class="chevron ')}
727
+ {ICON_WRENCH} Tool Call: {_escape_html(fn_name)}
728
+ </div>
729
+ <div class="tool-call-content">
730
+ <pre><code>{_escape_html(args)}</code></pre>
731
+ </div>
732
+ </div>
733
+ '''
734
+
735
+ # Content
736
+ if content:
737
+ if role == "tool":
738
+ html += f' <div class="content"><pre><code>{_escape_html(content)}</code></pre></div>'
739
+ else:
740
+ html += f' <div class="content">{_escape_html(content)}</div>'
741
+
742
+ # Reasoning
743
+ reasoning = msg.get("reasoning") or msg.get("reasoning_content")
744
+ if reasoning:
745
+ html += f'''
746
+ <div class="reasoning">
747
+ <div class="reasoning-header">
748
+ {ICON_CHEVRON_RIGHT.replace('class="', 'class="chevron ')}
749
+ {ICON_SPARKLES} Reasoning
750
+ </div>
751
+ <div class="reasoning-content">
752
+ <div class="content">{_escape_html(reasoning)}</div>
753
+ </div>
754
+ </div>
755
+ '''
756
+
757
+ html += ' </div>'
758
+ html += '</div>'
759
+ html_list.append(html)
760
+ return "\n".join(html_list)
761
+
762
+ def generate_multi_session_html_export(sessions: List[Dict[str, Any]]) -> str:
763
+ if not sessions:
764
+ return "<html><body><h1>No sessions to export.</h1></body></html>"
765
+
766
+ is_multi = len(sessions) > 1
767
+ generated_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
768
+
769
+ # Sidebar
770
+ sidebar_html = ""
771
+ if is_multi:
772
+ sidebar_items = []
773
+ for s in sessions:
774
+ sid = str(s.get("id", "N/A"))
775
+ escaped_sid = _escape_html(sid)
776
+ title = s.get("title") or s.get("preview") or "Untitled Session"
777
+ if len(title) > 50: title = title[:47] + "..."
778
+ date = _format_timestamp(s.get("started_at", 0)).split(" ")[0]
779
+
780
+ item = f'''
781
+ <a class="session-item" data-id="{escaped_sid}" href="#{quote(sid, safe='')}">
782
+ <div class="session-item-title">{_escape_html(title)}</div>
783
+ <div class="session-item-meta">
784
+ <span>{_escape_html(sid[:8])}</span>
785
+ <span>{date}</span>
786
+ </div>
787
+ </a>
788
+ '''
789
+ sidebar_items.append(item)
790
+
791
+ sidebar_html = f'''
792
+ <aside class="sidebar">
793
+ <div class="sidebar-header">
794
+ <div class="sidebar-brand">
795
+ {ICON_HERMES} Hermes History
796
+ </div>
797
+ <div class="search-container">
798
+ {ICON_SEARCH}
799
+ <input type="text" id="session-search" placeholder="Search sessions...">
800
+ </div>
801
+ </div>
802
+ <div class="session-list">
803
+ {"".join(sidebar_items)}
804
+ </div>
805
+ </aside>
806
+ '''
807
+
808
+ # Main Content
809
+ sessions_html_list = []
810
+ for s in sessions:
811
+ sid = str(s.get("id", "N/A"))
812
+ escaped_sid = _escape_html(sid)
813
+ title = s.get("title") or "Hermes Session"
814
+ model = s.get("model", "Unknown")
815
+ started_at = _format_timestamp(s.get("started_at", 0))
816
+ messages = s.get("messages", [])
817
+
818
+ messages_html = _generate_messages_html(messages)
819
+
820
+ view_class = "session-view"
821
+ if not is_multi: view_class += " active"
822
+
823
+ session_view_id = f"view-{escaped_sid}"
824
+
825
+ system_prompt = s.get("system_prompt")
826
+ system_html = ""
827
+ if system_prompt:
828
+ system_html = f'''
829
+ <div class="system-prompt-section active">
830
+ <div class="system-prompt-header">
831
+ {ICON_CHEVRON_RIGHT.replace('class="', 'class="chevron ')}
832
+ {ICON_SHIELD} System Prompt (Persona)
833
+ </div>
834
+ <div class="system-prompt-content">
835
+ <div class="content">{_escape_html(system_prompt)}</div>
836
+ </div>
837
+ </div>
838
+ '''
839
+
840
+ session_html = f'''
841
+ <div class="{view_class}" id="{session_view_id}">
842
+ <header class="fade-in">
843
+ <h1>{_escape_html(title)}</h1>
844
+ <div class="meta">
845
+ <div class="meta-item"><strong>ID:</strong> {escaped_sid}</div>
846
+ <div class="meta-item"><strong>Model:</strong> {_escape_html(model)}</div>
847
+ <div class="meta-item"><strong>Started:</strong> {started_at}</div>
848
+ </div>
849
+ {system_html}
850
+ </header>
851
+ <main>
852
+ {messages_html}
853
+ </main>
854
+ </div>
855
+ '''
856
+ sessions_html_list.append(session_html)
857
+
858
+ script_nonce = secrets.token_urlsafe(16)
859
+ return HTML_TEMPLATE.format(
860
+ page_title="Hermes Session Export" if is_multi else _escape_html(sessions[0].get("title", "Hermes Session")),
861
+ sidebar_html=sidebar_html,
862
+ sessions_html="\n".join(sessions_html_list),
863
+ main_margin="var(--sidebar-width)" if is_multi else "0",
864
+ layout_class="layout-multi" if is_multi else "layout-single",
865
+ generated_at=generated_at,
866
+ script_nonce=script_nonce,
867
+ )
868
+
869
+ def generate_html_export(session_data: Dict[str, Any]) -> str:
870
+ """Legacy wrapper for single session export."""
871
+ return generate_multi_session_html_export([session_data])