kodu 1.2.0 → 2.0.1
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/AGENTS.md +36 -68
- package/README.md +128 -96
- package/dist/package.json +1 -2
- package/dist/src/app.module.js +0 -8
- package/dist/src/app.module.js.map +1 -1
- package/dist/src/commands/clean/clean.command.d.ts +14 -1
- package/dist/src/commands/clean/clean.command.js +142 -32
- package/dist/src/commands/clean/clean.command.js.map +1 -1
- package/dist/src/commands/init/init.command.d.ts +2 -9
- package/dist/src/commands/init/init.command.js +15 -241
- package/dist/src/commands/init/init.command.js.map +1 -1
- package/dist/src/commands/pack/pack.command.d.ts +12 -1
- package/dist/src/commands/pack/pack.command.js +81 -6
- package/dist/src/commands/pack/pack.command.js.map +1 -1
- package/dist/src/commands/pack/pack.module.js +2 -1
- package/dist/src/commands/pack/pack.module.js.map +1 -1
- package/dist/src/core/config/config.schema.d.ts +0 -46
- package/dist/src/core/config/config.schema.js +1 -51
- package/dist/src/core/config/config.schema.js.map +1 -1
- package/dist/src/core/config/config.service.js +2 -2
- package/dist/src/core/config/config.service.js.map +1 -1
- package/dist/src/core/config/prompt.service.d.ts +1 -4
- package/dist/src/core/config/prompt.service.js +4 -17
- package/dist/src/core/config/prompt.service.js.map +1 -1
- package/dist/src/shared/cleaner/cleaner.service.d.ts +2 -0
- package/dist/src/shared/cleaner/cleaner.service.js +32 -7
- package/dist/src/shared/cleaner/cleaner.service.js.map +1 -1
- package/dist/src/shared/cleaner/cleaner.types.d.ts +7 -0
- package/dist/src/shared/constants.d.ts +0 -4
- package/dist/src/shared/constants.js +1 -5
- package/dist/src/shared/constants.js.map +1 -1
- package/dist/src/shared/git/git.module.js +0 -2
- package/dist/src/shared/git/git.module.js.map +1 -1
- package/dist/src/shared/git/git.service.d.ts +1 -8
- package/dist/src/shared/git/git.service.js +10 -33
- package/dist/src/shared/git/git.service.js.map +1 -1
- package/dist/src/shared/tokenizer/tokenizer.module.js +0 -2
- package/dist/src/shared/tokenizer/tokenizer.module.js.map +1 -1
- package/dist/src/shared/tokenizer/tokenizer.service.d.ts +0 -6
- package/dist/src/shared/tokenizer/tokenizer.service.js +8 -38
- package/dist/src/shared/tokenizer/tokenizer.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/kodu.schema.json +0 -139
- package/package.json +1 -2
- package/src/app.module.ts +0 -8
- package/src/commands/clean/clean.command.ts +143 -33
- package/src/commands/init/init.command.ts +15 -310
- package/src/commands/pack/pack.command.ts +74 -4
- package/src/commands/pack/pack.module.ts +2 -1
- package/src/core/config/config.schema.ts +1 -68
- package/src/core/config/config.service.ts +2 -2
- package/src/core/config/prompt.service.ts +4 -26
- package/src/shared/cleaner/cleaner.service.ts +43 -12
- package/src/shared/cleaner/cleaner.types.ts +7 -0
- package/src/shared/constants.ts +0 -4
- package/src/shared/git/git.module.ts +0 -2
- package/src/shared/git/git.service.ts +9 -31
- package/src/shared/tokenizer/tokenizer.module.ts +0 -2
- package/src/shared/tokenizer/tokenizer.service.ts +9 -39
- package/.kodu/prompts/.keep +0 -0
- package/.kodu/prompts/commit.md +0 -9
- package/.kodu/prompts/pack.md +0 -7
- package/.kodu/prompts/review-bug.md +0 -6
- package/.kodu/prompts/review-security.md +0 -6
- package/.kodu/prompts/review-style.md +0 -6
- package/.opencode/command/openspec-apply.md +0 -24
- package/.opencode/command/openspec-archive.md +0 -27
- package/.opencode/command/openspec-proposal.md +0 -29
- package/.opencode/skills/kodu-ops/SKILL.md +0 -184
- package/dist/src/commands/commit/commit.command.d.ts +0 -18
- package/dist/src/commands/commit/commit.command.js +0 -149
- package/dist/src/commands/commit/commit.command.js.map +0 -1
- package/dist/src/commands/commit/commit.module.d.ts +0 -2
- package/dist/src/commands/commit/commit.module.js +0 -25
- package/dist/src/commands/commit/commit.module.js.map +0 -1
- package/dist/src/commands/ops/ops.command.d.ts +0 -4
- package/dist/src/commands/ops/ops.command.js +0 -39
- package/dist/src/commands/ops/ops.command.js.map +0 -1
- package/dist/src/commands/ops/ops.module.d.ts +0 -2
- package/dist/src/commands/ops/ops.module.js +0 -33
- package/dist/src/commands/ops/ops.module.js.map +0 -1
- package/dist/src/commands/ops/ops.types.d.ts +0 -13
- package/dist/src/commands/ops/ops.types.js +0 -12
- package/dist/src/commands/ops/ops.types.js.map +0 -1
- package/dist/src/commands/ops/ops.utils.d.ts +0 -13
- package/dist/src/commands/ops/ops.utils.js +0 -121
- package/dist/src/commands/ops/ops.utils.js.map +0 -1
- package/dist/src/commands/ops/subcommands/ops-env.command.d.ts +0 -24
- package/dist/src/commands/ops/subcommands/ops-env.command.js +0 -156
- package/dist/src/commands/ops/subcommands/ops-env.command.js.map +0 -1
- package/dist/src/commands/ops/subcommands/ops-routes.command.d.ts +0 -22
- package/dist/src/commands/ops/subcommands/ops-routes.command.js +0 -203
- package/dist/src/commands/ops/subcommands/ops-routes.command.js.map +0 -1
- package/dist/src/commands/ops/subcommands/ops-service.command.d.ts +0 -22
- package/dist/src/commands/ops/subcommands/ops-service.command.js +0 -169
- package/dist/src/commands/ops/subcommands/ops-service.command.js.map +0 -1
- package/dist/src/commands/ops/subcommands/ops-sysinfo.command.d.ts +0 -14
- package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js +0 -75
- package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js.map +0 -1
- package/dist/src/commands/review/review.command.d.ts +0 -26
- package/dist/src/commands/review/review.command.js +0 -205
- package/dist/src/commands/review/review.command.js.map +0 -1
- package/dist/src/commands/review/review.module.d.ts +0 -2
- package/dist/src/commands/review/review.module.js +0 -26
- package/dist/src/commands/review/review.module.js.map +0 -1
- package/dist/src/core/config/default-prompts.d.ts +0 -9
- package/dist/src/core/config/default-prompts.js +0 -49
- package/dist/src/core/config/default-prompts.js.map +0 -1
- package/dist/src/shared/ai/ai.module.d.ts +0 -2
- package/dist/src/shared/ai/ai.module.js +0 -23
- package/dist/src/shared/ai/ai.module.js.map +0 -1
- package/dist/src/shared/ai/ai.service.d.ts +0 -22
- package/dist/src/shared/ai/ai.service.js +0 -164
- package/dist/src/shared/ai/ai.service.js.map +0 -1
- package/dist/src/shared/ssh/ssh.module.d.ts +0 -2
- package/dist/src/shared/ssh/ssh.module.js +0 -21
- package/dist/src/shared/ssh/ssh.module.js.map +0 -1
- package/dist/src/shared/ssh/ssh.service.d.ts +0 -11
- package/dist/src/shared/ssh/ssh.service.js +0 -53
- package/dist/src/shared/ssh/ssh.service.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/commands/commit/commit.command.ts +0 -139
- package/src/commands/commit/commit.module.ts +0 -12
- package/src/commands/ops/ops.command.ts +0 -30
- package/src/commands/ops/ops.module.ts +0 -20
- package/src/commands/ops/ops.types.ts +0 -24
- package/src/commands/ops/ops.utils.ts +0 -160
- package/src/commands/ops/subcommands/ops-env.command.ts +0 -165
- package/src/commands/ops/subcommands/ops-routes.command.ts +0 -221
- package/src/commands/ops/subcommands/ops-service.command.ts +0 -190
- package/src/commands/ops/subcommands/ops-sysinfo.command.ts +0 -77
- package/src/commands/review/review.command.ts +0 -199
- package/src/commands/review/review.module.ts +0 -13
- package/src/core/config/default-prompts.ts +0 -53
- package/src/shared/ai/ai.module.ts +0 -10
- package/src/shared/ai/ai.service.ts +0 -216
- package/src/shared/ssh/ssh.module.ts +0 -8
- package/src/shared/ssh/ssh.service.ts +0 -61
package/kodu.schema.json
CHANGED
|
@@ -5,74 +5,6 @@
|
|
|
5
5
|
"$schema": {
|
|
6
6
|
"type": "string"
|
|
7
7
|
},
|
|
8
|
-
"llm": {
|
|
9
|
-
"type": "object",
|
|
10
|
-
"properties": {
|
|
11
|
-
"model": {
|
|
12
|
-
"default": "openai/gpt-4o",
|
|
13
|
-
"type": "string",
|
|
14
|
-
"pattern": "^[a-zA-Z0-9-_]+\\/[a-zA-Z0-9-_.]+$"
|
|
15
|
-
},
|
|
16
|
-
"apiKeyEnv": {
|
|
17
|
-
"default": "OPENAI_API_KEY",
|
|
18
|
-
"type": "string"
|
|
19
|
-
},
|
|
20
|
-
"commands": {
|
|
21
|
-
"default": {
|
|
22
|
-
"commit": {
|
|
23
|
-
"modelSettings": {
|
|
24
|
-
"maxOutputTokens": 1500
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"review": {
|
|
28
|
-
"modelSettings": {
|
|
29
|
-
"maxOutputTokens": 5000
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"type": "object",
|
|
34
|
-
"properties": {
|
|
35
|
-
"commit": {
|
|
36
|
-
"type": "object",
|
|
37
|
-
"properties": {
|
|
38
|
-
"modelSettings": {
|
|
39
|
-
"type": "object",
|
|
40
|
-
"properties": {
|
|
41
|
-
"maxOutputTokens": {
|
|
42
|
-
"type": "integer",
|
|
43
|
-
"exclusiveMinimum": 0,
|
|
44
|
-
"maximum": 9007199254740991
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
"additionalProperties": {}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"additionalProperties": false
|
|
51
|
-
},
|
|
52
|
-
"review": {
|
|
53
|
-
"type": "object",
|
|
54
|
-
"properties": {
|
|
55
|
-
"modelSettings": {
|
|
56
|
-
"type": "object",
|
|
57
|
-
"properties": {
|
|
58
|
-
"maxOutputTokens": {
|
|
59
|
-
"type": "integer",
|
|
60
|
-
"exclusiveMinimum": 0,
|
|
61
|
-
"maximum": 9007199254740991
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
"additionalProperties": {}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
"additionalProperties": false
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
"additionalProperties": false
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
"required": ["model", "apiKeyEnv"],
|
|
74
|
-
"additionalProperties": false
|
|
75
|
-
},
|
|
76
8
|
"cleaner": {
|
|
77
9
|
"default": {
|
|
78
10
|
"whitelist": ["//!"],
|
|
@@ -156,82 +88,11 @@
|
|
|
156
88
|
"prompts": {
|
|
157
89
|
"type": "object",
|
|
158
90
|
"properties": {
|
|
159
|
-
"review": {
|
|
160
|
-
"type": "object",
|
|
161
|
-
"propertyNames": {
|
|
162
|
-
"type": "string"
|
|
163
|
-
},
|
|
164
|
-
"additionalProperties": {
|
|
165
|
-
"type": "string"
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
"commit": {
|
|
169
|
-
"type": "string"
|
|
170
|
-
},
|
|
171
91
|
"pack": {
|
|
172
92
|
"type": "string"
|
|
173
93
|
}
|
|
174
94
|
},
|
|
175
95
|
"additionalProperties": false
|
|
176
|
-
},
|
|
177
|
-
"ops": {
|
|
178
|
-
"type": "object",
|
|
179
|
-
"properties": {
|
|
180
|
-
"servers": {
|
|
181
|
-
"type": "object",
|
|
182
|
-
"propertyNames": {
|
|
183
|
-
"type": "string"
|
|
184
|
-
},
|
|
185
|
-
"additionalProperties": {
|
|
186
|
-
"type": "object",
|
|
187
|
-
"properties": {
|
|
188
|
-
"host": {
|
|
189
|
-
"type": "string"
|
|
190
|
-
},
|
|
191
|
-
"port": {
|
|
192
|
-
"default": 22,
|
|
193
|
-
"type": "number"
|
|
194
|
-
},
|
|
195
|
-
"user": {
|
|
196
|
-
"type": "string"
|
|
197
|
-
},
|
|
198
|
-
"sshKeyPath": {
|
|
199
|
-
"type": "string"
|
|
200
|
-
},
|
|
201
|
-
"description": {
|
|
202
|
-
"type": "string"
|
|
203
|
-
},
|
|
204
|
-
"paths": {
|
|
205
|
-
"type": "object",
|
|
206
|
-
"properties": {
|
|
207
|
-
"apps": {
|
|
208
|
-
"default": "/var/agent-apps",
|
|
209
|
-
"type": "string"
|
|
210
|
-
},
|
|
211
|
-
"caddy": {
|
|
212
|
-
"type": "string"
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
"required": ["apps"],
|
|
216
|
-
"additionalProperties": false
|
|
217
|
-
},
|
|
218
|
-
"env": {
|
|
219
|
-
"type": "object",
|
|
220
|
-
"propertyNames": {
|
|
221
|
-
"type": "string"
|
|
222
|
-
},
|
|
223
|
-
"additionalProperties": {
|
|
224
|
-
"type": "string"
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
"required": ["host", "port", "user", "sshKeyPath"],
|
|
229
|
-
"additionalProperties": false
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
"required": ["servers"],
|
|
234
|
-
"additionalProperties": false
|
|
235
96
|
}
|
|
236
97
|
},
|
|
237
98
|
"required": ["cleaner", "packer"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodu",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "High-performance CLI to prepare codebase for LLMs, automate reviews, and draft commits.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
"@inquirer/confirm": "^6.0.4",
|
|
51
51
|
"@inquirer/input": "^5.0.4",
|
|
52
52
|
"@inquirer/select": "^5.0.4",
|
|
53
|
-
"@mastra/core": "^1.0.4",
|
|
54
53
|
"@nestjs/common": "^11.0.1",
|
|
55
54
|
"@nestjs/core": "^11.0.1",
|
|
56
55
|
"clipboardy": "^5.0.2",
|
package/src/app.module.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { Module } from '@nestjs/common';
|
|
2
2
|
import { CleanModule } from './commands/clean/clean.module';
|
|
3
|
-
import { CommitModule } from './commands/commit/commit.module';
|
|
4
3
|
import { InitModule } from './commands/init/init.module';
|
|
5
|
-
import { OpsModule } from './commands/ops/ops.module';
|
|
6
4
|
import { PackModule } from './commands/pack/pack.module';
|
|
7
|
-
import { ReviewModule } from './commands/review/review.module';
|
|
8
5
|
import { ConfigModule } from './core/config/config.module';
|
|
9
6
|
import { FsModule } from './core/file-system/fs.module';
|
|
10
7
|
import { UiModule } from './core/ui/ui.module';
|
|
11
|
-
import { AiModule } from './shared/ai/ai.module';
|
|
12
8
|
import { GitModule } from './shared/git/git.module';
|
|
13
9
|
import { TokenizerModule } from './shared/tokenizer/tokenizer.module';
|
|
14
10
|
|
|
@@ -18,14 +14,10 @@ import { TokenizerModule } from './shared/tokenizer/tokenizer.module';
|
|
|
18
14
|
UiModule,
|
|
19
15
|
FsModule,
|
|
20
16
|
GitModule,
|
|
21
|
-
AiModule,
|
|
22
17
|
TokenizerModule,
|
|
23
18
|
InitModule,
|
|
24
19
|
PackModule,
|
|
25
20
|
CleanModule,
|
|
26
|
-
ReviewModule,
|
|
27
|
-
CommitModule,
|
|
28
|
-
OpsModule,
|
|
29
21
|
],
|
|
30
22
|
})
|
|
31
23
|
export class AppModule {}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createReadStream } from 'node:fs';
|
|
1
2
|
import { Command, CommandRunner, Option } from 'nest-commander';
|
|
2
3
|
import { ConfigService } from '../../core/config/config.service';
|
|
3
4
|
import { FsService } from '../../core/file-system/fs.service';
|
|
@@ -5,9 +6,16 @@ import { UiService } from '../../core/ui/ui.service';
|
|
|
5
6
|
import { CleanerService } from '../../shared/cleaner/cleaner.service';
|
|
6
7
|
import { GitService } from '../../shared/git/git.service';
|
|
7
8
|
|
|
9
|
+
const SUPPORTED_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|html|htm)$/i;
|
|
10
|
+
|
|
8
11
|
type CleanOptions = {
|
|
9
12
|
dryRun?: boolean;
|
|
10
13
|
changed?: boolean;
|
|
14
|
+
staged?: boolean;
|
|
15
|
+
backup?: boolean;
|
|
16
|
+
noJsdoc?: boolean;
|
|
17
|
+
verbose?: boolean;
|
|
18
|
+
stdin?: boolean;
|
|
11
19
|
};
|
|
12
20
|
|
|
13
21
|
@Command({ name: 'clean', description: 'Remove comments from code' })
|
|
@@ -22,23 +30,65 @@ export class CleanCommand extends CommandRunner {
|
|
|
22
30
|
super();
|
|
23
31
|
}
|
|
24
32
|
|
|
25
|
-
@Option({
|
|
26
|
-
flags: '-d, --dry-run',
|
|
27
|
-
description: 'Show what will be removed',
|
|
28
|
-
})
|
|
33
|
+
@Option({ flags: '-d, --dry-run', description: 'Show what will be removed' })
|
|
29
34
|
parseDryRun(): boolean {
|
|
30
35
|
return true;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
@Option({
|
|
34
39
|
flags: '-c, --changed',
|
|
35
|
-
description: 'Clean only changed files',
|
|
40
|
+
description: 'Clean only git-changed files (staged + unstaged + untracked)',
|
|
36
41
|
})
|
|
37
42
|
parseChanged(): boolean {
|
|
38
43
|
return true;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
@Option({
|
|
47
|
+
flags: '-s, --staged',
|
|
48
|
+
description: 'Clean only git-staged files',
|
|
49
|
+
})
|
|
50
|
+
parseStaged(): boolean {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Option({
|
|
55
|
+
flags: '-b, --backup',
|
|
56
|
+
description: 'Save originals to .kodu/backup/ before modifying',
|
|
57
|
+
})
|
|
58
|
+
parseBackup(): boolean {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Option({
|
|
63
|
+
flags: '-n, --no-jsdoc',
|
|
64
|
+
description: 'Remove JSDoc comments (overrides config keepJSDoc)',
|
|
65
|
+
})
|
|
66
|
+
parseNoJsdoc(): boolean {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Option({
|
|
71
|
+
flags: '-v, --verbose',
|
|
72
|
+
description: 'Show all removed comments in dry-run (not just first 3)',
|
|
73
|
+
})
|
|
74
|
+
parseVerbose(): boolean {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@Option({
|
|
79
|
+
flags: '--stdin',
|
|
80
|
+
description: 'Read from stdin, write cleaned result to stdout',
|
|
81
|
+
})
|
|
82
|
+
parseStdin(): boolean {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async run(inputs: string[], options: CleanOptions = {}): Promise<void> {
|
|
87
|
+
if (options.stdin) {
|
|
88
|
+
await this.runStdin(options);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
42
92
|
const spinner = this.ui
|
|
43
93
|
.createSpinner({ text: this.buildSpinnerText(options) })
|
|
44
94
|
.start();
|
|
@@ -53,45 +103,62 @@ export class CleanCommand extends CommandRunner {
|
|
|
53
103
|
useGitignore: cleanerConfig.useGitignore,
|
|
54
104
|
ignore: ignorePatterns,
|
|
55
105
|
});
|
|
56
|
-
|
|
106
|
+
|
|
107
|
+
const targets = await this.collectTargets(allFiles, inputs, options);
|
|
57
108
|
|
|
58
109
|
if (targets.length === 0) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
spinner.stop(noFilesMessage);
|
|
63
|
-
this.ui.log.warn(noFilesMessage);
|
|
110
|
+
const msg = this.noFilesMessage(options);
|
|
111
|
+
spinner.stop(msg);
|
|
112
|
+
this.ui.log.warn(msg);
|
|
64
113
|
return;
|
|
65
114
|
}
|
|
66
115
|
|
|
67
116
|
const summary = await this.cleaner.cleanFiles(targets, {
|
|
68
117
|
dryRun: options.dryRun,
|
|
118
|
+
backup: options.backup,
|
|
119
|
+
keepJSDoc: options.noJsdoc ? false : undefined,
|
|
120
|
+
onProgress: (current, total) => {
|
|
121
|
+
spinner.text = `${this.buildSpinnerText(options)} (${current}/${total})`;
|
|
122
|
+
},
|
|
69
123
|
});
|
|
70
124
|
|
|
71
125
|
spinner.success(
|
|
72
126
|
options.dryRun ? 'Analysis complete' : 'Cleaning complete',
|
|
73
127
|
);
|
|
74
128
|
|
|
129
|
+
const bytesSaved = summary.bytesBefore - summary.bytesAfter;
|
|
130
|
+
const tokensSaved = Math.round(bytesSaved / 4);
|
|
131
|
+
|
|
75
132
|
if (options.dryRun) {
|
|
76
133
|
this.ui.log.info(
|
|
77
|
-
`Files
|
|
134
|
+
`Files affected: ${summary.filesChanged}/${summary.filesProcessed}, comments: ${summary.commentsRemoved}`,
|
|
78
135
|
);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
136
|
+
this.ui.log.info(`Bytes saved: ${bytesSaved} (~${tokensSaved} tokens)`);
|
|
137
|
+
|
|
138
|
+
const limit = options.verbose ? Number.POSITIVE_INFINITY : 3;
|
|
139
|
+
for (const report of summary.reports.filter((r) => r.removed > 0)) {
|
|
140
|
+
const previews = options.verbose
|
|
141
|
+
? report.previews
|
|
142
|
+
: report.previews.slice(0, limit);
|
|
143
|
+
const more =
|
|
144
|
+
!options.verbose && report.previews.length > limit
|
|
145
|
+
? ` +${report.previews.length - limit} more`
|
|
146
|
+
: '';
|
|
147
|
+
this.ui.log.info(
|
|
148
|
+
` ${report.file} (${report.removed}): ${previews.map((p) => `"${p}"`).join(', ')}${more}`,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
89
151
|
return;
|
|
90
152
|
}
|
|
91
153
|
|
|
92
154
|
this.ui.log.success(
|
|
93
155
|
`Files cleaned: ${summary.filesChanged}, comments removed: ${summary.commentsRemoved}`,
|
|
94
156
|
);
|
|
157
|
+
this.ui.log.info(`Bytes saved: ${bytesSaved} (~${tokensSaved} tokens)`);
|
|
158
|
+
|
|
159
|
+
if (options.backup && summary.filesChanged > 0) {
|
|
160
|
+
this.ui.log.info('Originals backed up to .kodu/backup/');
|
|
161
|
+
}
|
|
95
162
|
} catch (error) {
|
|
96
163
|
spinner.error('Error during cleaning');
|
|
97
164
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -100,26 +167,69 @@ export class CleanCommand extends CommandRunner {
|
|
|
100
167
|
}
|
|
101
168
|
}
|
|
102
169
|
|
|
170
|
+
private async runStdin(options: CleanOptions): Promise<void> {
|
|
171
|
+
try {
|
|
172
|
+
const input = await this.readStdin();
|
|
173
|
+
const cleaned = this.cleaner.cleanContent(
|
|
174
|
+
'stdin.ts',
|
|
175
|
+
input,
|
|
176
|
+
options.noJsdoc ? false : undefined,
|
|
177
|
+
);
|
|
178
|
+
process.stdout.write(cleaned);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
181
|
+
this.ui.log.error(message);
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private readStdin(): Promise<string> {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
const chunks: Buffer[] = [];
|
|
189
|
+
const stream = createReadStream('/dev/stdin');
|
|
190
|
+
stream.on('data', (chunk) =>
|
|
191
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk),
|
|
192
|
+
);
|
|
193
|
+
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
194
|
+
stream.on('error', reject);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
103
198
|
private buildSpinnerText(options: CleanOptions): string {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return
|
|
199
|
+
if (options.staged) return 'Cleaning staged files...';
|
|
200
|
+
if (options.changed) return 'Cleaning changed files...';
|
|
201
|
+
return options.dryRun ? 'Analysing...' : 'Cleaning...';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private noFilesMessage(options: CleanOptions): string {
|
|
205
|
+
if (options.staged) return 'No staged files to clean.';
|
|
206
|
+
if (options.changed) return 'No changed files to clean.';
|
|
207
|
+
return 'No files to clean.';
|
|
107
208
|
}
|
|
108
209
|
|
|
109
210
|
private async collectTargets(
|
|
110
211
|
allFiles: string[],
|
|
212
|
+
inputs: string[],
|
|
111
213
|
options: CleanOptions,
|
|
112
214
|
): Promise<string[]> {
|
|
113
|
-
const
|
|
114
|
-
|
|
215
|
+
const supported = allFiles.filter((f) => SUPPORTED_EXTENSIONS.test(f));
|
|
216
|
+
|
|
217
|
+
if (inputs.length > 0) {
|
|
218
|
+
return supported.filter((f) =>
|
|
219
|
+
inputs.some((i) => f === i || f.startsWith(`${i.replace(/\/$/, '')}/`)),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
115
222
|
|
|
116
|
-
if (
|
|
117
|
-
|
|
223
|
+
if (options.staged) {
|
|
224
|
+
const staged = new Set(await this.git.getStagedFiles());
|
|
225
|
+
return supported.filter((f) => staged.has(f));
|
|
118
226
|
}
|
|
119
227
|
|
|
120
|
-
|
|
121
|
-
|
|
228
|
+
if (options.changed) {
|
|
229
|
+
const changed = new Set(await this.git.getChangedFiles());
|
|
230
|
+
return supported.filter((f) => changed.has(f));
|
|
231
|
+
}
|
|
122
232
|
|
|
123
|
-
return
|
|
233
|
+
return supported;
|
|
124
234
|
}
|
|
125
235
|
}
|