kodu 1.1.2 → 1.1.4

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 (128) hide show
  1. package/.prettierrc +4 -0
  2. package/AGENTS.md +97 -0
  3. package/README.md +85 -100
  4. package/biome.json +50 -0
  5. package/dist/app.module.d.ts +2 -0
  6. package/dist/app.module.js +42 -0
  7. package/dist/app.module.js.map +1 -0
  8. package/dist/commands/clean/clean.command.d.ts +16 -0
  9. package/dist/commands/clean/clean.command.js +88 -0
  10. package/dist/commands/clean/clean.command.js.map +1 -0
  11. package/dist/commands/clean/clean.module.d.ts +2 -0
  12. package/dist/commands/clean/clean.module.js +25 -0
  13. package/dist/commands/clean/clean.module.js.map +1 -0
  14. package/dist/commands/commit/commit.command.d.ts +18 -0
  15. package/dist/commands/commit/commit.command.js +135 -0
  16. package/dist/commands/commit/commit.command.js.map +1 -0
  17. package/dist/commands/commit/commit.module.d.ts +2 -0
  18. package/dist/commands/commit/commit.module.js +25 -0
  19. package/dist/commands/commit/commit.module.js.map +1 -0
  20. package/dist/commands/init/init.command.d.ts +14 -0
  21. package/dist/commands/init/init.command.js +166 -0
  22. package/dist/commands/init/init.command.js.map +1 -0
  23. package/dist/commands/init/init.module.d.ts +2 -0
  24. package/dist/commands/init/init.module.js +22 -0
  25. package/dist/commands/init/init.module.js.map +1 -0
  26. package/dist/commands/pack/pack.command.d.ts +25 -0
  27. package/dist/commands/pack/pack.command.js +161 -0
  28. package/dist/commands/pack/pack.command.js.map +1 -0
  29. package/dist/commands/pack/pack.module.d.ts +2 -0
  30. package/dist/commands/pack/pack.module.js +25 -0
  31. package/dist/commands/pack/pack.module.js.map +1 -0
  32. package/dist/commands/review/review.command.d.ts +31 -0
  33. package/dist/commands/review/review.command.js +260 -0
  34. package/dist/commands/review/review.command.js.map +1 -0
  35. package/dist/commands/review/review.module.d.ts +2 -0
  36. package/dist/commands/review/review.module.js +26 -0
  37. package/dist/commands/review/review.module.js.map +1 -0
  38. package/dist/core/config/config.module.d.ts +2 -0
  39. package/dist/core/config/config.module.js +22 -0
  40. package/dist/core/config/config.module.js.map +1 -0
  41. package/dist/core/config/config.schema.d.ts +16 -0
  42. package/dist/core/config/config.schema.js +48 -0
  43. package/dist/core/config/config.schema.js.map +1 -0
  44. package/dist/core/config/config.service.d.ts +7 -0
  45. package/dist/core/config/config.service.js +51 -0
  46. package/dist/core/config/config.service.js.map +1 -0
  47. package/dist/core/config/config.types.d.ts +1 -0
  48. package/dist/core/config/config.types.js +3 -0
  49. package/dist/core/config/config.types.js.map +1 -0
  50. package/dist/core/file-system/fs.module.d.ts +2 -0
  51. package/dist/core/file-system/fs.module.js +21 -0
  52. package/dist/core/file-system/fs.module.js.map +1 -0
  53. package/dist/core/file-system/fs.service.d.ts +8 -0
  54. package/dist/core/file-system/fs.service.js +62 -0
  55. package/dist/core/file-system/fs.service.js.map +1 -0
  56. package/dist/core/ui/ui.module.d.ts +2 -0
  57. package/dist/core/ui/ui.module.js +22 -0
  58. package/dist/core/ui/ui.module.js.map +1 -0
  59. package/dist/core/ui/ui.service.d.ts +22 -0
  60. package/dist/core/ui/ui.service.js +43 -0
  61. package/dist/core/ui/ui.service.js.map +1 -0
  62. package/dist/main.d.ts +2 -0
  63. package/dist/main.js +10 -0
  64. package/dist/main.js.map +1 -0
  65. package/dist/shared/ai/ai.module.d.ts +2 -0
  66. package/dist/shared/ai/ai.module.js +23 -0
  67. package/dist/shared/ai/ai.module.js.map +1 -0
  68. package/dist/shared/ai/ai.service.d.ts +27 -0
  69. package/dist/shared/ai/ai.service.js +126 -0
  70. package/dist/shared/ai/ai.service.js.map +1 -0
  71. package/dist/shared/cleaner/cleaner.service.d.ts +18 -0
  72. package/dist/shared/cleaner/cleaner.service.js +187 -0
  73. package/dist/shared/cleaner/cleaner.service.js.map +1 -0
  74. package/dist/shared/cleaner/cleaner.types.d.ts +14 -0
  75. package/dist/shared/cleaner/cleaner.types.js +3 -0
  76. package/dist/shared/cleaner/cleaner.types.js.map +1 -0
  77. package/dist/shared/git/git.module.d.ts +2 -0
  78. package/dist/shared/git/git.module.js +23 -0
  79. package/dist/shared/git/git.module.js.map +1 -0
  80. package/dist/shared/git/git.service.d.ts +11 -0
  81. package/dist/shared/git/git.service.js +61 -0
  82. package/dist/shared/git/git.service.js.map +1 -0
  83. package/dist/shared/tokenizer/tokenizer.module.d.ts +2 -0
  84. package/dist/shared/tokenizer/tokenizer.module.js +23 -0
  85. package/dist/shared/tokenizer/tokenizer.module.js.map +1 -0
  86. package/dist/shared/tokenizer/tokenizer.service.d.ts +15 -0
  87. package/dist/shared/tokenizer/tokenizer.service.js +59 -0
  88. package/dist/shared/tokenizer/tokenizer.service.js.map +1 -0
  89. package/dist/tsconfig.build.tsbuildinfo +1 -0
  90. package/docs/plan.md +92 -0
  91. package/docs/project_charter.md +92 -0
  92. package/docs/todo.md +5 -0
  93. package/knip.json +10 -0
  94. package/kodu.json +22 -0
  95. package/nest-cli.json +8 -0
  96. package/package.json +41 -41
  97. package/src/app.module.ts +29 -0
  98. package/src/commands/clean/clean.command.ts +83 -0
  99. package/src/commands/clean/clean.module.ts +12 -0
  100. package/src/commands/commit/commit.command.ts +120 -0
  101. package/src/commands/commit/commit.module.ts +12 -0
  102. package/src/commands/init/init.command.ts +193 -0
  103. package/src/commands/init/init.module.ts +9 -0
  104. package/src/commands/pack/pack.command.ts +167 -0
  105. package/src/commands/pack/pack.module.ts +12 -0
  106. package/src/commands/review/review.command.ts +266 -0
  107. package/src/commands/review/review.module.ts +13 -0
  108. package/src/core/config/config.module.ts +9 -0
  109. package/src/core/config/config.schema.ts +50 -0
  110. package/src/core/config/config.service.ts +46 -0
  111. package/src/core/config/config.types.ts +1 -0
  112. package/src/core/file-system/fs.module.ts +8 -0
  113. package/src/core/file-system/fs.service.ts +44 -0
  114. package/src/core/ui/ui.module.ts +9 -0
  115. package/src/core/ui/ui.service.ts +39 -0
  116. package/src/main.ts +9 -0
  117. package/src/shared/ai/ai.module.ts +10 -0
  118. package/src/shared/ai/ai.service.ts +160 -0
  119. package/src/shared/cleaner/cleaner.service.ts +227 -0
  120. package/src/shared/cleaner/cleaner.types.ts +16 -0
  121. package/src/shared/git/git.module.ts +10 -0
  122. package/src/shared/git/git.service.ts +49 -0
  123. package/src/shared/tokenizer/tokenizer.module.ts +10 -0
  124. package/src/shared/tokenizer/tokenizer.service.ts +54 -0
  125. package/tsconfig.build.json +4 -0
  126. package/tsconfig.json +25 -0
  127. package/LICENSE +0 -21
  128. package/dist/index.js +0 -146
package/docs/plan.md ADDED
@@ -0,0 +1,92 @@
1
+ ### 1. Выбор "Fresh & Modern" стека (Библиотеки)
2
+
3
+ Вместо старых монстров берем инструменты экосистемы UnJS, Sindre Sorhus и современные стандарты:
4
+
5
+ * **File System:** `node:fs/promises` (нативный, мощный) + **`tinyglobby`** (вместо тяжелого `globby` или `fast-glob`, супер-быстрый паттерн-матчинг).
6
+ * **CLI UI:** **`@inquirer/prompts`** (новый модульный инквайрер, тянет меньше зависимостей) + **`picocolors`** (в 10 раз быстрее и меньше `chalk`).
7
+ * **Spinners:** **`yocto-spinner`** (современная, легкая замена `ora`).
8
+ * **Process Execution:** **`execa`** (лучшая обертка над child_process для работы с Git).
9
+ * **Validation:** **`zod`** (стандарт де-факто).
10
+ * **Clipboard:** **`clipboardy`** (надежный кроссплатформ, альтернатив мало).
11
+ * **AI/HTTP:** **`mastra`** (как договорились) + нативный `fetch`.
12
+
13
+ ---
14
+
15
+ ### 2. Архитектура NestJS (Module Map)
16
+
17
+ Разбиваем монолит на функциональные домены.
18
+
19
+ ```text
20
+ src/
21
+ ├── app.module.ts # Корневой модуль (оркестратор)
22
+
23
+ ├── core/ # Global Modules (инфраструктура)
24
+ │ ├── config/ # ConfigModule (Zod + cosmiconfig)
25
+ │ ├── file-system/ # FsModule (tinyglobby, node:fs обертки)
26
+ │ └── ui/ # UiModule (Спиннеры, цвета, промпты)
27
+
28
+ ├── shared/ # Общая бизнес-логика
29
+ │ ├── tokenizer/ # TokenizerModule (js-tiktoken)
30
+ │ ├── git/ # GitModule (execa обертки над git)
31
+ │ └── ai/ # AiModule (Mastra client setup)
32
+
33
+ └── commands/ # Feature Modules (команды)
34
+ ├── init/ # InitModule (kodu init)
35
+ ├── pack/ # PackModule (kodu pack)
36
+ ├── clean/ # CleanModule (kodu clean /w ts-morph)
37
+ ├── review/ # ReviewModule (kodu review)
38
+ └── commit/ # CommitModule (kodu commit)
39
+ ```
40
+
41
+ ---
42
+
43
+ ### 3. План разработки (Roadmap)
44
+
45
+ Разбиваем на 4 спринта (фазы).
46
+
47
+ #### Фаза 1: The Foundation (Фундамент)
48
+ *Цель: Приложение запускается, читает конфиг и умеет работать с файлами.*
49
+
50
+ 1. **Core Setup:**
51
+ * Настройка `ConfigModule`: чтение `kodu.json`, валидация через `Zod`.
52
+ * Настройка `UiModule`: сделать красивые хелперы для вывода (success, error, warning).
53
+ 2. **Command: Init:**
54
+ * Реализация `InitCommand`.
55
+ * Интерактивный опросник через `@inquirer/prompts`.
56
+ * Генерация дефолтного конфига.
57
+
58
+ #### Фаза 2: The Packer & Tokenizer (Локальная магия)
59
+ *Цель: Утилита полезна даже без интернета.*
60
+
61
+ 1. **File System Logic:**
62
+ * Интеграция `tinyglobby` для умного поиска файлов (учет `.gitignore` + `kodu.json`).
63
+ 2. **Tokenizer:**
64
+ * Сервис подсчета токенов на базе `js-tiktoken`.
65
+ 3. **Command: Pack:**
66
+ * Сборка контента.
67
+ * Реализация флага `--copy` (буфер обмена).
68
+ * Реализация Template Engine (простая подстановка шаблонов промптов).
69
+
70
+ #### Фаза 3: The Cleaner (AST Engineering)
71
+ *Цель: Умная очистка кода.*
72
+
73
+ 1. **Clean Logic:**
74
+ * Подключение `ts-morph`.
75
+ * Реализация алгоритма обхода AST.
76
+ * Реализация whitelist (System + Biome + User).
77
+ * Особое внимание удалению JSX-комментариев `{/* ... */}`.
78
+ 2. **Command: Clean:**
79
+ * Интеграция логики в команду.
80
+ * Добавление флага `--dry-run` (чтобы показать, что удалится, не удаляя).
81
+
82
+ #### Фаза 4: AI Integration (Мозги)
83
+ *Цель: Подключение Mastra и Git.*
84
+
85
+ 1. **Git Integration:**
86
+ * Сервис на `execa` для получения `git diff --staged`.
87
+ 2. **Mastra Agent:**
88
+ * Настройка агента в `AiModule`.
89
+ 3. **Command: Review:**
90
+ * Пайплайн: Git Diff -> Tokenizer Check -> Mastra -> Report.
91
+ 4. **Command: Commit:**
92
+ * Пайплайн: Git Diff -> Mastra -> Generate Msg -> Inquirer Confirm -> Git Commit.
@@ -0,0 +1,92 @@
1
+ # 🚀 Project Charter: Kodu
2
+
3
+ **Дата:** 24.01.2026
4
+ **Тип проекта:** CLI Utility / Developer Tooling
5
+ **Рабочее название:** Kodu
6
+
7
+ ## 1. Резюме проекта (Executive Summary)
8
+ **Kodu** — это консольная утилита (CLI), предназначенная для оптимизации взаимодействия разработчиков с большими языковыми моделями (LLM).
9
+ Утилита решает проблему ручной подготовки контекста (копирования кода), очистки файлов от мусора и выполнения рутинных операций (ревью, написание коммитов) с помощью AI.
10
+ **Ключевая философия:** Высокий Developer Experience (DX), скорость работы и детерминированность критических операций.
11
+
12
+ ## 2. Цели и Метрики успеха
13
+ 1. **Ускорение работы с AI:** Сократить время подготовки промпта с кодом с 2–5 минут до 5 секунд.
14
+ 2. **Качество контекста:** Обеспечить передачу в AI только чистого, полезного кода без лишних комментариев, но с сохранением важной семантики.
15
+ 3. **Интеграция:** Бесшовная работа в пайплайнах (CI/CD, Git Hooks).
16
+ 4. **Расширяемость:** Архитектура, готовая к добавлению новых языков и команд.
17
+
18
+ ## 3. Технический стек (Technology Stack)
19
+ Мы выбираем стек, обеспечивающий надежность, модульность и типизацию.
20
+
21
+ * **Runtime:** Node.js
22
+ * **Framework:** NestJS + **Nest Commander** (модульность, DI, удобство поддержки).
23
+ * **AI Orchestration:** **Mastra** (абстракция над провайдерами LLM, агенты).
24
+ * **Validation:** **Zod** (валидация конфигов и входных данных).
25
+ * **Code Analysis (AST):** **ts-morph** (безопасный парсинг и модификация TypeScript/JSX/TSX).
26
+ * **Token Counting:** **js-tiktoken** (точный подсчет токенов OpenAI).
27
+ * **Utils:** `globby` (файловая система), `inquirer` (интерактив), `chalk`/`ora` (UI).
28
+
29
+ ## 4. Функциональные требования (Scope)
30
+
31
+ ### 4.1. Core: Initialization & Config
32
+ * **Команда:** `kodu init`
33
+ * Генерация файла `kodu.json`.
34
+ * Настройка `.gitignore` и `.kodu/`.
35
+ * Валидация конфигурации через Zod при каждом запуске.
36
+
37
+ ### 4.2. The Packer (Сборщик контекста)
38
+ * **Команда:** `kodu pack [options]`
39
+ * Сборка файлов проекта в один текстовый файл или буфер обмена (`--copy`).
40
+ * Учет `.gitignore` и `ignorePatterns` из конфига.
41
+ * **Token Budgeting:** Всегда выводить количество токенов и примерную стоимость.
42
+ * **Prompt Templates:** Поддержка флага `--template <name>`, подстановка шаблонов из `.kodu/prompts/`.
43
+ * *Ограничение:* Отказ от "Smart Context" (разрешения импортов) ради универсальности.
44
+
45
+ ### 4.3. The Cleaner (Очистка кода)
46
+ * **Команда:** `kodu clean`
47
+ * Удаление комментариев из кода.
48
+ * **Алгоритм:** Строго детерминированный (без AI), на базе AST (`ts-morph`).
49
+ * **Поддержка:** `.ts`, `.js`, `.tsx`, `.jsx`.
50
+ * **Whitelist (Исключения):**
51
+ * *System:* `@ts-ignore`, `eslint-disable`, `prettier-ignore`, `TODO`, `FIXME`.
52
+ * *Biome:* Специальная поддержка `// biome-ignore ...`.
53
+ * *User:* Настраиваемый список в `kodu.json` (например, `//!`).
54
+
55
+ ### 4.4. AI Features (Mastra Integration)
56
+ * **Команда:** `kodu review`
57
+ * Анализ `git diff` через AI с режимами Security, Style, Bug hunting.
58
+ * Поддержка CI/CD: `--ci` отключает спиннеры/буфер, `--output` сохраняет JSON/text, `--json` снимает структурированный отчет.
59
+ * Команда выходит с `1`, когда AI находит проблемы в структурированном режиме.
60
+ * **Команда:** `kodu commit`
61
+ * Генерация сообщения коммита на основе `staged` изменений с методикой Conventional Commits.
62
+ * Выводит результат в `stdout`, поддерживает `--output` и `--ci`, сама не выполняет `git commit`.
63
+
64
+ ### Быстрый старт AI
65
+ * Установите ключ: `export OPENAI_API_KEY=<ключ>` (имя переменной настраивается через `llm.apiKeyEnv`).
66
+ * Ревью: `kodu review --mode bug|style|security [--json] [--ci] [--output review.json]`.
67
+ * Коммит: `kodu commit [--ci] [--output commit-message.txt]` (просто выводит сообщение).
68
+ * В git diff автоматически исключаются файлы из `packer.ignore` (например, lock-файлы и `dist/`).
69
+
70
+ ## 5. Границы проекта (Out of Scope for MVP)
71
+ * Поддержка языков, отличных от JS/TS (для команды `clean`). `pack` будет работать со всем текстом.
72
+ * AI-based удаление комментариев (слишком рискованно и медленно).
73
+ * Обфускация кода (секреты должны быть в `.env`).
74
+ * GUI версия.
75
+
76
+ ## 6. Конфигурация (`kodu.json`)
77
+ Пример структуры, к которой мы стремимся:
78
+ ```json
79
+ {
80
+ "$schema": "./node_modules/kodu/schema.json",
81
+ "llm": {
82
+ "provider": "openai",
83
+ "model": "gpt-4o"
84
+ },
85
+ "cleaner": {
86
+ "whitelist": ["//!"]
87
+ },
88
+ "packer": {
89
+ "ignore": ["*.lock", "coverage"]
90
+ }
91
+ }
92
+ ```
package/docs/todo.md ADDED
@@ -0,0 +1,5 @@
1
+ # ToDo
2
+
3
+ - [ ] Сделать чтобы AI ключ был не обязательным при инициализации. Наш проект должен работать и без него (просто
4
+ функционал будет урезан)
5
+ - [ ] Добавить JSON schema для конфига
package/knip.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://unpkg.com/knip@5/schema.json",
3
+ "entry": ["src/main.ts!"],
4
+ "project": ["src/**/*.ts!"],
5
+ "ignore": [],
6
+ "ignoreDependencies": ["source-map-support"],
7
+ "paths": {
8
+ "@/*": ["src/*"]
9
+ }
10
+ }
package/kodu.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "llm": {
3
+ "provider": "openai",
4
+ "model": "gpt-4o"
5
+ },
6
+ "cleaner": {
7
+ "whitelist": ["//!"],
8
+ "keepJSDoc": true
9
+ },
10
+ "packer": {
11
+ "ignore": [
12
+ "package-lock.json",
13
+ "yarn.lock",
14
+ "pnpm-lock.yaml",
15
+ ".git",
16
+ ".kodu",
17
+ "node_modules",
18
+ "dist",
19
+ "coverage"
20
+ ]
21
+ }
22
+ }
package/nest-cli.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
2
  "name": "kodu",
3
- "version": "1.1.2",
4
- "description": "kodu — A lightning-fast CLI tool to bundle your codebase into a single context file for LLMs (ChatGPT, Claude, DeepSeek). Features smart prioritization, interactive history, and gitignore support.",
5
- "type": "module",
3
+ "version": "1.1.4",
4
+ "private": false,
5
+ "license": "UNLICENSED",
6
6
  "bin": {
7
- "kodu": "./dist/index.js"
7
+ "kodu": "dist/main.js"
8
8
  },
9
- "files": [
10
- "dist",
11
- "README.md",
12
- "LICENSE"
13
- ],
14
9
  "scripts": {
15
10
  "________________ BUILD AND RUN ________________": "",
16
- "dev": "bun run src/index.ts",
17
- "build": "bun build ./src/index.ts --outfile=./dist/index.js --target=node --minify",
18
- "prepublishOnly": "bun run build",
11
+ "build": "nest build && chmod +x dist/main.js",
12
+ "start:prod": "node dist/main.js",
13
+ "new:command": "nest g -c nest-commander-schematics command",
14
+ "new:question": "nest g -c nest-commander-schematics question",
19
15
  "________________ FORMAT AND LINT ________________": "",
20
16
  "lint": "biome check",
21
17
  "lint:fix": "biome check --write",
22
18
  "lint:fix:unsafe": "biome check --write --unsafe",
23
19
  "ts:check": "tsc --noEmit",
24
- "check": "run-p ts:check lint"
20
+ "knip": "knip --production",
21
+ "check": "run-p ts:check lint:fix knip"
25
22
  },
26
- "keywords": [
27
- "cli",
28
- "context",
29
- "llm",
30
- "ai",
31
- "bundler"
32
- ],
33
- "author": "uxname",
34
- "license": "MIT",
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/uxname/pp.git"
38
- },
39
- "bugs": {
40
- "url": "https://github.com/uxname/pp/issues"
23
+ "dependencies": {
24
+ "@inquirer/prompts": "^8.2.0",
25
+ "@mastra/core": "^1.0.4",
26
+ "@nestjs/common": "^11.0.1",
27
+ "@nestjs/core": "^11.0.1",
28
+ "clipboardy": "^5.0.2",
29
+ "execa": "^9.6.1",
30
+ "js-tiktoken": "^1.0.21",
31
+ "lilconfig": "^3.1.3",
32
+ "mastra": "^1.0.1",
33
+ "nest-commander": "^3.20.1",
34
+ "picocolors": "^1.1.1",
35
+ "reflect-metadata": "^0.2.2",
36
+ "rxjs": "^7.8.1",
37
+ "source-map-support": "^0.5.21",
38
+ "tinyglobby": "^0.2.15",
39
+ "ts-morph": "^24.0.0",
40
+ "yocto-spinner": "^1.0.0",
41
+ "zod": "^4.3.6"
41
42
  },
42
- "homepage": "https://github.com/uxname/pp#readme",
43
43
  "devDependencies": {
44
- "@biomejs/biome": "^2.3.10",
45
- "@types/bun": "latest",
46
- "@types/strip-comments": "^2.0.4",
47
- "npm-run-all": "^4.1.5"
48
- },
49
- "dependencies": {
50
- "@types/prompts": "^2.4.9",
51
- "commander": "^14.0.2",
52
- "ignore": "^7.0.5",
53
- "ora": "^9.0.0",
54
- "prompts": "^2.4.2",
55
- "strip-comments": "^2.0.1"
44
+ "@biomejs/biome": "^2.3.12",
45
+ "@nestjs/cli": "^11.0.0",
46
+ "@nestjs/schematics": "^11.0.0",
47
+ "@nestjs/testing": "^11.0.1",
48
+ "@types/node": "^22.10.7",
49
+ "knip": "^5.82.1",
50
+ "nest-commander-schematics": "^3.2.0",
51
+ "npm-run-all": "^4.1.5",
52
+ "ts-loader": "^9.5.2",
53
+ "ts-node": "^10.9.2",
54
+ "tsconfig-paths": "^4.2.0",
55
+ "typescript": "^5.7.3"
56
56
  }
57
57
  }
@@ -0,0 +1,29 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { CleanModule } from './commands/clean/clean.module';
3
+ import { CommitModule } from './commands/commit/commit.module';
4
+ import { InitModule } from './commands/init/init.module';
5
+ import { PackModule } from './commands/pack/pack.module';
6
+ import { ReviewModule } from './commands/review/review.module';
7
+ import { ConfigModule } from './core/config/config.module';
8
+ import { FsModule } from './core/file-system/fs.module';
9
+ import { UiModule } from './core/ui/ui.module';
10
+ import { AiModule } from './shared/ai/ai.module';
11
+ import { GitModule } from './shared/git/git.module';
12
+ import { TokenizerModule } from './shared/tokenizer/tokenizer.module';
13
+
14
+ @Module({
15
+ imports: [
16
+ ConfigModule,
17
+ UiModule,
18
+ FsModule,
19
+ GitModule,
20
+ AiModule,
21
+ TokenizerModule,
22
+ InitModule,
23
+ PackModule,
24
+ CleanModule,
25
+ ReviewModule,
26
+ CommitModule,
27
+ ],
28
+ })
29
+ export class AppModule {}
@@ -0,0 +1,83 @@
1
+ import { Command, CommandRunner, Option } from 'nest-commander';
2
+ import { FsService } from '../../core/file-system/fs.service';
3
+ import { UiService } from '../../core/ui/ui.service';
4
+ import { CleanerService } from '../../shared/cleaner/cleaner.service';
5
+
6
+ type CleanOptions = {
7
+ dryRun?: boolean;
8
+ };
9
+
10
+ @Command({ name: 'clean', description: 'Удалить комментарии из кода' })
11
+ export class CleanCommand extends CommandRunner {
12
+ constructor(
13
+ private readonly ui: UiService,
14
+ private readonly fsService: FsService,
15
+ private readonly cleaner: CleanerService,
16
+ ) {
17
+ super();
18
+ }
19
+
20
+ @Option({
21
+ flags: '-d, --dry-run',
22
+ description: 'Показать, что будет удалено',
23
+ })
24
+ parseDryRun(): boolean {
25
+ return true;
26
+ }
27
+
28
+ async run(_inputs: string[], options: CleanOptions = {}): Promise<void> {
29
+ const spinner = this.ui
30
+ .createSpinner({
31
+ text: options.dryRun
32
+ ? 'Анализ комментариев...'
33
+ : 'Очистка комментариев...',
34
+ })
35
+ .start();
36
+
37
+ try {
38
+ const allFiles = await this.fsService.findProjectFiles();
39
+ const targets = allFiles.filter((file) =>
40
+ /\.(ts|tsx|js|jsx)$/i.test(file),
41
+ );
42
+
43
+ if (targets.length === 0) {
44
+ spinner.stop('Нет файлов для очистки.');
45
+ this.ui.log.warn('Нет файлов для очистки.');
46
+ return;
47
+ }
48
+
49
+ const summary = await this.cleaner.cleanFiles(targets, {
50
+ dryRun: options.dryRun,
51
+ });
52
+
53
+ spinner.success(options.dryRun ? 'Анализ завершен' : 'Очистка завершена');
54
+
55
+ if (options.dryRun) {
56
+ this.ui.log.info(
57
+ `Будет затронуто файлов: ${summary.filesChanged}, комментариев: ${summary.commentsRemoved}`,
58
+ );
59
+ summary.reports
60
+ .filter((report) => report.removed > 0)
61
+ .forEach((report) => {
62
+ const previews = report.previews
63
+ .map((item) => `"${item}"`)
64
+ .join(', ');
65
+ this.ui.log.info(
66
+ `- ${report.file} (${report.removed}): ${previews}`,
67
+ );
68
+ });
69
+ return;
70
+ }
71
+
72
+ this.ui.log.success(
73
+ `Очищено файлов: ${summary.filesChanged}, удалено комментариев: ${summary.commentsRemoved}`,
74
+ );
75
+ } catch (error) {
76
+ spinner.error('Ошибка при очистке');
77
+ const message =
78
+ error instanceof Error ? error.message : 'Неизвестная ошибка';
79
+ this.ui.log.error(message);
80
+ process.exitCode = 1;
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,12 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from '../../core/config/config.module';
3
+ import { FsModule } from '../../core/file-system/fs.module';
4
+ import { UiModule } from '../../core/ui/ui.module';
5
+ import { CleanerService } from '../../shared/cleaner/cleaner.service';
6
+ import { CleanCommand } from './clean.command';
7
+
8
+ @Module({
9
+ imports: [FsModule, UiModule, ConfigModule],
10
+ providers: [CleanCommand, CleanerService],
11
+ })
12
+ export class CleanModule {}
@@ -0,0 +1,120 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { Command, CommandRunner, Option } from 'nest-commander';
3
+ import { UiService } from '../../core/ui/ui.service';
4
+ import { AiService } from '../../shared/ai/ai.service';
5
+ import { GitService } from '../../shared/git/git.service';
6
+
7
+ type CommitOptions = {
8
+ ci?: boolean;
9
+ output?: string;
10
+ };
11
+
12
+ @Command({
13
+ name: 'commit',
14
+ description: 'Сгенерировать и применить сообщение коммита',
15
+ })
16
+ export class CommitCommand extends CommandRunner {
17
+ constructor(
18
+ private readonly ui: UiService,
19
+ private readonly git: GitService,
20
+ private readonly ai: AiService,
21
+ ) {
22
+ super();
23
+ }
24
+
25
+ @Option({ flags: '--ci', description: 'CI-режим: без спиннеров и диалогов' })
26
+ parseCi(): boolean {
27
+ return true;
28
+ }
29
+
30
+ @Option({
31
+ flags: '-o, --output <path>',
32
+ description: 'Сохранить сообщение в файл',
33
+ })
34
+ parseOutput(value: string): string {
35
+ return value;
36
+ }
37
+
38
+ async run(_inputs: string[], options: CommitOptions = {}): Promise<void> {
39
+ const ciMode = Boolean(options.ci);
40
+ const spinner = ciMode
41
+ ? undefined
42
+ : this.ui.createSpinner({ text: 'Собираю diff...' }).start();
43
+
44
+ const logProgress = (text: string): void => {
45
+ if (ciMode) {
46
+ return;
47
+ }
48
+ if (spinner) {
49
+ spinner.text = text;
50
+ return;
51
+ }
52
+ this.ui.log.info(text);
53
+ };
54
+
55
+ const finishProgress = (text: string): void => {
56
+ if (ciMode) {
57
+ return;
58
+ }
59
+ if (spinner) {
60
+ spinner.success(text);
61
+ return;
62
+ }
63
+ this.ui.log.success(text);
64
+ };
65
+
66
+ try {
67
+ await this.git.ensureRepo();
68
+
69
+ const hasStaged = await this.git.hasStagedChanges();
70
+ if (!hasStaged) {
71
+ if (spinner) {
72
+ spinner.stop('Нет застейдженных изменений');
73
+ } else {
74
+ this.ui.log.info('Нет застейдженных изменений');
75
+ }
76
+ this.ui.log.warn('Сначала выполните git add для нужных файлов.');
77
+ return;
78
+ }
79
+
80
+ const diff = await this.git.getStagedDiff();
81
+ if (!diff.trim()) {
82
+ if (spinner) {
83
+ spinner.stop('Diff пуст — возможно, всё исключено packer.ignore');
84
+ } else {
85
+ this.ui.log.info('Diff пуст — возможно, всё исключено packer.ignore');
86
+ }
87
+ this.ui.log.warn(
88
+ 'Diff пустой: все изменения попали в исключения packer.ignore.',
89
+ );
90
+ return;
91
+ }
92
+
93
+ logProgress('Генерирую сообщение коммита...');
94
+ const commitMessage = await this.ai.generateCommitMessage(diff);
95
+
96
+ finishProgress('Сообщение готово');
97
+ if (!ciMode) {
98
+ this.ui.log.info(`Предложение: ${commitMessage}`);
99
+ }
100
+
101
+ console.log(commitMessage);
102
+ if (options.output) {
103
+ await writeFile(options.output, commitMessage, { encoding: 'utf8' });
104
+ if (!ciMode) {
105
+ this.ui.log.success(`Сообщение сохранено в ${options.output}`);
106
+ }
107
+ }
108
+ } catch (error) {
109
+ if (spinner) {
110
+ spinner.error('Ошибка при создании коммита');
111
+ } else {
112
+ this.ui.log.error('Ошибка при создании коммита');
113
+ }
114
+ const message =
115
+ error instanceof Error ? error.message : 'Неизвестная ошибка';
116
+ this.ui.log.error(message);
117
+ process.exitCode = 1;
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,12 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from '../../core/config/config.module';
3
+ import { UiModule } from '../../core/ui/ui.module';
4
+ import { AiModule } from '../../shared/ai/ai.module';
5
+ import { GitModule } from '../../shared/git/git.module';
6
+ import { CommitCommand } from './commit.command';
7
+
8
+ @Module({
9
+ imports: [ConfigModule, UiModule, GitModule, AiModule],
10
+ providers: [CommitCommand],
11
+ })
12
+ export class CommitModule {}