@quikcommit/cli 11.0.0 → 12.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/index.js +214 -89
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -89,9 +89,14 @@ function slugifyFilename(path) {
|
|
|
89
89
|
const noExt = basename.replace(/\.[^.]+$/, "");
|
|
90
90
|
return noExt.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
91
91
|
}
|
|
92
|
+
function pickBestFile(files) {
|
|
93
|
+
const codeFiles = files.filter((f) => !NON_CODE_PATTERNS.some((rx) => rx.test(f)));
|
|
94
|
+
return codeFiles[0] ?? files[0] ?? "";
|
|
95
|
+
}
|
|
92
96
|
function deterministicBranchName(opts) {
|
|
93
97
|
const files = opts.files ?? [];
|
|
94
|
-
const
|
|
98
|
+
const codeFiles = files.filter((f) => !NON_CODE_PATTERNS.some((rx) => rx.test(f)));
|
|
99
|
+
const haystack = `${opts.description ?? ""} ${(codeFiles.length > 0 ? codeFiles : files).join(" ")}`;
|
|
95
100
|
let type = "chore";
|
|
96
101
|
for (const [rx, t] of TYPE_HINTS) {
|
|
97
102
|
if (rx.test(haystack)) {
|
|
@@ -103,7 +108,7 @@ function deterministicBranchName(opts) {
|
|
|
103
108
|
if (opts.description) {
|
|
104
109
|
slug = opts.description.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").split("-").slice(0, 5).join("-").slice(0, 40);
|
|
105
110
|
} else if (files.length > 0) {
|
|
106
|
-
slug = slugifyFilename(files
|
|
111
|
+
slug = slugifyFilename(pickBestFile(files));
|
|
107
112
|
} else {
|
|
108
113
|
slug = "changes";
|
|
109
114
|
}
|
|
@@ -117,7 +122,7 @@ function deterministicBranchName(opts) {
|
|
|
117
122
|
}
|
|
118
123
|
return { name, type, slug };
|
|
119
124
|
}
|
|
120
|
-
var BRANCH_NAME_RX, PROTECTED_BRANCH_RX, MAX_BRANCH_NAME_LENGTH, TYPE_HINTS;
|
|
125
|
+
var BRANCH_NAME_RX, PROTECTED_BRANCH_RX, MAX_BRANCH_NAME_LENGTH, TYPE_HINTS, NON_CODE_PATTERNS;
|
|
121
126
|
var init_branch = __esm({
|
|
122
127
|
"../shared/dist/branch.js"() {
|
|
123
128
|
"use strict";
|
|
@@ -133,6 +138,21 @@ var init_branch = __esm({
|
|
|
133
138
|
[/\bfix|bug|issue/i, "fix"],
|
|
134
139
|
[/\bfeat|add|new\b/i, "feat"]
|
|
135
140
|
];
|
|
141
|
+
NON_CODE_PATTERNS = [
|
|
142
|
+
/^docs?\//i,
|
|
143
|
+
/^\.env/,
|
|
144
|
+
/\.md$/i,
|
|
145
|
+
/^readme/i,
|
|
146
|
+
/^changelog/i,
|
|
147
|
+
/^license/i,
|
|
148
|
+
/\.lock$/,
|
|
149
|
+
/\.ya?ml$/,
|
|
150
|
+
/\.json$/,
|
|
151
|
+
/\.toml$/,
|
|
152
|
+
/\/\.?config\b/i,
|
|
153
|
+
/^\.github\//,
|
|
154
|
+
/^\.vscode\//
|
|
155
|
+
];
|
|
136
156
|
}
|
|
137
157
|
});
|
|
138
158
|
|
|
@@ -439,6 +459,13 @@ var init_api = __esm({
|
|
|
439
459
|
async generateBranchName(req) {
|
|
440
460
|
return this.request("/v1/branch", req);
|
|
441
461
|
}
|
|
462
|
+
async summarizeChunk(diff, changes, model) {
|
|
463
|
+
const data = await this.request(
|
|
464
|
+
"/v1/summarize",
|
|
465
|
+
{ diff, changes, ...model ? { model } : {} }
|
|
466
|
+
);
|
|
467
|
+
return data.summary ?? "";
|
|
468
|
+
}
|
|
442
469
|
async fetchJson(endpoint, options) {
|
|
443
470
|
if (!this.apiKey) {
|
|
444
471
|
throw new Error("Not authenticated. Run `qc login` first.");
|
|
@@ -7913,7 +7940,7 @@ function getStagedDiff(excludes = []) {
|
|
|
7913
7940
|
}
|
|
7914
7941
|
return (0, import_child_process2.execFileSync)("git", args, {
|
|
7915
7942
|
encoding: "utf-8",
|
|
7916
|
-
maxBuffer:
|
|
7943
|
+
maxBuffer: 50 * 1024 * 1024
|
|
7917
7944
|
});
|
|
7918
7945
|
}
|
|
7919
7946
|
function getStagedFiles() {
|
|
@@ -7975,8 +8002,18 @@ function gitCommit(message) {
|
|
|
7975
8002
|
}
|
|
7976
8003
|
}
|
|
7977
8004
|
function gitPush() {
|
|
8005
|
+
const branch = (0, import_child_process2.execFileSync)("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
8006
|
+
encoding: "utf-8"
|
|
8007
|
+
}).trim();
|
|
8008
|
+
let hasUpstream = false;
|
|
8009
|
+
try {
|
|
8010
|
+
(0, import_child_process2.execFileSync)("git", ["rev-parse", "--abbrev-ref", `${branch}@{upstream}`], { stdio: "pipe" });
|
|
8011
|
+
hasUpstream = true;
|
|
8012
|
+
} catch {
|
|
8013
|
+
}
|
|
8014
|
+
const args = hasUpstream ? ["push"] : ["push", "--set-upstream", "origin", branch];
|
|
7978
8015
|
try {
|
|
7979
|
-
(0, import_child_process2.execFileSync)("git",
|
|
8016
|
+
(0, import_child_process2.execFileSync)("git", args, { stdio: "pipe" });
|
|
7980
8017
|
} catch (err) {
|
|
7981
8018
|
const stderr = err?.stderr?.toString() ?? "";
|
|
7982
8019
|
if (stderr) process.stderr.write(stderr);
|
|
@@ -8091,19 +8128,36 @@ function getPushStats() {
|
|
|
8091
8128
|
const branch = (0, import_child_process2.execFileSync)("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
8092
8129
|
encoding: "utf-8"
|
|
8093
8130
|
}).trim();
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8131
|
+
let upstream = null;
|
|
8132
|
+
try {
|
|
8133
|
+
upstream = (0, import_child_process2.execFileSync)(
|
|
8134
|
+
"git",
|
|
8135
|
+
["rev-parse", "--abbrev-ref", `${branch}@{upstream}`],
|
|
8136
|
+
{ encoding: "utf-8", stdio: "pipe" }
|
|
8137
|
+
).trim();
|
|
8138
|
+
} catch {
|
|
8139
|
+
}
|
|
8140
|
+
if (upstream) {
|
|
8141
|
+
const countOutput = (0, import_child_process2.execFileSync)(
|
|
8142
|
+
"git",
|
|
8143
|
+
["rev-list", "--count", `${upstream}..HEAD`],
|
|
8144
|
+
{ encoding: "utf-8" }
|
|
8145
|
+
).trim();
|
|
8146
|
+
const parsedCount = parseInt(countOutput, 10);
|
|
8147
|
+
const commits = Number.isFinite(parsedCount) ? parsedCount : 0;
|
|
8148
|
+
const stat2 = (0, import_child_process2.execFileSync)(
|
|
8149
|
+
"git",
|
|
8150
|
+
["diff", "--shortstat", `${upstream}..HEAD`],
|
|
8151
|
+
{ encoding: "utf-8" }
|
|
8152
|
+
).trim();
|
|
8153
|
+
return { commits, stat: stat2 };
|
|
8154
|
+
}
|
|
8101
8155
|
const stat = (0, import_child_process2.execFileSync)(
|
|
8102
8156
|
"git",
|
|
8103
|
-
["diff", "--shortstat",
|
|
8157
|
+
["diff", "--shortstat", "HEAD~1..HEAD"],
|
|
8104
8158
|
{ encoding: "utf-8" }
|
|
8105
8159
|
).trim();
|
|
8106
|
-
return { commits, stat };
|
|
8160
|
+
return { commits: 1, stat };
|
|
8107
8161
|
} catch {
|
|
8108
8162
|
return null;
|
|
8109
8163
|
}
|
|
@@ -8747,7 +8801,8 @@ var smart_diff_exports = {};
|
|
|
8747
8801
|
__export(smart_diff_exports, {
|
|
8748
8802
|
classifyFile: () => classifyFile,
|
|
8749
8803
|
preprocessDiff: () => preprocessDiff,
|
|
8750
|
-
preprocessDiffWithSizeBudget: () => preprocessDiffWithSizeBudget
|
|
8804
|
+
preprocessDiffWithSizeBudget: () => preprocessDiffWithSizeBudget,
|
|
8805
|
+
splitDiffIntoChunks: () => splitDiffIntoChunks
|
|
8751
8806
|
});
|
|
8752
8807
|
function sanitizeFilepath(path) {
|
|
8753
8808
|
return path.replace(/[\x00-\x1F\x7F[\]`]/g, "_").slice(0, 200);
|
|
@@ -8788,7 +8843,7 @@ function isMinified(content) {
|
|
|
8788
8843
|
}
|
|
8789
8844
|
function preprocessDiff(diff) {
|
|
8790
8845
|
const files = parseDiffIntoFiles(diff);
|
|
8791
|
-
if (files.length === 0) return { processedDiff: diff, summarized: [],
|
|
8846
|
+
if (files.length === 0) return { processedDiff: diff, summarized: [], tokensSaved: 0, needsChunking: false };
|
|
8792
8847
|
const kept = [];
|
|
8793
8848
|
const summarized = [];
|
|
8794
8849
|
let tokensSaved = 0;
|
|
@@ -8833,19 +8888,50 @@ function preprocessDiff(diff) {
|
|
|
8833
8888
|
return {
|
|
8834
8889
|
processedDiff: kept.join(""),
|
|
8835
8890
|
summarized,
|
|
8836
|
-
|
|
8837
|
-
|
|
8891
|
+
tokensSaved,
|
|
8892
|
+
needsChunking: false
|
|
8838
8893
|
};
|
|
8839
8894
|
}
|
|
8840
|
-
function
|
|
8841
|
-
const
|
|
8842
|
-
|
|
8843
|
-
|
|
8895
|
+
function stripContext(fileContent, contextLines) {
|
|
8896
|
+
const lines = fileContent.split("\n");
|
|
8897
|
+
const result = [];
|
|
8898
|
+
let inHeader = true;
|
|
8899
|
+
const pendingContext = [];
|
|
8900
|
+
let afterChange = 0;
|
|
8901
|
+
for (const line of lines) {
|
|
8902
|
+
if (inHeader) {
|
|
8903
|
+
result.push(line);
|
|
8904
|
+
if (line.startsWith("@@")) inHeader = false;
|
|
8905
|
+
continue;
|
|
8906
|
+
}
|
|
8907
|
+
if (line.startsWith("@@")) {
|
|
8908
|
+
pendingContext.length = 0;
|
|
8909
|
+
afterChange = 0;
|
|
8910
|
+
result.push(line);
|
|
8911
|
+
continue;
|
|
8912
|
+
}
|
|
8913
|
+
if (line.startsWith("+") || line.startsWith("-")) {
|
|
8914
|
+
if (contextLines > 0) {
|
|
8915
|
+
result.push(...pendingContext.slice(-contextLines));
|
|
8916
|
+
}
|
|
8917
|
+
pendingContext.length = 0;
|
|
8918
|
+
result.push(line);
|
|
8919
|
+
afterChange = contextLines;
|
|
8920
|
+
continue;
|
|
8921
|
+
}
|
|
8922
|
+
if (afterChange > 0) {
|
|
8923
|
+
result.push(line);
|
|
8924
|
+
afterChange--;
|
|
8925
|
+
} else {
|
|
8926
|
+
pendingContext.push(line);
|
|
8927
|
+
}
|
|
8928
|
+
}
|
|
8929
|
+
return result.join("\n");
|
|
8844
8930
|
}
|
|
8845
|
-
function preprocessDiffWithSizeBudget(diff, maxBytes =
|
|
8931
|
+
function preprocessDiffWithSizeBudget(diff, maxBytes = 750 * 1024) {
|
|
8846
8932
|
const files = parseDiffIntoFiles(diff);
|
|
8847
8933
|
if (files.length === 0) {
|
|
8848
|
-
return { processedDiff: diff, summarized: [],
|
|
8934
|
+
return { processedDiff: diff, summarized: [], tokensSaved: 0, needsChunking: false };
|
|
8849
8935
|
}
|
|
8850
8936
|
const entries = [];
|
|
8851
8937
|
const summarized = [];
|
|
@@ -8856,7 +8942,7 @@ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
|
|
|
8856
8942
|
case "sourcemap":
|
|
8857
8943
|
tokensSaved += estimateTokens(file.content);
|
|
8858
8944
|
summarized.push(file.filepath);
|
|
8859
|
-
entries.push({ file, isNoise: true, summaryLine: null });
|
|
8945
|
+
entries.push({ file, isNoise: true, summaryLine: null, strippedContent: null });
|
|
8860
8946
|
break;
|
|
8861
8947
|
case "lock":
|
|
8862
8948
|
tokensSaved += estimateTokens(file.content);
|
|
@@ -8864,6 +8950,7 @@ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
|
|
|
8864
8950
|
entries.push({
|
|
8865
8951
|
file,
|
|
8866
8952
|
isNoise: true,
|
|
8953
|
+
strippedContent: null,
|
|
8867
8954
|
summaryLine: `[lock file updated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions} lines)]
|
|
8868
8955
|
`
|
|
8869
8956
|
});
|
|
@@ -8874,6 +8961,7 @@ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
|
|
|
8874
8961
|
entries.push({
|
|
8875
8962
|
file,
|
|
8876
8963
|
isNoise: true,
|
|
8964
|
+
strippedContent: null,
|
|
8877
8965
|
summaryLine: `[generated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions})]
|
|
8878
8966
|
`
|
|
8879
8967
|
});
|
|
@@ -8884,6 +8972,7 @@ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
|
|
|
8884
8972
|
entries.push({
|
|
8885
8973
|
file,
|
|
8886
8974
|
isNoise: true,
|
|
8975
|
+
strippedContent: null,
|
|
8887
8976
|
summaryLine: `[vendored: ${sanitizeFilepath(file.filepath)} updated]
|
|
8888
8977
|
`
|
|
8889
8978
|
});
|
|
@@ -8896,83 +8985,75 @@ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
|
|
|
8896
8985
|
entries.push({
|
|
8897
8986
|
file,
|
|
8898
8987
|
isNoise: true,
|
|
8988
|
+
strippedContent: null,
|
|
8899
8989
|
summaryLine: `[minified asset: ${sanitizeFilepath(file.filepath)} (${sizeKB} KB)]
|
|
8900
8990
|
`
|
|
8901
8991
|
});
|
|
8902
8992
|
} else {
|
|
8903
|
-
entries.push({ file, isNoise: false, summaryLine: null });
|
|
8993
|
+
entries.push({ file, isNoise: false, summaryLine: null, strippedContent: null });
|
|
8904
8994
|
}
|
|
8905
8995
|
break;
|
|
8906
8996
|
}
|
|
8907
8997
|
}
|
|
8908
|
-
const
|
|
8998
|
+
const codeEntries = entries.filter((e) => !e.isNoise);
|
|
8909
8999
|
function buildOutput() {
|
|
8910
9000
|
const parts = [];
|
|
8911
9001
|
for (const entry of entries) {
|
|
8912
9002
|
if (entry.isNoise) {
|
|
8913
9003
|
if (entry.summaryLine !== null) parts.push(entry.summaryLine);
|
|
8914
|
-
} else if (aggressiveMap.has(entry.file.filepath)) {
|
|
8915
|
-
parts.push(aggressiveMap.get(entry.file.filepath));
|
|
8916
9004
|
} else {
|
|
8917
|
-
parts.push(entry.file.content);
|
|
9005
|
+
parts.push(entry.strippedContent ?? entry.file.content);
|
|
8918
9006
|
}
|
|
8919
9007
|
}
|
|
8920
9008
|
return parts.join("");
|
|
8921
9009
|
}
|
|
8922
|
-
const codeEntries = entries.filter((e) => !e.isNoise);
|
|
8923
9010
|
let output = buildOutput();
|
|
8924
9011
|
if (output.length <= maxBytes) {
|
|
8925
|
-
return {
|
|
8926
|
-
processedDiff: output,
|
|
8927
|
-
summarized,
|
|
8928
|
-
aggressivelySummarized: [],
|
|
8929
|
-
tokensSaved
|
|
8930
|
-
};
|
|
9012
|
+
return { processedDiff: output, summarized, tokensSaved, needsChunking: false };
|
|
8931
9013
|
}
|
|
8932
|
-
const TIER1_THRESHOLD = 5 * 1024;
|
|
8933
9014
|
for (const entry of codeEntries) {
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
}
|
|
9015
|
+
const stripped = stripContext(entry.file.content, 1);
|
|
9016
|
+
tokensSaved += estimateTokens(entry.file.content) - estimateTokens(stripped);
|
|
9017
|
+
entry.strippedContent = stripped;
|
|
8938
9018
|
}
|
|
8939
9019
|
output = buildOutput();
|
|
8940
9020
|
if (output.length <= maxBytes) {
|
|
8941
|
-
return {
|
|
8942
|
-
processedDiff: output,
|
|
8943
|
-
summarized,
|
|
8944
|
-
aggressivelySummarized: [...aggressiveMap.keys()],
|
|
8945
|
-
tokensSaved
|
|
8946
|
-
};
|
|
9021
|
+
return { processedDiff: output, summarized, tokensSaved, needsChunking: false };
|
|
8947
9022
|
}
|
|
8948
|
-
const TIER2_THRESHOLD = 2 * 1024;
|
|
8949
9023
|
for (const entry of codeEntries) {
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
}
|
|
9024
|
+
const stripped = stripContext(entry.file.content, 0);
|
|
9025
|
+
tokensSaved += estimateTokens(entry.strippedContent ?? entry.file.content) - estimateTokens(stripped);
|
|
9026
|
+
entry.strippedContent = stripped;
|
|
8954
9027
|
}
|
|
8955
9028
|
output = buildOutput();
|
|
8956
9029
|
if (output.length <= maxBytes) {
|
|
8957
|
-
return {
|
|
8958
|
-
processedDiff: output,
|
|
8959
|
-
summarized,
|
|
8960
|
-
aggressivelySummarized: [...aggressiveMap.keys()],
|
|
8961
|
-
tokensSaved
|
|
8962
|
-
};
|
|
9030
|
+
return { processedDiff: output, summarized, tokensSaved, needsChunking: false };
|
|
8963
9031
|
}
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
9032
|
+
return { processedDiff: output, summarized, tokensSaved, needsChunking: true };
|
|
9033
|
+
}
|
|
9034
|
+
function splitDiffIntoChunks(diff, maxChunkBytes = 600 * 1024) {
|
|
9035
|
+
const files = parseDiffIntoFiles(diff);
|
|
9036
|
+
if (files.length === 0) return [];
|
|
9037
|
+
const chunks = [];
|
|
9038
|
+
let currentDiff = "";
|
|
9039
|
+
let currentFiles = [];
|
|
9040
|
+
for (const file of files) {
|
|
9041
|
+
let content = file.content;
|
|
9042
|
+
if (content.length > maxChunkBytes) {
|
|
9043
|
+
content = stripContext(content, 0);
|
|
9044
|
+
}
|
|
9045
|
+
if (currentDiff.length > 0 && currentDiff.length + content.length > maxChunkBytes) {
|
|
9046
|
+
chunks.push({ diff: currentDiff, files: currentFiles });
|
|
9047
|
+
currentDiff = "";
|
|
9048
|
+
currentFiles = [];
|
|
8968
9049
|
}
|
|
9050
|
+
currentDiff += content;
|
|
9051
|
+
currentFiles.push(file.filepath);
|
|
8969
9052
|
}
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
tokensSaved
|
|
8975
|
-
};
|
|
9053
|
+
if (currentDiff.length > 0) {
|
|
9054
|
+
chunks.push({ diff: currentDiff, files: currentFiles });
|
|
9055
|
+
}
|
|
9056
|
+
return chunks;
|
|
8976
9057
|
}
|
|
8977
9058
|
var LOCK_FILES, GENERATED_PATTERNS, VENDORED_PREFIXES;
|
|
8978
9059
|
var init_smart_diff = __esm({
|
|
@@ -10579,17 +10660,15 @@ async function runLocalCommit(args) {
|
|
|
10579
10660
|
let diff = getStagedDiff(excludes);
|
|
10580
10661
|
const changes = getStagedFiles();
|
|
10581
10662
|
if (!args.noSmartDiff) {
|
|
10582
|
-
const smartResult = preprocessDiffWithSizeBudget(diff
|
|
10663
|
+
const smartResult = preprocessDiffWithSizeBudget(diff);
|
|
10583
10664
|
diff = smartResult.processedDiff;
|
|
10584
10665
|
if (smartResult.summarized.length > 0 && !silent) {
|
|
10585
10666
|
log.step(
|
|
10586
10667
|
`smart-diff: ${smartResult.summarized.length} file(s) summarized (saved ~${Math.round(smartResult.tokensSaved / 1e3)}K tokens)`
|
|
10587
10668
|
);
|
|
10588
10669
|
}
|
|
10589
|
-
if (smartResult.
|
|
10590
|
-
log.step(
|
|
10591
|
-
`large-diff: ${smartResult.aggressivelySummarized.length} additional file(s) summarized to fit (commit message may be less specific)`
|
|
10592
|
-
);
|
|
10670
|
+
if (smartResult.needsChunking && !silent) {
|
|
10671
|
+
log.step("large diff detected \u2014 local providers receive context-stripped diff");
|
|
10593
10672
|
}
|
|
10594
10673
|
}
|
|
10595
10674
|
let rules = { ...await detectCommitlintRules(), ...config2.rules ?? {} };
|
|
@@ -11768,19 +11847,16 @@ async function runCommit(args) {
|
|
|
11768
11847
|
const diff = getStagedDiff(excludes);
|
|
11769
11848
|
const changes = getStagedFiles();
|
|
11770
11849
|
let processedDiff = diff;
|
|
11850
|
+
let needsChunking = false;
|
|
11771
11851
|
if (!args.noSmartDiff) {
|
|
11772
|
-
const smartResult = preprocessDiffWithSizeBudget(diff
|
|
11852
|
+
const smartResult = preprocessDiffWithSizeBudget(diff);
|
|
11773
11853
|
processedDiff = smartResult.processedDiff;
|
|
11854
|
+
needsChunking = smartResult.needsChunking;
|
|
11774
11855
|
if (smartResult.summarized.length > 0) {
|
|
11775
11856
|
log.step(
|
|
11776
11857
|
`smart-diff: ${smartResult.summarized.length} file(s) summarized (saved ~${Math.round(smartResult.tokensSaved / 1e3)}K tokens)`
|
|
11777
11858
|
);
|
|
11778
11859
|
}
|
|
11779
|
-
if (smartResult.aggressivelySummarized.length > 0) {
|
|
11780
|
-
log.step(
|
|
11781
|
-
`large-diff: ${smartResult.aggressivelySummarized.length} additional file(s) summarized to fit (commit message may be less specific \u2014 consider committing fewer files at a time)`
|
|
11782
|
-
);
|
|
11783
|
-
}
|
|
11784
11860
|
}
|
|
11785
11861
|
const commitlintRules = await detectCommitlintRules();
|
|
11786
11862
|
let rules = { ...commitlintRules, ...config2.rules ?? {} };
|
|
@@ -11818,7 +11894,7 @@ async function runCommit(args) {
|
|
|
11818
11894
|
const boxStyle = args.boxStyleOverride ?? config2.ui?.box?.style ?? "gradient";
|
|
11819
11895
|
const spinner = createStageSpinner({
|
|
11820
11896
|
stage: "aiGenerate",
|
|
11821
|
-
message: `generating commit (${modelDisplay})...`,
|
|
11897
|
+
message: needsChunking ? `analyzing ${changes.trim().split("\n").length} files in chunks (${modelDisplay})...` : `generating commit (${modelDisplay})...`,
|
|
11822
11898
|
...uiCtx
|
|
11823
11899
|
});
|
|
11824
11900
|
if (!silent) spinner.start();
|
|
@@ -11826,14 +11902,63 @@ async function runCommit(args) {
|
|
|
11826
11902
|
let generatedMessage;
|
|
11827
11903
|
let diagnostics;
|
|
11828
11904
|
try {
|
|
11829
|
-
({
|
|
11830
|
-
processedDiff
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
11836
|
-
|
|
11905
|
+
if (needsChunking) {
|
|
11906
|
+
const chunks = splitDiffIntoChunks(processedDiff);
|
|
11907
|
+
if (chunks.length === 0) {
|
|
11908
|
+
spinner.stop();
|
|
11909
|
+
log.error("No parseable diff content to analyze.");
|
|
11910
|
+
process.exit(1);
|
|
11911
|
+
}
|
|
11912
|
+
spinner.stop();
|
|
11913
|
+
if (!silent) log.step(`large diff \u2014 analyzing ${chunks.length} chunk(s) in parallel...`);
|
|
11914
|
+
const results = await Promise.allSettled(
|
|
11915
|
+
chunks.map(
|
|
11916
|
+
(chunk) => client.summarizeChunk(chunk.diff, chunk.files.filter(Boolean).join("\n") || "unknown", model)
|
|
11917
|
+
)
|
|
11918
|
+
);
|
|
11919
|
+
const summaries = [];
|
|
11920
|
+
for (const r of results) {
|
|
11921
|
+
if (r.status === "fulfilled" && r.value) {
|
|
11922
|
+
summaries.push(r.value);
|
|
11923
|
+
}
|
|
11924
|
+
}
|
|
11925
|
+
if (summaries.length === 0) {
|
|
11926
|
+
log.error("All chunk summaries failed. Check your connection and try again.");
|
|
11927
|
+
process.exit(1);
|
|
11928
|
+
}
|
|
11929
|
+
if (results.some((r) => r.status === "rejected") && !silent) {
|
|
11930
|
+
const failed = results.filter((r) => r.status === "rejected").length;
|
|
11931
|
+
log.step(`${failed}/${results.length} chunk(s) failed \u2014 continuing with partial summaries`);
|
|
11932
|
+
}
|
|
11933
|
+
const combinedSummary = summaries.join("\n\n");
|
|
11934
|
+
const finalSpinner = createStageSpinner({
|
|
11935
|
+
stage: "aiGenerate",
|
|
11936
|
+
message: `generating commit from ${chunks.length} summaries (${modelDisplay})...`,
|
|
11937
|
+
...uiCtx
|
|
11938
|
+
});
|
|
11939
|
+
if (!silent) finalSpinner.start();
|
|
11940
|
+
try {
|
|
11941
|
+
({ message: generatedMessage, diagnostics } = await client.generateCommit(
|
|
11942
|
+
combinedSummary,
|
|
11943
|
+
changes,
|
|
11944
|
+
rules,
|
|
11945
|
+
model,
|
|
11946
|
+
recentCommits,
|
|
11947
|
+
generationHints
|
|
11948
|
+
));
|
|
11949
|
+
} finally {
|
|
11950
|
+
finalSpinner.stop();
|
|
11951
|
+
}
|
|
11952
|
+
} else {
|
|
11953
|
+
({ message: generatedMessage, diagnostics } = await client.generateCommit(
|
|
11954
|
+
processedDiff,
|
|
11955
|
+
changes,
|
|
11956
|
+
rules,
|
|
11957
|
+
model,
|
|
11958
|
+
recentCommits,
|
|
11959
|
+
generationHints
|
|
11960
|
+
));
|
|
11961
|
+
}
|
|
11837
11962
|
} finally {
|
|
11838
11963
|
spinner.stop();
|
|
11839
11964
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quikcommit/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "AI-powered conventional commit messages",
|
|
5
5
|
"bin": {
|
|
6
6
|
"qc": "./dist/index.js"
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"esbuild": "^0.28.0",
|
|
35
35
|
"typescript": "^5.9.3",
|
|
36
36
|
"vitest": "^4.1.5",
|
|
37
|
-
"@quikcommit/shared": "
|
|
37
|
+
"@quikcommit/shared": "9.0.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "node build.mjs",
|