@ksw8954/git-ai-commit 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -0
- package/dist/commands/git.d.ts.map +1 -1
- package/dist/commands/git.js +81 -11
- package/dist/commands/git.js.map +1 -1
- package/justfile +54 -0
- package/package.json +1 -1
- package/src/commands/git.ts +94 -11
package/AGENTS.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Repository Guidelines
|
|
2
2
|
|
|
3
|
+
## Local Search Tooling
|
|
4
|
+
- Use `rg` for local search; do not use `mgrep` in this repository.
|
|
5
|
+
|
|
3
6
|
## Project Structure & Module Organization
|
|
4
7
|
- `src/index.ts` bootstraps the CLI and wires subcommands.
|
|
5
8
|
- `src/commands/` houses command implementations; `src/prompts/` stores prompt templates.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"AA+EA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,UAAU;WACR,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;WA6BvC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;WA+BpE,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAU/C,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;WAUxB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAU1C,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;WAwBrC,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;WAmC5D,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAUtE,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAS5C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WASlD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAUjD,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAUlD,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAS7D"}
|
package/dist/commands/git.js
CHANGED
|
@@ -5,11 +5,74 @@ const child_process_1 = require("child_process");
|
|
|
5
5
|
const util_1 = require("util");
|
|
6
6
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
7
7
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
8
|
+
const GIT_DIFF_MAX_BUFFER = 50 * 1024 * 1024;
|
|
9
|
+
const MAX_DIFF_TOKENS = 50000;
|
|
10
|
+
const APPROX_CHARS_PER_TOKEN = 4;
|
|
11
|
+
const MAX_DIFF_CHARS = MAX_DIFF_TOKENS * APPROX_CHARS_PER_TOKEN;
|
|
12
|
+
const MAX_FILE_LINES = 400;
|
|
13
|
+
const MAX_NEW_FILE_LINES = 200;
|
|
14
|
+
const splitDiffSections = (diff) => {
|
|
15
|
+
const lines = diff.split('\n');
|
|
16
|
+
const sections = [];
|
|
17
|
+
let current = [];
|
|
18
|
+
for (const line of lines) {
|
|
19
|
+
if (line.startsWith('diff --git ')) {
|
|
20
|
+
if (current.length > 0) {
|
|
21
|
+
sections.push(current.join('\n'));
|
|
22
|
+
}
|
|
23
|
+
current = [line];
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
current.push(line);
|
|
27
|
+
}
|
|
28
|
+
if (current.length > 0) {
|
|
29
|
+
sections.push(current.join('\n'));
|
|
30
|
+
}
|
|
31
|
+
return sections.length > 0 ? sections : [diff];
|
|
32
|
+
};
|
|
33
|
+
const truncateSection = (section) => {
|
|
34
|
+
const lines = section.split('\n');
|
|
35
|
+
const isNewFile = section.includes('new file mode') || section.includes('--- /dev/null');
|
|
36
|
+
const limit = isNewFile ? MAX_NEW_FILE_LINES : MAX_FILE_LINES;
|
|
37
|
+
if (lines.length <= limit) {
|
|
38
|
+
return section;
|
|
39
|
+
}
|
|
40
|
+
const omitted = lines.length - limit;
|
|
41
|
+
const truncated = lines.slice(0, limit);
|
|
42
|
+
truncated.push(`... (truncated ${omitted} lines)`);
|
|
43
|
+
return truncated.join('\n');
|
|
44
|
+
};
|
|
45
|
+
const truncateDiffByFile = (diff) => {
|
|
46
|
+
const sections = splitDiffSections(diff);
|
|
47
|
+
return sections.map(truncateSection).join('\n');
|
|
48
|
+
};
|
|
49
|
+
const truncateDiffByTotal = (diff) => {
|
|
50
|
+
const lines = diff.split('\n');
|
|
51
|
+
let total = 0;
|
|
52
|
+
const kept = [];
|
|
53
|
+
for (const line of lines) {
|
|
54
|
+
const addition = line.length + 1;
|
|
55
|
+
if (total + addition > MAX_DIFF_CHARS) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
kept.push(line);
|
|
59
|
+
total += addition;
|
|
60
|
+
}
|
|
61
|
+
if (kept.length === lines.length) {
|
|
62
|
+
return diff;
|
|
63
|
+
}
|
|
64
|
+
kept.push(`... (truncated remaining diff to stay under ${MAX_DIFF_TOKENS} tokens)`);
|
|
65
|
+
return kept.join('\n');
|
|
66
|
+
};
|
|
67
|
+
const truncateDiff = (diff) => truncateDiffByTotal(truncateDiffByFile(diff));
|
|
8
68
|
class GitService {
|
|
9
69
|
static async getStagedDiff() {
|
|
10
70
|
try {
|
|
11
|
-
const { stdout } = await
|
|
12
|
-
|
|
71
|
+
const { stdout } = await execFileAsync('git', ['diff', '--staged'], {
|
|
72
|
+
maxBuffer: GIT_DIFF_MAX_BUFFER
|
|
73
|
+
});
|
|
74
|
+
const diff = truncateDiff(stdout);
|
|
75
|
+
if (!diff.trim()) {
|
|
13
76
|
return {
|
|
14
77
|
success: false,
|
|
15
78
|
error: 'No staged changes found. Please stage your changes first.'
|
|
@@ -17,21 +80,26 @@ class GitService {
|
|
|
17
80
|
}
|
|
18
81
|
return {
|
|
19
82
|
success: true,
|
|
20
|
-
diff
|
|
83
|
+
diff
|
|
21
84
|
};
|
|
22
85
|
}
|
|
23
86
|
catch (error) {
|
|
87
|
+
const message = error instanceof Error ? error.message : 'Failed to get git diff';
|
|
24
88
|
return {
|
|
25
89
|
success: false,
|
|
26
|
-
error:
|
|
90
|
+
error: message.includes('maxBuffer')
|
|
91
|
+
? 'Staged diff is too large to process. Try committing in smaller batches.'
|
|
92
|
+
: message
|
|
27
93
|
};
|
|
28
94
|
}
|
|
29
95
|
}
|
|
30
96
|
static async getBranchDiff(base, compare) {
|
|
31
97
|
try {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
98
|
+
const { stdout } = await execFileAsync('git', ['diff', `${base}...${compare}`], {
|
|
99
|
+
maxBuffer: GIT_DIFF_MAX_BUFFER
|
|
100
|
+
});
|
|
101
|
+
const diff = truncateDiff(stdout);
|
|
102
|
+
if (!diff.trim()) {
|
|
35
103
|
return {
|
|
36
104
|
success: false,
|
|
37
105
|
error: `No differences found between ${base} and ${compare}.`
|
|
@@ -39,16 +107,18 @@ class GitService {
|
|
|
39
107
|
}
|
|
40
108
|
return {
|
|
41
109
|
success: true,
|
|
42
|
-
diff
|
|
110
|
+
diff
|
|
43
111
|
};
|
|
44
112
|
}
|
|
45
113
|
catch (error) {
|
|
46
114
|
const message = error instanceof Error ? error.message : 'Failed to get branch diff';
|
|
47
115
|
return {
|
|
48
116
|
success: false,
|
|
49
|
-
error: message.includes('
|
|
50
|
-
?
|
|
51
|
-
: message
|
|
117
|
+
error: message.includes('maxBuffer')
|
|
118
|
+
? 'Diff is too large to process. Try narrowing the compare range.'
|
|
119
|
+
: message.includes('unknown revision')
|
|
120
|
+
? `Unable to resolve one of the branches: ${base} or ${compare}.`
|
|
121
|
+
: message
|
|
52
122
|
};
|
|
53
123
|
}
|
|
54
124
|
}
|
package/dist/commands/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAC/C,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAClC,MAAM,aAAa,GAAG,IAAA,gBAAS,EAAC,wBAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"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"}
|
package/justfile
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Install dependencies and build the project
|
|
2
|
+
LEVEL := "patch"
|
|
3
|
+
|
|
4
|
+
install:
|
|
5
|
+
npm install
|
|
6
|
+
npm run build
|
|
7
|
+
|
|
8
|
+
# Compile TypeScript sources
|
|
9
|
+
build:
|
|
10
|
+
npm run build
|
|
11
|
+
|
|
12
|
+
# Run the CLI via ts-node in dev mode
|
|
13
|
+
dev:
|
|
14
|
+
npm run dev -- commit
|
|
15
|
+
|
|
16
|
+
# Run ESLint
|
|
17
|
+
lint:
|
|
18
|
+
npm run lint
|
|
19
|
+
|
|
20
|
+
# Run Jest test suite
|
|
21
|
+
test:
|
|
22
|
+
npm run test
|
|
23
|
+
|
|
24
|
+
# Run TypeScript type checking
|
|
25
|
+
typecheck:
|
|
26
|
+
npm run typecheck
|
|
27
|
+
|
|
28
|
+
# Remove build and coverage artifacts
|
|
29
|
+
clean:
|
|
30
|
+
rm -rf dist coverage
|
|
31
|
+
|
|
32
|
+
# Remove installed dependencies and build outputs
|
|
33
|
+
uninstall:
|
|
34
|
+
rm -rf node_modules package-lock.json dist coverage
|
|
35
|
+
|
|
36
|
+
# Link the CLI globally
|
|
37
|
+
link:
|
|
38
|
+
npm link
|
|
39
|
+
|
|
40
|
+
# Unlink the globally installed CLI
|
|
41
|
+
unlink:
|
|
42
|
+
npm unlink -g git-ai-commit
|
|
43
|
+
|
|
44
|
+
# Bump package.json version one step (default: patch)
|
|
45
|
+
version:
|
|
46
|
+
npm version {{LEVEL}} --no-git-tag-version
|
|
47
|
+
|
|
48
|
+
# Publish the package to npm (ensure you're logged in)
|
|
49
|
+
publish: build
|
|
50
|
+
npm publish
|
|
51
|
+
|
|
52
|
+
# Install this package globally via npm
|
|
53
|
+
install-package:
|
|
54
|
+
npm i -g @ksw8954/git-ai-commit
|
package/package.json
CHANGED
package/src/commands/git.ts
CHANGED
|
@@ -3,6 +3,79 @@ import { promisify } from 'util';
|
|
|
3
3
|
|
|
4
4
|
const execAsync = promisify(exec);
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
|
+
const GIT_DIFF_MAX_BUFFER = 50 * 1024 * 1024;
|
|
7
|
+
const MAX_DIFF_TOKENS = 50000;
|
|
8
|
+
const APPROX_CHARS_PER_TOKEN = 4;
|
|
9
|
+
const MAX_DIFF_CHARS = MAX_DIFF_TOKENS * APPROX_CHARS_PER_TOKEN;
|
|
10
|
+
const MAX_FILE_LINES = 400;
|
|
11
|
+
const MAX_NEW_FILE_LINES = 200;
|
|
12
|
+
|
|
13
|
+
const splitDiffSections = (diff: string): string[] => {
|
|
14
|
+
const lines = diff.split('\n');
|
|
15
|
+
const sections: string[] = [];
|
|
16
|
+
let current: string[] = [];
|
|
17
|
+
|
|
18
|
+
for (const line of lines) {
|
|
19
|
+
if (line.startsWith('diff --git ')) {
|
|
20
|
+
if (current.length > 0) {
|
|
21
|
+
sections.push(current.join('\n'));
|
|
22
|
+
}
|
|
23
|
+
current = [line];
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
current.push(line);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (current.length > 0) {
|
|
30
|
+
sections.push(current.join('\n'));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return sections.length > 0 ? sections : [diff];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const truncateSection = (section: string): string => {
|
|
37
|
+
const lines = section.split('\n');
|
|
38
|
+
const isNewFile = section.includes('new file mode') || section.includes('--- /dev/null');
|
|
39
|
+
const limit = isNewFile ? MAX_NEW_FILE_LINES : MAX_FILE_LINES;
|
|
40
|
+
|
|
41
|
+
if (lines.length <= limit) {
|
|
42
|
+
return section;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const omitted = lines.length - limit;
|
|
46
|
+
const truncated = lines.slice(0, limit);
|
|
47
|
+
truncated.push(`... (truncated ${omitted} lines)`);
|
|
48
|
+
return truncated.join('\n');
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const truncateDiffByFile = (diff: string): string => {
|
|
52
|
+
const sections = splitDiffSections(diff);
|
|
53
|
+
return sections.map(truncateSection).join('\n');
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const truncateDiffByTotal = (diff: string): string => {
|
|
57
|
+
const lines = diff.split('\n');
|
|
58
|
+
let total = 0;
|
|
59
|
+
const kept: string[] = [];
|
|
60
|
+
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const addition = line.length + 1;
|
|
63
|
+
if (total + addition > MAX_DIFF_CHARS) {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
kept.push(line);
|
|
67
|
+
total += addition;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (kept.length === lines.length) {
|
|
71
|
+
return diff;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
kept.push(`... (truncated remaining diff to stay under ${MAX_DIFF_TOKENS} tokens)`);
|
|
75
|
+
return kept.join('\n');
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const truncateDiff = (diff: string): string => truncateDiffByTotal(truncateDiffByFile(diff));
|
|
6
79
|
|
|
7
80
|
export interface GitDiffResult {
|
|
8
81
|
success: boolean;
|
|
@@ -25,9 +98,12 @@ export interface GitLogResult {
|
|
|
25
98
|
export class GitService {
|
|
26
99
|
static async getStagedDiff(): Promise<GitDiffResult> {
|
|
27
100
|
try {
|
|
28
|
-
const { stdout } = await
|
|
101
|
+
const { stdout } = await execFileAsync('git', ['diff', '--staged'], {
|
|
102
|
+
maxBuffer: GIT_DIFF_MAX_BUFFER
|
|
103
|
+
});
|
|
104
|
+
const diff = truncateDiff(stdout);
|
|
29
105
|
|
|
30
|
-
if (!
|
|
106
|
+
if (!diff.trim()) {
|
|
31
107
|
return {
|
|
32
108
|
success: false,
|
|
33
109
|
error: 'No staged changes found. Please stage your changes first.'
|
|
@@ -36,22 +112,27 @@ export class GitService {
|
|
|
36
112
|
|
|
37
113
|
return {
|
|
38
114
|
success: true,
|
|
39
|
-
diff
|
|
115
|
+
diff
|
|
40
116
|
};
|
|
41
117
|
} catch (error) {
|
|
118
|
+
const message = error instanceof Error ? error.message : 'Failed to get git diff';
|
|
42
119
|
return {
|
|
43
120
|
success: false,
|
|
44
|
-
error:
|
|
121
|
+
error: message.includes('maxBuffer')
|
|
122
|
+
? 'Staged diff is too large to process. Try committing in smaller batches.'
|
|
123
|
+
: message
|
|
45
124
|
};
|
|
46
125
|
}
|
|
47
126
|
}
|
|
48
127
|
|
|
49
128
|
static async getBranchDiff(base: string, compare: string): Promise<GitDiffResult> {
|
|
50
129
|
try {
|
|
51
|
-
const
|
|
52
|
-
|
|
130
|
+
const { stdout } = await execFileAsync('git', ['diff', `${base}...${compare}`], {
|
|
131
|
+
maxBuffer: GIT_DIFF_MAX_BUFFER
|
|
132
|
+
});
|
|
133
|
+
const diff = truncateDiff(stdout);
|
|
53
134
|
|
|
54
|
-
if (!
|
|
135
|
+
if (!diff.trim()) {
|
|
55
136
|
return {
|
|
56
137
|
success: false,
|
|
57
138
|
error: `No differences found between ${base} and ${compare}.`
|
|
@@ -60,15 +141,17 @@ export class GitService {
|
|
|
60
141
|
|
|
61
142
|
return {
|
|
62
143
|
success: true,
|
|
63
|
-
diff
|
|
144
|
+
diff
|
|
64
145
|
};
|
|
65
146
|
} catch (error) {
|
|
66
147
|
const message = error instanceof Error ? error.message : 'Failed to get branch diff';
|
|
67
148
|
return {
|
|
68
149
|
success: false,
|
|
69
|
-
error: message.includes('
|
|
70
|
-
?
|
|
71
|
-
: message
|
|
150
|
+
error: message.includes('maxBuffer')
|
|
151
|
+
? 'Diff is too large to process. Try narrowing the compare range.'
|
|
152
|
+
: message.includes('unknown revision')
|
|
153
|
+
? `Unable to resolve one of the branches: ${base} or ${compare}.`
|
|
154
|
+
: message
|
|
72
155
|
};
|
|
73
156
|
}
|
|
74
157
|
}
|