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
tools/descriptors.py ADDED
@@ -0,0 +1,452 @@
1
+ """Single source of truth for tool metadata and configuration.
2
+
3
+ This module consolidates all tool-related constants that were previously
4
+ duplicated between tools/__init__.py and core/initialization.py.
5
+
6
+ IMPORTANT: This is the ONLY place tool metadata should be defined.
7
+ """
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import Dict, List, Type, Any, Optional, TYPE_CHECKING
11
+ from enum import Enum
12
+
13
+ if TYPE_CHECKING:
14
+ from tools.base_tool import BaseTool
15
+
16
+
17
+ class ToolCategory(Enum):
18
+ """Tool categories for organization."""
19
+ CORE = "core" # Essential tools (filesystem, task)
20
+ BROWSER = "browser" # Browser automation
21
+ COMMUNICATION = "comm" # Email, social media
22
+ SEARCH = "search" # Search and research
23
+ VERIFICATION = "verify" # Token gating, identity
24
+ INTEGRATION = "integration" # MCP, external APIs
25
+
26
+
27
+ @dataclass
28
+ class ToolDescriptor:
29
+ """Complete descriptor for a tool.
30
+
31
+ This replaces the previous scattered definitions:
32
+ - TOOL_COMPONENTS (name, class)
33
+ - TOOL_DEPENDENCIES (required, optional)
34
+ - TOOL_METADATA (description, requires_config, etc.)
35
+ - TOOL_INIT_ORDER (via init_priority)
36
+ """
37
+
38
+ name: str
39
+ description: str
40
+ category: ToolCategory
41
+
42
+ # Dependencies - services this tool needs
43
+ required_services: List[str] = field(default_factory=list)
44
+ optional_services: List[str] = field(default_factory=list)
45
+
46
+ # Configuration requirements
47
+ required_config: List[str] = field(default_factory=list)
48
+
49
+ # Initialization
50
+ init_priority: int = 50 # Lower = earlier (0-100)
51
+ is_optional: bool = True # Can system start without it?
52
+
53
+ # Rate limiting
54
+ rate_limited: bool = False
55
+ rate_limit_settings: Dict[str, Any] = field(default_factory=dict)
56
+
57
+ # Class reference (set during registration)
58
+ tool_class: Optional[Type["BaseTool"]] = None
59
+
60
+ def __post_init__(self):
61
+ # Ensure rate_limit_manager is always required if rate_limited
62
+ if self.rate_limited and 'rate_limit_manager' not in self.required_services:
63
+ self.required_services = ['rate_limit_manager'] + self.required_services
64
+
65
+
66
+ # =============================================================================
67
+ # TOOL REGISTRY - Single Source of Truth
68
+ # =============================================================================
69
+
70
+ TOOL_DESCRIPTORS: Dict[str, ToolDescriptor] = {
71
+ # ---------------------------------------------------------------------
72
+ # CORE TOOLS (init_priority 0-19)
73
+ # ---------------------------------------------------------------------
74
+ 'filesystem': ToolDescriptor(
75
+ name='filesystem',
76
+ description='File system operations and document processing',
77
+ category=ToolCategory.CORE,
78
+ required_services=['rate_limit_manager'],
79
+ optional_services=['llm_client', 'cache_manager'],
80
+ required_config=[],
81
+ init_priority=10,
82
+ is_optional=False, # Required tool
83
+ ),
84
+
85
+ 'task': ToolDescriptor(
86
+ name='task',
87
+ description='Task and todo list management',
88
+ category=ToolCategory.CORE,
89
+ required_services=['rate_limit_manager'],
90
+ optional_services=[],
91
+ required_config=[],
92
+ init_priority=15,
93
+ is_optional=True,
94
+ ),
95
+
96
+ # ---------------------------------------------------------------------
97
+ # BROWSER TOOLS (init_priority 5 - needs to be early for pooling)
98
+ # ---------------------------------------------------------------------
99
+ 'browser_manager': ToolDescriptor(
100
+ name='browser_manager',
101
+ description='Browser lifecycle and context pooling manager',
102
+ category=ToolCategory.BROWSER,
103
+ required_services=[],
104
+ optional_services=[],
105
+ required_config=[],
106
+ init_priority=5, # Very early - browser pool
107
+ is_optional=True,
108
+ ),
109
+
110
+ # ---------------------------------------------------------------------
111
+ # SEARCH TOOLS (init_priority 20-29)
112
+ # ---------------------------------------------------------------------
113
+ 'perplexity': ToolDescriptor(
114
+ name='perplexity',
115
+ description='AI-powered search via Perplexity API',
116
+ category=ToolCategory.SEARCH,
117
+ required_services=['rate_limit_manager'],
118
+ optional_services=['cache_manager'],
119
+ required_config=['perplexity_api_key'],
120
+ init_priority=20,
121
+ is_optional=True,
122
+ ),
123
+
124
+ 'web_fetch': ToolDescriptor(
125
+ name='web_fetch',
126
+ description='Stateless web page reader (URL -> markdown). No browser/Chromium.',
127
+ category=ToolCategory.SEARCH,
128
+ required_services=[],
129
+ optional_services=['cache_manager'],
130
+ required_config=[],
131
+ init_priority=21,
132
+ is_optional=True,
133
+ ),
134
+
135
+ # ---------------------------------------------------------------------
136
+ # COMMUNICATION TOOLS (init_priority 30-39)
137
+ # ---------------------------------------------------------------------
138
+ 'twitter': ToolDescriptor(
139
+ name='twitter',
140
+ description='Twitter/X account actions: post/media/poll/thread, reply/quote/delete, like/retweet, follow/mute/block, DM, mentions (gated by TWITTER_ENABLED). For Twitter/X DATA RETRIEVAL prefer the anysite tool to conserve quota.',
141
+ category=ToolCategory.COMMUNICATION,
142
+ required_services=['rate_limit_manager', 'database_manager'],
143
+ optional_services=['cache_manager'],
144
+ required_config=[], # Uses OAuth tokens from DB
145
+ init_priority=30,
146
+ is_optional=True,
147
+ rate_limited=True,
148
+ rate_limit_settings={
149
+ 'default_wait': 900, # 15 minutes
150
+ 'requests_per_minute': 300,
151
+ 'burst_limit': 50
152
+ }
153
+ ),
154
+
155
+ 'email': ToolDescriptor(
156
+ name='email',
157
+ description='Email sending via Gmail',
158
+ category=ToolCategory.COMMUNICATION,
159
+ required_services=['rate_limit_manager'],
160
+ optional_services=[],
161
+ required_config=['gmail_email', 'gmail_app_password'],
162
+ init_priority=35,
163
+ is_optional=True,
164
+ ),
165
+
166
+ # ---------------------------------------------------------------------
167
+ # VERIFICATION TOOLS (init_priority 40-49)
168
+ # ---------------------------------------------------------------------
169
+ 'collabland': ToolDescriptor(
170
+ name='collabland',
171
+ description='CollabLand token gating verification',
172
+ category=ToolCategory.VERIFICATION,
173
+ required_services=['rate_limit_manager', 'database_manager'],
174
+ optional_services=['cache_manager'],
175
+ required_config=['collabland_api_key'],
176
+ init_priority=40,
177
+ is_optional=True,
178
+ ),
179
+
180
+ 'alchemy': ToolDescriptor(
181
+ name='alchemy',
182
+ description='Alchemy NFT API for token verification',
183
+ category=ToolCategory.VERIFICATION,
184
+ required_services=['rate_limit_manager'],
185
+ optional_services=['cache_manager'],
186
+ required_config=['alchemy_api_key'],
187
+ init_priority=45,
188
+ is_optional=True,
189
+ ),
190
+
191
+ # ---------------------------------------------------------------------
192
+ # INTEGRATION TOOLS (init_priority 50-59)
193
+ # ---------------------------------------------------------------------
194
+ 'mcp': ToolDescriptor(
195
+ name='mcp',
196
+ description='Model Context Protocol server integration',
197
+ category=ToolCategory.INTEGRATION,
198
+ required_services=['rate_limit_manager'],
199
+ optional_services=['cache_manager'],
200
+ required_config=[], # MCP config is separate
201
+ init_priority=50,
202
+ is_optional=True,
203
+ ),
204
+
205
+ 'anysite': ToolDescriptor(
206
+ name='anysite',
207
+ description="Query AnySite's 200+ sources / 1,200+ endpoints (LinkedIn, X, Reddit, YouTube, GitHub, SEC, web scraper) via the anysite CLI",
208
+ category=ToolCategory.INTEGRATION,
209
+ is_optional=True,
210
+ init_priority=52,
211
+ ),
212
+
213
+ 'polymarket_data': ToolDescriptor(
214
+ name='polymarket_data',
215
+ description='Polymarket prediction markets - read-only market data & research (no wallet)',
216
+ category=ToolCategory.INTEGRATION,
217
+ required_services=['rate_limit_manager'],
218
+ optional_services=['cache_manager'],
219
+ required_config=[],
220
+ init_priority=53, # before the trade tool
221
+ is_optional=True,
222
+ rate_limited=True,
223
+ rate_limit_settings={'requests_per_minute': 60, 'burst_limit': 10, 'default_wait': 60},
224
+ ),
225
+
226
+ 'polymarket': ToolDescriptor(
227
+ name='polymarket',
228
+ description='Polymarket prediction markets - trading and market data',
229
+ category=ToolCategory.INTEGRATION,
230
+ required_services=['rate_limit_manager'],
231
+ optional_services=['cache_manager', 'database_manager'],
232
+ required_config=[], # Credentials stored in DB, not config
233
+ init_priority=55, # After MCP
234
+ is_optional=True,
235
+ rate_limited=True,
236
+ rate_limit_settings={
237
+ 'requests_per_minute': 60,
238
+ 'burst_limit': 10,
239
+ 'default_wait': 60
240
+ }
241
+ ),
242
+
243
+ 'hyperliquid_data': ToolDescriptor(
244
+ name='hyperliquid_data',
245
+ description='Hyperliquid perps/spot - read-only market data & account state (no signing)',
246
+ category=ToolCategory.INTEGRATION,
247
+ required_services=['rate_limit_manager'],
248
+ optional_services=['cache_manager'],
249
+ required_config=[],
250
+ init_priority=54, # before the trade tool
251
+ is_optional=True,
252
+ rate_limited=True,
253
+ rate_limit_settings={'requests_per_minute': 120, 'burst_limit': 20, 'default_wait': 30},
254
+ ),
255
+
256
+ 'hyperliquid': ToolDescriptor(
257
+ name='hyperliquid',
258
+ description='Hyperliquid perpetuals and spot trading - market data and execution',
259
+ category=ToolCategory.INTEGRATION,
260
+ required_services=['rate_limit_manager'],
261
+ optional_services=['cache_manager', 'database_manager'],
262
+ required_config=[], # Credentials stored in DB, not config
263
+ init_priority=56, # After polymarket
264
+ is_optional=True,
265
+ rate_limited=True,
266
+ rate_limit_settings={
267
+ 'requests_per_minute': 120,
268
+ 'burst_limit': 20,
269
+ 'default_wait': 30
270
+ }
271
+ ),
272
+ }
273
+
274
+
275
+ # =============================================================================
276
+ # DERIVED CONSTANTS (for backward compatibility)
277
+ # =============================================================================
278
+
279
+ def get_tool_init_order() -> List[str]:
280
+ """Get tools in initialization order (sorted by init_priority)."""
281
+ return sorted(
282
+ TOOL_DESCRIPTORS.keys(),
283
+ key=lambda name: TOOL_DESCRIPTORS[name].init_priority
284
+ )
285
+
286
+
287
+ def get_tool_dependencies(tool_name: str) -> Dict[str, List[str]]:
288
+ """Get dependencies for a tool (backward compatible format)."""
289
+ if tool_name not in TOOL_DESCRIPTORS:
290
+ return {'required': [], 'optional': []}
291
+ desc = TOOL_DESCRIPTORS[tool_name]
292
+ return {
293
+ 'required': desc.required_services,
294
+ 'optional': desc.optional_services
295
+ }
296
+
297
+
298
+ def get_tool_metadata(tool_name: str) -> Dict[str, Any]:
299
+ """Get metadata for a tool (backward compatible format)."""
300
+ if tool_name not in TOOL_DESCRIPTORS:
301
+ return {
302
+ 'name': tool_name.title(),
303
+ 'description': 'No description available',
304
+ 'requires_config': [],
305
+ 'required': False
306
+ }
307
+ desc = TOOL_DESCRIPTORS[tool_name]
308
+ return {
309
+ 'name': desc.name,
310
+ 'description': desc.description,
311
+ 'requires_config': desc.required_config,
312
+ 'required': not desc.is_optional,
313
+ 'dependencies': desc.required_services,
314
+ 'optional_dependencies': desc.optional_services,
315
+ 'rate_limited': desc.rate_limited,
316
+ 'rate_limit_settings': desc.rate_limit_settings,
317
+ 'is_core': desc.category == ToolCategory.CORE
318
+ }
319
+
320
+
321
+ def get_optional_tools() -> set:
322
+ """Get set of optional tool names."""
323
+ return {
324
+ name for name, desc in TOOL_DESCRIPTORS.items()
325
+ if desc.is_optional
326
+ }
327
+
328
+
329
+ def get_available_tools() -> Dict[str, str]:
330
+ """Get dict of tool name -> description."""
331
+ return {
332
+ name: desc.description
333
+ for name, desc in TOOL_DESCRIPTORS.items()
334
+ }
335
+
336
+
337
+ def get_default_tools() -> List[str]:
338
+ """Get list of tools that should be enabled by default in UI.
339
+
340
+ These are the baseline tools that provide essential functionality.
341
+ Returns both the canonical name and any aliases (e.g., 'browser' for 'browser_manager').
342
+ """
343
+ # Core tools always enabled
344
+ defaults = ['filesystem', 'browser']
345
+ return defaults
346
+
347
+
348
+ def get_agent_usable_tools() -> Dict[str, ToolDescriptor]:
349
+ """Get tools that should appear in the agent configuration panel.
350
+
351
+ Excludes:
352
+ - Internal verification tools (collabland, alchemy)
353
+ - Tools shown as MCP servers (polymarket)
354
+ - Deprecated tools (twitter - use mcp:anysite)
355
+ - Internal tools not meant for user selection (task)
356
+ """
357
+ # Categories that should appear in config panel
358
+ usable_categories = {ToolCategory.CORE, ToolCategory.BROWSER, ToolCategory.SEARCH, ToolCategory.COMMUNICATION, ToolCategory.INTEGRATION}
359
+
360
+ # Specific exclusions
361
+ # NOTE: polymarket/hyperliquid are live in-process tools (see TOOL_DESCRIPTORS above),
362
+ # NOT MCP — the old "polymarket is MCP-only" note was stale. They are selectable but
363
+ # high-risk and stay out of the DEFAULT tool lists (opt-in only).
364
+ # twitter is loadable (G1 full write surface, gated by TWITTER_ENABLED) — it is
365
+ # selectable in the panel but stays out of the DEFAULT tool lists (opt-in only).
366
+ excluded_tools = {'collabland', 'alchemy', 'task'}
367
+
368
+ return {
369
+ name: desc
370
+ for name, desc in TOOL_DESCRIPTORS.items()
371
+ if desc.category in usable_categories and name not in excluded_tools
372
+ }
373
+
374
+
375
+ def get_tool_display_name(tool_name: str) -> str:
376
+ """Get display name for a tool, handling aliases.
377
+
378
+ Maps internal names to user-facing names:
379
+ - browser_manager -> browser
380
+ """
381
+ aliases = {
382
+ 'browser_manager': 'browser'
383
+ }
384
+ return aliases.get(tool_name, tool_name)
385
+
386
+
387
+ # Backward compatible exports
388
+ TOOL_INIT_ORDER = get_tool_init_order()
389
+ OPTIONAL_TOOLS = get_optional_tools()
390
+ AVAILABLE_TOOLS = get_available_tools()
391
+
392
+
393
+ # Build TOOL_COMPONENTS and TOOL_DEPENDENCIES dynamically
394
+ # (These will be populated when tools/__init__.py imports this and registers classes)
395
+ TOOL_COMPONENTS: List[tuple] = []
396
+ TOOL_DEPENDENCIES: Dict[str, Dict[str, List[str]]] = {
397
+ name: get_tool_dependencies(name)
398
+ for name in TOOL_DESCRIPTORS
399
+ }
400
+ TOOL_METADATA: Dict[str, Dict[str, Any]] = {
401
+ name: get_tool_metadata(name)
402
+ for name in TOOL_DESCRIPTORS
403
+ }
404
+
405
+
406
+ def register_tool_class(tool_name: str, tool_class: Type["BaseTool"]) -> None:
407
+ """Register a tool class with its descriptor.
408
+
409
+ Called from tools/__init__.py to associate classes with descriptors.
410
+ """
411
+ if tool_name in TOOL_DESCRIPTORS:
412
+ TOOL_DESCRIPTORS[tool_name].tool_class = tool_class
413
+ # Update TOOL_COMPONENTS for backward compatibility
414
+ if not any(name == tool_name for name, _ in TOOL_COMPONENTS):
415
+ TOOL_COMPONENTS.append((tool_name, tool_class))
416
+
417
+
418
+ def get_tool_class(tool_name: str) -> Optional[Type["BaseTool"]]:
419
+ """Get the tool class for a given tool name."""
420
+ if tool_name in TOOL_DESCRIPTORS:
421
+ return TOOL_DESCRIPTORS[tool_name].tool_class
422
+ return None
423
+
424
+
425
+ def register_optional_tool(
426
+ name: str,
427
+ tool_cls: Type["BaseTool"],
428
+ descriptor: "ToolDescriptor",
429
+ enabled_fn,
430
+ *,
431
+ force: bool = False,
432
+ ) -> bool:
433
+ """Register an opt-in tool (code_exec/cronjob/goal) behind a feature gate.
434
+
435
+ Inserts *descriptor* into ``TOOL_DESCRIPTORS`` idempotently (existing entry is
436
+ never overwritten), then calls ``register_tool_class``. Returns ``True`` iff
437
+ the tool was registered.
438
+
439
+ Args:
440
+ name: Tool key (e.g. ``"cronjob"``).
441
+ tool_cls: The ``BaseTool`` subclass to register.
442
+ descriptor: ``ToolDescriptor`` instance for this tool.
443
+ enabled_fn: Zero-argument callable; if it returns falsy *and* ``force`` is
444
+ ``False``, registration is skipped.
445
+ force: If ``True``, bypass ``enabled_fn`` and register unconditionally.
446
+ """
447
+ if not (force or enabled_fn()):
448
+ return False
449
+ if name not in TOOL_DESCRIPTORS:
450
+ TOOL_DESCRIPTORS[name] = descriptor
451
+ register_tool_class(name, tool_cls)
452
+ return True
tools/dom/__init__.py ADDED
File without changes
@@ -0,0 +1,244 @@
1
+ import hashlib
2
+ from dataclasses import dataclass
3
+ from typing import Optional
4
+
5
+ from tools.dom.history_tree_processor.view import DOMHistoryElement, HashedDomElement
6
+ from tools.dom.views import DOMElementNode
7
+
8
+
9
+ class HistoryTreeProcessor:
10
+ """ "
11
+ Operations on the DOM elements
12
+
13
+ @dev be careful - text nodes can change even if elements stay the same
14
+ """
15
+
16
+ @staticmethod
17
+ def convert_dom_element_to_history_element(dom_element: DOMElementNode) -> DOMHistoryElement:
18
+ try:
19
+ parent_branch_path = HistoryTreeProcessor._get_parent_branch_path(dom_element)
20
+ # Safely try to get the CSS selector with error handling
21
+ try:
22
+ css_selector = dom_element.get_advanced_css_selector()
23
+ except Exception as e:
24
+ # If CSS selector generation fails, create a simple fallback
25
+ css_selector = f"{dom_element.tag_name}_{hash(dom_element.xpath)}"
26
+
27
+ return DOMHistoryElement(
28
+ dom_element.tag_name,
29
+ dom_element.xpath,
30
+ dom_element.highlight_index,
31
+ parent_branch_path,
32
+ dom_element.attributes,
33
+ dom_element.shadow_root,
34
+ css_selector=css_selector,
35
+ page_coordinates=dom_element.page_coordinates,
36
+ viewport_coordinates=dom_element.viewport_coordinates,
37
+ viewport_info=dom_element.viewport_info,
38
+ )
39
+ except Exception as e:
40
+ # Create a minimal history element as fallback if anything fails
41
+ default_branch_path = ["html", "body"] if dom_element.tag_name.lower() != "html" else ["html"]
42
+ return DOMHistoryElement(
43
+ tag_name=dom_element.tag_name or "div",
44
+ xpath=dom_element.xpath or "",
45
+ highlight_index=dom_element.highlight_index,
46
+ entire_parent_branch_path=default_branch_path,
47
+ attributes=dom_element.attributes or {},
48
+ shadow_root=False,
49
+ css_selector=f"fallback-{hash(str(dom_element))}",
50
+ page_coordinates=None,
51
+ viewport_coordinates=None,
52
+ viewport_info=None
53
+ )
54
+
55
+ @staticmethod
56
+ def find_history_element_in_tree(dom_history_element: DOMHistoryElement, tree: DOMElementNode) -> Optional[DOMElementNode]:
57
+ hashed_dom_history_element = HistoryTreeProcessor._hash_dom_history_element(dom_history_element)
58
+
59
+ def process_node(node: DOMElementNode):
60
+ if node.highlight_index is not None:
61
+ hashed_node = HistoryTreeProcessor._hash_dom_element(node)
62
+ if hashed_node == hashed_dom_history_element:
63
+ return node
64
+ for child in node.children:
65
+ if isinstance(child, DOMElementNode):
66
+ result = process_node(child)
67
+ if result is not None:
68
+ return result
69
+ return None
70
+
71
+ return process_node(tree)
72
+
73
+ @staticmethod
74
+ def compare_history_element_and_dom_element(dom_history_element: DOMHistoryElement, dom_element: DOMElementNode) -> bool:
75
+ hashed_dom_history_element = HistoryTreeProcessor._hash_dom_history_element(dom_history_element)
76
+ hashed_dom_element = HistoryTreeProcessor._hash_dom_element(dom_element)
77
+
78
+ return hashed_dom_history_element == hashed_dom_element
79
+
80
+ @staticmethod
81
+ def _hash_dom_history_element(dom_history_element: DOMHistoryElement) -> HashedDomElement:
82
+ branch_path_hash = HistoryTreeProcessor._parent_branch_path_hash(dom_history_element.entire_parent_branch_path)
83
+ attributes_hash = HistoryTreeProcessor._attributes_hash(dom_history_element.attributes)
84
+ xpath_hash = HistoryTreeProcessor._xpath_hash(dom_history_element.xpath)
85
+
86
+ return HashedDomElement(branch_path_hash, attributes_hash, xpath_hash)
87
+
88
+ @staticmethod
89
+ def _hash_dom_element(dom_element: DOMElementNode) -> HashedDomElement:
90
+ """Hash a DOM element with comprehensive error handling"""
91
+ try:
92
+ # Get parent branch path with error handling
93
+ try:
94
+ parent_branch_path = HistoryTreeProcessor._get_parent_branch_path(dom_element)
95
+ except Exception as e:
96
+ import logging
97
+ logging.warning(f"Error getting parent branch path: {str(e)}")
98
+ # Use a fallback path based on tag name
99
+ parent_branch_path = ["html", dom_element.tag_name] if hasattr(dom_element, "tag_name") else ["html", "unknown"]
100
+
101
+ # Get branch path hash with error handling
102
+ try:
103
+ branch_path_hash = HistoryTreeProcessor._parent_branch_path_hash(parent_branch_path)
104
+ except Exception as e:
105
+ import logging
106
+ logging.warning(f"Error hashing branch path: {str(e)}")
107
+ # Use a fallback hash from the path or a constant
108
+ import hashlib
109
+ path_str = "/".join(parent_branch_path)
110
+ branch_path_hash = hashlib.sha256(path_str.encode()).hexdigest()
111
+
112
+ # Get attributes hash with error handling
113
+ try:
114
+ attributes = dom_element.attributes if hasattr(dom_element, "attributes") else {}
115
+ attributes_hash = HistoryTreeProcessor._attributes_hash(attributes)
116
+ except Exception as e:
117
+ import logging
118
+ logging.warning(f"Error hashing attributes: {str(e)}")
119
+ # Use a fallback hash from stringified attributes or a constant
120
+ import hashlib
121
+ attr_str = str(getattr(dom_element, "attributes", {}))
122
+ attributes_hash = hashlib.sha256(attr_str.encode()).hexdigest()
123
+
124
+ # Get xpath hash with error handling
125
+ try:
126
+ xpath = dom_element.xpath if hasattr(dom_element, "xpath") else ""
127
+ xpath_hash = HistoryTreeProcessor._xpath_hash(xpath)
128
+ except Exception as e:
129
+ import logging
130
+ logging.warning(f"Error hashing xpath: {str(e)}")
131
+ # Use a fallback hash from the xpath or a constant
132
+ import hashlib
133
+ xpath_str = str(getattr(dom_element, "xpath", ""))
134
+ xpath_hash = hashlib.sha256(xpath_str.encode()).hexdigest()
135
+
136
+ # Create a HashedDomElement with the computed hashes
137
+ return HashedDomElement(branch_path_hash, attributes_hash, xpath_hash)
138
+ except Exception as e:
139
+ # Log the error and create a minimal valid hash as a fallback
140
+ import logging
141
+ logging.error(f"Critical error in _hash_dom_element: {str(e)}")
142
+
143
+ # Create minimal valid hash values based on element ID to ensure uniqueness
144
+ import hashlib
145
+ element_id = str(id(dom_element))
146
+ fallback_hash = hashlib.sha256(element_id.encode()).hexdigest()
147
+
148
+ # Split the hash into three parts for the three hash fields
149
+ third = len(fallback_hash) // 3
150
+ return HashedDomElement(
151
+ fallback_hash[:third],
152
+ fallback_hash[third:2*third],
153
+ fallback_hash[2*third:]
154
+ )
155
+
156
+ @staticmethod
157
+ def _get_parent_branch_path(dom_element: DOMElementNode) -> list[str]:
158
+ try:
159
+ parents: list[DOMElementNode] = []
160
+ current_element: DOMElementNode = dom_element
161
+
162
+ # Safety check - limit iterations to prevent infinite loops
163
+ iteration_limit = 100
164
+ iteration_count = 0
165
+
166
+ while current_element.parent is not None and iteration_count < iteration_limit:
167
+ parents.append(current_element)
168
+ current_element = current_element.parent
169
+ iteration_count += 1
170
+
171
+ if iteration_count >= iteration_limit:
172
+ # If we hit the limit, it could be a circular reference
173
+ # Return just the direct path we have so far
174
+ return [parent.tag_name for parent in parents[-10:]] if parents else []
175
+
176
+ parents.reverse()
177
+ return [parent.tag_name for parent in parents]
178
+ except Exception as e:
179
+ # If anything goes wrong, return a minimal valid path
180
+ return ["html", "body"] if dom_element.tag_name.lower() != "html" else ["html"]
181
+
182
+ @staticmethod
183
+ def _parent_branch_path_hash(parent_branch_path: list[str]) -> str:
184
+ try:
185
+ # If list is empty, use a default path
186
+ if not parent_branch_path:
187
+ return hashlib.sha256("default/path".encode()).hexdigest()
188
+
189
+ # Join with extra safety for invalid data
190
+ safe_path = []
191
+ for item in parent_branch_path:
192
+ if item is not None and isinstance(item, str):
193
+ safe_path.append(item)
194
+ else:
195
+ safe_path.append("unknown")
196
+
197
+ parent_branch_path_string = '/'.join(safe_path)
198
+ return hashlib.sha256(parent_branch_path_string.encode()).hexdigest()
199
+ except Exception as e:
200
+ # Fallback hash if anything fails
201
+ return hashlib.sha256("error".encode()).hexdigest()
202
+
203
+ @staticmethod
204
+ def _attributes_hash(attributes: dict[str, str]) -> str:
205
+ try:
206
+ if not attributes:
207
+ return hashlib.sha256("empty_attributes".encode()).hexdigest()
208
+
209
+ # Handle attributes safely
210
+ safe_attrs = []
211
+ for key, value in attributes.items():
212
+ if key is not None and value is not None:
213
+ # Convert any non-string values to strings safely
214
+ if not isinstance(key, str):
215
+ key = str(key)
216
+ if not isinstance(value, str):
217
+ value = str(value)
218
+ safe_attrs.append(f'{key}={value}')
219
+
220
+ attributes_string = ''.join(safe_attrs)
221
+ return hashlib.sha256(attributes_string.encode()).hexdigest()
222
+ except Exception as e:
223
+ # Fallback hash if anything fails
224
+ return hashlib.sha256("error_attributes".encode()).hexdigest()
225
+
226
+ @staticmethod
227
+ def _xpath_hash(xpath: str) -> str:
228
+ try:
229
+ if not xpath:
230
+ return hashlib.sha256("empty_xpath".encode()).hexdigest()
231
+
232
+ if not isinstance(xpath, str):
233
+ xpath = str(xpath)
234
+
235
+ return hashlib.sha256(xpath.encode()).hexdigest()
236
+ except Exception as e:
237
+ # Fallback hash if anything fails
238
+ return hashlib.sha256("error_xpath".encode()).hexdigest()
239
+
240
+ @staticmethod
241
+ def _text_hash(dom_element: DOMElementNode) -> str:
242
+ """ """
243
+ text_string = dom_element.get_all_text_till_next_clickable_element()
244
+ return hashlib.sha256(text_string.encode()).hexdigest()