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,882 @@
1
+ from abc import ABC, abstractmethod
2
+ from dataclasses import asdict, dataclass, is_dataclass
3
+ from typing import Any, Dict, List, Optional, Union
4
+ import time
5
+ from datetime import datetime
6
+ from agents.task.path import pm
7
+
8
+
9
+ @dataclass
10
+ class BaseTelemetryEvent(ABC):
11
+ @property
12
+ @abstractmethod
13
+ def name(self) -> str:
14
+ pass
15
+
16
+ @property
17
+ def properties(self) -> Dict[str, Any]:
18
+ try:
19
+ # Import and check if the object is a dataclass before using asdict
20
+ if is_dataclass(self):
21
+ return {k: v for k, v in asdict(self).items() if k != 'name'}
22
+ # Fallback for non-dataclass instances
23
+ return {k: v for k, v in self.__dict__.items() if k != 'name' and not k.startswith('_')}
24
+ except (TypeError, ValueError, ImportError):
25
+ # Fallback for any errors or if is_dataclass is not available
26
+ return {k: v for k, v in self.__dict__.items() if k != 'name' and not k.startswith('_')}
27
+
28
+ def get_session_id(self) -> Optional[str]:
29
+ """Get the session ID associated with this event.
30
+
31
+ Default implementation checks common attributes that might contain the session ID.
32
+ Override this method in subclasses to provide more specific session ID extraction.
33
+
34
+ Returns:
35
+ The session ID or None if not found
36
+ """
37
+ # Check for explicit session_id attribute
38
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
39
+ # Session ID already cleaned by session creator
40
+ return getattr(self, 'session_id')
41
+
42
+ # Check for parent_session_id attribute (used in relationship events)
43
+ if hasattr(self, 'parent_session_id') and getattr(self, 'parent_session_id'):
44
+ # Session ID already cleaned by session creator
45
+ return getattr(self, 'parent_session_id')
46
+
47
+ # Try to extract from agent_id if available
48
+ if hasattr(self, 'agent_id') and getattr(self, 'agent_id'):
49
+ from agents.task.utils import extract_session_from_agent_id
50
+ agent_id = getattr(self, 'agent_id')
51
+ return extract_session_from_agent_id(agent_id)
52
+
53
+ return None
54
+
55
+
56
+ @dataclass
57
+ class RegisteredFunction:
58
+ name: str
59
+ params: dict[str, Any]
60
+ service: str = "default" # Track which service the function belongs to
61
+
62
+
63
+ @dataclass
64
+ class ControllerRegisteredFunctionsTelemetryEvent(BaseTelemetryEvent):
65
+ registered_functions: list[RegisteredFunction]
66
+ name: str = 'controller_registered_functions'
67
+
68
+
69
+ @dataclass
70
+ class AgentStepTelemetryEvent(BaseTelemetryEvent):
71
+ agent_id: str
72
+ step: int
73
+ step_error: list[str]
74
+ consecutive_failures: int
75
+ actions: list[dict]
76
+ service_actions: Optional[list[str]] = None # Track actions by service type
77
+ action_details: Optional[Dict[str, Any]] = None # Additional action details
78
+ agent_name: Optional[str] = None # Add agent name
79
+ agent_type: Optional[str] = None # Add agent type
80
+ task_progress: Optional[str] = None # Add task progress
81
+ current_task: Optional[str] = None # Add current task
82
+ reasoning: Optional[str] = None # Add reasoning field
83
+ context_data: Optional[Dict[str, Any]] = None # Additional context data
84
+
85
+ # Iteration metadata for enhanced UI rendering
86
+ iteration: Optional[int] = None # Logical iteration number (1-indexed)
87
+ iteration_type: str = "mixed" # thinking, browser, filesystem, mcp, mixed, done
88
+ iteration_status: str = "active" # active, completed, partial, failed, thinking, cancelled, timeout, done
89
+
90
+ # File tracking per iteration
91
+ files_created: Optional[List[str]] = None
92
+ files_modified: Optional[List[str]] = None
93
+ files_read: Optional[List[str]] = None
94
+ files_deleted: Optional[List[str]] = None
95
+
96
+ # Error/warning info
97
+ error_message: Optional[str] = None
98
+ loop_warning: Optional[str] = None
99
+ is_done: bool = False
100
+
101
+ # Synthesis indicator
102
+ reasoning_synthesized: bool = False
103
+
104
+ name: str = 'agent_step'
105
+
106
+ def __post_init__(self):
107
+ """Initialize optional fields and extract agent name from agent_id.
108
+
109
+ Note: Service detection and action categorization moved to formatters.py
110
+ where it belongs (presentation layer, not data layer).
111
+ """
112
+ if self.service_actions is None:
113
+ self.service_actions = []
114
+
115
+ if self.action_details is None:
116
+ self.action_details = {}
117
+
118
+ # Extract agent name from agent_id if not explicitly provided
119
+ if (not self.agent_name or self.agent_name == 'Unknown') and self.agent_id and '_' in self.agent_id:
120
+ prefix = self.agent_id.split('_')[0]
121
+ # Capitalize first letter for display
122
+ self.agent_name = prefix.capitalize()
123
+
124
+
125
+ @dataclass
126
+ class AgentRunTelemetryEvent(BaseTelemetryEvent):
127
+ agent_id: str
128
+ use_vision: bool
129
+ task: str
130
+ model_name: str
131
+ chat_model_library: str
132
+ version: str
133
+ source: str
134
+ name: str = 'agent_run'
135
+
136
+
137
+ @dataclass
138
+ class AgentEndTelemetryEvent(BaseTelemetryEvent):
139
+ agent_id: str
140
+ steps: int
141
+ max_steps_reached: bool
142
+ success: bool
143
+ errors: list[str]
144
+ name: str = 'agent_end'
145
+
146
+
147
+ @dataclass
148
+ class LLMRequestTelemetryEvent(BaseTelemetryEvent):
149
+ """
150
+ Telemetry event for LLM requests and usage.
151
+
152
+ This is the canonical event class for tracking LLM requests and usage.
153
+ It replaces both the old LLMRequestTelemetryEvent and LLMUsageTelemetryEvent
154
+ classes to eliminate redundancy. Downstream collectors should be configured
155
+ to handle events with the 'llm_request' name.
156
+ """
157
+ component: str
158
+ purpose: str
159
+ model_name: str
160
+ duration_seconds: float
161
+ success: bool
162
+ token_count: Optional[int] = None
163
+ session_id: Optional[str] = None
164
+ error: Optional[str] = None # Add error field for error reporting
165
+ prompt_tokens: Optional[int] = None # For detailed token usage
166
+ completion_tokens: Optional[int] = None # For detailed token usage
167
+ provider: Optional[str] = None # Provider name (openai, anthropic, etc.)
168
+ parameters: Optional[Dict[str, Any]] = None # Additional parameters
169
+ cost_estimate: Optional[float] = None # Estimated cost of the request
170
+ agent_id: Optional[str] = None # Optional agent ID
171
+ # Unique identifier for this LLM request so that downstream analytics can
172
+ # safely deuplicate entries that originate from multiple telemetry
173
+ # sources (e.g. llm_usage JSON + feed event). When not provided by the
174
+ # caller a UUID will be generated automatically inside
175
+ # ProductTelemetry.capture_llm_usage().
176
+ request_id: Optional[str] = None
177
+ name: str = 'llm_request'
178
+
179
+ def __post_init__(self):
180
+ """Initialize provider after dataclass initialization.
181
+
182
+ This resolves the dataclass-vs-property collision by ensuring
183
+ the provider field is set based on the model_name.
184
+ """
185
+ # FIXED: Initialize provider field if not set
186
+ if self.provider is None and self.model_name:
187
+ # Use centralized provider detection directly
188
+ from agents.task.utils import detect_llm_provider
189
+ provider = detect_llm_provider(None, self.model_name)
190
+ # Map 'generic' to 'unknown' for consistency with existing code
191
+ self.provider = 'unknown' if provider == 'generic' else provider
192
+
193
+ # Initialize parameters if needed
194
+ if self.parameters is None:
195
+ self.parameters = {}
196
+
197
+
198
+ @dataclass
199
+ class InterfaceTelemetryEvent(BaseTelemetryEvent):
200
+ """Telemetry event for UI/interface related events"""
201
+ event_type: str # e.g., 'view_loaded', 'session_created', 'screenshot_saved'
202
+ session_id: str
203
+ data: Optional[dict] = None
204
+ name: str = 'interface_event'
205
+
206
+
207
+ # DEPRECATED: PlannerOutputTelemetryEvent - planning is now integrated into agent
208
+
209
+
210
+
211
+ @dataclass
212
+ class SessionRelationshipTelemetryEvent(BaseTelemetryEvent):
213
+ """Telemetry event for tracking parent-child agent relationships in multi-agent sessions"""
214
+ parent_session_id: str
215
+ agent_ids: List[str]
216
+ agent_types: Dict[str, str] # Maps agent_id -> agent_type
217
+ agent_sequence: List[str] # Order of execution
218
+ orchestrator_type: str = "default"
219
+ name: str = 'multi_agent_relationship' # Changed from 'session_relationship' to match expected name
220
+
221
+ def get_session_id(self) -> str:
222
+ """Get the session ID for this event"""
223
+ return self.parent_session_id
224
+
225
+
226
+ class MultiAgentRelationshipEvent(BaseTelemetryEvent):
227
+ """Detailed telemetry event for multi-agent relationships."""
228
+
229
+ def __init__(self, agent_ids: List[str], agent_types: Dict[str, str], execution_sequence: List[str],
230
+ agent_details: List[Dict] = None, start_times: Dict[str, float] = None,
231
+ end_times: Dict[str, float] = None, durations: Dict[str, float] = None,
232
+ agent_models: Dict[str, str] = None, session_id: Optional[str] = None):
233
+ self.agent_ids = agent_ids
234
+ self.agent_types = agent_types
235
+ self.execution_sequence = execution_sequence
236
+ self.agent_details = agent_details or []
237
+ self.start_times = start_times or {}
238
+ self.end_times = end_times or {}
239
+ self.durations = durations or {}
240
+ self.agent_models = agent_models or {}
241
+ self.session_id = session_id # Explicit session context when available
242
+
243
+ # Ensure model information is added to agent_details if provided separately
244
+ if self.agent_models and self.agent_details:
245
+ for agent_detail in self.agent_details:
246
+ agent_id = agent_detail.get('id') or agent_detail.get('agent_id')
247
+ if agent_id and agent_id in self.agent_models:
248
+ if not agent_detail.get('model'):
249
+ agent_detail['model'] = self.agent_models[agent_id]
250
+
251
+ @property
252
+ def name(self) -> str:
253
+ """Get the name of this event. Implements the abstract property from BaseTelemetryEvent."""
254
+ return 'multi_agent_relationship_detailed'
255
+
256
+ @property
257
+ def properties(self) -> Dict[str, Any]:
258
+ """Get the properties for the event.
259
+
260
+ Returns:
261
+ Dict with event properties
262
+ """
263
+ props = {
264
+ 'agent_ids': self.agent_ids,
265
+ 'agent_types': self.agent_types,
266
+ 'execution_sequence': self.execution_sequence,
267
+ 'agent_details': self.agent_details,
268
+ 'agent_models': self.agent_models, # Explicitly include agent_models
269
+ 'orchestrator_type': 'default'
270
+ }
271
+
272
+ # Add timing data if available
273
+ if self.start_times:
274
+ props['start_times'] = self.start_times
275
+ if self.end_times:
276
+ props['end_times'] = self.end_times
277
+ if self.durations:
278
+ props['durations'] = self.durations
279
+
280
+ return props
281
+
282
+ def get_session_id(self) -> Optional[str]:
283
+ """Return the session identifier for the event so it can be routed to the correct feed."""
284
+ if self.session_id:
285
+ return self.session_id
286
+ # Fallback: derive from first agent id
287
+ if self.agent_ids:
288
+ first = self.agent_ids[0]
289
+ if '_' in first:
290
+ return first.split('_', 1)[1]
291
+ return None
292
+
293
+
294
+ class SessionStartTelemetryEvent(BaseTelemetryEvent):
295
+ """Event for session start."""
296
+
297
+ def __init__(self, session_id: str, task: str, model_name: str, *args, **kwargs):
298
+ """Initialize a session start event with task information.
299
+
300
+ Args:
301
+ session_id: The session ID
302
+ task: The description of the task being executed
303
+ model_name: The name of the model being used
304
+ """
305
+ # Remove super() call since BaseTelemetryEvent has no __init__
306
+ self.session_id = session_id
307
+ self.task = task
308
+ self.model_name = model_name
309
+ self._name = 'session_start'
310
+
311
+ # Store additional attributes
312
+ for key, value in kwargs.items():
313
+ setattr(self, key, value)
314
+
315
+ @property
316
+ def name(self) -> str:
317
+ """Get the name of this event. Implements the abstract property from BaseTelemetryEvent."""
318
+ return self._name
319
+
320
+ @property
321
+ def properties(self) -> Dict[str, Any]:
322
+ """Get the properties of this event."""
323
+ # Build a comprehension of public attributes
324
+ props = {
325
+ 'session_id': self.session_id,
326
+ 'task': self.task,
327
+ 'model_name': self.model_name
328
+ }
329
+
330
+ # Include other instance attributes that don't start with underscore
331
+ for key, value in self.__dict__.items():
332
+ if not key.startswith('_') and key not in props:
333
+ props[key] = value
334
+
335
+ return props
336
+
337
+ def get_session_id(self) -> str:
338
+ """Get the session ID associated with this event."""
339
+ return self.session_id
340
+
341
+
342
+ @dataclass
343
+ class SessionCompletionTelemetryEvent(BaseTelemetryEvent):
344
+ """Event for session completion."""
345
+ session_id: str
346
+ success: bool
347
+ total_steps: int
348
+ duration_seconds: float
349
+ error_message: Optional[str] = None
350
+ metrics: Optional[Dict[str, Any]] = None
351
+ name: str = 'session_completion'
352
+
353
+ def get_session_id(self) -> str:
354
+ """Get the session ID for this event"""
355
+ return self.session_id
356
+
357
+
358
+ @dataclass
359
+ class ScreenshotSavedTelemetryEvent(BaseTelemetryEvent):
360
+ """Event for when a screenshot is saved to disk."""
361
+ agent_id: str
362
+ step: int
363
+ screenshot_path: str
364
+ name: str = 'screenshot_saved'
365
+
366
+
367
+ @dataclass
368
+ class AgentRegistrationEvent(BaseTelemetryEvent):
369
+ """Event for agent registration."""
370
+ agent_id: str
371
+ agent_name: str
372
+ agent_type: str
373
+ model_name: str
374
+ task: str
375
+ session_id: Optional[str] = None
376
+ name: str = 'agent_registration'
377
+
378
+ def __post_init__(self):
379
+ """Ensure model_name is properly set."""
380
+ # Set a default model_name if it's empty
381
+ if not self.model_name or self.model_name == "None":
382
+ self.model_name = "Unknown"
383
+
384
+ def get_session_id(self) -> Optional[str]:
385
+ """Get the session ID for this event"""
386
+ if self.session_id:
387
+ return self.session_id
388
+ elif self.agent_id and '_' in self.agent_id:
389
+ return self.agent_id.split('_', 1)[1]
390
+ return None
391
+
392
+
393
+ @dataclass
394
+ class HumanApprovalRequestedEvent(BaseTelemetryEvent):
395
+ """Event for when human approval is requested for an action."""
396
+ agent_id: str
397
+ step: int
398
+ reason: str
399
+ required: bool = True
400
+ payload: Optional[Dict[str, Any]] = None
401
+ action_preview: Optional[List[str]] = None # List of action names/types
402
+ checkpoint_type: Optional[str] = None # 'pre_action', 'destructive', 'final'
403
+ timeout_seconds: Optional[int] = None
404
+ name: str = 'human_approval_requested'
405
+
406
+ def get_session_id(self) -> Optional[str]:
407
+ """Get the session ID for this event"""
408
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
409
+ return getattr(self, 'session_id')
410
+ elif self.agent_id and '_' in self.agent_id:
411
+ return self.agent_id.split('_', 1)[1]
412
+ return None
413
+
414
+
415
+ @dataclass
416
+ class HumanApprovalDecisionEvent(BaseTelemetryEvent):
417
+ """Event for when a human provides an approval decision."""
418
+ agent_id: str
419
+ step: int
420
+ approved: bool
421
+ note: Optional[str] = None
422
+ decision_time_seconds: Optional[float] = None # Time taken to make decision
423
+ override_type: Optional[str] = None # 'approve', 'reject', 'skip', 'edit'
424
+ edited_params: Optional[Dict[str, Any]] = None # If action params were edited
425
+ name: str = 'human_approval_decision'
426
+
427
+ def get_session_id(self) -> Optional[str]:
428
+ """Get the session ID for this event"""
429
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
430
+ return getattr(self, 'session_id')
431
+ elif self.agent_id and '_' in self.agent_id:
432
+ return self.agent_id.split('_', 1)[1]
433
+ return None
434
+
435
+
436
+ @dataclass
437
+ class UserGuidanceEvent(BaseTelemetryEvent):
438
+ """Event for when user provides guidance/message to agent."""
439
+ agent_id: str
440
+ kind: str # 'message', 'todo_update', 'approval', 'correction'
441
+ text: str
442
+ injected_at: Optional[str] = None # Where in agent flow it was injected
443
+ processed: bool = False
444
+ name: str = 'user_guidance'
445
+
446
+ def get_session_id(self) -> Optional[str]:
447
+ """Get the session ID for this event"""
448
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
449
+ return getattr(self, 'session_id')
450
+ elif self.agent_id and '_' in self.agent_id:
451
+ return self.agent_id.split('_', 1)[1]
452
+ return None
453
+
454
+
455
+ @dataclass
456
+ class TodoStatusEvent(BaseTelemetryEvent):
457
+ """Event for TODO list status updates."""
458
+ agent_id: str
459
+ todos_total: int
460
+ todos_completed: int
461
+ todos_pending: int
462
+ todo_items: Optional[List[Dict[str, Any]]] = None
463
+ enforcement_triggered: bool = False # If Done was blocked due to incomplete TODOs
464
+ name: str = 'todo_status'
465
+
466
+ def get_session_id(self) -> Optional[str]:
467
+ """Get the session ID for this event"""
468
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
469
+ return getattr(self, 'session_id')
470
+ elif self.agent_id and '_' in self.agent_id:
471
+ return self.agent_id.split('_', 1)[1]
472
+ return None
473
+
474
+
475
+ @dataclass
476
+ class AssistantMessageEvent(BaseTelemetryEvent):
477
+ """Event for chat-like assistant messages in HITL flow."""
478
+ agent_id: str
479
+ step: int
480
+ message: str
481
+ page_summary: Optional[str] = None
482
+ next_goal: Optional[str] = None
483
+ key_actions: Optional[List[str]] = None
484
+ url: Optional[str] = None
485
+ title: Optional[str] = None
486
+ name: str = 'assistant_message'
487
+
488
+ def get_session_id(self) -> Optional[str]:
489
+ """Get the session ID for this event"""
490
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
491
+ return getattr(self, 'session_id')
492
+ elif self.agent_id and '_' in self.agent_id:
493
+ return self.agent_id.split('_', 1)[1]
494
+ return None
495
+
496
+
497
+ @dataclass
498
+ class UserMessageDuringExecutionEvent(BaseTelemetryEvent):
499
+ """Event for user messages sent during agent execution (continuous chat).
500
+
501
+ This is for analytics/telemetry purposes. For UI display, use UserMessageFeedEvent.
502
+ """
503
+ agent_id: str
504
+ step: int
505
+ message_text: str # Truncated for privacy
506
+ message_kind: str
507
+ queue_depth: int
508
+ execution_phase: str # "running", "browser_action", "llm_call"
509
+ name: str = 'user_message_during_execution'
510
+
511
+ def get_session_id(self) -> Optional[str]:
512
+ """Get the session ID for this event"""
513
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
514
+ return getattr(self, 'session_id')
515
+ elif self.agent_id and '_' in self.agent_id:
516
+ return self.agent_id.split('_', 1)[1]
517
+ return None
518
+
519
+
520
+ @dataclass
521
+ class UserMessageFeedEvent(BaseTelemetryEvent):
522
+ """Event for user messages - rendered in chat UI.
523
+
524
+ This event is specifically for the feed/chat rendering.
525
+ Separate from UserMessageDuringExecutionEvent which is for analytics.
526
+
527
+ CRITICAL: The 'name' field MUST be 'user_message' to match chat.js expectations.
528
+ """
529
+ agent_id: str
530
+ text: str
531
+ kind: str = "comment" # comment, guidance, correction
532
+ step: int = 0
533
+ metadata: Optional[Dict[str, Any]] = None
534
+ state: str = "queued" # queued, injected, processed
535
+ name: str = 'user_message' # CRITICAL: Must match chat.js handleUserMessage()
536
+
537
+ def get_session_id(self) -> Optional[str]:
538
+ """Get the session ID for this event"""
539
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
540
+ return getattr(self, 'session_id')
541
+ elif self.agent_id and '_' in self.agent_id:
542
+ return self.agent_id.split('_', 1)[1]
543
+ return None
544
+
545
+
546
+ @dataclass
547
+ class QueueStatusEvent(BaseTelemetryEvent):
548
+ """Event for message queue status updates.
549
+
550
+ Emitted when the message queue changes to update UI indicators.
551
+ """
552
+ agent_id: str
553
+ queued_count: int
554
+ processing: bool = False
555
+ oldest_message_age_seconds: Optional[float] = None
556
+ name: str = 'queue_status'
557
+
558
+ def get_session_id(self) -> Optional[str]:
559
+ """Get the session ID for this event"""
560
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
561
+ return getattr(self, 'session_id')
562
+ elif self.agent_id and '_' in self.agent_id:
563
+ return self.agent_id.split('_', 1)[1]
564
+ return None
565
+
566
+
567
+ @dataclass
568
+ class StreamingOutputEvent(BaseTelemetryEvent):
569
+ """Event for streaming LLM output in continuous chat."""
570
+ agent_id: str
571
+ step: int
572
+ total_chunks: int
573
+ total_chars: int
574
+ provider: str
575
+ duration_seconds: float
576
+ callbacks_count: int
577
+ callback_failures: int
578
+ name: str = 'streaming_output'
579
+
580
+ def get_session_id(self) -> Optional[str]:
581
+ """Get the session ID for this event"""
582
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
583
+ return getattr(self, 'session_id')
584
+ elif self.agent_id and '_' in self.agent_id:
585
+ return self.agent_id.split('_', 1)[1]
586
+ return None
587
+
588
+
589
+ @dataclass
590
+ class AgentQuestionEvent(BaseTelemetryEvent):
591
+ """Event for agent-initiated questions to user."""
592
+ agent_id: str
593
+ step: int
594
+ question_prompt: str # Truncated
595
+ response_time_seconds: float
596
+ timed_out: bool
597
+ user_response: Optional[str] # Truncated
598
+ name: str = 'agent_question'
599
+
600
+ def get_session_id(self) -> Optional[str]:
601
+ """Get the session ID for this event"""
602
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
603
+ return getattr(self, 'session_id')
604
+ elif self.agent_id and '_' in self.agent_id:
605
+ return self.agent_id.split('_', 1)[1]
606
+ return None
607
+
608
+
609
+ @dataclass
610
+ class PostCompletionContinuationEvent(BaseTelemetryEvent):
611
+ """Event for user continuing task after agent completion."""
612
+ agent_id: str
613
+ final_step: int
614
+ continuation_message: str # Truncated
615
+ delay_seconds: float # Time between done and message
616
+ new_task_count: int # Steps after continuation
617
+ name: str = 'post_completion_continuation'
618
+
619
+ def get_session_id(self) -> Optional[str]:
620
+ """Get the session ID for this event"""
621
+ if hasattr(self, 'session_id') and getattr(self, 'session_id'):
622
+ return getattr(self, 'session_id')
623
+ elif self.agent_id and '_' in self.agent_id:
624
+ return self.agent_id.split('_', 1)[1]
625
+ return None
626
+
627
+
628
+ @dataclass
629
+ class ToolExecutionTelemetryEvent(BaseTelemetryEvent):
630
+ """Event for individual tool executions to track performance and results.
631
+
632
+ This event captures granular details about each tool execution including:
633
+ - Which tool/action was executed
634
+ - Parameters passed
635
+ - Execution timing
636
+ - Success/failure status
637
+ - Result size and truncation
638
+ """
639
+ agent_id: str
640
+ step: int
641
+ tool_name: str # e.g., 'filesystem', 'browser', 'task'
642
+ action_name: str # e.g., 'read_file', 'click', 'task_todo_list'
643
+ parameters: Dict[str, Any] # Action parameters (sanitized)
644
+ duration_seconds: float # Execution time
645
+ success: bool # Whether execution succeeded
646
+ error: Optional[str] = None # Error message if failed
647
+ result_size: Optional[int] = None # Size of result in characters
648
+ result_truncated: bool = False # Whether result was truncated
649
+ result_preview: Optional[str] = None # First 200 chars of result
650
+ session_id: Optional[str] = None # Explicit session ID
651
+ name: str = 'tool_execution'
652
+
653
+ def get_session_id(self) -> Optional[str]:
654
+ """Get the session ID for this event"""
655
+ if self.session_id:
656
+ return self.session_id
657
+ elif self.agent_id and '_' in self.agent_id:
658
+ return self.agent_id.split('_', 1)[1]
659
+ return None
660
+
661
+
662
+ @dataclass
663
+ class ErrorTelemetryEvent(BaseTelemetryEvent):
664
+ """Event for tracking errors with context.
665
+
666
+ Provides dedicated error tracking separate from step events to enable:
667
+ - Error analytics and dashboards
668
+ - Error rate monitoring
669
+ - Root cause analysis
670
+ - Recovery tracking
671
+ """
672
+ agent_id: str
673
+ step: int
674
+ error_type: str # 'tool_error', 'llm_error', 'validation_error', 'timeout', etc.
675
+ error_message: str # Error message
676
+ error_stack: Optional[str] = None # Stack trace (sanitized)
677
+ recoverable: bool = True # Whether error is recoverable
678
+ context: Optional[Dict[str, Any]] = None # Additional context
679
+ session_id: Optional[str] = None # Explicit session ID
680
+ name: str = 'error'
681
+
682
+ def get_session_id(self) -> Optional[str]:
683
+ """Get the session ID for this event"""
684
+ if self.session_id:
685
+ return self.session_id
686
+ elif self.agent_id and '_' in self.agent_id:
687
+ return self.agent_id.split('_', 1)[1]
688
+ return None
689
+
690
+
691
+ @dataclass
692
+ class VisionContentInjectedEvent(BaseTelemetryEvent):
693
+ """Track when vision content is injected into agent context."""
694
+ agent_id: str
695
+ step: int
696
+ image_count: int
697
+ image_sources: List[str] # ['msg_0', 'msg_1', ...]
698
+ model_name: str
699
+ vision_supported: bool
700
+ injection_position: int
701
+ survived_recalibration: bool
702
+
703
+ name: str = "vision_content_injected"
704
+
705
+
706
+ @dataclass
707
+ class VisionResponseAnalyzedEvent(BaseTelemetryEvent):
708
+ """Track LLM response analysis for vision content."""
709
+ agent_id: str
710
+ step: int
711
+ expected_image_count: int
712
+ mentioned_visual_content: bool
713
+ response_length: int
714
+ model_name: str
715
+ vision_keywords_found: List[str] # Which keywords were detected
716
+
717
+ name: str = "vision_response_analyzed"
718
+
719
+
720
+ @dataclass
721
+ class ProviderFailureEvent(BaseTelemetryEvent):
722
+ """Telemetry event for LLM provider failures.
723
+
724
+ This event is emitted when an LLM provider fails and a fallback is attempted.
725
+ Used for monitoring provider health, tracking failure patterns, and
726
+ understanding fallback behavior.
727
+
728
+ Attributes:
729
+ failed_provider: Provider that failed (e.g., 'openai', 'anthropic')
730
+ failed_model: Model that was being used when failure occurred
731
+ error_type: Type of error (e.g., 'LLMRateLimitError', 'LLMAuthenticationError')
732
+ error_message: Truncated error message
733
+ fallback_provider: Provider selected for fallback (None if no fallback available)
734
+ fallback_model: Model selected for fallback
735
+ fallback_success: Whether the fallback attempt succeeded
736
+ attempt_number: Which attempt this was (1 = first try, 2+ = fallback attempts)
737
+ session_id: Session where failure occurred
738
+ agent_id: Agent that encountered the failure
739
+ step: Step number when failure occurred
740
+ """
741
+ failed_provider: str
742
+ failed_model: str
743
+ error_type: str
744
+ error_message: str
745
+ fallback_provider: Optional[str] = None
746
+ fallback_model: Optional[str] = None
747
+ fallback_success: Optional[bool] = None
748
+ attempt_number: int = 1
749
+ session_id: Optional[str] = None
750
+ agent_id: Optional[str] = None
751
+ step: Optional[int] = None
752
+ timestamp: Optional[float] = None
753
+ name: str = 'provider_failure'
754
+
755
+ def __post_init__(self):
756
+ """Initialize timestamp if not provided."""
757
+ if self.timestamp is None:
758
+ self.timestamp = time.time()
759
+
760
+ def get_session_id(self) -> Optional[str]:
761
+ """Get the session ID for this event"""
762
+ if self.session_id:
763
+ return self.session_id
764
+ elif self.agent_id and '_' in self.agent_id:
765
+ return self.agent_id.split('_', 1)[1]
766
+ return None
767
+
768
+
769
+ @dataclass
770
+ class ProviderFallbackSuccessEvent(BaseTelemetryEvent):
771
+ """Telemetry event for successful provider fallback.
772
+
773
+ Emitted when a fallback provider successfully handles a request
774
+ after the primary provider failed.
775
+ """
776
+ original_provider: str
777
+ original_model: str
778
+ fallback_provider: str
779
+ fallback_model: str
780
+ original_error_type: str
781
+ total_attempts: int
782
+ total_fallback_time_seconds: float
783
+ session_id: Optional[str] = None
784
+ agent_id: Optional[str] = None
785
+ step: Optional[int] = None
786
+ name: str = 'provider_fallback_success'
787
+
788
+ def get_session_id(self) -> Optional[str]:
789
+ """Get the session ID for this event"""
790
+ if self.session_id:
791
+ return self.session_id
792
+ elif self.agent_id and '_' in self.agent_id:
793
+ return self.agent_id.split('_', 1)[1]
794
+ return None
795
+
796
+
797
+ @dataclass
798
+ class SessionPausedEvent(BaseTelemetryEvent):
799
+ """Event emitted when a session is paused by user.
800
+
801
+ Used for audit trail and UI synchronization.
802
+ """
803
+ session_id: str
804
+ reason: str = "user_interrupt" # user_interrupt, timeout, error
805
+ paused_by: str = "user" # user, system, admin
806
+ name: str = 'session_paused'
807
+
808
+ def get_session_id(self) -> Optional[str]:
809
+ return self.session_id
810
+
811
+
812
+ @dataclass
813
+ class SessionResumedEvent(BaseTelemetryEvent):
814
+ """Event emitted when a session is resumed by user.
815
+
816
+ Used for audit trail and UI synchronization.
817
+ """
818
+ session_id: str
819
+ resumed_by: str = "user" # user, system, admin
820
+ name: str = 'session_resumed'
821
+
822
+ def get_session_id(self) -> Optional[str]:
823
+ return self.session_id
824
+
825
+
826
+ @dataclass
827
+ class SessionStatusEvent(BaseTelemetryEvent):
828
+ """Generic status event for session state changes.
829
+
830
+ Used for UI synchronization via feed events.
831
+ """
832
+ session_id: str
833
+ status: str # running, paused, completed, error
834
+ previous_status: Optional[str] = None
835
+ reason: Optional[str] = None
836
+ name: str = 'status'
837
+
838
+ def get_session_id(self) -> Optional[str]:
839
+ return self.session_id
840
+
841
+
842
+ @dataclass
843
+ class IterationCompleteEvent(BaseTelemetryEvent):
844
+ """Event emitted when an agent iteration completes.
845
+
846
+ This provides a clean boundary marker for the UI to know
847
+ when one iteration ends and another begins. Contains full
848
+ summary of what happened in the iteration.
849
+ """
850
+ agent_id: str
851
+ iteration: int
852
+ step: int
853
+
854
+ # Iteration classification
855
+ iteration_type: str # thinking, browser, filesystem, mcp, mixed, done
856
+ iteration_status: str # completed, partial, failed, timeout, done
857
+
858
+ # Summary
859
+ reasoning_summary: str
860
+ actions_executed: List[Dict[str, Any]]
861
+ action_results: List[Dict[str, Any]] # Success/failure per action
862
+
863
+ # Files touched (empty lists if none)
864
+ files_created: List[str]
865
+ files_modified: List[str]
866
+ files_read: List[str]
867
+ files_deleted: List[str]
868
+
869
+ # Status
870
+ success: bool
871
+ error: Optional[str] = None
872
+ is_done: bool = False
873
+
874
+ # Timing
875
+ duration_seconds: float = 0.0
876
+
877
+ name: str = 'iteration_complete'
878
+
879
+ def get_session_id(self) -> Optional[str]:
880
+ if self.agent_id and '_' in self.agent_id:
881
+ return self.agent_id.split('_', 1)[1]
882
+ return None