polyrob 0.5.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 (745) hide show
  1. agents/README.md +453 -0
  2. agents/__init__.py +164 -0
  3. agents/base_agent.py +743 -0
  4. agents/personality/character.py +119 -0
  5. agents/personality/character_manager.py +309 -0
  6. agents/personality/characters/rob.character.json +56 -0
  7. agents/personality/characters/trump.character.json +63 -0
  8. agents/personality/persona_render.py +78 -0
  9. agents/personality/persona_resolver.py +115 -0
  10. agents/prompt/__init__.py +58 -0
  11. agents/prompt/base_prompt.py +92 -0
  12. agents/prompt/system.py +417 -0
  13. agents/task/README_PATH_MANAGEMENT.md +141 -0
  14. agents/task/__init__.py +162 -0
  15. agents/task/agent/__init__.py +70 -0
  16. agents/task/agent/agent_state.py +408 -0
  17. agents/task/agent/async_delegation.py +274 -0
  18. agents/task/agent/autonomy_state.py +275 -0
  19. agents/task/agent/conversation.py +75 -0
  20. agents/task/agent/core/__init__.py +6 -0
  21. agents/task/agent/core/aux_metering.py +61 -0
  22. agents/task/agent/core/background_review.py +157 -0
  23. agents/task/agent/core/construction.py +1179 -0
  24. agents/task/agent/core/conversational_exit.py +49 -0
  25. agents/task/agent/core/correspondent_gate.py +227 -0
  26. agents/task/agent/core/curator.py +246 -0
  27. agents/task/agent/core/episodic_digest.py +103 -0
  28. agents/task/agent/core/error_recovery.py +480 -0
  29. agents/task/agent/core/history_io.py +257 -0
  30. agents/task/agent/core/llm_provisioning.py +287 -0
  31. agents/task/agent/core/llm_runner.py +547 -0
  32. agents/task/agent/core/logging_io.py +276 -0
  33. agents/task/agent/core/loop_detection.py +262 -0
  34. agents/task/agent/core/memory_prefetch.py +325 -0
  35. agents/task/agent/core/memory_writer.py +667 -0
  36. agents/task/agent/core/model_introspection.py +82 -0
  37. agents/task/agent/core/model_swap.py +177 -0
  38. agents/task/agent/core/next_action_internal.py +1331 -0
  39. agents/task/agent/core/output_validation.py +303 -0
  40. agents/task/agent/core/project_context.py +272 -0
  41. agents/task/agent/core/resources.py +93 -0
  42. agents/task/agent/core/result_processing.py +389 -0
  43. agents/task/agent/core/run_loop.py +661 -0
  44. agents/task/agent/core/safety_lifecycle.py +228 -0
  45. agents/task/agent/core/secret_guard.py +293 -0
  46. agents/task/agent/core/self_wake.py +280 -0
  47. agents/task/agent/core/session_metadata.py +104 -0
  48. agents/task/agent/core/step.py +781 -0
  49. agents/task/agent/core/step_execution.py +398 -0
  50. agents/task/agent/core/step_telemetry.py +222 -0
  51. agents/task/agent/core/test_aux_metering.py +50 -0
  52. agents/task/agent/core/test_billing_failover.py +68 -0
  53. agents/task/agent/core/test_fatal_error_classifier.py +38 -0
  54. agents/task/agent/core/test_judge_validation.py +275 -0
  55. agents/task/agent/core/test_model_swap.py +190 -0
  56. agents/task/agent/core/test_reflection_offload.py +54 -0
  57. agents/task/agent/core/turn_input.py +8 -0
  58. agents/task/agent/core/untrusted_wrap.py +103 -0
  59. agents/task/agent/core/user_ingress.py +228 -0
  60. agents/task/agent/hitl_manager.py +396 -0
  61. agents/task/agent/log_sanitize.py +36 -0
  62. agents/task/agent/message_manager/config.py +97 -0
  63. agents/task/agent/message_manager/service.py +758 -0
  64. agents/task/agent/message_manager/tests.py +305 -0
  65. agents/task/agent/message_manager/tool_call_builder.py +539 -0
  66. agents/task/agent/message_manager/tool_message_repair.py +364 -0
  67. agents/task/agent/message_manager/views.py +143 -0
  68. agents/task/agent/messages/__init__.py +8 -0
  69. agents/task/agent/messages/builders.py +309 -0
  70. agents/task/agent/messages/compactor.py +611 -0
  71. agents/task/agent/messages/context_references.py +271 -0
  72. agents/task/agent/messages/filters.py +333 -0
  73. agents/task/agent/messages/guidance.py +328 -0
  74. agents/task/agent/messages/persistence.py +448 -0
  75. agents/task/agent/messages/retrieval.py +506 -0
  76. agents/task/agent/messages/sqlite_persistence.py +85 -0
  77. agents/task/agent/messages/test_compaction_upgrade.py +349 -0
  78. agents/task/agent/messages/test_persistence_subdir_fix.py +28 -0
  79. agents/task/agent/messages/test_sqlite_persistence.py +54 -0
  80. agents/task/agent/messages/token_counter.py +532 -0
  81. agents/task/agent/orchestrator.py +776 -0
  82. agents/task/agent/profile_manager.py +105 -0
  83. agents/task/agent/profile_registry.py +173 -0
  84. agents/task/agent/prompts.py +1090 -0
  85. agents/task/agent/scenario_registry.py +226 -0
  86. agents/task/agent/service.py +509 -0
  87. agents/task/agent/session.py +984 -0
  88. agents/task/agent/skill_discovery.py +110 -0
  89. agents/task/agent/skill_frontmatter.py +94 -0
  90. agents/task/agent/skill_manager.py +1201 -0
  91. agents/task/agent/skill_store.py +627 -0
  92. agents/task/agent/skill_validation.py +56 -0
  93. agents/task/agent/skill_writer.py +492 -0
  94. agents/task/agent/sub_agent_manager.py +1137 -0
  95. agents/task/agent/test_session_disk_recovery.py +34 -0
  96. agents/task/agent/tests.py +513 -0
  97. agents/task/agent/tool_call_tracker.py +511 -0
  98. agents/task/agent/views.py +469 -0
  99. agents/task/config.py +432 -0
  100. agents/task/constants.py +1384 -0
  101. agents/task/flag_defaults.py +63 -0
  102. agents/task/goals/__init__.py +1 -0
  103. agents/task/goals/autonomy_marker.py +28 -0
  104. agents/task/goals/board.py +690 -0
  105. agents/task/goals/completion_judge.py +247 -0
  106. agents/task/goals/context.py +62 -0
  107. agents/task/goals/dispatcher.py +848 -0
  108. agents/task/goals/escalation.py +102 -0
  109. agents/task/goals/planner.py +114 -0
  110. agents/task/logging_config.py +155 -0
  111. agents/task/path.py +991 -0
  112. agents/task/robust_parse_config.py +400 -0
  113. agents/task/runtime/__init__.py +0 -0
  114. agents/task/runtime/run_as_session.py +130 -0
  115. agents/task/runtime_safety.py +308 -0
  116. agents/task/session/__init__.py +5 -0
  117. agents/task/session/browser_pool.py +130 -0
  118. agents/task/session/cleanup.py +612 -0
  119. agents/task/session/execution.py +397 -0
  120. agents/task/session/feed.py +200 -0
  121. agents/task/session/hitl_ingress.py +201 -0
  122. agents/task/session/hooks.py +83 -0
  123. agents/task/session/multi_agent.py +243 -0
  124. agents/task/session/workspace.py +91 -0
  125. agents/task/session_registry.py +91 -0
  126. agents/task/session_route.py +35 -0
  127. agents/task/sqlite_session_registry.py +261 -0
  128. agents/task/surface_config.py +185 -0
  129. agents/task/telemetry/__init__.py +58 -0
  130. agents/task/telemetry/event_log.py +180 -0
  131. agents/task/telemetry/formatters.py +642 -0
  132. agents/task/telemetry/manager.py +571 -0
  133. agents/task/telemetry/memory_events.py +66 -0
  134. agents/task/telemetry/self_events.py +53 -0
  135. agents/task/telemetry/sequence.py +160 -0
  136. agents/task/telemetry/service.py +1265 -0
  137. agents/task/telemetry/views.py +882 -0
  138. agents/task/templates.py +98 -0
  139. agents/task/test_aux_chain.py +151 -0
  140. agents/task/test_aux_router.py +41 -0
  141. agents/task/tests/test_parse_robustness.py +170 -0
  142. agents/task/tool_defaults.py +110 -0
  143. agents/task/utils.py +762 -0
  144. agents/task/utils_json.py +768 -0
  145. agents/task/utils_webview.py +86 -0
  146. agents/task/workspace_context.py +229 -0
  147. agents/task_agent_lite.py +2398 -0
  148. api/README.md +683 -0
  149. api/TASK_API_DOCS.md +151 -0
  150. api/__init__.py +0 -0
  151. api/a2a/__init__.py +37 -0
  152. api/a2a/agent_card.py +337 -0
  153. api/a2a/client.py +657 -0
  154. api/a2a/endpoints.py +375 -0
  155. api/a2a/models.py +268 -0
  156. api/a2a/streaming.py +419 -0
  157. api/a2a/task_handler.py +929 -0
  158. api/admin_endpoints.py +1584 -0
  159. api/app.py +923 -0
  160. api/auth_constants.py +28 -0
  161. api/auth_endpoints.py +402 -0
  162. api/auth_state.py +36 -0
  163. api/chat_via_task.py +42 -0
  164. api/conversation_manager.py +231 -0
  165. api/dependencies.py +186 -0
  166. api/eip8004_endpoints.py +452 -0
  167. api/hyperliquid_models.py +174 -0
  168. api/hyperliquid_routes.py +450 -0
  169. api/interfaces.py +207 -0
  170. api/jwt_middleware.py +83 -0
  171. api/kb/__init__.py +1 -0
  172. api/kb/endpoints.py +314 -0
  173. api/mcp_models.py +279 -0
  174. api/mcp_routes.py +438 -0
  175. api/middleware.py +526 -0
  176. api/models.py +176 -0
  177. api/openai_compat/__init__.py +0 -0
  178. api/openai_compat/model_map.py +25 -0
  179. api/openai_compat/models.py +59 -0
  180. api/openai_compat/router.py +140 -0
  181. api/payment_endpoints.py +444 -0
  182. api/payment_verification.py +138 -0
  183. api/polymarket_models.py +155 -0
  184. api/polymarket_routes.py +501 -0
  185. api/pricing_endpoints.py +89 -0
  186. api/session_routing.py +54 -0
  187. api/skill_endpoints.py +453 -0
  188. api/task_http_api.py +1856 -0
  189. api/webhooks.py +52 -0
  190. api/x402_endpoints.py +280 -0
  191. avatar/README.md +44 -0
  192. avatar/__init__.py +1 -0
  193. avatar/config/rob.json +7 -0
  194. avatar/mindprint.js +395 -0
  195. avatar/renders/rob.meta.json +20 -0
  196. avatar/renders/rob.png +0 -0
  197. avatar/studio.html +373 -0
  198. avatar/webview/avatar-live.js +44 -0
  199. cli/README.md +89 -0
  200. cli/__init__.py +0 -0
  201. cli/cli_surface.py +67 -0
  202. cli/commands/__init__.py +0 -0
  203. cli/commands/_bootstrap.py +49 -0
  204. cli/commands/_errors.py +53 -0
  205. cli/commands/chat.py +973 -0
  206. cli/commands/config.py +100 -0
  207. cli/commands/dashboard.py +103 -0
  208. cli/commands/doctor.py +222 -0
  209. cli/commands/email.py +174 -0
  210. cli/commands/gateway.py +346 -0
  211. cli/commands/goals.py +509 -0
  212. cli/commands/init.py +276 -0
  213. cli/commands/journey.py +30 -0
  214. cli/commands/kb.py +280 -0
  215. cli/commands/model.py +107 -0
  216. cli/commands/owner.py +431 -0
  217. cli/commands/pfp.py +232 -0
  218. cli/commands/run.py +414 -0
  219. cli/commands/serve.py +41 -0
  220. cli/commands/session.py +684 -0
  221. cli/commands/skill_install.py +786 -0
  222. cli/commands/skills.py +128 -0
  223. cli/commands/subagents.py +100 -0
  224. cli/commands/surface.py +81 -0
  225. cli/commands/telegram.py +185 -0
  226. cli/commands/todos.py +209 -0
  227. cli/commands/tools.py +102 -0
  228. cli/commands/update.py +316 -0
  229. cli/commands/whatsapp.py +175 -0
  230. cli/config_store.py +276 -0
  231. cli/gitignore.py +43 -0
  232. cli/inventory.py +46 -0
  233. cli/keys.py +101 -0
  234. cli/persona.py +17 -0
  235. cli/polyrob.py +137 -0
  236. cli/ui/__init__.py +64 -0
  237. cli/ui/activity.py +141 -0
  238. cli/ui/app.py +538 -0
  239. cli/ui/banner.py +233 -0
  240. cli/ui/blocks.py +534 -0
  241. cli/ui/bootstrap_notice.py +47 -0
  242. cli/ui/commands/__init__.py +41 -0
  243. cli/ui/commands/h_cron.py +64 -0
  244. cli/ui/commands/h_journey.py +164 -0
  245. cli/ui/commands/h_kb.py +121 -0
  246. cli/ui/commands/h_learn.py +100 -0
  247. cli/ui/commands/h_mcp.py +215 -0
  248. cli/ui/commands/h_self.py +113 -0
  249. cli/ui/commands/h_skills.py +314 -0
  250. cli/ui/commands/handlers.py +1672 -0
  251. cli/ui/commands/registry.py +426 -0
  252. cli/ui/dialog.py +425 -0
  253. cli/ui/event_registry.py +110 -0
  254. cli/ui/event_specs.py +45 -0
  255. cli/ui/events.py +433 -0
  256. cli/ui/identity.py +15 -0
  257. cli/ui/lifecycle.py +159 -0
  258. cli/ui/live_hooks.py +43 -0
  259. cli/ui/model_selector.py +532 -0
  260. cli/ui/persistent_loop.py +181 -0
  261. cli/ui/pick.py +113 -0
  262. cli/ui/plain_renderer.py +351 -0
  263. cli/ui/renderer.py +384 -0
  264. cli/ui/rich_renderer.py +533 -0
  265. cli/ui/secrets.py +115 -0
  266. cli/ui/state.py +376 -0
  267. cli/ui/statusbar.py +231 -0
  268. cli/ui/streaming.py +254 -0
  269. cli/ui/terminal_render.py +105 -0
  270. cli/ui/theme.py +132 -0
  271. cli/update/__init__.py +6 -0
  272. cli/update/context.py +121 -0
  273. cli/update/detect.py +176 -0
  274. cli/update/engine.py +95 -0
  275. cli/update/migrate_guarded.py +55 -0
  276. cli/update/process_guard.py +215 -0
  277. cli/update/runners.py +78 -0
  278. cli/update/snapshot.py +270 -0
  279. cli/update/versions.py +205 -0
  280. core/README.md +377 -0
  281. core/__init__.py +174 -0
  282. core/assets.py +87 -0
  283. core/async_bridge.py +76 -0
  284. core/autonomy_runtime.py +259 -0
  285. core/base_component.py +302 -0
  286. core/bootstrap.py +681 -0
  287. core/bot.py +310 -0
  288. core/config.py +833 -0
  289. core/constants.py +126 -0
  290. core/container.py +462 -0
  291. core/db_manifest.py +101 -0
  292. core/embedding.py +57 -0
  293. core/env.py +39 -0
  294. core/exceptions.py +287 -0
  295. core/flags.py +144 -0
  296. core/flags_catalog.py +345 -0
  297. core/home_migration.py +62 -0
  298. core/identity.py +118 -0
  299. core/initialization.py +1004 -0
  300. core/instance.py +537 -0
  301. core/interactive_gate.py +96 -0
  302. core/logging.py +436 -0
  303. core/owner_doc_writer.py +176 -0
  304. core/pairing.py +193 -0
  305. core/path_safety.py +20 -0
  306. core/paths.py +27 -0
  307. core/payment_config.py +21 -0
  308. core/permissions.py +322 -0
  309. core/runtime_config.py +96 -0
  310. core/runtime_paths.py +135 -0
  311. core/seams.py +35 -0
  312. core/secret_scan.py +25 -0
  313. core/secret_scrub.py +71 -0
  314. core/secrets.py +35 -0
  315. core/security_logging_filter.py +148 -0
  316. core/self_context_writer.py +333 -0
  317. core/self_evolution.py +294 -0
  318. core/session_context.py +47 -0
  319. core/sqlite_util.py +59 -0
  320. core/surfaces/__init__.py +16 -0
  321. core/surfaces/access.py +118 -0
  322. core/surfaces/binding.py +88 -0
  323. core/surfaces/bootstrap.py +78 -0
  324. core/surfaces/circuit.py +168 -0
  325. core/surfaces/continuity.py +77 -0
  326. core/surfaces/correspondents.py +228 -0
  327. core/surfaces/dispatcher.py +216 -0
  328. core/surfaces/envelopes.py +75 -0
  329. core/surfaces/gc.py +30 -0
  330. core/surfaces/idempotency.py +57 -0
  331. core/surfaces/inbound_webhook.py +124 -0
  332. core/surfaces/media.py +32 -0
  333. core/surfaces/message_router.py +91 -0
  334. core/surfaces/outbound_allowlist.py +80 -0
  335. core/surfaces/outbound_dispatcher.py +110 -0
  336. core/surfaces/outbound_mirror.py +37 -0
  337. core/surfaces/outbound_queue.py +107 -0
  338. core/surfaces/outbound_target.py +12 -0
  339. core/surfaces/owner_admin.py +29 -0
  340. core/surfaces/proactive.py +78 -0
  341. core/surfaces/progress.py +108 -0
  342. core/surfaces/rate_bucket.py +21 -0
  343. core/surfaces/registry.py +51 -0
  344. core/surfaces/rendering.py +53 -0
  345. core/surfaces/send_policy.py +14 -0
  346. core/surfaces/serialize.py +24 -0
  347. core/surfaces/session_chat_registry.py +112 -0
  348. core/surfaces/session_policy.py +60 -0
  349. core/surfaces/surface.py +288 -0
  350. core/surfaces/transcription.py +88 -0
  351. core/surfaces/voice_echo.py +26 -0
  352. core/surfaces/voice_guard.py +23 -0
  353. core/tickers.py +174 -0
  354. core/tool_catalog.py +192 -0
  355. core/version.py +75 -0
  356. core/wallet/__init__.py +5 -0
  357. core/wallet/agent_wallet.py +59 -0
  358. core/wallet/audit_sink.py +61 -0
  359. core/wallet/config.py +70 -0
  360. core/wallet/factory.py +87 -0
  361. core/wallet/policy.py +104 -0
  362. core/wallet/signer.py +51 -0
  363. cron/README.md +65 -0
  364. cron/__init__.py +0 -0
  365. cron/delivery.py +277 -0
  366. cron/digest.py +124 -0
  367. cron/jobs.py +207 -0
  368. cron/runner.py +297 -0
  369. cron/schedule.py +194 -0
  370. cron/scheduler.py +201 -0
  371. cron/service.py +57 -0
  372. cron/wake_gate.py +223 -0
  373. data/__init__.py +1 -0
  374. data/prompts/autov2_prompts.json +87 -0
  375. data/prompts/skills/browser-automation/SKILL.md +43 -0
  376. data/prompts/skills/coding-workflow/SKILL.md +36 -0
  377. data/prompts/skills/crypto-trading-safety/SKILL.md +53 -0
  378. data/prompts/skills/document-writing/SKILL.md +33 -0
  379. data/prompts/skills/email-comms/SKILL.md +33 -0
  380. data/prompts/skills/file-data-ops/SKILL.md +35 -0
  381. data/prompts/skills/hyperliquid-account-review/SKILL.md +48 -0
  382. data/prompts/skills/hyperliquid-market-data/SKILL.md +52 -0
  383. data/prompts/skills/hyperliquid-trading/SKILL.md +59 -0
  384. data/prompts/skills/lead-research/SKILL.md +86 -0
  385. data/prompts/skills/market-research-brief/SKILL.md +104 -0
  386. data/prompts/skills/person-analyzer/SKILL.md +124 -0
  387. data/prompts/skills/polymarket-market-research/SKILL.md +54 -0
  388. data/prompts/skills/polymarket-portfolio-review/SKILL.md +50 -0
  389. data/prompts/skills/polymarket-trading/SKILL.md +55 -0
  390. data/prompts/skills/presentation-creator/SKILL.md +36 -0
  391. data/prompts/skills/project-analyzer/SKILL.md +169 -0
  392. data/prompts/skills/rules.json +268 -0
  393. data/prompts/skills/secret-handling/SKILL.md +20 -0
  394. data/prompts/skills/skill-authoring/SKILL.md +31 -0
  395. data/prompts/skills/skill-security-review/SKILL.md +27 -0
  396. data/prompts/skills/social-discovery/SKILL.md +57 -0
  397. data/prompts/skills/task-planning/SKILL.md +33 -0
  398. data/prompts/skills/web-research/SKILL.md +39 -0
  399. data/prompts/skills/web-scraping/SKILL.md +73 -0
  400. data/prompts/skills/x-engagement/SKILL.md +69 -0
  401. data/prompts/system_prompts.json +4 -0
  402. data/subscription_channels.json +5 -0
  403. modules/README.md +503 -0
  404. modules/__init__.py +124 -0
  405. modules/auth/__init__.py +13 -0
  406. modules/auth/api_key_manager.py +157 -0
  407. modules/auth/identity_mapper.py +380 -0
  408. modules/auth/siwe_auth.py +273 -0
  409. modules/auth/tier_manager.py +173 -0
  410. modules/base_module.py +190 -0
  411. modules/credits/__init__.py +29 -0
  412. modules/credits/balance_manager.py +237 -0
  413. modules/credits/cost_utils.py +129 -0
  414. modules/credits/pricing.py +139 -0
  415. modules/credits/unified_ledger.py +148 -0
  416. modules/credits/usage_meter.py +310 -0
  417. modules/credits/usage_tracker.py +674 -0
  418. modules/database/__init__.py +33 -0
  419. modules/database/audit_log.py +322 -0
  420. modules/database/auth_tables.py +276 -0
  421. modules/database/connection.py +644 -0
  422. modules/database/connection_pool.py +305 -0
  423. modules/database/conversation_contexts.py +446 -0
  424. modules/database/database_manager.py +237 -0
  425. modules/database/hyperliquid.py +375 -0
  426. modules/database/polymarket.py +574 -0
  427. modules/database/user_mcp_servers.py +728 -0
  428. modules/database/user_profiles.py +562 -0
  429. modules/database/utils.py +107 -0
  430. modules/database/x402_tables.py +92 -0
  431. modules/eip8004/README.md +1069 -0
  432. modules/eip8004/__init__.py +65 -0
  433. modules/eip8004/contracts.py +498 -0
  434. modules/eip8004/models.py +271 -0
  435. modules/eip8004/registration.py +148 -0
  436. modules/eip8004/reputation.py +367 -0
  437. modules/eip8004/validation.py +277 -0
  438. modules/llm/__init__.py +97 -0
  439. modules/llm/adapters.py +963 -0
  440. modules/llm/anthropic_client.py +831 -0
  441. modules/llm/available_models.py +106 -0
  442. modules/llm/brain_scrubber.py +137 -0
  443. modules/llm/cache_hints.py +162 -0
  444. modules/llm/deepseek_client.py +562 -0
  445. modules/llm/gemini_client.py +1367 -0
  446. modules/llm/llm_client.py +1139 -0
  447. modules/llm/llm_client_registry.py +188 -0
  448. modules/llm/llm_factory.py +237 -0
  449. modules/llm/llm_manager.py +1036 -0
  450. modules/llm/messages.py +374 -0
  451. modules/llm/model_registry.py +1935 -0
  452. modules/llm/nvidia_client.py +125 -0
  453. modules/llm/openai_client.py +800 -0
  454. modules/llm/openrouter_client.py +969 -0
  455. modules/llm/profiles.py +178 -0
  456. modules/llm/test_anthropic_cache_capture.py +35 -0
  457. modules/llm/test_cached_pricing_derivation.py +24 -0
  458. modules/llm/think_scrubber.py +444 -0
  459. modules/llm/token_counter.py +268 -0
  460. modules/memory/__init__.py +35 -0
  461. modules/memory/backend_factory.py +83 -0
  462. modules/memory/cache_manager.py +186 -0
  463. modules/memory/episodic.py +108 -0
  464. modules/memory/local_vector_memory_provider.py +552 -0
  465. modules/memory/memory_manager.py +225 -0
  466. modules/memory/models.py +312 -0
  467. modules/memory/provider.py +210 -0
  468. modules/memory/registry.py +205 -0
  469. modules/memory/sqlite_memory_provider.py +767 -0
  470. modules/memory/task/__init__.py +52 -0
  471. modules/memory/task/compaction_manager.py +157 -0
  472. modules/memory/task/context_retriever.py +809 -0
  473. modules/memory/task/hierarchical_memory.py +1002 -0
  474. modules/memory/task/lexical_retriever.py +71 -0
  475. modules/memory/task/null_context_manager.py +213 -0
  476. modules/memory/task/phase_manager.py +625 -0
  477. modules/memory/task/reflection_service.py +157 -0
  478. modules/memory/task/semantic_retriever.py +218 -0
  479. modules/memory/task/task_context_manager.py +1165 -0
  480. modules/memory/task/test_forgetting_engages.py +24 -0
  481. modules/memory/task/test_reflection_llm.py +39 -0
  482. modules/memory/task/test_threat_scan.py +53 -0
  483. modules/memory/task/threat_scan.py +90 -0
  484. modules/memory/test_sqlite_memory_provider.py +106 -0
  485. modules/memory/user_profile_manager.py +527 -0
  486. modules/payments/__init__.py +11 -0
  487. modules/payments/deposit_monitor.py +478 -0
  488. modules/payments/price_oracle.py +70 -0
  489. modules/payments/treasury_sweeper.py +401 -0
  490. modules/payments/wallet_generator.py +145 -0
  491. modules/pfp/__init__.py +1 -0
  492. modules/pfp/config.py +92 -0
  493. modules/pfp/mesh.py +565 -0
  494. modules/pfp/push.py +69 -0
  495. modules/pfp/renderer.py +85 -0
  496. modules/pfp/store.py +82 -0
  497. modules/skills/__init__.py +1 -0
  498. modules/skills/skill_usage.py +248 -0
  499. modules/transcription/__init__.py +24 -0
  500. modules/transcription/base.py +20 -0
  501. modules/transcription/faster_whisper_transcriber.py +55 -0
  502. modules/x402/README.md +249 -0
  503. modules/x402/__init__.py +22 -0
  504. modules/x402/invoicing.py +416 -0
  505. modules/x402/middleware.py +364 -0
  506. modules/x402/settlement_watcher.py +145 -0
  507. modules/x402/x402_integration.py +344 -0
  508. polyrob-0.5.0.dist-info/METADATA +482 -0
  509. polyrob-0.5.0.dist-info/RECORD +745 -0
  510. polyrob-0.5.0.dist-info/WHEEL +5 -0
  511. polyrob-0.5.0.dist-info/entry_points.txt +2 -0
  512. polyrob-0.5.0.dist-info/licenses/LICENSE +21 -0
  513. polyrob-0.5.0.dist-info/top_level.txt +12 -0
  514. surfaces/README.md +70 -0
  515. surfaces/__init__.py +0 -0
  516. surfaces/email/__init__.py +0 -0
  517. surfaces/email/dedup.py +44 -0
  518. surfaces/email/harness.py +187 -0
  519. surfaces/email/inbound.py +159 -0
  520. surfaces/email/seed.py +60 -0
  521. surfaces/email/surface.py +105 -0
  522. surfaces/telegram/__init__.py +0 -0
  523. surfaces/telegram/dedup.py +83 -0
  524. surfaces/telegram/harness.py +886 -0
  525. surfaces/telegram/inbound.py +145 -0
  526. surfaces/telegram/interactive_tools.py +49 -0
  527. surfaces/telegram/markdown.py +347 -0
  528. surfaces/telegram/rate_limit.py +167 -0
  529. surfaces/telegram/surface.py +187 -0
  530. surfaces/telegram/voice.py +52 -0
  531. surfaces/whatsapp/__init__.py +0 -0
  532. surfaces/whatsapp/client.py +51 -0
  533. surfaces/whatsapp/harness.py +62 -0
  534. surfaces/whatsapp/inbound.py +132 -0
  535. surfaces/whatsapp/surface.py +64 -0
  536. surfaces/whatsapp/window.py +34 -0
  537. tools/README.md +578 -0
  538. tools/__init__.py +424 -0
  539. tools/alchemy/__init__.py +5 -0
  540. tools/alchemy/alchemy_tool.py +389 -0
  541. tools/anysite/__init__.py +17 -0
  542. tools/anysite/client.py +88 -0
  543. tools/anysite/tool.py +89 -0
  544. tools/base_tool.py +468 -0
  545. tools/browser/__init__.py +22 -0
  546. tools/browser/actions.py +118 -0
  547. tools/browser/browser.py +1457 -0
  548. tools/browser/browser_manager.py +690 -0
  549. tools/browser/context.py +1748 -0
  550. tools/browser/playwright_utils.py +137 -0
  551. tools/browser/views.py +56 -0
  552. tools/code_exec/SANDBOX_SECURITY.md +144 -0
  553. tools/code_exec/__init__.py +178 -0
  554. tools/code_exec/backend.py +73 -0
  555. tools/code_exec/backends/__init__.py +1 -0
  556. tools/code_exec/backends/docker.py +779 -0
  557. tools/code_exec/backends/local_subprocess.py +154 -0
  558. tools/code_exec/env_policy.py +45 -0
  559. tools/code_exec/result.py +42 -0
  560. tools/code_exec/sandbox_guard.py +59 -0
  561. tools/code_exec/tool.py +227 -0
  562. tools/coding/__init__.py +50 -0
  563. tools/coding/edit.py +107 -0
  564. tools/coding/search.py +113 -0
  565. tools/coding/tool.py +353 -0
  566. tools/collabland/__init__.py +5 -0
  567. tools/collabland/collabland_tool.py +471 -0
  568. tools/controller/__init__.py +0 -0
  569. tools/controller/_helpers.py +165 -0
  570. tools/controller/action_registration.py +1765 -0
  571. tools/controller/approval.py +244 -0
  572. tools/controller/approval_interactive.py +90 -0
  573. tools/controller/delegation.py +195 -0
  574. tools/controller/execution.py +797 -0
  575. tools/controller/execution_context.py +141 -0
  576. tools/controller/hooks.py +135 -0
  577. tools/controller/introspection.py +344 -0
  578. tools/controller/mcp_registrar.py +190 -0
  579. tools/controller/message_send.py +31 -0
  580. tools/controller/registry/__init__.py +4 -0
  581. tools/controller/registry/schema_generators.py +395 -0
  582. tools/controller/registry/schema_sanitizer.py +406 -0
  583. tools/controller/registry/service.py +1266 -0
  584. tools/controller/registry/views.py +151 -0
  585. tools/controller/service.py +409 -0
  586. tools/controller/tool_management.py +334 -0
  587. tools/controller/types.py +28 -0
  588. tools/controller/views.py +450 -0
  589. tools/cronjob_tools.py +166 -0
  590. tools/crypto_trade_gate.py +59 -0
  591. tools/descriptors.py +452 -0
  592. tools/dom/__init__.py +0 -0
  593. tools/dom/history_tree_processor/service.py +244 -0
  594. tools/dom/history_tree_processor/view.py +99 -0
  595. tools/dom/service.py +471 -0
  596. tools/dom/views.py +346 -0
  597. tools/email_tool.py +403 -0
  598. tools/exceptions.py +169 -0
  599. tools/filesystem.py +1038 -0
  600. tools/filesystem_docproc.py +331 -0
  601. tools/filesystem_pdf.py +755 -0
  602. tools/git/__init__.py +42 -0
  603. tools/git/tool.py +258 -0
  604. tools/github/__init__.py +33 -0
  605. tools/github/client.py +94 -0
  606. tools/github/tool.py +237 -0
  607. tools/goal_tools.py +309 -0
  608. tools/hyperliquid/__init__.py +56 -0
  609. tools/hyperliquid/models.py +233 -0
  610. tools/hyperliquid/service.py +1680 -0
  611. tools/knowledge_ingest.py +950 -0
  612. tools/mcp/README.md +535 -0
  613. tools/mcp/__init__.py +52 -0
  614. tools/mcp/catalog.py +115 -0
  615. tools/mcp/config.py +337 -0
  616. tools/mcp/mcp_tool.py +1415 -0
  617. tools/mcp/param_coercion.py +289 -0
  618. tools/mcp/protocol.py +1520 -0
  619. tools/mcp/rate_limit.py +50 -0
  620. tools/mcp/security.py +424 -0
  621. tools/mcp/self_install.py +111 -0
  622. tools/mcp/server_manager.py +829 -0
  623. tools/mcp/subscriptions.py +72 -0
  624. tools/mcp/user_mcp_service.py +899 -0
  625. tools/mcp/validation_tracker.py +89 -0
  626. tools/mcp/views.py +346 -0
  627. tools/oauth/__init__.py +17 -0
  628. tools/oauth/manager.py +75 -0
  629. tools/oauth/provider.py +69 -0
  630. tools/oauth/providers/__init__.py +1 -0
  631. tools/oauth/providers/generic_oauth2.py +96 -0
  632. tools/perplexity_tool.py +280 -0
  633. tools/polymarket/__init__.py +41 -0
  634. tools/polymarket/clob_adapter.py +76 -0
  635. tools/polymarket/models.py +182 -0
  636. tools/polymarket/service.py +2082 -0
  637. tools/self_env/__init__.py +61 -0
  638. tools/self_env/tool.py +274 -0
  639. tools/shell/__init__.py +80 -0
  640. tools/shell/backend_pool.py +118 -0
  641. tools/shell/discipline.py +62 -0
  642. tools/shell/executor.py +157 -0
  643. tools/shell/loopback_allow.py +87 -0
  644. tools/shell/process_registry.py +113 -0
  645. tools/shell/process_tool.py +131 -0
  646. tools/shell/state.py +129 -0
  647. tools/shell/tool.py +151 -0
  648. tools/task_tool.py +637 -0
  649. tools/twitter_tool.py +2086 -0
  650. tools/user_directory.py +179 -0
  651. tools/web_fetch/__init__.py +3 -0
  652. tools/web_fetch/fetcher.py +144 -0
  653. tools/web_fetch/render.py +44 -0
  654. tools/web_fetch/tool.py +60 -0
  655. tools/x402/__init__.py +60 -0
  656. tools/x402/client.py +47 -0
  657. tools/x402/invoice_tool.py +143 -0
  658. tools/x402/real_client.py +250 -0
  659. tools/x402/service.py +131 -0
  660. utils/README.md +498 -0
  661. utils/__init__.py +46 -0
  662. utils/auth_utils.py +114 -0
  663. utils/bounded_collections.py +162 -0
  664. utils/circuit_breaker.py +389 -0
  665. utils/gif_utils.py +435 -0
  666. utils/markdown_utils.py +291 -0
  667. utils/message_utils.py +147 -0
  668. utils/metrics.py +36 -0
  669. utils/path_validator.py +227 -0
  670. utils/rate_limit_manager.py +399 -0
  671. utils/result_size.py +296 -0
  672. utils/time_utils.py +206 -0
  673. utils/user_utils.py +188 -0
  674. webview/README.md +111 -0
  675. webview/RENAME_AND_ALIGN_HANDOFF.md +200 -0
  676. webview/__init__.py +8 -0
  677. webview/activity.py +636 -0
  678. webview/owner_auth.py +108 -0
  679. webview/pages.py +448 -0
  680. webview/repair_sessions.py +399 -0
  681. webview/server.py +4323 -0
  682. webview/server_launcher.py +112 -0
  683. webview/static/css/activity.css +89 -0
  684. webview/static/css/chat.css +1772 -0
  685. webview/static/css/components.css +1190 -0
  686. webview/static/css/config-panel.css +651 -0
  687. webview/static/css/pages/admin.css +766 -0
  688. webview/static/css/pages/profile.css +231 -0
  689. webview/static/css/pages/settings.css +297 -0
  690. webview/static/css/pages/signin.css +316 -0
  691. webview/static/css/style.css +4250 -0
  692. webview/static/css/variables.css +147 -0
  693. webview/static/css/workspace-fullwidth-fix.css +109 -0
  694. webview/static/img/favicon.ico +0 -0
  695. webview/static/js/activity.js +394 -0
  696. webview/static/js/admin/activity.js +186 -0
  697. webview/static/js/admin/dashboard.js +163 -0
  698. webview/static/js/admin/user_detail.js +400 -0
  699. webview/static/js/admin/users.js +174 -0
  700. webview/static/js/admin/utils.js +214 -0
  701. webview/static/js/chat.js +3178 -0
  702. webview/static/js/config-panel.js +522 -0
  703. webview/static/js/constants.js +20 -0
  704. webview/static/js/error-handler.js +226 -0
  705. webview/static/js/ethers.min.js +1 -0
  706. webview/static/js/event-filter.js +137 -0
  707. webview/static/js/event-store.js +351 -0
  708. webview/static/js/file-attachments.js +374 -0
  709. webview/static/js/file-loader.js +163 -0
  710. webview/static/js/index.js +103 -0
  711. webview/static/js/performance-utils.js +196 -0
  712. webview/static/js/profile.js +396 -0
  713. webview/static/js/screenshot.js +386 -0
  714. webview/static/js/session.js +1527 -0
  715. webview/static/js/settings.js +1288 -0
  716. webview/static/js/sidebar-data.js +766 -0
  717. webview/static/js/sidebar-toggle.js +296 -0
  718. webview/static/js/socket.io.min.js +7 -0
  719. webview/static/js/stats.js +355 -0
  720. webview/static/js/ui-utils.js +420 -0
  721. webview/static/js/workspace.js +966 -0
  722. webview/stats_service.py +613 -0
  723. webview/templates/__init__.py +1 -0
  724. webview/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  725. webview/templates/activity.html +36 -0
  726. webview/templates/admin/activity.html +122 -0
  727. webview/templates/admin/dashboard.html +112 -0
  728. webview/templates/admin/user_detail.html +228 -0
  729. webview/templates/admin/users.html +105 -0
  730. webview/templates/autonomy.html +60 -0
  731. webview/templates/error.html +133 -0
  732. webview/templates/finance.html +90 -0
  733. webview/templates/identity.html +73 -0
  734. webview/templates/index.html +42 -0
  735. webview/templates/layout.html +125 -0
  736. webview/templates/memory.html +59 -0
  737. webview/templates/owner_login.html +15 -0
  738. webview/templates/profile.html +121 -0
  739. webview/templates/session.html +312 -0
  740. webview/templates/settings.html +534 -0
  741. webview/templates/sidebar.html +112 -0
  742. webview/templates/signin.html +213 -0
  743. webview/templates/status.html +14 -0
  744. webview/templates/system.html +45 -0
  745. webview/webgate.py +196 -0
@@ -0,0 +1,766 @@
1
+ /* Sidebar data management for WebView */
2
+ import { setText, fetchJSON, on, emit, sessionState, logger } from '/static/js/ui-utils.js?v=2';
3
+
4
+ // Refresh state tracking
5
+ const REFRESH_INTERVAL = 15000; // 15 seconds
6
+ let refreshTimer = null;
7
+ let isRefreshing = false;
8
+ let lastRefreshTime = {
9
+ session: 0,
10
+ task: 0,
11
+ agents: 0,
12
+ services: 0,
13
+ skills: 0
14
+ };
15
+
16
+ // Create debounce cache to prevent overlapping requests
17
+ const _inflightTokens = {
18
+ task: 0,
19
+ agents: 0,
20
+ services: 0,
21
+ session: 0,
22
+ skills: 0
23
+ };
24
+
25
+ function _nextToken(kind) {
26
+ _inflightTokens[kind] = (_inflightTokens[kind] || 0) + 1;
27
+ return _inflightTokens[kind];
28
+ }
29
+
30
+ function _isLatest(kind, token) {
31
+ return token === _inflightTokens[kind];
32
+ }
33
+
34
+ // Track in-flight requests
35
+ const _inflightRequests = {
36
+ agents: null,
37
+ services: null,
38
+ task: null,
39
+ session: null,
40
+ skills: null
41
+ };
42
+
43
+ document.addEventListener('DOMContentLoaded', function() {
44
+ // Initialize sidebar data once
45
+ refreshSidebar('all');
46
+
47
+ // Set up auto-refresh with a single timer that handles all updates
48
+ refreshTimer = setInterval(() => {
49
+ // Only refresh if page is visible and we're not already refreshing
50
+ if (document.visibilityState === 'visible' && !isRefreshing) {
51
+ refreshSidebar('all');
52
+ }
53
+ }, REFRESH_INTERVAL);
54
+
55
+ // Listen for specific refresh requests from other modules
56
+ on('sidebar:refreshRequest', (event) => {
57
+ const kind = event.detail?.kind || 'all';
58
+ refreshSidebar(kind);
59
+ });
60
+
61
+ // Pause refreshes when page is hidden
62
+ document.addEventListener('visibilitychange', () => {
63
+ if (document.visibilityState === 'hidden') {
64
+ logger.debug('[Sidebar] Page hidden, pausing sidebar refreshes');
65
+ } else {
66
+ logger.debug('[Sidebar] Page visible, resuming sidebar refreshes');
67
+ // Refresh immediately when becoming visible again
68
+ refreshSidebar('all');
69
+ }
70
+ });
71
+ });
72
+
73
+ /**
74
+ * Central refresh function that manages all sidebar data updates
75
+ * @param {string} kind - What to refresh: 'all', 'session', 'task', 'agents', or 'services'
76
+ * @param {boolean} force - Force refresh regardless of timing
77
+ */
78
+ function refreshSidebar(kind = 'all', force = false) {
79
+ // Don't try to load data for new sessions (empty state)
80
+ const sessionId = sessionState.sessionId;
81
+
82
+ if (!sessionId || sessionState.isNew) {
83
+ logger.debug('[Sidebar] Skipping refresh - no active session yet');
84
+ return;
85
+ }
86
+
87
+ if (isRefreshing && !force) return;
88
+
89
+ logger.debug(`[Sidebar] Refreshing sidebar: ${kind}`);
90
+ isRefreshing = true;
91
+
92
+ const now = Date.now();
93
+ const debounceTime = 2000; // 2 second debounce
94
+
95
+ try {
96
+ if (kind === 'all' || kind === 'session') {
97
+ if (force || now - lastRefreshTime.session > debounceTime) {
98
+ updateSessionInfo();
99
+ lastRefreshTime.session = now;
100
+ }
101
+ }
102
+
103
+ if (kind === 'all' || kind === 'task') {
104
+ if (force || now - lastRefreshTime.task > debounceTime) {
105
+ loadTask();
106
+ lastRefreshTime.task = now;
107
+ }
108
+ }
109
+
110
+ if (kind === 'all' || kind === 'agents') {
111
+ if (force || now - lastRefreshTime.agents > debounceTime) {
112
+ loadAgents();
113
+ lastRefreshTime.agents = now;
114
+ }
115
+ }
116
+
117
+ if (kind === 'all' || kind === 'services') {
118
+ if (force || now - lastRefreshTime.services > debounceTime) {
119
+ loadServices();
120
+ lastRefreshTime.services = now;
121
+ }
122
+ }
123
+
124
+ if (kind === 'all' || kind === 'skills') {
125
+ if (force || now - lastRefreshTime.skills > debounceTime) {
126
+ loadSkills();
127
+ lastRefreshTime.skills = now;
128
+ }
129
+ }
130
+ } finally {
131
+ isRefreshing = false;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Update session information in the sidebar
137
+ */
138
+ function updateSessionInfo() {
139
+ const sessionId = sessionState.sessionId;
140
+ if (!sessionId) return;
141
+
142
+ const token = _nextToken('session');
143
+ logger.debug('[Sidebar] Updating session info for', sessionId);
144
+
145
+ // Don't start a new request if one is already in progress
146
+ if (_inflightRequests.session) {
147
+ logger.debug('[Sidebar] Session info request already in progress, skipping');
148
+ return;
149
+ }
150
+
151
+ // Update session ID (should already be in the template, but just in case)
152
+ const sessionIdEl = document.getElementById('session-id');
153
+ if (sessionIdEl) {
154
+ sessionIdEl.textContent = sessionId;
155
+ }
156
+
157
+ // Get session status and update it
158
+ try {
159
+ // Set in-flight request
160
+ _inflightRequests.session = true;
161
+
162
+ // Use fetchJSON utility with proper error handling
163
+ fetchJSON(`/api/session/${sessionId}/status`)
164
+ .then(data => {
165
+ // Clear in-flight request
166
+ _inflightRequests.session = null;
167
+
168
+ // Guard against race
169
+ if (!_isLatest('session', token)) {
170
+ logger.debug('[Sidebar] Discarding stale session response');
171
+ return;
172
+ }
173
+
174
+ logger.debug('[Sidebar] Session status response:', data);
175
+ const statusEl = document.getElementById('session-status');
176
+ if (statusEl) {
177
+ if (data && data.status) {
178
+ // Format the status: capitalize first letter
179
+ const formattedStatus = data.status.charAt(0).toUpperCase() + data.status.slice(1);
180
+ statusEl.textContent = formattedStatus;
181
+ logger.debug('[Sidebar] Updated session status to:', formattedStatus);
182
+
183
+ // Add status class for styling
184
+ statusEl.className = ''; // Clear existing classes
185
+ if (data.status === 'running' || data.status === 'active') {
186
+ statusEl.classList.add('status-running');
187
+ } else if (data.status === 'completed' || data.status === 'success') {
188
+ statusEl.classList.add('status-completed');
189
+ } else if (data.status === 'failed' || data.status === 'error') {
190
+ statusEl.classList.add('status-failed');
191
+ }
192
+ } else {
193
+ statusEl.textContent = 'Unknown';
194
+ logger.debug('[Sidebar] No status in response, setting to Unknown');
195
+ }
196
+ }
197
+
198
+ // Also update session duration if available
199
+ if (data && data.created_at) {
200
+ updateSessionDuration(data.created_at);
201
+ }
202
+
203
+ // Emit event that session info is updated
204
+ emit('sidebar:sessionUpdated', { status: data?.status });
205
+ })
206
+ .catch(err => {
207
+ // Clear in-flight request on error
208
+ _inflightRequests.session = null;
209
+
210
+ logger.warn('[Sidebar] Failed to fetch session status:', err);
211
+ // Set a fallback status on error
212
+ const statusEl = document.getElementById('session-status');
213
+ if (statusEl) {
214
+ statusEl.textContent = 'Unknown';
215
+ }
216
+ });
217
+ } catch (e) {
218
+ // Clear in-flight request
219
+ _inflightRequests.session = null;
220
+ logger.warn('[Sidebar] Error in updateSessionInfo:', e);
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Update the session duration display
226
+ * @param {number} createdAt - Timestamp when session was created
227
+ */
228
+ function updateSessionDuration(createdAt) {
229
+ const durationEl = document.getElementById('session-duration');
230
+ if (!durationEl || !createdAt) return;
231
+
232
+ // Calculate duration
233
+ const now = Date.now() / 1000;
234
+ const startTime = Number(createdAt);
235
+ const duration = now - startTime;
236
+
237
+ // Format duration
238
+ let formattedDuration = '';
239
+ if (duration < 60) {
240
+ formattedDuration = `${Math.floor(duration)}s`;
241
+ } else if (duration < 3600) {
242
+ const minutes = Math.floor(duration / 60);
243
+ const seconds = Math.floor(duration % 60);
244
+ formattedDuration = `${minutes}m ${seconds}s`;
245
+ } else {
246
+ const hours = Math.floor(duration / 3600);
247
+ const minutes = Math.floor((duration % 3600) / 60);
248
+ formattedDuration = `${hours}h ${minutes}m`;
249
+ }
250
+
251
+ durationEl.textContent = formattedDuration;
252
+ logger.debug('[Sidebar] Updated session duration:', formattedDuration);
253
+
254
+ // Schedule next update in 1 second
255
+ setTimeout(() => updateSessionDuration(createdAt), 1000);
256
+ }
257
+
258
+ /**
259
+ * Load agents information for the session
260
+ */
261
+ async function loadAgents() {
262
+ const sessionId = sessionState.sessionId;
263
+ if (!sessionId) return;
264
+
265
+ const token = _nextToken('agents');
266
+ const agentsContainer = document.getElementById('agents-container');
267
+
268
+ if (!agentsContainer) return;
269
+
270
+ // Don't start a new request if one is already in progress
271
+ if (_inflightRequests.agents) {
272
+ logger.debug('[Sidebar] Agents request already in progress, skipping');
273
+ return;
274
+ }
275
+
276
+ try {
277
+ // Store current HTML before updating to avoid flicker
278
+ const currentContent = agentsContainer.innerHTML;
279
+
280
+ // Add cache-busting parameter to force a fresh load without caching
281
+ const timestamp = new Date().getTime();
282
+ const url = `/api/session/${sessionId}/agents?nocache=${timestamp}`;
283
+
284
+ // Set the in-flight request
285
+ _inflightRequests.agents = url;
286
+
287
+ // Fetch agents data using the utility function with the non-cached URL
288
+ const result = await fetchJSON(url);
289
+
290
+ // Clear in-flight request now that it's done
291
+ _inflightRequests.agents = null;
292
+
293
+ // Guard against race – if another call was triggered afterwards we
294
+ // ignore this stale result.
295
+ if (!_isLatest('agents', token)) {
296
+ logger.debug('[Sidebar] Discarding stale agents response');
297
+ return;
298
+ }
299
+
300
+ logger.debug('[Sidebar] Agents data:', result);
301
+
302
+ // Update the agents container
303
+ if (result.agents && result.agents.length > 0) {
304
+ const agentsHtml = result.agents.map(agent => {
305
+ // Extract agent data using consistent field names
306
+ // Support both field naming conventions for compatibility
307
+ const agentId = agent.id || agent.agent_id || 'unknown';
308
+ const agentName = agent.name || agent.agent_name || '';
309
+
310
+ // Properly format agent type - ensure full agent type name
311
+ let agentType = agent.type || agent.agent_type || 'Unknown';
312
+
313
+ // Add "Agent" suffix if missing and not already containing "Agent"
314
+ if (!agentType.includes("Agent") && agentType !== "Unknown") {
315
+ // Special handling for common agent types
316
+ if (agentType.toLowerCase() === "planner") {
317
+ agentType = "PlannerAgent";
318
+ } else if (agentType.toLowerCase() === "executor") {
319
+ agentType = "ExecutorAgent";
320
+ } else if (agentType.toLowerCase() === "evaluator") {
321
+ agentType = "EvaluatorAgent";
322
+ } else if (agentType.toLowerCase() === "orchestrator") {
323
+ agentType = "SessionOrchestrator";
324
+ } else {
325
+ agentType = `${agentType}Agent`;
326
+ }
327
+ }
328
+
329
+ // Get model name - check both field naming conventions
330
+ let agentModel = agent.model || agent.model_name || '';
331
+
332
+ // Clean up "Unknown" or empty values
333
+ if (!agentModel || agentModel === 'Unknown' || agentModel === 'None') {
334
+ agentModel = '';
335
+ }
336
+
337
+ // Log model information for debugging
338
+ logger.debug(`[Sidebar] Agent "${agentName}" model: "${agentModel}", type: ${agentType}`);
339
+
340
+ // Determine agent role/badge based on name or type - use generic approach
341
+ // Extract role from agent name - simply use agent name or type as badge
342
+ let role = '';
343
+ if (agentName) {
344
+ role = agentName.toLowerCase();
345
+ } else if (agentType && agentType !== 'Unknown') {
346
+ role = agentType.toLowerCase().replace('agent', '').replace('session', '');
347
+ } else {
348
+ role = 'agent';
349
+ }
350
+
351
+ // Use role name as the display title, properly formatted
352
+ let roleDisplay = role.charAt(0).toUpperCase() + role.slice(1);
353
+
354
+ // Properly clean up common agent roles for display
355
+ if (roleDisplay === "Executor") roleDisplay = "Executor";
356
+ if (roleDisplay === "Planner") roleDisplay = "Planner";
357
+ if (roleDisplay === "Evaluator") roleDisplay = "Evaluator";
358
+ if (roleDisplay === "Orchestrator") roleDisplay = "Orchestrator";
359
+
360
+ return `
361
+ <div class="agent-item">
362
+ <div class="agent-info-row">
363
+ <div class="agent-role">${roleDisplay}</div>
364
+ <div class="agent-type">${agentType}</div>
365
+ ${agentModel ? `<div class="agent-model" title="${agentModel}">${agentModel}</div>` : ''}
366
+ </div>
367
+ </div>
368
+ `;
369
+ }).join('');
370
+
371
+ // Compare with existing content before updating to avoid DOM flicker
372
+ const newContent = agentsHtml;
373
+ if (newContent !== currentContent) {
374
+ agentsContainer.innerHTML = newContent;
375
+ }
376
+ } else {
377
+ // Only update if necessary
378
+ if (currentContent !== '<div class="empty-state">No agents available</div>') {
379
+ agentsContainer.innerHTML = '<div class="empty-state">No agents available</div>';
380
+ }
381
+ }
382
+
383
+ // Emit event that agents are updated
384
+ emit('sidebar:agentsUpdated');
385
+ } catch (error) {
386
+ // Clear in-flight request on error
387
+ _inflightRequests.agents = null;
388
+
389
+ logger.error('Error loading agents:', error);
390
+ // Only update with error if not already showing an error
391
+ if (!agentsContainer.innerHTML.includes('error-message')) {
392
+ agentsContainer.innerHTML = `<div class="error-message">Error loading agents: ${error.message}</div>`;
393
+ }
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Load services information for the session
399
+ */
400
+ async function loadServices() {
401
+ const sessionId = sessionState.sessionId;
402
+ if (!sessionId) return;
403
+
404
+ const token = _nextToken('services');
405
+ const servicesContainer = document.getElementById('services-container');
406
+
407
+ if (!servicesContainer) return;
408
+
409
+ // Don't start a new request if one is already in progress
410
+ if (_inflightRequests.services) {
411
+ logger.debug('[Sidebar] Services request already in progress, skipping');
412
+ return;
413
+ }
414
+
415
+ try {
416
+ // Store current HTML before updating to avoid flicker
417
+ const currentContent = servicesContainer.innerHTML;
418
+
419
+ // Add cache-busting parameter to force a fresh load without caching
420
+ const timestamp = new Date().getTime();
421
+ const url = `/api/session/${sessionId}/services?nocache=${timestamp}`;
422
+
423
+ // Set the in-flight request
424
+ _inflightRequests.services = url;
425
+
426
+ // Fetch services data using the utility function with the non-cached URL
427
+ const result = await fetchJSON(url);
428
+
429
+ // Clear in-flight request now that it's done
430
+ _inflightRequests.services = null;
431
+
432
+ // Guard against race – if another call was triggered afterwards we
433
+ // ignore this stale result.
434
+ if (!_isLatest('services', token)) {
435
+ logger.debug('[Sidebar] Discarding stale services response');
436
+ return;
437
+ }
438
+
439
+ // Update the services container
440
+ if (result.services && result.services.length > 0) {
441
+ // Sort services by name (safely)
442
+ const sortedServices = [...result.services].sort((a, b) => {
443
+ const nameA = (a.name || 'Unknown').toString();
444
+ const nameB = (b.name || 'Unknown').toString();
445
+ return nameA.localeCompare(nameB);
446
+ });
447
+
448
+ let servicesHtml = '';
449
+
450
+ // Create service tiles with name and description only (no action count)
451
+ for (const service of sortedServices) {
452
+ const serviceName = service.name || 'Unknown';
453
+ const rawDesc = service.description || '';
454
+ const hasCustomDesc = rawDesc && rawDesc.toLowerCase() !== 'no description available';
455
+
456
+ servicesHtml += `
457
+ <div class="service-tile sidebar-tile">
458
+ <div class="service-name">${serviceName}</div>
459
+ ${hasCustomDesc ? `<div class="service-description">${rawDesc}</div>` : ''}
460
+ </div>
461
+ `;
462
+ }
463
+
464
+ // Only update DOM if content has changed
465
+ if (servicesHtml !== currentContent) {
466
+ servicesContainer.innerHTML = servicesHtml;
467
+ }
468
+ } else {
469
+ // Only update if necessary
470
+ if (currentContent !== '<div class="empty-state">No services available</div>') {
471
+ servicesContainer.innerHTML = '<div class="empty-state">No services available</div>';
472
+ }
473
+ }
474
+
475
+ // Emit event that services are updated
476
+ emit('sidebar:servicesUpdated');
477
+ } catch (error) {
478
+ // Clear in-flight request on error
479
+ _inflightRequests.services = null;
480
+
481
+ logger.error('Error loading services:', error);
482
+ // Only update with error if not already showing an error
483
+ if (!servicesContainer.innerHTML.includes('error-message')) {
484
+ servicesContainer.innerHTML = `<div class="error-message">Error loading services: ${error.message}</div>`;
485
+ }
486
+ }
487
+ }
488
+
489
+ /**
490
+ * Load the task information
491
+ */
492
+ async function loadTask() {
493
+ const sessionId = sessionState.sessionId;
494
+ if (!sessionId) return;
495
+
496
+ const token = _nextToken('task');
497
+ const taskDisplay = document.getElementById('task-display');
498
+ const currentTaskText = document.getElementById('current-task-text');
499
+
500
+ if (!taskDisplay) return;
501
+
502
+ // Don't start a new request if one is already in progress
503
+ if (_inflightRequests.task) {
504
+ logger.debug('[Sidebar] Task request already in progress, skipping');
505
+ return;
506
+ }
507
+
508
+ try {
509
+ logger.debug(`[Sidebar] Fetching task data for session ${sessionId}`);
510
+
511
+ // Store current content to avoid flicker
512
+ const currentContent = taskDisplay.textContent;
513
+
514
+ // Set the in-flight request
515
+ _inflightRequests.task = true;
516
+
517
+ fetch('/api/session/' + sessionId + '/task')
518
+ .then(response => {
519
+ logger.debug(`[Sidebar] Direct fetch response:`, response);
520
+ if (!response.ok) {
521
+ logger.error(`[Sidebar] Task API returned error:`, response.status);
522
+ throw new Error(`Failed to fetch task: ${response.statusText}`);
523
+ }
524
+ return response.json();
525
+ })
526
+ .then(data => {
527
+ // Clear in-flight request
528
+ _inflightRequests.task = null;
529
+
530
+ // Guard against race – if another call was triggered afterwards we
531
+ // ignore this stale result.
532
+ if (!_isLatest('task', token)) {
533
+ logger.debug('[Sidebar] Discarding stale task response');
534
+ return;
535
+ }
536
+
537
+ logger.debug(`[Sidebar] Task API response:`, data);
538
+
539
+ // Handle different response formats and statuses
540
+ if (data && data.status === "ok" && data.task) {
541
+ // We have a valid initial task
542
+ logger.debug(`[Sidebar] Task found: "${data.task}"`);
543
+
544
+ // Store the initial task once we retrieve it, to avoid showing dynamic task updates
545
+ if (!window.initialTaskSet) {
546
+ // Only update if the content has changed
547
+ if (taskDisplay.textContent !== data.task) {
548
+ taskDisplay.textContent = data.task;
549
+
550
+ // Update page title with task
551
+ document.title = `Session: ${sessionId} - ${data.task.substring(0, 30)}${data.task.length > 30 ? '...' : ''}`;
552
+
553
+ // Mark that we've set the initial task
554
+ window.initialTaskSet = true;
555
+
556
+ // Store task in localStorage to preserve between page refreshes
557
+ try {
558
+ localStorage.setItem(`task_${sessionId}`, data.task);
559
+ } catch (e) {
560
+ logger.error('[Sidebar] Error storing task in localStorage:', e);
561
+ }
562
+ }
563
+ } else {
564
+ logger.debug('[Sidebar] Initial task already set, not updating with new task data');
565
+ }
566
+
567
+ // Always update the current task text (status) - this is independent of the task description
568
+ if (currentTaskText) {
569
+ // For the status, we can use either current_status if available, or status
570
+ const statusText = data.current_status || data.status || 'Running';
571
+ if (currentTaskText.textContent !== statusText) {
572
+ currentTaskText.textContent = statusText;
573
+ }
574
+ }
575
+ }
576
+ else if (data && data.status === "not_found") {
577
+ // Check if we have a stored task first
578
+ const storedTask = localStorage.getItem(`task_${sessionId}`);
579
+ if (storedTask) {
580
+ logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
581
+ taskDisplay.textContent = storedTask;
582
+ window.initialTaskSet = true;
583
+ } else {
584
+ // No task found but response was valid
585
+ logger.debug(`[Sidebar] No task data available`);
586
+ if (taskDisplay.textContent !== 'No task specified') {
587
+ taskDisplay.textContent = 'No task specified';
588
+
589
+ // Update page title with just session ID
590
+ document.title = `Session: ${sessionId}`;
591
+ }
592
+ }
593
+ }
594
+ else if (data && data.task === "") {
595
+ // Check if we have a stored task first
596
+ const storedTask = localStorage.getItem(`task_${sessionId}`);
597
+ if (storedTask) {
598
+ logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
599
+ taskDisplay.textContent = storedTask;
600
+ window.initialTaskSet = true;
601
+ } else {
602
+ // Empty task string
603
+ logger.debug(`[Sidebar] Empty task string received`);
604
+ if (taskDisplay.textContent !== 'No task specified') {
605
+ taskDisplay.textContent = 'No task specified';
606
+
607
+ // Update page title with just session ID
608
+ document.title = `Session: ${sessionId}`;
609
+ }
610
+ }
611
+ }
612
+ else {
613
+ // Check if we have a stored task first
614
+ const storedTask = localStorage.getItem(`task_${sessionId}`);
615
+ if (storedTask) {
616
+ logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
617
+ taskDisplay.textContent = storedTask;
618
+ window.initialTaskSet = true;
619
+ } else {
620
+ // Some other response format
621
+ logger.debug(`[Sidebar] Unexpected task response format`);
622
+ if (data && typeof data === "string" && data.trim().length > 0) {
623
+ // If data is a non-empty string, use it as the task
624
+ logger.debug(`[Sidebar] Task found: "${data}"`);
625
+ if (taskDisplay.textContent !== data) {
626
+ taskDisplay.textContent = data;
627
+ window.initialTaskSet = true;
628
+
629
+ // Store task in localStorage
630
+ try {
631
+ localStorage.setItem(`task_${sessionId}`, data);
632
+ } catch (e) {
633
+ logger.error('[Sidebar] Error storing task in localStorage:', e);
634
+ }
635
+ }
636
+ } else {
637
+ if (taskDisplay.textContent !== 'No task specified') {
638
+ taskDisplay.textContent = 'No task specified';
639
+
640
+ // Update page title with just session ID
641
+ document.title = `Session: ${sessionId}`;
642
+ }
643
+ }
644
+ }
645
+ }
646
+
647
+ // Emit event that task is updated
648
+ emit('sidebar:taskUpdated');
649
+ })
650
+ .catch(error => {
651
+ // Clear in-flight request on error
652
+ _inflightRequests.task = null;
653
+
654
+ logger.error(`[Sidebar] Error fetching task:`, error);
655
+ // Check if we have a stored task
656
+ const storedTask = localStorage.getItem(`task_${sessionId}`);
657
+ if (storedTask) {
658
+ logger.debug(`[Sidebar] Using stored task on error: "${storedTask}"`);
659
+ taskDisplay.textContent = storedTask;
660
+ } else if (taskDisplay.textContent !== 'Error loading task information') {
661
+ taskDisplay.textContent = 'Error loading task information';
662
+ }
663
+ });
664
+ } catch (error) {
665
+ // Clear in-flight request on error
666
+ _inflightRequests.task = null;
667
+
668
+ logger.error('[Sidebar] Error loading task:', error);
669
+ // Check for stored task on error
670
+ const storedTask = localStorage.getItem(`task_${sessionId}`);
671
+ if (storedTask) {
672
+ logger.debug(`[Sidebar] Using stored task on error: "${storedTask}"`);
673
+ taskDisplay.textContent = storedTask;
674
+ } else if (taskDisplay.textContent !== 'Error loading task information') {
675
+ taskDisplay.textContent = 'Error loading task information';
676
+ }
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Load skills information for the session
682
+ */
683
+ async function loadSkills() {
684
+ const sessionId = sessionState.sessionId;
685
+ if (!sessionId) return;
686
+
687
+ const token = _nextToken('skills');
688
+ const skillsContainer = document.getElementById('skills-container');
689
+
690
+ if (!skillsContainer) return;
691
+
692
+ // Don't start a new request if one is already in progress
693
+ if (_inflightRequests.skills) {
694
+ logger.debug('[Sidebar] Skills request already in progress, skipping');
695
+ return;
696
+ }
697
+
698
+ try {
699
+ // Store current HTML before updating to avoid flicker
700
+ const currentContent = skillsContainer.innerHTML;
701
+
702
+ // Add cache-busting parameter to force a fresh load without caching
703
+ const timestamp = new Date().getTime();
704
+ const url = `/api/session/${sessionId}/skills?nocache=${timestamp}`;
705
+
706
+ // Set the in-flight request
707
+ _inflightRequests.skills = url;
708
+
709
+ // Fetch skills data
710
+ const result = await fetchJSON(url);
711
+
712
+ // Clear in-flight request now that it's done
713
+ _inflightRequests.skills = null;
714
+
715
+ // Guard against race
716
+ if (!_isLatest('skills', token)) {
717
+ logger.debug('[Sidebar] Discarding stale skills response');
718
+ return;
719
+ }
720
+
721
+ logger.debug('[Sidebar] Skills data:', result);
722
+
723
+ // Update the skills container
724
+ if (result.skills && result.skills.length > 0) {
725
+ const skillsHtml = result.skills.map(skill => {
726
+ const skillId = skill.id || skill.skill_id || 'unknown';
727
+ const skillName = skill.name || skillId;
728
+ const isUserSkill = skill.type === 'user' || skill.is_user_skill;
729
+
730
+ return `
731
+ <div class="service-tile sidebar-tile">
732
+ <div class="service-name">
733
+ ${skillName}
734
+ ${isUserSkill ? '<span class="skill-badge custom">Custom</span>' : ''}
735
+ </div>
736
+ </div>
737
+ `;
738
+ }).join('');
739
+
740
+ // Only update DOM if content has changed
741
+ if (skillsHtml !== currentContent) {
742
+ skillsContainer.innerHTML = skillsHtml;
743
+ }
744
+ } else {
745
+ // Only update if necessary
746
+ if (currentContent !== '<div class="empty-state compact">No skills loaded</div>') {
747
+ skillsContainer.innerHTML = '<div class="empty-state compact">No skills loaded</div>';
748
+ }
749
+ }
750
+
751
+ // Emit event that skills are updated
752
+ emit('sidebar:skillsUpdated');
753
+ } catch (error) {
754
+ // Clear in-flight request on error
755
+ _inflightRequests.skills = null;
756
+
757
+ // Skills endpoint may not exist yet, just show empty state
758
+ logger.debug('[Sidebar] Skills API not available:', error.message);
759
+ if (!skillsContainer.innerHTML.includes('No skills loaded')) {
760
+ skillsContainer.innerHTML = '<div class="empty-state compact">No skills loaded</div>';
761
+ }
762
+ }
763
+ }
764
+
765
+ // Export functions for use in other modules
766
+ export { refreshSidebar, updateSessionInfo, loadTask, loadAgents, loadServices, loadSkills };