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,452 @@
1
+ """ERC-8004 Trustless Agents API Endpoints.
2
+
3
+ Implements the HTTP API for ERC-8004 integration:
4
+ - Registration file endpoint (for Identity Registry tokenURI)
5
+ - Reputation endpoints (feedback auth, submission, querying)
6
+ - Validation endpoints (request, response, status)
7
+
8
+ Reference: https://eips.ethereum.org/EIPS/eip-8004
9
+ """
10
+
11
+ import os
12
+ import logging
13
+ from typing import Optional, Dict, Any, List
14
+ from fastapi import APIRouter, Request, HTTPException, Depends
15
+ from pydantic import BaseModel, Field
16
+
17
+ from modules.eip8004 import (
18
+ build_registration_file,
19
+ ReputationManager,
20
+ ValidationManager,
21
+ EIP8004Config,
22
+ )
23
+ from modules.eip8004.registration import get_eip8004_config
24
+ from modules.eip8004.models import (
25
+ CreateFeedbackAuthRequest,
26
+ CreateFeedbackAuthResponse,
27
+ SubmitFeedbackRequest,
28
+ GetReputationRequest,
29
+ ReputationSummary,
30
+ RequestValidationRequest,
31
+ ValidationSummary,
32
+ ProofOfPayment,
33
+ FeedbackAuth,
34
+ )
35
+
36
+ logger = logging.getLogger(__name__)
37
+ router = APIRouter(prefix="/eip8004", tags=["EIP-8004 Trustless Agents"])
38
+
39
+ # Singleton managers
40
+ _reputation_manager: Optional[ReputationManager] = None
41
+ _validation_manager: Optional[ValidationManager] = None
42
+
43
+
44
+ def require_eip8004_enabled() -> bool:
45
+ """Gate write endpoints behind EIP8004_ENABLED (404 when off).
46
+
47
+ Discovery/read endpoints stay open; only the state-changing surface is hidden
48
+ unless an operator explicitly enables ERC-8004.
49
+ """
50
+ if os.environ.get("EIP8004_ENABLED", "false").lower() != "true":
51
+ raise HTTPException(status_code=404, detail="ERC-8004 not enabled")
52
+ return True
53
+
54
+
55
+ def require_owner_or_admin(request: Request) -> bool:
56
+ """Require admin/owner for sensitive ERC-8004 writes.
57
+
58
+ /reputation/authorize signs an EIP-712 payload with the AGENT'S private key,
59
+ so it must never be callable anonymously (it would be a signing oracle).
60
+ """
61
+ if not getattr(request.state, "is_admin", False):
62
+ raise HTTPException(status_code=403, detail="Admin access required")
63
+ return True
64
+
65
+
66
+ def get_reputation_manager() -> ReputationManager:
67
+ """Get or create reputation manager singleton."""
68
+ global _reputation_manager
69
+ if _reputation_manager is None:
70
+ _reputation_manager = ReputationManager()
71
+ return _reputation_manager
72
+
73
+
74
+ def get_validation_manager() -> ValidationManager:
75
+ """Get or create validation manager singleton."""
76
+ global _validation_manager
77
+ if _validation_manager is None:
78
+ _validation_manager = ValidationManager()
79
+ return _validation_manager
80
+
81
+
82
+ # =============================================================================
83
+ # Registration / Discovery Endpoints
84
+ # =============================================================================
85
+
86
+ @router.get("/registration.json", response_model=Dict[str, Any])
87
+ async def get_registration_file(request: Request):
88
+ """Get the ERC-8004 registration file.
89
+
90
+ This is what the Identity Registry tokenURI points to.
91
+ Contains all agent endpoints (A2A, MCP, wallets) and trust models.
92
+
93
+ Returns:
94
+ Registration file JSON per ERC-8004 spec
95
+ """
96
+ # Determine base URL
97
+ scheme = request.headers.get("x-forwarded-proto", request.url.scheme)
98
+ host = request.headers.get("host", request.url.netloc)
99
+ base_url = f"{scheme}://{host}"
100
+
101
+ registration = build_registration_file(base_url)
102
+ return registration.model_dump(exclude_none=True)
103
+
104
+
105
+ @router.get("/config")
106
+ async def get_config():
107
+ """Get ERC-8004 configuration status.
108
+
109
+ Returns:
110
+ Current configuration (addresses, chain, supported trust models)
111
+ """
112
+ config = get_eip8004_config()
113
+ return {
114
+ "enabled": config.enabled,
115
+ "chainId": config.chain_id,
116
+ "agentId": config.agent_id,
117
+ "identityRegistry": config.identity_registry_address,
118
+ "reputationRegistry": config.reputation_registry_address,
119
+ "validationRegistry": config.validation_registry_address,
120
+ "supportedTrust": config.supported_trust,
121
+ }
122
+
123
+
124
+ # =============================================================================
125
+ # Reputation Registry Endpoints
126
+ # =============================================================================
127
+
128
+ class FeedbackAuthRequest(BaseModel):
129
+ """Request body for creating feedback authorization."""
130
+ clientAddress: str = Field(..., description="Client wallet address to authorize")
131
+ taskId: Optional[str] = Field(None, description="Optional A2A task ID")
132
+ expiresInSeconds: int = Field(default=86400, description="Validity period (default 24h)")
133
+
134
+
135
+ class FeedbackAuthResponse(BaseModel):
136
+ """Response with feedback authorization."""
137
+ agentId: int
138
+ clientAddress: str
139
+ expiresAt: int
140
+ nonce: str
141
+ signature: str
142
+ message: str = "Feedback authorization created"
143
+
144
+
145
+ @router.post(
146
+ "/reputation/authorize",
147
+ response_model=FeedbackAuthResponse,
148
+ dependencies=[Depends(require_eip8004_enabled), Depends(require_owner_or_admin)],
149
+ )
150
+ async def create_feedback_authorization(
151
+ body: FeedbackAuthRequest,
152
+ manager: ReputationManager = Depends(get_reputation_manager),
153
+ ):
154
+ """Create a signed authorization for a client to submit feedback.
155
+
156
+ This endpoint is called by the agent after accepting a task.
157
+ The client uses the returned authorization when submitting feedback.
158
+
159
+ Args:
160
+ body: Client address and optional task ID
161
+
162
+ Returns:
163
+ Signed FeedbackAuth per ERC-8004 spec
164
+ """
165
+ try:
166
+ auth = await manager.create_feedback_auth(
167
+ client_address=body.clientAddress,
168
+ task_id=body.taskId,
169
+ expires_in_seconds=body.expiresInSeconds,
170
+ )
171
+
172
+ return FeedbackAuthResponse(
173
+ agentId=auth.agentId,
174
+ clientAddress=auth.clientAddress,
175
+ expiresAt=auth.expiresAt,
176
+ nonce=auth.nonce,
177
+ signature=auth.signature,
178
+ )
179
+ except ValueError as e:
180
+ raise HTTPException(status_code=400, detail=str(e))
181
+ except Exception as e:
182
+ logger.error(f"Failed to create feedback auth: {e}")
183
+ raise HTTPException(status_code=500, detail="Failed to create authorization")
184
+
185
+
186
+ class SubmitFeedbackBody(BaseModel):
187
+ """Request body for feedback submission."""
188
+ agentId: int = Field(..., description="Agent's on-chain ID")
189
+ score: int = Field(..., ge=0, le=100, description="Score 0-100")
190
+
191
+ # Authorization (from /reputation/authorize)
192
+ feedbackAuth: Dict[str, Any] = Field(..., description="Authorization from agent")
193
+
194
+ # Optional fields
195
+ tag1: Optional[str] = Field(None, description="Primary categorization tag")
196
+ tag2: Optional[str] = Field(None, description="Secondary tag")
197
+ skill: Optional[str] = Field(None, description="A2A skill identifier")
198
+ taskId: Optional[str] = Field(None, description="A2A task ID")
199
+ comment: Optional[str] = Field(None, description="Text feedback")
200
+
201
+ # x402 integration
202
+ proofOfPayment: Optional[Dict[str, str]] = Field(None, description="x402 payment proof")
203
+
204
+
205
+ @router.post("/reputation/feedback", dependencies=[Depends(require_eip8004_enabled)])
206
+ async def submit_feedback(
207
+ body: SubmitFeedbackBody,
208
+ manager: ReputationManager = Depends(get_reputation_manager),
209
+ ):
210
+ """Submit feedback for an agent.
211
+
212
+ Called by clients after completing a task. Requires valid authorization
213
+ from the agent (obtained via /reputation/authorize).
214
+
215
+ Args:
216
+ body: Feedback data including score, auth, and optional tags
217
+
218
+ Returns:
219
+ Submission result with file hash
220
+ """
221
+ try:
222
+ # Parse feedback auth
223
+ auth = FeedbackAuth(**body.feedbackAuth)
224
+
225
+ # Parse proof of payment if provided
226
+ pop = None
227
+ if body.proofOfPayment:
228
+ pop = ProofOfPayment(**body.proofOfPayment)
229
+
230
+ result = await manager.submit_feedback(
231
+ agent_id=body.agentId,
232
+ score=body.score,
233
+ feedback_auth=auth,
234
+ tag1=body.tag1,
235
+ tag2=body.tag2,
236
+ skill=body.skill,
237
+ task_id=body.taskId,
238
+ proof_of_payment=pop,
239
+ comment=body.comment,
240
+ )
241
+
242
+ return result
243
+ except ValueError as e:
244
+ raise HTTPException(status_code=400, detail=str(e))
245
+ except Exception as e:
246
+ logger.error(f"Failed to submit feedback: {e}")
247
+ raise HTTPException(status_code=500, detail="Failed to submit feedback")
248
+
249
+
250
+ class ReputationQuery(BaseModel):
251
+ """Query parameters for reputation lookup."""
252
+ agentId: int
253
+ clientAddress: Optional[str] = None
254
+ tag1: Optional[str] = None
255
+ tag2: Optional[str] = None
256
+
257
+
258
+ @router.post("/reputation/query", response_model=ReputationSummary)
259
+ async def query_reputation(
260
+ body: ReputationQuery,
261
+ manager: ReputationManager = Depends(get_reputation_manager),
262
+ ):
263
+ """Query reputation for an agent.
264
+
265
+ Returns aggregated feedback statistics with optional filtering.
266
+
267
+ Args:
268
+ body: Query filters (agent ID, client, tags)
269
+
270
+ Returns:
271
+ ReputationSummary with scores and stats
272
+ """
273
+ return await manager.get_reputation(
274
+ agent_id=body.agentId,
275
+ client_address=body.clientAddress,
276
+ tag1=body.tag1,
277
+ tag2=body.tag2,
278
+ )
279
+
280
+
281
+ @router.get("/reputation/{agent_id}")
282
+ async def get_reputation(
283
+ agent_id: int,
284
+ limit: int = 50,
285
+ offset: int = 0,
286
+ manager: ReputationManager = Depends(get_reputation_manager),
287
+ ):
288
+ """Get reputation summary and feedback list for an agent.
289
+
290
+ Args:
291
+ agent_id: Agent's on-chain ID
292
+ limit: Max feedback entries to return
293
+ offset: Pagination offset
294
+
295
+ Returns:
296
+ Summary and list of feedback entries
297
+ """
298
+ summary = await manager.get_reputation(agent_id=agent_id)
299
+ feedback_list = await manager.get_feedback_list(
300
+ agent_id=agent_id,
301
+ limit=limit,
302
+ offset=offset,
303
+ )
304
+
305
+ return {
306
+ "summary": summary.model_dump(),
307
+ "feedback": feedback_list,
308
+ }
309
+
310
+
311
+ # =============================================================================
312
+ # Validation Registry Endpoints
313
+ # =============================================================================
314
+
315
+ class ValidationRequestBody(BaseModel):
316
+ """Request body for validation request."""
317
+ validatorAddress: str = Field(..., description="Validator contract address")
318
+ requestData: Dict[str, Any] = Field(..., description="Data to validate")
319
+
320
+
321
+ @router.post("/validation/request", dependencies=[Depends(require_eip8004_enabled)])
322
+ async def request_validation(
323
+ body: ValidationRequestBody,
324
+ manager: ValidationManager = Depends(get_validation_manager),
325
+ ):
326
+ """Request validation from a validator.
327
+
328
+ Submits data to be validated by a specific validator contract.
329
+
330
+ Args:
331
+ body: Validator address and request data
332
+
333
+ Returns:
334
+ Request result with hash for tracking
335
+ """
336
+ try:
337
+ result = await manager.request_validation(
338
+ validator_address=body.validatorAddress,
339
+ request_data=body.requestData,
340
+ )
341
+ return result
342
+ except ValueError as e:
343
+ raise HTTPException(status_code=400, detail=str(e))
344
+ except Exception as e:
345
+ logger.error(f"Failed to request validation: {e}")
346
+ raise HTTPException(status_code=500, detail="Failed to request validation")
347
+
348
+
349
+ class ValidationResponseBody(BaseModel):
350
+ """Request body for validation response."""
351
+ requestHash: str = Field(..., description="Hash of original request")
352
+ response: int = Field(..., ge=0, le=100, description="Result 0-100")
353
+ responseData: Optional[Dict[str, Any]] = Field(None, description="Evidence data")
354
+ tag: Optional[str] = Field(None, description="Categorization tag")
355
+
356
+
357
+ @router.post(
358
+ "/validation/respond",
359
+ dependencies=[Depends(require_eip8004_enabled), Depends(require_owner_or_admin)],
360
+ )
361
+ async def submit_validation_response(
362
+ body: ValidationResponseBody,
363
+ manager: ValidationManager = Depends(get_validation_manager),
364
+ ):
365
+ """Submit a validation response.
366
+
367
+ Called by validators after processing a request.
368
+
369
+ Args:
370
+ body: Request hash, response value, optional evidence
371
+
372
+ Returns:
373
+ Response submission result
374
+ """
375
+ try:
376
+ result = await manager.submit_response(
377
+ request_hash=body.requestHash,
378
+ response=body.response,
379
+ response_data=body.responseData,
380
+ tag=body.tag,
381
+ )
382
+ return result
383
+ except ValueError as e:
384
+ raise HTTPException(status_code=400, detail=str(e))
385
+ except Exception as e:
386
+ logger.error(f"Failed to submit validation response: {e}")
387
+ raise HTTPException(status_code=500, detail="Failed to submit response")
388
+
389
+
390
+ @router.get("/validation/status/{request_hash}")
391
+ async def get_validation_status(
392
+ request_hash: str,
393
+ manager: ValidationManager = Depends(get_validation_manager),
394
+ ):
395
+ """Get status of a validation request.
396
+
397
+ Args:
398
+ request_hash: Hash of the validation request
399
+
400
+ Returns:
401
+ Validation status with response and timestamp
402
+ """
403
+ status = await manager.get_validation_status(request_hash)
404
+ if status is None:
405
+ raise HTTPException(status_code=404, detail="Validation request not found")
406
+
407
+ return status.model_dump()
408
+
409
+
410
+ @router.get("/validation/summary/{agent_id}", response_model=ValidationSummary)
411
+ async def get_validation_summary(
412
+ agent_id: int,
413
+ manager: ValidationManager = Depends(get_validation_manager),
414
+ ):
415
+ """Get validation summary for an agent.
416
+
417
+ Args:
418
+ agent_id: Agent's on-chain ID
419
+
420
+ Returns:
421
+ ValidationSummary with aggregated stats
422
+ """
423
+ return await manager.get_validation_summary(agent_id=agent_id)
424
+
425
+
426
+ @router.get("/validation/pending")
427
+ async def list_pending_validations(
428
+ agent_id: Optional[int] = None,
429
+ manager: ValidationManager = Depends(get_validation_manager),
430
+ ):
431
+ """List pending validation requests.
432
+
433
+ Args:
434
+ agent_id: Optional filter by agent ID
435
+
436
+ Returns:
437
+ List of pending validation requests
438
+ """
439
+ return await manager.list_pending_validations(agent_id=agent_id)
440
+
441
+
442
+ @router.get("/validation/validators")
443
+ async def list_validators(
444
+ manager: ValidationManager = Depends(get_validation_manager),
445
+ ):
446
+ """List supported validator types.
447
+
448
+ Returns:
449
+ Dictionary of validator types and descriptions
450
+ """
451
+ return manager.get_supported_validators()
452
+
@@ -0,0 +1,174 @@
1
+ """
2
+ Hyperliquid API Models
3
+
4
+ Pydantic models for request/response validation.
5
+ """
6
+
7
+ import re
8
+ from typing import Optional, Dict, Any, List
9
+ from pydantic import BaseModel, Field, field_validator
10
+
11
+
12
+ # =============================================================================
13
+ # Validation Patterns
14
+ # =============================================================================
15
+
16
+ WALLET_ADDRESS_PATTERN = re.compile(r"^0x[a-fA-F0-9]{40}$")
17
+ PRIVATE_KEY_PATTERN = re.compile(r"^(0x)?[a-fA-F0-9]{64}$")
18
+
19
+
20
+ # =============================================================================
21
+ # Request Models
22
+ # =============================================================================
23
+
24
+ class ConfigureHyperliquidRequest(BaseModel):
25
+ """Request to configure Hyperliquid credentials"""
26
+
27
+ wallet_address: str = Field(..., description="Ethereum wallet address (0x...)")
28
+ private_key: str = Field(..., description="Wallet private key")
29
+
30
+ # Optional agent wallet for delegated trading
31
+ agent_wallet_address: Optional[str] = Field(None, description="Agent wallet address")
32
+ agent_wallet_private_key: Optional[str] = Field(None, description="Agent wallet private key")
33
+ agent_wallet_name: Optional[str] = Field(None, description="Agent wallet label")
34
+
35
+ # Network and mode
36
+ testnet: bool = Field(True, description="Use testnet (True) or mainnet (False)")
37
+ demo_mode: bool = Field(True, description="Read-only mode (True) or trading enabled (False)")
38
+
39
+ # Trading limits
40
+ max_order_size_usd: Optional[float] = Field(1000.0, ge=10, le=100000)
41
+ max_leverage: Optional[int] = Field(5, ge=1, le=50)
42
+ enable_autonomous_trading: Optional[bool] = Field(False)
43
+
44
+ @field_validator("wallet_address", "agent_wallet_address", mode="before")
45
+ @classmethod
46
+ def validate_address(cls, v):
47
+ if v is None:
48
+ return v
49
+ if not WALLET_ADDRESS_PATTERN.match(v):
50
+ raise ValueError("Invalid wallet address format (expected 0x followed by 40 hex chars)")
51
+ return v.lower()
52
+
53
+ @field_validator("private_key", "agent_wallet_private_key", mode="before")
54
+ @classmethod
55
+ def validate_private_key(cls, v):
56
+ if v is None:
57
+ return v
58
+ # Remove 0x prefix if present for validation
59
+ key = v[2:] if v.startswith("0x") else v
60
+ if len(key) != 64 or not all(c in "0123456789abcdefABCDEF" for c in key):
61
+ raise ValueError("Invalid private key format (expected 64 hex chars)")
62
+ return v
63
+
64
+
65
+ class UpdateTradingLimitsRequest(BaseModel):
66
+ """Request to update trading limits"""
67
+
68
+ max_order_size_usd: Optional[float] = Field(None, ge=10, le=100000)
69
+ max_total_exposure_usd: Optional[float] = Field(None, ge=100, le=1000000)
70
+ max_position_per_market_usd: Optional[float] = Field(None, ge=100, le=500000)
71
+ max_leverage: Optional[int] = Field(None, ge=1, le=50)
72
+ max_daily_loss_usd: Optional[float] = Field(None, ge=10, le=50000)
73
+ require_confirmation_above_usd: Optional[float] = Field(None, ge=0)
74
+ enable_autonomous_trading: Optional[bool] = Field(None)
75
+ allowed_coins: Optional[List[str]] = Field(None)
76
+ blocked_coins: Optional[List[str]] = Field(None)
77
+
78
+
79
+ class ExecuteToolRequest(BaseModel):
80
+ """Request to execute a tool action"""
81
+
82
+ tool_name: str = Field(..., description="Name of the tool to execute")
83
+ arguments: Optional[Dict[str, Any]] = Field(default_factory=dict)
84
+
85
+
86
+ class SetDemoModeRequest(BaseModel):
87
+ """Request to set demo mode"""
88
+ demo_mode: bool = Field(..., description="True for read-only, False for trading")
89
+
90
+
91
+ class SetEnabledRequest(BaseModel):
92
+ """Request to enable/disable the tool"""
93
+ enabled: bool = Field(..., description="True to enable, False to disable")
94
+
95
+
96
+ # =============================================================================
97
+ # Response Models
98
+ # =============================================================================
99
+
100
+ class HyperliquidStatusResponse(BaseModel):
101
+ """Response for configuration status"""
102
+
103
+ configured: bool
104
+ wallet_address: Optional[str] = None
105
+ agent_wallet_address: Optional[str] = None
106
+ testnet: bool = True
107
+ demo_mode: bool = True
108
+ enabled: bool = False
109
+ trading_limits: Optional[Dict[str, Any]] = None
110
+ connection_count: Optional[int] = None
111
+ last_connected_at: Optional[str] = None
112
+ last_error: Optional[str] = None
113
+
114
+
115
+ class ExecuteToolResponse(BaseModel):
116
+ """Response for tool execution"""
117
+
118
+ success: bool
119
+ data: Optional[Any] = None
120
+ error: Optional[str] = None
121
+ tool_name: Optional[str] = None
122
+ execution_time_ms: Optional[float] = None
123
+
124
+
125
+ class AvailableToolsResponse(BaseModel):
126
+ """Response listing available tools"""
127
+
128
+ tools: List[Dict[str, Any]]
129
+ count: int
130
+
131
+
132
+ class AuditLogEntry(BaseModel):
133
+ """Single audit log entry"""
134
+
135
+ id: int
136
+ action: str
137
+ tool_name: Optional[str] = None
138
+ market_id: Optional[str] = None
139
+ details: Dict[str, Any] = {}
140
+ ip_address: Optional[str] = None
141
+ timestamp: str
142
+
143
+
144
+ class AuditLogResponse(BaseModel):
145
+ """Response for audit log query"""
146
+
147
+ entries: List[Dict[str, Any]]
148
+ count: int
149
+
150
+
151
+ class TradingStatsResponse(BaseModel):
152
+ """Response for trading statistics"""
153
+
154
+ orders_placed: int = 0
155
+ orders_cancelled: int = 0
156
+ bulk_cancels: int = 0
157
+ leverage_updates: int = 0
158
+ total_actions: int = 0
159
+ first_action: Optional[str] = None
160
+ last_action: Optional[str] = None
161
+
162
+
163
+ class ErrorResponse(BaseModel):
164
+ """Error response"""
165
+
166
+ error: str
167
+ detail: Optional[str] = None
168
+
169
+
170
+ class SuccessResponse(BaseModel):
171
+ """Generic success response"""
172
+
173
+ success: bool = True
174
+ message: Optional[str] = None