@mr_ezo/aicommits 1.0.0
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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +897 -0
- package/dist/cli.js.map +1 -0
- package/dist/providers/groq.d.ts +3 -0
- package/dist/providers/groq.d.ts.map +1 -0
- package/dist/providers/groq.js +121 -0
- package/dist/providers/groq.js.map +1 -0
- package/dist/providers/types.d.ts +10 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +3 -0
- package/dist/providers/types.js.map +1 -0
- package/package.json +31 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,897 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
4
|
+
import { createInterface } from "node:readline/promises";
|
|
5
|
+
import { groqProvider } from "./providers/groq.js";
|
|
6
|
+
const MAX_CHARS = 25_000;
|
|
7
|
+
const LOCKFILES = new Set(["package-lock.json", "yarn.lock", "pnpm-lock.yaml"]);
|
|
8
|
+
const EXCLUDED_PREFIXES = ["dist/", "build/", "coverage/", "node_modules/"];
|
|
9
|
+
const ALLOWED_COMMIT_TYPES = new Set([
|
|
10
|
+
"feat",
|
|
11
|
+
"fix",
|
|
12
|
+
"docs",
|
|
13
|
+
"refactor",
|
|
14
|
+
"perf",
|
|
15
|
+
"test",
|
|
16
|
+
"build",
|
|
17
|
+
"ci",
|
|
18
|
+
"chore",
|
|
19
|
+
"revert",
|
|
20
|
+
]);
|
|
21
|
+
const SAFE_FALLBACK_MESSAGE = "chore: update staged changes";
|
|
22
|
+
const MAX_REGENERATIONS = 3;
|
|
23
|
+
const MAX_REGENERATION_PROVIDER_ATTEMPTS = 3;
|
|
24
|
+
const MAX_CUSTOM_INSTRUCTIONS_CHARS = 1_000;
|
|
25
|
+
const STYLE_HISTORY_LIMIT = 20;
|
|
26
|
+
function printHelp() {
|
|
27
|
+
console.log([
|
|
28
|
+
"Usage:",
|
|
29
|
+
" aicommits [--custom \"<preferences>\"] [--include-lockfiles] [--exclude <glob>] [--debug-payload] [--copy] [--dry-run] [--help]",
|
|
30
|
+
"",
|
|
31
|
+
"Options:",
|
|
32
|
+
" --custom <text> Add optional commit style preferences (max 1000 chars).",
|
|
33
|
+
" This is additive and never overrides safety/format rules.",
|
|
34
|
+
" --include-lockfiles",
|
|
35
|
+
" Include lockfile diffs in AI input (default: excluded).",
|
|
36
|
+
" --exclude <glob> Exclude staged paths from AI input (repeatable).",
|
|
37
|
+
" Examples: --exclude \"dist/**\" --exclude \"*.map\"",
|
|
38
|
+
" --debug-payload Print exact payload text sent to the provider.",
|
|
39
|
+
" --copy Copy final validated message to clipboard, then exit.",
|
|
40
|
+
" --dry-run Print final validated message and exit (no prompt, no commit).",
|
|
41
|
+
" --help, -h Show this help message.",
|
|
42
|
+
"",
|
|
43
|
+
"Examples:",
|
|
44
|
+
" aicommits",
|
|
45
|
+
" aicommits --custom \"prefer scope cli and mention tests when relevant\"",
|
|
46
|
+
" aicommits --custom \"focus on user-facing behavior changes\"",
|
|
47
|
+
" aicommits --include-lockfiles",
|
|
48
|
+
" aicommits --exclude \"dist/**\" --exclude \"*.map\"",
|
|
49
|
+
" aicommits --debug-payload",
|
|
50
|
+
" aicommits --copy",
|
|
51
|
+
" aicommits --dry-run",
|
|
52
|
+
].join("\n"));
|
|
53
|
+
}
|
|
54
|
+
function parseCliOptions(argv) {
|
|
55
|
+
const parsed = {
|
|
56
|
+
showHelp: false,
|
|
57
|
+
includeLockfiles: false,
|
|
58
|
+
excludeGlobs: [],
|
|
59
|
+
debugPayload: false,
|
|
60
|
+
copy: false,
|
|
61
|
+
dryRun: false,
|
|
62
|
+
};
|
|
63
|
+
let sawCustom = false;
|
|
64
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
65
|
+
const arg = argv[i];
|
|
66
|
+
if (!arg) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (arg === "--help" || arg === "-h") {
|
|
70
|
+
parsed.showHelp = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (arg === "--include-lockfiles") {
|
|
74
|
+
parsed.includeLockfiles = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (arg === "--debug-payload") {
|
|
78
|
+
parsed.debugPayload = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (arg === "--copy") {
|
|
82
|
+
parsed.copy = true;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (arg === "--dry-run") {
|
|
86
|
+
parsed.dryRun = true;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (arg === "--exclude") {
|
|
90
|
+
const next = argv[i + 1];
|
|
91
|
+
if (!next || next === "--help" || next === "-h" || next.startsWith("--")) {
|
|
92
|
+
throw new Error("Missing value for `--exclude`. Example: --exclude \"dist/**\"");
|
|
93
|
+
}
|
|
94
|
+
parsed.excludeGlobs.push(next);
|
|
95
|
+
i += 1;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (arg.startsWith("--exclude=")) {
|
|
99
|
+
parsed.excludeGlobs.push(arg.slice("--exclude=".length));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (arg === "--custom") {
|
|
103
|
+
if (sawCustom) {
|
|
104
|
+
throw new Error("`--custom` can only be provided once.");
|
|
105
|
+
}
|
|
106
|
+
const next = argv[i + 1];
|
|
107
|
+
if (!next || next === "--help" || next === "-h" || next.startsWith("--")) {
|
|
108
|
+
throw new Error("Missing value for `--custom`. Example: --custom \"prefer concise subjects\"");
|
|
109
|
+
}
|
|
110
|
+
parsed.customInstructions = next;
|
|
111
|
+
sawCustom = true;
|
|
112
|
+
i += 1;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (arg.startsWith("--custom=")) {
|
|
116
|
+
if (sawCustom) {
|
|
117
|
+
throw new Error("`--custom` can only be provided once.");
|
|
118
|
+
}
|
|
119
|
+
parsed.customInstructions = arg.slice("--custom=".length);
|
|
120
|
+
sawCustom = true;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (arg.startsWith("-")) {
|
|
124
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
127
|
+
}
|
|
128
|
+
if (parsed.customInstructions !== undefined) {
|
|
129
|
+
const custom = parsed.customInstructions.trim();
|
|
130
|
+
if (custom.length === 0) {
|
|
131
|
+
throw new Error("`--custom` value cannot be empty.");
|
|
132
|
+
}
|
|
133
|
+
if (custom.length > MAX_CUSTOM_INSTRUCTIONS_CHARS) {
|
|
134
|
+
throw new Error(`\`--custom\` is too long (${custom.length} chars). Max is ${MAX_CUSTOM_INSTRUCTIONS_CHARS} chars.`);
|
|
135
|
+
}
|
|
136
|
+
parsed.customInstructions = custom;
|
|
137
|
+
}
|
|
138
|
+
parsed.excludeGlobs = parsed.excludeGlobs.map((glob) => glob.trim()).filter(Boolean);
|
|
139
|
+
for (const glob of parsed.excludeGlobs) {
|
|
140
|
+
if (glob.length > 512) {
|
|
141
|
+
throw new Error(`\`--exclude\` glob is too long (${glob.length} chars).`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
function getRecentCommitSubjects(limit = STYLE_HISTORY_LIMIT) {
|
|
147
|
+
try {
|
|
148
|
+
const raw = run(`git log -n ${limit} --pretty=%s`);
|
|
149
|
+
return raw
|
|
150
|
+
.split(/\r?\n/)
|
|
151
|
+
.map((line) => line.trim())
|
|
152
|
+
.filter(Boolean);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Best-effort only (e.g., brand new repo with no commits).
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function getMostFrequent(counts) {
|
|
160
|
+
let bestValue = "";
|
|
161
|
+
let bestCount = 0;
|
|
162
|
+
for (const [value, count] of counts.entries()) {
|
|
163
|
+
if (count > bestCount) {
|
|
164
|
+
bestValue = value;
|
|
165
|
+
bestCount = count;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!bestValue) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
return { value: bestValue, count: bestCount };
|
|
172
|
+
}
|
|
173
|
+
function getLetterCase(text) {
|
|
174
|
+
const firstLetter = text.match(/[A-Za-z]/)?.[0] ?? "";
|
|
175
|
+
if (!firstLetter) {
|
|
176
|
+
return "none";
|
|
177
|
+
}
|
|
178
|
+
return firstLetter === firstLetter.toLowerCase() ? "lower" : "upper";
|
|
179
|
+
}
|
|
180
|
+
function inferRepoStyleInstructions(subjects) {
|
|
181
|
+
if (subjects.length === 0) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
const typeCounts = new Map();
|
|
185
|
+
const scopeCounts = new Map();
|
|
186
|
+
let parsedCount = 0;
|
|
187
|
+
let lowerCaseSubjects = 0;
|
|
188
|
+
let upperCaseSubjects = 0;
|
|
189
|
+
let ticketPrefixCount = 0;
|
|
190
|
+
let ticketPrefixSample = "";
|
|
191
|
+
for (const subject of subjects) {
|
|
192
|
+
const parsed = parseCommitMessage(subject);
|
|
193
|
+
const subjectText = parsed?.subject ?? subject;
|
|
194
|
+
const letterCase = getLetterCase(subjectText);
|
|
195
|
+
if (letterCase === "lower") {
|
|
196
|
+
lowerCaseSubjects += 1;
|
|
197
|
+
}
|
|
198
|
+
else if (letterCase === "upper") {
|
|
199
|
+
upperCaseSubjects += 1;
|
|
200
|
+
}
|
|
201
|
+
const ticketMatch = subjectText.match(/^(?:\[[A-Z]+-\d+\]|[A-Z]+-\d+)[:\s-]?/);
|
|
202
|
+
if (ticketMatch) {
|
|
203
|
+
ticketPrefixCount += 1;
|
|
204
|
+
if (!ticketPrefixSample) {
|
|
205
|
+
ticketPrefixSample = ticketMatch[0].trim();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!parsed) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
parsedCount += 1;
|
|
212
|
+
typeCounts.set(parsed.type, (typeCounts.get(parsed.type) ?? 0) + 1);
|
|
213
|
+
if (parsed.scope) {
|
|
214
|
+
scopeCounts.set(parsed.scope, (scopeCounts.get(parsed.scope) ?? 0) + 1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const hints = [];
|
|
218
|
+
const dominantType = getMostFrequent(typeCounts);
|
|
219
|
+
if (dominantType && parsedCount > 0 && dominantType.count / parsedCount >= 0.35) {
|
|
220
|
+
hints.push(`Prefer type \`${dominantType.value}\` when it accurately matches the staged change.`);
|
|
221
|
+
}
|
|
222
|
+
const dominantScope = getMostFrequent(scopeCounts);
|
|
223
|
+
if (dominantScope && parsedCount > 0 && dominantScope.count / parsedCount >= 0.25) {
|
|
224
|
+
hints.push(`Preferred scope is often \`${dominantScope.value}\`; use it when relevant.`);
|
|
225
|
+
}
|
|
226
|
+
if (subjects.length > 0 && lowerCaseSubjects / subjects.length >= 0.7) {
|
|
227
|
+
hints.push("Start subject text with lowercase (repo convention).");
|
|
228
|
+
}
|
|
229
|
+
else if (subjects.length > 0 && upperCaseSubjects / subjects.length >= 0.7) {
|
|
230
|
+
hints.push("Start subject text with uppercase (repo convention).");
|
|
231
|
+
}
|
|
232
|
+
if (subjects.length > 0 && ticketPrefixCount / subjects.length >= 0.25) {
|
|
233
|
+
const sample = ticketPrefixSample || "ABC-123";
|
|
234
|
+
hints.push(`When applicable, keep ticket-prefix style in subject (e.g. \`${sample}\`).`);
|
|
235
|
+
}
|
|
236
|
+
if (hints.length === 0) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
return [
|
|
240
|
+
`Repository style hints inferred from last ${subjects.length} commit subjects:`,
|
|
241
|
+
...hints.map((hint) => `- ${hint}`),
|
|
242
|
+
].join("\n");
|
|
243
|
+
}
|
|
244
|
+
function buildEffectiveCustomInstructions(userCustomInstructions) {
|
|
245
|
+
const styleInstructions = inferRepoStyleInstructions(getRecentCommitSubjects());
|
|
246
|
+
if (styleInstructions && userCustomInstructions) {
|
|
247
|
+
return `${styleInstructions}\n\nUser preferences:\n${userCustomInstructions}`;
|
|
248
|
+
}
|
|
249
|
+
return styleInstructions || userCustomInstructions;
|
|
250
|
+
}
|
|
251
|
+
// Runs a shell command and returns stdout as a string.
|
|
252
|
+
// Throws if the command exits non-zero.
|
|
253
|
+
function run(cmd) {
|
|
254
|
+
return execSync(cmd, {
|
|
255
|
+
encoding: "utf8",
|
|
256
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
function isGitRepo() {
|
|
260
|
+
try {
|
|
261
|
+
run("git rev-parse --is-inside-work-tree");
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function getStagedNameStatus() {
|
|
269
|
+
return run("git diff --staged --name-status");
|
|
270
|
+
}
|
|
271
|
+
function getStagedDiffUnified0() {
|
|
272
|
+
return run("git diff --staged --unified=0");
|
|
273
|
+
}
|
|
274
|
+
function parseStagedNameStatus(rawNameStatus) {
|
|
275
|
+
const files = [];
|
|
276
|
+
const lines = rawNameStatus.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
277
|
+
for (const line of lines) {
|
|
278
|
+
// Git usually uses tabs here; fall back to whitespace to stay resilient.
|
|
279
|
+
const tabParts = line.split("\t");
|
|
280
|
+
const statusToken = tabParts[0]?.trim();
|
|
281
|
+
if (!statusToken) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const statusChar = statusToken.charAt(0);
|
|
285
|
+
if (!statusChar) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const status = statusChar;
|
|
289
|
+
if (!["A", "M", "D", "R", "C"].includes(status)) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
let path = "";
|
|
293
|
+
if (tabParts.length >= 2) {
|
|
294
|
+
// For rename/copy, use the destination path (last field).
|
|
295
|
+
path = (tabParts[tabParts.length - 1] ?? "").trim();
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const whitespaceParts = line.trim().split(/\s+/);
|
|
299
|
+
path = whitespaceParts.slice(1).join(" ").trim();
|
|
300
|
+
}
|
|
301
|
+
if (!path) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
files.push({ status, path });
|
|
305
|
+
}
|
|
306
|
+
return files;
|
|
307
|
+
}
|
|
308
|
+
function normalizePath(path) {
|
|
309
|
+
return path.replace(/\\/g, "/");
|
|
310
|
+
}
|
|
311
|
+
function globToRegExp(glob) {
|
|
312
|
+
const normalizedGlob = normalizePath(glob).replace(/^\.\/+/, "");
|
|
313
|
+
let pattern = "";
|
|
314
|
+
for (let i = 0; i < normalizedGlob.length; i += 1) {
|
|
315
|
+
const ch = normalizedGlob.charAt(i);
|
|
316
|
+
if (ch === "*") {
|
|
317
|
+
if (normalizedGlob.charAt(i + 1) === "*") {
|
|
318
|
+
pattern += ".*";
|
|
319
|
+
i += 1;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
pattern += "[^/]*";
|
|
323
|
+
}
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (ch === "?") {
|
|
327
|
+
pattern += "[^/]";
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
pattern += ch.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&");
|
|
331
|
+
}
|
|
332
|
+
return new RegExp(`^${pattern}$`);
|
|
333
|
+
}
|
|
334
|
+
function matchesGlob(path, glob) {
|
|
335
|
+
const normalizedPath = normalizePath(path);
|
|
336
|
+
const normalizedGlob = normalizePath(glob).replace(/^\.\/+/, "");
|
|
337
|
+
if (!normalizedGlob) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const regex = globToRegExp(normalizedGlob);
|
|
341
|
+
if (normalizedGlob.includes("/")) {
|
|
342
|
+
return regex.test(normalizedPath);
|
|
343
|
+
}
|
|
344
|
+
const basename = normalizedPath.split("/").at(-1) ?? normalizedPath;
|
|
345
|
+
return regex.test(normalizedPath) || regex.test(basename);
|
|
346
|
+
}
|
|
347
|
+
function isLockfile(path) {
|
|
348
|
+
return LOCKFILES.has(normalizePath(path));
|
|
349
|
+
}
|
|
350
|
+
function getExclusionReason(path, options) {
|
|
351
|
+
const normalized = normalizePath(path);
|
|
352
|
+
const matchingGlob = options.excludeGlobs.find((glob) => matchesGlob(normalized, glob));
|
|
353
|
+
if (matchingGlob) {
|
|
354
|
+
return `matched --exclude ${matchingGlob}`;
|
|
355
|
+
}
|
|
356
|
+
if (EXCLUDED_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
|
|
357
|
+
return "generated/build directory";
|
|
358
|
+
}
|
|
359
|
+
if (normalized === "node_modules" || normalized.includes("/node_modules/")) {
|
|
360
|
+
return "node_modules";
|
|
361
|
+
}
|
|
362
|
+
if (normalized.endsWith(".map")) {
|
|
363
|
+
return "*.map";
|
|
364
|
+
}
|
|
365
|
+
if (normalized.includes(".min.")) {
|
|
366
|
+
return "*.min.*";
|
|
367
|
+
}
|
|
368
|
+
if (normalized === ".env") {
|
|
369
|
+
return ".env";
|
|
370
|
+
}
|
|
371
|
+
if (!options.includeLockfiles && isLockfile(normalized)) {
|
|
372
|
+
return "lockfile";
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
function isExcludedFromLLM(path, options) {
|
|
377
|
+
return getExclusionReason(path, options) !== null;
|
|
378
|
+
}
|
|
379
|
+
function printAIInputSummary(stagedFiles, options) {
|
|
380
|
+
const included = stagedFiles.filter((file) => !isExcludedFromLLM(file.path, options));
|
|
381
|
+
const excluded = stagedFiles
|
|
382
|
+
.map((file) => ({ file, reason: getExclusionReason(file.path, options) }))
|
|
383
|
+
.filter((item) => item.reason !== null);
|
|
384
|
+
console.log(`ℹ️ AI input summary: ${included.length} included, ${excluded.length} excluded, ${stagedFiles.length} staged total`);
|
|
385
|
+
if (included.length > 0) {
|
|
386
|
+
const includedList = included.map((file) => `${file.status} ${file.path}`).join(", ");
|
|
387
|
+
console.log(` included: ${includedList}`);
|
|
388
|
+
}
|
|
389
|
+
if (excluded.length > 0) {
|
|
390
|
+
const excludedList = excluded
|
|
391
|
+
.map((item) => `${item.file.status} ${item.file.path} (${item.reason})`)
|
|
392
|
+
.join(", ");
|
|
393
|
+
console.log(` excluded: ${excludedList}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function assertNoSecrets(rawDiff) {
|
|
397
|
+
// Very basic “obvious secret” patterns (MVP).
|
|
398
|
+
// This is NOT perfect security—just a guardrail.
|
|
399
|
+
const secretPatterns = [
|
|
400
|
+
{ name: "private key block", re: /BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY/i },
|
|
401
|
+
// Match env-style secret assignments (e.g. GROQ_API_KEY=..., export API_KEY=...)
|
|
402
|
+
// and avoid false positives like `const apiKey = ...`.
|
|
403
|
+
{ name: "API key assignment", re: /\b(?:export\s+)?[A-Z0-9_]*API[_-]?KEY[A-Z0-9_]*\s*=\s*\S+/ },
|
|
404
|
+
{ name: "password assignment", re: /\bPASS(?:WORD)?\s*=/i },
|
|
405
|
+
{ name: "secret assignment", re: /\bSECRET\s*=/i },
|
|
406
|
+
{ name: "token assignment", re: /\bTOKEN\s*=/i },
|
|
407
|
+
// common OpenAI-style key prefix (not guaranteed, but good guardrail)
|
|
408
|
+
{ name: "sk- token prefix", re: /\bsk-[A-Za-z0-9]{16,}/ },
|
|
409
|
+
];
|
|
410
|
+
for (const p of secretPatterns) {
|
|
411
|
+
if (p.re.test(rawDiff)) {
|
|
412
|
+
// Block sending this to any LLM.
|
|
413
|
+
throw new Error(`Possible sensitive data detected (${p.name}). Refusing to continue. ` +
|
|
414
|
+
`Unstage/remove secrets and try again.`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function collectNoiseWarnings(rawDiff) {
|
|
419
|
+
const warnings = [];
|
|
420
|
+
// Optional “noise” warnings (we don't remove yet; just warn).
|
|
421
|
+
const noisyPathHints = [
|
|
422
|
+
{ label: "node_modules/", re: /diff --git a\/(?:.+\/)?node_modules\// },
|
|
423
|
+
{ label: "dist/ or build output", re: /diff --git a\/(?:dist|build)\// },
|
|
424
|
+
{ label: "coverage/", re: /diff --git a\/coverage\// },
|
|
425
|
+
{ label: "lockfile", re: /diff --git a\/(?:package-lock\.json|yarn\.lock|pnpm-lock\.yaml)/ },
|
|
426
|
+
{ label: ".env file", re: /diff --git a\/\.env(\.|$)/ },
|
|
427
|
+
];
|
|
428
|
+
for (const n of noisyPathHints) {
|
|
429
|
+
if (n.re.test(rawDiff)) {
|
|
430
|
+
warnings.push(`⚠️ Diff includes ${n.label} (often noise). Consider unstaging if unintended.`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return warnings;
|
|
434
|
+
}
|
|
435
|
+
function truncateForLLM(text) {
|
|
436
|
+
const warnings = [];
|
|
437
|
+
let output = text;
|
|
438
|
+
if (output.length > MAX_CHARS) {
|
|
439
|
+
warnings.push(`⚠️ Large payload (${output.length.toLocaleString()} chars). Using first ${MAX_CHARS.toLocaleString()} chars.`);
|
|
440
|
+
output = output.slice(0, MAX_CHARS) + "\n\n…(truncated)\n";
|
|
441
|
+
}
|
|
442
|
+
return { text: output, warnings };
|
|
443
|
+
}
|
|
444
|
+
function filterDiffByExcludedFiles(diffUnified0, options) {
|
|
445
|
+
if (!diffUnified0.trim()) {
|
|
446
|
+
return "";
|
|
447
|
+
}
|
|
448
|
+
const lines = diffUnified0.split("\n");
|
|
449
|
+
const keptChunks = [];
|
|
450
|
+
let currentChunk = [];
|
|
451
|
+
let keepCurrentChunk = true;
|
|
452
|
+
const flushChunk = () => {
|
|
453
|
+
if (currentChunk.length > 0 && keepCurrentChunk) {
|
|
454
|
+
keptChunks.push(currentChunk.join("\n"));
|
|
455
|
+
}
|
|
456
|
+
currentChunk = [];
|
|
457
|
+
keepCurrentChunk = true;
|
|
458
|
+
};
|
|
459
|
+
for (const line of lines) {
|
|
460
|
+
if (line.startsWith("diff --git ")) {
|
|
461
|
+
flushChunk();
|
|
462
|
+
currentChunk.push(line);
|
|
463
|
+
const match = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
464
|
+
const path = match?.[2] ?? match?.[1] ?? "";
|
|
465
|
+
keepCurrentChunk = path ? !isExcludedFromLLM(path, options) : true;
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
currentChunk.push(line);
|
|
469
|
+
}
|
|
470
|
+
flushChunk();
|
|
471
|
+
return keptChunks.join("\n").trim();
|
|
472
|
+
}
|
|
473
|
+
function buildLLMPayload(stagedFiles, diffUnified0, options) {
|
|
474
|
+
const stagedLines = stagedFiles.map((file) => {
|
|
475
|
+
const exclusionReason = getExclusionReason(file.path, options);
|
|
476
|
+
const excludedSuffix = exclusionReason ? ` (excluded: ${exclusionReason})` : "";
|
|
477
|
+
return `${file.status} ${file.path}${excludedSuffix}`;
|
|
478
|
+
});
|
|
479
|
+
const filteredDiff = filterDiffByExcludedFiles(diffUnified0, options);
|
|
480
|
+
return [
|
|
481
|
+
"STAGED FILES:",
|
|
482
|
+
...stagedLines,
|
|
483
|
+
"",
|
|
484
|
+
"FILTERED DIFF:",
|
|
485
|
+
filteredDiff || "(all staged file diffs excluded)",
|
|
486
|
+
].join("\n");
|
|
487
|
+
}
|
|
488
|
+
const CONVENTIONAL_COMMIT_RE = /^([a-z]+)(?:\(([^)]+)\))?: (.+)$/;
|
|
489
|
+
function validateCommitMessage(message) {
|
|
490
|
+
const trimmed = message.trim();
|
|
491
|
+
if (!trimmed) {
|
|
492
|
+
return { valid: false, reason: "empty message" };
|
|
493
|
+
}
|
|
494
|
+
if (trimmed.includes("\n") || trimmed.includes("\r")) {
|
|
495
|
+
return { valid: false, reason: "must be a single line" };
|
|
496
|
+
}
|
|
497
|
+
if (trimmed.length > 72) {
|
|
498
|
+
return { valid: false, reason: "must be <= 72 chars" };
|
|
499
|
+
}
|
|
500
|
+
if (trimmed.endsWith(".")) {
|
|
501
|
+
return { valid: false, reason: "must not end with a period" };
|
|
502
|
+
}
|
|
503
|
+
const match = trimmed.match(CONVENTIONAL_COMMIT_RE);
|
|
504
|
+
if (!match) {
|
|
505
|
+
return { valid: false, reason: "must match type(scope?): subject" };
|
|
506
|
+
}
|
|
507
|
+
const type = match[1];
|
|
508
|
+
const subject = match[3];
|
|
509
|
+
if (!type || !ALLOWED_COMMIT_TYPES.has(type)) {
|
|
510
|
+
return { valid: false, reason: "type must be allowed lowercase conventional type" };
|
|
511
|
+
}
|
|
512
|
+
if (!subject || !subject.trim()) {
|
|
513
|
+
return { valid: false, reason: "subject must be present" };
|
|
514
|
+
}
|
|
515
|
+
return { valid: true };
|
|
516
|
+
}
|
|
517
|
+
function parseCommitMessage(message) {
|
|
518
|
+
const match = message.trim().match(CONVENTIONAL_COMMIT_RE);
|
|
519
|
+
if (!match) {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
const type = match[1];
|
|
523
|
+
const scope = match[2];
|
|
524
|
+
const subject = match[3];
|
|
525
|
+
if (!type || !subject) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
if (scope) {
|
|
529
|
+
return { type, scope, subject };
|
|
530
|
+
}
|
|
531
|
+
return { type, subject };
|
|
532
|
+
}
|
|
533
|
+
function normalizeSubject(subject) {
|
|
534
|
+
return subject
|
|
535
|
+
.toLowerCase()
|
|
536
|
+
.replace(/[^a-z0-9\s]/g, " ")
|
|
537
|
+
.replace(/\s+/g, " ")
|
|
538
|
+
.trim();
|
|
539
|
+
}
|
|
540
|
+
function isSubjectMeaningfullyDifferent(previousSubject, nextSubject) {
|
|
541
|
+
const previous = normalizeSubject(previousSubject);
|
|
542
|
+
const next = normalizeSubject(nextSubject);
|
|
543
|
+
if (!previous || !next) {
|
|
544
|
+
return previous !== next;
|
|
545
|
+
}
|
|
546
|
+
if (previous === next) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
const previousWords = previous.split(" ").filter(Boolean);
|
|
550
|
+
const nextWords = next.split(" ").filter(Boolean);
|
|
551
|
+
const previousSet = new Set(previousWords);
|
|
552
|
+
const nextSet = new Set(nextWords);
|
|
553
|
+
const allWords = new Set([...previousSet, ...nextSet]);
|
|
554
|
+
let overlap = 0;
|
|
555
|
+
for (const word of previousSet) {
|
|
556
|
+
if (nextSet.has(word)) {
|
|
557
|
+
overlap += 1;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
const jaccard = allWords.size === 0 ? 1 : overlap / allWords.size;
|
|
561
|
+
return jaccard < 0.75;
|
|
562
|
+
}
|
|
563
|
+
function buildPrefix(type, scope) {
|
|
564
|
+
return scope ? `${type}(${scope})` : type;
|
|
565
|
+
}
|
|
566
|
+
function buildRetryPayload(basePayload, firstOutput, reason) {
|
|
567
|
+
return [
|
|
568
|
+
basePayload,
|
|
569
|
+
"",
|
|
570
|
+
"FORMAT FIX REQUEST:",
|
|
571
|
+
"Your previous output was invalid. Return ONLY one corrected commit message line.",
|
|
572
|
+
"Strict rules:",
|
|
573
|
+
"1) Must match: type(scope?): subject",
|
|
574
|
+
"2) Allowed lowercase types: feat, fix, docs, refactor, perf, test, build, ci, chore, revert",
|
|
575
|
+
"3) Max 72 characters total",
|
|
576
|
+
"4) No trailing period",
|
|
577
|
+
"5) No quotes, markdown, bullets, or extra text",
|
|
578
|
+
`Invalid output: ${firstOutput.replace(/\s+/g, " ").trim() || "(empty)"}`,
|
|
579
|
+
`Reason: ${reason}`,
|
|
580
|
+
].join("\n");
|
|
581
|
+
}
|
|
582
|
+
function printDebugPayload(payload, label) {
|
|
583
|
+
console.log(`\n🔎 DEBUG PAYLOAD (${label}) START`);
|
|
584
|
+
console.log(payload);
|
|
585
|
+
console.log(`🔎 DEBUG PAYLOAD (${label}) END\n`);
|
|
586
|
+
}
|
|
587
|
+
function copyToClipboard(text) {
|
|
588
|
+
const attempts = [];
|
|
589
|
+
if (process.platform === "darwin") {
|
|
590
|
+
attempts.push({ cmd: "pbcopy", args: [] });
|
|
591
|
+
}
|
|
592
|
+
else if (process.platform === "win32") {
|
|
593
|
+
attempts.push({ cmd: "clip", args: [] });
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
attempts.push({ cmd: "wl-copy", args: [] });
|
|
597
|
+
attempts.push({ cmd: "xclip", args: ["-selection", "clipboard"] });
|
|
598
|
+
attempts.push({ cmd: "xsel", args: ["--clipboard", "--input"] });
|
|
599
|
+
}
|
|
600
|
+
let lastError = "no clipboard command available";
|
|
601
|
+
for (const attempt of attempts) {
|
|
602
|
+
const result = spawnSync(attempt.cmd, attempt.args, {
|
|
603
|
+
input: text,
|
|
604
|
+
encoding: "utf8",
|
|
605
|
+
stdio: ["pipe", "ignore", "pipe"],
|
|
606
|
+
});
|
|
607
|
+
if (!result.error && (result.status ?? 1) === 0) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
lastError = result.error?.message || result.stderr || `exit code ${result.status ?? 1}`;
|
|
611
|
+
}
|
|
612
|
+
throw new Error(`Failed to copy to clipboard (${lastError.trim()}).`);
|
|
613
|
+
}
|
|
614
|
+
async function promptForCommitAction(message, allowRegenerate) {
|
|
615
|
+
console.log("✅ Proposed commit message:");
|
|
616
|
+
console.log(message);
|
|
617
|
+
const rl = createInterface({
|
|
618
|
+
input: process.stdin,
|
|
619
|
+
output: process.stdout,
|
|
620
|
+
});
|
|
621
|
+
try {
|
|
622
|
+
let settled = false;
|
|
623
|
+
const answer = await new Promise((resolve) => {
|
|
624
|
+
const settle = (value) => {
|
|
625
|
+
if (settled) {
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
settled = true;
|
|
629
|
+
resolve(value);
|
|
630
|
+
};
|
|
631
|
+
rl.on("SIGINT", () => settle(""));
|
|
632
|
+
rl.on("close", () => settle(""));
|
|
633
|
+
const prompt = allowRegenerate
|
|
634
|
+
? "\nCommit with this message? [y]es / [n]o / [r]egenerate: "
|
|
635
|
+
: "\nCommit with this message? (y/N): ";
|
|
636
|
+
rl.question(prompt)
|
|
637
|
+
.then((value) => settle(value))
|
|
638
|
+
.catch(() => settle(""));
|
|
639
|
+
});
|
|
640
|
+
const normalized = answer.trim().toLowerCase();
|
|
641
|
+
if (normalized === "y" || normalized === "yes") {
|
|
642
|
+
return "yes";
|
|
643
|
+
}
|
|
644
|
+
if (allowRegenerate && normalized === "r") {
|
|
645
|
+
return "regenerate";
|
|
646
|
+
}
|
|
647
|
+
return "no";
|
|
648
|
+
}
|
|
649
|
+
finally {
|
|
650
|
+
rl.close();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function commitWithMessage(message) {
|
|
654
|
+
const result = spawnSync("git", ["commit", "-m", message], {
|
|
655
|
+
stdio: "inherit",
|
|
656
|
+
});
|
|
657
|
+
if (result.error) {
|
|
658
|
+
throw result.error;
|
|
659
|
+
}
|
|
660
|
+
if ((result.status ?? 1) !== 0) {
|
|
661
|
+
throw new Error(`git commit failed with exit code ${result.status ?? 1}`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
function getDeterministicAlternativeMessage(previousMessage) {
|
|
665
|
+
const previous = previousMessage.trim();
|
|
666
|
+
const parsedPrevious = parseCommitMessage(previous);
|
|
667
|
+
if (parsedPrevious) {
|
|
668
|
+
const prefix = buildPrefix(parsedPrevious.type, parsedPrevious.scope);
|
|
669
|
+
const alternativeSubjects = [
|
|
670
|
+
"refine staged updates",
|
|
671
|
+
"adjust staged implementation",
|
|
672
|
+
"improve staged changes",
|
|
673
|
+
"update staged changes",
|
|
674
|
+
];
|
|
675
|
+
for (const subject of alternativeSubjects) {
|
|
676
|
+
if (!isSubjectMeaningfullyDifferent(parsedPrevious.subject, subject)) {
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
const candidate = `${prefix}: ${subject}`;
|
|
680
|
+
if (validateCommitMessage(candidate).valid) {
|
|
681
|
+
return candidate;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return SAFE_FALLBACK_MESSAGE;
|
|
686
|
+
}
|
|
687
|
+
async function generateValidatedMessage(payload, customInstructions, debugPayload = false) {
|
|
688
|
+
const providerOptions = customInstructions ? { customInstructions } : undefined;
|
|
689
|
+
if (debugPayload) {
|
|
690
|
+
printDebugPayload(payload, "provider:first-attempt");
|
|
691
|
+
}
|
|
692
|
+
const firstAttempt = await groqProvider.generateCommitMessage(payload, providerOptions);
|
|
693
|
+
const firstValidation = validateCommitMessage(firstAttempt);
|
|
694
|
+
let msg = firstAttempt.trim();
|
|
695
|
+
if (!firstValidation.valid) {
|
|
696
|
+
const retryPayload = buildRetryPayload(payload, firstAttempt, firstValidation.reason);
|
|
697
|
+
if (debugPayload) {
|
|
698
|
+
printDebugPayload(retryPayload, "provider:format-retry");
|
|
699
|
+
}
|
|
700
|
+
const secondAttempt = await groqProvider.generateCommitMessage(retryPayload, providerOptions);
|
|
701
|
+
const secondValidation = validateCommitMessage(secondAttempt);
|
|
702
|
+
if (secondValidation.valid) {
|
|
703
|
+
msg = secondAttempt.trim();
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
msg = SAFE_FALLBACK_MESSAGE;
|
|
707
|
+
console.log(`⚠️ Provider returned invalid commit messages twice (${firstValidation.reason}; ${secondValidation.reason}). Using fallback.`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const finalValidation = validateCommitMessage(msg);
|
|
711
|
+
if (!finalValidation.valid) {
|
|
712
|
+
console.log(`⚠️ Final message failed validation (${finalValidation.reason}). Using fallback.`);
|
|
713
|
+
return SAFE_FALLBACK_MESSAGE;
|
|
714
|
+
}
|
|
715
|
+
return msg;
|
|
716
|
+
}
|
|
717
|
+
async function generateDistinctRegeneratedMessage(basePayload, previousMessage, regenerationNumber, customInstructions, debugPayload = false) {
|
|
718
|
+
const previous = previousMessage.trim();
|
|
719
|
+
const previousParsed = parseCommitMessage(previous);
|
|
720
|
+
const fixedPrefix = previousParsed ? buildPrefix(previousParsed.type, previousParsed.scope) : "";
|
|
721
|
+
for (let attempt = 1; attempt <= MAX_REGENERATION_PROVIDER_ATTEMPTS; attempt += 1) {
|
|
722
|
+
const regenerationPayload = [
|
|
723
|
+
basePayload,
|
|
724
|
+
"",
|
|
725
|
+
"ALTERNATIVE PHRASING REQUEST:",
|
|
726
|
+
"Generate an alternative valid commit message by rephrasing the subject.",
|
|
727
|
+
"Keep the same underlying change intent and keep the same type/scope prefix.",
|
|
728
|
+
fixedPrefix ? `Required prefix: ${fixedPrefix}:` : "",
|
|
729
|
+
"Do NOT only swap the type (feat/fix/etc). Rewrite the subject wording.",
|
|
730
|
+
`Regeneration number: ${regenerationNumber}`,
|
|
731
|
+
`Message you MUST NOT repeat exactly: ${previous}`,
|
|
732
|
+
previousParsed ? `Previous subject you must rewrite: ${previousParsed.subject}` : "",
|
|
733
|
+
attempt > 1 ? "The previous regenerated output repeated. You must choose different wording." : "",
|
|
734
|
+
]
|
|
735
|
+
.filter(Boolean)
|
|
736
|
+
.join("\n");
|
|
737
|
+
const candidate = await generateValidatedMessage(regenerationPayload, customInstructions, debugPayload);
|
|
738
|
+
const candidateTrimmed = candidate.trim();
|
|
739
|
+
const candidateParsed = parseCommitMessage(candidateTrimmed);
|
|
740
|
+
const hasDifferentSubject = previousParsed && candidateParsed
|
|
741
|
+
? isSubjectMeaningfullyDifferent(previousParsed.subject, candidateParsed.subject)
|
|
742
|
+
: candidateTrimmed !== previous;
|
|
743
|
+
const hasSamePrefix = previousParsed && candidateParsed
|
|
744
|
+
? candidateParsed.type === previousParsed.type &&
|
|
745
|
+
(candidateParsed.scope ?? "") === (previousParsed.scope ?? "")
|
|
746
|
+
: true;
|
|
747
|
+
if (candidateTrimmed !== previous && hasSamePrefix && hasDifferentSubject) {
|
|
748
|
+
return candidate;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
console.log("⚠️ Regeneration repeated the same message. Using deterministic alternative.");
|
|
752
|
+
return getDeterministicAlternativeMessage(previous);
|
|
753
|
+
}
|
|
754
|
+
async function main() {
|
|
755
|
+
let cliOptions;
|
|
756
|
+
try {
|
|
757
|
+
cliOptions = parseCliOptions(process.argv.slice(2));
|
|
758
|
+
}
|
|
759
|
+
catch (e) {
|
|
760
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
761
|
+
console.error(`❌ ${msg}`);
|
|
762
|
+
console.error("Run `aicommits --help` for usage.");
|
|
763
|
+
process.exit(1);
|
|
764
|
+
}
|
|
765
|
+
if (cliOptions.showHelp) {
|
|
766
|
+
printHelp();
|
|
767
|
+
process.exit(0);
|
|
768
|
+
}
|
|
769
|
+
const userCustomInstructions = cliOptions.customInstructions;
|
|
770
|
+
if (userCustomInstructions) {
|
|
771
|
+
try {
|
|
772
|
+
assertNoSecrets(userCustomInstructions);
|
|
773
|
+
}
|
|
774
|
+
catch (e) {
|
|
775
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
776
|
+
console.error(`❌ ${msg}`);
|
|
777
|
+
process.exit(1);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
const effectiveCustomInstructions = buildEffectiveCustomInstructions(userCustomInstructions);
|
|
781
|
+
if (effectiveCustomInstructions && !userCustomInstructions) {
|
|
782
|
+
console.log("ℹ️ Applying inferred repository commit style from recent history.");
|
|
783
|
+
}
|
|
784
|
+
else if (effectiveCustomInstructions && userCustomInstructions) {
|
|
785
|
+
console.log("ℹ️ Applying inferred repository style + your custom instructions.");
|
|
786
|
+
}
|
|
787
|
+
const filteringOptions = {
|
|
788
|
+
includeLockfiles: cliOptions.includeLockfiles,
|
|
789
|
+
excludeGlobs: cliOptions.excludeGlobs,
|
|
790
|
+
};
|
|
791
|
+
const debugPayload = cliOptions.debugPayload;
|
|
792
|
+
if (!isGitRepo()) {
|
|
793
|
+
console.error("❌ Not a git repository. Run this inside a repo.");
|
|
794
|
+
process.exit(1);
|
|
795
|
+
}
|
|
796
|
+
const rawNameStatus = getStagedNameStatus();
|
|
797
|
+
if (!rawNameStatus.trim()) {
|
|
798
|
+
console.log("🟡 No staged changes. Run: git add <files>");
|
|
799
|
+
process.exit(0);
|
|
800
|
+
}
|
|
801
|
+
const stagedFiles = parseStagedNameStatus(rawNameStatus);
|
|
802
|
+
if (stagedFiles.length === 0) {
|
|
803
|
+
console.log("🟡 No staged changes. Run: git add <files>");
|
|
804
|
+
process.exit(0);
|
|
805
|
+
}
|
|
806
|
+
const rawDiffUnified0 = getStagedDiffUnified0();
|
|
807
|
+
console.log(`ℹ️ Raw diff size (unified=0): ${rawDiffUnified0.length.toLocaleString()} chars`);
|
|
808
|
+
try {
|
|
809
|
+
assertNoSecrets(rawDiffUnified0);
|
|
810
|
+
}
|
|
811
|
+
catch (e) {
|
|
812
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
813
|
+
console.error(`❌ ${msg}`);
|
|
814
|
+
process.exit(1);
|
|
815
|
+
}
|
|
816
|
+
printAIInputSummary(stagedFiles, filteringOptions);
|
|
817
|
+
const includedFiles = stagedFiles.filter((f) => !isExcludedFromLLM(f.path, filteringOptions));
|
|
818
|
+
const hasLockfile = stagedFiles.some((f) => isLockfile(f.path));
|
|
819
|
+
let finalMessage = "";
|
|
820
|
+
let truncatedPayload = "";
|
|
821
|
+
let canRegenerate = false;
|
|
822
|
+
if (includedFiles.length === 0 && hasLockfile) {
|
|
823
|
+
finalMessage = "chore(deps): update lockfile";
|
|
824
|
+
}
|
|
825
|
+
else {
|
|
826
|
+
const basePayload = buildLLMPayload(stagedFiles, rawDiffUnified0, filteringOptions);
|
|
827
|
+
const truncation = truncateForLLM(basePayload);
|
|
828
|
+
const warnings = [...collectNoiseWarnings(rawDiffUnified0), ...truncation.warnings];
|
|
829
|
+
truncatedPayload = truncation.text;
|
|
830
|
+
canRegenerate = true;
|
|
831
|
+
for (const w of warnings) {
|
|
832
|
+
console.log(w);
|
|
833
|
+
}
|
|
834
|
+
console.log(`ℹ️ Using payload size: ${truncatedPayload.length.toLocaleString()} chars\n`);
|
|
835
|
+
try {
|
|
836
|
+
finalMessage = await generateValidatedMessage(truncatedPayload, effectiveCustomInstructions, debugPayload);
|
|
837
|
+
}
|
|
838
|
+
catch (e) {
|
|
839
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
840
|
+
console.error(`❌ ${msg}`);
|
|
841
|
+
process.exit(1);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (cliOptions.copy || cliOptions.dryRun) {
|
|
845
|
+
console.log("✅ Final commit message:");
|
|
846
|
+
console.log(finalMessage);
|
|
847
|
+
if (cliOptions.copy) {
|
|
848
|
+
try {
|
|
849
|
+
copyToClipboard(finalMessage);
|
|
850
|
+
console.log("ℹ️ Copied commit message to clipboard.");
|
|
851
|
+
}
|
|
852
|
+
catch (e) {
|
|
853
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
854
|
+
console.error(`❌ ${msg}`);
|
|
855
|
+
process.exit(1);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
console.log("🟡 Non-destructive mode enabled. No commit was created.");
|
|
859
|
+
process.exit(0);
|
|
860
|
+
}
|
|
861
|
+
let regenerations = 0;
|
|
862
|
+
while (true) {
|
|
863
|
+
const allowRegenerate = canRegenerate && regenerations < MAX_REGENERATIONS;
|
|
864
|
+
const action = await promptForCommitAction(finalMessage, allowRegenerate);
|
|
865
|
+
if (action === "yes") {
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
if (action === "regenerate") {
|
|
869
|
+
regenerations += 1;
|
|
870
|
+
try {
|
|
871
|
+
finalMessage = await generateDistinctRegeneratedMessage(truncatedPayload, finalMessage, regenerations, effectiveCustomInstructions, debugPayload);
|
|
872
|
+
}
|
|
873
|
+
catch (e) {
|
|
874
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
875
|
+
console.error(`❌ ${msg}`);
|
|
876
|
+
process.exit(1);
|
|
877
|
+
}
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
console.log("🟡 Commit cancelled. No changes were committed.");
|
|
881
|
+
process.exit(0);
|
|
882
|
+
}
|
|
883
|
+
try {
|
|
884
|
+
commitWithMessage(finalMessage);
|
|
885
|
+
}
|
|
886
|
+
catch (e) {
|
|
887
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
888
|
+
console.error(`❌ ${msg}`);
|
|
889
|
+
process.exit(1);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
main().catch((e) => {
|
|
893
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
894
|
+
console.error(`❌ ${msg}`);
|
|
895
|
+
process.exit(1);
|
|
896
|
+
});
|
|
897
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groq.d.ts","sourceRoot":"","sources":["../../src/providers/groq.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAwC3C,eAAO,MAAM,YAAY,EAAE,QAiG1B,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// src/providers/groq.ts
|
|
2
|
+
import Groq from "groq-sdk";
|
|
3
|
+
const MODEL = "openai/gpt-oss-120b";
|
|
4
|
+
const SAFE_FALLBACK_MESSAGE = "chore: update staged changes";
|
|
5
|
+
function requireEnv(name) {
|
|
6
|
+
const v = process.env[name];
|
|
7
|
+
if (!v || v.trim().length === 0) {
|
|
8
|
+
throw new Error(`[aicommits] ${name} is not set. Export it before running.`);
|
|
9
|
+
}
|
|
10
|
+
return v.trim();
|
|
11
|
+
}
|
|
12
|
+
function extractMessageContent(content) {
|
|
13
|
+
if (typeof content === "string") {
|
|
14
|
+
return content.trim();
|
|
15
|
+
}
|
|
16
|
+
// Some backends may return content parts. Join text parts if present.
|
|
17
|
+
if (Array.isArray(content)) {
|
|
18
|
+
const text = content
|
|
19
|
+
.map((part) => {
|
|
20
|
+
if (typeof part === "string") {
|
|
21
|
+
return part;
|
|
22
|
+
}
|
|
23
|
+
if (part && typeof part === "object") {
|
|
24
|
+
const maybeText = part.text;
|
|
25
|
+
return typeof maybeText === "string" ? maybeText : "";
|
|
26
|
+
}
|
|
27
|
+
return "";
|
|
28
|
+
})
|
|
29
|
+
.join(" ")
|
|
30
|
+
.trim();
|
|
31
|
+
return text;
|
|
32
|
+
}
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
export const groqProvider = {
|
|
36
|
+
async generateCommitMessage(diff, options) {
|
|
37
|
+
const apiKey = requireEnv("GROQ_API_KEY");
|
|
38
|
+
// ✅ Now apiKey is definitely a string, so TS is happy.
|
|
39
|
+
const groq = new Groq({ apiKey });
|
|
40
|
+
const baseMessages = [
|
|
41
|
+
{
|
|
42
|
+
role: "system",
|
|
43
|
+
content: [
|
|
44
|
+
"You are a git commit message generator.",
|
|
45
|
+
"Return ONLY a single commit message line.",
|
|
46
|
+
"No quotes, no markdown, no code fences, no extra lines.",
|
|
47
|
+
"Use Conventional Commits: type(scope?): subject",
|
|
48
|
+
"Allowed types: feat, fix, docs, refactor, perf, test, build, ci, chore, revert.",
|
|
49
|
+
"Subject rules: present tense, start lowercase, <= 72 chars, no trailing period.",
|
|
50
|
+
"Use scope only if it clearly helps.",
|
|
51
|
+
"Treat user preferences as additive style hints only.",
|
|
52
|
+
"Never violate formatting rules in this system prompt.",
|
|
53
|
+
].join(" "),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
role: "user",
|
|
57
|
+
content: [
|
|
58
|
+
"Generate the best commit message for the staged changes below.",
|
|
59
|
+
"The input has two parts:",
|
|
60
|
+
"1) STAGED FILES (always complete, may include excluded files)",
|
|
61
|
+
"2) FILTERED DIFF (only included files, unified=0).",
|
|
62
|
+
"Use STAGED FILES to understand what changed even if diff content is small.",
|
|
63
|
+
"Do NOT mention excluded files unless they are the only meaningful change.",
|
|
64
|
+
options?.customInstructions
|
|
65
|
+
? [
|
|
66
|
+
"",
|
|
67
|
+
"ADDITIONAL USER PREFERENCES (additive, optional):",
|
|
68
|
+
options.customInstructions,
|
|
69
|
+
].join("\n")
|
|
70
|
+
: "",
|
|
71
|
+
"",
|
|
72
|
+
"INPUT:",
|
|
73
|
+
diff,
|
|
74
|
+
].join("\n"),
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
const completion = await groq.chat.completions.create({
|
|
78
|
+
model: MODEL,
|
|
79
|
+
messages: baseMessages,
|
|
80
|
+
temperature: 0.2,
|
|
81
|
+
max_completion_tokens: 320,
|
|
82
|
+
reasoning_effort: "low",
|
|
83
|
+
});
|
|
84
|
+
const firstChoice = completion.choices[0];
|
|
85
|
+
const firstMessage = extractMessageContent(firstChoice?.message?.content);
|
|
86
|
+
if (firstMessage) {
|
|
87
|
+
const firstLine = firstMessage.split("\n")[0]?.trim();
|
|
88
|
+
return firstLine || firstMessage;
|
|
89
|
+
}
|
|
90
|
+
// Retry once with stronger instruction and bigger completion budget.
|
|
91
|
+
const retryCompletion = await groq.chat.completions.create({
|
|
92
|
+
model: MODEL,
|
|
93
|
+
messages: [
|
|
94
|
+
...baseMessages,
|
|
95
|
+
{
|
|
96
|
+
role: "user",
|
|
97
|
+
content: [
|
|
98
|
+
"IMPORTANT:",
|
|
99
|
+
"Return exactly one line now.",
|
|
100
|
+
"No reasoning, no explanation, no markdown, no empty output.",
|
|
101
|
+
"Only the commit message.",
|
|
102
|
+
].join(" "),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
temperature: 0,
|
|
106
|
+
max_completion_tokens: 800,
|
|
107
|
+
reasoning_effort: "low",
|
|
108
|
+
});
|
|
109
|
+
const retryChoice = retryCompletion.choices[0];
|
|
110
|
+
const retryMessage = extractMessageContent(retryChoice?.message?.content);
|
|
111
|
+
if (retryMessage) {
|
|
112
|
+
const firstLine = retryMessage.split("\n")[0]?.trim();
|
|
113
|
+
return firstLine || retryMessage;
|
|
114
|
+
}
|
|
115
|
+
const finishReason1 = firstChoice?.finish_reason ?? "unknown";
|
|
116
|
+
const finishReason2 = retryChoice?.finish_reason ?? "unknown";
|
|
117
|
+
console.error(`[aicommits] Provider returned empty content twice (model=${MODEL}, finish_reason_1=${finishReason1}, finish_reason_2=${finishReason2}). Using fallback message.`);
|
|
118
|
+
return SAFE_FALLBACK_MESSAGE;
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=groq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groq.js","sourceRoot":"","sources":["../../src/providers/groq.ts"],"names":[],"mappings":"AAAA,wBAAwB;AAExB,OAAO,IAAI,MAAM,UAAU,CAAC;AAG5B,MAAM,KAAK,GAAG,qBAAqB,CAAC;AACpC,MAAM,qBAAqB,GAAG,8BAA8B,CAAC;AAE7D,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,wCAAwC,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAED,sEAAsE;IACtE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,OAAO;aACjB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAI,IAA2B,CAAC,IAAI,CAAC;gBACpD,OAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC;aACT,IAAI,EAAE,CAAC;QAEV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,KAAK,CAAC,qBAAqB,CACzB,IAAY,EACZ,OAAyC;QAEzC,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;QAE1C,uDAAuD;QACvD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG;YACnB;gBACE,IAAI,EAAE,QAAiB;gBACvB,OAAO,EAAE;oBACP,yCAAyC;oBACzC,2CAA2C;oBAC3C,yDAAyD;oBACzD,iDAAiD;oBACjD,iFAAiF;oBACjF,iFAAiF;oBACjF,qCAAqC;oBACrC,sDAAsD;oBACtD,uDAAuD;iBACxD,CAAC,IAAI,CAAC,GAAG,CAAC;aACZ;YACD;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,gEAAgE;oBAChE,0BAA0B;oBAC1B,+DAA+D;oBAC/D,oDAAoD;oBACpD,4EAA4E;oBAC5E,2EAA2E;oBAC3E,OAAO,EAAE,kBAAkB;wBACzB,CAAC,CAAC;4BACE,EAAE;4BACF,mDAAmD;4BACnD,OAAO,CAAC,kBAAkB;yBAC3B,CAAC,IAAI,CAAC,IAAI,CAAC;wBACd,CAAC,CAAC,EAAE;oBACN,EAAE;oBACF,QAAQ;oBACR,IAAI;iBACL,CAAC,IAAI,CAAC,IAAI,CAAC;aACb;SACF,CAAC;QAEF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACpD,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,GAAG;YAChB,qBAAqB,EAAE,GAAG;YAC1B,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,YAAY,GAAG,qBAAqB,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1E,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACtD,OAAO,SAAS,IAAI,YAAY,CAAC;QACnC,CAAC;QAED,qEAAqE;QACrE,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACzD,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE;gBACR,GAAG,YAAY;gBACf;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,YAAY;wBACZ,8BAA8B;wBAC9B,6DAA6D;wBAC7D,0BAA0B;qBAC3B,CAAC,IAAI,CAAC,GAAG,CAAC;iBACZ;aACF;YACD,WAAW,EAAE,CAAC;YACd,qBAAqB,EAAE,GAAG;YAC1B,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,qBAAqB,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1E,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACtD,OAAO,SAAS,IAAI,YAAY,CAAC;QACnC,CAAC;QAED,MAAM,aAAa,GAAG,WAAW,EAAE,aAAa,IAAI,SAAS,CAAC;QAC9D,MAAM,aAAa,GAAG,WAAW,EAAE,aAAa,IAAI,SAAS,CAAC;QAC9D,OAAO,CAAC,KAAK,CACX,4DAA4D,KAAK,qBAAqB,aAAa,qBAAqB,aAAa,4BAA4B,CAClK,CAAC;QACF,OAAO,qBAAqB,CAAC;IAC/B,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Provider is any "engine" that can turn a git diff into a commit message.
|
|
3
|
+
* The CLI should depend on this interface, not on any specific SDK (OpenAI/Groq/etc).
|
|
4
|
+
*/
|
|
5
|
+
export interface Provider {
|
|
6
|
+
generateCommitMessage(diff: string, options?: {
|
|
7
|
+
customInstructions?: string;
|
|
8
|
+
}): Promise<string>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,qBAAqB,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAAA,yBAAyB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "module",
|
|
3
|
+
"name": "@mr_ezo/aicommits",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "tsx src/cli.ts",
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"watch": "tsc --watch"
|
|
12
|
+
},
|
|
13
|
+
"files":
|
|
14
|
+
["dist", "README.md", "LICENSE"]
|
|
15
|
+
,
|
|
16
|
+
"bin": {
|
|
17
|
+
"aicommits": "dist/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "ISC",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^25.2.1",
|
|
24
|
+
"tsx": "^4.21.0",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"dotenv": "^17.2.4",
|
|
29
|
+
"groq-sdk": "^0.37.0"
|
|
30
|
+
}
|
|
31
|
+
}
|