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,35 @@
1
+ """Read contents of a file from the filesystem."""
2
+
3
+ from pathlib import Path
4
+
5
+ from devsper.tools.base import Tool
6
+ from devsper.tools.registry import register
7
+
8
+
9
+ class ReadFileTool(Tool):
10
+ """Read and return the full text content of a file."""
11
+
12
+ name = "read_file"
13
+ description = "Read the contents of a file. Returns the raw text."
14
+ input_schema = {
15
+ "type": "object",
16
+ "properties": {"path": {"type": "string", "description": "Path to the file"}},
17
+ "required": ["path"],
18
+ }
19
+
20
+ def run(self, **kwargs) -> str:
21
+ path = kwargs.get("path")
22
+ if not path or not isinstance(path, str):
23
+ return "Error: path must be a non-empty string"
24
+ p = Path(path)
25
+ if not p.exists():
26
+ return f"Error: file not found: {path}"
27
+ if not p.is_file():
28
+ return f"Error: not a file: {path}"
29
+ try:
30
+ return p.read_text(encoding="utf-8", errors="replace")
31
+ except Exception as e:
32
+ return f"Error reading file: {e}"
33
+
34
+
35
+ register(ReadFileTool())
@@ -0,0 +1,60 @@
1
+ """Search for files by name pattern or content."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+
6
+ from devsper.tools.base import Tool
7
+ from devsper.tools.registry import register
8
+
9
+
10
+ class SearchFilesTool(Tool):
11
+ """Search for files: by filename pattern (glob) or by text content in files."""
12
+
13
+ name = "search_files"
14
+ description = "Search for files by path/name pattern or by content. Returns matching file paths."
15
+ input_schema = {
16
+ "type": "object",
17
+ "properties": {
18
+ "path": {"type": "string", "description": "Root directory to search"},
19
+ "pattern": {"type": "string", "description": "Glob pattern for filename (e.g. *.py) or regex for content"},
20
+ "content_search": {"type": "boolean", "description": "If true, pattern is used as regex to search file contents"},
21
+ },
22
+ "required": ["path", "pattern"],
23
+ }
24
+
25
+ def run(self, **kwargs) -> str:
26
+ path = kwargs.get("path")
27
+ pattern = kwargs.get("pattern")
28
+ content_search = kwargs.get("content_search", False)
29
+ if not path or not isinstance(path, str):
30
+ return "Error: path must be a non-empty string"
31
+ if not pattern or not isinstance(pattern, str):
32
+ return "Error: pattern must be a non-empty string"
33
+ p = Path(path)
34
+ if not p.exists() or not p.is_dir():
35
+ return f"Error: path must be an existing directory: {path}"
36
+ try:
37
+ if content_search:
38
+ try:
39
+ rx = re.compile(pattern)
40
+ except re.error:
41
+ return f"Error: invalid regex pattern: {pattern}"
42
+ results = []
43
+ for f in p.rglob("*"):
44
+ if f.is_file():
45
+ try:
46
+ text = f.read_text(encoding="utf-8", errors="replace")
47
+ if rx.search(text):
48
+ results.append(str(f))
49
+ except (OSError, UnicodeDecodeError):
50
+ pass
51
+ return "\n".join(sorted(results)) if results else "No matches found"
52
+ else:
53
+ matches = sorted(p.rglob(pattern))
54
+ files = [str(m) for m in matches if m.is_file()]
55
+ return "\n".join(files) if files else "No matches found"
56
+ except Exception as e:
57
+ return f"Error searching: {e}"
58
+
59
+
60
+ register(SearchFilesTool())
@@ -0,0 +1,41 @@
1
+ """Write content to a file."""
2
+
3
+ from pathlib import Path
4
+
5
+ from devsper.tools.base import Tool
6
+ from devsper.tools.registry import register
7
+
8
+
9
+ class WriteFileTool(Tool):
10
+ """Write text content to a file. Overwrites if the file exists."""
11
+
12
+ name = "write_file"
13
+ description = "Write content to a file. Creates parent dirs if needed. Overwrites existing file."
14
+ input_schema = {
15
+ "type": "object",
16
+ "properties": {
17
+ "path": {"type": "string", "description": "Path to the file"},
18
+ "content": {"type": "string", "description": "Content to write"},
19
+ },
20
+ "required": ["path", "content"],
21
+ }
22
+
23
+ def run(self, **kwargs) -> str:
24
+ path = kwargs.get("path")
25
+ content = kwargs.get("content")
26
+ if not path or not isinstance(path, str):
27
+ return "Error: path must be a non-empty string"
28
+ if content is None:
29
+ return "Error: content is required"
30
+ if not isinstance(content, str):
31
+ content = str(content)
32
+ p = Path(path).resolve()
33
+ try:
34
+ p.parent.mkdir(parents=True, exist_ok=True)
35
+ p.write_text(content, encoding="utf-8")
36
+ return f"Wrote {len(content)} characters to {p}"
37
+ except Exception as e:
38
+ return f"Error writing file: {e}"
39
+
40
+
41
+ register(WriteFileTool())
@@ -0,0 +1,15 @@
1
+ """Flagship high-value tools: docproc corpus, research graph, repo map, experiment runner, distributed document analysis."""
2
+
3
+ from devsper.tools.flagship.docproc_corpus_pipeline import DocprocCorpusPipelineTool
4
+ from devsper.tools.flagship.research_graph_builder import ResearchGraphBuilderTool
5
+ from devsper.tools.flagship.repository_semantic_map import RepositorySemanticMapTool
6
+ from devsper.tools.flagship.swarm_experiment_runner import SwarmExperimentRunnerTool
7
+ from devsper.tools.flagship.distributed_document_analysis import DistributedDocumentAnalysisTool
8
+
9
+ __all__ = [
10
+ "DocprocCorpusPipelineTool",
11
+ "ResearchGraphBuilderTool",
12
+ "RepositorySemanticMapTool",
13
+ "SwarmExperimentRunnerTool",
14
+ "DistributedDocumentAnalysisTool",
15
+ ]
@@ -0,0 +1,77 @@
1
+ """Analyze hundreds of documents using swarm parallelism: batch → swarm tasks → aggregate insights."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from unittest.mock import patch
6
+
7
+ from devsper.tools.base import Tool
8
+ from devsper.tools.registry import register
9
+ from devsper.types.task import Task
10
+ from devsper.swarm.scheduler import Scheduler
11
+ from devsper.swarm.executor import Executor
12
+ from devsper.agents.agent import Agent
13
+ from devsper.utils.event_logger import EventLog
14
+ from devsper.tools.documents._docproc import run_docproc_to_markdown, DOCPROC_EXTENSIONS
15
+
16
+
17
+ class DistributedDocumentAnalysisTool(Tool):
18
+ """
19
+ Analyze many documents using swarm parallelism: split into batches, spawn swarm tasks,
20
+ collect summaries, aggregate into a single research report.
21
+ """
22
+
23
+ name = "distributed_document_analysis"
24
+ description = "Analyze hundreds of documents using swarm parallelism; returns aggregated research report."
25
+ input_schema = {
26
+ "type": "object",
27
+ "properties": {
28
+ "documents": {
29
+ "type": "array",
30
+ "items": {"type": "string"},
31
+ "description": "List of document paths to analyze",
32
+ },
33
+ },
34
+ "required": ["documents"],
35
+ }
36
+
37
+ def run(self, **kwargs) -> str:
38
+ documents = kwargs.get("documents")
39
+ if not documents or not isinstance(documents, list):
40
+ return "Error: documents must be a non-empty list of paths"
41
+ paths = [p for p in documents if isinstance(p, str) and p.strip()][:30]
42
+
43
+ tasks = []
44
+ for i, path in enumerate(paths):
45
+ task_id = f"doc_{i}"
46
+ deps = [f"doc_{i - 1}"] if i > 0 else []
47
+ tasks.append(Task(id=task_id, description=f"Summarize the document at: {path}", dependencies=deps))
48
+
49
+ scheduler = Scheduler()
50
+ scheduler.add_tasks(tasks)
51
+ log = EventLog()
52
+
53
+ def _mock_generate(model_name: str, prompt: str) -> str:
54
+ for p in paths:
55
+ if p in prompt:
56
+ content, _ = run_docproc_to_markdown(p)
57
+ if content:
58
+ return (content[:300] + "...") if len(content) > 300 else content
59
+ return f"Summary of document at {p} (no content extracted)."
60
+ return "Summary unavailable."
61
+
62
+ with patch("devsper.agents.agent.generate", side_effect=_mock_generate):
63
+ agent = Agent(model_name="mock", event_log=log)
64
+ executor = Executor(scheduler=scheduler, agent=agent, worker_count=4, event_log=log)
65
+ executor.run_sync()
66
+
67
+ results = scheduler.get_results()
68
+ summaries = [results.get(f"doc_{i}", "") for i in range(len(paths))]
69
+ aggregated = {
70
+ "total_documents": len(paths),
71
+ "summaries": [{"path": p, "summary": s[:500]} for p, s in zip(paths, summaries)],
72
+ "insights": f"Processed {len(paths)} documents with swarm parallelism. Total summaries: {len(summaries)}.",
73
+ }
74
+ return json.dumps(aggregated, indent=2)
75
+
76
+
77
+ register(DistributedDocumentAnalysisTool())
@@ -0,0 +1,91 @@
1
+ """Convert a directory of PDFs/DOCX/PPTX into a structured research corpus (discover → extract → markdown → sections → JSON)."""
2
+
3
+ import json
4
+ import re
5
+ from pathlib import Path
6
+
7
+ from devsper.tools.base import Tool
8
+ from devsper.tools.registry import register
9
+ from devsper.tools.documents._docproc import run_docproc_to_markdown, DOCPROC_EXTENSIONS
10
+
11
+
12
+ def _extract_sections(markdown: str) -> list[dict]:
13
+ """Extract sections from markdown (headers and following content)."""
14
+ sections = []
15
+ current = {"title": "", "content": "", "word_count": 0}
16
+ for line in markdown.splitlines():
17
+ if line.startswith("#"):
18
+ if current["title"] or current["content"]:
19
+ current["word_count"] = len(current["content"].split())
20
+ sections.append(current)
21
+ level = len(line) - len(line.lstrip("#"))
22
+ title = line.lstrip("#").strip()
23
+ current = {"title": title, "content": "", "word_count": 0}
24
+ else:
25
+ current["content"] = (current["content"] + "\n" + line).strip()
26
+ if current["title"] or current["content"]:
27
+ current["word_count"] = len(current["content"].split())
28
+ sections.append(current)
29
+ return sections
30
+
31
+
32
+ def _extract_citations(text: str) -> list[str]:
33
+ """Heuristic citation extraction."""
34
+ refs = []
35
+ refs.extend(re.findall(r"\[\d+(?:\s*[-–,]\s*\d+)*\]", text))
36
+ refs.extend(re.findall(r"\([A-Z][a-z]+(?:\s+et\s+al\.?)?,?\s*\d{4}\)", text))
37
+ return list(dict.fromkeys(refs))
38
+
39
+
40
+ class DocprocCorpusPipelineTool(Tool):
41
+ """
42
+ Convert a directory of PDF/DOCX/PPTX into a structured research dataset:
43
+ discover files → docproc extraction → markdown → sections → structured JSON corpus.
44
+ """
45
+
46
+ name = "docproc_corpus_pipeline"
47
+ description = "Convert a directory of PDFs/DOCX/PPTX into a structured research dataset (markdown, sections, word counts, citations)."
48
+ input_schema = {
49
+ "type": "object",
50
+ "properties": {"directory": {"type": "string", "description": "Path to directory containing documents"}},
51
+ "required": ["directory"],
52
+ }
53
+
54
+ def run(self, **kwargs) -> str:
55
+ directory = kwargs.get("directory")
56
+ if not directory or not isinstance(directory, str):
57
+ return "Error: directory must be a non-empty string"
58
+ root = Path(directory).resolve()
59
+ if not root.exists() or not root.is_dir():
60
+ return f"Error: directory not found: {directory}"
61
+
62
+ files = []
63
+ for ext in DOCPROC_EXTENSIONS:
64
+ files.extend(root.rglob(f"*{ext}"))
65
+ files = [f for f in files if f.is_file()][:50]
66
+
67
+ corpus = []
68
+ for path in files:
69
+ content, err = run_docproc_to_markdown(str(path))
70
+ if err:
71
+ corpus.append({"path": str(path.name), "error": err, "title": path.stem, "sections": [], "word_count": 0, "citations": []})
72
+ continue
73
+ md = content or ""
74
+ sections = _extract_sections(md)
75
+ citations = _extract_citations(md)
76
+ word_count = sum(s.get("word_count", 0) for s in sections) or len(md.split())
77
+ title = path.stem
78
+ if sections and sections[0].get("title"):
79
+ title = sections[0]["title"][:200]
80
+ corpus.append({
81
+ "title": title,
82
+ "path": str(path.name),
83
+ "sections": [{"title": s["title"], "word_count": s["word_count"]} for s in sections],
84
+ "word_count": word_count,
85
+ "citations": citations[:30],
86
+ })
87
+
88
+ return json.dumps({"documents": corpus, "total_files": len(files)}, indent=2)
89
+
90
+
91
+ register(DocprocCorpusPipelineTool())
@@ -0,0 +1,99 @@
1
+ """Generate a semantic architecture map of a codebase: modules, dependencies, entrypoints, summary."""
2
+
3
+ import ast
4
+ import json
5
+ from pathlib import Path
6
+
7
+ from devsper.tools.base import Tool
8
+ from devsper.tools.registry import register
9
+
10
+
11
+ class RepositorySemanticMapTool(Tool):
12
+ """
13
+ Generate a semantic architecture map of a codebase: scan files, parse AST,
14
+ extract modules, build dependency graph, summarize responsibilities.
15
+ Output: modules, dependencies, entrypoints, architecture_summary.
16
+ """
17
+
18
+ name = "repository_semantic_map"
19
+ description = "Generate a semantic architecture map of a codebase: modules, dependencies, entrypoints, architecture_summary."
20
+ input_schema = {
21
+ "type": "object",
22
+ "properties": {"repo_path": {"type": "string", "description": "Path to repository root"}},
23
+ "required": ["repo_path"],
24
+ }
25
+
26
+ def _imports(self, p: Path, root: Path) -> list[str]:
27
+ rel = str(p.relative_to(root)).replace("\\", "/").replace(".py", "").replace("/", ".")
28
+ imports = []
29
+ try:
30
+ tree = ast.parse(p.read_text(encoding="utf-8", errors="replace"))
31
+ for node in ast.walk(tree):
32
+ if isinstance(node, ast.Import):
33
+ for alias in node.names:
34
+ imports.append(alias.name.split(".")[0])
35
+ elif isinstance(node, ast.ImportFrom):
36
+ if node.module:
37
+ imports.append(node.module.split(".")[0])
38
+ except (SyntaxError, OSError):
39
+ pass
40
+ return list(dict.fromkeys(imports))
41
+
42
+ def _responsibility(self, p: Path) -> str:
43
+ try:
44
+ tree = ast.parse(p.read_text(encoding="utf-8", errors="replace"))
45
+ doc = ast.get_docstring(tree)
46
+ if doc:
47
+ return doc.split("\n")[0][:120].strip()
48
+ first = p.read_text(encoding="utf-8", errors="replace").strip().split("\n")
49
+ for line in first[:5]:
50
+ if line.strip().startswith("class ") or line.strip().startswith("def "):
51
+ return line.strip()[:80]
52
+ except (SyntaxError, OSError):
53
+ pass
54
+ return ""
55
+
56
+ def run(self, **kwargs) -> str:
57
+ repo_path = kwargs.get("repo_path")
58
+ if not repo_path or not isinstance(repo_path, str):
59
+ return "Error: repo_path must be a non-empty string"
60
+ root = Path(repo_path).resolve()
61
+ if not root.exists() or not root.is_dir():
62
+ return f"Error: repo_path not found: {repo_path}"
63
+
64
+ modules = []
65
+ dependencies = []
66
+ entrypoints = []
67
+ max_files = 150
68
+
69
+ py_files = list(root.rglob("*.py"))
70
+ for p in py_files[:max_files]:
71
+ if not p.is_file():
72
+ continue
73
+ rel = str(p.relative_to(root)).replace("\\", "/")
74
+ mod = rel.replace(".py", "").replace("/", ".")
75
+ if "__pycache__" in mod or mod.startswith("."):
76
+ continue
77
+ resp = self._responsibility(p)
78
+ modules.append({"module": mod, "file": rel, "responsibility": resp})
79
+ for imp in self._imports(p, root):
80
+ if imp and imp != mod.split(".")[0]:
81
+ dependencies.append({"from": mod, "to": imp})
82
+ if "main" in p.name or "__main__" in rel or "run" in p.stem.lower():
83
+ entrypoints.append(mod)
84
+
85
+ entrypoints = list(dict.fromkeys(entrypoints))[:20]
86
+ architecture_summary = (
87
+ f"Modules: {len(modules)}. Dependencies: {len(dependencies)}. "
88
+ f"Entrypoints: {', '.join(entrypoints[:5]) or 'none detected'}."
89
+ )
90
+
91
+ return json.dumps({
92
+ "modules": modules[:80],
93
+ "dependencies": dependencies[:200],
94
+ "entrypoints": entrypoints,
95
+ "architecture_summary": architecture_summary,
96
+ }, indent=2)
97
+
98
+
99
+ register(RepositorySemanticMapTool())
@@ -0,0 +1,111 @@
1
+ """Build a knowledge graph from research documents: entities, citations, methods, datasets."""
2
+
3
+ import json
4
+ import re
5
+ from devsper.tools.base import Tool
6
+ from devsper.tools.registry import register
7
+
8
+ ENTITY_PATTERN = re.compile(r"\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b")
9
+ CITE_PATTERN = re.compile(r"\[[\d\s,–-]+\]|\([A-Z][a-z]+(?:\s+et\s+al\.?)?,?\s*\d{4}\)")
10
+ METHOD_PATTERN = re.compile(r"\b(?:method|approach|algorithm|model|framework|technique)s?\s+[:\s]+([^.!?\n]{10,80})", re.I)
11
+ DATASET_PATTERN = re.compile(r"\b(?:dataset|corpus|benchmark)s?\s+[:\s]*([A-Za-z0-9\-]+(?:\s+[A-Za-z0-9\-]+)*)", re.I)
12
+
13
+
14
+ def _extract_entities(text: str, max_n: int = 100) -> list[str]:
15
+ candidates = ENTITY_PATTERN.findall(text)
16
+ seen = set()
17
+ out = []
18
+ for c in candidates:
19
+ c = c.strip()
20
+ if len(c) > 2 and c not in seen and not c.isdigit():
21
+ seen.add(c)
22
+ out.append(c)
23
+ if len(out) >= max_n:
24
+ break
25
+ return out
26
+
27
+
28
+ def _extract_citations(text: str, max_n: int = 50) -> list[str]:
29
+ return list(dict.fromkeys(CITE_PATTERN.findall(text)))[:max_n]
30
+
31
+
32
+ def _extract_methods(text: str, max_n: int = 30) -> list[str]:
33
+ return [m.group(1).strip()[:80] for m in METHOD_PATTERN.finditer(text)][:max_n]
34
+
35
+
36
+ def _extract_datasets(text: str, max_n: int = 20) -> list[str]:
37
+ return [m.group(1).strip() for m in DATASET_PATTERN.finditer(text)][:max_n]
38
+
39
+
40
+ class ResearchGraphBuilderTool(Tool):
41
+ """
42
+ Build a graph of research knowledge from documents: entities, citations, methods, datasets.
43
+ Output: nodes, edges, entity types (knowledge graph JSON).
44
+ """
45
+
46
+ name = "research_graph_builder"
47
+ description = "Build a knowledge graph from research documents: extract entities, citations, methods, datasets."
48
+ input_schema = {
49
+ "type": "object",
50
+ "properties": {
51
+ "documents": {
52
+ "type": "array",
53
+ "items": {"type": "string"},
54
+ "description": "List of document texts to analyze",
55
+ },
56
+ },
57
+ "required": ["documents"],
58
+ }
59
+
60
+ def run(self, **kwargs) -> str:
61
+ documents = kwargs.get("documents")
62
+ if not documents or not isinstance(documents, list):
63
+ return "Error: documents must be a non-empty list of strings"
64
+ texts = [d for d in documents if isinstance(d, str) and d.strip()][:50]
65
+ if not texts:
66
+ return "Error: no valid document strings provided"
67
+
68
+ nodes = []
69
+ edges = []
70
+ entity_types = {}
71
+
72
+ for i, text in enumerate(texts):
73
+ doc_id = f"doc_{i}"
74
+ nodes.append({"id": doc_id, "type": "document"})
75
+ entities = _extract_entities(text)
76
+ for e in entities:
77
+ nid = f"entity_{e.replace(' ', '_')[:40]}"
78
+ if not any(n["id"] == nid for n in nodes):
79
+ nodes.append({"id": nid, "type": "entity", "label": e})
80
+ entity_types[nid] = "entity"
81
+ edges.append({"source": doc_id, "target": nid, "type": "mentions"})
82
+
83
+ for c in _extract_citations(text):
84
+ cid = f"cite_{hash(c) % 10**8}"
85
+ nodes.append({"id": cid, "type": "citation", "label": c[:60]})
86
+ edges.append({"source": doc_id, "target": cid, "type": "cites"})
87
+
88
+ for m in _extract_methods(text):
89
+ mid = f"method_{hash(m) % 10**8}"
90
+ nodes.append({"id": mid, "type": "method", "label": m[:80]})
91
+ entity_types[mid] = "method"
92
+ edges.append({"source": doc_id, "target": mid, "type": "describes_method"})
93
+
94
+ for d in _extract_datasets(text):
95
+ did = f"dataset_{d.replace(' ', '_')[:30]}"
96
+ if not any(n["id"] == did for n in nodes):
97
+ nodes.append({"id": did, "type": "dataset", "label": d})
98
+ entity_types[did] = "dataset"
99
+ edges.append({"source": doc_id, "target": did, "type": "uses_dataset"})
100
+
101
+ by_id = {n["id"]: n for n in nodes}
102
+ nodes = list(by_id.values())
103
+
104
+ return json.dumps({
105
+ "nodes": nodes,
106
+ "edges": edges,
107
+ "entity_types": entity_types,
108
+ }, indent=2)
109
+
110
+
111
+ register(ResearchGraphBuilderTool())
@@ -0,0 +1,86 @@
1
+ """Run parameter sweeps or experiments using the swarm runtime; executor divides runs across workers."""
2
+
3
+ import json
4
+ from devsper.tools.base import Tool
5
+ from devsper.tools.registry import register
6
+ from devsper.types.task import Task
7
+ from devsper.swarm.scheduler import Scheduler
8
+ from devsper.swarm.executor import Executor
9
+ from devsper.agents.agent import Agent
10
+ from devsper.utils.event_logger import EventLog
11
+
12
+
13
+ def _run_experiment_once(
14
+ task_description: str,
15
+ worker_model: str,
16
+ worker_count: int,
17
+ ) -> float:
18
+ """Run a single swarm-style run and return a numeric metric (e.g. result length sum)."""
19
+ from unittest.mock import patch
20
+ tasks = [
21
+ Task(id=f"run_1", description=task_description, dependencies=[]),
22
+ ]
23
+ scheduler = Scheduler()
24
+ scheduler.add_tasks(tasks)
25
+ log = EventLog()
26
+ with patch("devsper.agents.agent.generate", return_value="Experiment result output."):
27
+ agent = Agent(model_name=worker_model, event_log=log)
28
+ executor = Executor(scheduler=scheduler, agent=agent, worker_count=worker_count, event_log=log)
29
+ executor.run_sync()
30
+ results = scheduler.get_results()
31
+ total = sum(len(r or "") for r in results.values()) or 1.0
32
+ return float(total)
33
+
34
+
35
+ class SwarmExperimentRunnerTool(Tool):
36
+ """
37
+ Run parameter sweeps or experiments using the swarm runtime.
38
+ Executor divides runs across workers. Output: mean, std, best configuration.
39
+ """
40
+
41
+ name = "swarm_experiment_runner"
42
+ description = "Run parameter sweeps or experiments using the swarm runtime; returns experiment statistics (mean, std, best)."
43
+ input_schema = {
44
+ "type": "object",
45
+ "properties": {
46
+ "parameters": {"type": "object", "description": "Experiment parameters (e.g. task description, config)"},
47
+ "runs": {"type": "integer", "description": "Number of runs (default 3)"},
48
+ },
49
+ "required": ["parameters"],
50
+ }
51
+
52
+ def run(self, **kwargs) -> str:
53
+ parameters = kwargs.get("parameters")
54
+ runs = kwargs.get("runs", 3)
55
+ if not isinstance(parameters, dict):
56
+ return "Error: parameters must be an object"
57
+ if not isinstance(runs, int) or runs < 1:
58
+ runs = 3
59
+ runs = min(runs, 20)
60
+
61
+ task_description = parameters.get("task", parameters.get("prompt", "Run experiment."))
62
+ if not isinstance(task_description, str):
63
+ task_description = str(parameters)[:500]
64
+
65
+ metrics = []
66
+ for _ in range(runs):
67
+ m = _run_experiment_once(task_description, worker_model="mock", worker_count=2)
68
+ metrics.append(m)
69
+
70
+ n = len(metrics)
71
+ mean = sum(metrics) / n
72
+ variance = sum((x - mean) ** 2 for x in metrics) / n if n else 0
73
+ std = variance ** 0.5
74
+ best_idx = max(range(n), key=lambda i: metrics[i])
75
+ best_config = {"run_index": best_idx, "metric": metrics[best_idx]}
76
+
77
+ return json.dumps({
78
+ "mean": round(mean, 4),
79
+ "std": round(std, 4),
80
+ "runs": n,
81
+ "best_configuration": best_config,
82
+ "metrics": [round(x, 4) for x in metrics],
83
+ }, indent=2)
84
+
85
+
86
+ register(SwarmExperimentRunnerTool())
@@ -0,0 +1,10 @@
1
+ """Knowledge pipeline tools: corpus, topics, citations, knowledge graphs, timelines."""
2
+
3
+ from devsper.tools.knowledge.corpus_builder import CorpusBuilderTool
4
+ from devsper.tools.knowledge.document_corpus_summary import DocumentCorpusSummaryTool
5
+ from devsper.tools.knowledge.document_topic_extractor import DocumentTopicExtractorTool
6
+ from devsper.tools.knowledge.citation_graph_builder import CitationGraphBuilderTool
7
+ from devsper.tools.knowledge.knowledge_graph_extractor import KnowledgeGraphExtractorTool
8
+ from devsper.tools.knowledge.concept_frequency_analyzer import ConceptFrequencyAnalyzerTool
9
+ from devsper.tools.knowledge.timeline_extractor import TimelineExtractorTool
10
+ from devsper.tools.knowledge.cross_document_entity_linker import CrossDocumentEntityLinkerTool