deepdoc 3.0.0__tar.gz → 3.3.0__tar.gz
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.
- {deepdoc-3.0.0 → deepdoc-3.3.0}/PKG-INFO +9 -5
- {deepdoc-3.0.0 → deepdoc-3.3.0}/README.md +3 -4
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/__init__.py +1 -1
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/answer_mixin.py +3 -3
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/deep_research.py +33 -3
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/retrieval_mixin.py +3 -1
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/routes.py +13 -86
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/scaffold.py +4 -8
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/service.py +39 -98
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/settings.py +5 -6
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/cli.py +5 -5
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/config.py +5 -6
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/__init__.py +0 -2
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/generation.py +0 -8
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/post_processors.py +0 -96
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/pipeline_v2.py +7 -9
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/heuristics.py +0 -65
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/nav_shaping.py +18 -47
- deepdoc-3.3.0/deepdoc/site/builder/mkdocs_builder.py +2148 -0
- deepdoc-3.3.0/deepdoc/site/builder/vendor/highlight.min.js +1232 -0
- deepdoc-3.3.0/deepdoc/site/builder/vendor/hljs-theme.css +10 -0
- deepdoc-3.3.0/deepdoc/site/builder/vendor/markdown-it.min.js +2 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/PKG-INFO +9 -5
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/SOURCES.txt +3 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/requires.txt +6 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/pyproject.toml +12 -1
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_config.py +6 -6
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_query.py +20 -18
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_cli_serve.py +1 -1
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_mkdocs_builder.py +57 -49
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_planner_granularity.py +137 -3
- deepdoc-3.0.0/deepdoc/site/builder/mkdocs_builder.py +0 -560
- {deepdoc-3.0.0 → deepdoc-3.3.0}/LICENSE +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/__main__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/benchmark_v2.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/call_graph.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/changelog_writer.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/chunker.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/constants.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/docs_summary.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/embeddings.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/indexer.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/linking.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/live_fallback_mixin.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/persistence.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/providers.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/source_archive.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/symbol_index.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/chatbot/types.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/consistency.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/evidence.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/generator/validation.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/llm/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/llm/client.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/llm/json_utils.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/llm/litellm_compat.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/llm/retry.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/manifest.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/openapi.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/api_detector.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/base.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/go_parser.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/js_ts_parser.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/php_parser.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/python_parser.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/registry.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/base.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/common.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/detector.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/django.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/express.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/falcon.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/fastify.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/go.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/js_shared.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/laravel.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/nestjs.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/python_shared.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/registry.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/routes/repo_resolver.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/parser/vue_parser.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/persistence_v2.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/bucket_injection.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/bucket_refinement.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/common.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/endpoint_refs.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/engine.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/flow_candidates.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/specializations.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/topology.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/planner/utils.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/bucket_types.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/page_types.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/selectors.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/system.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/prompts/update.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/py.typed +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/artifacts.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/clustering.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/common.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/database.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/endpoints.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/integrations.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/runtime.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/scanner/utils.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/site/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/site/builder/__init__.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/site/builder/common.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/site/builder/mdx_utils.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/smart_update_v2.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/source_metadata.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/updater_v2.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc/v2_models.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/dependency_links.txt +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/entry_points.txt +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/deepdoc.egg-info/top_level.txt +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/setup.cfg +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_benchmark_scorecard.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_call_graph.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_changelog.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_embeddings.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_eval.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_index.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_persistence.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_providers.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_relationship.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_scaffold.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_chatbot_source_archive.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_classify.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_cli_generate.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_cli_update.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_consistency_pass.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_flow_candidates.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_framework_fixtures.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_framework_support.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_generation_evidence.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_internal_docs_metadata.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_litellm_compat.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_llm_json_utils.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_llm_retry.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_parallel_pipeline.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_parser_ranges.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_planner_consolidation.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_route_registry.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_runtime_scan.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_smart_update.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_stale.py +0 -0
- {deepdoc-3.0.0 → deepdoc-3.3.0}/tests/test_state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepdoc
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Auto-generate beautiful docs from any codebase
|
|
5
5
|
Author: Pranav Kumar
|
|
6
6
|
License: MIT
|
|
@@ -35,6 +35,11 @@ Requires-Dist: fastapi>=0.115; extra == "chatbot"
|
|
|
35
35
|
Requires-Dist: uvicorn>=0.30; extra == "chatbot"
|
|
36
36
|
Requires-Dist: httpx>=0.27; extra == "chatbot"
|
|
37
37
|
Requires-Dist: fastembed>=0.3.0; extra == "chatbot"
|
|
38
|
+
Provides-Extra: site
|
|
39
|
+
Requires-Dist: mkdocs>=1.6; extra == "site"
|
|
40
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "site"
|
|
41
|
+
Requires-Dist: pymdown-extensions>=10.0; extra == "site"
|
|
42
|
+
Requires-Dist: mkdocs-swagger-ui-tag>=0.6; extra == "site"
|
|
38
43
|
Dynamic: license-file
|
|
39
44
|
|
|
40
45
|
# DeepDoc
|
|
@@ -129,14 +134,13 @@ pip install click litellm gitpython rich pyyaml jinja2
|
|
|
129
134
|
pip install -e . --no-deps
|
|
130
135
|
```
|
|
131
136
|
|
|
132
|
-
To preview or deploy the generated site you also need **MkDocs Material** (pure Python — no Node.js):
|
|
137
|
+
To preview or deploy the generated site you also need **MkDocs Material** (pure Python — no Node.js). Install the `site` extra:
|
|
133
138
|
|
|
134
139
|
```bash
|
|
135
|
-
pip install mkdocs-material
|
|
136
|
-
pip install mkdocs-swagger-ui-tag # only when your repo has an OpenAPI/Swagger spec
|
|
140
|
+
pip install 'deepdoc[site]' # mkdocs-material + pymdown-extensions + mkdocs-swagger-ui-tag
|
|
137
141
|
```
|
|
138
142
|
|
|
139
|
-
`deepdoc serve` / `deepdoc deploy` will tell you
|
|
143
|
+
`deepdoc serve` / `deepdoc deploy` will tell you to run `pip install 'deepdoc[site]'` if MkDocs is missing.
|
|
140
144
|
|
|
141
145
|
### Verify installation
|
|
142
146
|
|
|
@@ -90,14 +90,13 @@ pip install click litellm gitpython rich pyyaml jinja2
|
|
|
90
90
|
pip install -e . --no-deps
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
To preview or deploy the generated site you also need **MkDocs Material** (pure Python — no Node.js):
|
|
93
|
+
To preview or deploy the generated site you also need **MkDocs Material** (pure Python — no Node.js). Install the `site` extra:
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
|
-
pip install mkdocs-material
|
|
97
|
-
pip install mkdocs-swagger-ui-tag # only when your repo has an OpenAPI/Swagger spec
|
|
96
|
+
pip install 'deepdoc[site]' # mkdocs-material + pymdown-extensions + mkdocs-swagger-ui-tag
|
|
98
97
|
```
|
|
99
98
|
|
|
100
|
-
`deepdoc serve` / `deepdoc deploy` will tell you
|
|
99
|
+
`deepdoc serve` / `deepdoc deploy` will tell you to run `pip install 'deepdoc[site]'` if MkDocs is missing.
|
|
101
100
|
|
|
102
101
|
### Verify installation
|
|
103
102
|
|
|
@@ -668,15 +668,15 @@ class AnswerMixin:
|
|
|
668
668
|
reason=str(row.get("reason", "") or ""),
|
|
669
669
|
)
|
|
670
670
|
)
|
|
671
|
-
if mode == "
|
|
672
|
-
diagnostics.warnings.append("No source/config evidence was available for
|
|
671
|
+
if mode == "deep" and not evidence:
|
|
672
|
+
diagnostics.warnings.append("No source/config evidence was available for deep mode.")
|
|
673
673
|
return evidence, diagnostics
|
|
674
674
|
|
|
675
675
|
def _evidence_role(self, row: dict[str, Any], *, source_kind: str, mode: str) -> str:
|
|
676
676
|
reason = str(row.get("reason", "") or "")
|
|
677
677
|
if source_kind == "config" or row.get("artifact_type"):
|
|
678
678
|
return "config"
|
|
679
|
-
if reason in {"investigation_step", "research_step"} or mode == "
|
|
679
|
+
if reason in {"investigation_step", "research_step"} or mode == "deep":
|
|
680
680
|
return "implementation"
|
|
681
681
|
if reason == "mentioned_source":
|
|
682
682
|
return "supporting"
|
|
@@ -426,7 +426,7 @@ class DeepResearcher:
|
|
|
426
426
|
step: int,
|
|
427
427
|
) -> ResearchStep:
|
|
428
428
|
"""Run a Tool-Using ReAct loop for a single sub-question."""
|
|
429
|
-
max_iterations =
|
|
429
|
+
max_iterations = 5
|
|
430
430
|
chunks = self._retrieve_for_question(
|
|
431
431
|
question,
|
|
432
432
|
history,
|
|
@@ -468,8 +468,9 @@ class DeepResearcher:
|
|
|
468
468
|
"You have access to the following initial evidence chunks from the codebase.\n\n"
|
|
469
469
|
"If the evidence is sufficient, provide your final answer in plain text.\n"
|
|
470
470
|
"If you need to explore the codebase further, you can use the following tools by outputting a JSON object and NOTHING else:\n"
|
|
471
|
-
'1.
|
|
472
|
-
'2.
|
|
471
|
+
'1. search: `{"action": "search", "query": "what you want to find"}` — semantic search over the code index\n'
|
|
472
|
+
'2. read_file: `{"action": "read_file", "path": "file/path.py", "start": 10, "end": 50}`\n'
|
|
473
|
+
'3. grep: `{"action": "grep", "pattern": "def main"}`\n\n'
|
|
473
474
|
"Answer ONLY based on evidence. Prefer a detailed, implementation-level walkthrough.\n\n"
|
|
474
475
|
"## STRICT GROUNDING RULES\n"
|
|
475
476
|
"- Do NOT invent, fabricate, or hallucinate any code, function names, class names, "
|
|
@@ -632,6 +633,35 @@ class DeepResearcher:
|
|
|
632
633
|
results.append("... [truncated due to length]")
|
|
633
634
|
return "\n".join(results)
|
|
634
635
|
|
|
636
|
+
elif action == "search":
|
|
637
|
+
query = str(tool_call.get("query", "")).strip()
|
|
638
|
+
if not query or len(query) < 3:
|
|
639
|
+
return "Error: search requires a non-empty 'query' (min 3 characters)."
|
|
640
|
+
try:
|
|
641
|
+
retrieve_context = getattr(self.service, "retrieve_context", None)
|
|
642
|
+
if not callable(retrieve_context):
|
|
643
|
+
return "Error: search tool unavailable."
|
|
644
|
+
context = retrieve_context(query, [], mode="fast")
|
|
645
|
+
code_hits = context.get("code_hits", [])[:8]
|
|
646
|
+
if not code_hits:
|
|
647
|
+
return f"No code matches found for '{query}'."
|
|
648
|
+
parts = []
|
|
649
|
+
for i, hit in enumerate(code_hits, 1):
|
|
650
|
+
record = getattr(hit, "record", hit)
|
|
651
|
+
source = (
|
|
652
|
+
getattr(record, "file_path", None)
|
|
653
|
+
or getattr(record, "doc_path", None)
|
|
654
|
+
or "unknown"
|
|
655
|
+
)
|
|
656
|
+
text = getattr(record, "text", "")[:1600]
|
|
657
|
+
score = round(float(getattr(hit, "score", 0.0)), 3)
|
|
658
|
+
parts.append(f"[{i}] {source} (score={score}):\n{text}")
|
|
659
|
+
if source not in sources_used:
|
|
660
|
+
sources_used.append(source)
|
|
661
|
+
return "\n\n".join(parts)
|
|
662
|
+
except Exception as e:
|
|
663
|
+
return f"Error: Search failed - {e}"
|
|
664
|
+
|
|
635
665
|
return f"Error: Unknown action '{action}'"
|
|
636
666
|
|
|
637
667
|
def _synthesise(
|
|
@@ -780,8 +780,10 @@ class RetrievalMixin:
|
|
|
780
780
|
source_kind = record.source_kind or ""
|
|
781
781
|
if source_kind == "product":
|
|
782
782
|
priority += 0.8 if supporting_requested else 2.5
|
|
783
|
-
elif source_kind in {"config", "
|
|
783
|
+
elif source_kind in {"config", "ops", "tooling"}:
|
|
784
784
|
priority += 1.2
|
|
785
|
+
elif source_kind == "docs":
|
|
786
|
+
priority += 0.2
|
|
785
787
|
elif source_kind in {"test", "fixture", "example", "generated"}:
|
|
786
788
|
priority += 4.5 if supporting_requested else -1.0
|
|
787
789
|
|
|
@@ -27,14 +27,8 @@ class QueryRequest(BaseModel):
|
|
|
27
27
|
return v
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
31
|
-
"""Incoming deep
|
|
32
|
-
|
|
33
|
-
max_rounds: int = Field(default=3, ge=1, le=6)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class CodeDeepRequest(QueryRequest):
|
|
37
|
-
"""Incoming code-deep payload."""
|
|
30
|
+
class DeepRequest(QueryRequest):
|
|
31
|
+
"""Incoming deep mode payload."""
|
|
38
32
|
|
|
39
33
|
max_rounds: int = Field(default=4, ge=1, le=8)
|
|
40
34
|
|
|
@@ -73,10 +67,10 @@ def create_fastapi_app(repo_root: Path, cfg: dict[str, Any]):
|
|
|
73
67
|
},
|
|
74
68
|
)
|
|
75
69
|
|
|
76
|
-
@app.post("/deep
|
|
77
|
-
def
|
|
70
|
+
@app.post("/deep")
|
|
71
|
+
def deep(request: DeepRequest = Body(...)) -> dict[str, Any]:
|
|
78
72
|
try:
|
|
79
|
-
return service.
|
|
73
|
+
return service.deep(
|
|
80
74
|
request.question,
|
|
81
75
|
request.history,
|
|
82
76
|
max_rounds=request.max_rounds,
|
|
@@ -85,7 +79,7 @@ def create_fastapi_app(repo_root: Path, cfg: dict[str, Any]):
|
|
|
85
79
|
return JSONResponse(
|
|
86
80
|
status_code=500,
|
|
87
81
|
content={
|
|
88
|
-
"error": "
|
|
82
|
+
"error": "chatbot_deep_failed",
|
|
89
83
|
"detail": str(exc),
|
|
90
84
|
},
|
|
91
85
|
)
|
|
@@ -138,96 +132,29 @@ def create_fastapi_app(repo_root: Path, cfg: dict[str, Any]):
|
|
|
138
132
|
},
|
|
139
133
|
)
|
|
140
134
|
|
|
141
|
-
@app.post("/deep
|
|
142
|
-
def
|
|
143
|
-
|
|
135
|
+
@app.post("/deep/stream")
|
|
136
|
+
def deep_stream(request: DeepRequest = Body(...)):
|
|
137
|
+
events: queue.Queue[tuple[str, dict[str, Any]] | None] = queue.Queue()
|
|
144
138
|
|
|
145
139
|
def on_token(text: str) -> None:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def run() -> None:
|
|
149
|
-
try:
|
|
150
|
-
result = service.deep_research(
|
|
151
|
-
request.question,
|
|
152
|
-
request.history,
|
|
153
|
-
max_rounds=request.max_rounds,
|
|
154
|
-
token_callback=on_token,
|
|
155
|
-
)
|
|
156
|
-
tokens.put(("result", result))
|
|
157
|
-
except Exception as exc:
|
|
158
|
-
tokens.put(("error", {"error": "chatbot_deep_research_failed", "detail": str(exc)}))
|
|
159
|
-
finally:
|
|
160
|
-
tokens.put(("done", {"status": "done"}))
|
|
161
|
-
tokens.put(None)
|
|
162
|
-
|
|
163
|
-
thread = threading.Thread(target=run, daemon=True)
|
|
164
|
-
thread.start()
|
|
165
|
-
|
|
166
|
-
def event_stream():
|
|
167
|
-
while True:
|
|
168
|
-
try:
|
|
169
|
-
item = tokens.get(timeout=30)
|
|
170
|
-
except queue.Empty:
|
|
171
|
-
yield "event: ping\ndata: {}\n\n"
|
|
172
|
-
continue
|
|
173
|
-
if item is None:
|
|
174
|
-
break
|
|
175
|
-
event_name, payload = item
|
|
176
|
-
yield f"event: {event_name}\n"
|
|
177
|
-
yield f"data: {json.dumps(payload)}\n\n"
|
|
178
|
-
|
|
179
|
-
return StreamingResponse(
|
|
180
|
-
event_stream(),
|
|
181
|
-
media_type="text/event-stream",
|
|
182
|
-
headers={
|
|
183
|
-
"Cache-Control": "no-cache",
|
|
184
|
-
"Connection": "keep-alive",
|
|
185
|
-
"X-Accel-Buffering": "no",
|
|
186
|
-
},
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
@app.post("/code-deep")
|
|
190
|
-
def code_deep(request: CodeDeepRequest = Body(...)) -> dict[str, Any]:
|
|
191
|
-
try:
|
|
192
|
-
return service.code_deep(
|
|
193
|
-
request.question,
|
|
194
|
-
request.history,
|
|
195
|
-
max_rounds=request.max_rounds,
|
|
196
|
-
)
|
|
197
|
-
except Exception as exc:
|
|
198
|
-
return JSONResponse(
|
|
199
|
-
status_code=500,
|
|
200
|
-
content={
|
|
201
|
-
"error": "chatbot_code_deep_failed",
|
|
202
|
-
"detail": str(exc),
|
|
203
|
-
},
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
@app.post("/code-deep/stream")
|
|
207
|
-
def code_deep_stream(request: CodeDeepRequest = Body(...)):
|
|
208
|
-
events: queue.Queue[tuple[str, dict[str, Any]] | None] = queue.Queue()
|
|
140
|
+
events.put(("token", {"text": text}))
|
|
209
141
|
|
|
210
142
|
def emit(event: dict[str, Any]) -> None:
|
|
211
143
|
events.put(("trace", event))
|
|
212
144
|
|
|
213
145
|
def run() -> None:
|
|
214
146
|
try:
|
|
215
|
-
result = service.
|
|
147
|
+
result = service.deep(
|
|
216
148
|
request.question,
|
|
217
149
|
request.history,
|
|
218
150
|
max_rounds=request.max_rounds,
|
|
219
151
|
trace_callback=emit,
|
|
152
|
+
token_callback=on_token,
|
|
220
153
|
)
|
|
221
154
|
events.put(("result", result))
|
|
222
155
|
except Exception as exc:
|
|
223
156
|
events.put(
|
|
224
|
-
(
|
|
225
|
-
"error",
|
|
226
|
-
{
|
|
227
|
-
"error": "chatbot_code_deep_failed",
|
|
228
|
-
"detail": str(exc),
|
|
229
|
-
},
|
|
230
|
-
)
|
|
157
|
+
("error", {"error": "chatbot_deep_failed", "detail": str(exc)})
|
|
231
158
|
)
|
|
232
159
|
finally:
|
|
233
160
|
events.put(("done", {"status": "done"}))
|
|
@@ -63,16 +63,12 @@ def _app_py() -> str:
|
|
|
63
63
|
def _query():
|
|
64
64
|
return JSONResponse(status_code=503, content={"error": "startup_failed", "detail": _detail})
|
|
65
65
|
|
|
66
|
-
@app.post("/deep
|
|
67
|
-
def
|
|
66
|
+
@app.post("/deep")
|
|
67
|
+
def _deep():
|
|
68
68
|
return JSONResponse(status_code=503, content={"error": "startup_failed", "detail": _detail})
|
|
69
69
|
|
|
70
|
-
@app.post("/
|
|
71
|
-
def
|
|
72
|
-
return JSONResponse(status_code=503, content={"error": "startup_failed", "detail": _detail})
|
|
73
|
-
|
|
74
|
-
@app.post("/code-deep/stream")
|
|
75
|
-
def _code_deep_stream():
|
|
70
|
+
@app.post("/deep/stream")
|
|
71
|
+
def _deep_stream():
|
|
76
72
|
return JSONResponse(status_code=503, content={"error": "startup_failed", "detail": _detail})
|
|
77
73
|
"""
|
|
78
74
|
)
|
|
@@ -49,7 +49,7 @@ from .constants import (
|
|
|
49
49
|
)
|
|
50
50
|
from .live_fallback_mixin import LiveFallbackMixin
|
|
51
51
|
from .retrieval_mixin import RetrievalMixin
|
|
52
|
-
from .routes import create_fastapi_app, QueryRequest,
|
|
52
|
+
from .routes import create_fastapi_app, QueryRequest, DeepRequest
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
@@ -106,7 +106,7 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
106
106
|
):
|
|
107
107
|
logger.warning(
|
|
108
108
|
"Source archive empty or unreadable at %s while indexed corpora "
|
|
109
|
-
"exist. Live-fallback, evidence verification, and
|
|
109
|
+
"exist. Live-fallback, evidence verification, and deep mode file "
|
|
110
110
|
"inventory will be degraded. Run `deepdoc update` to rebuild.",
|
|
111
111
|
self.index_dir / "source_archive.json.gz",
|
|
112
112
|
)
|
|
@@ -446,46 +446,24 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
446
446
|
**self._workspace_defaults(),
|
|
447
447
|
}
|
|
448
448
|
|
|
449
|
-
def
|
|
449
|
+
def deep(
|
|
450
450
|
self,
|
|
451
451
|
question: str,
|
|
452
452
|
history: list[dict[str, str]] | None = None,
|
|
453
|
-
max_rounds: int =
|
|
453
|
+
max_rounds: int = 4,
|
|
454
454
|
*,
|
|
455
|
+
trace_callback: Callable[[dict[str, Any]], None] | None = None,
|
|
455
456
|
token_callback: "Callable[[str], None] | None" = None,
|
|
456
457
|
) -> dict[str, Any]:
|
|
457
|
-
"""Run
|
|
458
|
-
|
|
459
|
-
Returns a ResearchResult with a comprehensive answer and source citations.
|
|
460
|
-
Requires an LLM client to be configured (llm= at construction time or via settings).
|
|
461
|
-
|
|
462
|
-
Args:
|
|
463
|
-
question: The research question to answer.
|
|
464
|
-
max_rounds: Maximum number of sub-questions to explore.
|
|
458
|
+
"""Run an agentic deep research session over the codebase.
|
|
465
459
|
|
|
466
|
-
|
|
467
|
-
|
|
460
|
+
Decomposes the question into sub-questions, retrieves code-heavy evidence,
|
|
461
|
+
runs a tool-using ReAct loop (search / read_file / grep) for each, then
|
|
462
|
+
synthesises a comprehensive answer with source citations and a file inventory.
|
|
468
463
|
"""
|
|
469
|
-
|
|
470
|
-
_, response = self._run_research_mode(
|
|
471
|
-
question,
|
|
472
|
-
history,
|
|
473
|
-
mode="deep",
|
|
474
|
-
max_rounds=max_rounds,
|
|
475
|
-
top_k=max(8, retrieval_cfg.get("deep_research_top_k", 10)),
|
|
476
|
-
token_callback=token_callback,
|
|
477
|
-
)
|
|
478
|
-
return response
|
|
464
|
+
from .deep_research import DeepResearcher
|
|
479
465
|
|
|
480
|
-
|
|
481
|
-
self,
|
|
482
|
-
question: str,
|
|
483
|
-
history: list[dict[str, str]] | None = None,
|
|
484
|
-
max_rounds: int = 4,
|
|
485
|
-
*,
|
|
486
|
-
trace_callback: Callable[[dict[str, Any]], None] | None = None,
|
|
487
|
-
) -> dict[str, Any]:
|
|
488
|
-
retrieval_cfg = self._retrieval_profile("code_deep")
|
|
466
|
+
retrieval_cfg = self._retrieval_profile("deep")
|
|
489
467
|
trace: list[dict[str, Any]] = []
|
|
490
468
|
|
|
491
469
|
def emit(event: dict[str, Any]) -> None:
|
|
@@ -496,56 +474,19 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
496
474
|
if callable(callback):
|
|
497
475
|
callback(payload)
|
|
498
476
|
|
|
499
|
-
|
|
500
|
-
question,
|
|
501
|
-
history,
|
|
502
|
-
mode="code_deep",
|
|
503
|
-
max_rounds=max_rounds,
|
|
504
|
-
top_k=max(
|
|
505
|
-
10,
|
|
506
|
-
int(retrieval_cfg.get("code_deep_top_k", retrieval_cfg["top_k_code"])),
|
|
507
|
-
),
|
|
508
|
-
trace_callback=emit,
|
|
509
|
-
)
|
|
510
|
-
response["trace"] = trace
|
|
511
|
-
response["response_mode"] = "code_deep"
|
|
512
|
-
response["research_mode"] = "code_deep"
|
|
513
|
-
response = self._finalize_answer_response(question, response, mode="code_deep")
|
|
514
|
-
response["trace"] = trace
|
|
515
|
-
response["file_inventory"] = self._collect_file_inventory(
|
|
516
|
-
question,
|
|
517
|
-
response,
|
|
518
|
-
result.all_sources,
|
|
519
|
-
retrieval_cfg,
|
|
520
|
-
trace,
|
|
521
|
-
)
|
|
522
|
-
return response
|
|
523
|
-
|
|
524
|
-
def _run_research_mode(
|
|
525
|
-
self,
|
|
526
|
-
question: str,
|
|
527
|
-
history: list[dict[str, str]] | None,
|
|
528
|
-
*,
|
|
529
|
-
mode: str,
|
|
530
|
-
max_rounds: int,
|
|
531
|
-
top_k: int,
|
|
532
|
-
trace_callback: Callable[[dict[str, Any]], None] | None = None,
|
|
533
|
-
token_callback: "Callable[[str], None] | None" = None,
|
|
534
|
-
) -> tuple[Any, dict[str, Any]]:
|
|
535
|
-
from .deep_research import DeepResearcher
|
|
536
|
-
|
|
477
|
+
top_k = max(10, int(retrieval_cfg.get("deep_top_k_code", retrieval_cfg["top_k_code"])))
|
|
537
478
|
researcher = DeepResearcher(
|
|
538
479
|
service=self,
|
|
539
480
|
llm=self._llm,
|
|
540
481
|
top_k=top_k,
|
|
541
482
|
max_rounds=max_rounds,
|
|
542
|
-
mode=
|
|
543
|
-
trace_callback=
|
|
483
|
+
mode="deep",
|
|
484
|
+
trace_callback=emit,
|
|
544
485
|
)
|
|
545
486
|
researcher.synthesis_token_callback = token_callback
|
|
546
487
|
result = researcher.research(question, history=history or [])
|
|
547
|
-
|
|
548
|
-
response = self.query(question, history, mode=
|
|
488
|
+
|
|
489
|
+
response = self.query(question, history, mode="deep")
|
|
549
490
|
response.update(
|
|
550
491
|
{
|
|
551
492
|
"answer": result.final_answer,
|
|
@@ -554,13 +495,17 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
554
495
|
sum(step.chunks_used for step in result.steps),
|
|
555
496
|
),
|
|
556
497
|
"confidence": result.confidence,
|
|
557
|
-
"research_mode":
|
|
498
|
+
"research_mode": "deep",
|
|
558
499
|
"research_sources": result.all_sources,
|
|
559
|
-
"response_mode":
|
|
500
|
+
"response_mode": "deep",
|
|
560
501
|
}
|
|
561
502
|
)
|
|
562
|
-
response = self._finalize_answer_response(question, response, mode=
|
|
563
|
-
|
|
503
|
+
response = self._finalize_answer_response(question, response, mode="deep")
|
|
504
|
+
response["trace"] = trace
|
|
505
|
+
response["file_inventory"] = self._collect_file_inventory(
|
|
506
|
+
question, response, result.all_sources, retrieval_cfg, trace,
|
|
507
|
+
)
|
|
508
|
+
return response
|
|
564
509
|
|
|
565
510
|
def _collect_file_inventory(
|
|
566
511
|
self,
|
|
@@ -570,7 +515,7 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
570
515
|
retrieval_cfg: dict[str, Any],
|
|
571
516
|
trace: list[dict[str, Any]],
|
|
572
517
|
) -> list[dict[str, Any]]:
|
|
573
|
-
limit = max(8, int(retrieval_cfg.get("
|
|
518
|
+
limit = max(8, int(retrieval_cfg.get("deep_file_inventory_limit", 18)))
|
|
574
519
|
inventory: dict[str, dict[str, Any]] = {}
|
|
575
520
|
|
|
576
521
|
def add_entry(
|
|
@@ -696,21 +641,17 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
696
641
|
|
|
697
642
|
def _retrieval_profile(self, mode: str) -> dict[str, Any]:
|
|
698
643
|
base = deepcopy(self.chat_cfg["retrieval"])
|
|
699
|
-
mode_name = mode.strip().lower() if isinstance(mode, str) else "
|
|
644
|
+
mode_name = mode.strip().lower() if isinstance(mode, str) else "fast"
|
|
645
|
+
|
|
700
646
|
if mode_name == "default":
|
|
701
647
|
return base
|
|
702
|
-
if mode_name == "deep":
|
|
703
|
-
deep_prompt_chars = base.get("deep_mode_max_prompt_chars")
|
|
704
|
-
if isinstance(deep_prompt_chars, int) and deep_prompt_chars > 0:
|
|
705
|
-
base["max_prompt_chars"] = deep_prompt_chars
|
|
706
|
-
return base
|
|
707
648
|
|
|
708
|
-
if mode_name == "
|
|
709
|
-
|
|
710
|
-
if isinstance(
|
|
711
|
-
base["max_prompt_chars"] =
|
|
649
|
+
if mode_name == "deep":
|
|
650
|
+
prompt_chars = base.get("deep_mode_max_prompt_chars")
|
|
651
|
+
if isinstance(prompt_chars, int) and prompt_chars > 0:
|
|
652
|
+
base["max_prompt_chars"] = prompt_chars
|
|
712
653
|
|
|
713
|
-
code_top_k = base.get("
|
|
654
|
+
code_top_k = base.get("deep_top_k_code")
|
|
714
655
|
if isinstance(code_top_k, int) and code_top_k > 0:
|
|
715
656
|
base["top_k_code"] = max(base.get("top_k_code", code_top_k), code_top_k)
|
|
716
657
|
base["candidate_top_k_code"] = max(
|
|
@@ -718,18 +659,17 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
718
659
|
code_top_k * 2,
|
|
719
660
|
)
|
|
720
661
|
|
|
721
|
-
|
|
722
|
-
if isinstance(
|
|
662
|
+
rel_top_k = base.get("deep_top_k_relationship")
|
|
663
|
+
if isinstance(rel_top_k, int) and rel_top_k > 0:
|
|
723
664
|
base["top_k_relationship"] = max(
|
|
724
|
-
base.get("top_k_relationship",
|
|
725
|
-
relationship_top_k,
|
|
665
|
+
base.get("top_k_relationship", rel_top_k), rel_top_k,
|
|
726
666
|
)
|
|
727
667
|
base["candidate_top_k_relationship"] = max(
|
|
728
|
-
base.get("candidate_top_k_relationship",
|
|
729
|
-
|
|
668
|
+
base.get("candidate_top_k_relationship", rel_top_k * 2),
|
|
669
|
+
rel_top_k * 2,
|
|
730
670
|
)
|
|
731
671
|
|
|
732
|
-
docs_cap = base.get("
|
|
672
|
+
docs_cap = base.get("deep_top_k_docs")
|
|
733
673
|
if isinstance(docs_cap, int) and docs_cap > 0:
|
|
734
674
|
base["top_k_docs"] = min(base.get("top_k_docs", docs_cap), docs_cap)
|
|
735
675
|
|
|
@@ -739,6 +679,7 @@ class ChatbotQueryService(RetrievalMixin, AnswerMixin, LiveFallbackMixin):
|
|
|
739
679
|
base["rerank"] = True
|
|
740
680
|
return base
|
|
741
681
|
|
|
682
|
+
# fast mode (default for any unrecognised mode string)
|
|
742
683
|
fast_prompt_chars = base.get("fast_mode_max_prompt_chars")
|
|
743
684
|
if isinstance(fast_prompt_chars, int) and fast_prompt_chars > 0:
|
|
744
685
|
base["max_prompt_chars"] = fast_prompt_chars
|
|
@@ -72,12 +72,11 @@ DEFAULT_CHATBOT_CONFIG: dict[str, Any] = {
|
|
|
72
72
|
"fast_mode_use_llm_retrieval_steps": False,
|
|
73
73
|
"fast_mode_iterative_retrieval": False,
|
|
74
74
|
"fast_mode_max_prompt_chars": 90000,
|
|
75
|
-
"deep_mode_max_prompt_chars":
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"code_deep_file_inventory_limit": 18,
|
|
75
|
+
"deep_mode_max_prompt_chars": 180000,
|
|
76
|
+
"deep_top_k_code": 16,
|
|
77
|
+
"deep_top_k_relationship": 12,
|
|
78
|
+
"deep_top_k_docs": 4,
|
|
79
|
+
"deep_file_inventory_limit": 18,
|
|
81
80
|
"lexical_retrieval": True,
|
|
82
81
|
"lexical_candidate_limit": 24,
|
|
83
82
|
"query_expansion": True,
|
|
@@ -974,7 +974,7 @@ def serve(port):
|
|
|
974
974
|
|
|
975
975
|
\b
|
|
976
976
|
Run `deepdoc generate` first so the generated MkDocs site and docs exist.
|
|
977
|
-
Requires
|
|
977
|
+
Requires the site extra: pip install 'deepdoc[site]'
|
|
978
978
|
"""
|
|
979
979
|
_load_or_exit()
|
|
980
980
|
cfg = _load_or_exit()
|
|
@@ -1026,7 +1026,7 @@ def serve(port):
|
|
|
1026
1026
|
pass
|
|
1027
1027
|
except FileNotFoundError:
|
|
1028
1028
|
console.print(
|
|
1029
|
-
"[red]mkdocs not found. Install it: [bold]pip install
|
|
1029
|
+
"[red]mkdocs not found. Install it: [bold]pip install 'deepdoc[site]'[/bold][/red]"
|
|
1030
1030
|
)
|
|
1031
1031
|
sys.exit(1)
|
|
1032
1032
|
finally:
|
|
@@ -1107,7 +1107,7 @@ def _deploy():
|
|
|
1107
1107
|
console.print("[red]Build failed.[/red]")
|
|
1108
1108
|
except FileNotFoundError:
|
|
1109
1109
|
console.print(
|
|
1110
|
-
"[red]mkdocs not found. Install it: [bold]pip install
|
|
1110
|
+
"[red]mkdocs not found. Install it: [bold]pip install 'deepdoc[site]'[/bold][/red]"
|
|
1111
1111
|
)
|
|
1112
1112
|
sys.exit(1)
|
|
1113
1113
|
|
|
@@ -1132,9 +1132,9 @@ def _ensure_mkdocs_installed(cfg: dict) -> None:
|
|
|
1132
1132
|
missing.append("mkdocs-swagger-ui-tag")
|
|
1133
1133
|
|
|
1134
1134
|
if missing:
|
|
1135
|
-
pkgs = " ".join(dict.fromkeys(missing))
|
|
1136
1135
|
raise click.ClickException(
|
|
1137
|
-
|
|
1136
|
+
"MkDocs is not installed. Install the site extra with:\n"
|
|
1137
|
+
" pip install 'deepdoc[site]'"
|
|
1138
1138
|
)
|
|
1139
1139
|
|
|
1140
1140
|
|
|
@@ -227,12 +227,11 @@ DEFAULT_CONFIG: dict[str, Any] = {
|
|
|
227
227
|
"fast_mode_use_llm_retrieval_steps": False,
|
|
228
228
|
"fast_mode_iterative_retrieval": False,
|
|
229
229
|
"fast_mode_max_prompt_chars": 90000,
|
|
230
|
-
"deep_mode_max_prompt_chars":
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"code_deep_file_inventory_limit": 18,
|
|
230
|
+
"deep_mode_max_prompt_chars": 180000,
|
|
231
|
+
"deep_top_k_code": 16,
|
|
232
|
+
"deep_top_k_relationship": 12,
|
|
233
|
+
"deep_top_k_docs": 4,
|
|
234
|
+
"deep_file_inventory_limit": 18,
|
|
236
235
|
"lexical_retrieval": True,
|
|
237
236
|
"lexical_candidate_limit": 24,
|
|
238
237
|
"query_expansion": True,
|
|
@@ -13,11 +13,9 @@ from .post_processors import (
|
|
|
13
13
|
build_internal_doc_link_maps,
|
|
14
14
|
fix_file_references,
|
|
15
15
|
fix_mermaid_diagrams,
|
|
16
|
-
normalize_code_fence_languages,
|
|
17
16
|
normalize_explanatory_lines_outside_fences,
|
|
18
17
|
normalize_html_code_blocks,
|
|
19
18
|
repair_internal_doc_links,
|
|
20
|
-
repair_split_object_code_fences,
|
|
21
19
|
repair_dangling_plain_fences,
|
|
22
20
|
repair_unbalanced_code_fences,
|
|
23
21
|
)
|