devsper 2.1.6__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 (375) hide show
  1. devsper/__init__.py +14 -0
  2. devsper/agents/a2a/__init__.py +27 -0
  3. devsper/agents/a2a/client.py +126 -0
  4. devsper/agents/a2a/discovery.py +24 -0
  5. devsper/agents/a2a/server.py +128 -0
  6. devsper/agents/a2a/tool_adapter.py +68 -0
  7. devsper/agents/a2a/types.py +49 -0
  8. devsper/agents/agent.py +602 -0
  9. devsper/agents/critic.py +80 -0
  10. devsper/agents/message_bus.py +124 -0
  11. devsper/agents/roles.py +181 -0
  12. devsper/agents/run_agent.py +78 -0
  13. devsper/analytics/__init__.py +5 -0
  14. devsper/analytics/tool_analytics.py +78 -0
  15. devsper/audit/__init__.py +5 -0
  16. devsper/audit/logger.py +214 -0
  17. devsper/bus/__init__.py +29 -0
  18. devsper/bus/backends/__init__.py +5 -0
  19. devsper/bus/backends/base.py +38 -0
  20. devsper/bus/backends/memory.py +55 -0
  21. devsper/bus/backends/redis.py +146 -0
  22. devsper/bus/message.py +56 -0
  23. devsper/bus/schema_version.py +3 -0
  24. devsper/bus/topics.py +19 -0
  25. devsper/cache/__init__.py +6 -0
  26. devsper/cache/embedding_index.py +98 -0
  27. devsper/cache/hashing.py +24 -0
  28. devsper/cache/store.py +153 -0
  29. devsper/cache/task_cache.py +191 -0
  30. devsper/cli/__init__.py +6 -0
  31. devsper/cli/commands/reg.py +733 -0
  32. devsper/cli/github_oauth.py +157 -0
  33. devsper/cli/init.py +637 -0
  34. devsper/cli/main.py +2956 -0
  35. devsper/cli/run_progress.py +103 -0
  36. devsper/cli/ui/__init__.py +65 -0
  37. devsper/cli/ui/components.py +94 -0
  38. devsper/cli/ui/errors.py +104 -0
  39. devsper/cli/ui/logging.py +120 -0
  40. devsper/cli/ui/onboarding.py +102 -0
  41. devsper/cli/ui/progress.py +43 -0
  42. devsper/cli/ui/run_view.py +308 -0
  43. devsper/cli/ui/theme.py +40 -0
  44. devsper/cluster/__init__.py +29 -0
  45. devsper/cluster/election.py +84 -0
  46. devsper/cluster/local.py +97 -0
  47. devsper/cluster/node_info.py +77 -0
  48. devsper/cluster/registry.py +71 -0
  49. devsper/cluster/router.py +117 -0
  50. devsper/cluster/state_backend.py +105 -0
  51. devsper/compliance/__init__.py +5 -0
  52. devsper/compliance/pii.py +147 -0
  53. devsper/config/__init__.py +52 -0
  54. devsper/config/config_loader.py +121 -0
  55. devsper/config/defaults.py +77 -0
  56. devsper/config/resolver.py +342 -0
  57. devsper/config/schema.py +237 -0
  58. devsper/credentials/__init__.py +19 -0
  59. devsper/credentials/cli.py +197 -0
  60. devsper/credentials/migration.py +124 -0
  61. devsper/credentials/store.py +142 -0
  62. devsper/dashboard/__init__.py +9 -0
  63. devsper/dashboard/dashboard.py +87 -0
  64. devsper/dev/__init__.py +25 -0
  65. devsper/dev/builder.py +195 -0
  66. devsper/dev/debugger.py +95 -0
  67. devsper/dev/repo_index.py +138 -0
  68. devsper/dev/sandbox.py +203 -0
  69. devsper/dev/scaffold.py +122 -0
  70. devsper/embeddings/__init__.py +5 -0
  71. devsper/embeddings/service.py +36 -0
  72. devsper/explainability/__init__.py +14 -0
  73. devsper/explainability/decision_tree.py +104 -0
  74. devsper/explainability/rationale.py +38 -0
  75. devsper/explainability/simulation.py +56 -0
  76. devsper/hitl/__init__.py +13 -0
  77. devsper/hitl/approval.py +160 -0
  78. devsper/hitl/escalation.py +95 -0
  79. devsper/intelligence/__init__.py +9 -0
  80. devsper/intelligence/adaptation.py +88 -0
  81. devsper/intelligence/analysis/__init__.py +19 -0
  82. devsper/intelligence/analysis/analyzer.py +71 -0
  83. devsper/intelligence/analysis/cost_estimator.py +66 -0
  84. devsper/intelligence/analysis/formatter.py +103 -0
  85. devsper/intelligence/analysis/run_report.py +402 -0
  86. devsper/intelligence/learning_engine.py +92 -0
  87. devsper/intelligence/strategies/__init__.py +23 -0
  88. devsper/intelligence/strategies/base.py +14 -0
  89. devsper/intelligence/strategies/code_analysis_strategy.py +33 -0
  90. devsper/intelligence/strategies/data_science_strategy.py +33 -0
  91. devsper/intelligence/strategies/document_pipeline_strategy.py +33 -0
  92. devsper/intelligence/strategies/experiment_strategy.py +33 -0
  93. devsper/intelligence/strategies/research_strategy.py +34 -0
  94. devsper/intelligence/strategy_selector.py +84 -0
  95. devsper/intelligence/synthesis.py +132 -0
  96. devsper/intelligence/task_optimizer.py +92 -0
  97. devsper/knowledge/__init__.py +5 -0
  98. devsper/knowledge/extractor.py +204 -0
  99. devsper/knowledge/knowledge_graph.py +184 -0
  100. devsper/knowledge/query.py +285 -0
  101. devsper/memory/__init__.py +35 -0
  102. devsper/memory/consolidation.py +138 -0
  103. devsper/memory/embeddings.py +60 -0
  104. devsper/memory/memory_index.py +97 -0
  105. devsper/memory/memory_router.py +62 -0
  106. devsper/memory/memory_store.py +221 -0
  107. devsper/memory/memory_types.py +54 -0
  108. devsper/memory/namespaces.py +45 -0
  109. devsper/memory/scoring.py +77 -0
  110. devsper/memory/summarizer.py +52 -0
  111. devsper/nodes/__init__.py +5 -0
  112. devsper/nodes/controller.py +449 -0
  113. devsper/nodes/rpc.py +127 -0
  114. devsper/nodes/single.py +161 -0
  115. devsper/nodes/worker.py +506 -0
  116. devsper/orchestration/__init__.py +19 -0
  117. devsper/orchestration/meta_planner.py +239 -0
  118. devsper/orchestration/priority_queue.py +61 -0
  119. devsper/plugins/__init__.py +19 -0
  120. devsper/plugins/marketplace/__init__.py +0 -0
  121. devsper/plugins/plugin_loader.py +70 -0
  122. devsper/plugins/plugin_registry.py +34 -0
  123. devsper/plugins/registry.py +83 -0
  124. devsper/protocols/__init__.py +6 -0
  125. devsper/providers/__init__.py +17 -0
  126. devsper/providers/anthropic.py +84 -0
  127. devsper/providers/base.py +75 -0
  128. devsper/providers/complexity_router.py +94 -0
  129. devsper/providers/gemini.py +36 -0
  130. devsper/providers/github.py +180 -0
  131. devsper/providers/model_router.py +40 -0
  132. devsper/providers/openai.py +105 -0
  133. devsper/providers/router/__init__.py +21 -0
  134. devsper/providers/router/backends/__init__.py +19 -0
  135. devsper/providers/router/backends/anthropic_backend.py +111 -0
  136. devsper/providers/router/backends/custom_backend.py +138 -0
  137. devsper/providers/router/backends/gemini_backend.py +89 -0
  138. devsper/providers/router/backends/github_backend.py +165 -0
  139. devsper/providers/router/backends/ollama_backend.py +104 -0
  140. devsper/providers/router/backends/openai_backend.py +142 -0
  141. devsper/providers/router/backends/vllm_backend.py +35 -0
  142. devsper/providers/router/base.py +60 -0
  143. devsper/providers/router/factory.py +92 -0
  144. devsper/providers/router/legacy.py +101 -0
  145. devsper/providers/router/router.py +135 -0
  146. devsper/reasoning/__init__.py +12 -0
  147. devsper/reasoning/graph.py +59 -0
  148. devsper/reasoning/nodes.py +20 -0
  149. devsper/reasoning/store.py +67 -0
  150. devsper/runtime/__init__.py +12 -0
  151. devsper/runtime/health.py +88 -0
  152. devsper/runtime/replay.py +53 -0
  153. devsper/runtime/replay_engine.py +142 -0
  154. devsper/runtime/run_history.py +204 -0
  155. devsper/runtime/telemetry.py +116 -0
  156. devsper/runtime/visualize.py +58 -0
  157. devsper/sandbox/__init__.py +13 -0
  158. devsper/sandbox/sandbox.py +161 -0
  159. devsper/swarm/checkpointer.py +65 -0
  160. devsper/swarm/executor.py +558 -0
  161. devsper/swarm/map_reduce.py +44 -0
  162. devsper/swarm/planner.py +197 -0
  163. devsper/swarm/prefetcher.py +91 -0
  164. devsper/swarm/scheduler.py +153 -0
  165. devsper/swarm/speculation.py +47 -0
  166. devsper/swarm/swarm.py +562 -0
  167. devsper/tools/__init__.py +33 -0
  168. devsper/tools/base.py +29 -0
  169. devsper/tools/code_intelligence/__init__.py +13 -0
  170. devsper/tools/code_intelligence/api_surface_extractor.py +73 -0
  171. devsper/tools/code_intelligence/architecture_analyzer.py +65 -0
  172. devsper/tools/code_intelligence/codebase_indexer.py +71 -0
  173. devsper/tools/code_intelligence/dependency_graph_builder.py +67 -0
  174. devsper/tools/code_intelligence/design_pattern_detector.py +62 -0
  175. devsper/tools/code_intelligence/large_function_detector.py +68 -0
  176. devsper/tools/code_intelligence/module_responsibility_mapper.py +56 -0
  177. devsper/tools/code_intelligence/parallel_codebase_analysis.py +44 -0
  178. devsper/tools/code_intelligence/refactor_candidate_detector.py +81 -0
  179. devsper/tools/code_intelligence/repository_semantic_index.py +61 -0
  180. devsper/tools/code_intelligence/test_coverage_estimator.py +62 -0
  181. devsper/tools/coding/__init__.py +12 -0
  182. devsper/tools/coding/analyze_code_complexity.py +48 -0
  183. devsper/tools/coding/dependency_analyzer.py +42 -0
  184. devsper/tools/coding/extract_functions.py +38 -0
  185. devsper/tools/coding/format_python.py +50 -0
  186. devsper/tools/coding/generate_docstrings.py +40 -0
  187. devsper/tools/coding/generate_unit_tests.py +42 -0
  188. devsper/tools/coding/lint_python.py +51 -0
  189. devsper/tools/coding/refactor_function.py +41 -0
  190. devsper/tools/coding/repo_structure_map.py +54 -0
  191. devsper/tools/coding/run_python.py +53 -0
  192. devsper/tools/data/__init__.py +12 -0
  193. devsper/tools/data/column_type_detection.py +64 -0
  194. devsper/tools/data/csv_summary.py +52 -0
  195. devsper/tools/data/dataframe_filter.py +51 -0
  196. devsper/tools/data/dataframe_groupby.py +47 -0
  197. devsper/tools/data/dataframe_stats.py +38 -0
  198. devsper/tools/data/dataset_sampling.py +55 -0
  199. devsper/tools/data/dataset_schema.py +45 -0
  200. devsper/tools/data/json_pretty_print.py +37 -0
  201. devsper/tools/data/json_query.py +46 -0
  202. devsper/tools/data/missing_value_report.py +47 -0
  203. devsper/tools/data_science/__init__.py +13 -0
  204. devsper/tools/data_science/correlation_heatmap.py +72 -0
  205. devsper/tools/data_science/dataset_bias_detector.py +49 -0
  206. devsper/tools/data_science/dataset_distribution_report.py +64 -0
  207. devsper/tools/data_science/dataset_drift_detector.py +64 -0
  208. devsper/tools/data_science/dataset_outlier_detector.py +65 -0
  209. devsper/tools/data_science/dataset_profile.py +76 -0
  210. devsper/tools/data_science/distributed_dataset_processor.py +54 -0
  211. devsper/tools/data_science/feature_engineering_suggestions.py +69 -0
  212. devsper/tools/data_science/feature_importance_estimator.py +82 -0
  213. devsper/tools/data_science/model_input_validator.py +59 -0
  214. devsper/tools/data_science/time_series_analyzer.py +57 -0
  215. devsper/tools/documents/__init__.py +11 -0
  216. devsper/tools/documents/_docproc.py +56 -0
  217. devsper/tools/documents/document_to_markdown.py +29 -0
  218. devsper/tools/documents/extract_document_images.py +39 -0
  219. devsper/tools/documents/extract_document_text.py +29 -0
  220. devsper/tools/documents/extract_equations.py +36 -0
  221. devsper/tools/documents/extract_tables.py +47 -0
  222. devsper/tools/documents/summarize_document.py +42 -0
  223. devsper/tools/documents/write_latex_document.py +133 -0
  224. devsper/tools/documents/write_markdown_document.py +89 -0
  225. devsper/tools/documents/write_word_document.py +149 -0
  226. devsper/tools/experiments/__init__.py +13 -0
  227. devsper/tools/experiments/bootstrap_estimator.py +54 -0
  228. devsper/tools/experiments/experiment_report_generator.py +50 -0
  229. devsper/tools/experiments/experiment_tracker.py +36 -0
  230. devsper/tools/experiments/grid_search_runner.py +50 -0
  231. devsper/tools/experiments/model_benchmark_runner.py +45 -0
  232. devsper/tools/experiments/monte_carlo_experiment.py +38 -0
  233. devsper/tools/experiments/parameter_sweep_runner.py +51 -0
  234. devsper/tools/experiments/result_comparator.py +58 -0
  235. devsper/tools/experiments/simulation_runner.py +43 -0
  236. devsper/tools/experiments/statistical_significance_test.py +56 -0
  237. devsper/tools/experiments/swarm_map_reduce.py +42 -0
  238. devsper/tools/filesystem/__init__.py +12 -0
  239. devsper/tools/filesystem/append_file.py +42 -0
  240. devsper/tools/filesystem/file_hash.py +40 -0
  241. devsper/tools/filesystem/file_line_count.py +36 -0
  242. devsper/tools/filesystem/file_metadata.py +38 -0
  243. devsper/tools/filesystem/file_preview.py +55 -0
  244. devsper/tools/filesystem/find_large_files.py +50 -0
  245. devsper/tools/filesystem/list_directory.py +39 -0
  246. devsper/tools/filesystem/read_file.py +35 -0
  247. devsper/tools/filesystem/search_files.py +60 -0
  248. devsper/tools/filesystem/write_file.py +41 -0
  249. devsper/tools/flagship/__init__.py +15 -0
  250. devsper/tools/flagship/distributed_document_analysis.py +77 -0
  251. devsper/tools/flagship/docproc_corpus_pipeline.py +91 -0
  252. devsper/tools/flagship/repository_semantic_map.py +99 -0
  253. devsper/tools/flagship/research_graph_builder.py +111 -0
  254. devsper/tools/flagship/swarm_experiment_runner.py +86 -0
  255. devsper/tools/knowledge/__init__.py +10 -0
  256. devsper/tools/knowledge/citation_graph_builder.py +69 -0
  257. devsper/tools/knowledge/concept_frequency_analyzer.py +74 -0
  258. devsper/tools/knowledge/corpus_builder.py +66 -0
  259. devsper/tools/knowledge/cross_document_entity_linker.py +71 -0
  260. devsper/tools/knowledge/document_corpus_summary.py +68 -0
  261. devsper/tools/knowledge/document_topic_extractor.py +58 -0
  262. devsper/tools/knowledge/knowledge_graph_extractor.py +58 -0
  263. devsper/tools/knowledge/timeline_extractor.py +59 -0
  264. devsper/tools/math/__init__.py +12 -0
  265. devsper/tools/math/calculate_expression.py +52 -0
  266. devsper/tools/math/correlation.py +44 -0
  267. devsper/tools/math/distribution_summary.py +39 -0
  268. devsper/tools/math/histogram.py +53 -0
  269. devsper/tools/math/linear_regression.py +47 -0
  270. devsper/tools/math/matrix_multiply.py +38 -0
  271. devsper/tools/math/mean_std.py +35 -0
  272. devsper/tools/math/monte_carlo_simulation.py +43 -0
  273. devsper/tools/math/polynomial_fit.py +40 -0
  274. devsper/tools/math/random_sample.py +36 -0
  275. devsper/tools/mcp/__init__.py +23 -0
  276. devsper/tools/mcp/adapter.py +53 -0
  277. devsper/tools/mcp/client.py +235 -0
  278. devsper/tools/mcp/discovery.py +53 -0
  279. devsper/tools/memory/__init__.py +16 -0
  280. devsper/tools/memory/delete_memory.py +25 -0
  281. devsper/tools/memory/list_memory.py +34 -0
  282. devsper/tools/memory/search_memory.py +36 -0
  283. devsper/tools/memory/store_memory.py +47 -0
  284. devsper/tools/memory/summarize_memory.py +41 -0
  285. devsper/tools/memory/tag_memory.py +47 -0
  286. devsper/tools/pipelines.py +92 -0
  287. devsper/tools/registry.py +39 -0
  288. devsper/tools/research/__init__.py +12 -0
  289. devsper/tools/research/arxiv_download.py +55 -0
  290. devsper/tools/research/arxiv_search.py +58 -0
  291. devsper/tools/research/citation_extractor.py +35 -0
  292. devsper/tools/research/duckduckgo_search.py +42 -0
  293. devsper/tools/research/paper_metadata_extractor.py +45 -0
  294. devsper/tools/research/paper_summarizer.py +41 -0
  295. devsper/tools/research/research_question_generator.py +39 -0
  296. devsper/tools/research/topic_cluster.py +46 -0
  297. devsper/tools/research/web_search.py +47 -0
  298. devsper/tools/research/wikipedia_lookup.py +50 -0
  299. devsper/tools/research_advanced/__init__.py +14 -0
  300. devsper/tools/research_advanced/citation_context_extractor.py +60 -0
  301. devsper/tools/research_advanced/literature_review_generator.py +79 -0
  302. devsper/tools/research_advanced/methodology_extractor.py +58 -0
  303. devsper/tools/research_advanced/paper_contribution_extractor.py +50 -0
  304. devsper/tools/research_advanced/paper_dataset_identifier.py +49 -0
  305. devsper/tools/research_advanced/paper_method_comparator.py +62 -0
  306. devsper/tools/research_advanced/paper_similarity_search.py +69 -0
  307. devsper/tools/research_advanced/paper_trend_analyzer.py +69 -0
  308. devsper/tools/research_advanced/parallel_document_analyzer.py +56 -0
  309. devsper/tools/research_advanced/research_gap_finder.py +71 -0
  310. devsper/tools/research_advanced/research_topic_mapper.py +69 -0
  311. devsper/tools/research_advanced/swarm_literature_review.py +58 -0
  312. devsper/tools/scoring/__init__.py +52 -0
  313. devsper/tools/scoring/report.py +44 -0
  314. devsper/tools/scoring/scorer.py +39 -0
  315. devsper/tools/scoring/selector.py +61 -0
  316. devsper/tools/scoring/store.py +267 -0
  317. devsper/tools/selector.py +130 -0
  318. devsper/tools/system/__init__.py +12 -0
  319. devsper/tools/system/cpu_usage.py +22 -0
  320. devsper/tools/system/disk_usage.py +35 -0
  321. devsper/tools/system/environment_variables.py +29 -0
  322. devsper/tools/system/memory_usage.py +23 -0
  323. devsper/tools/system/pip_install.py +44 -0
  324. devsper/tools/system/pip_search.py +29 -0
  325. devsper/tools/system/process_list.py +34 -0
  326. devsper/tools/system/python_package_list.py +40 -0
  327. devsper/tools/system/run_shell_command.py +51 -0
  328. devsper/tools/system/system_info.py +26 -0
  329. devsper/tools/tool_runner.py +122 -0
  330. devsper/tui/__init__.py +5 -0
  331. devsper/tui/activity_feed_view.py +73 -0
  332. devsper/tui/adaptive_tasks_view.py +75 -0
  333. devsper/tui/agent_role_view.py +35 -0
  334. devsper/tui/app.py +395 -0
  335. devsper/tui/dashboard_screen.py +290 -0
  336. devsper/tui/dev_view.py +99 -0
  337. devsper/tui/inject_screen.py +73 -0
  338. devsper/tui/knowledge_graph_view.py +46 -0
  339. devsper/tui/layout.py +43 -0
  340. devsper/tui/logs_view.py +83 -0
  341. devsper/tui/memory_view.py +58 -0
  342. devsper/tui/performance_view.py +33 -0
  343. devsper/tui/reasoning_graph_view.py +39 -0
  344. devsper/tui/results_view.py +139 -0
  345. devsper/tui/swarm_view.py +37 -0
  346. devsper/tui/task_detail_screen.py +55 -0
  347. devsper/tui/task_view.py +103 -0
  348. devsper/types/event.py +97 -0
  349. devsper/types/exceptions.py +21 -0
  350. devsper/types/swarm.py +41 -0
  351. devsper/types/task.py +80 -0
  352. devsper/upgrade/__init__.py +21 -0
  353. devsper/upgrade/changelog.py +124 -0
  354. devsper/upgrade/cli.py +145 -0
  355. devsper/upgrade/installer.py +103 -0
  356. devsper/upgrade/notifier.py +52 -0
  357. devsper/upgrade/version_check.py +121 -0
  358. devsper/utils/event_logger.py +88 -0
  359. devsper/utils/http.py +43 -0
  360. devsper/utils/models.py +54 -0
  361. devsper/visualization/__init__.py +5 -0
  362. devsper/visualization/dag_export.py +67 -0
  363. devsper/workflow/__init__.py +18 -0
  364. devsper/workflow/conditions.py +157 -0
  365. devsper/workflow/context.py +108 -0
  366. devsper/workflow/loader.py +156 -0
  367. devsper/workflow/resolver.py +109 -0
  368. devsper/workflow/runner.py +562 -0
  369. devsper/workflow/schema.py +63 -0
  370. devsper/workflow/validator.py +128 -0
  371. devsper-2.1.6.dist-info/METADATA +346 -0
  372. devsper-2.1.6.dist-info/RECORD +375 -0
  373. devsper-2.1.6.dist-info/WHEEL +4 -0
  374. devsper-2.1.6.dist-info/entry_points.txt +3 -0
  375. devsper-2.1.6.dist-info/licenses/LICENSE +639 -0
devsper/__init__.py ADDED
@@ -0,0 +1,14 @@
1
+ """
2
+ devsper: distributed AI swarm runtime.
3
+
4
+ Example:
5
+ from devsper import Swarm
6
+
7
+ swarm = Swarm(config="devsper.toml")
8
+ result = swarm.run("analyze diffusion models")
9
+ """
10
+
11
+ from devsper.config import get_config
12
+ from devsper.swarm.swarm import Swarm
13
+
14
+ __all__ = ["Swarm", "get_config"]
@@ -0,0 +1,27 @@
1
+ """
2
+ A2A (Agent-to-Agent) integration: client, server, tool adapter.
3
+ """
4
+
5
+ from devsper.agents.a2a.types import (
6
+ AgentCard,
7
+ AgentSkill,
8
+ A2ATaskRequest,
9
+ A2ATaskResponse,
10
+ )
11
+ from devsper.agents.a2a.client import A2AClient
12
+ from devsper.agents.a2a.server import create_a2a_app, run_a2a_server
13
+ from devsper.agents.a2a.tool_adapter import A2AAgentTool
14
+
15
+ # Alias for task spec: "A2AServer" = run_a2a_server / create_a2a_app
16
+ A2AServer = create_a2a_app
17
+
18
+ __all__ = [
19
+ "A2AClient",
20
+ "A2AServer",
21
+ "AgentCard",
22
+ "A2ATaskRequest",
23
+ "A2ATaskResponse",
24
+ "A2AAgentTool",
25
+ "create_a2a_app",
26
+ "run_a2a_server",
27
+ ]
@@ -0,0 +1,126 @@
1
+ """
2
+ A2A client: call external A2A-compliant agents (get AgentCard, send_task, stream_task).
3
+ """
4
+
5
+ import uuid
6
+ from typing import AsyncIterator
7
+
8
+ from devsper.agents.a2a.types import (
9
+ AgentCard,
10
+ AgentSkill,
11
+ A2ATaskRequest,
12
+ A2ATaskResponse,
13
+ )
14
+
15
+
16
+ def _parse_agent_card(data: dict) -> AgentCard:
17
+ """Build AgentCard from JSON response."""
18
+ skills_data = data.get("skills") or []
19
+ skills = [
20
+ AgentSkill(
21
+ id=s.get("id", ""),
22
+ name=s.get("name", ""),
23
+ description=s.get("description", ""),
24
+ input_modes=list(s.get("inputModes") or []),
25
+ output_modes=list(s.get("outputModes") or []),
26
+ )
27
+ for s in skills_data
28
+ if isinstance(s, dict)
29
+ ]
30
+ return AgentCard(
31
+ name=data.get("name", ""),
32
+ description=data.get("description", ""),
33
+ url=data.get("url", ""),
34
+ version=data.get("version", ""),
35
+ capabilities=list(data.get("capabilities") or []),
36
+ skills=skills,
37
+ authentication=data.get("authentication"),
38
+ )
39
+
40
+
41
+ def _parse_task_response(data: dict) -> A2ATaskResponse:
42
+ """Build A2ATaskResponse from JSON."""
43
+ status = data.get("status", "failed")
44
+ if status not in ("submitted", "working", "completed", "failed", "canceled"):
45
+ status = "failed"
46
+ return A2ATaskResponse(
47
+ id=data.get("id", ""),
48
+ status=status,
49
+ result=data.get("result"),
50
+ artifacts=data.get("artifacts") or [],
51
+ )
52
+
53
+
54
+ class A2AClient:
55
+ """Calls external A2A-compliant agents as if they were local tools."""
56
+
57
+ def __init__(self, timeout_seconds: float = 60.0) -> None:
58
+ self.timeout_seconds = timeout_seconds
59
+
60
+ def _client(self):
61
+ import httpx
62
+ return httpx.AsyncClient(timeout=self.timeout_seconds)
63
+
64
+ async def get_agent_card(self, base_url: str) -> AgentCard:
65
+ """GET {base_url}/.well-known/agent.json"""
66
+ url = base_url.rstrip("/") + "/.well-known/agent.json"
67
+ async with self._client() as client:
68
+ r = await client.get(url)
69
+ r.raise_for_status()
70
+ data = r.json()
71
+ return _parse_agent_card(data)
72
+
73
+ async def send_task(
74
+ self,
75
+ base_url: str,
76
+ request: A2ATaskRequest,
77
+ poll_interval: float = 0.5,
78
+ ) -> A2ATaskResponse:
79
+ """POST {base_url}/tasks/send, then poll GET /tasks/{id} until completed/failed."""
80
+ import asyncio
81
+ url = base_url.rstrip("/") + "/tasks/send"
82
+ body = {
83
+ "id": request.id,
84
+ "message": request.message,
85
+ "sessionId": request.session_id,
86
+ }
87
+ async with self._client() as client:
88
+ r = await client.post(url, json=body)
89
+ r.raise_for_status()
90
+ data = r.json()
91
+ resp = _parse_task_response(data)
92
+ if resp.status in ("completed", "failed", "canceled"):
93
+ return resp
94
+ task_url = base_url.rstrip("/") + f"/tasks/{resp.id}"
95
+ while resp.status in ("submitted", "working"):
96
+ await asyncio.sleep(poll_interval)
97
+ async with self._client() as client:
98
+ r = await client.get(task_url)
99
+ r.raise_for_status()
100
+ data = r.json()
101
+ resp = _parse_task_response(data)
102
+ if resp.status in ("completed", "failed", "canceled"):
103
+ return resp
104
+ return resp
105
+
106
+ async def stream_task(
107
+ self,
108
+ base_url: str,
109
+ request: A2ATaskRequest,
110
+ ) -> AsyncIterator[str]:
111
+ """POST {base_url}/tasks/sendSubscribe, consume SSE stream, yield text chunks."""
112
+ import httpx
113
+ url = base_url.rstrip("/") + "/tasks/sendSubscribe"
114
+ body = {
115
+ "id": request.id,
116
+ "message": request.message,
117
+ "sessionId": request.session_id,
118
+ }
119
+ async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
120
+ async with client.stream("POST", url, json=body) as response:
121
+ response.raise_for_status()
122
+ async for line in response.aiter_lines():
123
+ if line.startswith("data:"):
124
+ data = line[5:].strip()
125
+ if data and data != "[DONE]":
126
+ yield data
@@ -0,0 +1,24 @@
1
+ """
2
+ A2A discovery: fetch AgentCard from URL, register skills as A2AAgentTool.
3
+ """
4
+
5
+ import asyncio
6
+
7
+ from devsper.config.schema import A2AAgentConfig
8
+ from devsper.agents.a2a.client import A2AClient
9
+ from devsper.agents.a2a.tool_adapter import A2AAgentTool
10
+
11
+
12
+ async def discover_a2a_tools_async(agent_config: A2AAgentConfig) -> int:
13
+ """Fetch AgentCard from agent URL, create A2AAgentTool per skill, register. Return count."""
14
+ client = A2AClient()
15
+ card = await client.get_agent_card(agent_config.url)
16
+ name = agent_config.name or card.name or "a2a-agent"
17
+ for skill in card.skills:
18
+ A2AAgentTool(agent_name=name, skill=skill, base_url=agent_config.url, client=client)
19
+ return len(card.skills)
20
+
21
+
22
+ def register_a2a_agent(agent_config: A2AAgentConfig) -> int:
23
+ """Sync: discover and register A2A agent tools; return count."""
24
+ return asyncio.run(discover_a2a_tools_async(agent_config))
@@ -0,0 +1,128 @@
1
+ """
2
+ A2A server: expose devsper agents as A2A-compliant endpoints (FastAPI).
3
+ """
4
+
5
+ from typing import Any
6
+
7
+ from devsper.agents.a2a.types import AgentCard, AgentSkill, A2ATaskRequest, A2ATaskResponse
8
+
9
+
10
+ def _build_agent_card(host: str, port: int, swarm_name: str) -> dict:
11
+ """Build AgentCard JSON for GET /.well-known/agent.json."""
12
+ from devsper.intelligence.strategy_selector import ExecutionStrategy
13
+ url = f"http://{host}:{port}"
14
+ name = swarm_name or "devsper"
15
+ skills = [
16
+ {
17
+ "id": s.value,
18
+ "name": s.value.replace("_", " ").title(),
19
+ "description": f"Execute task using {s.value} strategy.",
20
+ "inputModes": ["text"],
21
+ "outputModes": ["text"],
22
+ }
23
+ for s in ExecutionStrategy
24
+ if s != ExecutionStrategy.GENERAL
25
+ ]
26
+ return {
27
+ "name": name,
28
+ "description": "devsper swarm orchestration as A2A agent.",
29
+ "url": url,
30
+ "version": "1.10.5",
31
+ "capabilities": ["streaming"],
32
+ "skills": skills,
33
+ }
34
+
35
+
36
+ def create_a2a_app(host: str = "localhost", port: int = 8080, swarm_name: str = "") -> Any:
37
+ """Create FastAPI app with A2A routes. Requires fastapi, uvicorn, sse-starlette."""
38
+ from fastapi import FastAPI
39
+ from fastapi.responses import StreamingResponse
40
+ import asyncio
41
+ import uuid
42
+
43
+ app = FastAPI(title="devsper A2A Server")
44
+
45
+ @app.get("/.well-known/agent.json")
46
+ def agent_card() -> dict:
47
+ return _build_agent_card(host, port, swarm_name)
48
+
49
+ @app.post("/tasks/send")
50
+ async def tasks_send(body: dict) -> dict:
51
+ """Accept A2A task, run via Swarm, return result."""
52
+ task_id = body.get("id") or str(uuid.uuid4())
53
+ message = body.get("message") or {}
54
+ text = message.get("text", "") if isinstance(message, dict) else ""
55
+ if not text:
56
+ return {
57
+ "id": task_id,
58
+ "status": "failed",
59
+ "result": "Missing message.text",
60
+ "artifacts": [],
61
+ }
62
+ try:
63
+ from devsper.config import get_config
64
+ from devsper.swarm.swarm import Swarm
65
+ cfg = get_config()
66
+ swarm = Swarm(config=cfg)
67
+ result = swarm.run(text)
68
+ out = "\n".join(f"{k}: {v[:2000]}" for k, v in result.items()) if result else ""
69
+ return {
70
+ "id": task_id,
71
+ "status": "completed",
72
+ "result": out,
73
+ "artifacts": [],
74
+ }
75
+ except Exception as e:
76
+ return {
77
+ "id": task_id,
78
+ "status": "failed",
79
+ "result": str(e),
80
+ "artifacts": [],
81
+ }
82
+
83
+ @app.post("/tasks/sendSubscribe")
84
+ async def tasks_send_subscribe(body: dict):
85
+ """SSE streaming task execution."""
86
+ task_id = body.get("id") or str(uuid.uuid4())
87
+ message = body.get("message") or {}
88
+ text = message.get("text", "") if isinstance(message, dict) else ""
89
+
90
+ async def stream():
91
+ if not text:
92
+ yield f"data: {__import__('json').dumps({'error': 'Missing message.text'})}\n\n"
93
+ return
94
+ try:
95
+ from devsper.config import get_config
96
+ from devsper.swarm.swarm import Swarm
97
+ cfg = get_config()
98
+ swarm = Swarm(config=cfg)
99
+ result = swarm.run(text)
100
+ out = "\n".join(f"{k}: {v[:2000]}" for k, v in result.items()) if result else ""
101
+ yield f"data: {__import__('json').dumps({'id': task_id, 'status': 'completed', 'result': out})}\n\n"
102
+ except Exception as e:
103
+ yield f"data: {__import__('json').dumps({'id': task_id, 'status': 'failed', 'result': str(e)})}\n\n"
104
+
105
+ return StreamingResponse(
106
+ stream(),
107
+ media_type="text/event-stream",
108
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"},
109
+ )
110
+
111
+ @app.get("/tasks/{task_id}")
112
+ def task_status(task_id: str) -> dict:
113
+ """Task status (stub: we don't persist task state for now)."""
114
+ return {"id": task_id, "status": "completed", "result": None, "artifacts": []}
115
+
116
+ @app.post("/tasks/{task_id}/cancel")
117
+ def task_cancel(task_id: str) -> dict:
118
+ """Cancel running task (stub)."""
119
+ return {"id": task_id, "status": "canceled", "result": None, "artifacts": []}
120
+
121
+ return app
122
+
123
+
124
+ def run_a2a_server(host: str = "localhost", port: int = 8080, swarm_name: str = "") -> None:
125
+ """Run A2A server with uvicorn."""
126
+ import uvicorn
127
+ app = create_a2a_app(host=host, port=port, swarm_name=swarm_name)
128
+ uvicorn.run(app, host=host, port=port)
@@ -0,0 +1,68 @@
1
+ """
2
+ A2AAgentTool: wrap an external A2A agent skill as a devsper Tool.
3
+ """
4
+
5
+ import asyncio
6
+ import uuid
7
+
8
+ from devsper.tools.base import Tool
9
+ from devsper.tools.registry import register
10
+
11
+ from devsper.agents.a2a.types import AgentCard, AgentSkill, A2ATaskRequest, A2ATaskResponse
12
+ from devsper.agents.a2a.client import A2AClient
13
+
14
+
15
+ class A2AAgentTool(Tool):
16
+ """
17
+ Wraps an external A2A agent skill as a devsper tool.
18
+ Discovery: fetch AgentCard, create one tool per skill.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ agent_name: str,
24
+ skill: AgentSkill,
25
+ base_url: str,
26
+ client: A2AClient | None = None,
27
+ ) -> None:
28
+ self.name = f"{agent_name}.{skill.id}"
29
+ self.description = skill.description or f"A2A skill: {skill.name}"
30
+ self.category = "a2a"
31
+ self.input_schema = {
32
+ "type": "object",
33
+ "properties": {"task": {"type": "string", "description": "Task or prompt for the agent"}},
34
+ "required": ["task"],
35
+ }
36
+ self._base_url = base_url.rstrip("/")
37
+ self._client = client or A2AClient()
38
+ self._skill_id = skill.id
39
+ register(self)
40
+
41
+ def run(self, task: str = "", **kwargs) -> str:
42
+ """Send task to external A2A agent via send_task."""
43
+ text = task or kwargs.get("task", "")
44
+ if not text:
45
+ return "Error: missing 'task' argument"
46
+ request = A2ATaskRequest(
47
+ id=str(uuid.uuid4()),
48
+ message={"text": text},
49
+ session_id=None,
50
+ )
51
+ try:
52
+ loop = asyncio.get_event_loop()
53
+ except RuntimeError:
54
+ loop = asyncio.new_event_loop()
55
+ asyncio.set_event_loop(loop)
56
+ if loop.is_running():
57
+ import concurrent.futures
58
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
59
+ future = pool.submit(
60
+ asyncio.run,
61
+ self._client.send_task(self._base_url, request),
62
+ )
63
+ resp = future.result()
64
+ else:
65
+ resp = loop.run_until_complete(self._client.send_task(self._base_url, request))
66
+ if resp.status == "completed" and resp.result is not None:
67
+ return resp.result
68
+ return f"Error: status={resp.status}, result={resp.result}"
@@ -0,0 +1,49 @@
1
+ """
2
+ A2A (Agent-to-Agent) protocol types — AgentCard, TaskRequest/Response, etc.
3
+ """
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Literal
7
+
8
+
9
+ @dataclass
10
+ class AgentSkill:
11
+ """One skill exposed by an A2A agent."""
12
+ id: str
13
+ name: str
14
+ description: str
15
+ input_modes: list[str] # e.g. ["text", "file"]
16
+ output_modes: list[str]
17
+
18
+
19
+ @dataclass
20
+ class AgentCard:
21
+ """A2A agent descriptor — follows A2A spec."""
22
+ name: str
23
+ description: str
24
+ url: str # this agent's A2A endpoint
25
+ version: str
26
+ capabilities: list[str] # e.g. ["streaming", "pushNotifications"]
27
+ skills: list[AgentSkill]
28
+ authentication: dict | None = None
29
+
30
+
31
+ @dataclass
32
+ class A2ATaskRequest:
33
+ """A2A task send request."""
34
+ id: str # uuid4
35
+ message: dict # A2A Message object
36
+ session_id: str | None = None
37
+
38
+
39
+ @dataclass
40
+ class A2ATaskResponse:
41
+ """A2A task response."""
42
+ id: str
43
+ status: Literal["submitted", "working", "completed", "failed", "canceled"]
44
+ result: str | None = None
45
+ artifacts: list[dict] | None = None
46
+
47
+ def __post_init__(self) -> None:
48
+ if self.artifacts is None:
49
+ self.artifacts = []