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.
Files changed (138) hide show
  1. package/AGENTS.md +36 -68
  2. package/README.md +128 -96
  3. package/dist/package.json +1 -2
  4. package/dist/src/app.module.js +0 -8
  5. package/dist/src/app.module.js.map +1 -1
  6. package/dist/src/commands/clean/clean.command.d.ts +14 -1
  7. package/dist/src/commands/clean/clean.command.js +142 -32
  8. package/dist/src/commands/clean/clean.command.js.map +1 -1
  9. package/dist/src/commands/init/init.command.d.ts +2 -9
  10. package/dist/src/commands/init/init.command.js +15 -241
  11. package/dist/src/commands/init/init.command.js.map +1 -1
  12. package/dist/src/commands/pack/pack.command.d.ts +12 -1
  13. package/dist/src/commands/pack/pack.command.js +81 -6
  14. package/dist/src/commands/pack/pack.command.js.map +1 -1
  15. package/dist/src/commands/pack/pack.module.js +2 -1
  16. package/dist/src/commands/pack/pack.module.js.map +1 -1
  17. package/dist/src/core/config/config.schema.d.ts +0 -46
  18. package/dist/src/core/config/config.schema.js +1 -51
  19. package/dist/src/core/config/config.schema.js.map +1 -1
  20. package/dist/src/core/config/config.service.js +2 -2
  21. package/dist/src/core/config/config.service.js.map +1 -1
  22. package/dist/src/core/config/prompt.service.d.ts +1 -4
  23. package/dist/src/core/config/prompt.service.js +4 -17
  24. package/dist/src/core/config/prompt.service.js.map +1 -1
  25. package/dist/src/shared/cleaner/cleaner.service.d.ts +2 -0
  26. package/dist/src/shared/cleaner/cleaner.service.js +32 -7
  27. package/dist/src/shared/cleaner/cleaner.service.js.map +1 -1
  28. package/dist/src/shared/cleaner/cleaner.types.d.ts +7 -0
  29. package/dist/src/shared/constants.d.ts +0 -4
  30. package/dist/src/shared/constants.js +1 -5
  31. package/dist/src/shared/constants.js.map +1 -1
  32. package/dist/src/shared/git/git.module.js +0 -2
  33. package/dist/src/shared/git/git.module.js.map +1 -1
  34. package/dist/src/shared/git/git.service.d.ts +1 -8
  35. package/dist/src/shared/git/git.service.js +10 -33
  36. package/dist/src/shared/git/git.service.js.map +1 -1
  37. package/dist/src/shared/tokenizer/tokenizer.module.js +0 -2
  38. package/dist/src/shared/tokenizer/tokenizer.module.js.map +1 -1
  39. package/dist/src/shared/tokenizer/tokenizer.service.d.ts +0 -6
  40. package/dist/src/shared/tokenizer/tokenizer.service.js +8 -38
  41. package/dist/src/shared/tokenizer/tokenizer.service.js.map +1 -1
  42. package/dist/tsconfig.build.tsbuildinfo +1 -1
  43. package/kodu.schema.json +0 -139
  44. package/package.json +1 -2
  45. package/src/app.module.ts +0 -8
  46. package/src/commands/clean/clean.command.ts +143 -33
  47. package/src/commands/init/init.command.ts +15 -310
  48. package/src/commands/pack/pack.command.ts +74 -4
  49. package/src/commands/pack/pack.module.ts +2 -1
  50. package/src/core/config/config.schema.ts +1 -68
  51. package/src/core/config/config.service.ts +2 -2
  52. package/src/core/config/prompt.service.ts +4 -26
  53. package/src/shared/cleaner/cleaner.service.ts +43 -12
  54. package/src/shared/cleaner/cleaner.types.ts +7 -0
  55. package/src/shared/constants.ts +0 -4
  56. package/src/shared/git/git.module.ts +0 -2
  57. package/src/shared/git/git.service.ts +9 -31
  58. package/src/shared/tokenizer/tokenizer.module.ts +0 -2
  59. package/src/shared/tokenizer/tokenizer.service.ts +9 -39
  60. package/.kodu/prompts/.keep +0 -0
  61. package/.kodu/prompts/commit.md +0 -9
  62. package/.kodu/prompts/pack.md +0 -7
  63. package/.kodu/prompts/review-bug.md +0 -6
  64. package/.kodu/prompts/review-security.md +0 -6
  65. package/.kodu/prompts/review-style.md +0 -6
  66. package/.opencode/command/openspec-apply.md +0 -24
  67. package/.opencode/command/openspec-archive.md +0 -27
  68. package/.opencode/command/openspec-proposal.md +0 -29
  69. package/.opencode/skills/kodu-ops/SKILL.md +0 -184
  70. package/dist/src/commands/commit/commit.command.d.ts +0 -18
  71. package/dist/src/commands/commit/commit.command.js +0 -149
  72. package/dist/src/commands/commit/commit.command.js.map +0 -1
  73. package/dist/src/commands/commit/commit.module.d.ts +0 -2
  74. package/dist/src/commands/commit/commit.module.js +0 -25
  75. package/dist/src/commands/commit/commit.module.js.map +0 -1
  76. package/dist/src/commands/ops/ops.command.d.ts +0 -4
  77. package/dist/src/commands/ops/ops.command.js +0 -39
  78. package/dist/src/commands/ops/ops.command.js.map +0 -1
  79. package/dist/src/commands/ops/ops.module.d.ts +0 -2
  80. package/dist/src/commands/ops/ops.module.js +0 -33
  81. package/dist/src/commands/ops/ops.module.js.map +0 -1
  82. package/dist/src/commands/ops/ops.types.d.ts +0 -13
  83. package/dist/src/commands/ops/ops.types.js +0 -12
  84. package/dist/src/commands/ops/ops.types.js.map +0 -1
  85. package/dist/src/commands/ops/ops.utils.d.ts +0 -13
  86. package/dist/src/commands/ops/ops.utils.js +0 -121
  87. package/dist/src/commands/ops/ops.utils.js.map +0 -1
  88. package/dist/src/commands/ops/subcommands/ops-env.command.d.ts +0 -24
  89. package/dist/src/commands/ops/subcommands/ops-env.command.js +0 -156
  90. package/dist/src/commands/ops/subcommands/ops-env.command.js.map +0 -1
  91. package/dist/src/commands/ops/subcommands/ops-routes.command.d.ts +0 -22
  92. package/dist/src/commands/ops/subcommands/ops-routes.command.js +0 -203
  93. package/dist/src/commands/ops/subcommands/ops-routes.command.js.map +0 -1
  94. package/dist/src/commands/ops/subcommands/ops-service.command.d.ts +0 -22
  95. package/dist/src/commands/ops/subcommands/ops-service.command.js +0 -169
  96. package/dist/src/commands/ops/subcommands/ops-service.command.js.map +0 -1
  97. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.d.ts +0 -14
  98. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js +0 -75
  99. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js.map +0 -1
  100. package/dist/src/commands/review/review.command.d.ts +0 -26
  101. package/dist/src/commands/review/review.command.js +0 -205
  102. package/dist/src/commands/review/review.command.js.map +0 -1
  103. package/dist/src/commands/review/review.module.d.ts +0 -2
  104. package/dist/src/commands/review/review.module.js +0 -26
  105. package/dist/src/commands/review/review.module.js.map +0 -1
  106. package/dist/src/core/config/default-prompts.d.ts +0 -9
  107. package/dist/src/core/config/default-prompts.js +0 -49
  108. package/dist/src/core/config/default-prompts.js.map +0 -1
  109. package/dist/src/shared/ai/ai.module.d.ts +0 -2
  110. package/dist/src/shared/ai/ai.module.js +0 -23
  111. package/dist/src/shared/ai/ai.module.js.map +0 -1
  112. package/dist/src/shared/ai/ai.service.d.ts +0 -22
  113. package/dist/src/shared/ai/ai.service.js +0 -164
  114. package/dist/src/shared/ai/ai.service.js.map +0 -1
  115. package/dist/src/shared/ssh/ssh.module.d.ts +0 -2
  116. package/dist/src/shared/ssh/ssh.module.js +0 -21
  117. package/dist/src/shared/ssh/ssh.module.js.map +0 -1
  118. package/dist/src/shared/ssh/ssh.service.d.ts +0 -11
  119. package/dist/src/shared/ssh/ssh.service.js +0 -53
  120. package/dist/src/shared/ssh/ssh.service.js.map +0 -1
  121. package/dist/tsconfig.tsbuildinfo +0 -1
  122. package/src/commands/commit/commit.command.ts +0 -139
  123. package/src/commands/commit/commit.module.ts +0 -12
  124. package/src/commands/ops/ops.command.ts +0 -30
  125. package/src/commands/ops/ops.module.ts +0 -20
  126. package/src/commands/ops/ops.types.ts +0 -24
  127. package/src/commands/ops/ops.utils.ts +0 -160
  128. package/src/commands/ops/subcommands/ops-env.command.ts +0 -165
  129. package/src/commands/ops/subcommands/ops-routes.command.ts +0 -221
  130. package/src/commands/ops/subcommands/ops-service.command.ts +0 -190
  131. package/src/commands/ops/subcommands/ops-sysinfo.command.ts +0 -77
  132. package/src/commands/review/review.command.ts +0 -199
  133. package/src/commands/review/review.module.ts +0 -13
  134. package/src/core/config/default-prompts.ts +0 -53
  135. package/src/shared/ai/ai.module.ts +0 -10
  136. package/src/shared/ai/ai.service.ts +0 -216
  137. package/src/shared/ssh/ssh.module.ts +0 -8
  138. 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": "1.2.0",
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
- async run(_inputs: string[], options: CleanOptions = {}): Promise<void> {
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
- const targets = await this.collectTargets(allFiles, options);
106
+
107
+ const targets = await this.collectTargets(allFiles, inputs, options);
57
108
 
58
109
  if (targets.length === 0) {
59
- const noFilesMessage = options.changed
60
- ? 'No changed files to clean.'
61
- : 'No files to clean.';
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 to be affected: ${summary.filesChanged}, comments: ${summary.commentsRemoved}`,
134
+ `Files affected: ${summary.filesChanged}/${summary.filesProcessed}, comments: ${summary.commentsRemoved}`,
78
135
  );
79
- summary.reports
80
- .filter((report) => report.removed > 0)
81
- .forEach((report) => {
82
- const previews = report.previews
83
- .map((item) => `"${item}"`)
84
- .join(', ');
85
- this.ui.log.info(
86
- `- ${report.file} (${report.removed}): ${previews}`,
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
- const action = options.dryRun ? 'Analysis' : 'Cleaning';
105
- const target = options.changed ? ' changed files' : ' comments';
106
- return `${action}${target}...`;
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 matcher = /\.(ts|tsx|js|jsx|html)$/i;
114
- const filtered = allFiles.filter((file) => matcher.test(file));
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 (!options.changed) {
117
- return filtered;
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
- const changedFiles = await this.git.getChangedFiles();
121
- const changedSet = new Set(changedFiles);
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 filtered.filter((file) => changedSet.has(file));
233
+ return supported;
124
234
  }
125
235
  }