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
api/a2a/endpoints.py ADDED
@@ -0,0 +1,375 @@
1
+ """A2A Protocol Endpoints - JSON-RPC over HTTP.
2
+
3
+ Implements the A2A JSON-RPC 2.0 interface for task management.
4
+ All methods follow the A2A specification naming convention.
5
+
6
+ Supported Methods:
7
+ - message/send: Create new task or continue existing
8
+ - tasks/get: Get task status
9
+ - tasks/list: List tasks with pagination
10
+ - tasks/cancel: Cancel a task
11
+ - tasks/resubscribe: Resubscribe to streaming events
12
+ - tasks/pushNotificationConfig/*: Push notification management
13
+
14
+ Reference: https://a2a-protocol.org/latest/specification/
15
+ """
16
+
17
+ import logging
18
+ from typing import Optional
19
+ from fastapi import APIRouter, Request, HTTPException, Depends
20
+ from fastapi.responses import JSONResponse
21
+
22
+ from api.a2a.models import (
23
+ JSONRPCRequest, JSONRPCResponse, JSONRPCError, A2AErrorCode,
24
+ SendMessageRequest, GetTaskRequest, ListTasksRequest,
25
+ CancelTaskRequest, TaskResubscriptionRequest,
26
+ SetPushNotificationConfigRequest, PushNotificationConfig,
27
+ A2AMessage, A2ATask, ListTasksResponse
28
+ )
29
+ from api.a2a.task_handler import A2ATaskHandler
30
+ from api.payment_verification import verify_payment_for_request, payment_required_response
31
+
32
+ logger = logging.getLogger(__name__)
33
+ router = APIRouter(prefix="/a2a", tags=["a2a"])
34
+
35
+ # A2A-specific error code for payment required
36
+ A2A_ERROR_PAYMENT_REQUIRED = -32402
37
+
38
+
39
+ def get_task_handler(request: Request) -> A2ATaskHandler:
40
+ """Get A2A task handler from container."""
41
+ from core.container import DependencyContainer
42
+ container = DependencyContainer.get_instance()
43
+ return A2ATaskHandler(container)
44
+
45
+
46
+ # Permissive auth policy (accepts x402, JWT, and API-key auth).
47
+ # Delegates to the canonical implementation in api.dependencies.
48
+ from api.dependencies import get_user_permissive as get_authenticated_user
49
+
50
+
51
+ @router.post("/rpc")
52
+ async def a2a_rpc_endpoint(
53
+ rpc_request: JSONRPCRequest,
54
+ request: Request,
55
+ handler: A2ATaskHandler = Depends(get_task_handler)
56
+ ):
57
+ """A2A JSON-RPC 2.0 endpoint.
58
+
59
+ Handles all A2A protocol methods via JSON-RPC.
60
+ """
61
+ request_id = rpc_request.id
62
+
63
+ try:
64
+ user_id = await get_authenticated_user(request)
65
+ method = rpc_request.method
66
+ params = rpc_request.params or {}
67
+
68
+ logger.info(f"A2A RPC: {method} from user {user_id}")
69
+
70
+ # Route to appropriate handler (pass request for payment verification)
71
+ result = await _handle_rpc_method(
72
+ method=method,
73
+ params=params,
74
+ user_id=user_id,
75
+ handler=handler,
76
+ request=request
77
+ )
78
+
79
+ return JSONRPCResponse(
80
+ id=request_id,
81
+ result=result.dict() if hasattr(result, 'dict') else result
82
+ )
83
+
84
+ except HTTPException as e:
85
+ # Handle 402 Payment Required specially for JSON-RPC
86
+ if e.status_code == 402:
87
+ return JSONRPCResponse(
88
+ id=request_id,
89
+ error=JSONRPCError(
90
+ code=A2A_ERROR_PAYMENT_REQUIRED,
91
+ message="Payment required",
92
+ data=e.detail if isinstance(e.detail, dict) else {"message": e.detail}
93
+ )
94
+ )
95
+ return JSONRPCResponse(
96
+ id=request_id,
97
+ error=JSONRPCError(
98
+ code=A2AErrorCode.AUTHENTICATION_REQUIRED if e.status_code == 401 else A2AErrorCode.INTERNAL_ERROR,
99
+ message=e.detail
100
+ )
101
+ )
102
+ except ValueError as e:
103
+ return JSONRPCResponse(
104
+ id=request_id,
105
+ error=JSONRPCError(
106
+ code=A2AErrorCode.INVALID_PARAMS,
107
+ message=str(e)
108
+ )
109
+ )
110
+ except Exception as e:
111
+ logger.error(f"A2A RPC error: {e}", exc_info=True)
112
+ return JSONRPCResponse(
113
+ id=request_id,
114
+ error=JSONRPCError(
115
+ code=A2AErrorCode.INTERNAL_ERROR,
116
+ message="Internal error",
117
+ data=str(e)
118
+ )
119
+ )
120
+
121
+
122
+ async def _handle_rpc_method(
123
+ method: str,
124
+ params: dict,
125
+ user_id: str,
126
+ handler: A2ATaskHandler,
127
+ request: Request
128
+ ):
129
+ """Handle individual RPC methods with payment verification.
130
+
131
+ Args:
132
+ method: RPC method name
133
+ params: Method parameters
134
+ user_id: Authenticated user
135
+ handler: A2A task handler
136
+ request: FastAPI request for payment verification
137
+
138
+ Returns:
139
+ Method result
140
+
141
+ Raises:
142
+ ValueError: Invalid params
143
+ HTTPException: Method not found or payment required
144
+ """
145
+ # Message operations
146
+ if method == "message/send":
147
+ message = A2AMessage(**params.get("message", {}))
148
+ config = params.get("configuration")
149
+ msg_request = SendMessageRequest(message=message, configuration=config)
150
+
151
+ # Check if this is a new task or continuation
152
+ if message.taskId:
153
+ # Continuation of existing task - already paid
154
+ return await handler.send_message(message.taskId, message, user_id)
155
+ else:
156
+ # NEW TASK: Verify payment before creation
157
+ try:
158
+ payment_method, details = await verify_payment_for_request(
159
+ request=request,
160
+ cost_credits=1 # Session creation = 1 credit
161
+ )
162
+ logger.info(f"A2A RPC task payment verified via {payment_method}: {details}")
163
+ except HTTPException as e:
164
+ if e.status_code == 402:
165
+ # Return 402 with payment options
166
+ raise HTTPException(
167
+ status_code=402,
168
+ detail=payment_required_response(request, cost_credits=1)
169
+ )
170
+ raise
171
+
172
+ return await handler.create_task(msg_request, user_id, message.contextId)
173
+
174
+ # Task operations
175
+ elif method == "tasks/get":
176
+ task_id = params.get("id")
177
+ if not task_id:
178
+ raise ValueError("Missing task id")
179
+ history_length = params.get("historyLength")
180
+ return await handler.get_task(task_id, history_length, user_id=user_id)
181
+
182
+ elif method == "tasks/list":
183
+ context_id = params.get("contextId")
184
+ page_token = params.get("pageToken")
185
+ page_size = params.get("pageSize", 20)
186
+ tasks, next_token = await handler.list_tasks(
187
+ user_id, context_id, page_token, page_size
188
+ )
189
+ return ListTasksResponse(tasks=tasks, nextPageToken=next_token)
190
+
191
+ elif method == "tasks/cancel":
192
+ task_id = params.get("id")
193
+ if not task_id:
194
+ raise ValueError("Missing task id")
195
+ return await handler.cancel_task(task_id, user_id)
196
+
197
+ # Push notification operations
198
+ elif method == "tasks/pushNotificationConfig/set":
199
+ task_id = params.get("taskId")
200
+ config_data = params.get("config", {})
201
+ config = PushNotificationConfig(**config_data)
202
+ await handler.set_push_notification_config(task_id, config, user_id=user_id)
203
+ return {"success": True}
204
+
205
+ elif method == "tasks/pushNotificationConfig/get":
206
+ task_id = params.get("taskId")
207
+ config = await handler.get_push_notification_config(task_id, user_id=user_id)
208
+ return config.dict() if config else None
209
+
210
+ elif method == "tasks/pushNotificationConfig/delete":
211
+ task_id = params.get("taskId")
212
+ success = await handler.delete_push_notification_config(task_id, user_id=user_id)
213
+ return {"success": success}
214
+
215
+ else:
216
+ raise HTTPException(
217
+ status_code=400,
218
+ detail=f"Method '{method}' not found"
219
+ )
220
+
221
+
222
+ # =============================================================================
223
+ @router.post("/tasks")
224
+ async def create_task(
225
+ request_body: SendMessageRequest,
226
+ request: Request,
227
+ handler: A2ATaskHandler = Depends(get_task_handler)
228
+ ):
229
+ """Create a new A2A task with payment verification.
230
+
231
+ RESTful convenience endpoint for task creation.
232
+ Equivalent to message/send RPC method.
233
+ """
234
+ user_id = await get_authenticated_user(request)
235
+
236
+ # Verify payment for new task creation
237
+ try:
238
+ payment_method, details = await verify_payment_for_request(
239
+ request=request,
240
+ cost_credits=1
241
+ )
242
+ logger.info(f"A2A REST task payment verified via {payment_method}")
243
+ except HTTPException as e:
244
+ if e.status_code == 402:
245
+ return JSONResponse(
246
+ status_code=402,
247
+ content=payment_required_response(request, cost_credits=1)
248
+ )
249
+ raise
250
+
251
+ return await handler.create_task(
252
+ request_body,
253
+ user_id,
254
+ request_body.message.contextId
255
+ )
256
+
257
+
258
+ @router.get("/tasks/{task_id}")
259
+ async def get_task(
260
+ task_id: str,
261
+ historyLength: Optional[int] = None,
262
+ request: Request = None,
263
+ handler: A2ATaskHandler = Depends(get_task_handler)
264
+ ):
265
+ """Get A2A task status.
266
+
267
+ RESTful convenience endpoint for getting task status.
268
+ Equivalent to tasks/get RPC method.
269
+ """
270
+ # Authenticate and enforce ownership (was previously unauthenticated — IDOR).
271
+ user_id = await get_authenticated_user(request)
272
+ try:
273
+ return await handler.get_task(task_id, historyLength, user_id=user_id)
274
+ except ValueError as e:
275
+ raise HTTPException(status_code=404, detail=str(e))
276
+
277
+
278
+ @router.post("/tasks/{task_id}/send")
279
+ async def send_to_task(
280
+ task_id: str,
281
+ message: A2AMessage,
282
+ request: Request,
283
+ handler: A2ATaskHandler = Depends(get_task_handler)
284
+ ):
285
+ """Send a message to an existing A2A task.
286
+
287
+ RESTful convenience endpoint for continuing tasks.
288
+ Equivalent to message/send RPC method with taskId.
289
+ """
290
+ user_id = await get_authenticated_user(request)
291
+ message.taskId = task_id # Ensure ID matches path
292
+ try:
293
+ return await handler.send_message(task_id, message, user_id)
294
+ except ValueError as e:
295
+ raise HTTPException(status_code=400, detail=str(e))
296
+
297
+
298
+ @router.post("/tasks/{task_id}/cancel")
299
+ async def cancel_task(
300
+ task_id: str,
301
+ request: Request,
302
+ handler: A2ATaskHandler = Depends(get_task_handler)
303
+ ):
304
+ """Cancel an A2A task.
305
+
306
+ RESTful convenience endpoint for task cancellation.
307
+ Equivalent to tasks/cancel RPC method.
308
+ """
309
+ user_id = await get_authenticated_user(request)
310
+ try:
311
+ return await handler.cancel_task(task_id, user_id)
312
+ except ValueError as e:
313
+ raise HTTPException(status_code=400, detail=str(e))
314
+
315
+
316
+ @router.get("/tasks")
317
+ async def list_tasks(
318
+ contextId: Optional[str] = None,
319
+ pageToken: Optional[str] = None,
320
+ pageSize: int = 20,
321
+ request: Request = None,
322
+ handler: A2ATaskHandler = Depends(get_task_handler)
323
+ ):
324
+ """List A2A tasks with pagination.
325
+
326
+ RESTful convenience endpoint for listing tasks.
327
+ Equivalent to tasks/list RPC method.
328
+ """
329
+ user_id = await get_authenticated_user(request)
330
+ tasks, next_token = await handler.list_tasks(
331
+ user_id, contextId, pageToken, pageSize
332
+ )
333
+ return ListTasksResponse(tasks=tasks, nextPageToken=next_token)
334
+
335
+
336
+ # =============================================================================
337
+ @router.post("/tasks/{task_id}/push-config")
338
+ async def set_push_config(
339
+ task_id: str,
340
+ config: PushNotificationConfig,
341
+ request: Request,
342
+ handler: A2ATaskHandler = Depends(get_task_handler)
343
+ ):
344
+ """Set push notification config for a task."""
345
+ user_id = await get_authenticated_user(request)
346
+ await handler.set_push_notification_config(task_id, config, user_id=user_id)
347
+ return {"success": True, "taskId": task_id}
348
+
349
+
350
+ @router.get("/tasks/{task_id}/push-config")
351
+ async def get_push_config(
352
+ task_id: str,
353
+ request: Request,
354
+ handler: A2ATaskHandler = Depends(get_task_handler)
355
+ ):
356
+ """Get push notification config for a task."""
357
+ user_id = await get_authenticated_user(request)
358
+ config = await handler.get_push_notification_config(task_id, user_id=user_id)
359
+ if not config:
360
+ raise HTTPException(status_code=404, detail="No push config found")
361
+ return config
362
+
363
+
364
+ @router.delete("/tasks/{task_id}/push-config")
365
+ async def delete_push_config(
366
+ task_id: str,
367
+ request: Request,
368
+ handler: A2ATaskHandler = Depends(get_task_handler)
369
+ ):
370
+ """Delete push notification config for a task."""
371
+ user_id = await get_authenticated_user(request)
372
+ success = await handler.delete_push_notification_config(task_id, user_id=user_id)
373
+ if not success:
374
+ raise HTTPException(status_code=404, detail="No push config found")
375
+ return {"success": True, "taskId": task_id}
api/a2a/models.py ADDED
@@ -0,0 +1,268 @@
1
+ """A2A Protocol Models - Pydantic models for A2A communication.
2
+
3
+ Based on Google's A2A Protocol Specification:
4
+ https://a2a-protocol.org/latest/specification/
5
+
6
+ All models follow the official A2A schema definitions.
7
+ """
8
+
9
+ from typing import Optional, List, Dict, Any, Union, Literal
10
+ from pydantic import BaseModel, Field
11
+ from enum import Enum
12
+ from datetime import datetime
13
+ import uuid
14
+
15
+
16
+ class A2ATaskState(str, Enum):
17
+ """A2A Task lifecycle states.
18
+
19
+ Non-terminal (active) states:
20
+ - submitted: Initial state, typically transitions immediately to working
21
+ - working: Agent actively processing the task
22
+
23
+ Interrupted states (can resume):
24
+ - input-required: Awaiting client information
25
+ - auth-required: Awaiting external authentication
26
+
27
+ Terminal states (immutable):
28
+ - completed: Task finished successfully
29
+ - failed: Task processing failed
30
+ - canceled: User-initiated cancellation
31
+ - rejected: Agent declined execution
32
+ - unknown: Unknown/undefined terminal state
33
+ """
34
+ SUBMITTED = "submitted"
35
+ WORKING = "working"
36
+ INPUT_REQUIRED = "input-required"
37
+ AUTH_REQUIRED = "auth-required"
38
+ COMPLETED = "completed"
39
+ FAILED = "failed"
40
+ CANCELED = "canceled"
41
+ REJECTED = "rejected"
42
+ UNKNOWN = "unknown"
43
+
44
+ @classmethod
45
+ def is_terminal(cls, state: 'A2ATaskState') -> bool:
46
+ """Check if state is terminal (no further transitions allowed)."""
47
+ return state in [
48
+ cls.COMPLETED, cls.FAILED, cls.CANCELED,
49
+ cls.REJECTED, cls.UNKNOWN
50
+ ]
51
+
52
+ @classmethod
53
+ def is_interrupted(cls, state: 'A2ATaskState') -> bool:
54
+ """Check if state is interrupted (awaiting input)."""
55
+ return state in [cls.INPUT_REQUIRED, cls.AUTH_REQUIRED]
56
+
57
+
58
+ class TextPart(BaseModel):
59
+ """Text content part."""
60
+ kind: Literal['text'] = 'text'
61
+ text: str
62
+ metadata: Optional[Dict[str, Any]] = None
63
+
64
+
65
+ class FileWithBytes(BaseModel):
66
+ """File content with inline bytes."""
67
+ bytes: str # base64-encoded content
68
+ name: Optional[str] = None
69
+ mimeType: Optional[str] = None
70
+
71
+
72
+ class FileWithUri(BaseModel):
73
+ """File content with URI reference."""
74
+ uri: str
75
+ name: Optional[str] = None
76
+ mimeType: Optional[str] = None
77
+
78
+
79
+ class FilePart(BaseModel):
80
+ """File content part."""
81
+ kind: Literal['file'] = 'file'
82
+ file: Union[FileWithBytes, FileWithUri]
83
+ metadata: Optional[Dict[str, Any]] = None
84
+
85
+
86
+ class DataPart(BaseModel):
87
+ """Structured JSON data part."""
88
+ kind: Literal['data'] = 'data'
89
+ data: Dict[str, Any]
90
+ metadata: Optional[Dict[str, Any]] = None
91
+
92
+
93
+ # Part union type
94
+ Part = Union[TextPart, FilePart, DataPart]
95
+
96
+
97
+ class A2AMessage(BaseModel):
98
+ """A2A Message - Communication payload.
99
+
100
+ Messages represent a single turn of communication between
101
+ user/client and agent.
102
+ """
103
+ messageId: str = Field(default_factory=lambda: str(uuid.uuid4()))
104
+ role: Literal["user", "agent"]
105
+ parts: List[Dict[str, Any]] # Mixed parts (text, file, data)
106
+ kind: Literal['message'] = 'message'
107
+ taskId: Optional[str] = None
108
+ contextId: Optional[str] = None
109
+ referenceTaskIds: Optional[List[str]] = None
110
+ extensions: Optional[List[str]] = None
111
+ metadata: Optional[Dict[str, Any]] = None
112
+
113
+
114
+ class A2AArtifact(BaseModel):
115
+ """A2A Artifact - Output produced by agent.
116
+
117
+ Artifacts represent outputs/results of task execution.
118
+ Can contain mixed content types via parts array.
119
+ """
120
+ artifactId: str = Field(default_factory=lambda: str(uuid.uuid4()))
121
+ parts: List[Dict[str, Any]]
122
+ name: Optional[str] = None
123
+ description: Optional[str] = None
124
+ extensions: Optional[List[str]] = None
125
+ metadata: Optional[Dict[str, Any]] = None
126
+
127
+ # Streaming support
128
+ index: Optional[int] = None # Index within owning task
129
+ append: Optional[bool] = None # For streaming: append to existing?
130
+ lastChunk: Optional[bool] = None # For streaming: final chunk?
131
+
132
+
133
+ class A2ATaskStatus(BaseModel):
134
+ """Task status and related messages."""
135
+ state: A2ATaskState
136
+ message: Optional[A2AMessage] = None
137
+ timestamp: Optional[str] = Field(default_factory=lambda: datetime.now().isoformat())
138
+
139
+
140
+ class A2ATask(BaseModel):
141
+ """A2A Task - Fundamental unit of work.
142
+
143
+ Tasks encapsulate the entire lifecycle of an agent interaction,
144
+ from initial request to final result.
145
+ """
146
+ id: str = Field(default_factory=lambda: str(uuid.uuid4()))
147
+ contextId: str = Field(default_factory=lambda: str(uuid.uuid4()))
148
+ status: A2ATaskStatus
149
+ kind: Literal['task'] = 'task'
150
+ history: Optional[List[A2AMessage]] = None
151
+ artifacts: Optional[List[A2AArtifact]] = None
152
+ metadata: Optional[Dict[str, Any]] = None
153
+
154
+
155
+ class SendMessageRequest(BaseModel):
156
+ """Request to send a message (create or continue task)."""
157
+ message: A2AMessage
158
+ configuration: Optional[Dict[str, Any]] = None # pushNotificationConfig, etc.
159
+
160
+
161
+ class SendMessageResponse(BaseModel):
162
+ """Response from sending a message."""
163
+ task: Optional[A2ATask] = None
164
+ message: Optional[A2AMessage] = None
165
+
166
+
167
+ class GetTaskRequest(BaseModel):
168
+ """Request to get task status."""
169
+ id: str
170
+ historyLength: Optional[int] = None # None = all, 0 = none, >0 = last N
171
+ metadata: Optional[Dict[str, Any]] = None
172
+
173
+
174
+ class ListTasksRequest(BaseModel):
175
+ """Request to list tasks."""
176
+ contextId: Optional[str] = None
177
+ pageToken: Optional[str] = None
178
+ pageSize: Optional[int] = 20
179
+ includeArtifacts: Optional[bool] = False
180
+
181
+
182
+ class ListTasksResponse(BaseModel):
183
+ """Response for listing tasks."""
184
+ tasks: List[A2ATask]
185
+ nextPageToken: Optional[str] = None
186
+
187
+
188
+ class CancelTaskRequest(BaseModel):
189
+ """Request to cancel a task."""
190
+ id: str
191
+
192
+
193
+ class TaskResubscriptionRequest(BaseModel):
194
+ """Request to resubscribe to task events."""
195
+ id: str
196
+ historyLength: Optional[int] = None
197
+
198
+
199
+ class AuthenticationInfo(BaseModel):
200
+ """Authentication info for webhook callbacks."""
201
+ schemes: List[str] # e.g., ["Bearer"]
202
+ credentials: Optional[str] = None
203
+
204
+
205
+ class PushNotificationConfig(BaseModel):
206
+ """Configuration for webhook push notifications."""
207
+ url: str # HTTPS webhook endpoint
208
+ token: Optional[str] = None # Client-generated validation token
209
+ authentication: Optional[AuthenticationInfo] = None
210
+
211
+
212
+ class SetPushNotificationConfigRequest(BaseModel):
213
+ """Request to set push notification config."""
214
+ taskId: str
215
+ config: PushNotificationConfig
216
+
217
+
218
+ class TaskStatusUpdateEvent(BaseModel):
219
+ """Task status update event in streaming response."""
220
+ task: A2ATask
221
+ final: bool = False # True if this is the final update
222
+
223
+
224
+ class TaskArtifactUpdateEvent(BaseModel):
225
+ """Artifact update event in streaming response."""
226
+ taskId: str
227
+ artifact: A2AArtifact
228
+
229
+
230
+ class JSONRPCRequest(BaseModel):
231
+ """JSON-RPC 2.0 Request."""
232
+ jsonrpc: str = "2.0"
233
+ method: str
234
+ params: Optional[Dict[str, Any]] = None
235
+ id: Optional[Union[str, int]] = None
236
+
237
+
238
+ class JSONRPCError(BaseModel):
239
+ """JSON-RPC 2.0 Error."""
240
+ code: int
241
+ message: str
242
+ data: Optional[Any] = None
243
+
244
+
245
+ class JSONRPCResponse(BaseModel):
246
+ """JSON-RPC 2.0 Response."""
247
+ jsonrpc: str = "2.0"
248
+ result: Optional[Any] = None
249
+ error: Optional[JSONRPCError] = None
250
+ id: Optional[Union[str, int]] = None
251
+
252
+
253
+ class A2AErrorCode:
254
+ """A2A-specific error codes (JSON-RPC server error range)."""
255
+ # Standard JSON-RPC errors
256
+ PARSE_ERROR = -32700
257
+ INVALID_REQUEST = -32600
258
+ METHOD_NOT_FOUND = -32601
259
+ INVALID_PARAMS = -32602
260
+ INTERNAL_ERROR = -32603
261
+
262
+ # A2A-specific errors (-32000 to -32099)
263
+ TASK_NOT_FOUND = -32000
264
+ TASK_NOT_CANCELABLE = -32001
265
+ PUSH_NOTIFICATION_NOT_SUPPORTED = -32002
266
+ UNSUPPORTED_OPERATION = -32003
267
+ AUTHENTICATION_REQUIRED = -32004
268
+ PAYMENT_REQUIRED = -32005