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,122 @@
1
+ """
2
+ Repo scaffolder: generate repo structure from an architecture plan.
3
+
4
+ Structure: repo/backend/, frontend/, tests/, docker/, README.md
5
+ """
6
+
7
+ from pathlib import Path
8
+ from dataclasses import dataclass, field
9
+
10
+
11
+ @dataclass
12
+ class ArchitecturePlan:
13
+ """High-level architecture for the app to build."""
14
+
15
+ name: str
16
+ description: str
17
+ backend: str # e.g. "fastapi", "flask"
18
+ frontend: str # e.g. "react", "vanilla", "none"
19
+ features: list[str] = field(default_factory=list)
20
+
21
+
22
+ def scaffold_repo(
23
+ root: str | Path,
24
+ plan: ArchitecturePlan,
25
+ ) -> list[str]:
26
+ """
27
+ Create directory structure and minimal files based on architecture plan.
28
+ Returns list of created paths (relative to root).
29
+ """
30
+ root = Path(root).resolve()
31
+ root.mkdir(parents=True, exist_ok=True)
32
+ created: list[str] = []
33
+
34
+ # Directories
35
+ dirs = ["backend", "frontend", "tests", "docker"]
36
+ for d in dirs:
37
+ (root / d).mkdir(parents=True, exist_ok=True)
38
+ created.append(d + "/")
39
+
40
+ # README
41
+ readme = f"""# {plan.name}
42
+
43
+ {plan.description}
44
+
45
+ ## Structure
46
+
47
+ - `backend/` — {plan.backend} API
48
+ - `frontend/` — {plan.frontend} UI
49
+ - `tests/` — integration and unit tests
50
+ - `docker/` — container config
51
+
52
+ ## Run
53
+
54
+ ### Backend
55
+ ```bash
56
+ cd backend && pip install -r requirements.txt && python -m uvicorn main:app --reload
57
+ ```
58
+
59
+ ### Frontend (if applicable)
60
+ ```bash
61
+ cd frontend && npm install && npm run dev
62
+ ```
63
+ """
64
+ (root / "README.md").write_text(readme, encoding="utf-8")
65
+ created.append("README.md")
66
+
67
+ # Backend scaffold based on plan.backend
68
+ backend_dir = root / "backend"
69
+ if "fastapi" in plan.backend.lower():
70
+ (backend_dir / "main.py").write_text(
71
+ '"""FastAPI app entrypoint."""\n\nfrom fastapi import FastAPI\n\napp = FastAPI(title="'
72
+ + plan.name.replace('"', "'")
73
+ + '")\n\n\n@app.get("/")\ndef root():\n return {"message": "Hello"}\n',
74
+ encoding="utf-8",
75
+ )
76
+ created.append("backend/main.py")
77
+ (backend_dir / "requirements.txt").write_text(
78
+ "fastapi>=0.100.0\nuvicorn[standard]>=0.22.0\n",
79
+ encoding="utf-8",
80
+ )
81
+ created.append("backend/requirements.txt")
82
+ elif "flask" in plan.backend.lower():
83
+ (backend_dir / "main.py").write_text(
84
+ '"""Flask app entrypoint."""\n\nfrom flask import Flask\n\napp = Flask(__name__)\n\n\n@app.route("/")\ndef root():\n return {"message": "Hello"}\n',
85
+ encoding="utf-8",
86
+ )
87
+ created.append("backend/main.py")
88
+ (backend_dir / "requirements.txt").write_text(
89
+ "flask>=3.0.0\n",
90
+ encoding="utf-8",
91
+ )
92
+ created.append("backend/requirements.txt")
93
+ else:
94
+ (backend_dir / "main.py").write_text(
95
+ '"""App entrypoint."""\n\n# TODO: implement\n',
96
+ encoding="utf-8",
97
+ )
98
+ (backend_dir / "requirements.txt").write_text(
99
+ "\n",
100
+ encoding="utf-8",
101
+ )
102
+ created.append("backend/main.py")
103
+ created.append("backend/requirements.txt")
104
+
105
+ # Tests
106
+ tests_dir = root / "tests"
107
+ (tests_dir / "__init__.py").write_text("", encoding="utf-8")
108
+ (tests_dir / "test_app.py").write_text(
109
+ '"""Basic tests."""\nimport pytest\n\n\ndef test_placeholder():\n assert True\n',
110
+ encoding="utf-8",
111
+ )
112
+ created.append("tests/__init__.py")
113
+ created.append("tests/test_app.py")
114
+
115
+ # Docker placeholder
116
+ (root / "docker" / "Dockerfile").write_text(
117
+ "# Dockerfile placeholder\nFROM python:3.12-slim\nWORKDIR /app\nCOPY backend/ .\nRUN pip install -r requirements.txt\nCMD [\"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\"]\n",
118
+ encoding="utf-8",
119
+ )
120
+ created.append("docker/Dockerfile")
121
+
122
+ return created
@@ -0,0 +1,5 @@
1
+ """Local embedding service with sentence-transformers; fallback to provider embeddings."""
2
+
3
+ from devsper.embeddings.service import embed
4
+
5
+ __all__ = ["embed"]
@@ -0,0 +1,36 @@
1
+ """
2
+ Local embedding service using sentence-transformers (all-MiniLM-L6-v2).
3
+ Falls back to provider embeddings (memory.embeddings.embed_text) if local model unavailable.
4
+ """
5
+
6
+
7
+ def embed(text: str) -> list[float]:
8
+ """
9
+ Return embedding vector for text. Tries local sentence-transformers model first,
10
+ then falls back to provider embeddings (OpenAI/stub).
11
+ """
12
+ if not text or not str(text).strip():
13
+ return _fallback_embed(" ")
14
+ vec = _local_embed(text)
15
+ if vec is not None:
16
+ return vec
17
+ return _fallback_embed(text)
18
+
19
+
20
+ def _local_embed(text: str) -> list[float] | None:
21
+ """Use sentence-transformers all-MiniLM-L6-v2 if available."""
22
+ try:
23
+ from sentence_transformers import SentenceTransformer
24
+
25
+ model = SentenceTransformer("all-MiniLM-L6-v2")
26
+ emb = model.encode(text[:8192], convert_to_numpy=True)
27
+ return emb.tolist()
28
+ except Exception:
29
+ return None
30
+
31
+
32
+ def _fallback_embed(text: str) -> list[float]:
33
+ """Use provider embeddings (OpenAI or stub) from memory.embeddings."""
34
+ from devsper.memory.embeddings import embed_text
35
+
36
+ return embed_text(text)
@@ -0,0 +1,14 @@
1
+ """Explainability: decision tree, rationale, simulation (v2.0)."""
2
+
3
+ from devsper.explainability.decision_tree import DecisionRecord, DecisionTreeBuilder, ToolConsideration
4
+ from devsper.explainability.rationale import RationaleGenerator
5
+ from devsper.explainability.simulation import SimulationMode, SimulationReport
6
+
7
+ __all__ = [
8
+ "DecisionRecord",
9
+ "DecisionTreeBuilder",
10
+ "ToolConsideration",
11
+ "RationaleGenerator",
12
+ "SimulationMode",
13
+ "SimulationReport",
14
+ ]
@@ -0,0 +1,104 @@
1
+ """Decision records per task for explainability."""
2
+
3
+ from dataclasses import dataclass, field
4
+
5
+
6
+ @dataclass
7
+ class ToolConsideration:
8
+ tool_name: str
9
+ similarity_score: float
10
+ reliability_score: float
11
+ blended_score: float
12
+ selected: bool
13
+
14
+
15
+ @dataclass
16
+ class DecisionRecord:
17
+ task_id: str
18
+ task_description: str
19
+ strategy_selected: str
20
+ strategy_reason: str
21
+ tools_considered: list[ToolConsideration] = field(default_factory=list)
22
+ tools_selected: list[str] = field(default_factory=list)
23
+ model_tier: str = ""
24
+ model_selected: str = ""
25
+ model_reason: str = ""
26
+ memory_records_used: int = 0
27
+ kg_context_injected: bool = False
28
+ critic_score: float | None = None
29
+ confidence: float = 0.0
30
+ rationale: str = ""
31
+
32
+
33
+ class DecisionTreeBuilder:
34
+ """Build DecisionRecords from events in a run."""
35
+
36
+ def build_from_events(self, run_id: str, events_dir: str) -> list[DecisionRecord]:
37
+ """Parse events from events_dir for this run_id and build one DecisionRecord per task."""
38
+ import os
39
+ import json
40
+ from pathlib import Path
41
+ records: list[DecisionRecord] = []
42
+ path = Path(events_dir)
43
+ if not path.is_dir():
44
+ return records
45
+ event_files = list(path.glob("*.jsonl"))
46
+ if run_id:
47
+ exact = path / f"{run_id}.jsonl"
48
+ if exact.is_file():
49
+ event_files = [exact]
50
+ else:
51
+ event_files = [f for f in event_files if run_id in f.stem or run_id in f.name]
52
+ events: list[dict] = []
53
+ for f in event_files:
54
+ try:
55
+ with open(f, "r", encoding="utf-8") as fp:
56
+ for line in fp:
57
+ line = line.strip()
58
+ if not line:
59
+ continue
60
+ try:
61
+ events.append(json.loads(line))
62
+ except Exception:
63
+ pass
64
+ except Exception:
65
+ pass
66
+ task_ids = set()
67
+ for ev in events:
68
+ payload = ev.get("payload") or ev if isinstance(ev.get("payload"), dict) else {}
69
+ tid = payload.get("task_id") or ev.get("task_id")
70
+ if tid:
71
+ task_ids.add(tid)
72
+ for tid in sorted(task_ids):
73
+ task_events = [e for e in events if (e.get("payload") or {}).get("task_id") == tid or e.get("task_id") == tid]
74
+ model = ""
75
+ tier = ""
76
+ tools: list[str] = []
77
+ for e in task_events:
78
+ p = e.get("payload") or {}
79
+ if e.get("type") == "task_model_selected" or p.get("model"):
80
+ model = p.get("model") or model
81
+ tier = p.get("tier") or tier
82
+ if e.get("type") == "tool_called" or p.get("tool"):
83
+ t = p.get("tool")
84
+ if t and t not in tools:
85
+ tools.append(t)
86
+ desc = next((p.get("description") for e in task_events for p in [e.get("payload") or {}] if p.get("description")), tid)
87
+ rec = DecisionRecord(
88
+ task_id=tid,
89
+ task_description=desc or tid,
90
+ strategy_selected=tier or "default",
91
+ strategy_reason="from events",
92
+ tools_considered=[],
93
+ tools_selected=tools,
94
+ model_tier=tier or "default",
95
+ model_selected=model or "unknown",
96
+ model_reason="from events",
97
+ memory_records_used=0,
98
+ kg_context_injected=False,
99
+ critic_score=None,
100
+ confidence=0.8,
101
+ rationale=f"Task classified as {tier or 'default'}. Selected {len(tools)} tools ({', '.join(tools)}). Used {model or 'unknown'} ({tier or 'default'} tier). Confidence: 80%.",
102
+ )
103
+ records.append(rec)
104
+ return records
@@ -0,0 +1,38 @@
1
+ """Rationale generation (LLM or template) for decision records."""
2
+
3
+ from devsper.explainability.decision_tree import DecisionRecord
4
+
5
+
6
+ class RationaleGenerator:
7
+ """Generate NL explanation for a DecisionRecord. Cached per task."""
8
+
9
+ def __init__(self) -> None:
10
+ self._cache: dict[str, str] = {}
11
+
12
+ async def generate(self, record: DecisionRecord, model: str = "mock") -> str:
13
+ """Use LLM to generate one-paragraph explanation. Cached per task_id."""
14
+ if record.task_id in self._cache:
15
+ return self._cache[record.task_id]
16
+ try:
17
+ from devsper.utils.models import generate
18
+ prompt = (
19
+ f"Explain in one short paragraph why this AI task was executed this way.\n"
20
+ f"Task: {record.task_description}\n"
21
+ f"Strategy: {record.strategy_selected}. Model: {record.model_selected}. "
22
+ f"Tools used: {', '.join(record.tools_selected)}. Confidence: {record.confidence:.0%}.\n"
23
+ f"Write 2-3 sentences only."
24
+ )
25
+ out = generate(model, prompt)
26
+ self._cache[record.task_id] = out or ""
27
+ return out or self.template_rationale(record)
28
+ except Exception:
29
+ return self.template_rationale(record)
30
+
31
+ def template_rationale(self, record: DecisionRecord) -> str:
32
+ """Template-based fallback (no LLM)."""
33
+ return (
34
+ f"Task classified as {record.strategy_selected}. "
35
+ f"Selected {len(record.tools_selected)} tools ({', '.join(record.tools_selected) or 'none'}). "
36
+ f"Used {record.model_selected} ({record.model_tier} tier). "
37
+ f"Confidence: {record.confidence:.0%}."
38
+ )
@@ -0,0 +1,56 @@
1
+ """Simulation mode: dry-run planning and scheduling without LLM or tool execution."""
2
+
3
+ from dataclasses import dataclass, field
4
+
5
+
6
+ @dataclass
7
+ class SimulationReport:
8
+ task_list: list[str] = field(default_factory=list)
9
+ estimated_cost: str = "N/A"
10
+ estimated_duration: str = "N/A"
11
+ tool_usage_plan: list[str] = field(default_factory=list)
12
+ model_tier_breakdown: dict = field(default_factory=dict)
13
+
14
+
15
+ class SimulationMode:
16
+ """Dry-run: run planner and scheduler, build DecisionRecords, no LLM or tools."""
17
+
18
+ async def simulate(self, root_task: str) -> SimulationReport:
19
+ """Run planning and scheduling only; return SimulationReport."""
20
+ from devsper.swarm.planner import Planner
21
+ from devsper.swarm.scheduler import Scheduler
22
+ from devsper.types.task import Task, TaskStatus
23
+ from devsper.explainability.decision_tree import DecisionTreeBuilder, DecisionRecord
24
+ from devsper.explainability.rationale import RationaleGenerator
25
+ planner = Planner(model_name="mock", event_log=None)
26
+ tasks = planner.plan(root_task)
27
+ if not tasks:
28
+ tasks = [Task(id="1", description=root_task, status=TaskStatus.PENDING)]
29
+ scheduler = Scheduler()
30
+ for t in tasks:
31
+ scheduler.add_task(t)
32
+ task_list = [t.description or t.id for t in scheduler.get_all_tasks()]
33
+ records: list[DecisionRecord] = []
34
+ gen = RationaleGenerator()
35
+ for t in scheduler.get_all_tasks():
36
+ rec = DecisionRecord(
37
+ task_id=t.id,
38
+ task_description=t.description or t.id,
39
+ strategy_selected="default",
40
+ strategy_reason="simulation",
41
+ tools_selected=[],
42
+ model_tier="default",
43
+ model_selected="mock",
44
+ model_reason="simulation",
45
+ confidence=0.5,
46
+ rationale="",
47
+ )
48
+ rec.rationale = gen.template_rationale(rec)
49
+ records.append(rec)
50
+ return SimulationReport(
51
+ task_list=task_list,
52
+ estimated_cost="N/A",
53
+ estimated_duration="N/A",
54
+ tool_usage_plan=[],
55
+ model_tier_breakdown={"default": len(task_list)},
56
+ )
@@ -0,0 +1,13 @@
1
+ """Human-in-the-Loop: escalation triggers, approval requests, and notification."""
2
+
3
+ from devsper.hitl.escalation import EscalationChecker, EscalationPolicy, EscalationTrigger
4
+ from devsper.hitl.approval import ApprovalRequest, ApprovalStore, ApprovalNotifier
5
+
6
+ __all__ = [
7
+ "ApprovalNotifier",
8
+ "ApprovalRequest",
9
+ "ApprovalStore",
10
+ "EscalationChecker",
11
+ "EscalationPolicy",
12
+ "EscalationTrigger",
13
+ ]
@@ -0,0 +1,160 @@
1
+ """
2
+ Approval store and notifier: persist pending approvals, notify approvers, resolve (approve/reject).
3
+ """
4
+
5
+ import json
6
+ import os
7
+ import uuid
8
+ from dataclasses import dataclass
9
+ from datetime import datetime, timezone
10
+ from typing import Literal
11
+
12
+ from devsper.hitl.escalation import EscalationPolicy, EscalationTrigger
13
+
14
+
15
+ @dataclass
16
+ class ApprovalRequest:
17
+ request_id: str
18
+ task: object # Task
19
+ proposed_result: str
20
+ decision_record: object | None # DecisionRecord
21
+ trigger: EscalationTrigger
22
+ created_at: str
23
+ expires_at: str
24
+ status: Literal["pending", "approved", "rejected", "timeout"] = "pending"
25
+ reviewer_notes: str | None = None
26
+
27
+ def to_dict(self) -> dict:
28
+ task = self.task
29
+ task_dict = getattr(task, "to_dict", lambda: {"id": getattr(task, "id", ""), "description": getattr(task, "description", "")})()
30
+ dr = self.decision_record
31
+ dr_dict = None
32
+ if dr is not None and hasattr(dr, "__dict__"):
33
+ dr_dict = {"task_id": getattr(dr, "task_id", ""), "critic_score": getattr(dr, "critic_score", None), "confidence": getattr(dr, "confidence", 0)}
34
+ return {
35
+ "request_id": self.request_id,
36
+ "task": task_dict,
37
+ "proposed_result": self.proposed_result,
38
+ "decision_record": dr_dict,
39
+ "trigger": {"type": self.trigger.type, "threshold": self.trigger.threshold},
40
+ "created_at": self.created_at,
41
+ "expires_at": self.expires_at,
42
+ "status": self.status,
43
+ "reviewer_notes": self.reviewer_notes,
44
+ }
45
+
46
+ @classmethod
47
+ def from_dict(cls, data: dict) -> "ApprovalRequest":
48
+ from devsper.types.task import Task
49
+ task_data = data.get("task") or {}
50
+ task = Task.from_dict(task_data) if isinstance(task_data, dict) else task_data
51
+ tr = data.get("trigger") or {}
52
+ trigger = EscalationTrigger(type=tr.get("type", "confidence_below"), threshold=tr.get("threshold", 0.5))
53
+ return cls(
54
+ request_id=data.get("request_id", ""),
55
+ task=task,
56
+ proposed_result=data.get("proposed_result", ""),
57
+ decision_record=data.get("decision_record"),
58
+ trigger=trigger,
59
+ created_at=data.get("created_at", ""),
60
+ expires_at=data.get("expires_at", ""),
61
+ status=data.get("status", "pending"),
62
+ reviewer_notes=data.get("reviewer_notes"),
63
+ )
64
+
65
+
66
+ class ApprovalStore:
67
+ """Persist pending approvals under {data_dir}/approvals/{request_id}.json."""
68
+
69
+ def __init__(self, data_dir: str = ".devsper") -> None:
70
+ self.data_dir = data_dir
71
+ self._approvals_dir = os.path.join(data_dir, "approvals")
72
+ os.makedirs(self._approvals_dir, exist_ok=True)
73
+
74
+ def _path(self, request_id: str) -> str:
75
+ return os.path.join(self._approvals_dir, f"{request_id}.json")
76
+
77
+ def list_pending(self) -> list[ApprovalRequest]:
78
+ """Return all pending approval requests."""
79
+ out: list[ApprovalRequest] = []
80
+ for name in os.listdir(self._approvals_dir):
81
+ if name.endswith(".json"):
82
+ rid = name[:-5]
83
+ req = self.get(rid)
84
+ if req is not None and req.status == "pending":
85
+ out.append(req)
86
+ return out
87
+
88
+ def get(self, request_id: str) -> ApprovalRequest | None:
89
+ """Load one request by id."""
90
+ path = self._path(request_id)
91
+ if not os.path.isfile(path):
92
+ return None
93
+ try:
94
+ with open(path, "r", encoding="utf-8") as f:
95
+ return ApprovalRequest.from_dict(json.load(f))
96
+ except Exception:
97
+ return None
98
+
99
+ def save(self, request: ApprovalRequest) -> None:
100
+ """Write request to disk."""
101
+ path = self._path(request.request_id)
102
+ with open(path, "w", encoding="utf-8") as f:
103
+ json.dump(request.to_dict(), f, indent=0)
104
+
105
+ def resolve(self, request_id: str, approved: bool, notes: str = "") -> None:
106
+ """Mark request approved or rejected and save."""
107
+ req = self.get(request_id)
108
+ if req is None:
109
+ return
110
+ req.status = "approved" if approved else "rejected"
111
+ req.reviewer_notes = notes or req.reviewer_notes
112
+ self.save(req)
113
+
114
+
115
+ class ApprovalNotifier:
116
+ """Send approval requests via configured channels (webhook, slack, email)."""
117
+
118
+ async def notify(self, request: ApprovalRequest, policy: EscalationPolicy) -> None:
119
+ """For each approver in policy.approvers, parse scheme and dispatch."""
120
+ for approver in policy.approvers or []:
121
+ if approver.startswith("webhook://"):
122
+ await self._notify_webhook(request, approver[10:].strip())
123
+ elif approver.startswith("slack://"):
124
+ await self._notify_slack(request, approver[8:].strip())
125
+ elif approver.startswith("email://"):
126
+ self._notify_email(request, approver[8:].strip())
127
+
128
+ async def _notify_webhook(self, request: ApprovalRequest, url: str) -> None:
129
+ try:
130
+ import httpx
131
+ async with httpx.AsyncClient() as client:
132
+ await client.post(url, json=request.to_dict(), timeout=10.0)
133
+ except Exception as e:
134
+ import sys
135
+ print(f"[hitl] webhook notification failed: {e}", file=sys.stderr)
136
+
137
+ async def _notify_slack(self, request: ApprovalRequest, webhook_or_channel: str) -> None:
138
+ try:
139
+ import httpx
140
+ payload = {
141
+ "text": f"Approval requested: {getattr(request.task, 'description', '')[:200]}...",
142
+ "blocks": [
143
+ {"type": "section", "text": {"type": "mrkdwn", "text": f"*Task:* {getattr(request.task, 'description', '')[:300]}"}},
144
+ {"type": "section", "text": {"type": "mrkdwn", "text": f"*Request ID:* `{request.request_id}`"}},
145
+ ],
146
+ }
147
+ if webhook_or_channel.startswith("http"):
148
+ async with httpx.AsyncClient() as client:
149
+ await client.post(webhook_or_channel, json=payload, timeout=10.0)
150
+ else:
151
+ import sys
152
+ print("[hitl] slack:// URL must be webhook URL (https://hooks.slack.com/...)", file=sys.stderr)
153
+ except Exception as e:
154
+ import sys
155
+ print(f"[hitl] slack notification failed: {e}", file=sys.stderr)
156
+
157
+ def _notify_email(self, request: ApprovalRequest, _address: str) -> None:
158
+ import sys
159
+ print("[hitl] email notifications require external SMTP config; printing to stdout", file=sys.stderr)
160
+ print(f"Approval requested: request_id={request.request_id} task={getattr(request.task, 'description', '')[:100]}")
@@ -0,0 +1,95 @@
1
+ """
2
+ Escalation policies and triggers: when to send a task for human approval.
3
+ """
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Literal
7
+
8
+ # Avoid circular import; Task, AgentResponse, DecisionRecord used at runtime
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from devsper.types.task import Task
13
+ from devsper.agents.agent import AgentResponse
14
+ from devsper.explainability.decision_tree import DecisionRecord
15
+
16
+
17
+ EscalationTriggerType = Literal[
18
+ "confidence_below",
19
+ "cost_above",
20
+ "tool_category",
21
+ "keyword_match",
22
+ "critic_score_below",
23
+ "sla_at_risk",
24
+ ]
25
+
26
+
27
+ @dataclass
28
+ class EscalationTrigger:
29
+ type: EscalationTriggerType
30
+ threshold: float | str # number for numeric triggers, string for keyword/category
31
+
32
+
33
+ @dataclass
34
+ class EscalationPolicy:
35
+ triggers: list[EscalationTrigger]
36
+ approvers: list[str] # email://, slack://, webhook://
37
+ timeout_seconds: int = 3600
38
+ on_timeout: Literal["auto_approve", "auto_reject", "escalate_further"] = "auto_approve"
39
+
40
+
41
+ class EscalationChecker:
42
+ """Evaluate task + response + decision against configured triggers; return first match or None."""
43
+
44
+ def __init__(self, policies: list[EscalationPolicy]) -> None:
45
+ self.policies = policies
46
+ self._triggers: list[tuple[EscalationTrigger, EscalationPolicy]] = []
47
+ for p in policies:
48
+ for t in p.triggers:
49
+ self._triggers.append((t, p))
50
+
51
+ def evaluate(
52
+ self,
53
+ task: "Task",
54
+ response: "AgentResponse",
55
+ decision: "DecisionRecord | None",
56
+ ) -> tuple[EscalationTrigger, EscalationPolicy] | None:
57
+ """Check all configured triggers. Return first (trigger, policy) match or None."""
58
+ for trigger, policy in self._triggers:
59
+ if self._matches(trigger, task, response, decision):
60
+ return (trigger, policy)
61
+ return None
62
+
63
+ def _matches(
64
+ self,
65
+ trigger: EscalationTrigger,
66
+ task: "Task",
67
+ response: "AgentResponse",
68
+ decision: "DecisionRecord | None",
69
+ ) -> bool:
70
+ t = trigger.type
71
+ th = trigger.threshold
72
+ if t == "confidence_below" and decision is not None:
73
+ return (decision.confidence or 0) < float(th)
74
+ if t == "cost_above":
75
+ # Approximate cost from tokens if available
76
+ cost = 0.0
77
+ if getattr(response, "tokens_used", None):
78
+ cost = (response.tokens_used or 0) * 1e-6 # rough
79
+ return cost > float(th)
80
+ if t == "tool_category":
81
+ tools = getattr(response, "tools_called", []) or []
82
+ # Compare category names if we had a category; use tool names as proxy
83
+ return isinstance(th, str) and th.lower() in [str(x).lower() for x in tools]
84
+ if t == "keyword_match" and isinstance(th, str):
85
+ text = (task.description or "") + " " + (response.result or "")
86
+ return th.lower() in text.lower()
87
+ if t == "critic_score_below" and decision is not None:
88
+ score = decision.critic_score
89
+ if score is not None:
90
+ return score < float(th)
91
+ return False
92
+ if t == "sla_at_risk":
93
+ # Would need SLA context; treat as no match if not applicable
94
+ return False
95
+ return False
@@ -0,0 +1,9 @@
1
+ """
2
+ Swarm intelligence: task optimization, strategy selection, learning from runs.
3
+ """
4
+
5
+ from devsper.intelligence.task_optimizer import TaskOptimizer
6
+ from devsper.intelligence.strategy_selector import StrategySelector
7
+ from devsper.intelligence.learning_engine import LearningEngine
8
+
9
+ __all__ = ["TaskOptimizer", "StrategySelector", "LearningEngine"]