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,509 @@
1
+
2
+ from __future__ import annotations
3
+
4
+ import asyncio
5
+ import base64
6
+ import http
7
+ import importlib
8
+ import json
9
+ import logging
10
+ import os
11
+ import re
12
+ import subprocess
13
+ import traceback
14
+ import time
15
+ from dataclasses import dataclass, field
16
+ from datetime import datetime
17
+ from io import BytesIO
18
+ from pathlib import Path
19
+ from typing import Any, Callable, Dict, List, Optional, Type, TypeVar, Union, Tuple
20
+ from collections import deque # ADDED: Import deque for bounded collections
21
+ from agents.task.agent.tool_call_tracker import ToolCallTracker # Robust tool call ID tracking
22
+
23
+ from dotenv import load_dotenv
24
+
25
+ # Import centralized constants
26
+ from agents.task.constants import (
27
+ IMG_TOKENS,
28
+ LoopDetectionConfig,
29
+ DEFAULT_USER_ID,
30
+ MemoryConfig,
31
+ MAX_MCP_PER_STEP
32
+ )
33
+
34
+ # Import POLYROB exceptions
35
+ from core.exceptions import (
36
+ AgentError,
37
+ ValidationError as ROBValidationError,
38
+ LLMResponseError,
39
+ ToolError
40
+ )
41
+
42
+ # Import billing exception for fail-fast handling
43
+ from core.exceptions import InsufficientCreditsError
44
+
45
+ # Import centralized utilities to avoid repeated inline imports
46
+ from agents.task.utils_json import normalize_action_schema
47
+ from core.env import bool_env as _bool_env
48
+ # Model limits now come from modules.llm.model_registry
49
+
50
+ # Native message types
51
+ from modules.llm.messages import (
52
+ AIMessage,
53
+ BaseMessage,
54
+ HumanMessage,
55
+ SystemMessage,
56
+ ToolMessage,
57
+ MessageOrigin,
58
+ make_control_message,
59
+ )
60
+ from modules.llm.adapters import BaseChatModel
61
+ from core.exceptions import (
62
+ RateLimitError,
63
+ LLMError,
64
+ LLMRateLimitError,
65
+ LLMAuthenticationError,
66
+ LLMConnectionError,
67
+ LLMContextLengthError,
68
+ LLMResponseError,
69
+ LLMPermanentError,
70
+ LLMProviderExhaustedError
71
+ )
72
+ # PIL Image imported locally in save_screenshot() method where needed
73
+ from pydantic import BaseModel, ConfigDict, ValidationError
74
+
75
+ from tools.browser.views import BrowserStateHistory, BrowserState
76
+ from agents.task.agent.message_manager.service import MessageManager
77
+ from agents.task.agent.core.llm_runner import LLMRunnerMixin
78
+ from agents.task.agent.core.memory_writer import MemoryWriterMixin
79
+ from agents.task.agent.core.memory_prefetch import MemoryPrefetchMixin
80
+ from agents.task.agent.core.background_review import BackgroundReviewMixin
81
+ from agents.task.agent.core.step import StepMixin
82
+ from agents.task.agent.core.history_io import HistoryIOMixin
83
+ from agents.task.agent.core.logging_io import LoggingIOMixin
84
+ from agents.task.agent.core.safety_lifecycle import SafetyLifecycleMixin
85
+ from agents.task.agent.core.user_ingress import UserIngressMixin
86
+ from agents.task.agent.core.llm_provisioning import LLMProvisioningMixin
87
+ from agents.task.agent.core.model_swap import ModelSwapMixin
88
+ from agents.task.agent.core.model_introspection import ModelIntrospectionMixin
89
+ from agents.task.agent.core.loop_detection import LoopDetectionMixin
90
+ from agents.task.agent.core.turn_input import TurnInputMixin
91
+ from agents.task.agent.core.resources import ResourceMixin
92
+ from agents.task.agent.core.session_metadata import SessionMetadataMixin
93
+ from agents.task.agent.core.error_recovery import ErrorRecoveryMixin
94
+ from agents.task.agent.core.step_telemetry import StepTelemetryMixin
95
+ from agents.task.agent.core.output_validation import OutputValidationMixin
96
+ from agents.task.agent.core.result_processing import ResultProcessingMixin
97
+ from agents.task.agent.core.next_action_internal import NextActionInternalMixin
98
+ from agents.task.agent.core.step_execution import StepExecutionMixin
99
+ from agents.task.agent.core.run_loop import RunLoopMixin
100
+ from agents.task.agent.core.construction import AgentConstructionMixin
101
+ from agents.task.agent.prompts import SystemPrompt, AgentMessagePrompt
102
+ from agents.task.agent.views import (
103
+ ActionModel,
104
+ AgentBrain,
105
+ AgentError,
106
+ AgentHistory,
107
+ AgentHistoryList,
108
+ AgentOutput,
109
+ AgentStepInfo,
110
+ ActionResult,
111
+ )
112
+ from tools.browser.context import BrowserContext
113
+ from tools.dom.views import DOMElementNode, SelectorMap
114
+ from agents.task.telemetry.views import (
115
+ HumanApprovalRequestedEvent,
116
+ HumanApprovalDecisionEvent,
117
+ TodoStatusEvent,
118
+ AgentRunTelemetryEvent,
119
+ AgentEndTelemetryEvent,
120
+ ProviderFailureEvent,
121
+ ProviderFallbackSuccessEvent,
122
+ )
123
+ # ProductTelemetry no longer directly used - accessed via TelemetryManager
124
+ from agents.task.utils import time_execution_async, detect_llm_provider, extract_token_usage
125
+ # Safely import Google API exceptions
126
+ try:
127
+ from google.api_core.exceptions import ResourceExhausted
128
+ except ImportError:
129
+ # Create a dummy exception class if google-api-core is not installed
130
+ class ResourceExhausted(Exception):
131
+ pass
132
+
133
+ # Import from our own logging config
134
+ from agents.task.logging_config import get_task_logger
135
+
136
+ # Import centralized path management
137
+ from agents.task.path import pm
138
+
139
+ load_dotenv()
140
+
141
+ # Generic logger for the module itself (not instances)
142
+ logger = get_task_logger('agent')
143
+
144
+ T = TypeVar('T', bound=BaseModel)
145
+
146
+
147
+
148
+ def _normalize_llm_content(content: Any) -> str:
149
+ """
150
+ Normalize LLM response content to string format.
151
+
152
+ Some providers (like Gemini) return content as a list of content blocks,
153
+ while others (OpenAI, Anthropic) return it as a string.
154
+
155
+ Args:
156
+ content: LLM response content (str, list, or other)
157
+
158
+ Returns:
159
+ Normalized string content
160
+ """
161
+ if content is None:
162
+ return ""
163
+
164
+ if isinstance(content, str):
165
+ return content
166
+
167
+ if isinstance(content, list):
168
+ # Extract text from content blocks
169
+ content_parts = []
170
+ for block in content:
171
+ if isinstance(block, str):
172
+ content_parts.append(block)
173
+ elif hasattr(block, 'text'):
174
+ content_parts.append(block.text)
175
+ elif isinstance(block, dict) and 'text' in block:
176
+ content_parts.append(block['text'])
177
+ else:
178
+ content_parts.append(str(block))
179
+ return "".join(content_parts)
180
+
181
+ # Fallback to string conversion
182
+ return str(content)
183
+
184
+
185
+ # Known tool/service names that namespace their actions
186
+ _KNOWN_TOOLS = {
187
+ 'polymarket', 'mcp', 'twitter', 'email', 'perplexity',
188
+ 'filesystem', 'browser', 'collabland', 'alchemy', 'task'
189
+ }
190
+
191
+
192
+ def _detect_service_for_action(action_name: str) -> str:
193
+ """Detect which service an action belongs to based on its name.
194
+
195
+ Uses a multi-tier detection strategy:
196
+ 1. Check for known tool prefix (e.g., 'polymarket_get_markets' → 'polymarket')
197
+ 2. Fall back to keyword-based detection for legacy actions
198
+ 3. Return 'default' if no match found
199
+
200
+ Args:
201
+ action_name: The name of the action
202
+
203
+ Returns:
204
+ The service name or 'default' if not detected
205
+ """
206
+ action_name_lower = action_name.lower()
207
+
208
+ # Strategy 1: Check for known tool prefix pattern (tool_action)
209
+ for tool in _KNOWN_TOOLS:
210
+ if action_name_lower.startswith(f"{tool}_"):
211
+ return tool
212
+
213
+ # Strategy 2: Keyword-based detection for actions without prefix
214
+ if 'perplexity' in action_name_lower or 'search_web' in action_name_lower:
215
+ return 'perplexity'
216
+ elif any(kw in action_name_lower for kw in ['document', 'doc_', 'extract_text', 'process_',
217
+ 'file', 'write_file', 'read_file', 'append_file',
218
+ 'delete_file', 'create_directory', 'list_directory']):
219
+ return 'filesystem'
220
+ elif any(kw in action_name_lower for kw in ['click', 'scroll', 'input', 'navigate', 'go_to',
221
+ 'browse_to', 'back', 'forward', 'reload', 'screenshot']):
222
+ return 'browser'
223
+ elif 'mcp' in action_name_lower:
224
+ return 'mcp'
225
+
226
+ # Strategy 3: Try to extract prefix from first underscore
227
+ if '_' in action_name_lower:
228
+ potential_tool = action_name_lower.split('_')[0]
229
+ if len(potential_tool) >= 3 and potential_tool not in {'get', 'set', 'add', 'del', 'run'}:
230
+ return potential_tool
231
+
232
+ return 'default'
233
+
234
+
235
+ @dataclass
236
+ class AgentDeps:
237
+ """Injected collaborators an Agent needs (objects/callables, not config values).
238
+
239
+ Split out of the old 31-param Agent.__init__ (PR9 item #2). Construct via
240
+ Agent(config, deps), or use Agent.from_params(**kwargs) for the legacy kwarg
241
+ interface.
242
+ """
243
+ llm: "BaseChatModel"
244
+ orchestrator: Any # Required: provides session_id/user_id + infrastructure
245
+ page_extraction_llm: Optional["BaseChatModel"] = None
246
+ system_prompt_class: Type[SystemPrompt] = SystemPrompt
247
+ register_new_step_callback: Optional[Callable[['BrowserState', 'AgentOutput', int], None]] = None
248
+ register_done_callback: Optional[Callable[['AgentHistoryList'], None]] = None
249
+ # UP-05: an explicit Controller to bind instead of orchestrator.controller — used
250
+ # to give a delegated sub-agent a least-privilege child Controller. None => the
251
+ # shared orchestrator controller (default, pre-UP-05 behaviour).
252
+ controller: Optional[Any] = None
253
+
254
+
255
+ @dataclass
256
+ class AgentConfig:
257
+ """Scalar/behavioural configuration for an Agent (everything that isn't a
258
+ collaborator). Defaults match the historical Agent.__init__ defaults exactly."""
259
+ task: str
260
+ use_vision: bool = True
261
+ save_conversation_path: Optional[str] = None
262
+ save_conversation_path_encoding: Optional[str] = 'utf-8'
263
+ max_failures: int = 5
264
+ retry_delay: int = 10
265
+ max_input_tokens: Optional[int] = None # model-specific limit if not provided
266
+ # CO-F1: judge-backed output validation of the agent's final answer. Default OFF
267
+ # (env `VALIDATE_OUTPUT`, core.env SSOT falsey-set); an explicit AgentConfig
268
+ # kwarg still wins over the env default (this is a plain field, not a
269
+ # default_factory, so callers that pass validate_output=... are unaffected).
270
+ validate_output: bool = field(default_factory=lambda: _bool_env("VALIDATE_OUTPUT", False))
271
+ generate_gif: bool | str = True
272
+ sensitive_data: Optional[Dict[str, str]] = None
273
+ available_file_paths: Optional[list[str]] = None
274
+ include_attributes: Optional[list[str]] = None
275
+ max_error_length: int = 400
276
+ max_actions_per_step: int = 10
277
+ initial_actions: Optional[List[Dict[str, Dict[str, Any]]]] = None
278
+ tool_calling_method: Optional[str] = 'auto'
279
+ agent_name: str = "agent"
280
+ session_config: Optional[Dict[str, Any]] = None
281
+ profile_id: Optional[str] = None
282
+ profile_overrides: Optional[Dict[str, Any]] = None
283
+ use_native_tools: bool = True
284
+ step_timeout_seconds: Optional[int] = 600
285
+ stall_timeout_seconds: Optional[int] = 600
286
+ max_step_timeout: int = 900
287
+ is_sub_agent: bool = False
288
+ parent_session_id: Optional[str] = None
289
+ role: str = "orchestrator" # "orchestrator" may delegate; sub-agents get "leaf"
290
+ persona_block: Optional[str] = None # S1: chat-mode persona text → SystemPrompt <identity>
291
+
292
+
293
+ # Keys that belong to AgentDeps; everything else in a kwargs blob is AgentConfig.
294
+ _AGENT_DEP_KEYS = frozenset({
295
+ 'llm', 'orchestrator', 'page_extraction_llm', 'system_prompt_class',
296
+ 'register_new_step_callback', 'register_done_callback', 'controller',
297
+ })
298
+
299
+
300
+ class Agent(AgentConstructionMixin, RunLoopMixin, StepMixin, StepExecutionMixin, StepTelemetryMixin, ResultProcessingMixin, LLMRunnerMixin, NextActionInternalMixin, ErrorRecoveryMixin, OutputValidationMixin, MemoryWriterMixin, MemoryPrefetchMixin, BackgroundReviewMixin, HistoryIOMixin, LoggingIOMixin, SafetyLifecycleMixin, UserIngressMixin, TurnInputMixin, LLMProvisioningMixin, ModelSwapMixin, ModelIntrospectionMixin, LoopDetectionMixin, ResourceMixin, SessionMetadataMixin):
301
+ @classmethod
302
+ def from_params(cls, **kwargs) -> "Agent":
303
+ """Build an Agent from the legacy flat keyword arguments.
304
+
305
+ Splits kwargs into AgentDeps (the collaborators in _AGENT_DEP_KEYS) and
306
+ AgentConfig (everything else), then calls Agent(config, deps). This keeps
307
+ every existing call site (orchestrator.create_agent, tests) working with a
308
+ one-token change while Agent.__init__ itself takes just (config, deps).
309
+ """
310
+ dep_kwargs = {k: kwargs.pop(k) for k in list(kwargs) if k in _AGENT_DEP_KEYS}
311
+ config = AgentConfig(**kwargs)
312
+ deps = AgentDeps(**dep_kwargs)
313
+ return cls(config, deps)
314
+
315
+ def _save_initial_task(self):
316
+ """Save the initial task to task.json for webview chat.
317
+
318
+ Creates a task.json file in the session directory that contains:
319
+ - task: The initial task description
320
+ - timestamp: When the task was created
321
+ - agent_name: Name of the agent handling the task
322
+
323
+ This file is used by the webview chat tab to display the initial
324
+ user message/task at the top of the conversation.
325
+ """
326
+ try:
327
+ from agents.task.path import pm
328
+
329
+ session_id = pm().clean_session_id(self.session_id)
330
+ session_dir = pm().get_data_dir(session_id, user_id=self.user_id)
331
+ task_file = session_dir / "task.json"
332
+
333
+ task_data = {
334
+ "task": self.task,
335
+ "timestamp": time.time(),
336
+ "agent_name": self.agent_name
337
+ }
338
+
339
+ with open(task_file, 'w') as f:
340
+ json.dump(task_data, f, indent=2)
341
+
342
+ self.logger.info(f"✓ Saved task.json for session {session_id}")
343
+ except Exception as e:
344
+ self.logger.warning(f"Failed to save task.json: {e}")
345
+
346
+ def _has_active_browser_usage(self) -> bool:
347
+ """Check if browser was ACTIVELY used in recent steps.
348
+
349
+ FIX (Jan 2026): Simplified detection - only check recent action history.
350
+ The AgentMessagePrompt._has_meaningful_browser_state() handles the
351
+ current state check. This method only checks if browser TOOLS were used.
352
+
353
+ CRITICAL: Does NOT check:
354
+ - browser_context existence (always exists for browser-capable agents)
355
+ - task keywords (too aggressive, e.g. "parse URL from file")
356
+
357
+ DOES check:
358
+ - If recent actions include browser tool usage
359
+ - If last browser state has a real URL (not empty/placeholder)
360
+
361
+ Returns:
362
+ True if browser was actively used recently, False otherwise
363
+ """
364
+ # Check 1: Were browser tools used in recent actions?
365
+ if hasattr(self, '_previous_actions') and self._previous_actions:
366
+ browser_action_prefixes = ('browser_go_to', 'browser_click', 'browser_type',
367
+ 'browser_scroll', 'browser_screenshot',
368
+ 'browser_extract', 'browser_navigate')
369
+ for action in self._previous_actions:
370
+ action_name = str(action).lower() if action else ""
371
+ if any(prefix in action_name for prefix in browser_action_prefixes):
372
+ return True
373
+
374
+ # Check 2: Does the last browser state have a real URL?
375
+ if hasattr(self, '_last_browser_states') and self._last_browser_states:
376
+ last_state = self._last_browser_states[-1] if self._last_browser_states else None
377
+ if last_state and hasattr(last_state, 'url'):
378
+ url = last_state.url
379
+ # Real URL must be non-empty and not a placeholder
380
+ if url and url.strip() and url != "about:blank":
381
+ return True
382
+
383
+ # Default: Browser not actively used
384
+ return False
385
+
386
+ @property
387
+ def session_id(self) -> str:
388
+ """Get session_id from orchestrator (single source of truth)."""
389
+ return self.orchestrator.session_id
390
+
391
+ @property
392
+ def effective_session_id(self) -> str:
393
+ """Get the effective session_id for this agent.
394
+
395
+ For main agents: returns orchestrator.session_id
396
+ For sub-agents: returns the virtual session_id (isolated context)
397
+
398
+ Use this for action execution contexts and file paths.
399
+ """
400
+ if self._is_sub_agent and hasattr(self, 'message_manager') and self.message_manager:
401
+ # Sub-agents use their isolated session_id from message_manager
402
+ return getattr(self.message_manager, 'session_id', self.orchestrator.session_id)
403
+ return self.orchestrator.session_id
404
+
405
+ @property
406
+ def user_id(self) -> Optional[str]:
407
+ """Get user_id from orchestrator (single source of truth)."""
408
+ return self.orchestrator.user_id
409
+
410
+ @property
411
+ def model_name(self) -> str:
412
+ """Get model_name from MessageManager (single source of truth)."""
413
+ return self.message_manager.model_name
414
+
415
+ @model_name.setter
416
+ def model_name(self, value: str) -> None:
417
+ """Update model_name via MessageManager (for LLM fallback scenarios)."""
418
+ self.message_manager.model_name = value
419
+
420
+ @property
421
+ def provider_name(self) -> str:
422
+ """Get provider_name from MessageManager (single source of truth)."""
423
+ return self.message_manager.provider_name
424
+
425
+ @provider_name.setter
426
+ def provider_name(self, value: str) -> None:
427
+ """Update provider_name via MessageManager (for live model swaps).
428
+
429
+ Mirrors the ``model_name`` setter: MessageManager is the SSOT and the
430
+ Agent property is a thin mirror. Needed so ``swap_model`` can set the
431
+ registry-canonical provider label authoritatively after a swap."""
432
+ self.message_manager.provider_name = value
433
+
434
+ @property
435
+ def container(self) -> Optional[Any]:
436
+ """Get container from orchestrator (single source of truth).
437
+
438
+ Returns:
439
+ Container instance from orchestrator, or None if not available.
440
+
441
+ Note:
442
+ This property provides unified access to the container without
443
+ duplicating storage. The orchestrator is the single owner.
444
+ """
445
+ return self.orchestrator.container if self.orchestrator else None
446
+
447
+ # LLM provisioning (_supports_streaming, _create_llm_from_config[_async],
448
+ # set_token_limits, _get_model_max_completion_tokens, _reconcile_native_tools,
449
+ # set_tool_calling_method) lives in core/llm_provisioning.py::LLMProvisioningMixin (P9).
450
+ # REMOVED: _set_model_names() - deprecated; chat_model_library set in __init__;
451
+ # model_name is a property delegating to MessageManager.
452
+
453
+ def _save_session_config(self) -> None:
454
+ """Save the session configuration to the session directory for persistence and debugging."""
455
+ if not self.session_config:
456
+ return
457
+
458
+ try:
459
+ from agents.task.path import pm
460
+ from pathlib import Path
461
+
462
+ # Get session directory
463
+ session_dir = pm().get_session_root(self.session_id)
464
+ config_file = session_dir / "task_config.json"
465
+
466
+ # Save configuration
467
+ self.session_config.save(config_file)
468
+ self.logger.info(f"Saved session config to {config_file}")
469
+
470
+ # Also log a summary
471
+ self.logger.info(f"Config summary:\n{self.session_config.summary()}")
472
+
473
+ except Exception as e:
474
+ self.logger.warning(f"Failed to save session config: {e}")
475
+
476
+ def add_new_task(self, new_task: str) -> None:
477
+ self.message_manager.add_new_task(new_task)
478
+
479
+ async def _save_progress_on_timeout(self) -> None:
480
+ """Save progress when a step times out to enable recovery."""
481
+ try:
482
+ # Save current todo state using TaskTool
483
+ if self.controller:
484
+ task_tool = self.controller.get_tool('task')
485
+ if task_tool and hasattr(task_tool, '_save_to_file'):
486
+ try:
487
+ task_tool._save_to_file(self.session_id)
488
+ self.logger.info("Saved todo progress on timeout")
489
+ except Exception as e:
490
+ self.logger.warning(f"Failed to save todos on timeout: {e}")
491
+
492
+ # Save message history checkpoint
493
+ if hasattr(self, 'message_manager'):
494
+ self.message_manager.checkpoint_history()
495
+ self.logger.info("Checkpointed message history on timeout")
496
+
497
+ except Exception as e:
498
+ self.logger.warning(f"Failed to save progress on timeout: {e}")
499
+
500
+ def _sanitize_text_for_log(self, text: str) -> str:
501
+ """Trim inline base64 images or very long strings for logging (P9: see log_sanitize)."""
502
+ from agents.task.agent.log_sanitize import sanitize_text_for_log
503
+ return sanitize_text_for_log(text)
504
+
505
+ def _sanitize_structure_for_log(self, data):
506
+ """Recursively sanitise nested structures for logging (P9: see log_sanitize)."""
507
+ from agents.task.agent.log_sanitize import sanitize_structure_for_log
508
+ return sanitize_structure_for_log(data)
509
+