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
@@ -0,0 +1,51 @@
1
+ """Run a shell command and return stdout/stderr."""
2
+
3
+ import subprocess
4
+ import shlex
5
+
6
+ from devsper.tools.base import Tool
7
+ from devsper.tools.registry import register
8
+
9
+
10
+ class RunShellCommandTool(Tool):
11
+ """Execute a shell command and return combined stdout and stderr."""
12
+
13
+ name = "run_shell_command"
14
+ description = "Run a shell command. Returns stdout and stderr. Timeout 60s."
15
+ input_schema = {
16
+ "type": "object",
17
+ "properties": {
18
+ "command": {"type": "string", "description": "Shell command to run"},
19
+ "timeout_seconds": {"type": "integer", "description": "Timeout in seconds (default 60)"},
20
+ },
21
+ "required": ["command"],
22
+ }
23
+
24
+ def run(self, **kwargs) -> str:
25
+ command = kwargs.get("command")
26
+ timeout = kwargs.get("timeout_seconds", 60)
27
+ if not command or not isinstance(command, str):
28
+ return "Error: command must be a non-empty string"
29
+ if not isinstance(timeout, int) or timeout < 1:
30
+ timeout = 60
31
+ try:
32
+ result = subprocess.run(
33
+ shlex.split(command) if isinstance(command, str) else [command],
34
+ capture_output=True,
35
+ text=True,
36
+ timeout=timeout,
37
+ )
38
+ out = result.stdout or ""
39
+ err = result.stderr or ""
40
+ if err:
41
+ out = out + "\n--- stderr ---\n" + err
42
+ if result.returncode != 0:
43
+ out = f"[exit {result.returncode}]\n" + out
44
+ return out.strip() or "(no output)"
45
+ except subprocess.TimeoutExpired:
46
+ return f"Error: command timed out after {timeout}s"
47
+ except Exception as e:
48
+ return f"Error: {e}"
49
+
50
+
51
+ register(RunShellCommandTool())
@@ -0,0 +1,26 @@
1
+ """Return basic system information."""
2
+
3
+ import platform
4
+ import sys
5
+
6
+ from devsper.tools.base import Tool
7
+ from devsper.tools.registry import register
8
+
9
+
10
+ class SystemInfoTool(Tool):
11
+ """Return system info: OS, machine, Python version."""
12
+
13
+ name = "system_info"
14
+ description = "Get system information: OS, machine, Python version."
15
+ input_schema = {"type": "object", "properties": {}, "required": []}
16
+
17
+ def run(self, **kwargs) -> str:
18
+ return (
19
+ f"system = {platform.system()}\n"
20
+ f"machine = {platform.machine()}\n"
21
+ f"processor = {platform.processor() or 'N/A'}\n"
22
+ f"python = {sys.version}"
23
+ )
24
+
25
+
26
+ register(SystemInfoTool())
@@ -0,0 +1,122 @@
1
+ """
2
+ Tool runner: execute a tool by name with validated arguments and safe error handling.
3
+ """
4
+
5
+ import time
6
+
7
+ from devsper.tools.registry import get_with_mcp_fallback
8
+
9
+
10
+ def _validate_args(args: dict, schema: dict) -> str | None:
11
+ """
12
+ Validate args against JSON Schema-style input_schema.
13
+ Returns None if valid, or an error message string if invalid.
14
+ """
15
+ if not isinstance(args, dict):
16
+ return "args must be a dict"
17
+ required = schema.get("required", [])
18
+ properties = schema.get("properties", {})
19
+ for key in required:
20
+ if key not in args:
21
+ return f"Missing required argument: {key}"
22
+ for key, value in args.items():
23
+ if key not in properties:
24
+ continue
25
+ prop = properties[key]
26
+ expected_type = prop.get("type")
27
+ if expected_type == "string" and not isinstance(value, str):
28
+ return f"Argument '{key}' must be a string"
29
+ if expected_type == "number" and not isinstance(value, (int, float)):
30
+ return f"Argument '{key}' must be a number"
31
+ if expected_type == "integer" and not isinstance(value, int):
32
+ return f"Argument '{key}' must be an integer"
33
+ if expected_type == "boolean" and not isinstance(value, bool):
34
+ return f"Argument '{key}' must be a boolean"
35
+ if expected_type == "array" and not isinstance(value, list):
36
+ return f"Argument '{key}' must be an array"
37
+ if expected_type == "object" and not isinstance(value, dict):
38
+ return f"Argument '{key}' must be an object"
39
+ return None
40
+
41
+
42
+ def run_tool(
43
+ name: str,
44
+ args: dict,
45
+ task_type: str | None = None,
46
+ ) -> str:
47
+ """
48
+ Execute the tool by name with the given arguments.
49
+
50
+ Validates args against the tool's input_schema, runs the tool, and returns
51
+ its string output. On validation failure or exception, returns a formatted error string.
52
+ Records usage to tool analytics and tool scoring when available.
53
+ """
54
+ start = time.perf_counter()
55
+ tool = get_with_mcp_fallback(name)
56
+ if tool is None:
57
+ _record_analytics(name, False, start)
58
+ _record_scoring(name, task_type, False, start, error_type="ToolNotFound")
59
+ return f"Tool not found: {name}"
60
+ resolved_name = tool.name
61
+ err = _validate_args(args, tool.input_schema)
62
+ if err is not None:
63
+ _record_analytics(resolved_name, False, start)
64
+ _record_scoring(resolved_name, task_type, False, start, error_type="ValidationError")
65
+ return f"Validation error: {err}"
66
+ try:
67
+ result = tool.run(**args)
68
+ latency_ms = int((time.monotonic() - start) * 1000)
69
+ success = not (isinstance(result, str) and result.startswith("Tool error:"))
70
+ _record_analytics(resolved_name, success, start)
71
+ _record_scoring(resolved_name, task_type, success, start, latency_ms=latency_ms)
72
+ return result
73
+ except Exception as e:
74
+ latency_ms = int((time.monotonic() - start) * 1000)
75
+ _record_analytics(resolved_name, False, start)
76
+ _record_scoring(
77
+ resolved_name,
78
+ task_type,
79
+ False,
80
+ start,
81
+ latency_ms=latency_ms,
82
+ error_type=type(e).__name__,
83
+ )
84
+ return f"Tool error: {type(e).__name__}: {e}"
85
+
86
+
87
+ def _record_analytics(tool_name: str, success: bool, start_time: float) -> None:
88
+ """Record tool invocation to analytics if available."""
89
+ try:
90
+ from devsper.analytics import get_default_analytics
91
+
92
+ latency_ms = (time.perf_counter() - start_time) * 1000
93
+ get_default_analytics().record(tool_name, success, latency_ms)
94
+ except Exception:
95
+ pass
96
+
97
+
98
+ def _record_scoring(
99
+ tool_name: str,
100
+ task_type: str | None,
101
+ success: bool,
102
+ start_time: float,
103
+ latency_ms: int | None = None,
104
+ error_type: str | None = None,
105
+ ) -> None:
106
+ """Record tool result to scoring store if available."""
107
+ try:
108
+ from devsper.tools.scoring import record_tool_result
109
+ except Exception:
110
+ return
111
+ if latency_ms is None:
112
+ latency_ms = int((time.perf_counter() - start_time) * 1000)
113
+ try:
114
+ record_tool_result(
115
+ tool_name,
116
+ task_type or "general",
117
+ success=success,
118
+ latency_ms=latency_ms,
119
+ error_type=error_type,
120
+ )
121
+ except Exception:
122
+ pass
@@ -0,0 +1,5 @@
1
+ """Terminal UI for devsper swarm runtime."""
2
+
3
+ from devsper.tui.app import devsperTUI
4
+
5
+ __all__ = ["devsperTUI"]
@@ -0,0 +1,73 @@
1
+ """
2
+ Agent activity feed: chronological feed of agent actions (task started/ended, tool calls).
3
+ Reads from EventLog when log path is set.
4
+ """
5
+
6
+ from textual.widgets import Static
7
+
8
+
9
+ class ActivityFeedView(Static):
10
+ """Shows recent events: TASK_STARTED, TASK_COMPLETED, TOOL_CALLED, etc."""
11
+
12
+ def __init__(self, *args, **kwargs) -> None:
13
+ super().__init__(*args, **kwargs)
14
+ self._events_folder: str = ".devsper/events"
15
+ self._log_path: str | None = None
16
+ self._lines: list[str] = []
17
+
18
+ def set_events_folder(self, folder: str) -> None:
19
+ self._events_folder = folder
20
+
21
+ def set_log_path(self, path: str | None) -> None:
22
+ self._log_path = path
23
+
24
+ def refresh_events(self, limit: int = 50) -> None:
25
+ """Load recent events from the event log and display as feed."""
26
+ self._lines = []
27
+ try:
28
+ from pathlib import Path
29
+ import json
30
+
31
+ path = self._log_path
32
+ if not path and self._events_folder:
33
+ folder = Path(self._events_folder)
34
+ if folder.is_dir():
35
+ files = sorted(folder.glob("*.jsonl"), key=lambda p: p.stat().st_mtime, reverse=True)
36
+ path = str(files[0]) if files else None
37
+ if not path or not Path(path).is_file():
38
+ self._lines = ["(no event log)\nRun swarm to see activity."]
39
+ self.update("\n".join(self._lines))
40
+ return
41
+ with open(path) as f:
42
+ raw_lines = f.readlines()
43
+ for line in raw_lines[-limit:]:
44
+ line = line.strip()
45
+ if not line:
46
+ continue
47
+ try:
48
+ obj = json.loads(line)
49
+ ev = obj.get("type", "?")
50
+ payload = obj.get("payload", {})
51
+ task_id = payload.get("task_id", "")
52
+ tool = payload.get("tool", "")
53
+ if ev == "task_started":
54
+ self._lines.append(f"[dim]▶ task {task_id}[/dim]")
55
+ elif ev == "task_completed":
56
+ self._lines.append(f"[dim]✔ task {task_id}[/dim]")
57
+ elif ev == "tool_called":
58
+ self._lines.append(f"[dim]🔧 {tool} (task {task_id})[/dim]")
59
+ elif ev == "user_injection":
60
+ msg = (payload.get("message") or "")[:60]
61
+ if len(payload.get("message") or "") > 60:
62
+ msg += "…"
63
+ self._lines.append(f"📌 [bold]User injected:[/] [dim]{msg}[/]")
64
+ else:
65
+ self._lines.append(f"[dim]{ev}[/dim]")
66
+ except Exception:
67
+ self._lines.append(line[:80])
68
+ except Exception as e:
69
+ self._lines = [f"(error: {e})"]
70
+ self.update("\n".join(self._lines[-limit:]))
71
+
72
+ def on_mount(self) -> None:
73
+ self.update("(activity feed)\n\nRun swarm to see events.")
@@ -0,0 +1,75 @@
1
+ """
2
+ Adaptive task creation: show when alternative tasks were injected (e.g. after failure).
3
+ """
4
+
5
+ from textual.widgets import Static
6
+
7
+
8
+ class AdaptiveTasksView(Static):
9
+ """Shows adaptive events: failed tasks and newly created alternative tasks."""
10
+
11
+ def __init__(self, *args, **kwargs) -> None:
12
+ super().__init__(*args, **kwargs)
13
+ self._events_folder: str = ".devsper/events"
14
+ self._log_path: str | None = None
15
+
16
+ def set_events_folder(self, folder: str) -> None:
17
+ self._events_folder = folder
18
+
19
+ def set_log_path(self, path: str | None) -> None:
20
+ self._log_path = path
21
+
22
+ def refresh_adaptive_events(self, limit: int = 20) -> None:
23
+ """Load task_failed and subsequent task_created from event log."""
24
+ lines = ["(Adaptive task creation)", ""]
25
+ try:
26
+ from pathlib import Path
27
+ import json
28
+
29
+ path = self._log_path
30
+ if not path and self._events_folder:
31
+ folder = Path(self._events_folder)
32
+ if folder.is_dir():
33
+ files = sorted(
34
+ folder.glob("*.jsonl"),
35
+ key=lambda p: p.stat().st_mtime,
36
+ reverse=True,
37
+ )
38
+ path = str(files[0]) if files else None
39
+ if not path or not Path(path).is_file():
40
+ self.update("(Adaptive tasks)\n\nNo event log.\nRun with adaptive_execution=true to see alternatives.")
41
+ return
42
+ with open(path) as f:
43
+ raw = f.readlines()
44
+ failed_ids = set()
45
+ created_after_fail = []
46
+ for line in raw:
47
+ line = line.strip()
48
+ if not line:
49
+ continue
50
+ try:
51
+ obj = json.loads(line)
52
+ ev = obj.get("type", "?")
53
+ payload = obj.get("payload", {})
54
+ if ev == "task_failed":
55
+ failed_ids.add(payload.get("task_id", ""))
56
+ if ev == "task_created" and failed_ids:
57
+ created_after_fail.append(
58
+ (payload.get("task_id", ""), payload.get("description", "")[:60])
59
+ )
60
+ except Exception:
61
+ pass
62
+ if failed_ids:
63
+ lines.append("Failed tasks:")
64
+ for tid in list(failed_ids)[:5]:
65
+ lines.append(f" • {tid}")
66
+ lines.append("")
67
+ if created_after_fail:
68
+ lines.append("New tasks (after failure):")
69
+ for tid, desc in created_after_fail[-limit:]:
70
+ lines.append(f" • {tid}: {desc}")
71
+ elif not failed_ids:
72
+ lines.append("No adaptive events in this run.")
73
+ except Exception as e:
74
+ lines.append(f"Error: {e}")
75
+ self.update("\n".join(lines))
@@ -0,0 +1,35 @@
1
+ """
2
+ Agent role activity: show which roles are active and for which tasks.
3
+ """
4
+
5
+ from textual.widgets import Static
6
+
7
+
8
+ class AgentRoleActivityView(Static):
9
+ """Shows agent role per task: research_agent, code_agent, analysis_agent, critic_agent."""
10
+
11
+ def __init__(self, *args, **kwargs) -> None:
12
+ super().__init__(*args, **kwargs)
13
+ self._tasks_with_roles: list[dict] = []
14
+
15
+ def set_tasks_with_roles(self, tasks: list[dict]) -> None:
16
+ """Update with list of {task_id, role, status}. Role can be None."""
17
+ self._tasks_with_roles = tasks
18
+ self._refresh_display()
19
+
20
+ def _refresh_display(self) -> None:
21
+ if not self._tasks_with_roles:
22
+ self.update("(Agent roles)\n\nNo task/role data yet.")
23
+ return
24
+ by_role: dict[str, list[str]] = {}
25
+ for t in self._tasks_with_roles:
26
+ role = t.get("role") or "general"
27
+ tid = t.get("task_id", "?")
28
+ by_role.setdefault(role, []).append(tid)
29
+ lines = ["(Agent role activity)", ""]
30
+ for role in ["research_agent", "code_agent", "analysis_agent", "critic_agent", "general"]:
31
+ if role not in by_role:
32
+ continue
33
+ tasks = by_role[role][:10]
34
+ lines.append(f" {role}: {', '.join(tasks)}")
35
+ self.update("\n".join(lines))