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,155 @@
1
+ """
2
+ Pydantic models for Polymarket API endpoints.
3
+ """
4
+
5
+ from typing import Any, Dict, List, Optional
6
+ from pydantic import BaseModel, Field, field_validator
7
+ import re
8
+
9
+
10
+ class TradingLimitsRequest(BaseModel):
11
+ """Trading limits configuration."""
12
+ max_order_size_usd: int = Field(default=1000, ge=1, le=100000)
13
+ max_total_exposure_usd: int = Field(default=5000, ge=1, le=1000000)
14
+ max_position_per_market_usd: int = Field(default=2000, ge=1, le=100000)
15
+ min_liquidity_required: int = Field(default=10000, ge=0)
16
+ max_spread_tolerance: float = Field(default=0.05, ge=0, le=1)
17
+ require_confirmation_above_usd: int = Field(default=500, ge=0)
18
+ enable_autonomous_trading: bool = Field(default=False)
19
+
20
+
21
+ class ConfigurePolymarketRequest(BaseModel):
22
+ """Request to configure Polymarket credentials with proxy wallet support."""
23
+ wallet_address: Optional[str] = Field(
24
+ None,
25
+ description="EOA wallet address (0x...) - derived from private key",
26
+ pattern=r"^0x[a-fA-F0-9]{40}$"
27
+ )
28
+ proxy_wallet_address: Optional[str] = Field(
29
+ None,
30
+ description="Proxy wallet address from Polymarket profile (for website users)",
31
+ pattern=r"^0x[a-fA-F0-9]{40}$"
32
+ )
33
+ private_key: Optional[str] = Field(
34
+ None,
35
+ description="Polygon private key (with or without 0x prefix)",
36
+ min_length=64,
37
+ max_length=66
38
+ )
39
+ signature_type: int = Field(
40
+ default=2,
41
+ ge=0,
42
+ le=2,
43
+ description="Signature type: 0=EOA (hardware wallet), 1=Magic (email wallet), 2=Proxy (Polymarket website users, default)"
44
+ )
45
+ demo_mode: bool = Field(
46
+ default=True,
47
+ description="Use demo mode (read-only, no wallet required)"
48
+ )
49
+ trading_limits: Optional[TradingLimitsRequest] = Field(
50
+ default=None,
51
+ description="Trading safety limits"
52
+ )
53
+
54
+ @field_validator("wallet_address")
55
+ @classmethod
56
+ def validate_wallet_address(cls, v: Optional[str]) -> Optional[str]:
57
+ if v and not re.match(r"^0x[a-fA-F0-9]{40}$", v):
58
+ raise ValueError("Invalid wallet address format. Must be 0x followed by 40 hex characters.")
59
+ return v
60
+
61
+ @field_validator("proxy_wallet_address")
62
+ @classmethod
63
+ def validate_proxy_wallet_address(cls, v: Optional[str]) -> Optional[str]:
64
+ if v and not re.match(r"^0x[a-fA-F0-9]{40}$", v):
65
+ raise ValueError("Invalid proxy wallet address format. Must be 0x followed by 40 hex characters.")
66
+ return v
67
+
68
+ @field_validator("private_key")
69
+ @classmethod
70
+ def validate_private_key(cls, v: Optional[str]) -> Optional[str]:
71
+ if v:
72
+ # Remove 0x prefix for validation
73
+ key = v[2:] if v.startswith("0x") else v
74
+ if len(key) != 64 or not re.match(r"^[a-fA-F0-9]+$", key):
75
+ raise ValueError("Invalid private key format. Must be 64 hex characters.")
76
+ return v
77
+
78
+
79
+ class UpdateTradingLimitsRequest(BaseModel):
80
+ """Request to update trading limits only."""
81
+ trading_limits: TradingLimitsRequest
82
+
83
+
84
+ class PolymarketStatusResponse(BaseModel):
85
+ """Response with Polymarket configuration status."""
86
+ configured: bool
87
+ enabled: bool
88
+ demo_mode: bool
89
+ wallet_address: Optional[str] = None
90
+ proxy_wallet_address: Optional[str] = None
91
+ has_private_key: bool = False
92
+ has_api_credentials: bool = False
93
+ signature_type: int = 2 # 0=EOA, 1=Magic, 2=Proxy
94
+ chain_id: int = 137
95
+ trading_limits: Dict[str, Any]
96
+ connection_count: int = 0
97
+ last_connected_at: Optional[str] = None
98
+ last_error: Optional[str] = None
99
+ allowances_verified: bool = False
100
+
101
+
102
+ class ExecuteToolRequest(BaseModel):
103
+ """Request to execute a Polymarket tool."""
104
+ tool_name: str = Field(..., description="Name of the tool to execute")
105
+ arguments: Dict[str, Any] = Field(
106
+ default_factory=dict,
107
+ description="Tool arguments"
108
+ )
109
+
110
+
111
+ class ExecuteToolResponse(BaseModel):
112
+ """Response from tool execution."""
113
+ success: bool
114
+ data: Optional[Any] = None
115
+ error: Optional[str] = None
116
+ tool_name: str
117
+ execution_time_ms: float
118
+
119
+
120
+ class AvailableToolsResponse(BaseModel):
121
+ """Response with available Polymarket tools."""
122
+ tools: List[Dict[str, Any]]
123
+ demo_mode: bool
124
+ enabled: bool
125
+
126
+
127
+ class AuditLogEntryResponse(BaseModel):
128
+ """Single audit log entry."""
129
+ id: int
130
+ action: str
131
+ tool_name: Optional[str]
132
+ market_id: Optional[str]
133
+ details: Optional[Dict[str, Any]]
134
+ ip_address: Optional[str]
135
+ timestamp: str
136
+
137
+
138
+ class AuditLogResponse(BaseModel):
139
+ """Response with audit log entries."""
140
+ entries: List[AuditLogEntryResponse]
141
+ count: int
142
+
143
+
144
+ class TradingStatsResponse(BaseModel):
145
+ """Response with trading statistics."""
146
+ total_calls: int
147
+ orders_placed: int
148
+ orders_cancelled: int
149
+ first_activity: Optional[str]
150
+ last_activity: Optional[str]
151
+
152
+
153
+ class ErrorResponse(BaseModel):
154
+ """Error response."""
155
+ detail: str
@@ -0,0 +1,501 @@
1
+ """
2
+ API routes for Polymarket integration.
3
+
4
+ Provides endpoints for configuring wallet credentials, executing tools,
5
+ and managing Polymarket access.
6
+ """
7
+
8
+ import logging
9
+ from typing import Optional
10
+ from fastapi import APIRouter, HTTPException, Request, Depends
11
+
12
+ from api.polymarket_models import (
13
+ ConfigurePolymarketRequest,
14
+ UpdateTradingLimitsRequest,
15
+ PolymarketStatusResponse,
16
+ ExecuteToolRequest,
17
+ ExecuteToolResponse,
18
+ AvailableToolsResponse,
19
+ AuditLogResponse,
20
+ AuditLogEntryResponse,
21
+ TradingStatsResponse,
22
+ ErrorResponse,
23
+ )
24
+ from tools.polymarket.models import TradingLimits
25
+ from api.dependencies import get_user_id, get_client_ip
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+ router = APIRouter(tags=["polymarket"])
30
+
31
+
32
+ async def get_polymarket_tool():
33
+ """Get PolymarketTool from container."""
34
+ from core.container import DependencyContainer
35
+
36
+ container = DependencyContainer.get_instance()
37
+ if not container:
38
+ raise HTTPException(status_code=503, detail="Service unavailable")
39
+
40
+ tool = container.get_service("polymarket")
41
+ if not tool:
42
+ raise HTTPException(
43
+ status_code=503,
44
+ detail="Polymarket service not available"
45
+ )
46
+
47
+ return tool
48
+
49
+
50
+ async def get_polymarket_db():
51
+ """Get PolymarketDBHandler from container."""
52
+ from core.container import DependencyContainer
53
+
54
+ container = DependencyContainer.get_instance()
55
+ if not container:
56
+ raise HTTPException(status_code=503, detail="Service unavailable")
57
+
58
+ db = container.get_service("polymarket_db")
59
+ if not db:
60
+ raise HTTPException(
61
+ status_code=503,
62
+ detail="Polymarket database not available"
63
+ )
64
+
65
+ return db
66
+
67
+
68
+ # ========================================
69
+ # CONFIGURATION ENDPOINTS
70
+ # ========================================
71
+
72
+ @router.post(
73
+ "/configure",
74
+ response_model=PolymarketStatusResponse,
75
+ responses={400: {"model": ErrorResponse}}
76
+ )
77
+ async def configure_polymarket(
78
+ request: Request,
79
+ data: ConfigurePolymarketRequest,
80
+ user_id: str = Depends(get_user_id)
81
+ ):
82
+ """
83
+ Configure Polymarket credentials.
84
+
85
+ Set up wallet address and private key for trading, or enable demo mode
86
+ for read-only access to market data.
87
+
88
+ **Demo Mode**: Set `demo_mode: true` to use Polymarket without a wallet.
89
+ You can search markets, view prices, and analyze data, but cannot trade.
90
+
91
+ **Trading Mode**: Set `demo_mode: false` and provide:
92
+ - `wallet_address`: Your Polygon wallet address (0x...)
93
+ - `private_key`: Your wallet's private key (64 hex characters)
94
+
95
+ **Security**: Private keys are encrypted at rest using AES-128-CBC.
96
+ """
97
+ db = await get_polymarket_db()
98
+
99
+ # Validate: if not demo mode, need wallet credentials
100
+ # Check if this is an update (existing credentials) or new setup
101
+ existing_credentials = await db.get_credentials(user_id)
102
+
103
+ if not data.demo_mode:
104
+ # For new setup, require wallet address and private key
105
+ # For updates, allow partial updates (use existing values)
106
+ if not existing_credentials:
107
+ if not data.wallet_address:
108
+ raise HTTPException(
109
+ status_code=400,
110
+ detail="Wallet address required when not in demo mode"
111
+ )
112
+ if not data.private_key:
113
+ raise HTTPException(
114
+ status_code=400,
115
+ detail="Private key required when not in demo mode"
116
+ )
117
+
118
+ # Build trading limits
119
+ trading_limits = None
120
+ if data.trading_limits:
121
+ trading_limits = TradingLimits(
122
+ max_order_size_usd=data.trading_limits.max_order_size_usd,
123
+ max_total_exposure_usd=data.trading_limits.max_total_exposure_usd,
124
+ max_position_per_market_usd=data.trading_limits.max_position_per_market_usd,
125
+ min_liquidity_required=data.trading_limits.min_liquidity_required,
126
+ max_spread_tolerance=data.trading_limits.max_spread_tolerance,
127
+ require_confirmation_above_usd=data.trading_limits.require_confirmation_above_usd,
128
+ enable_autonomous_trading=data.trading_limits.enable_autonomous_trading,
129
+ )
130
+ elif existing_credentials:
131
+ # Preserve existing trading limits if not provided
132
+ trading_limits = existing_credentials.trading_limits
133
+
134
+ # Save credentials with proxy wallet support
135
+ await db.save_credentials(
136
+ user_id=user_id,
137
+ wallet_address=data.wallet_address,
138
+ proxy_wallet_address=data.proxy_wallet_address,
139
+ private_key=data.private_key,
140
+ signature_type=data.signature_type,
141
+ demo_mode=data.demo_mode,
142
+ enabled=True,
143
+ trading_limits=trading_limits
144
+ )
145
+
146
+ return await get_status(request, user_id)
147
+
148
+
149
+ @router.get("/status", response_model=PolymarketStatusResponse)
150
+ async def get_status(
151
+ request: Request,
152
+ user_id: str = Depends(get_user_id)
153
+ ):
154
+ """
155
+ Get Polymarket configuration status.
156
+
157
+ Returns current configuration including wallet address (masked),
158
+ trading limits, and connection statistics.
159
+ """
160
+ db = await get_polymarket_db()
161
+
162
+ credentials = await db.get_credentials(user_id)
163
+
164
+ if not credentials:
165
+ return PolymarketStatusResponse(
166
+ configured=False,
167
+ enabled=False,
168
+ demo_mode=True,
169
+ has_api_credentials=False,
170
+ signature_type=2,
171
+ chain_id=137,
172
+ trading_limits=TradingLimits().to_dict(),
173
+ allowances_verified=False
174
+ )
175
+
176
+ # Mask wallet address for display
177
+ wallet_display = None
178
+ if credentials.wallet_address:
179
+ addr = credentials.wallet_address
180
+ wallet_display = f"{addr[:6]}...{addr[-4:]}"
181
+
182
+ # Mask proxy wallet address for display
183
+ proxy_wallet_display = None
184
+ if credentials.proxy_wallet_address:
185
+ addr = credentials.proxy_wallet_address
186
+ proxy_wallet_display = f"{addr[:6]}...{addr[-4:]}"
187
+
188
+ # Get connection stats from DB
189
+ query = """
190
+ SELECT connection_count, last_connected_at, last_error
191
+ FROM polymarket_credentials
192
+ WHERE user_id = ?
193
+ """
194
+ stats = await db.db.fetch_one(query, (user_id,))
195
+
196
+ return PolymarketStatusResponse(
197
+ configured=True,
198
+ enabled=credentials.enabled,
199
+ demo_mode=credentials.demo_mode,
200
+ wallet_address=wallet_display,
201
+ proxy_wallet_address=proxy_wallet_display,
202
+ has_private_key=bool(credentials.private_key),
203
+ has_api_credentials=credentials.has_api_credentials(),
204
+ signature_type=credentials.signature_type,
205
+ chain_id=credentials.chain_id,
206
+ trading_limits=credentials.trading_limits.to_dict(),
207
+ connection_count=stats["connection_count"] if stats else 0,
208
+ last_connected_at=stats["last_connected_at"] if stats else None,
209
+ last_error=stats["last_error"] if stats else None,
210
+ allowances_verified=credentials.allowances_verified
211
+ )
212
+
213
+
214
+ @router.patch(
215
+ "/trading-limits",
216
+ response_model=PolymarketStatusResponse,
217
+ responses={404: {"model": ErrorResponse}}
218
+ )
219
+ async def update_trading_limits(
220
+ request: Request,
221
+ data: UpdateTradingLimitsRequest,
222
+ user_id: str = Depends(get_user_id)
223
+ ):
224
+ """
225
+ Update trading limits without changing credentials.
226
+
227
+ Allows adjusting safety limits like max order size, exposure limits,
228
+ and autonomous trading settings.
229
+ """
230
+ db = await get_polymarket_db()
231
+
232
+ credentials = await db.get_credentials(user_id)
233
+ if not credentials:
234
+ raise HTTPException(
235
+ status_code=404,
236
+ detail="Polymarket not configured. Use POST /configure first."
237
+ )
238
+
239
+ trading_limits = TradingLimits(
240
+ max_order_size_usd=data.trading_limits.max_order_size_usd,
241
+ max_total_exposure_usd=data.trading_limits.max_total_exposure_usd,
242
+ max_position_per_market_usd=data.trading_limits.max_position_per_market_usd,
243
+ min_liquidity_required=data.trading_limits.min_liquidity_required,
244
+ max_spread_tolerance=data.trading_limits.max_spread_tolerance,
245
+ require_confirmation_above_usd=data.trading_limits.require_confirmation_above_usd,
246
+ enable_autonomous_trading=data.trading_limits.enable_autonomous_trading,
247
+ )
248
+
249
+ await db.save_credentials(
250
+ user_id=user_id,
251
+ wallet_address=credentials.wallet_address,
252
+ proxy_wallet_address=credentials.proxy_wallet_address,
253
+ signature_type=credentials.signature_type,
254
+ demo_mode=credentials.demo_mode,
255
+ enabled=credentials.enabled,
256
+ trading_limits=trading_limits
257
+ )
258
+
259
+ return await get_status(request, user_id)
260
+
261
+
262
+ @router.post("/disable", response_model=PolymarketStatusResponse)
263
+ async def disable_polymarket(
264
+ request: Request,
265
+ user_id: str = Depends(get_user_id)
266
+ ):
267
+ """
268
+ Disable Polymarket access.
269
+
270
+ Disables Polymarket without deleting credentials.
271
+ Can be re-enabled later.
272
+ """
273
+ db = await get_polymarket_db()
274
+
275
+ credentials = await db.get_credentials(user_id)
276
+ if credentials:
277
+ await db.save_credentials(
278
+ user_id=user_id,
279
+ wallet_address=credentials.wallet_address,
280
+ proxy_wallet_address=credentials.proxy_wallet_address,
281
+ signature_type=credentials.signature_type,
282
+ demo_mode=credentials.demo_mode,
283
+ enabled=False,
284
+ trading_limits=credentials.trading_limits
285
+ )
286
+
287
+ return await get_status(request, user_id)
288
+
289
+
290
+ @router.post("/enable", response_model=PolymarketStatusResponse)
291
+ async def enable_polymarket(
292
+ request: Request,
293
+ user_id: str = Depends(get_user_id)
294
+ ):
295
+ """
296
+ Enable Polymarket access.
297
+
298
+ Re-enables Polymarket if it was disabled.
299
+ """
300
+ db = await get_polymarket_db()
301
+
302
+ credentials = await db.get_credentials(user_id)
303
+ if not credentials:
304
+ raise HTTPException(
305
+ status_code=404,
306
+ detail="Polymarket not configured. Use POST /configure first."
307
+ )
308
+
309
+ await db.save_credentials(
310
+ user_id=user_id,
311
+ wallet_address=credentials.wallet_address,
312
+ proxy_wallet_address=credentials.proxy_wallet_address,
313
+ signature_type=credentials.signature_type,
314
+ demo_mode=credentials.demo_mode,
315
+ enabled=True,
316
+ trading_limits=credentials.trading_limits
317
+ )
318
+
319
+ return await get_status(request, user_id)
320
+
321
+
322
+ @router.delete("/credentials")
323
+ async def delete_credentials(
324
+ request: Request,
325
+ user_id: str = Depends(get_user_id)
326
+ ):
327
+ """
328
+ Delete Polymarket credentials.
329
+
330
+ Permanently removes wallet credentials and configuration.
331
+ This action cannot be undone.
332
+ """
333
+ db = await get_polymarket_db()
334
+ await db.delete_credentials(user_id)
335
+
336
+ return {"status": "deleted", "message": "Polymarket credentials removed"}
337
+
338
+
339
+ # ========================================
340
+ # TOOL EXECUTION ENDPOINTS
341
+ # ========================================
342
+
343
+ @router.get("/tools", response_model=AvailableToolsResponse)
344
+ async def get_available_tools(
345
+ request: Request,
346
+ user_id: str = Depends(get_user_id)
347
+ ):
348
+ """
349
+ Get available Polymarket tools.
350
+
351
+ Returns list of all Polymarket tools with their schemas.
352
+ """
353
+ db = await get_polymarket_db()
354
+ tool = await get_polymarket_tool()
355
+
356
+ credentials = await db.get_credentials(user_id)
357
+ if not credentials or not credentials.enabled:
358
+ return AvailableToolsResponse(
359
+ tools=[],
360
+ demo_mode=True,
361
+ enabled=False
362
+ )
363
+
364
+ # Get tools from PolymarketTool
365
+ tools = tool.get_available_tools()
366
+
367
+ return AvailableToolsResponse(
368
+ tools=tools,
369
+ demo_mode=credentials.demo_mode,
370
+ enabled=credentials.enabled
371
+ )
372
+
373
+
374
+ @router.post("/execute", response_model=ExecuteToolResponse)
375
+ async def execute_tool(
376
+ request: Request,
377
+ data: ExecuteToolRequest,
378
+ user_id: str = Depends(get_user_id)
379
+ ):
380
+ """
381
+ Execute a Polymarket tool.
382
+
383
+ Executes the specified tool with provided arguments.
384
+ Trading tools require proper wallet configuration.
385
+ """
386
+ import time
387
+
388
+ polymarket_tool = await get_polymarket_tool()
389
+ db = await get_polymarket_db()
390
+
391
+ # Set user context for the tool
392
+ polymarket_tool.set_user_context(user_id)
393
+
394
+ start_time = time.time()
395
+
396
+ try:
397
+ # Execute the action on the tool
398
+ result = await polymarket_tool.execute_action(data.tool_name, data.arguments)
399
+ execution_time = (time.time() - start_time) * 1000
400
+
401
+ # Log to audit
402
+ await db.audit_log(
403
+ user_id=user_id,
404
+ action="tool_call",
405
+ tool_name=data.tool_name,
406
+ details={"arguments": data.arguments, "success": True},
407
+ ip_address=get_client_ip(request)
408
+ )
409
+
410
+ return ExecuteToolResponse(
411
+ success=True,
412
+ data=result,
413
+ error=None,
414
+ tool_name=data.tool_name,
415
+ execution_time_ms=execution_time
416
+ )
417
+
418
+ except Exception as e:
419
+ execution_time = (time.time() - start_time) * 1000
420
+
421
+ # Log error to audit
422
+ await db.audit_log(
423
+ user_id=user_id,
424
+ action="tool_call_error",
425
+ tool_name=data.tool_name,
426
+ details={"arguments": data.arguments, "error": str(e)},
427
+ ip_address=get_client_ip(request)
428
+ )
429
+
430
+ return ExecuteToolResponse(
431
+ success=False,
432
+ data=None,
433
+ error=str(e),
434
+ tool_name=data.tool_name,
435
+ execution_time_ms=execution_time
436
+ )
437
+
438
+
439
+ # ========================================
440
+ # AUDIT & STATS ENDPOINTS
441
+ # ========================================
442
+
443
+ @router.get("/audit", response_model=AuditLogResponse)
444
+ async def get_audit_log(
445
+ request: Request,
446
+ limit: int = 50,
447
+ action: Optional[str] = None,
448
+ user_id: str = Depends(get_user_id)
449
+ ):
450
+ """
451
+ Get Polymarket audit log.
452
+
453
+ Returns history of Polymarket operations including tool calls,
454
+ configuration changes, and errors.
455
+ """
456
+ db = await get_polymarket_db()
457
+
458
+ entries = await db.get_audit_log(
459
+ user_id,
460
+ limit=min(limit, 100),
461
+ action=action
462
+ )
463
+
464
+ return AuditLogResponse(
465
+ entries=[
466
+ AuditLogEntryResponse(
467
+ id=e["id"],
468
+ action=e["action"],
469
+ tool_name=e["tool_name"],
470
+ market_id=e["market_id"],
471
+ details=e["details"],
472
+ ip_address=e["ip_address"],
473
+ timestamp=e["timestamp"]
474
+ )
475
+ for e in entries
476
+ ],
477
+ count=len(entries)
478
+ )
479
+
480
+
481
+ @router.get("/stats", response_model=TradingStatsResponse)
482
+ async def get_trading_stats(
483
+ request: Request,
484
+ user_id: str = Depends(get_user_id)
485
+ ):
486
+ """
487
+ Get trading statistics.
488
+
489
+ Returns aggregate statistics about Polymarket usage.
490
+ """
491
+ db = await get_polymarket_db()
492
+
493
+ stats = await db.get_trading_stats(user_id)
494
+
495
+ return TradingStatsResponse(
496
+ total_calls=stats["total_calls"],
497
+ orders_placed=stats["orders_placed"],
498
+ orders_cancelled=stats["orders_cancelled"],
499
+ first_activity=stats["first_activity"],
500
+ last_activity=stats["last_activity"]
501
+ )