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,197 @@
1
+ """CLI for credential management: set, list, delete, migrate, export."""
2
+
3
+ import getpass
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+
10
+ from devsper.credentials import (
11
+ delete_credential,
12
+ get_credential,
13
+ list_credentials,
14
+ set_credential,
15
+ )
16
+ from devsper.credentials.migration import migrate_from_config
17
+
18
+ KNOWN_CREDENTIALS = {
19
+ "openai": ["api_key"],
20
+ "anthropic": ["api_key"],
21
+ "github": ["token"],
22
+ "gemini": ["api_key"],
23
+ "azure": ["endpoint", "api_key", "deployment", "api_version"],
24
+ "azure_anthropic": ["endpoint", "api_key", "deployment"],
25
+ }
26
+
27
+ # Keys that must never be shown in list (only "(stored)"); all others can show value
28
+ SENSITIVE_KEYS = {"api_key", "token"}
29
+
30
+ # (provider, key) -> env var name for export
31
+ PROVIDER_KEY_TO_ENV: dict[tuple[str, str], str] = {
32
+ ("openai", "api_key"): "OPENAI_API_KEY",
33
+ ("anthropic", "api_key"): "ANTHROPIC_API_KEY",
34
+ ("github", "token"): "GITHUB_TOKEN",
35
+ ("gemini", "api_key"): "GEMINI_API_KEY",
36
+ ("azure", "endpoint"): "AZURE_OPENAI_ENDPOINT",
37
+ ("azure", "api_key"): "AZURE_OPENAI_API_KEY",
38
+ ("azure", "deployment"): "AZURE_OPENAI_DEPLOYMENT_NAME",
39
+ ("azure", "api_version"): "AZURE_OPENAI_API_VERSION",
40
+ ("azure_anthropic", "endpoint"): "AZURE_ANTHROPIC_ENDPOINT",
41
+ ("azure_anthropic", "api_key"): "AZURE_ANTHROPIC_API_KEY",
42
+ ("azure_anthropic", "deployment"): "AZURE_ANTHROPIC_DEPLOYMENT_NAME",
43
+ }
44
+
45
+
46
+ def _env_escape(value: str) -> str:
47
+ """Escape value for .env / export format: double-quote and escape internal quotes."""
48
+ return '"' + value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + '"'
49
+
50
+
51
+ def _run_credentials_export(provider: str) -> int:
52
+ """Print provider's credentials in env format (KEY=value, one per line)."""
53
+ if provider not in KNOWN_CREDENTIALS:
54
+ print(f"Unknown provider: {provider}", file=sys.stderr)
55
+ return 1
56
+ lines: list[str] = []
57
+ for key in KNOWN_CREDENTIALS[provider]:
58
+ env_var = PROVIDER_KEY_TO_ENV.get((provider, key))
59
+ if not env_var:
60
+ continue
61
+ val = get_credential(provider, key)
62
+ if val is not None:
63
+ lines.append(f"{env_var}={_env_escape(val)}")
64
+ if not lines:
65
+ print(f"No credentials stored for provider: {provider}", file=sys.stderr)
66
+ return 1
67
+ for line in lines:
68
+ print(line)
69
+ return 0
70
+
71
+
72
+ def _run_credentials_set(provider: str, key: str, value: str | None = None) -> int:
73
+ """Store credential. Value can be passed inline, read from stdin, or prompted interactively."""
74
+ if provider not in KNOWN_CREDENTIALS:
75
+ print(f"Unknown provider: {provider}", file=sys.stderr)
76
+ return 1
77
+ if key not in KNOWN_CREDENTIALS[provider]:
78
+ print(f"Unknown key for {provider}: {key}", file=sys.stderr)
79
+ return 1
80
+
81
+ if value is not None and value.strip():
82
+ # Inline value from CLI
83
+ pass
84
+ elif not sys.stdin.isatty():
85
+ # Piped input: echo "val" | devsper credentials set ...
86
+ try:
87
+ value = sys.stdin.read().strip()
88
+ except (KeyboardInterrupt, EOFError):
89
+ print("\nCancelled.", file=sys.stderr)
90
+ return 130
91
+ else:
92
+ # Interactive prompt
93
+ try:
94
+ if key in SENSITIVE_KEYS:
95
+ value = getpass.getpass(f"Enter value for {provider}/{key}: ")
96
+ else:
97
+ value = input(f"Enter value for {provider}/{key}: ")
98
+ except (KeyboardInterrupt, EOFError):
99
+ print("\nCancelled.", file=sys.stderr)
100
+ return 130
101
+
102
+ if not value or not value.strip():
103
+ print("Empty value, not stored.", file=sys.stderr)
104
+ return 1
105
+ set_credential(provider, key, value.strip())
106
+ print(f"Stored {provider}/{key}")
107
+ return 0
108
+
109
+
110
+ def _run_credentials_list() -> int:
111
+ """List credentials as table (provider, key, value). Secret keys show '(stored)', others show value."""
112
+ creds = list_credentials()
113
+ if not creds:
114
+ print("No credentials stored.")
115
+ return 0
116
+ table = Table(title="Stored credentials")
117
+ table.add_column("Provider", style="cyan")
118
+ table.add_column("Key", style="green")
119
+ table.add_column("Value", style="dim")
120
+ for c in creds:
121
+ p, k = c["provider"], c["key"]
122
+ if k in SENSITIVE_KEYS:
123
+ value = "(stored)"
124
+ else:
125
+ val = get_credential(p, k)
126
+ value = (val[:60] + "…") if val and len(val) > 60 else (val or "")
127
+ table.add_row(p, k, value)
128
+ console = Console()
129
+ console.print(table)
130
+ return 0
131
+
132
+
133
+ def _run_credentials_delete(provider: str, key: str) -> int:
134
+ """Remove a credential."""
135
+ if provider not in KNOWN_CREDENTIALS:
136
+ print(f"Unknown provider: {provider}", file=sys.stderr)
137
+ return 1
138
+ if key not in KNOWN_CREDENTIALS[provider]:
139
+ print(f"Unknown key for {provider}: {key}", file=sys.stderr)
140
+ return 1
141
+ delete_credential(provider, key)
142
+ print(f"Deleted {provider}/{key}")
143
+ return 0
144
+
145
+
146
+ def _run_credentials_migrate() -> int:
147
+ """Migrate credentials from TOML and env to store."""
148
+ from devsper.config.config_loader import project_config_paths
149
+
150
+ config_path = None
151
+ for p in project_config_paths():
152
+ if p.is_file():
153
+ config_path = p
154
+ break
155
+ if not config_path:
156
+ config_path = Path.cwd() / "devsper.toml"
157
+
158
+ migrated = migrate_from_config(config_path)
159
+ if not migrated:
160
+ print("No credentials found in env or TOML to migrate.")
161
+ return 0
162
+ print(f"Migrated {len(migrated)} credential(s):")
163
+ for item in migrated:
164
+ print(f" - {item}")
165
+ print("\nYou can now remove these from devsper.toml and .env for better security.")
166
+ return 0
167
+
168
+
169
+ def run_credentials(args: object) -> int:
170
+ """Dispatch credentials subcommand."""
171
+ sub = getattr(args, "credentials_subcommand", None)
172
+ provider = getattr(args, "provider", None)
173
+ key = getattr(args, "key", None)
174
+
175
+ if sub == "set":
176
+ if not provider or not key:
177
+ print("Usage: devsper credentials set <provider> <key> [value]", file=sys.stderr)
178
+ return 1
179
+ value = getattr(args, "value", None)
180
+ return _run_credentials_set(provider, key, value)
181
+ if sub == "list":
182
+ return _run_credentials_list()
183
+ if sub == "delete":
184
+ if not provider or not key:
185
+ print("Usage: devsper credentials delete <provider> <key>", file=sys.stderr)
186
+ return 1
187
+ return _run_credentials_delete(provider, key)
188
+ if sub == "migrate":
189
+ return _run_credentials_migrate()
190
+ if sub == "export":
191
+ if not provider:
192
+ print("Usage: devsper credentials export <provider>", file=sys.stderr)
193
+ return 1
194
+ return _run_credentials_export(provider)
195
+
196
+ print("Usage: devsper credentials set|list|delete|migrate|export", file=sys.stderr)
197
+ return 1
@@ -0,0 +1,124 @@
1
+ """Migrate credentials from devsper.toml and env to the credential store."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ from devsper.credentials import set_credential
7
+
8
+
9
+ def _load_dotenv_for_config(config_path: Path) -> None:
10
+ """Load .env from config directory so env vars are available for migration."""
11
+ try:
12
+ from dotenv import load_dotenv
13
+
14
+ load_dotenv(config_path.parent / ".env")
15
+ except Exception:
16
+ pass
17
+
18
+ # Env var -> (provider, key)
19
+ _ENV_TO_CREDENTIAL: dict[str, tuple[str, str]] = {
20
+ "OPENAI_API_KEY": ("openai", "api_key"),
21
+ "ANTHROPIC_API_KEY": ("anthropic", "api_key"),
22
+ "GITHUB_TOKEN": ("github", "token"),
23
+ "GEMINI_API_KEY": ("gemini", "api_key"),
24
+ "GOOGLE_API_KEY": ("gemini", "api_key"),
25
+ "AZURE_OPENAI_API_KEY": ("azure", "api_key"),
26
+ "AZURE_OPENAI_ENDPOINT": ("azure", "endpoint"),
27
+ "AZURE_OPENAI_DEPLOYMENT_NAME": ("azure", "deployment"),
28
+ "AZURE_OPENAI_API_VERSION": ("azure", "api_version"),
29
+ "AZURE_ANTHROPIC_ENDPOINT": ("azure_anthropic", "endpoint"),
30
+ "AZURE_ANTHROPIC_API_KEY": ("azure_anthropic", "api_key"),
31
+ "AZURE_ANTHROPIC_DEPLOYMENT_NAME": ("azure_anthropic", "deployment"),
32
+ }
33
+
34
+
35
+ def migrate_from_config(config_path: Path) -> list[str]:
36
+ """
37
+ Scan TOML and env for known credentials, migrate to store.
38
+ Returns list of migrated items (e.g. ["openai/api_key", "azure/endpoint"]).
39
+ Does NOT delete from env — inform user they can remove them.
40
+ """
41
+ migrated: list[str] = []
42
+
43
+ # Load .env from config directory so all env vars are available
44
+ _load_dotenv_for_config(config_path)
45
+
46
+ # 1. Check env vars
47
+ for env_var, (provider, key) in _ENV_TO_CREDENTIAL.items():
48
+ val = os.environ.get(env_var)
49
+ if val and str(val).strip():
50
+ set_credential(provider, key, str(val).strip())
51
+ migrated.append(f"{provider}/{key}")
52
+
53
+ # 2. Check TOML
54
+ if config_path.is_file():
55
+ try:
56
+ import tomllib
57
+
58
+ with open(config_path, "rb") as f:
59
+ data = tomllib.load(f)
60
+ except Exception:
61
+ return migrated
62
+
63
+ # [providers.azure]
64
+ providers = data.get("providers") or {}
65
+ azure = providers.get("azure")
66
+ if isinstance(azure, dict):
67
+ for toml_key, cred_key in [
68
+ ("endpoint", "endpoint"),
69
+ ("api_key", "api_key"),
70
+ ("deployment", "deployment"),
71
+ ("api_version", "api_version"),
72
+ ]:
73
+ val = azure.get(toml_key)
74
+ if val is not None and str(val).strip():
75
+ item = f"azure/{cred_key}"
76
+ if item not in migrated:
77
+ set_credential("azure", cred_key, str(val).strip())
78
+ migrated.append(item)
79
+
80
+ # Legacy sections: [openai], [anthropic], [azure_openai], etc.
81
+ for section, (provider, key) in [
82
+ ("openai", ("openai", "api_key")),
83
+ ("anthropic", ("anthropic", "api_key")),
84
+ ("google", ("gemini", "api_key")),
85
+ ]:
86
+ block = data.get(section)
87
+ if isinstance(block, dict):
88
+ val = block.get("api_key")
89
+ if val is not None and str(val).strip():
90
+ item = f"{provider}/{key}"
91
+ if item not in migrated:
92
+ set_credential(provider, key, str(val).strip())
93
+ migrated.append(item)
94
+
95
+ azure_block = data.get("azure_openai")
96
+ if isinstance(azure_block, dict):
97
+ for toml_key, cred_key in [
98
+ ("endpoint", "endpoint"),
99
+ ("api_key", "api_key"),
100
+ ("deployment_name", "deployment"),
101
+ ("api_version", "api_version"),
102
+ ]:
103
+ val = azure_block.get(toml_key)
104
+ if val is not None and str(val).strip():
105
+ item = f"azure/{cred_key}"
106
+ if item not in migrated:
107
+ set_credential("azure", cred_key, str(val).strip())
108
+ migrated.append(item)
109
+
110
+ azure_anthropic_block = data.get("azure_anthropic")
111
+ if isinstance(azure_anthropic_block, dict):
112
+ for toml_key, cred_key in [
113
+ ("endpoint", "endpoint"),
114
+ ("api_key", "api_key"),
115
+ ("deployment_name", "deployment"),
116
+ ]:
117
+ val = azure_anthropic_block.get(toml_key)
118
+ if val is not None and str(val).strip():
119
+ item = f"azure_anthropic/{cred_key}"
120
+ if item not in migrated:
121
+ set_credential("azure_anthropic", cred_key, str(val).strip())
122
+ migrated.append(item)
123
+
124
+ return migrated
@@ -0,0 +1,142 @@
1
+ """Credential store: OS keychain (keyring) only."""
2
+
3
+ import os
4
+ import logging
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ # (provider, key) -> env var name; used to inject keychain into env for providers (e.g. run_agent subprocess).
9
+ _PROVIDER_KEY_TO_ENV: list[tuple[str, str, str]] = [
10
+ ("openai", "api_key", "OPENAI_API_KEY"),
11
+ ("anthropic", "api_key", "ANTHROPIC_API_KEY"),
12
+ ("github", "token", "GITHUB_TOKEN"),
13
+ ("gemini", "api_key", "GEMINI_API_KEY"),
14
+ ("gemini", "api_key", "GOOGLE_API_KEY"),
15
+ ("azure", "api_key", "AZURE_OPENAI_API_KEY"),
16
+ ("azure", "endpoint", "AZURE_OPENAI_ENDPOINT"),
17
+ ("azure", "deployment", "AZURE_OPENAI_DEPLOYMENT_NAME"),
18
+ ("azure", "api_version", "AZURE_OPENAI_API_VERSION"),
19
+ ("azure_anthropic", "api_key", "AZURE_ANTHROPIC_API_KEY"),
20
+ ("azure_anthropic", "endpoint", "AZURE_ANTHROPIC_ENDPOINT"),
21
+ ("azure_anthropic", "deployment", "AZURE_ANTHROPIC_DEPLOYMENT_NAME"),
22
+ ]
23
+
24
+ SERVICE_NAME = "devsper"
25
+
26
+ # Provider/key -> known keys for list_all
27
+ KNOWN_CREDENTIALS = {
28
+ "openai": ["api_key"],
29
+ "anthropic": ["api_key"],
30
+ "github": ["token"],
31
+ "gemini": ["api_key"],
32
+ "azure": ["endpoint", "api_key", "deployment", "api_version"],
33
+ "azure_anthropic": ["endpoint", "api_key", "deployment"],
34
+ }
35
+
36
+
37
+ def _username(provider: str, key: str) -> str:
38
+ return f"{provider}/{key}"
39
+
40
+
41
+ class CredentialStore:
42
+ """
43
+ Secure credential store using OS keychain (keyring) only.
44
+ Never logs credential values.
45
+ """
46
+
47
+ def get(self, provider: str, key: str) -> str | None:
48
+ """Get credential from keyring. Returns None if not found or keyring unavailable."""
49
+ username = _username(provider, key)
50
+ try:
51
+ import keyring
52
+ from keyring.errors import KeyringError
53
+
54
+ val = keyring.get_password(SERVICE_NAME, username)
55
+ if val is not None:
56
+ logger.debug("Credential %s/%s retrieved from keyring", provider, key)
57
+ return val
58
+ except KeyringError:
59
+ logger.debug("Keyring unavailable")
60
+ return None
61
+ except Exception as e:
62
+ logger.debug("Keyring error: %s", type(e).__name__)
63
+ return None
64
+
65
+ def set(self, provider: str, key: str, value: str) -> None:
66
+ """Store credential in keyring."""
67
+ username = _username(provider, key)
68
+ try:
69
+ import keyring
70
+ from keyring.errors import KeyringError
71
+
72
+ keyring.set_password(SERVICE_NAME, username, value)
73
+ logger.debug("Credential %s/%s stored in keyring", provider, key)
74
+ except KeyringError as e:
75
+ raise RuntimeError("Keyring unavailable; cannot store credentials") from e
76
+ except Exception as e:
77
+ raise RuntimeError(f"Keyring error: {e}") from e
78
+
79
+ def delete(self, provider: str, key: str) -> None:
80
+ """Delete credential from keyring."""
81
+ username = _username(provider, key)
82
+ try:
83
+ import keyring
84
+ keyring.delete_password(SERVICE_NAME, username)
85
+ except Exception:
86
+ pass
87
+
88
+ def list_all(self) -> list[dict]:
89
+ """List stored credentials: [{provider, key, source}]. Never returns values."""
90
+ result: list[dict] = []
91
+ try:
92
+ import keyring
93
+
94
+ for provider, keys in KNOWN_CREDENTIALS.items():
95
+ for k in keys:
96
+ username = _username(provider, k)
97
+ val = keyring.get_password(SERVICE_NAME, username)
98
+ if val is not None:
99
+ result.append({"provider": provider, "key": k, "source": "keyring"})
100
+ except Exception:
101
+ pass
102
+ return result
103
+
104
+
105
+ _default_store: CredentialStore | None = None
106
+
107
+
108
+ def _get_store() -> CredentialStore:
109
+ global _default_store
110
+ if _default_store is None:
111
+ _default_store = CredentialStore()
112
+ return _default_store
113
+
114
+
115
+ def get_credential(provider: str, key: str) -> str | None:
116
+ """Get credential from store. Returns None if not found."""
117
+ return _get_store().get(provider, key)
118
+
119
+
120
+ def set_credential(provider: str, key: str, value: str) -> None:
121
+ """Store credential in keyring."""
122
+ _get_store().set(provider, key, value)
123
+
124
+
125
+ def delete_credential(provider: str, key: str) -> None:
126
+ """Remove credential from store."""
127
+ _get_store().delete(provider, key)
128
+
129
+
130
+ def list_credentials() -> list[dict]:
131
+ """List stored credentials (provider, key, source). Never returns values."""
132
+ return _get_store().list_all()
133
+
134
+
135
+ def inject_into_env() -> None:
136
+ """Set os.environ from keychain for each provider key that is not already set.
137
+ Call this at process startup (e.g. run_agent subprocess) so providers see credentials."""
138
+ for provider, key, env_var in _PROVIDER_KEY_TO_ENV:
139
+ if not os.environ.get(env_var):
140
+ val = get_credential(provider, key)
141
+ if val:
142
+ os.environ[env_var] = val
@@ -0,0 +1,9 @@
1
+ """
2
+ Swarm dashboard: view task DAG, replay, memory entries, telemetry.
3
+
4
+ Terminal output via Rich. Use show_dashboard() for a combined view.
5
+ """
6
+
7
+ from devsper.dashboard.dashboard import show_dashboard
8
+
9
+ __all__ = ["show_dashboard"]
@@ -0,0 +1,87 @@
1
+ """
2
+ Minimal visualization: task DAG, swarm replay, memory entries, telemetry.
3
+
4
+ Uses Rich for terminal output when available; falls back to plain text.
5
+ """
6
+
7
+ import os
8
+ from pathlib import Path
9
+
10
+ from devsper.swarm.scheduler import Scheduler
11
+ from devsper.runtime.visualize import visualize_scheduler_dag
12
+ from devsper.runtime.replay import replay_execution
13
+ from devsper.runtime.telemetry import collect_telemetry, print_telemetry_summary
14
+ from devsper.memory.memory_store import MemoryStore, get_default_store
15
+
16
+
17
+ def _latest_log_path(events_folder: str = ".devsper/events") -> str | None:
18
+ if not os.path.isdir(events_folder):
19
+ return None
20
+ files = list(Path(events_folder).glob("events_*.jsonl"))
21
+ if not files:
22
+ return None
23
+ files.sort(key=lambda p: p.stat().st_mtime, reverse=True)
24
+ return str(files[0])
25
+
26
+
27
+ def show_dashboard(
28
+ scheduler: Scheduler | None = None,
29
+ log_path: str | None = None,
30
+ memory_store: MemoryStore | None = None,
31
+ events_folder: str = ".devsper/events",
32
+ memory_limit: int = 20,
33
+ ) -> str:
34
+ """
35
+ Print a combined dashboard: task DAG (if scheduler given), swarm replay and telemetry
36
+ (if log_path or latest log in events_folder), and recent memory entries (if store given).
37
+ Returns the full dashboard as a string.
38
+ """
39
+ try:
40
+ from rich.console import Console
41
+ from rich.panel import Panel
42
+ use_rich = True
43
+ except ImportError:
44
+ use_rich = False
45
+
46
+ lines: list[str] = []
47
+
48
+ if scheduler is not None:
49
+ dag = visualize_scheduler_dag(scheduler)
50
+ lines.append("=== TASK DAG ===")
51
+ lines.append(dag)
52
+ lines.append("")
53
+
54
+ if log_path is None:
55
+ log_path = _latest_log_path(events_folder)
56
+ if log_path and os.path.exists(log_path):
57
+ lines.append("=== SWARM REPLAY ===")
58
+ lines.append(replay_execution(log_path))
59
+ lines.append("")
60
+ lines.append("=== TELEMETRY ===")
61
+ lines.append(print_telemetry_summary(log_path))
62
+ lines.append("")
63
+ else:
64
+ lines.append("=== SWARM REPLAY / TELEMETRY ===")
65
+ lines.append("(no event log found)")
66
+ lines.append("")
67
+
68
+ store = memory_store or get_default_store()
69
+ lines.append("=== MEMORY (recent) ===")
70
+ try:
71
+ records = store.list_memory(limit=memory_limit)
72
+ if not records:
73
+ lines.append("(no memory entries)")
74
+ else:
75
+ for r in records:
76
+ lines.append(f" [{r.memory_type.value}] {r.id}: {r.content[:120]}{'...' if len(r.content) > 120 else ''}")
77
+ except Exception as e:
78
+ lines.append(f"(error listing memory: {e})")
79
+ lines.append("")
80
+
81
+ out = "\n".join(lines)
82
+ if use_rich:
83
+ console = Console()
84
+ console.print(Panel(out, title="Swarm Dashboard", border_style="blue"))
85
+ else:
86
+ print(out)
87
+ return out
@@ -0,0 +1,25 @@
1
+ """
2
+ Autonomous Application Builder: build working repos from app descriptions.
3
+
4
+ Modules:
5
+ - builder: orchestrates architecture → scaffold → implement → test → debug
6
+ - scaffold: repo structure generation (backend, frontend, tests, docker)
7
+ - sandbox: isolated execution with timeout and resource limits
8
+ - debugger: test run → error detection → fix tasks → patch loop
9
+ - repo_index: AST parsing, dependency graph, symbol search (code intelligence)
10
+ - agents: dev-specific roles (architect, backend, frontend, test, review)
11
+ """
12
+
13
+ from devsper.dev.builder import run_build
14
+ from devsper.dev.scaffold import scaffold_repo
15
+ from devsper.dev.sandbox import Sandbox
16
+ from devsper.dev.debugger import debug_loop
17
+ from devsper.dev.repo_index import RepoIndex
18
+
19
+ __all__ = [
20
+ "run_build",
21
+ "scaffold_repo",
22
+ "Sandbox",
23
+ "debug_loop",
24
+ "RepoIndex",
25
+ ]