ai-docs-gen 0.1.2__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.
- ai_docs/__init__.py +0 -0
- ai_docs/__main__.py +22 -0
- ai_docs/assets/mermaid.min.js +1642 -0
- ai_docs/cache.py +52 -0
- ai_docs/changes.py +25 -0
- ai_docs/cli.py +84 -0
- ai_docs/domain.py +206 -0
- ai_docs/generator.py +959 -0
- ai_docs/llm.py +82 -0
- ai_docs/mkdocs.py +161 -0
- ai_docs/scanner.py +237 -0
- ai_docs/summary.py +238 -0
- ai_docs/tokenizer.py +26 -0
- ai_docs/utils.py +43 -0
- ai_docs_gen-0.1.2.dist-info/METADATA +197 -0
- ai_docs_gen-0.1.2.dist-info/RECORD +19 -0
- ai_docs_gen-0.1.2.dist-info/WHEEL +5 -0
- ai_docs_gen-0.1.2.dist-info/entry_points.txt +2 -0
- ai_docs_gen-0.1.2.dist-info/top_level.txt +1 -0
ai_docs/summary.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Dict, List
|
|
3
|
+
|
|
4
|
+
from .tokenizer import chunk_text
|
|
5
|
+
from .utils import ensure_dir
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
SUMMARY_PROMPT = """
|
|
9
|
+
Ты эксперт по технической документации. Сформируй краткое, но информативное описание файла для включения в документацию.
|
|
10
|
+
Укажи назначение, ключевые сущности и важные настройки. Если файл конфигурационный — перечисли ключевые параметры/секции.
|
|
11
|
+
Ответ строго в Markdown, без заголовка. Не используй блоки кода и не оборачивай текст в ```markdown.
|
|
12
|
+
""".strip()
|
|
13
|
+
|
|
14
|
+
MODULE_SUMMARY_PROMPT = """
|
|
15
|
+
Ты технический писатель. Сформируй документацию модуля в стиле Doxygen.
|
|
16
|
+
Сначала дай краткое верхнеуровневое описание модуля (2–4 предложения).
|
|
17
|
+
Затем, если есть важные структуры данных/типы, добавь блок:
|
|
18
|
+
Ключевые структуры данных
|
|
19
|
+
<имя> — <краткое описание>
|
|
20
|
+
|
|
21
|
+
Далее перечисли функции/процедуры и классы строго в Doxygen‑формате.
|
|
22
|
+
Для функций/процедур используй формат:
|
|
23
|
+
|
|
24
|
+
<сигнатура>
|
|
25
|
+
<краткое назначение одной строкой>
|
|
26
|
+
Аргументы
|
|
27
|
+
<имя> — <описание>
|
|
28
|
+
Возвращает
|
|
29
|
+
<описание>
|
|
30
|
+
Исключения
|
|
31
|
+
<описание>
|
|
32
|
+
|
|
33
|
+
Для классов используй формат:
|
|
34
|
+
class <имя>
|
|
35
|
+
<краткое назначение одной строкой>
|
|
36
|
+
Поля
|
|
37
|
+
<имя> — <описание>
|
|
38
|
+
Методы
|
|
39
|
+
<сигнатура> — <краткое назначение>
|
|
40
|
+
|
|
41
|
+
Если аргументов/возвращаемого значения/исключений/полей нет — соответствующий блок пропускай.
|
|
42
|
+
Разделяй сущности строкой из трёх дефисов: `---`.
|
|
43
|
+
Не используй заголовки Markdown, списки, подзаголовки вроде "Основные функции".
|
|
44
|
+
Ответ строго в Markdown, без заголовка документа, сохраняя последовательность блоков.
|
|
45
|
+
""".strip()
|
|
46
|
+
|
|
47
|
+
MODULE_SUMMARY_REFORMAT_PROMPT = """
|
|
48
|
+
Переформатируй текст в строгий Doxygen‑стиль для модуля.
|
|
49
|
+
Требования:
|
|
50
|
+
- Без заголовков Markdown, без списков, без блоков кода.
|
|
51
|
+
- Структура: краткое описание модуля; затем (если есть) "Ключевые структуры данных" с линиями "<имя> — <описание>".
|
|
52
|
+
- Далее только сущности (функции/процедуры/классы) в формате:
|
|
53
|
+
<сигнатура>
|
|
54
|
+
<краткое назначение одной строкой>
|
|
55
|
+
Аргументы
|
|
56
|
+
<имя> — <описание>
|
|
57
|
+
Возвращает
|
|
58
|
+
<описание>
|
|
59
|
+
Исключения
|
|
60
|
+
<описание>
|
|
61
|
+
Для классов:
|
|
62
|
+
class <имя>
|
|
63
|
+
<краткое назначение одной строкой>
|
|
64
|
+
Поля
|
|
65
|
+
<имя> — <описание>
|
|
66
|
+
Методы
|
|
67
|
+
<сигнатура> — <краткое назначение>
|
|
68
|
+
|
|
69
|
+
Если блок пустой — не выводи его. Между сущностями ставь строку `---`.
|
|
70
|
+
Ответ строго в Markdown без заголовка документа.
|
|
71
|
+
""".strip()
|
|
72
|
+
|
|
73
|
+
CONFIG_SUMMARY_PROMPT = """
|
|
74
|
+
Ты технический писатель. Сформируй описание конфигурационного файла в универсальном стиле.
|
|
75
|
+
Сначала дай краткое описание файла (2–4 предложения).
|
|
76
|
+
Затем блок:
|
|
77
|
+
Секции и ключи
|
|
78
|
+
<секция/ключ> — <описание>
|
|
79
|
+
|
|
80
|
+
Далее (если есть важные параметры) добавь блок:
|
|
81
|
+
Важные параметры
|
|
82
|
+
<параметр> — <описание>
|
|
83
|
+
|
|
84
|
+
Не используй заголовки Markdown, списки, нумерацию и блоки кода.
|
|
85
|
+
Ответ строго в Markdown без заголовка документа, соблюдай указанные блоки.
|
|
86
|
+
""".strip()
|
|
87
|
+
|
|
88
|
+
CONFIG_SUMMARY_REFORMAT_PROMPT = """
|
|
89
|
+
Переформатируй текст в универсальный конфиг-стиль.
|
|
90
|
+
Требования:
|
|
91
|
+
- Без заголовков Markdown, списков, нумерации и блоков кода.
|
|
92
|
+
- Структура: краткое описание файла; затем блок "Секции и ключи" с линиями "<секция/ключ> — <описание>".
|
|
93
|
+
- Далее (если есть) блок "Важные параметры" с линиями "<параметр> — <описание>".
|
|
94
|
+
Если блок пустой — не выводи его.
|
|
95
|
+
Ответ строго в Markdown без заголовка документа.
|
|
96
|
+
""".strip()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _needs_doxygen_fix(text: str) -> bool:
|
|
100
|
+
if "```" in text:
|
|
101
|
+
return True
|
|
102
|
+
for line in text.splitlines():
|
|
103
|
+
stripped = line.strip()
|
|
104
|
+
if stripped.startswith("#"):
|
|
105
|
+
return True
|
|
106
|
+
if stripped.startswith(("-", "*", "•")):
|
|
107
|
+
return True
|
|
108
|
+
if stripped[:2].isdigit() and stripped[1] == ".":
|
|
109
|
+
return True
|
|
110
|
+
lowered = text.lower()
|
|
111
|
+
noisy_markers = [
|
|
112
|
+
"основные функции",
|
|
113
|
+
"основные возможности",
|
|
114
|
+
"обработка ошибок",
|
|
115
|
+
"интеграции",
|
|
116
|
+
"ключевые структуры данных:",
|
|
117
|
+
"##",
|
|
118
|
+
]
|
|
119
|
+
return any(marker in lowered for marker in noisy_markers)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _normalize_module_summary(
|
|
123
|
+
summary: str, llm_client, llm_cache: Dict[str, str]
|
|
124
|
+
) -> str:
|
|
125
|
+
if not _needs_doxygen_fix(summary):
|
|
126
|
+
return summary
|
|
127
|
+
messages = [
|
|
128
|
+
{"role": "system", "content": MODULE_SUMMARY_REFORMAT_PROMPT},
|
|
129
|
+
{"role": "user", "content": summary},
|
|
130
|
+
]
|
|
131
|
+
return llm_client.chat(messages, cache=llm_cache).strip()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _normalize_config_summary(summary: str, llm_client, llm_cache: Dict[str, str]) -> str:
|
|
135
|
+
if not _needs_doxygen_fix(summary):
|
|
136
|
+
return _format_config_blocks(summary)
|
|
137
|
+
messages = [
|
|
138
|
+
{"role": "system", "content": CONFIG_SUMMARY_REFORMAT_PROMPT},
|
|
139
|
+
{"role": "user", "content": summary},
|
|
140
|
+
]
|
|
141
|
+
return _format_config_blocks(llm_client.chat(messages, cache=llm_cache).strip())
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _format_config_blocks(text: str) -> str:
|
|
145
|
+
lines = [line.rstrip() for line in text.strip().splitlines() if line.strip()]
|
|
146
|
+
if not lines:
|
|
147
|
+
return text.strip()
|
|
148
|
+
output: List[str] = []
|
|
149
|
+
i = 0
|
|
150
|
+
headers = {"Секции и ключи", "Важные параметры"}
|
|
151
|
+
while i < len(lines):
|
|
152
|
+
line = lines[i].strip()
|
|
153
|
+
if line in headers:
|
|
154
|
+
entries: List[str] = []
|
|
155
|
+
i += 1
|
|
156
|
+
while i < len(lines) and lines[i].strip() not in headers:
|
|
157
|
+
entries.append(lines[i].strip())
|
|
158
|
+
i += 1
|
|
159
|
+
output.append(line)
|
|
160
|
+
if entries:
|
|
161
|
+
output.append("<br>\n".join(entries))
|
|
162
|
+
continue
|
|
163
|
+
output.append(line)
|
|
164
|
+
i += 1
|
|
165
|
+
return "\n\n".join(output).strip()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _strip_fenced_markdown(text: str) -> str:
|
|
169
|
+
stripped = text.strip()
|
|
170
|
+
if stripped.startswith("```"):
|
|
171
|
+
lines = stripped.splitlines()
|
|
172
|
+
if len(lines) >= 2 and lines[0].startswith("```") and lines[-1].strip() == "```":
|
|
173
|
+
return "\n".join(lines[1:-1]).strip()
|
|
174
|
+
return text
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def summarize_file(
|
|
178
|
+
content: str,
|
|
179
|
+
file_type: str,
|
|
180
|
+
domains: List[str],
|
|
181
|
+
llm_client,
|
|
182
|
+
llm_cache: Dict[str, str],
|
|
183
|
+
model: str,
|
|
184
|
+
detailed: bool = False,
|
|
185
|
+
) -> str:
|
|
186
|
+
chunks = chunk_text(content, model=model, max_tokens=1800)
|
|
187
|
+
summaries = []
|
|
188
|
+
for chunk in chunks:
|
|
189
|
+
if detailed and file_type == "config":
|
|
190
|
+
prompt = CONFIG_SUMMARY_PROMPT
|
|
191
|
+
else:
|
|
192
|
+
prompt = MODULE_SUMMARY_PROMPT if detailed else SUMMARY_PROMPT
|
|
193
|
+
if not detailed and (file_type == "infra" or domains):
|
|
194
|
+
prompt = SUMMARY_PROMPT + "\nФайл относится к инфраструктуре: " + ", ".join(domains)
|
|
195
|
+
messages = [
|
|
196
|
+
{"role": "system", "content": prompt},
|
|
197
|
+
{"role": "user", "content": chunk},
|
|
198
|
+
]
|
|
199
|
+
summaries.append(_strip_fenced_markdown(llm_client.chat(messages, cache=llm_cache).strip()))
|
|
200
|
+
|
|
201
|
+
if len(summaries) == 1:
|
|
202
|
+
result = summaries[0]
|
|
203
|
+
if detailed and file_type == "config":
|
|
204
|
+
return _normalize_config_summary(result, llm_client, llm_cache)
|
|
205
|
+
if detailed:
|
|
206
|
+
return _normalize_module_summary(result, llm_client, llm_cache)
|
|
207
|
+
return result
|
|
208
|
+
|
|
209
|
+
combined = "\n\n".join(summaries)
|
|
210
|
+
if detailed and file_type == "config":
|
|
211
|
+
messages = [
|
|
212
|
+
{"role": "system", "content": CONFIG_SUMMARY_REFORMAT_PROMPT},
|
|
213
|
+
{"role": "user", "content": combined},
|
|
214
|
+
]
|
|
215
|
+
elif detailed:
|
|
216
|
+
messages = [
|
|
217
|
+
{"role": "system", "content": MODULE_SUMMARY_REFORMAT_PROMPT},
|
|
218
|
+
{"role": "user", "content": combined},
|
|
219
|
+
]
|
|
220
|
+
else:
|
|
221
|
+
messages = [
|
|
222
|
+
{"role": "system", "content": "Собери единое краткое резюме для документации на основе частей ниже. Ответ в Markdown."},
|
|
223
|
+
{"role": "user", "content": combined},
|
|
224
|
+
]
|
|
225
|
+
result = _strip_fenced_markdown(llm_client.chat(messages, cache=llm_cache).strip())
|
|
226
|
+
if detailed and file_type == "config":
|
|
227
|
+
return _normalize_config_summary(result, llm_client, llm_cache)
|
|
228
|
+
if detailed:
|
|
229
|
+
return _normalize_module_summary(result, llm_client, llm_cache)
|
|
230
|
+
return result
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def write_summary(summary_dir: Path, rel_path: str, summary: str) -> Path:
|
|
234
|
+
ensure_dir(summary_dir)
|
|
235
|
+
safe_name = "".join(c if c.isalnum() else "_" for c in rel_path).strip("_").lower()
|
|
236
|
+
out_path = summary_dir / f"{safe_name}.md"
|
|
237
|
+
out_path.write_text(summary, encoding="utf-8")
|
|
238
|
+
return out_path
|
ai_docs/tokenizer.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import tiktoken
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_encoding(model: str):
|
|
7
|
+
try:
|
|
8
|
+
return tiktoken.encoding_for_model(model)
|
|
9
|
+
except KeyError:
|
|
10
|
+
return tiktoken.get_encoding("cl100k_base")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def count_tokens(text: str, model: str) -> int:
|
|
14
|
+
enc = get_encoding(model)
|
|
15
|
+
return len(enc.encode(text))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def chunk_text(text: str, model: str, max_tokens: int) -> List[str]:
|
|
19
|
+
enc = get_encoding(model)
|
|
20
|
+
tokens = enc.encode(text)
|
|
21
|
+
chunks = []
|
|
22
|
+
for i in range(0, len(tokens), max_tokens):
|
|
23
|
+
chunk = tokens[i:i + max_tokens]
|
|
24
|
+
chunks.append(enc.decode(chunk))
|
|
25
|
+
return chunks
|
|
26
|
+
|
ai_docs/utils.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def sha256_bytes(data: bytes) -> str:
|
|
7
|
+
return hashlib.sha256(data).hexdigest()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sha256_text(text: str) -> str:
|
|
11
|
+
return sha256_bytes(text.encode("utf-8", errors="ignore"))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def read_text_file(path: Path) -> str:
|
|
15
|
+
return path.read_text(encoding="utf-8", errors="ignore")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def safe_slug(path: str) -> str:
|
|
19
|
+
return "".join(c if c.isalnum() else "_" for c in path).strip("_").lower()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def ensure_dir(path: Path) -> None:
|
|
23
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def is_binary_file(path: Path, sample_size: int = 2048) -> bool:
|
|
27
|
+
try:
|
|
28
|
+
with path.open("rb") as f:
|
|
29
|
+
chunk = f.read(sample_size)
|
|
30
|
+
if b"\x00" in chunk:
|
|
31
|
+
return True
|
|
32
|
+
return False
|
|
33
|
+
except OSError:
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_url(value: str) -> bool:
|
|
38
|
+
return value.startswith("http://") or value.startswith("https://") or value.startswith("git@")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def to_posix(path: Path) -> str:
|
|
42
|
+
return path.as_posix()
|
|
43
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ai-docs-gen
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: CLI-инструмент для генерации технической документации по коду и конфигурациям
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: requests
|
|
8
|
+
Requires-Dist: tiktoken
|
|
9
|
+
Requires-Dist: pyyaml
|
|
10
|
+
Requires-Dist: pathspec
|
|
11
|
+
Requires-Dist: tomli
|
|
12
|
+
Requires-Dist: python-dotenv
|
|
13
|
+
Requires-Dist: mkdocs
|
|
14
|
+
Requires-Dist: mkdocs-mermaid2-plugin
|
|
15
|
+
Requires-Dist: pymdown-extensions
|
|
16
|
+
|
|
17
|
+
# ai_docs — генератор технической документации
|
|
18
|
+
|
|
19
|
+
## Обзор
|
|
20
|
+
`ai_docs` — CLI‑инструмент для генерации технической документации по коду и конфигурациям.
|
|
21
|
+
Поддерживает локальные папки, локальные git‑проекты и удалённые git‑репозитории.
|
|
22
|
+
Генерирует `README.md` и MkDocs‑сайт (с автоматической сборкой).
|
|
23
|
+
|
|
24
|
+
Ключевые возможности:
|
|
25
|
+
- Автоопределение доменов инфраструктуры (Kubernetes, Helm, Terraform, Ansible, Docker, CI/CD, Observability, Service Mesh / Ingress, Data / Storage)
|
|
26
|
+
- Инкрементальная генерация и кэширование
|
|
27
|
+
- Учет `.gitignore` и фильтрация файлов
|
|
28
|
+
- Параллельная LLM‑суммаризация (`--threads` / `AI_DOCS_THREADS`)
|
|
29
|
+
- Отчёт об изменениях в `docs/changes.md`
|
|
30
|
+
|
|
31
|
+
## Быстрый старт
|
|
32
|
+
|
|
33
|
+
1) Установка зависимостей:
|
|
34
|
+
```bash
|
|
35
|
+
python3 -m venv .venv
|
|
36
|
+
. .venv/bin/activate
|
|
37
|
+
pip install -r requirements.txt
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Альтернатива (установка как пакет):
|
|
41
|
+
```bash
|
|
42
|
+
python3 -m venv .venv
|
|
43
|
+
. .venv/bin/activate
|
|
44
|
+
pip install ai-docs-gen
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Локальная установка в editable‑режиме:
|
|
48
|
+
```bash
|
|
49
|
+
python3 -m venv .venv
|
|
50
|
+
. .venv/bin/activate
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
2) Настройка `.env` (пример — `.env.example`):
|
|
55
|
+
```env
|
|
56
|
+
OPENAI_API_KEY=your_api_key_here
|
|
57
|
+
OPENAI_BASE_URL=https://api.openai.com/v1
|
|
58
|
+
OPENAI_MODEL=gpt-4o-mini
|
|
59
|
+
OPENAI_MAX_TOKENS=1200
|
|
60
|
+
OPENAI_CONTEXT_TOKENS=8192
|
|
61
|
+
OPENAI_TEMPERATURE=0.2
|
|
62
|
+
AI_DOCS_THREADS=1
|
|
63
|
+
AI_DOCS_LOCAL_SITE=false
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3) Генерация README и MkDocs:
|
|
67
|
+
```bash
|
|
68
|
+
python -m ai_docs --source .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Альтернативно:
|
|
72
|
+
```bash
|
|
73
|
+
python ai_docs --source .
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Если установлен как пакет:
|
|
77
|
+
```bash
|
|
78
|
+
ai-docs --source .
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Примеры использования
|
|
82
|
+
|
|
83
|
+
Локальная папка:
|
|
84
|
+
```bash
|
|
85
|
+
python -m ai_docs --source /path/to/project
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Локальный git‑проект:
|
|
89
|
+
```bash
|
|
90
|
+
python -m ai_docs --source ~/projects/my-repo
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Удалённый репозиторий:
|
|
94
|
+
```bash
|
|
95
|
+
python -m ai_docs --source https://github.com/org/repo.git
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Только README:
|
|
99
|
+
```bash
|
|
100
|
+
python -m ai_docs --source . --readme
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Только MkDocs:
|
|
104
|
+
```bash
|
|
105
|
+
python -m ai_docs --source . --mkdocs
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Локальный режим для MkDocs:
|
|
109
|
+
```bash
|
|
110
|
+
python -m ai_docs --source . --mkdocs --local-site
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Что генерируется
|
|
114
|
+
- `README.md` — краткое описание проекта
|
|
115
|
+
- `.ai-docs/` — страницы документации
|
|
116
|
+
- `.ai-docs/changes.md` — изменения с последней генерации
|
|
117
|
+
- `.ai-docs/modules/` — детальная документация модулей (страница на модуль, Doxygen‑подобное описание функций/классов/параметров)
|
|
118
|
+
- `.ai-docs/configs/` — документация конфигов проекта (обзор + страницы конфигов в универсальном стиле)
|
|
119
|
+
- `.ai-docs/_index.json` — навигационный индекс документации (правила маршрутизации, список секций и модулей)
|
|
120
|
+
- `mkdocs.yml` — конфиг MkDocs
|
|
121
|
+
- `ai_docs_site/` — собранный сайт MkDocs
|
|
122
|
+
- `.ai_docs_cache/` — кэш и промежуточные summary‑файлы
|
|
123
|
+
|
|
124
|
+
## Поддерживаемые языки и расширения
|
|
125
|
+
Поддержка основана на расширениях кода в `ai_docs/domain.py`:
|
|
126
|
+
`.py`, `.pyi`, `.pyx`, `.js`, `.jsx`, `.ts`, `.tsx`, `.go`, `.java`, `.c`, `.cc`, `.cpp`, `.h`, `.hpp`, `.rs`, `.rb`, `.php`, `.cs`, `.kt`, `.kts`, `.swift`, `.m`, `.mm`, `.vb`, `.bas`, `.sql`, `.pas`, `.dpr`, `.pp`, `.r`, `.pl`, `.pm`, `.f`, `.for`, `.f90`, `.f95`, `.f03`, `.f08`, `.sb3`, `.adb`, `.ads`, `.asm`, `.s`, `.ino`, `.htm`, `.html`, `.css`.
|
|
127
|
+
|
|
128
|
+
## Индекс документации
|
|
129
|
+
Файл `.ai-docs/_index.json` строится автоматически при генерации и содержит:
|
|
130
|
+
- список секций и модулей (пути и краткие описания);
|
|
131
|
+
- правила маршрутизации: приоритет `modules/index.md → modules/* → index.md/architecture.md/conventions.md`;
|
|
132
|
+
- принцип ранжирования: частота ключевых совпадений + приоритет файла.
|
|
133
|
+
|
|
134
|
+
## .ai-docs.yaml (расширения)
|
|
135
|
+
Если в проекте есть файл `.ai-docs.yaml`, он задаёт приоритетный список расширений для сканирования.
|
|
136
|
+
Если файла нет, он создаётся автоматически на основе текущих `*_EXTENSIONS`.
|
|
137
|
+
|
|
138
|
+
Формат (поддерживаются map и list для расширений):
|
|
139
|
+
```yaml
|
|
140
|
+
code_extensions:
|
|
141
|
+
.py: Python
|
|
142
|
+
.ts: TypeScript
|
|
143
|
+
doc_extensions:
|
|
144
|
+
.md: Markdown
|
|
145
|
+
.rst: reStructuredText
|
|
146
|
+
config_extensions:
|
|
147
|
+
.yml: YAML
|
|
148
|
+
.json: JSON
|
|
149
|
+
exclude:
|
|
150
|
+
- "temp/*"
|
|
151
|
+
- "*.log"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## CLI‑параметры
|
|
155
|
+
- `--source <path|url>` — источник
|
|
156
|
+
- `--output <path>` — выходная директория (по умолчанию: source для локальных путей, `./output/<repo>` для URL)
|
|
157
|
+
|
|
158
|
+
## Тестирование
|
|
159
|
+
Тесты находятся в каталоге `tests/`:
|
|
160
|
+
- `test_cache.py`
|
|
161
|
+
- `test_changes.py`
|
|
162
|
+
- `test_scanner.py`
|
|
163
|
+
|
|
164
|
+
Запуск (из корня проекта):
|
|
165
|
+
```bash
|
|
166
|
+
python -m pytest
|
|
167
|
+
```
|
|
168
|
+
- `--readme` — генерировать только README
|
|
169
|
+
- `--mkdocs` — генерировать только MkDocs
|
|
170
|
+
- `--language ru|en` — язык документации
|
|
171
|
+
- `--include/--exclude` — фильтры
|
|
172
|
+
- `--max-size` — максимальный размер файла
|
|
173
|
+
- `--threads` — число потоков LLM
|
|
174
|
+
- `--cache-dir` — директория кэша (по умолчанию `.ai_docs_cache`)
|
|
175
|
+
- `--no-cache` — отключить LLM‑кэш
|
|
176
|
+
- `--local-site` — добавить `site_url` и `use_directory_urls` в `mkdocs.yml`
|
|
177
|
+
- `--force` — перезаписать `README.md`, если он уже существует
|
|
178
|
+
|
|
179
|
+
Поведение по умолчанию: если не указаны `--readme` и `--mkdocs`, генерируются оба артефакта.
|
|
180
|
+
|
|
181
|
+
## MkDocs
|
|
182
|
+
Сборка выполняется автоматически в конце генерации:
|
|
183
|
+
```
|
|
184
|
+
mkdocs build -f mkdocs.yml
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Исключения
|
|
188
|
+
Сканер учитывает `.gitignore`, `.build_ignore` и дефолтные исключения:
|
|
189
|
+
`.venv`, `node_modules`, `ai_docs_site`, `.ai-docs`, `.ai_docs_cache`, `dist`, `build`, т.д.
|
|
190
|
+
|
|
191
|
+
## Разработка и вклад
|
|
192
|
+
- Установите зависимости (см. «Быстрый старт»)
|
|
193
|
+
- Запускайте через `python -m ai_docs ...` для отладки
|
|
194
|
+
- PR и предложения приветствуются
|
|
195
|
+
|
|
196
|
+
## Лицензия
|
|
197
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
ai_docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
ai_docs/__main__.py,sha256=yNFl5cGhWoeZLOulgfPCd-pOwjq0dclhAyB-OiG-cvE,512
|
|
3
|
+
ai_docs/cache.py,sha256=Z3Mwg2QEYZNaC6bRyv6Py0FcFDV0d9KnyFiBf-EsyFE,1784
|
|
4
|
+
ai_docs/changes.py,sha256=tA6kf79XPiywqWBBfBaqf-upRyowyInsw-BFYOIUAmA,973
|
|
5
|
+
ai_docs/cli.py,sha256=XhZO6b49lYGqefITwu-R57-pN6t5esyARGlcMz7cXAA,3639
|
|
6
|
+
ai_docs/domain.py,sha256=HrbdDw_Qxe1gk7J4dzYN1MHbYXDGY3-Tyr5--LgSjzc,6253
|
|
7
|
+
ai_docs/generator.py,sha256=n_sdUxHPFF4c4CPplbxEGDYmK32tfXq2w7a1sEVqa8E,41146
|
|
8
|
+
ai_docs/llm.py,sha256=BCVcMM1X_B_LMEuyLBM6jFNz8jYONikM4pEJVhJ16c0,2633
|
|
9
|
+
ai_docs/mkdocs.py,sha256=Zh23S3T3gTou2TryfLSwDWzWTwDtLYf5kM5eTnLpGek,5243
|
|
10
|
+
ai_docs/scanner.py,sha256=KwJnu3GYL1lABeSVTlxlrddOuKkHyomQ39g6AdPbPh0,8793
|
|
11
|
+
ai_docs/summary.py,sha256=01cJer00yJnT7p7nKgvPy-H37A3PqHHVeA8RuzkwX8M,10357
|
|
12
|
+
ai_docs/tokenizer.py,sha256=G8btLH0IRJCx4b2jM8lWSzS0dcOZP-sAqwWYUQ5jF40,614
|
|
13
|
+
ai_docs/utils.py,sha256=kJKgO2R8ZQa58MBUZK2oEr03wFvVkRaWZYruxxJigGo,993
|
|
14
|
+
ai_docs/assets/mermaid.min.js,sha256=LPe7bNxKbqlto9MkpER9gwDR2nA85fMTEWCGQsD4Ymk,2908475
|
|
15
|
+
ai_docs_gen-0.1.2.dist-info/METADATA,sha256=0-ncf5tDSlADitUF5erpLL6Ew2Yl02HYDcoVnV_ejIM,7723
|
|
16
|
+
ai_docs_gen-0.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
17
|
+
ai_docs_gen-0.1.2.dist-info/entry_points.txt,sha256=C5tKlnOjrwbPgVbOB_zA8WeFjk05DXsMhq2UgTw5BDk,45
|
|
18
|
+
ai_docs_gen-0.1.2.dist-info/top_level.txt,sha256=Uqf4JT1_bI7m3yV5gs5kuL5Nmws5E2XT3W9yajZck2c,8
|
|
19
|
+
ai_docs_gen-0.1.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ai_docs
|