commitect 1.0.2 → 1.0.3
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/README.md +4 -4
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +6 -8
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/clear-cache.js +4 -4
- package/dist/commands/clear-cache.js.map +1 -1
- package/dist/commands/commit.js +8 -8
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/copy.js +7 -7
- package/dist/commands/copy.js.map +1 -1
- package/dist/commands/help.js +2 -2
- package/dist/commands/history.js +2 -2
- package/dist/commands/history.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +44 -10
- package/dist/services/llm.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/analyze.ts +6 -8
- package/src/commands/clear-cache.ts +4 -4
- package/src/commands/commit.ts +8 -8
- package/src/commands/copy.ts +7 -7
- package/src/commands/help.ts +2 -2
- package/src/commands/history.ts +2 -2
- package/src/index.ts +1 -1
- package/src/services/llm.ts +51 -11
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install
|
|
24
|
+
npm install commitect
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Usage
|
|
@@ -49,7 +49,7 @@ commitect copy
|
|
|
49
49
|
|
|
50
50
|
**Output:**
|
|
51
51
|
```
|
|
52
|
-
|
|
52
|
+
✓ Commit message copied to clipboard
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
### Auto-Commit
|
|
@@ -62,7 +62,7 @@ commitect commit
|
|
|
62
62
|
|
|
63
63
|
**Output:**
|
|
64
64
|
```
|
|
65
|
-
|
|
65
|
+
✓ Committed: Feature: Add user authentication with JWT tokens
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
### View History
|
|
@@ -100,7 +100,7 @@ commitect clear-cache
|
|
|
100
100
|
|
|
101
101
|
**Output:**
|
|
102
102
|
```
|
|
103
|
-
|
|
103
|
+
✓ Cache cleared (15 entries removed)
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
## How It Works
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAqCpD"}
|
package/dist/commands/analyze.js
CHANGED
|
@@ -5,34 +5,32 @@ export async function analyzeCommand() {
|
|
|
5
5
|
try {
|
|
6
6
|
// Validate git repository
|
|
7
7
|
if (!isGitRepository()) {
|
|
8
|
-
console.error(chalk.red('
|
|
8
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
9
9
|
process.exit(1);
|
|
10
10
|
}
|
|
11
11
|
// Check for changes
|
|
12
12
|
if (!hasChanges()) {
|
|
13
|
-
console.log(chalk.yellow('⚠
|
|
13
|
+
console.log(chalk.yellow('⚠ No changes detected'));
|
|
14
14
|
process.exit(0);
|
|
15
15
|
}
|
|
16
16
|
// Get diff
|
|
17
17
|
const diff = getGitDiff();
|
|
18
18
|
if (!diff.trim()) {
|
|
19
|
-
console.log(chalk.yellow('⚠
|
|
19
|
+
console.log(chalk.yellow('⚠ No changes to analyze'));
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
22
|
// Generate commit message
|
|
23
|
-
console.log(chalk.blue('
|
|
23
|
+
console.log(chalk.blue('🔎︎ Analyzing changes...'));
|
|
24
24
|
const suggestion = await generateCommitMessage(diff);
|
|
25
25
|
// Print result
|
|
26
|
-
console.log('');
|
|
27
26
|
console.log(chalk.green(`${suggestion.intent}: ${suggestion.message}`));
|
|
28
|
-
console.log('');
|
|
29
27
|
}
|
|
30
28
|
catch (error) {
|
|
31
29
|
if (error instanceof Error) {
|
|
32
|
-
console.error(chalk.red('
|
|
30
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
33
31
|
}
|
|
34
32
|
else {
|
|
35
|
-
console.error(chalk.red('
|
|
33
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
36
34
|
}
|
|
37
35
|
process.exit(1);
|
|
38
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,WAAW;QACX,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAErD,eAAe;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE1E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -4,18 +4,18 @@ export function clearCacheCommand() {
|
|
|
4
4
|
try {
|
|
5
5
|
const stats = commitCache.getStats();
|
|
6
6
|
if (stats.size === 0) {
|
|
7
|
-
console.log(chalk.yellow('ℹ
|
|
7
|
+
console.log(chalk.yellow('ℹ Cache is already empty'));
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
commitCache.clear();
|
|
11
|
-
console.log(chalk.green(
|
|
11
|
+
console.log(chalk.green(`✓ Cache cleared (${stats.size} entries removed)`));
|
|
12
12
|
}
|
|
13
13
|
catch (error) {
|
|
14
14
|
if (error instanceof Error) {
|
|
15
|
-
console.error(chalk.red('
|
|
15
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
18
|
-
console.error(chalk.red('
|
|
18
|
+
console.error(chalk.red('✗ Failed to clear cache'));
|
|
19
19
|
}
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clear-cache.js","sourceRoot":"","sources":["../../src/commands/clear-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC;QAErC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"clear-cache.js","sourceRoot":"","sources":["../../src/commands/clear-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC;QAErC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,KAAK,CAAC,IAAI,mBAAmB,CAAC,CAAC,CAAC;IAC/E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/commands/commit.js
CHANGED
|
@@ -5,36 +5,36 @@ export async function commitCommand() {
|
|
|
5
5
|
try {
|
|
6
6
|
// Validate git repository
|
|
7
7
|
if (!isGitRepository()) {
|
|
8
|
-
console.error(chalk.red('
|
|
8
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
9
9
|
process.exit(1);
|
|
10
10
|
}
|
|
11
11
|
// Check for changes
|
|
12
12
|
if (!hasChanges()) {
|
|
13
|
-
console.log(chalk.yellow('⚠
|
|
13
|
+
console.log(chalk.yellow('⚠ No changes to commit'));
|
|
14
14
|
process.exit(0);
|
|
15
15
|
}
|
|
16
16
|
// Get diff
|
|
17
17
|
const diff = getGitDiff();
|
|
18
18
|
if (!diff.trim()) {
|
|
19
|
-
console.log(chalk.yellow('⚠
|
|
19
|
+
console.log(chalk.yellow('⚠ No changes to commit'));
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
22
|
// Generate commit message
|
|
23
|
-
console.log(chalk.blue('
|
|
23
|
+
console.log(chalk.blue('🔎︎ Generating commit message...'));
|
|
24
24
|
const suggestion = await generateCommitMessage(diff);
|
|
25
25
|
// Build commit message as "intent: message"
|
|
26
26
|
const commitMessage = `${suggestion.intent}: ${suggestion.message}`;
|
|
27
27
|
// Execute git commit
|
|
28
|
-
console.log(chalk.blue('
|
|
28
|
+
console.log(chalk.blue('🖫 Committing changes...'));
|
|
29
29
|
executeCommit(commitMessage);
|
|
30
|
-
console.log(chalk.green('
|
|
30
|
+
console.log(chalk.green('✓ Committed: ') + commitMessage);
|
|
31
31
|
}
|
|
32
32
|
catch (error) {
|
|
33
33
|
if (error instanceof Error) {
|
|
34
|
-
console.error(chalk.red('
|
|
34
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
console.error(chalk.red('
|
|
37
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
38
38
|
}
|
|
39
39
|
process.exit(1);
|
|
40
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/commands/commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,WAAW;QACX,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAErD,4CAA4C;QAC5C,MAAM,aAAa,GAAG,GAAG,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QAEpE,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACrD,aAAa,CAAC,aAAa,CAAC,CAAC;QAE7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAC,CAAC;IAE7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/commands/copy.js
CHANGED
|
@@ -6,35 +6,35 @@ export async function copyCommand() {
|
|
|
6
6
|
try {
|
|
7
7
|
// Validate git repository
|
|
8
8
|
if (!isGitRepository()) {
|
|
9
|
-
console.error(chalk.red('
|
|
9
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
10
10
|
process.exit(1);
|
|
11
11
|
}
|
|
12
12
|
// Check for changes
|
|
13
13
|
if (!hasChanges()) {
|
|
14
|
-
console.log(chalk.yellow('⚠
|
|
14
|
+
console.log(chalk.yellow('⚠ No changes detected'));
|
|
15
15
|
process.exit(0);
|
|
16
16
|
}
|
|
17
17
|
// Get diff
|
|
18
18
|
const diff = getGitDiff();
|
|
19
19
|
if (!diff.trim()) {
|
|
20
|
-
console.log(chalk.yellow('⚠
|
|
20
|
+
console.log(chalk.yellow('⚠ No changes to analyze'));
|
|
21
21
|
process.exit(0);
|
|
22
22
|
}
|
|
23
23
|
// Generate commit message
|
|
24
|
-
console.log(chalk.blue('
|
|
24
|
+
console.log(chalk.blue('🔎︎ Generating commit message...'));
|
|
25
25
|
const suggestion = await generateCommitMessage(diff);
|
|
26
26
|
// Build commit message as "intent: message"
|
|
27
27
|
const commitMessage = `${suggestion.intent}: ${suggestion.message}`;
|
|
28
28
|
// Copy to clipboard
|
|
29
29
|
await clipboardy.write(commitMessage);
|
|
30
|
-
console.log(chalk.green('
|
|
30
|
+
console.log(chalk.green('✓ Commit message copied to clipboard'));
|
|
31
31
|
}
|
|
32
32
|
catch (error) {
|
|
33
33
|
if (error instanceof Error) {
|
|
34
|
-
console.error(chalk.red('
|
|
34
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
console.error(chalk.red('
|
|
37
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
38
38
|
}
|
|
39
39
|
process.exit(1);
|
|
40
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/commands/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/commands/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,WAAW;QACX,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAErD,4CAA4C;QAC5C,MAAM,aAAa,GAAG,GAAG,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QAEpE,oBAAoB;QACpB,MAAM,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAEtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAEpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/commands/help.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
const VERSION = '1.0.
|
|
3
|
-
const GITHUB_REPO = 'https://github.com/
|
|
2
|
+
const VERSION = '1.0.3';
|
|
3
|
+
const GITHUB_REPO = 'https://github.com/Mohammed-3tef/CommiTect_CLI';
|
|
4
4
|
const ISSUES_URL = GITHUB_REPO + '/issues';
|
|
5
5
|
export function helpCommand() {
|
|
6
6
|
console.log('');
|
package/dist/commands/history.js
CHANGED
|
@@ -27,10 +27,10 @@ export function historyCommand() {
|
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
29
|
if (error instanceof Error) {
|
|
30
|
-
console.error(chalk.red('
|
|
30
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
|
-
console.error(chalk.red('
|
|
33
|
+
console.error(chalk.red('✗ Failed to load history'));
|
|
34
34
|
}
|
|
35
35
|
process.exit(1);
|
|
36
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;QAEzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC/B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAE5C,+CAA+C;YAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACzG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,cAAc,EAAE,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,MAAM,yBAAyB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5G,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAElB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/services/llm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/services/llm.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsFnF"}
|
package/dist/services/llm.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
+
import crypto from 'crypto';
|
|
2
3
|
import { commitCache } from '../utils/cache.js';
|
|
3
4
|
const API_ENDPOINT = 'http://commitintentdetector.runasp.net/api/Commit/analyze';
|
|
4
5
|
export async function generateCommitMessage(diff) {
|
|
6
|
+
const diffHash = crypto.createHash('sha1').update(diff).digest('hex');
|
|
5
7
|
// Check cache first
|
|
6
|
-
const cached = commitCache.get(
|
|
8
|
+
const cached = commitCache.get(diffHash);
|
|
7
9
|
if (cached) {
|
|
8
10
|
return cached;
|
|
9
11
|
}
|
|
@@ -15,7 +17,7 @@ export async function generateCommitMessage(diff) {
|
|
|
15
17
|
headers: {
|
|
16
18
|
'Content-Type': 'application/json'
|
|
17
19
|
},
|
|
18
|
-
timeout:
|
|
20
|
+
timeout: 10000
|
|
19
21
|
});
|
|
20
22
|
// API returns: { intent: "Intent: Feature\nMessage: Add subtraction support function" }
|
|
21
23
|
const data = response.data;
|
|
@@ -24,7 +26,7 @@ export async function generateCommitMessage(diff) {
|
|
|
24
26
|
}
|
|
25
27
|
const result = parseResponse(data.intent);
|
|
26
28
|
// Cache the result
|
|
27
|
-
commitCache.set(
|
|
29
|
+
commitCache.set(diffHash, result.intent, result.message);
|
|
28
30
|
return result;
|
|
29
31
|
}
|
|
30
32
|
catch (error) {
|
|
@@ -34,25 +36,24 @@ export async function generateCommitMessage(diff) {
|
|
|
34
36
|
// Handle rate limiting (429)
|
|
35
37
|
if (axiosError.response?.status === 429) {
|
|
36
38
|
if (attempt < maxRetries) {
|
|
37
|
-
await sleep(
|
|
39
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
38
40
|
continue;
|
|
39
41
|
}
|
|
40
|
-
|
|
42
|
+
break;
|
|
41
43
|
}
|
|
42
44
|
// Handle server errors (5xx) - retry
|
|
43
45
|
if (axiosError.response?.status && axiosError.response.status >= 500) {
|
|
44
46
|
if (attempt < maxRetries) {
|
|
45
|
-
await sleep(
|
|
47
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
46
48
|
continue;
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
// Handle network errors - retry
|
|
50
52
|
if (axiosError.code === 'ECONNREFUSED' || axiosError.code === 'ETIMEDOUT') {
|
|
51
53
|
if (attempt < maxRetries) {
|
|
52
|
-
await sleep(
|
|
54
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
53
55
|
continue;
|
|
54
56
|
}
|
|
55
|
-
throw new Error('Unable to connect to API. Please check your network connection.');
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
// Don't retry on client errors (4xx) except 429
|
|
@@ -61,12 +62,13 @@ export async function generateCommitMessage(diff) {
|
|
|
61
62
|
}
|
|
62
63
|
// Retry on other errors
|
|
63
64
|
if (attempt < maxRetries) {
|
|
64
|
-
await sleep(
|
|
65
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
65
66
|
continue;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
+
console.warn('⚠ AI service unavailable, using fallback commit message.');
|
|
71
|
+
return generateFallbackCommit(diff);
|
|
70
72
|
}
|
|
71
73
|
function parseResponse(response) {
|
|
72
74
|
const lines = response.trim().split('\n');
|
|
@@ -88,6 +90,38 @@ function parseResponse(response) {
|
|
|
88
90
|
}
|
|
89
91
|
return { intent, message };
|
|
90
92
|
}
|
|
93
|
+
function generateFallbackCommit(diff) {
|
|
94
|
+
const diffHash = crypto.createHash('sha1').update(diff).digest('hex');
|
|
95
|
+
const lowerDiff = diff.toLowerCase();
|
|
96
|
+
let intent;
|
|
97
|
+
let message;
|
|
98
|
+
if (/(fix|bug|error|issue|crash|fault)/i.test(lowerDiff)) {
|
|
99
|
+
intent = 'Bug Fix';
|
|
100
|
+
message = 'fix reported issue';
|
|
101
|
+
}
|
|
102
|
+
else if (/(add|create|implement|introduce|new)/i.test(lowerDiff)) {
|
|
103
|
+
intent = 'Feature';
|
|
104
|
+
message = 'add new functionality';
|
|
105
|
+
}
|
|
106
|
+
else if (/(refactor|cleanup|restructure|optimize)/i.test(lowerDiff)) {
|
|
107
|
+
intent = 'Refactor';
|
|
108
|
+
message = 'refactor code structure';
|
|
109
|
+
}
|
|
110
|
+
else if (/(doc|readme|comment)/i.test(lowerDiff)) {
|
|
111
|
+
intent = 'Docs';
|
|
112
|
+
message = 'update documentation';
|
|
113
|
+
}
|
|
114
|
+
else if (/(test|spec|coverage)/i.test(lowerDiff)) {
|
|
115
|
+
intent = 'Test';
|
|
116
|
+
message = 'update tests';
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
intent = 'Chore';
|
|
120
|
+
message = 'update project files';
|
|
121
|
+
}
|
|
122
|
+
commitCache.set(diffHash, intent, message);
|
|
123
|
+
return { intent, message };
|
|
124
|
+
}
|
|
91
125
|
function sleep(ms) {
|
|
92
126
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
93
127
|
}
|
package/dist/services/llm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/services/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,MAAM,YAAY,GAAG,2DAA2D,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,oBAAoB;IACpB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/services/llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,MAAM,YAAY,GAAG,2DAA2D,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtE,oBAAoB;IACpB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAC;IACrB,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,YAAY,EACZ,EAAE,IAAI,EAAE,EACR;gBACE,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,OAAO,EAAE,KAAK;aACf,CACF,CAAC;YAEF,wFAAwF;YACxF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YAE3B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAE1C,mBAAmB;YACnB,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAEzD,OAAO,MAAM,CAAC;QAEhB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAc,CAAC;YAE3B,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,KAAmB,CAAC;gBAEvC,6BAA6B;gBAC7B,IAAI,UAAU,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;oBACxC,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;wBACzB,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;wBACxC,SAAS;oBACX,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,qCAAqC;gBACrC,IAAI,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBACrE,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;wBACzB,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;wBACxC,SAAS;oBACX,CAAC;gBACH,CAAC;gBAED,gCAAgC;gBAChC,IAAI,UAAU,CAAC,IAAI,KAAK,cAAc,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAC1E,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;wBACzB,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;wBACxC,SAAS;oBACX,CAAC;gBACH,CAAC;YACH,CAAC;YAED,gDAAgD;YAChD,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACxH,MAAM;YACR,CAAC;YAED,wBAAwB;YACxB,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBACzB,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;gBACxC,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC1E,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE1C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACxB,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;IAC7C,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAErC,IAAI,MAAkC,CAAC;IACvC,IAAI,OAAe,CAAC;IAEpB,IAAI,oCAAoC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,MAAM,GAAG,SAAS,CAAC;QACnB,OAAO,GAAG,oBAAoB,CAAC;IACjC,CAAC;SACI,IAAI,uCAAuC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,MAAM,GAAG,SAAS,CAAC;QACnB,OAAO,GAAG,uBAAuB,CAAC;IACpC,CAAC;SACI,IAAI,0CAA0C,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,MAAM,GAAG,UAAU,CAAC;QACpB,OAAO,GAAG,yBAAyB,CAAC;IACtC,CAAC;SACI,IAAI,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,MAAM,GAAG,MAAM,CAAC;QAChB,OAAO,GAAG,sBAAsB,CAAC;IACnC,CAAC;SACI,IAAI,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,MAAM,GAAG,MAAM,CAAC;QAChB,OAAO,GAAG,cAAc,CAAC;IAC3B,CAAC;SACI,CAAC;QACJ,MAAM,GAAG,OAAO,CAAC;QACjB,OAAO,GAAG,sBAAsB,CAAC;IACnC,CAAC;IAED,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC"}
|
package/package.json
CHANGED
package/src/commands/analyze.ts
CHANGED
|
@@ -6,13 +6,13 @@ export async function analyzeCommand(): Promise<void> {
|
|
|
6
6
|
try {
|
|
7
7
|
// Validate git repository
|
|
8
8
|
if (!isGitRepository()) {
|
|
9
|
-
console.error(chalk.red('
|
|
9
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
10
10
|
process.exit(1);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// Check for changes
|
|
14
14
|
if (!hasChanges()) {
|
|
15
|
-
console.log(chalk.yellow('⚠
|
|
15
|
+
console.log(chalk.yellow('⚠ No changes detected'));
|
|
16
16
|
process.exit(0);
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -20,24 +20,22 @@ export async function analyzeCommand(): Promise<void> {
|
|
|
20
20
|
const diff = getGitDiff();
|
|
21
21
|
|
|
22
22
|
if (!diff.trim()) {
|
|
23
|
-
console.log(chalk.yellow('⚠
|
|
23
|
+
console.log(chalk.yellow('⚠ No changes to analyze'));
|
|
24
24
|
process.exit(0);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Generate commit message
|
|
28
|
-
console.log(chalk.blue('
|
|
28
|
+
console.log(chalk.blue('🔎︎ Analyzing changes...'));
|
|
29
29
|
const suggestion = await generateCommitMessage(diff);
|
|
30
30
|
|
|
31
31
|
// Print result
|
|
32
|
-
console.log('');
|
|
33
32
|
console.log(chalk.green(`${suggestion.intent}: ${suggestion.message}`));
|
|
34
|
-
console.log('');
|
|
35
33
|
|
|
36
34
|
} catch (error) {
|
|
37
35
|
if (error instanceof Error) {
|
|
38
|
-
console.error(chalk.red('
|
|
36
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
39
37
|
} else {
|
|
40
|
-
console.error(chalk.red('
|
|
38
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
41
39
|
}
|
|
42
40
|
process.exit(1);
|
|
43
41
|
}
|
|
@@ -6,17 +6,17 @@ export function clearCacheCommand(): void {
|
|
|
6
6
|
const stats = commitCache.getStats();
|
|
7
7
|
|
|
8
8
|
if (stats.size === 0) {
|
|
9
|
-
console.log(chalk.yellow('ℹ
|
|
9
|
+
console.log(chalk.yellow('ℹ Cache is already empty'));
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
commitCache.clear();
|
|
14
|
-
console.log(chalk.green(
|
|
14
|
+
console.log(chalk.green(`✓ Cache cleared (${stats.size} entries removed)`));
|
|
15
15
|
} catch (error) {
|
|
16
16
|
if (error instanceof Error) {
|
|
17
|
-
console.error(chalk.red('
|
|
17
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
18
18
|
} else {
|
|
19
|
-
console.error(chalk.red('
|
|
19
|
+
console.error(chalk.red('✗ Failed to clear cache'));
|
|
20
20
|
}
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
package/src/commands/commit.ts
CHANGED
|
@@ -6,13 +6,13 @@ export async function commitCommand(): Promise<void> {
|
|
|
6
6
|
try {
|
|
7
7
|
// Validate git repository
|
|
8
8
|
if (!isGitRepository()) {
|
|
9
|
-
console.error(chalk.red('
|
|
9
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
10
10
|
process.exit(1);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// Check for changes
|
|
14
14
|
if (!hasChanges()) {
|
|
15
|
-
console.log(chalk.yellow('⚠
|
|
15
|
+
console.log(chalk.yellow('⚠ No changes to commit'));
|
|
16
16
|
process.exit(0);
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -20,28 +20,28 @@ export async function commitCommand(): Promise<void> {
|
|
|
20
20
|
const diff = getGitDiff();
|
|
21
21
|
|
|
22
22
|
if (!diff.trim()) {
|
|
23
|
-
console.log(chalk.yellow('⚠
|
|
23
|
+
console.log(chalk.yellow('⚠ No changes to commit'));
|
|
24
24
|
process.exit(0);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Generate commit message
|
|
28
|
-
console.log(chalk.blue('
|
|
28
|
+
console.log(chalk.blue('🔎︎ Generating commit message...'));
|
|
29
29
|
const suggestion = await generateCommitMessage(diff);
|
|
30
30
|
|
|
31
31
|
// Build commit message as "intent: message"
|
|
32
32
|
const commitMessage = `${suggestion.intent}: ${suggestion.message}`;
|
|
33
33
|
|
|
34
34
|
// Execute git commit
|
|
35
|
-
console.log(chalk.blue('
|
|
35
|
+
console.log(chalk.blue('🖫 Committing changes...'));
|
|
36
36
|
executeCommit(commitMessage);
|
|
37
37
|
|
|
38
|
-
console.log(chalk.green('
|
|
38
|
+
console.log(chalk.green('✓ Committed: ') + commitMessage);
|
|
39
39
|
|
|
40
40
|
} catch (error) {
|
|
41
41
|
if (error instanceof Error) {
|
|
42
|
-
console.error(chalk.red('
|
|
42
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
43
43
|
} else {
|
|
44
|
-
console.error(chalk.red('
|
|
44
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
45
45
|
}
|
|
46
46
|
process.exit(1);
|
|
47
47
|
}
|
package/src/commands/copy.ts
CHANGED
|
@@ -7,13 +7,13 @@ export async function copyCommand(): Promise<void> {
|
|
|
7
7
|
try {
|
|
8
8
|
// Validate git repository
|
|
9
9
|
if (!isGitRepository()) {
|
|
10
|
-
console.error(chalk.red('
|
|
10
|
+
console.error(chalk.red('✗ Not a git repository'));
|
|
11
11
|
process.exit(1);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// Check for changes
|
|
15
15
|
if (!hasChanges()) {
|
|
16
|
-
console.log(chalk.yellow('⚠
|
|
16
|
+
console.log(chalk.yellow('⚠ No changes detected'));
|
|
17
17
|
process.exit(0);
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -21,12 +21,12 @@ export async function copyCommand(): Promise<void> {
|
|
|
21
21
|
const diff = getGitDiff();
|
|
22
22
|
|
|
23
23
|
if (!diff.trim()) {
|
|
24
|
-
console.log(chalk.yellow('⚠
|
|
24
|
+
console.log(chalk.yellow('⚠ No changes to analyze'));
|
|
25
25
|
process.exit(0);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Generate commit message
|
|
29
|
-
console.log(chalk.blue('
|
|
29
|
+
console.log(chalk.blue('🔎︎ Generating commit message...'));
|
|
30
30
|
const suggestion = await generateCommitMessage(diff);
|
|
31
31
|
|
|
32
32
|
// Build commit message as "intent: message"
|
|
@@ -35,13 +35,13 @@ export async function copyCommand(): Promise<void> {
|
|
|
35
35
|
// Copy to clipboard
|
|
36
36
|
await clipboardy.write(commitMessage);
|
|
37
37
|
|
|
38
|
-
console.log(chalk.green('
|
|
38
|
+
console.log(chalk.green('✓ Commit message copied to clipboard'));
|
|
39
39
|
|
|
40
40
|
} catch (error) {
|
|
41
41
|
if (error instanceof Error) {
|
|
42
|
-
console.error(chalk.red('
|
|
42
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
43
43
|
} else {
|
|
44
|
-
console.error(chalk.red('
|
|
44
|
+
console.error(chalk.red('✗ An unexpected error occurred'));
|
|
45
45
|
}
|
|
46
46
|
process.exit(1);
|
|
47
47
|
}
|
package/src/commands/help.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
|
|
3
|
-
const VERSION = '1.0.
|
|
4
|
-
const GITHUB_REPO = 'https://github.com/
|
|
3
|
+
const VERSION = '1.0.3';
|
|
4
|
+
const GITHUB_REPO = 'https://github.com/Mohammed-3tef/CommiTect_CLI';
|
|
5
5
|
const ISSUES_URL = GITHUB_REPO + '/issues';
|
|
6
6
|
|
|
7
7
|
export function helpCommand(): void {
|
package/src/commands/history.ts
CHANGED
|
@@ -33,9 +33,9 @@ export function historyCommand(): void {
|
|
|
33
33
|
|
|
34
34
|
} catch (error) {
|
|
35
35
|
if (error instanceof Error) {
|
|
36
|
-
console.error(chalk.red('
|
|
36
|
+
console.error(chalk.red('✗ ' + error.message));
|
|
37
37
|
} else {
|
|
38
|
-
console.error(chalk.red('
|
|
38
|
+
console.error(chalk.red('✗ Failed to load history'));
|
|
39
39
|
}
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
package/src/index.ts
CHANGED
package/src/services/llm.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import axios, { AxiosError } from 'axios';
|
|
2
|
+
import crypto from 'crypto';
|
|
2
3
|
import { commitCache } from '../utils/cache.js';
|
|
3
4
|
|
|
4
5
|
export interface CommitSuggestion {
|
|
@@ -9,11 +10,14 @@ export interface CommitSuggestion {
|
|
|
9
10
|
const API_ENDPOINT = 'http://commitintentdetector.runasp.net/api/Commit/analyze';
|
|
10
11
|
|
|
11
12
|
export async function generateCommitMessage(diff: string): Promise<CommitSuggestion> {
|
|
13
|
+
const diffHash = crypto.createHash('sha1').update(diff).digest('hex');
|
|
14
|
+
|
|
12
15
|
// Check cache first
|
|
13
|
-
const cached = commitCache.get(
|
|
16
|
+
const cached = commitCache.get(diffHash);
|
|
14
17
|
if (cached) {
|
|
15
18
|
return cached;
|
|
16
19
|
}
|
|
20
|
+
|
|
17
21
|
const maxRetries = 3;
|
|
18
22
|
let lastError: Error | null = null;
|
|
19
23
|
|
|
@@ -26,7 +30,7 @@ export async function generateCommitMessage(diff: string): Promise<CommitSuggest
|
|
|
26
30
|
headers: {
|
|
27
31
|
'Content-Type': 'application/json'
|
|
28
32
|
},
|
|
29
|
-
timeout:
|
|
33
|
+
timeout: 10000
|
|
30
34
|
}
|
|
31
35
|
);
|
|
32
36
|
|
|
@@ -40,7 +44,7 @@ export async function generateCommitMessage(diff: string): Promise<CommitSuggest
|
|
|
40
44
|
const result = parseResponse(data.intent);
|
|
41
45
|
|
|
42
46
|
// Cache the result
|
|
43
|
-
commitCache.set(
|
|
47
|
+
commitCache.set(diffHash, result.intent, result.message);
|
|
44
48
|
|
|
45
49
|
return result;
|
|
46
50
|
|
|
@@ -53,16 +57,16 @@ export async function generateCommitMessage(diff: string): Promise<CommitSuggest
|
|
|
53
57
|
// Handle rate limiting (429)
|
|
54
58
|
if (axiosError.response?.status === 429) {
|
|
55
59
|
if (attempt < maxRetries) {
|
|
56
|
-
await sleep(
|
|
60
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
57
61
|
continue;
|
|
58
62
|
}
|
|
59
|
-
|
|
63
|
+
break;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
// Handle server errors (5xx) - retry
|
|
63
67
|
if (axiosError.response?.status && axiosError.response.status >= 500) {
|
|
64
68
|
if (attempt < maxRetries) {
|
|
65
|
-
await sleep(
|
|
69
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
66
70
|
continue;
|
|
67
71
|
}
|
|
68
72
|
}
|
|
@@ -70,10 +74,9 @@ export async function generateCommitMessage(diff: string): Promise<CommitSuggest
|
|
|
70
74
|
// Handle network errors - retry
|
|
71
75
|
if (axiosError.code === 'ECONNREFUSED' || axiosError.code === 'ETIMEDOUT') {
|
|
72
76
|
if (attempt < maxRetries) {
|
|
73
|
-
await sleep(
|
|
77
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
74
78
|
continue;
|
|
75
79
|
}
|
|
76
|
-
throw new Error('Unable to connect to API. Please check your network connection.');
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
82
|
|
|
@@ -84,13 +87,14 @@ export async function generateCommitMessage(diff: string): Promise<CommitSuggest
|
|
|
84
87
|
|
|
85
88
|
// Retry on other errors
|
|
86
89
|
if (attempt < maxRetries) {
|
|
87
|
-
await sleep(
|
|
90
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
88
91
|
continue;
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
console.warn('⚠ AI service unavailable, using fallback commit message.');
|
|
97
|
+
return generateFallbackCommit(diff);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
function parseResponse(response: string): CommitSuggestion {
|
|
@@ -118,6 +122,42 @@ function parseResponse(response: string): CommitSuggestion {
|
|
|
118
122
|
return { intent, message };
|
|
119
123
|
}
|
|
120
124
|
|
|
125
|
+
function generateFallbackCommit(diff: string): CommitSuggestion {
|
|
126
|
+
const diffHash = crypto.createHash('sha1').update(diff).digest('hex');
|
|
127
|
+
const lowerDiff = diff.toLowerCase();
|
|
128
|
+
|
|
129
|
+
let intent: CommitSuggestion['intent'];
|
|
130
|
+
let message: string;
|
|
131
|
+
|
|
132
|
+
if (/(fix|bug|error|issue|crash|fault)/i.test(lowerDiff)) {
|
|
133
|
+
intent = 'Bug Fix';
|
|
134
|
+
message = 'fix reported issue';
|
|
135
|
+
}
|
|
136
|
+
else if (/(add|create|implement|introduce|new)/i.test(lowerDiff)) {
|
|
137
|
+
intent = 'Feature';
|
|
138
|
+
message = 'add new functionality';
|
|
139
|
+
}
|
|
140
|
+
else if (/(refactor|cleanup|restructure|optimize)/i.test(lowerDiff)) {
|
|
141
|
+
intent = 'Refactor';
|
|
142
|
+
message = 'refactor code structure';
|
|
143
|
+
}
|
|
144
|
+
else if (/(doc|readme|comment)/i.test(lowerDiff)) {
|
|
145
|
+
intent = 'Docs';
|
|
146
|
+
message = 'update documentation';
|
|
147
|
+
}
|
|
148
|
+
else if (/(test|spec|coverage)/i.test(lowerDiff)) {
|
|
149
|
+
intent = 'Test';
|
|
150
|
+
message = 'update tests';
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
intent = 'Chore';
|
|
154
|
+
message = 'update project files';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
commitCache.set(diffHash, intent, message);
|
|
158
|
+
return { intent, message };
|
|
159
|
+
}
|
|
160
|
+
|
|
121
161
|
function sleep(ms: number): Promise<void> {
|
|
122
162
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
123
|
-
}
|
|
163
|
+
}
|