@kirrosh/apitool 0.4.3

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 (191) hide show
  1. package/.github/workflows/ci.yml +27 -0
  2. package/.github/workflows/release.yml +97 -0
  3. package/.mcp.json +9 -0
  4. package/APITOOL.md +195 -0
  5. package/BACKLOG.md +62 -0
  6. package/CHANGELOG.md +88 -0
  7. package/LICENSE +21 -0
  8. package/README.md +105 -0
  9. package/bun.lock +291 -0
  10. package/docs/GLOSSARY.md +182 -0
  11. package/docs/INDEX.md +21 -0
  12. package/docs/agent.md +135 -0
  13. package/docs/archive/APITOOL-pre-M22.md +831 -0
  14. package/docs/archive/BACKLOG-AI-NATIVE.md +56 -0
  15. package/docs/archive/M1-M2-parser-runner.md +216 -0
  16. package/docs/archive/M4-M7-reporter-cli.md +179 -0
  17. package/docs/archive/M5-M7-storage-junit.md +300 -0
  18. package/docs/archive/M6-webui.md +339 -0
  19. package/docs/ci.md +274 -0
  20. package/docs/generation-issues.md +67 -0
  21. package/generated/.env.yaml +3 -0
  22. package/install.ps1 +80 -0
  23. package/install.sh +113 -0
  24. package/package.json +46 -0
  25. package/scripts/run-mocked-tests.ts +45 -0
  26. package/seed-demo.ts +53 -0
  27. package/self-tests/auth.yaml +18 -0
  28. package/self-tests/collections-crud.yaml +46 -0
  29. package/self-tests/environments-crud.yaml +48 -0
  30. package/self-tests/export.yaml +32 -0
  31. package/self-tests/runs.yaml +16 -0
  32. package/src/bun-types.d.ts +5 -0
  33. package/src/cli/commands/add-api.ts +51 -0
  34. package/src/cli/commands/ai-generate.ts +106 -0
  35. package/src/cli/commands/chat.ts +43 -0
  36. package/src/cli/commands/ci-init.ts +126 -0
  37. package/src/cli/commands/collections.ts +41 -0
  38. package/src/cli/commands/coverage.ts +65 -0
  39. package/src/cli/commands/doctor.ts +127 -0
  40. package/src/cli/commands/envs.ts +218 -0
  41. package/src/cli/commands/init.ts +84 -0
  42. package/src/cli/commands/mcp.ts +16 -0
  43. package/src/cli/commands/run.ts +137 -0
  44. package/src/cli/commands/runs.ts +108 -0
  45. package/src/cli/commands/serve.ts +22 -0
  46. package/src/cli/commands/update.ts +142 -0
  47. package/src/cli/commands/validate.ts +18 -0
  48. package/src/cli/index.ts +500 -0
  49. package/src/cli/output.ts +24 -0
  50. package/src/cli/runtime.ts +7 -0
  51. package/src/core/agent/agent-loop.ts +116 -0
  52. package/src/core/agent/context-manager.ts +41 -0
  53. package/src/core/agent/system-prompt.ts +33 -0
  54. package/src/core/agent/tools/diagnose-failure.ts +51 -0
  55. package/src/core/agent/tools/explore-api.ts +40 -0
  56. package/src/core/agent/tools/index.ts +48 -0
  57. package/src/core/agent/tools/manage-environment.ts +40 -0
  58. package/src/core/agent/tools/query-results.ts +40 -0
  59. package/src/core/agent/tools/run-tests.ts +38 -0
  60. package/src/core/agent/tools/send-request.ts +44 -0
  61. package/src/core/agent/tools/validate-tests.ts +23 -0
  62. package/src/core/agent/types.ts +22 -0
  63. package/src/core/generator/ai/ai-generator.ts +61 -0
  64. package/src/core/generator/ai/llm-client.ts +159 -0
  65. package/src/core/generator/ai/output-parser.ts +307 -0
  66. package/src/core/generator/ai/prompt-builder.ts +153 -0
  67. package/src/core/generator/ai/types.ts +56 -0
  68. package/src/core/generator/coverage-scanner.ts +87 -0
  69. package/src/core/generator/data-factory.ts +115 -0
  70. package/src/core/generator/index.ts +10 -0
  71. package/src/core/generator/openapi-reader.ts +142 -0
  72. package/src/core/generator/schema-utils.ts +52 -0
  73. package/src/core/generator/serializer.ts +189 -0
  74. package/src/core/generator/types.ts +47 -0
  75. package/src/core/parser/filter.ts +14 -0
  76. package/src/core/parser/index.ts +21 -0
  77. package/src/core/parser/schema.ts +175 -0
  78. package/src/core/parser/types.ts +50 -0
  79. package/src/core/parser/variables.ts +146 -0
  80. package/src/core/parser/yaml-parser.ts +85 -0
  81. package/src/core/reporter/console.ts +175 -0
  82. package/src/core/reporter/index.ts +23 -0
  83. package/src/core/reporter/json.ts +9 -0
  84. package/src/core/reporter/junit.ts +78 -0
  85. package/src/core/reporter/types.ts +12 -0
  86. package/src/core/runner/assertions.ts +172 -0
  87. package/src/core/runner/execute-run.ts +75 -0
  88. package/src/core/runner/executor.ts +150 -0
  89. package/src/core/runner/http-client.ts +69 -0
  90. package/src/core/runner/index.ts +12 -0
  91. package/src/core/runner/types.ts +48 -0
  92. package/src/core/setup-api.ts +97 -0
  93. package/src/core/utils.ts +9 -0
  94. package/src/db/queries.ts +868 -0
  95. package/src/db/schema.ts +215 -0
  96. package/src/mcp/server.ts +47 -0
  97. package/src/mcp/tools/ci-init.ts +57 -0
  98. package/src/mcp/tools/coverage-analysis.ts +58 -0
  99. package/src/mcp/tools/explore-api.ts +84 -0
  100. package/src/mcp/tools/generate-missing-tests.ts +80 -0
  101. package/src/mcp/tools/generate-tests-guide.ts +353 -0
  102. package/src/mcp/tools/manage-environment.ts +123 -0
  103. package/src/mcp/tools/manage-server.ts +87 -0
  104. package/src/mcp/tools/query-db.ts +141 -0
  105. package/src/mcp/tools/run-tests.ts +66 -0
  106. package/src/mcp/tools/save-test-suite.ts +164 -0
  107. package/src/mcp/tools/send-request.ts +53 -0
  108. package/src/mcp/tools/setup-api.ts +49 -0
  109. package/src/mcp/tools/validate-tests.ts +42 -0
  110. package/src/tui/chat-ui.ts +150 -0
  111. package/src/web/routes/api.ts +234 -0
  112. package/src/web/routes/dashboard.ts +348 -0
  113. package/src/web/routes/runs.ts +64 -0
  114. package/src/web/schemas.ts +121 -0
  115. package/src/web/server.ts +134 -0
  116. package/src/web/static/htmx.min.js +1 -0
  117. package/src/web/static/style.css +265 -0
  118. package/src/web/views/layout.ts +46 -0
  119. package/src/web/views/results.ts +209 -0
  120. package/tests/agent/agent-loop.test.ts +61 -0
  121. package/tests/agent/context-manager.test.ts +59 -0
  122. package/tests/agent/system-prompt.test.ts +42 -0
  123. package/tests/agent/tools/diagnose-failure.test.ts +85 -0
  124. package/tests/agent/tools/explore-api.test.ts +59 -0
  125. package/tests/agent/tools/manage-environment.test.ts +78 -0
  126. package/tests/agent/tools/query-results.test.ts +77 -0
  127. package/tests/agent/tools/run-tests.test.ts +89 -0
  128. package/tests/agent/tools/send-request.test.ts +78 -0
  129. package/tests/agent/tools/validate-tests.test.ts +59 -0
  130. package/tests/ai/ai-generator.integration.test.ts +131 -0
  131. package/tests/ai/llm-client.test.ts +145 -0
  132. package/tests/ai/output-parser.test.ts +132 -0
  133. package/tests/ai/prompt-builder.test.ts +67 -0
  134. package/tests/ai/types.test.ts +55 -0
  135. package/tests/cli/args.test.ts +63 -0
  136. package/tests/cli/chat.test.ts +38 -0
  137. package/tests/cli/ci-init.test.ts +112 -0
  138. package/tests/cli/commands.test.ts +316 -0
  139. package/tests/cli/coverage.test.ts +58 -0
  140. package/tests/cli/doctor.test.ts +39 -0
  141. package/tests/cli/envs.test.ts +181 -0
  142. package/tests/cli/init.test.ts +80 -0
  143. package/tests/cli/runs.test.ts +94 -0
  144. package/tests/cli/safe-run.test.ts +103 -0
  145. package/tests/cli/update.test.ts +32 -0
  146. package/tests/core/generator/schema-utils.test.ts +108 -0
  147. package/tests/core/parser/nested-assertions.test.ts +80 -0
  148. package/tests/core/runner/root-body-assertions.test.ts +70 -0
  149. package/tests/db/chat-queries.test.ts +88 -0
  150. package/tests/db/chat-schema.test.ts +37 -0
  151. package/tests/db/environments.test.ts +131 -0
  152. package/tests/db/queries.test.ts +409 -0
  153. package/tests/db/schema.test.ts +141 -0
  154. package/tests/fixtures/.env.yaml +3 -0
  155. package/tests/fixtures/auth-token-test.yaml +8 -0
  156. package/tests/fixtures/bail/suite-a.yaml +6 -0
  157. package/tests/fixtures/bail/suite-b.yaml +6 -0
  158. package/tests/fixtures/crud.yaml +35 -0
  159. package/tests/fixtures/invalid-missing-name.yaml +5 -0
  160. package/tests/fixtures/invalid-no-method.yaml +6 -0
  161. package/tests/fixtures/petstore-auth.json +295 -0
  162. package/tests/fixtures/petstore-simple.json +151 -0
  163. package/tests/fixtures/post-only.yaml +12 -0
  164. package/tests/fixtures/simple.yaml +6 -0
  165. package/tests/fixtures/valid/.env.yaml +1 -0
  166. package/tests/fixtures/valid/a.yaml +5 -0
  167. package/tests/fixtures/valid/b.yml +5 -0
  168. package/tests/generator/coverage-scanner.test.ts +129 -0
  169. package/tests/generator/data-factory.test.ts +133 -0
  170. package/tests/generator/openapi-reader.test.ts +131 -0
  171. package/tests/integration/auth-flow.test.ts +217 -0
  172. package/tests/mcp/coverage-analysis.test.ts +64 -0
  173. package/tests/mcp/explore-api-schemas.test.ts +105 -0
  174. package/tests/mcp/explore-api.test.ts +49 -0
  175. package/tests/mcp/generate-missing-tests.test.ts +69 -0
  176. package/tests/mcp/manage-environment.test.ts +89 -0
  177. package/tests/mcp/save-test-suite.test.ts +116 -0
  178. package/tests/mcp/send-request.test.ts +79 -0
  179. package/tests/mcp/setup-api.test.ts +106 -0
  180. package/tests/mcp/tools.test.ts +248 -0
  181. package/tests/parser/schema.test.ts +134 -0
  182. package/tests/parser/variables.test.ts +227 -0
  183. package/tests/parser/yaml-parser.test.ts +69 -0
  184. package/tests/reporter/console.test.ts +256 -0
  185. package/tests/reporter/json.test.ts +98 -0
  186. package/tests/reporter/junit.test.ts +284 -0
  187. package/tests/runner/assertions.test.ts +262 -0
  188. package/tests/runner/executor.test.ts +310 -0
  189. package/tests/runner/http-client.test.ts +138 -0
  190. package/tests/web/routes.test.ts +160 -0
  191. package/tsconfig.json +31 -0
@@ -0,0 +1,831 @@
1
+ # APITOOL
2
+
3
+ **API Testing Platform** — CLI + WebUI для тестирования API из одного бинарника.
4
+
5
+ OpenAPI спецификация → AI-генерация тестов + дашборд + MCP для AI-агентов. Один файл. Ноль настроек.
6
+
7
+ ---
8
+
9
+ ## Содержание
10
+
11
+ - [Стек](#стек)
12
+ - [Структура проекта](#структура-проекта)
13
+ - [Модули](#модули)
14
+ - [M1: Parser](#m1-parser-srcoreparser)
15
+ - [M2: Runner](#m2-runner-srcorerunner)
16
+ - [M3: Generator](#m3-generator-scoregenerator)
17
+ - [M4: Reporter](#m4-reporter-srcorereporter)
18
+ - [M5: Storage](#m5-storage-srcdb)
19
+ - [M6: WebUI](#m6-webui-srcweb)
20
+ - [M7: CLI](#m7-cli-srccli)
21
+ - [M10: AI Generation](#m10-ai-generation-srccoregeneratorai)
22
+ - [Agent — AI Chat](#agent--ai-chat)
23
+ - [Формат YAML-тестов](#формат-yaml-тестов)
24
+ - [Поток данных](#поток-данных)
25
+ - [Roadmap](#roadmap-mvp)
26
+ - [Сборка и установка](#сборка-и-установка)
27
+ - [Принципы](#принципы)
28
+
29
+ ---
30
+
31
+ ## Стек
32
+
33
+ | Компонент | Технология |
34
+ |-----------|-----------|
35
+ | Runtime | Bun |
36
+ | Язык | TypeScript (strict) |
37
+ | HTTP-клиент | `fetch` (Bun native) |
38
+ | БД | SQLite (`bun:sqlite`) |
39
+ | Веб-сервер | Hono + `@hono/zod-openapi` |
40
+ | Frontend | HTMX + минимальный CSS |
41
+ | OpenAPI парсер | `@readme/openapi-parser` |
42
+ | Формат тестов | YAML |
43
+ | Сборка | `bun build --compile` |
44
+
45
+ ---
46
+
47
+ ## Структура проекта
48
+
49
+ ```
50
+ apitool/
51
+ ├── src/
52
+ │ ├── core/
53
+ │ │ ├── parser/
54
+ │ │ │ ├── yaml-parser.ts # Парсинг YAML → TestSuite
55
+ │ │ │ ├── schema.ts # JSON Schema для валидации
56
+ │ │ │ ├── variables.ts # Подстановка {{var}}, {{$generators}}
57
+ │ │ │ └── types.ts # TestSuite, TestStep, Assertion, Capture
58
+ │ │ ├── runner/
59
+ │ │ │ ├── http-client.ts # fetch-обёртка с таймаутами и retry
60
+ │ │ │ ├── executor.ts # Выполнение TestSuite, цепочки captures
61
+ │ │ │ ├── execute-run.ts # Shared executeRun() — парсинг, запуск, сохранение
62
+ │ │ │ ├── assertions.ts # Проверка ассертов (status, jsonpath, regex, type)
63
+ │ │ │ └── types.ts # TestRunResult, StepResult
64
+ │ │ ├── generator/
65
+ │ │ │ ├── openapi-reader.ts # Парсинг OpenAPI 3.x
66
+ │ │ │ ├── serializer.ts # RawSuite → YAML сериализация, sanitizeEnvName
67
+ │ │ │ ├── coverage-scanner.ts # Сканер покрытия для инкрементальной генерации
68
+ │ │ │ ├── data-factory.ts # Генерация тестовых данных по схеме
69
+ │ │ │ └── ai/ # AI-генерация тестов (M10)
70
+ │ │ │ ├── ai-generator.ts # Оркестратор: spec → prompt → LLM → YAML
71
+ │ │ │ ├── llm-client.ts # HTTP-клиент для LLM провайдеров
72
+ │ │ │ ├── prompt-builder.ts # Сборка системного + user промпта
73
+ │ │ │ ├── output-parser.ts # Парсинг JSON-ответа LLM → TestSuite
74
+ │ │ │ └── types.ts # AIGenerateOptions, AIGenerateResult
75
+ │ │ └── agent/ # AI Chat Agent (AI SDK v6)
76
+ │ │ ├── agent-loop.ts # generateText + tools + stopWhen
77
+ │ │ ├── context-manager.ts # Автосжатие длинных диалогов
78
+ │ │ ├── system-prompt.ts # Системный промпт с примерами tools
79
+ │ │ ├── types.ts # AgentConfig, ToolEvent, AgentTurnResult
80
+ │ │ └── tools/ # 7 tools как AI SDK tool()
81
+ │ │ └── reporter/
82
+ │ │ ├── json.ts # JSON-отчёт
83
+ │ │ ├── junit.ts # JUnit XML
84
+ │ │ └── console.ts # Цветной вывод в терминал
85
+ │ ├── db/
86
+ │ │ ├── schema.ts # Создание таблиц, миграции
87
+ │ │ └── queries.ts # CRUD-операции с историей прогонов
88
+ │ ├── web/
89
+ │ │ ├── server.ts # OpenAPIHono-сервер, /api/openapi.json
90
+ │ │ ├── schemas.ts # Zod-схемы для API (валидация + OpenAPI)
91
+ │ │ ├── routes/
92
+ │ │ │ ├── dashboard.ts # GET / — главная с trend chart, коллекциями
93
+ │ │ │ ├── collections.ts # GET /collections/:id, POST/DELETE /api/collections
94
+ │ │ │ ├── suites.ts # GET /collections/:id/suites, detail — test file browser
95
+ │ │ │ ├── ai-generate.ts # POST /api/ai-generate, save, GET /api/ai-generation/:id
96
+ │ │ │ ├── runs.ts # GET /runs (с фильтрами), GET /runs/:id
97
+ │ │ │ ├── environments.ts # CRUD окружений: list, detail, create, update, delete
98
+ │ │ │ ├── explorer.ts # GET /explorer — дерево API
99
+ │ │ │ └── api.ts # POST /api/run, POST /api/try, GET /api/export
100
+ │ │ ├── views/
101
+ │ │ │ ├── layout.ts # HTML layout, escapeHtml()
102
+ │ │ │ └── trend-chart.ts # Shared SVG trend chart component
103
+ │ │ └── static/ # HTMX, CSS, иконки
104
+ │ ├── mcp/ # MCP Server — AI-agent integration (M15)
105
+ │ │ ├── server.ts # McpServer setup + stdio transport
106
+ │ │ └── tools/
107
+ │ │ ├── run-tests.ts # run_tests — запуск тестов
108
+ │ │ ├── validate-tests.ts # validate_tests — валидация YAML
109
+ │ │ ├── list-collections.ts # list_collections — список коллекций
110
+ │ │ ├── list-runs.ts # list_runs — список прогонов
111
+ │ │ ├── get-run-results.ts # get_run_results — детали прогона
112
+ │ │ ├── list-environments.ts # list_environments — список окружений
113
+ │ │ ├── send-request.ts # send_request — ad-hoc HTTP запросы
114
+ │ │ ├── explore-api.ts # explore_api — просмотр OpenAPI спеки
115
+ │ │ ├── manage-environment.ts # manage_environment — CRUD окружений
116
+ │ │ ├── diagnose-failure.ts # diagnose_failure — диагностика падений
117
+ │ │ └── coverage-analysis.ts # coverage_analysis — анализ покрытия
118
+ │ └── cli/
119
+ │ ├── index.ts # Точка входа, роутинг команд, --api резолвинг
120
+ │ ├── commands/
121
+ │ │ ├── add-api.ts # apitool add-api — регистрация нового API
122
+ │ │ ├── run.ts # apitool run
123
+ │ │ ├── ai-generate.ts # apitool ai-generate
124
+ │ │ ├── collections.ts # apitool collections
125
+ │ │ ├── serve.ts # apitool serve
126
+ │ │ ├── validate.ts # apitool validate
127
+ │ │ ├── mcp.ts # apitool mcp
128
+ │ │ ├── request.ts # apitool request
129
+ │ │ ├── envs.ts # apitool envs (--api для scoped envs)
130
+ │ │ ├── runs.ts # apitool runs
131
+ │ │ ├── coverage.ts # apitool coverage
132
+ │ │ ├── chat.ts # apitool chat
133
+ │ │ ├── init.ts # apitool init
134
+ │ │ ├── doctor.ts # apitool doctor
135
+ │ │ └── update.ts # apitool update
136
+ │ ├── runtime.ts # Определение standalone vs dev режима
137
+ │ └── output.ts # Форматирование CLI-вывода
138
+ ├── tests/ # Тесты самого инструмента
139
+ ├── self-tests/ # Сгенерированные skeleton-тесты для apitool API
140
+ ├── examples/ # Примеры YAML-тестов
141
+ ├── docs/ # Документация
142
+ ├── package.json
143
+ ├── tsconfig.json
144
+ └── bunfig.toml
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Модули
150
+
151
+ ### M1: Parser (`src/core/parser/`)
152
+
153
+ Читает YAML-файлы, валидирует, возвращает типизированные структуры.
154
+
155
+ **Вход:** путь к `.yaml` файлу или директории.
156
+ **Выход:** `TestSuite[]`
157
+
158
+ При парсинге директории невалидные файлы пропускаются (один сломанный файл не блокирует остальные). Каждый распарсенный suite получает `_source` — путь к исходному файлу (используется для AI badge в WebUI).
159
+
160
+ Функция `parseDirectorySafe(dirPath)` возвращает `{ suites: TestSuite[], errors: { file: string, error: string }[] }` — собирает ошибки парсинга вместо их игнорирования. Используется в WebUI для показа broken-файлов. Функции `parse()` / `parseDirectory()` не изменены (обратная совместимость).
161
+
162
+ Ключевые типы:
163
+
164
+ ```typescript
165
+ interface TestSuite {
166
+ name: string;
167
+ base_url?: string;
168
+ headers?: Record<string, string>; // общие заголовки для всех тестов
169
+ tests: TestStep[];
170
+ }
171
+
172
+ interface TestStep {
173
+ name: string;
174
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
175
+ path: string;
176
+ headers?: Record<string, string>;
177
+ json?: unknown; // тело запроса
178
+ form?: Record<string, string>; // form-urlencoded
179
+ query?: Record<string, string>; // query-параметры
180
+ expect: {
181
+ status?: number;
182
+ body?: Record<string, AssertionRule>; // JSONPath-подобные проверки
183
+ headers?: Record<string, string>;
184
+ duration?: number; // максимальное время ответа (мс)
185
+ };
186
+ }
187
+
188
+ interface AssertionRule {
189
+ capture?: string; // сохранить значение в переменную
190
+ type?: "string" | "integer" | "number" | "boolean" | "array" | "object";
191
+ equals?: unknown; // точное совпадение
192
+ contains?: string; // строка содержит подстроку
193
+ matches?: string; // regex
194
+ gt?: number; // больше
195
+ lt?: number; // меньше
196
+ exists?: boolean; // поле существует / не существует
197
+ }
198
+ ```
199
+
200
+ Встроенные генераторы переменных:
201
+
202
+ | Генератор | Пример значения |
203
+ |-----------|----------------|
204
+ | `{{$randomName}}` | "John Smith" |
205
+ | `{{$randomEmail}}` | "xk92m@test.com" |
206
+ | `{{$uuid}}` | "550e8400-e29b-41d4-a716-446655440000" |
207
+ | `{{$timestamp}}` | 1708876800 |
208
+ | `{{$randomInt}}` | 42 |
209
+ | `{{$randomString}}` | "aBcDeFgH" |
210
+
211
+ Environments — файлы `.env.yaml` и/или DB:
212
+
213
+ ```yaml
214
+ # .env.yaml (по умолчанию)
215
+ base_url: http://localhost:3000/api
216
+ token: dev-token-123
217
+
218
+ # .env.staging.yaml
219
+ base_url: https://staging.example.com/api
220
+ token: staging-token-456
221
+ ```
222
+
223
+ Использование: `apitool run tests/ --env staging` или `apitool run --api myapi --env staging`
224
+
225
+ **Приоритет резолва переменных:** файл `.env.<name>.yaml` > DB scoped env (привязан к коллекции) > DB global env (collection_id IS NULL) > генераторы > оставить `{{raw}}`
226
+
227
+ ---
228
+
229
+ ### M2: Runner (`src/core/runner/`)
230
+
231
+ Выполняет `TestSuite`, отправляет HTTP-запросы, проверяет ассерты, передаёт captures между шагами.
232
+
233
+ **Вход:** `TestSuite` + `Environment`
234
+ **Выход:** `TestRunResult`
235
+
236
+ ```typescript
237
+ interface TestRunResult {
238
+ suite_name: string;
239
+ started_at: string; // ISO 8601
240
+ finished_at: string;
241
+ total: number;
242
+ passed: number;
243
+ failed: number;
244
+ skipped: number;
245
+ steps: StepResult[];
246
+ }
247
+
248
+ interface StepResult {
249
+ name: string;
250
+ status: "pass" | "fail" | "skip" | "error";
251
+ duration_ms: number;
252
+ request: {
253
+ method: string;
254
+ url: string;
255
+ headers: Record<string, string>;
256
+ body?: string;
257
+ };
258
+ response: {
259
+ status: number;
260
+ headers: Record<string, string>;
261
+ body: string; // сырой текст (для отчёта)
262
+ body_parsed?: unknown; // JSON если application/json
263
+ };
264
+ assertions: AssertionResult[];
265
+ captures: Record<string, unknown>; // извлечённые значения
266
+ error?: string; // если error/skip — причина
267
+ }
268
+
269
+ interface AssertionResult {
270
+ field: string; // "status" | "body.id" | "headers.content-type"
271
+ rule: string; // "equals 201" | "type integer" | "matches .*@.*"
272
+ passed: boolean;
273
+ actual: unknown;
274
+ expected: unknown;
275
+ }
276
+ ```
277
+
278
+ Логика выполнения:
279
+
280
+ 1. Подставить переменные окружения и captures в URL, headers, body
281
+ 2. Отправить HTTP-запрос (fetch)
282
+ 3. Извлечь captures из ответа
283
+ 4. Проверить все ассерты
284
+ 5. Если шаг упал и он имеет `capture` — последующие шаги, зависящие от этой переменной, получают `status: skip`
285
+
286
+ Параллельность: файлы (suites) выполняются параллельно, шаги внутри suite — последовательно (из-за captures).
287
+
288
+ Конфигурация:
289
+
290
+ ```yaml
291
+ # в YAML-тесте или глобально
292
+ config:
293
+ timeout: 30000 # мс, таймаут на один запрос
294
+ retries: 0 # количество повторов при ошибке
295
+ retry_delay: 1000 # задержка между повторами
296
+ follow_redirects: true
297
+ verify_ssl: true
298
+ ```
299
+
300
+ ---
301
+
302
+ ### M3: Generator (`src/core/generator/`)
303
+
304
+ Утилиты для работы с OpenAPI и генерации тестов. Шаблонная генерация (CRUD/skeleton) удалена — остались только AI-генерация и вспомогательные модули.
305
+
306
+ - `openapi-reader.ts` — парсинг OpenAPI 3.x (файл или URL), `readOpenApiSpec()`, `extractEndpoints()`, `extractSecuritySchemes()`
307
+ - `serializer.ts` — конвертирует `RawSuite` в YAML формат, содержит `sanitizeEnvName()`
308
+ - `coverage-scanner.ts` — анализ покрытия: `scanCoveredEndpoints()`, `filterUncoveredEndpoints()`
309
+ - `data-factory.ts` — генерация тестовых данных по JSON Schema
310
+ - `ai/` — AI-генерация тестов (см. [M10: AI Generation](#m10-ai-generation-srccoregeneratorai))
311
+
312
+ ---
313
+
314
+ ### M4: Reporter (`src/core/reporter/`)
315
+
316
+ Формирует отчёты из `TestRunResult`.
317
+
318
+ **JSON** — полный дамп `TestRunResult`, сохраняется в SQLite.
319
+
320
+ **JUnit XML** — для CI:
321
+
322
+ ```xml
323
+ <testsuites tests="5" failures="1" time="2.34">
324
+ <testsuite name="Users CRUD" tests="5" failures="1">
325
+ <testcase name="Create user" time="0.45"/>
326
+ <testcase name="Get user" time="0.12"/>
327
+ <testcase name="Update user" time="0.31">
328
+ <failure message="Expected status 200, got 500">...</failure>
329
+ </testcase>
330
+ </testsuite>
331
+ </testsuites>
332
+ ```
333
+
334
+ **Console** — цветной вывод:
335
+
336
+ ```
337
+ Users CRUD
338
+ ✓ Create user (450ms)
339
+ ✓ Get user (120ms)
340
+ ✗ Update user (310ms)
341
+ Expected status 200, got 500
342
+ ✓ Delete user (89ms)
343
+ ○ Verify deleted (skipped)
344
+
345
+ Results: 3 passed, 1 failed, 1 skipped (1.2s)
346
+ ```
347
+
348
+ ---
349
+
350
+ ### M5: Storage (`src/db/`)
351
+
352
+ SQLite через `bun:sqlite`. Файл `apitool.db` создаётся автоматически при первом запуске.
353
+
354
+ ```sql
355
+ CREATE TABLE collections (
356
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
357
+ name TEXT NOT NULL,
358
+ base_dir TEXT, -- корневая директория коллекции
359
+ test_path TEXT NOT NULL, -- абсолютный путь к тестам (forward slashes)
360
+ openapi_spec TEXT, -- путь к OpenAPI спеке
361
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
362
+ );
363
+
364
+ CREATE TABLE runs (
365
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
366
+ started_at TEXT NOT NULL, -- ISO 8601
367
+ finished_at TEXT,
368
+ total INTEGER NOT NULL DEFAULT 0,
369
+ passed INTEGER NOT NULL DEFAULT 0,
370
+ failed INTEGER NOT NULL DEFAULT 0,
371
+ skipped INTEGER NOT NULL DEFAULT 0,
372
+ trigger TEXT DEFAULT 'manual', -- manual | ci | scheduled
373
+ commit_sha TEXT,
374
+ branch TEXT,
375
+ environment TEXT,
376
+ duration_ms INTEGER,
377
+ collection_id INTEGER REFERENCES collections(id) -- nullable, привязка к коллекции
378
+ );
379
+
380
+ CREATE TABLE results (
381
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
382
+ run_id INTEGER NOT NULL REFERENCES runs(id),
383
+ suite_name TEXT NOT NULL,
384
+ test_name TEXT NOT NULL,
385
+ status TEXT NOT NULL, -- pass | fail | skip | error
386
+ duration_ms INTEGER NOT NULL,
387
+ request_method TEXT,
388
+ request_url TEXT,
389
+ request_body TEXT,
390
+ response_status INTEGER,
391
+ response_body TEXT, -- хранить только при fail (экономия)
392
+ error_message TEXT,
393
+ assertions TEXT, -- JSON массив AssertionResult[]
394
+ captures TEXT -- JSON Record<string, unknown>
395
+ );
396
+
397
+ CREATE TABLE environments (
398
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
399
+ name TEXT NOT NULL,
400
+ collection_id INTEGER REFERENCES collections(id) ON DELETE CASCADE,
401
+ variables TEXT NOT NULL -- JSON
402
+ );
403
+ -- Уникальность: (name, collection_id) — scoped к коллекции
404
+ -- + отдельный индекс для глобальных (collection_id IS NULL)
405
+ CREATE UNIQUE INDEX idx_env_name_collection ON environments(name, collection_id);
406
+ CREATE UNIQUE INDEX idx_env_name_global ON environments(name) WHERE collection_id IS NULL;
407
+
408
+ CREATE TABLE ai_generations (
409
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
410
+ collection_id INTEGER REFERENCES collections(id),
411
+ prompt TEXT NOT NULL,
412
+ model TEXT NOT NULL,
413
+ provider TEXT NOT NULL, -- ollama | openai | anthropic | custom
414
+ generated_yaml TEXT, -- результат генерации (YAML)
415
+ output_path TEXT, -- путь к сохранённому файлу
416
+ status TEXT NOT NULL, -- success | error
417
+ error_message TEXT,
418
+ prompt_tokens INTEGER,
419
+ completion_tokens INTEGER,
420
+ duration_ms INTEGER,
421
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
422
+ );
423
+
424
+ -- Индексы для дашборда
425
+ CREATE INDEX idx_runs_started ON runs(started_at DESC);
426
+ CREATE INDEX idx_runs_collection ON runs(collection_id);
427
+ CREATE INDEX idx_results_run ON results(run_id);
428
+ CREATE INDEX idx_results_status ON results(status);
429
+ CREATE INDEX idx_results_name ON results(suite_name, test_name);
430
+ CREATE INDEX idx_collections_name ON collections(name);
431
+ ```
432
+
433
+ Миграции: массив SQL-строк с номером версии. При старте проверяется `PRAGMA user_version`, применяются недостающие миграции. Текущая версия: **5**.
434
+
435
+ Версии: V1 — базовые таблицы, V2 — `ai_generations`, V3 — `chat_sessions`/`chat_messages`, V4 — `settings`, V5 — `base_dir` в collections + `collection_id` в environments (scoped envs).
436
+
437
+ ---
438
+
439
+ ### M6: WebUI (`src/web/`)
440
+
441
+ Запускается командой `apitool serve --port 8080`.
442
+
443
+ Hono-сервер рендерит HTML, интерактивность через HTMX.
444
+
445
+ **Страницы:**
446
+
447
+ | Route | Описание |
448
+ |-------|----------|
449
+ | `GET /` | Dashboard: глобальные метрики, grid коллекций, форма добавления, recent runs, slowest/flaky |
450
+ | `GET /collections/:id` | Детали коллекции: метрики, trend chart, test suites (кликабельные — YAML, source, AI prompt/model), broken-файлы с Delete, per-suite Run, таблица прогонов |
451
+ | `GET /runs` | Список прогонов с фильтрацией (статус, environment, дата, поиск по имени теста) и пагинацией |
452
+ | `GET /runs/:id` | Детали прогона: каждый тест → запрос/ответ/ассерты + кнопки Export (JUnit XML, JSON) |
453
+ | `GET /environments` | Список окружений: имя, scope (global/api:N), кол-во переменных, actions (Edit/Delete), форма создания |
454
+ | `GET /environments/:id` | Редактор окружения: key-value editor с добавлением/удалением строк |
455
+ | `POST /environments` | Создать окружение (HTMX form-data) |
456
+ | `PUT /environments/:id` | Обновить переменные окружения (HTMX form-data) |
457
+ | `DELETE /environments/:id` | Удалить окружение (HTMX) |
458
+ | `GET /collections/:id/suites` | Список YAML test files: имя suite, кол-во тестов, base URL, Run/View/Delete |
459
+ | `GET /collections/:id/suites/detail?file=` | Детали suite: карточки метрик, таблица шагов с method badge, Run Suite |
460
+ | `GET /explorer` | Дерево API из OpenAPI, параметры, описания, multi-auth panel |
461
+ | `POST /collections` | Создать коллекцию из формы на дашборде (HTMX form-data) |
462
+ | `DELETE /collections/:id` | Удалить коллекцию (HTMX, runs unlinked) |
463
+ | `POST /run` | Запустить прогон из WebUI (HTMX form-data), авто-привязка к коллекции |
464
+ | `POST /api/try` | Отправить единичный запрос из Explorer (HTMX, с auth injection) |
465
+ | `POST /api/authorize` | Proxy login для Bearer auth (username/password → token) |
466
+ | `GET /api/export/:runId/junit` | Скачать JUnit XML отчёт для прогона |
467
+ | `GET /api/export/:runId/json` | Скачать JSON отчёт для прогона |
468
+ | `POST /api/ai-generate` | Генерация тестов через AI (Ollama/OpenAI/Anthropic) |
469
+ | `POST /api/ai-generate/save` | Сохранить YAML в файл, записать `output_path` в БД, показать подтверждение |
470
+ | `POST /api/ai-generate/delete-file` | Удалить broken/ненужный файл из коллекции (с проверкой что файл внутри test_path) |
471
+ | `GET /api/ai-generation/:id` | Просмотр деталей генерации (YAML, метаданные, путь файла) — HTMX fragment |
472
+
473
+ Dashboard-метрики (SQL-запросы):
474
+
475
+ - **Pass rate trend:** последние 30 прогонов, `passed / total * 100` — SVG line chart с area fill
476
+ - **Flaky-тесты:** тесты с разным статусом в последних N прогонах
477
+ - **Средняя длительность:** `AVG(duration_ms)` по тестам
478
+ - **Самые медленные:** `ORDER BY duration_ms DESC LIMIT 5`
479
+
480
+ Фильтрация прогонов (`GET /runs`):
481
+ - **Status:** All / Has Failures / All Passed
482
+ - **Environment:** dropdown из `listEnvironments()` + `getDistinctEnvironments()` (объединение определённых и из истории прогонов)
483
+ - **Date range:** from / to
484
+ - **Test name:** поиск по имени теста (LIKE)
485
+
486
+ Экспорт результатов (`/runs/:id`):
487
+ - **JUnit XML** — `GET /api/export/:runId/junit` (Content-Disposition: attachment)
488
+ - **JSON** — `GET /api/export/:runId/json` (Content-Disposition: attachment)
489
+
490
+ Статика: HTMX (CDN или вкомпилирован), CSS (один файл, без фреймворков).
491
+
492
+ ---
493
+
494
+ ### M7: CLI (`src/cli/`)
495
+
496
+ | Команда | Описание | Основные флаги |
497
+ |---------|----------|----------------|
498
+ | `add-api <name>` | Регистрация нового API (создаёт коллекцию, директории, .env.yaml) | `--spec <path-or-url>`, `--dir <directory>`, `--env key=value` |
499
+ | `run <path>` | Запуск тестов (авто-привязка к коллекции) | `--api <name>`, `--env`, `--report json\|junit\|console`, `--timeout`, `--bail`, `--no-db`, `--db`, `--auth-token`, `--safe` |
500
+ | `ai-generate` | AI-генерация тестов из OpenAPI | `--api <name>`, `--from <spec>`, `--prompt`, `--provider`, `--model`, `--api-key`, `--base-url`, `--output` |
501
+ | `request <METHOD> <URL>` | Ad-hoc HTTP запрос с цветным выводом | `--header "K:V"` (multiple), `--body '{}'`, `--env`, `--timeout` |
502
+ | `envs [list\|get\|set\|delete]` | Управление окружениями (CRUD) | `--api <name>`, `envs get <name>`, `envs set <name> K=V ...`, `envs delete <name>` |
503
+ | `runs [id]` | История прогонов и детали | `--limit <n>`, `--db <path>` |
504
+ | `coverage` | Анализ покрытия API тестами | `--api <name>`, `--spec <path>`, `--tests <dir>` |
505
+ | `collections` | Список коллекций с pass rate и датой последнего прогона | `--db <path>` |
506
+ | `serve` | Запуск WebUI | `--port`, `--host`, `--openapi <spec>`, `--db <path>`, `--watch` |
507
+ | `validate` | Проверка YAML-тестов | `<path>` |
508
+ | `chat` | Интерактивный AI-агент для управления тестами | `--provider`, `--model`, `--api-key`, `--base-url`, `--safe` |
509
+ | `mcp` | MCP-сервер для AI-агентов | `--db` |
510
+ | `doctor` | Диагностика (DB, тесты, OpenAPI, Ollama) | `--db <path>` |
511
+ | `init` | Scaffolding нового проекта | `--force` |
512
+ | `update` | Обновление до последней версии | `--force` |
513
+
514
+ Флаг `--api <name>` — альтернатива пути, автоматически резолвит `test_path`, `openapi_spec` и `base_dir` из коллекции в DB. Пример: `apitool run --api petstore` вместо `apitool run ./apis/petstore/tests/`.
515
+
516
+ Exit codes: `0` — все тесты прошли, `1` — есть падения, `2` — ошибка конфигурации.
517
+
518
+ ---
519
+
520
+ ### M10: AI Generation (`src/core/generator/ai/`)
521
+
522
+ AI-генерация тестов из OpenAPI-спецификации с использованием LLM.
523
+
524
+ **Архитектура:**
525
+
526
+ ```
527
+ OpenAPI spec + prompt
528
+
529
+
530
+ prompt-builder.ts → системный промпт + контекст API + пользовательский запрос
531
+
532
+
533
+ llm-client.ts → HTTP-запрос к LLM-провайдеру
534
+
535
+
536
+ output-parser.ts → JSON-ответ LLM → TestSuite[] → serializeSuite() → YAML
537
+ ```
538
+
539
+ **Ключевое решение:** LLM генерирует **JSON** (не YAML), затем `serializeSuite()` конвертирует в YAML. Это обеспечивает валидный формат вне зависимости от качества ответа модели.
540
+
541
+ **Провайдеры:**
542
+
543
+ | Провайдер | Base URL | Модель по умолчанию |
544
+ |-----------|----------|-------------------|
545
+ | `ollama` | `http://localhost:11434/v1` | `qwen3:4b` |
546
+ | `openai` | `https://api.openai.com/v1` | `gpt-4o` |
547
+ | `anthropic` | `https://api.anthropic.com` | `claude-sonnet-4-20250514` |
548
+ | `custom` | задаётся через `--base-url` | задаётся через `--model` |
549
+
550
+ **CLI:** `apitool ai-generate --from <spec> --prompt "..." --provider <name> --model <name> --api-key <key> --output <dir>`
551
+
552
+ **WebUI:**
553
+ - Форма генерации: выбор провайдера, модель, промпт
554
+ - Preview сгенерированного YAML перед сохранением
555
+ - Сохранение в файл с привязкой к коллекции
556
+ - История генераций с View/Reuse
557
+ - AI badge на suite'ах, сгенерированных через AI
558
+
559
+ **БД:** таблица `ai_generations` — хранит prompt, model, provider, результат, token usage, duration.
560
+
561
+ ---
562
+
563
+ ### Agent — AI Chat
564
+
565
+ Интерактивный AI-агент в терминале. Использует AI SDK v6 (`generateText` + `tool()` + `stopWhen`).
566
+
567
+ **Запуск:** `apitool chat` (Ollama/qwen3:4b по умолчанию), `apitool chat --provider openai --api-key sk-...`
568
+
569
+ **7 tools:** `run_tests`, `validate_tests`, `query_results`, `manage_environment`, `diagnose_failure`, `send_request`, `explore_api` — каждый как AI SDK `tool()` с Zod `inputSchema`.
570
+
571
+ **Особенности:**
572
+ - Safe mode (`--safe`) — принудительно только GET-тесты
573
+ - Context manager — автосжатие диалога при >20 сообщений
574
+ - Для Ollama system prompt инжектируется в user message (workaround для thinking-моделей)
575
+
576
+ Подробная документация: [docs/agent.md](docs/agent.md)
577
+
578
+ ---
579
+
580
+ ## Формат YAML-тестов
581
+
582
+ ### Минимальный пример
583
+
584
+ ```yaml
585
+ name: Health Check
586
+ tests:
587
+ - name: "API is alive"
588
+ GET: /health
589
+ expect:
590
+ status: 200
591
+ ```
592
+
593
+ ### Полный пример (CRUD-цепочка)
594
+
595
+ ```yaml
596
+ name: Users CRUD
597
+ base_url: "{{base}}"
598
+ headers:
599
+ Authorization: "Bearer {{token}}"
600
+ Content-Type: application/json
601
+
602
+ config:
603
+ timeout: 10000
604
+ retries: 1
605
+
606
+ tests:
607
+ - name: "Create user"
608
+ POST: /users
609
+ json:
610
+ name: "{{$randomName}}"
611
+ email: "{{$randomEmail}}"
612
+ expect:
613
+ status: 201
614
+ body:
615
+ id: { capture: user_id, type: integer }
616
+ name: { type: string }
617
+ duration: 2000
618
+
619
+ - name: "Get created user"
620
+ GET: /users/{{user_id}}
621
+ expect:
622
+ status: 200
623
+ body:
624
+ id: { equals: "{{user_id}}" }
625
+ email: { matches: ".+@.+" }
626
+
627
+ - name: "Update user"
628
+ PUT: /users/{{user_id}}
629
+ json:
630
+ name: "Updated Name"
631
+ expect:
632
+ status: 200
633
+ body:
634
+ name: { equals: "Updated Name" }
635
+
636
+ - name: "List users"
637
+ GET: /users
638
+ query:
639
+ page: "1"
640
+ limit: "10"
641
+ expect:
642
+ status: 200
643
+ body:
644
+ data: { type: array }
645
+ total: { type: integer, gt: 0 }
646
+
647
+ - name: "Delete user"
648
+ DELETE: /users/{{user_id}}
649
+ expect:
650
+ status: 204
651
+
652
+ - name: "Verify deleted"
653
+ GET: /users/{{user_id}}
654
+ expect:
655
+ status: 404
656
+ ```
657
+
658
+ ---
659
+
660
+ ## Поток данных
661
+
662
+ ```
663
+ CLI WebUI
664
+ │ │
665
+ ▼ ▼
666
+ ┌──────────┐ ┌───────────┐
667
+ │ Commands │ │ Hono │
668
+ └────┬─────┘ └─────┬─────┘
669
+ │ │
670
+ ▼ ▼
671
+ ┌───────────────────────────────────────┐
672
+ │ Core Engine │
673
+ │ │
674
+ │ ┌──────────┐ ┌──────────┐ │
675
+ │ │ Parser │→ │ Runner │ │
676
+ │ └──────────┘ └────┬─────┘ │
677
+ │ │ │
678
+ │ ┌──────────┐ ┌────▼─────┐ │
679
+ │ │Generator │ │ Reporter │ │
680
+ │ └──────────┘ └────┬─────┘ │
681
+ └─────────────────────┼──────────────────┘
682
+
683
+ ┌─────▼─────┐
684
+ │ Storage │
685
+ │ (SQLite) │
686
+ └───────────┘
687
+ ```
688
+
689
+ ---
690
+
691
+ ## Roadmap (MVP)
692
+
693
+ | Модуль | Статус | Коммит | Результат |
694
+ |--------|--------|--------|-----------|
695
+ | M1 (Parser) + M2 (Runner) | DONE | `4e270ab` | `apitool run test.yaml` работает |
696
+ | M3 (Generator) | DONE | `e3d94d8` | OpenAPI reader, data factory, serializer (шаблонная генерация удалена → только AI) |
697
+ | M4 (Reporter) + M7 (CLI basic) | DONE | `e179180` | console/json/junit отчёты, CLI команды |
698
+ | M5 (Storage/SQLite) | DONE | `2245e79` | История прогонов в apitool.db |
699
+ | M6 (WebUI) | DONE | `94a58e4` | `apitool serve --port 8080 --openapi <spec>`, multi-auth panel, trend chart, filters, export |
700
+ | M7 (CLI) | DONE | — | run, generate, ai-generate, collections, serve, validate |
701
+ | M8 (Standalone binary) | DONE | `6bd2401` | `bun run build` → `apitool.exe`, CSS embedded, runtime detection |
702
+ | M9 (Collections) | DONE | `56a3995` | Сущность Collection, группировка runs, CLI `collections`, dashboard redesign |
703
+ | M10 (AI Generate) | DONE | `7901df7` | AI-генерация тестов, история генераций с View/Reuse, AI badge на сьютах, сохранение с output_path |
704
+ | M11 (Suite Details) | DONE | `9e4e87e` | Кликабельные сьюты (YAML, source file, AI prompt/model), показ broken-файлов с Delete, per-suite Run, улучшенный AI-промпт |
705
+ | M12 (Public Release) | DONE | `da9e027` | README, CHANGELOG, CI pipeline, GitHub Release workflow |
706
+ | M13 (Environments) | DONE | — | CRUD окружений в WebUI, key-value editor, env selector при запуске тестов |
707
+ | M14 (Self-Documented API) | DONE | — | OpenAPI спека из собственного API, инкрементальная генерация, dogfooding |
708
+ | M15 (MCP Server) | DONE | — | 11 MCP tools для AI-агентов, stdio transport |
709
+ | M16 (Generate Wizard) | DONE | — | Safe mode, auth-token, env creation, relative base_url |
710
+ | M19 (Unified Capabilities) | DONE | — | request, envs, runs, coverage CLI + 5 MCP tools + 2 agent tools |
711
+ | M20 (Post-M19) | DONE | — | doctor, envs import/export, DB singleton fix |
712
+ | M21 (Collection Architecture) | DONE | — | add-api, --api flag, environment scoping, base_dir, DB V5 |
713
+
714
+ ---
715
+
716
+ ## Сборка и установка
717
+
718
+ ```bash
719
+ # Разработка (требуется Bun runtime)
720
+ bun run src/cli/index.ts run tests/
721
+
722
+ # Компиляция в standalone бинарник
723
+ bun run build
724
+ # или: bun build --compile src/cli/index.ts --outfile apitool
725
+
726
+ # Результат: apitool / apitool.exe — один файл, Bun не нужен
727
+ ./apitool run tests/*.yaml
728
+ ./apitool serve --port 8080
729
+ ```
730
+
731
+ ### Установка
732
+
733
+ Скопировать бинарник в любую папку из `PATH`:
734
+
735
+ ```bash
736
+ # Linux / macOS
737
+ cp apitool /usr/local/bin/
738
+
739
+ # Windows — скопировать apitool.exe в папку из PATH
740
+ ```
741
+
742
+ После этого `apitool` доступен из любой директории.
743
+
744
+ ### Как работает бинарник
745
+
746
+ Бинарник **stateless** — он ничего не хранит внутри себя. Все файлы создаются в **текущей рабочей директории** (cwd):
747
+
748
+ ```bash
749
+ cd ~/projects/myapi
750
+
751
+ # Регистрация API — создаст ./apis/myapi/, .env.yaml, запись в DB
752
+ apitool add-api myapi --spec openapi.json
753
+
754
+ # AI-генерация тестов
755
+ apitool ai-generate --api myapi --prompt "test all user endpoints"
756
+
757
+ # Запуск тестов — создаст ./apitool.db для хранения результатов
758
+ apitool run --api myapi
759
+
760
+ # Web-дашборд — читает apitool.db и спеку из cwd
761
+ apitool serve --port 4000 --openapi openapi.json
762
+ ```
763
+
764
+ | Артефакт | Расположение | Описание |
765
+ |----------|-------------|----------|
766
+ | YAML-тесты | `./generated/` (или `--output <dir>`) | Сгенерированные/написанные тесты |
767
+ | `apitool.db` | `./apitool.db` (или `--db <path>`) | SQLite — история прогонов |
768
+ | OpenAPI спека | указывается через `--from` / `--openapi` | Читается, не копируется |
769
+
770
+ ### Runtime detection
771
+
772
+ ```bash
773
+ ./apitool --version
774
+ # apitool 0.1.0 (standalone) — из скомпилированного бинарника
775
+
776
+ bun src/cli/index.ts --version
777
+ # apitool 0.1.0 (bun) — из dev-режима
778
+ ```
779
+
780
+ ---
781
+
782
+ ## M15: MCP Server (AI-agent интеграция)
783
+
784
+ APITOOL предоставляет MCP (Model Context Protocol) сервер для интеграции с AI-агентами (Claude Code, Cursor, Windsurf, Cline).
785
+
786
+ ### Запуск
787
+
788
+ ```bash
789
+ apitool mcp # stdio transport
790
+ apitool mcp --db ./my.db # с кастомным путём к БД
791
+ ```
792
+
793
+ ### MCP Tools
794
+
795
+ | Tool | Описание |
796
+ |------|----------|
797
+ | `run_tests` | Запуск тестов из YAML-файла/директории, возврат summary |
798
+ | `validate_tests` | Валидация YAML без запуска |
799
+ | `list_collections` | Список коллекций с статистикой |
800
+ | `list_runs` | Список последних прогонов |
801
+ | `get_run_results` | Детальные результаты конкретного прогона |
802
+ | `list_environments` | Список окружений (ключи переменных, без значений) |
803
+ | `send_request` | Ad-hoc HTTP запрос с variable interpolation из окружений |
804
+ | `explore_api` | Просмотр OpenAPI спеки — endpoints, servers, security schemes, фильтр по tag |
805
+ | `manage_environment` | CRUD окружений — list, get, set, delete (с `collectionName` для scoping) |
806
+ | `diagnose_failure` | Диагностика падений — анализ failed steps и assertion mismatches |
807
+ | `coverage_analysis` | Анализ покрытия API тестами (spec vs test files) |
808
+
809
+ ### Конфигурация Claude Code
810
+
811
+ ```json
812
+ // .claude/settings.json или claude_desktop_config.json
813
+ {
814
+ "mcpServers": {
815
+ "apitool": {
816
+ "command": "apitool",
817
+ "args": ["mcp"]
818
+ }
819
+ }
820
+ }
821
+ ```
822
+
823
+ ---
824
+
825
+ ## Принципы
826
+
827
+ 1. **Один файл** — скачал бинарник, запустил, работает. Без Docker, без apt install.
828
+ 2. **Тесты как код** — YAML в git, code review, merge requests.
829
+ 3. **OpenAPI-first** — спецификация есть → тесты генерируются.
830
+ 4. **Два режима** — CLI для CI/CD, WebUI для команды. Одна кодовая база.
831
+ 5. **SQLite по умолчанию** — история работает из коробки, без настройки БД.