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.
- package/.prettierrc +4 -0
- package/AGENTS.md +97 -0
- package/README.md +85 -100
- package/biome.json +50 -0
- package/dist/app.module.d.ts +2 -0
- package/dist/app.module.js +42 -0
- package/dist/app.module.js.map +1 -0
- package/dist/commands/clean/clean.command.d.ts +16 -0
- package/dist/commands/clean/clean.command.js +88 -0
- package/dist/commands/clean/clean.command.js.map +1 -0
- package/dist/commands/clean/clean.module.d.ts +2 -0
- package/dist/commands/clean/clean.module.js +25 -0
- package/dist/commands/clean/clean.module.js.map +1 -0
- package/dist/commands/commit/commit.command.d.ts +18 -0
- package/dist/commands/commit/commit.command.js +135 -0
- package/dist/commands/commit/commit.command.js.map +1 -0
- package/dist/commands/commit/commit.module.d.ts +2 -0
- package/dist/commands/commit/commit.module.js +25 -0
- package/dist/commands/commit/commit.module.js.map +1 -0
- package/dist/commands/init/init.command.d.ts +14 -0
- package/dist/commands/init/init.command.js +166 -0
- package/dist/commands/init/init.command.js.map +1 -0
- package/dist/commands/init/init.module.d.ts +2 -0
- package/dist/commands/init/init.module.js +22 -0
- package/dist/commands/init/init.module.js.map +1 -0
- package/dist/commands/pack/pack.command.d.ts +25 -0
- package/dist/commands/pack/pack.command.js +161 -0
- package/dist/commands/pack/pack.command.js.map +1 -0
- package/dist/commands/pack/pack.module.d.ts +2 -0
- package/dist/commands/pack/pack.module.js +25 -0
- package/dist/commands/pack/pack.module.js.map +1 -0
- package/dist/commands/review/review.command.d.ts +31 -0
- package/dist/commands/review/review.command.js +260 -0
- package/dist/commands/review/review.command.js.map +1 -0
- package/dist/commands/review/review.module.d.ts +2 -0
- package/dist/commands/review/review.module.js +26 -0
- package/dist/commands/review/review.module.js.map +1 -0
- package/dist/core/config/config.module.d.ts +2 -0
- package/dist/core/config/config.module.js +22 -0
- package/dist/core/config/config.module.js.map +1 -0
- package/dist/core/config/config.schema.d.ts +16 -0
- package/dist/core/config/config.schema.js +48 -0
- package/dist/core/config/config.schema.js.map +1 -0
- package/dist/core/config/config.service.d.ts +7 -0
- package/dist/core/config/config.service.js +51 -0
- package/dist/core/config/config.service.js.map +1 -0
- package/dist/core/config/config.types.d.ts +1 -0
- package/dist/core/config/config.types.js +3 -0
- package/dist/core/config/config.types.js.map +1 -0
- package/dist/core/file-system/fs.module.d.ts +2 -0
- package/dist/core/file-system/fs.module.js +21 -0
- package/dist/core/file-system/fs.module.js.map +1 -0
- package/dist/core/file-system/fs.service.d.ts +8 -0
- package/dist/core/file-system/fs.service.js +62 -0
- package/dist/core/file-system/fs.service.js.map +1 -0
- package/dist/core/ui/ui.module.d.ts +2 -0
- package/dist/core/ui/ui.module.js +22 -0
- package/dist/core/ui/ui.module.js.map +1 -0
- package/dist/core/ui/ui.service.d.ts +22 -0
- package/dist/core/ui/ui.service.js +43 -0
- package/dist/core/ui/ui.service.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +10 -0
- package/dist/main.js.map +1 -0
- package/dist/shared/ai/ai.module.d.ts +2 -0
- package/dist/shared/ai/ai.module.js +23 -0
- package/dist/shared/ai/ai.module.js.map +1 -0
- package/dist/shared/ai/ai.service.d.ts +27 -0
- package/dist/shared/ai/ai.service.js +126 -0
- package/dist/shared/ai/ai.service.js.map +1 -0
- package/dist/shared/cleaner/cleaner.service.d.ts +18 -0
- package/dist/shared/cleaner/cleaner.service.js +187 -0
- package/dist/shared/cleaner/cleaner.service.js.map +1 -0
- package/dist/shared/cleaner/cleaner.types.d.ts +14 -0
- package/dist/shared/cleaner/cleaner.types.js +3 -0
- package/dist/shared/cleaner/cleaner.types.js.map +1 -0
- package/dist/shared/git/git.module.d.ts +2 -0
- package/dist/shared/git/git.module.js +23 -0
- package/dist/shared/git/git.module.js.map +1 -0
- package/dist/shared/git/git.service.d.ts +11 -0
- package/dist/shared/git/git.service.js +61 -0
- package/dist/shared/git/git.service.js.map +1 -0
- package/dist/shared/tokenizer/tokenizer.module.d.ts +2 -0
- package/dist/shared/tokenizer/tokenizer.module.js +23 -0
- package/dist/shared/tokenizer/tokenizer.module.js.map +1 -0
- package/dist/shared/tokenizer/tokenizer.service.d.ts +15 -0
- package/dist/shared/tokenizer/tokenizer.service.js +59 -0
- package/dist/shared/tokenizer/tokenizer.service.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/docs/plan.md +92 -0
- package/docs/project_charter.md +92 -0
- package/docs/todo.md +5 -0
- package/knip.json +10 -0
- package/kodu.json +22 -0
- package/nest-cli.json +8 -0
- package/package.json +41 -41
- package/src/app.module.ts +29 -0
- package/src/commands/clean/clean.command.ts +83 -0
- package/src/commands/clean/clean.module.ts +12 -0
- package/src/commands/commit/commit.command.ts +120 -0
- package/src/commands/commit/commit.module.ts +12 -0
- package/src/commands/init/init.command.ts +193 -0
- package/src/commands/init/init.module.ts +9 -0
- package/src/commands/pack/pack.command.ts +167 -0
- package/src/commands/pack/pack.module.ts +12 -0
- package/src/commands/review/review.command.ts +266 -0
- package/src/commands/review/review.module.ts +13 -0
- package/src/core/config/config.module.ts +9 -0
- package/src/core/config/config.schema.ts +50 -0
- package/src/core/config/config.service.ts +46 -0
- package/src/core/config/config.types.ts +1 -0
- package/src/core/file-system/fs.module.ts +8 -0
- package/src/core/file-system/fs.service.ts +44 -0
- package/src/core/ui/ui.module.ts +9 -0
- package/src/core/ui/ui.service.ts +39 -0
- package/src/main.ts +9 -0
- package/src/shared/ai/ai.module.ts +10 -0
- package/src/shared/ai/ai.service.ts +160 -0
- package/src/shared/cleaner/cleaner.service.ts +227 -0
- package/src/shared/cleaner/cleaner.types.ts +16 -0
- package/src/shared/git/git.module.ts +10 -0
- package/src/shared/git/git.service.ts +49 -0
- package/src/shared/tokenizer/tokenizer.module.ts +10 -0
- package/src/shared/tokenizer/tokenizer.service.ts +54 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +25 -0
- package/LICENSE +0 -21
- package/dist/index.js +0 -146
package/.prettierrc
ADDED
package/AGENTS.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# AGENTS
|
|
2
|
+
|
|
3
|
+
## 1. Project Overview & Philosophy
|
|
4
|
+
- **Kodu** is a CLI assistant for developers (JS/TS focus) to streamline interactions with LLMs.
|
|
5
|
+
- **Key Goals:** Speed (0.5s startup), Determinism (no AI for critical file ops), and DX (Developer Experience).
|
|
6
|
+
- **Source of Truth:**
|
|
7
|
+
- Functional scope: `docs/project_charter.md`.
|
|
8
|
+
- Roadmap & Tech Stack: `docs/plan.md`.
|
|
9
|
+
- **Current Phase:** **Phase 4: AI Integration (Мозги)** — Mastra/Git интеграция, команды `review` и `commit`, фильтр diff через `packer.ignore`.
|
|
10
|
+
- **Команды сейчас:** `init`, `pack`, `clean`, `review`, `commit` (все зарегистрированы в `app.module.ts`).
|
|
11
|
+
|
|
12
|
+
## 2. Technology Stack (Enforced)
|
|
13
|
+
We strictly follow the "Fresh & Modern" stack strategy. Do not install legacy libraries.
|
|
14
|
+
|
|
15
|
+
| Category | **USE THIS** ✅ | **DO NOT USE** ❌ |
|
|
16
|
+
| :--- | :--- | :--- |
|
|
17
|
+
| **Framework** | `NestJS` + `nest-commander` | Pure Node.js scripts, Oclif |
|
|
18
|
+
| **File System** | `node:fs/promises` + `tinyglobby` | `fs-extra`, `glob`, `fast-glob`, `rimraf` |
|
|
19
|
+
| **Validation** | `zod` | `class-validator`, `joi` |
|
|
20
|
+
| **Process/Git** | `execa` | `child_process`, `shelljs` |
|
|
21
|
+
| **CLI UI** | `@inquirer/prompts` + `picocolors` | `inquirer` (legacy), `chalk`, `colors` |
|
|
22
|
+
| **Spinners** | `yocto-spinner` | `ora`, `cli-spinners` |
|
|
23
|
+
| **AI Agent** | `mastra` | Direct `openai` SDK calls (unless inside Mastra) |
|
|
24
|
+
| **AST/Parsing** | `ts-morph` | Regex for code parsing, `babel` |
|
|
25
|
+
| **Tokens** | `js-tiktoken` | `gpt-3-encoder` |
|
|
26
|
+
| **Git** | `git` via `execa` | `child_process`, `shelljs` |
|
|
27
|
+
|
|
28
|
+
## 3. Architecture & Module Map
|
|
29
|
+
The project is NOT a flat structure. Use the following Module Map as a guide for where to place files.
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
src/
|
|
33
|
+
├── app.module.ts # Root Orchestrator
|
|
34
|
+
├── main.ts # Entry Point
|
|
35
|
+
│
|
|
36
|
+
├── core/ # GLOBAL Infrastructure (Global Modules)
|
|
37
|
+
│ ├── config/ # ConfigModule (Zod schemas, loading kodu.json)
|
|
38
|
+
│ ├── file-system/ # FsModule (tinyglobby wrappers)
|
|
39
|
+
│ └── ui/ # UiModule (Spinners, colored loggers)
|
|
40
|
+
│
|
|
41
|
+
├── shared/ # Shared Business Logic
|
|
42
|
+
│ ├── tokenizer/ # TokenizerModule
|
|
43
|
+
│ ├── git/ # GitModule (execa git helpers, diff filters)
|
|
44
|
+
│ └── ai/ # AiModule (Mastra agents, API key from llm.apiKeyEnv)
|
|
45
|
+
│
|
|
46
|
+
└── commands/ # Feature Modules (The actual commands)
|
|
47
|
+
├── init/ # InitModule
|
|
48
|
+
├── pack/ # PackModule
|
|
49
|
+
├── clean/ # CleanModule
|
|
50
|
+
├── review/ # ReviewModule
|
|
51
|
+
└── commit/ # CommitModule
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 4. Coding Standards & Conventions
|
|
55
|
+
|
|
56
|
+
### 4.1. General
|
|
57
|
+
- **ESM Only:** The project runs in `nodenext` mode. Use `import` statements.
|
|
58
|
+
- **Strictness:** `strictNullChecks` is ON. No `any` allowed unless absolutely necessary (use `unknown` and refine).
|
|
59
|
+
- **Async/Await:** Prefer `node:fs/promises` over sync methods where possible, but for CLI startup (Config loading), sync operations are acceptable if they improve perceived performance.
|
|
60
|
+
|
|
61
|
+
### 4.2. NestJS Specifics
|
|
62
|
+
- **Dependency Injection:** Always use DI. Do not import services directly into other services without providing them in the Module.
|
|
63
|
+
- **CommandRunner:** All commands extend `CommandRunner` from `nest-commander`.
|
|
64
|
+
- **Zod Config:** Configuration is loaded ONCE in `ConfigModule` and validated. Other modules inject `ConfigService` to access typed settings.
|
|
65
|
+
|
|
66
|
+
### 4.3. Code Style (Biome)
|
|
67
|
+
- We use **Biome** for linting and formatting.
|
|
68
|
+
- **Quotes:** Single quotes.
|
|
69
|
+
- **Indent:** 2 spaces.
|
|
70
|
+
- **Run Check:** Always run `npm run lint` before finishing a task.
|
|
71
|
+
|
|
72
|
+
## 5. Development Workflow
|
|
73
|
+
|
|
74
|
+
### 5.1. Adding a New Command
|
|
75
|
+
1. Create a folder in `src/commands/<name>`.
|
|
76
|
+
2. Create `<name>.command.ts` and `<name>.module.ts`.
|
|
77
|
+
3. Implement `run()` method.
|
|
78
|
+
4. Register the module in `src/app.module.ts`.
|
|
79
|
+
5. **Test:** Run `npm run build && node dist/main.js <name>` to verify.
|
|
80
|
+
|
|
81
|
+
### 5.2. Scripts
|
|
82
|
+
- `npm run build`: Full build (Nest build).
|
|
83
|
+
- `npm run start:prod`: Run the built artifact.
|
|
84
|
+
- `npm run check`: Run TypeCheck + Biome + Knip (Dead code).
|
|
85
|
+
|
|
86
|
+
## 6. Critical Constraints
|
|
87
|
+
1. **No AI in Cleaner:** The `clean` command is purely deterministic (AST-based).
|
|
88
|
+
2. **Validation First:** The app must crash gracefully with a helpful message if `kodu.json` is invalid (handled by Zod).
|
|
89
|
+
3. **Secrets:** Never commit secrets. Assume `.env` usage for API keys.
|
|
90
|
+
4. **Performance:** Be mindful of import costs. We use `tinyglobby` and `picocolors` to keep startup time low.
|
|
91
|
+
5. **AI Keys:** `llm.apiKeyEnv` (default `OPENAI_API_KEY`) must be set before running AI commands.
|
|
92
|
+
6. **Diff Filtering:** `GitService` excludes paths from `packer.ignore` when строит staged diff для AI, чтобы отсечь lock/dist шум.
|
|
93
|
+
7. **Git Preconditions:** AI команды требуют git-репозиторий и застейдженные изменения (иначе выход с подсказкой).
|
|
94
|
+
|
|
95
|
+
## 7. Handling Uncertainties
|
|
96
|
+
- If a task involves logic not defined in `docs/project_charter.md`, ask the user.
|
|
97
|
+
- If unsure about a library, check Section 2 of this file. If not listed, prefer native Node.js APIs or check `docs/plan.md`.
|
package/README.md
CHANGED
|
@@ -1,141 +1,126 @@
|
|
|
1
|
-
|
|
2
|
-
# kodu
|
|
1
|
+
# Kodu 🚀
|
|
3
2
|
|
|
4
|
-
**
|
|
3
|
+
**Kodu** is a high-performance CLI tool designed to bridge the gap between your local codebase and Large Language Models (LLMs). It automates the tedious parts of AI-assisted development: preparing context, stripping "noise" from code, performing instant reviews, and drafting commit messages.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
like `package.json` or `README`), and concatenates everything into a single text output.
|
|
5
|
+
Built for speed and developer experience, Kodu helps you get the best out of AI without the manual "copy-paste" overhead.
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
---
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-

|
|
9
|
+
## Key Features
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
- **📦 Smart Context Packing**: Bundle your entire project (or specific parts) into a single, LLM-friendly format.
|
|
12
|
+
- **🧹 Deterministic Code Cleaning**: Strip comments and unnecessary metadata to save tokens while keeping critical logic and system instructions.
|
|
13
|
+
- **🔍 Instant AI Review**: Get immediate feedback on your staged changes (Bugs, Style, or Security).
|
|
14
|
+
- **📝 Automated Commits**: Generate meaningful, Conventional Commit messages based on your actual code changes.
|
|
15
|
+
- **💰 Token Budgeting**: Always know how many tokens you are sending and get an estimated cost before hitting the API.
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
- **🧠 Context-Aware:** Automatically puts `package.json`, docs, and entry points at the top of the file.
|
|
18
|
-
- **🛡️ Smart Filtering:**
|
|
19
|
-
- Respects `.gitignore`.
|
|
20
|
-
- Automatically excludes binary files, lockfiles, and huge directories (`node_modules`, `.git`, `dist`).
|
|
21
|
-
- Skips files larger than 1MB by default.
|
|
22
|
-
- **🧹 Code Cleanup:** Safely remove all comments from JS/TS files (`.ts`, `.js`, `.tsx`, `.jsx`) to reduce token usage
|
|
23
|
-
or minify code.
|
|
24
|
-
- **📜 Interactive History:** Run `kodu` without arguments to select from your recent commands.
|
|
25
|
-
- **📋 clipboard-ready:** Output to a file or pipe directly to stdout.
|
|
17
|
+
---
|
|
26
18
|
|
|
27
|
-
##
|
|
19
|
+
## Quick Start
|
|
28
20
|
|
|
29
|
-
|
|
21
|
+
### 1. Installation
|
|
30
22
|
|
|
31
23
|
```bash
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
## 🚀 Usage
|
|
36
|
-
|
|
37
|
-
### 1. Bundle Context (Default)
|
|
38
|
-
|
|
39
|
-
Scan the current directory and generate a text file for LLMs.
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# Basic usage
|
|
43
|
-
kodu
|
|
24
|
+
# Install globally
|
|
25
|
+
npm install -g kodu-cli # (Or your package name)
|
|
44
26
|
|
|
45
|
-
#
|
|
46
|
-
kodu
|
|
47
|
-
|
|
48
|
-
# Pipe to clipboard (macOS)
|
|
49
|
-
kodu . --stdout | pbcopy
|
|
27
|
+
# Or run via npx
|
|
28
|
+
npx kodu-cli init
|
|
50
29
|
```
|
|
51
30
|
|
|
52
|
-
### 2.
|
|
53
|
-
|
|
54
|
-
Remove all comments (`// ...`, `/* ... */`) from JavaScript and TypeScript files in a directory.
|
|
55
|
-
|
|
56
|
-
> **⚠️ Warning:** This command **modifies files in place**. Always commit your changes before running!
|
|
31
|
+
### 2. Initialization
|
|
57
32
|
|
|
58
|
-
|
|
59
|
-
See which files will be modified without actually touching them.
|
|
33
|
+
Set up Kodu in your project:
|
|
60
34
|
|
|
61
35
|
```bash
|
|
62
|
-
kodu
|
|
36
|
+
kodu init
|
|
63
37
|
```
|
|
38
|
+
This creates a `kodu.json` configuration file and a `.kodu/` folder for your custom prompt templates.
|
|
64
39
|
|
|
65
|
-
|
|
66
|
-
This will ask for confirmation before proceeding.
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
kodu strip
|
|
70
|
-
# or
|
|
71
|
-
kodu strip ./src
|
|
72
|
-
```
|
|
40
|
+
### 3. Configure AI (Optional)
|
|
73
41
|
|
|
74
|
-
|
|
75
|
-
Useful for scripts or CI/CD.
|
|
42
|
+
For AI-powered features (`review`, `commit`), set your API key in your environment:
|
|
76
43
|
|
|
77
44
|
```bash
|
|
78
|
-
|
|
45
|
+
export OPENAI_API_KEY=your_key_here
|
|
79
46
|
```
|
|
80
47
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
### Bundle Command (`kodu [path]`)
|
|
48
|
+
---
|
|
84
49
|
|
|
85
|
-
|
|
86
|
-
|-----------------------|-------------------------------------------------------------------------|
|
|
87
|
-
| `-o, --output <file>` | Specify the output file path. |
|
|
88
|
-
| `-s, --stdout` | Print to stdout instead of creating a file. |
|
|
89
|
-
| `--exclude <pattern>` | Add custom glob patterns to exclude (e.g. `--exclude "*.css"`). |
|
|
90
|
-
| `--no-gitignore` | Disable `.gitignore` parsing (scan everything except default excludes). |
|
|
50
|
+
## Usage
|
|
91
51
|
|
|
92
|
-
###
|
|
52
|
+
### Pack Context
|
|
53
|
+
Collect your project files into one file or directly to your clipboard. Kodu respects your `.gitignore` automatically.
|
|
93
54
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
| `-y, --yes` | Skip confirmation prompt (Danger!). |
|
|
98
|
-
| `-e, --exclude` | Exclude patterns from stripping. |
|
|
99
|
-
| `--no-gitignore` | Disable `.gitignore` parsing. |
|
|
55
|
+
```bash
|
|
56
|
+
# Copy context to clipboard with a specific prompt template
|
|
57
|
+
kodu pack --copy --template refactor
|
|
100
58
|
|
|
101
|
-
|
|
59
|
+
# Save context to a specific file
|
|
60
|
+
kodu pack --out context.txt
|
|
61
|
+
```
|
|
102
62
|
|
|
103
|
-
|
|
63
|
+
### Clean Code
|
|
64
|
+
Remove comments from your JS/TS files to reduce token usage. It uses safe parsing to ensure `@ts-ignore`, `TODO`, and `biome-ignore` comments are preserved.
|
|
104
65
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
4. **Config:** Configuration files.
|
|
109
|
-
5. **Source Code:** Files in `src/`, `lib/`.
|
|
110
|
-
6. **Tests:** Test files are placed last.
|
|
66
|
+
```bash
|
|
67
|
+
# See what will be removed without changing files
|
|
68
|
+
kodu clean --dry-run
|
|
111
69
|
|
|
112
|
-
|
|
70
|
+
# Clean the code
|
|
71
|
+
kodu clean
|
|
72
|
+
```
|
|
113
73
|
|
|
114
|
-
|
|
74
|
+
### AI Code Review
|
|
75
|
+
Analyze your **staged** changes before committing.
|
|
115
76
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
77
|
+
```bash
|
|
78
|
+
# Check for bugs (default)
|
|
79
|
+
kodu review
|
|
119
80
|
|
|
120
|
-
|
|
81
|
+
# Check for security vulnerabilities or style issues
|
|
82
|
+
kodu review --mode security
|
|
83
|
+
kodu review --mode style
|
|
84
|
+
```
|
|
121
85
|
|
|
122
|
-
|
|
86
|
+
### AI Commit Messages
|
|
87
|
+
Generate a concise Conventional Commit message based on your staged diff.
|
|
123
88
|
|
|
124
89
|
```bash
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
cd pp
|
|
90
|
+
kodu commit
|
|
91
|
+
```
|
|
128
92
|
|
|
129
|
-
|
|
130
|
-
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
Kodu is controlled by `kodu.json`. You can customize:
|
|
98
|
+
- **LLM Settings**: Choose your model (e.g., `gpt-4o`) and provider.
|
|
99
|
+
- **Ignored Patterns**: Files that should never be sent to the AI (e.g., lockfiles, binaries).
|
|
100
|
+
- **Cleaner Whitelist**: Specific comment prefixes you want to keep.
|
|
101
|
+
|
|
102
|
+
Example `kodu.json`:
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"llm": {
|
|
106
|
+
"model": "gpt-4o"
|
|
107
|
+
},
|
|
108
|
+
"packer": {
|
|
109
|
+
"ignore": ["*.log", "dist/**"]
|
|
110
|
+
},
|
|
111
|
+
"cleaner": {
|
|
112
|
+
"whitelist": ["//!"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
131
116
|
|
|
132
|
-
|
|
133
|
-
bun run dev
|
|
117
|
+
## Why Kodu?
|
|
134
118
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
119
|
+
1. **Speed**: Optimized for near-instant startup.
|
|
120
|
+
2. **Privacy & Control**: You decide exactly what code leaves your machine.
|
|
121
|
+
3. **Deterministic**: Code cleaning is performed via logic, not AI, ensuring your actual code logic is never accidentally altered.
|
|
122
|
+
4. **CI/CD Ready**: Use `--ci` and `--json` flags to integrate Kodu reviews into your automation pipelines.
|
|
138
123
|
|
|
139
|
-
|
|
124
|
+
---
|
|
140
125
|
|
|
141
|
-
|
|
126
|
+
**Happy Coding!** 🦄
|
package/biome.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
|
3
|
+
"assist": {
|
|
4
|
+
"actions": {
|
|
5
|
+
"source": {
|
|
6
|
+
"organizeImports": "on"
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"files": {
|
|
11
|
+
"ignoreUnknown": false,
|
|
12
|
+
"includes": ["**", "!**/node_modules", "!**/dist"]
|
|
13
|
+
},
|
|
14
|
+
"formatter": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"indentStyle": "space",
|
|
17
|
+
"lineEnding": "lf"
|
|
18
|
+
},
|
|
19
|
+
"javascript": {
|
|
20
|
+
"formatter": {
|
|
21
|
+
"quoteStyle": "single"
|
|
22
|
+
},
|
|
23
|
+
"parser": {
|
|
24
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"linter": {
|
|
28
|
+
"enabled": true,
|
|
29
|
+
"rules": {
|
|
30
|
+
"correctness": {
|
|
31
|
+
"noUnusedFunctionParameters": "error",
|
|
32
|
+
"noUnusedImports": "error",
|
|
33
|
+
"noUnusedVariables": "error"
|
|
34
|
+
},
|
|
35
|
+
"recommended": true,
|
|
36
|
+
"style": {
|
|
37
|
+
"noNonNullAssertion": "off",
|
|
38
|
+
"useImportType": "off"
|
|
39
|
+
},
|
|
40
|
+
"suspicious": {
|
|
41
|
+
"noPrototypeBuiltins": "off"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"vcs": {
|
|
46
|
+
"clientKind": "git",
|
|
47
|
+
"enabled": true,
|
|
48
|
+
"useIgnoreFile": true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AppModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const clean_module_1 = require("./commands/clean/clean.module");
|
|
12
|
+
const commit_module_1 = require("./commands/commit/commit.module");
|
|
13
|
+
const init_module_1 = require("./commands/init/init.module");
|
|
14
|
+
const pack_module_1 = require("./commands/pack/pack.module");
|
|
15
|
+
const review_module_1 = require("./commands/review/review.module");
|
|
16
|
+
const config_module_1 = require("./core/config/config.module");
|
|
17
|
+
const fs_module_1 = require("./core/file-system/fs.module");
|
|
18
|
+
const ui_module_1 = require("./core/ui/ui.module");
|
|
19
|
+
const ai_module_1 = require("./shared/ai/ai.module");
|
|
20
|
+
const git_module_1 = require("./shared/git/git.module");
|
|
21
|
+
const tokenizer_module_1 = require("./shared/tokenizer/tokenizer.module");
|
|
22
|
+
let AppModule = class AppModule {
|
|
23
|
+
};
|
|
24
|
+
exports.AppModule = AppModule;
|
|
25
|
+
exports.AppModule = AppModule = __decorate([
|
|
26
|
+
(0, common_1.Module)({
|
|
27
|
+
imports: [
|
|
28
|
+
config_module_1.ConfigModule,
|
|
29
|
+
ui_module_1.UiModule,
|
|
30
|
+
fs_module_1.FsModule,
|
|
31
|
+
git_module_1.GitModule,
|
|
32
|
+
ai_module_1.AiModule,
|
|
33
|
+
tokenizer_module_1.TokenizerModule,
|
|
34
|
+
init_module_1.InitModule,
|
|
35
|
+
pack_module_1.PackModule,
|
|
36
|
+
clean_module_1.CleanModule,
|
|
37
|
+
review_module_1.ReviewModule,
|
|
38
|
+
commit_module_1.CommitModule,
|
|
39
|
+
],
|
|
40
|
+
})
|
|
41
|
+
], AppModule);
|
|
42
|
+
//# sourceMappingURL=app.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,gEAA4D;AAC5D,mEAA+D;AAC/D,6DAAyD;AACzD,6DAAyD;AACzD,mEAA+D;AAC/D,+DAA2D;AAC3D,4DAAwD;AACxD,mDAA+C;AAC/C,qDAAiD;AACjD,wDAAoD;AACpD,0EAAsE;AAiB/D,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAfrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,4BAAY;YACZ,oBAAQ;YACR,oBAAQ;YACR,sBAAS;YACT,oBAAQ;YACR,kCAAe;YACf,wBAAU;YACV,wBAAU;YACV,0BAAW;YACX,4BAAY;YACZ,4BAAY;SACb;KACF,CAAC;GACW,SAAS,CAAG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CommandRunner } 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
|
+
type CleanOptions = {
|
|
6
|
+
dryRun?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare class CleanCommand extends CommandRunner {
|
|
9
|
+
private readonly ui;
|
|
10
|
+
private readonly fsService;
|
|
11
|
+
private readonly cleaner;
|
|
12
|
+
constructor(ui: UiService, fsService: FsService, cleaner: CleanerService);
|
|
13
|
+
parseDryRun(): boolean;
|
|
14
|
+
run(_inputs: string[], options?: CleanOptions): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CleanCommand = void 0;
|
|
13
|
+
const nest_commander_1 = require("nest-commander");
|
|
14
|
+
const fs_service_1 = require("../../core/file-system/fs.service");
|
|
15
|
+
const ui_service_1 = require("../../core/ui/ui.service");
|
|
16
|
+
const cleaner_service_1 = require("../../shared/cleaner/cleaner.service");
|
|
17
|
+
let CleanCommand = class CleanCommand extends nest_commander_1.CommandRunner {
|
|
18
|
+
ui;
|
|
19
|
+
fsService;
|
|
20
|
+
cleaner;
|
|
21
|
+
constructor(ui, fsService, cleaner) {
|
|
22
|
+
super();
|
|
23
|
+
this.ui = ui;
|
|
24
|
+
this.fsService = fsService;
|
|
25
|
+
this.cleaner = cleaner;
|
|
26
|
+
}
|
|
27
|
+
parseDryRun() {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
async run(_inputs, options = {}) {
|
|
31
|
+
const spinner = this.ui
|
|
32
|
+
.createSpinner({
|
|
33
|
+
text: options.dryRun
|
|
34
|
+
? 'Анализ комментариев...'
|
|
35
|
+
: 'Очистка комментариев...',
|
|
36
|
+
})
|
|
37
|
+
.start();
|
|
38
|
+
try {
|
|
39
|
+
const allFiles = await this.fsService.findProjectFiles();
|
|
40
|
+
const targets = allFiles.filter((file) => /\.(ts|tsx|js|jsx)$/i.test(file));
|
|
41
|
+
if (targets.length === 0) {
|
|
42
|
+
spinner.stop('Нет файлов для очистки.');
|
|
43
|
+
this.ui.log.warn('Нет файлов для очистки.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const summary = await this.cleaner.cleanFiles(targets, {
|
|
47
|
+
dryRun: options.dryRun,
|
|
48
|
+
});
|
|
49
|
+
spinner.success(options.dryRun ? 'Анализ завершен' : 'Очистка завершена');
|
|
50
|
+
if (options.dryRun) {
|
|
51
|
+
this.ui.log.info(`Будет затронуто файлов: ${summary.filesChanged}, комментариев: ${summary.commentsRemoved}`);
|
|
52
|
+
summary.reports
|
|
53
|
+
.filter((report) => report.removed > 0)
|
|
54
|
+
.forEach((report) => {
|
|
55
|
+
const previews = report.previews
|
|
56
|
+
.map((item) => `"${item}"`)
|
|
57
|
+
.join(', ');
|
|
58
|
+
this.ui.log.info(`- ${report.file} (${report.removed}): ${previews}`);
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.ui.log.success(`Очищено файлов: ${summary.filesChanged}, удалено комментариев: ${summary.commentsRemoved}`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
spinner.error('Ошибка при очистке');
|
|
66
|
+
const message = error instanceof Error ? error.message : 'Неизвестная ошибка';
|
|
67
|
+
this.ui.log.error(message);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
exports.CleanCommand = CleanCommand;
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, nest_commander_1.Option)({
|
|
75
|
+
flags: '-d, --dry-run',
|
|
76
|
+
description: 'Показать, что будет удалено',
|
|
77
|
+
}),
|
|
78
|
+
__metadata("design:type", Function),
|
|
79
|
+
__metadata("design:paramtypes", []),
|
|
80
|
+
__metadata("design:returntype", Boolean)
|
|
81
|
+
], CleanCommand.prototype, "parseDryRun", null);
|
|
82
|
+
exports.CleanCommand = CleanCommand = __decorate([
|
|
83
|
+
(0, nest_commander_1.Command)({ name: 'clean', description: 'Удалить комментарии из кода' }),
|
|
84
|
+
__metadata("design:paramtypes", [ui_service_1.UiService,
|
|
85
|
+
fs_service_1.FsService,
|
|
86
|
+
cleaner_service_1.CleanerService])
|
|
87
|
+
], CleanCommand);
|
|
88
|
+
//# sourceMappingURL=clean.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean.command.js","sourceRoot":"","sources":["../../../src/commands/clean/clean.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CleanModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const config_module_1 = require("../../core/config/config.module");
|
|
12
|
+
const fs_module_1 = require("../../core/file-system/fs.module");
|
|
13
|
+
const ui_module_1 = require("../../core/ui/ui.module");
|
|
14
|
+
const cleaner_service_1 = require("../../shared/cleaner/cleaner.service");
|
|
15
|
+
const clean_command_1 = require("./clean.command");
|
|
16
|
+
let CleanModule = class CleanModule {
|
|
17
|
+
};
|
|
18
|
+
exports.CleanModule = CleanModule;
|
|
19
|
+
exports.CleanModule = CleanModule = __decorate([
|
|
20
|
+
(0, common_1.Module)({
|
|
21
|
+
imports: [fs_module_1.FsModule, ui_module_1.UiModule, config_module_1.ConfigModule],
|
|
22
|
+
providers: [clean_command_1.CleanCommand, cleaner_service_1.CleanerService],
|
|
23
|
+
})
|
|
24
|
+
], CleanModule);
|
|
25
|
+
//# sourceMappingURL=clean.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean.module.js","sourceRoot":"","sources":["../../../src/commands/clean/clean.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,mEAA+D;AAC/D,gEAA4D;AAC5D,uDAAmD;AACnD,0EAAsE;AACtE,mDAA+C;AAMxC,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAJvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,oBAAQ,EAAE,oBAAQ,EAAE,4BAAY,CAAC;QAC3C,SAAS,EAAE,CAAC,4BAAY,EAAE,gCAAc,CAAC;KAC1C,CAAC;GACW,WAAW,CAAG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CommandRunner } from 'nest-commander';
|
|
2
|
+
import { UiService } from '../../core/ui/ui.service';
|
|
3
|
+
import { AiService } from '../../shared/ai/ai.service';
|
|
4
|
+
import { GitService } from '../../shared/git/git.service';
|
|
5
|
+
type CommitOptions = {
|
|
6
|
+
ci?: boolean;
|
|
7
|
+
output?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class CommitCommand extends CommandRunner {
|
|
10
|
+
private readonly ui;
|
|
11
|
+
private readonly git;
|
|
12
|
+
private readonly ai;
|
|
13
|
+
constructor(ui: UiService, git: GitService, ai: AiService);
|
|
14
|
+
parseCi(): boolean;
|
|
15
|
+
parseOutput(value: string): string;
|
|
16
|
+
run(_inputs: string[], options?: CommitOptions): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|