ai-ship-cli 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +3 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/ai/gemini.js +34 -0
- package/dist/ai/ollama.js +36 -0
- package/dist/analyzers/analyzer.js +93 -0
- package/dist/analyzers/compressBranchSummary.js +12 -0
- package/dist/analyzers/configAnalyzer.js +18 -0
- package/dist/analyzers/detectSignals.js +18 -0
- package/dist/analyzers/markupAnalyzer.js +26 -0
- package/dist/commands/commit/customAdd.js +1 -0
- package/dist/commands/commit/startCommit.js +155 -0
- package/dist/commands/commit.js +21 -0
- package/dist/commands/config/deleteKey.js +15 -0
- package/dist/commands/config.js +65 -0
- package/dist/commands/git/startCheckout.js +62 -0
- package/dist/commands/git/startCommit.js +91 -0
- package/dist/commands/git/startPR.js +51 -0
- package/dist/commands/git/startPush.js +24 -0
- package/dist/commands/git/startWorkflow.js +71 -0
- package/dist/commands/github/github.js +63 -0
- package/dist/commands/pr.js +1 -0
- package/dist/index.js +38 -0
- package/dist/utils/ai.js +22 -0
- package/dist/utils/asyncExecuter.js +35 -0
- package/dist/utils/files.js +28 -0
- package/dist/utils/git.js +106 -0
- package/dist/utils/github.js +13 -0
- package/dist/utils/helper.js +130 -0
- package/dist/utils/inputs.js +20 -0
- package/dist/utils/inquirer.js +79 -0
- package/dist/utils/parser.js +54 -0
- package/dist/utils/print.js +25 -0
- package/dist/utils/prompts.js +206 -0
- package/dist/utils/runCommit.js +17 -0
- package/dist/utils/runConfig.js +35 -0
- package/docs/commands.md +106 -0
- package/package.json +44 -0
- package/src/ai/gemini.ts +27 -0
- package/src/ai/ollama.ts +38 -0
- package/src/analyzers/analyzer.ts +117 -0
- package/src/analyzers/compressBranchSummary.ts +16 -0
- package/src/analyzers/configAnalyzer.ts +17 -0
- package/src/analyzers/detectSignals.ts +13 -0
- package/src/analyzers/markupAnalyzer.ts +25 -0
- package/src/commands/commit.ts +18 -0
- package/src/commands/config.ts +73 -0
- package/src/commands/git/startCheckout.ts +97 -0
- package/src/commands/git/startCommit.ts +108 -0
- package/src/commands/git/startPR.ts +66 -0
- package/src/commands/git/startPush.ts +18 -0
- package/src/commands/git/startWorkflow.ts +71 -0
- package/src/commands/github/github.ts +72 -0
- package/src/commands/pr.ts +0 -0
- package/src/index.ts +40 -0
- package/src/utils/ai.ts +30 -0
- package/src/utils/asyncExecuter.ts +39 -0
- package/src/utils/files.ts +30 -0
- package/src/utils/git.ts +108 -0
- package/src/utils/github.ts +19 -0
- package/src/utils/helper.ts +145 -0
- package/src/utils/inputs.ts +15 -0
- package/src/utils/inquirer.ts +99 -0
- package/src/utils/parser.ts +58 -0
- package/src/utils/print.ts +16 -0
- package/src/utils/prompts.ts +234 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const LOCK_FILES = [
|
|
2
|
+
'*.lock',
|
|
3
|
+
'package-lock.json',
|
|
4
|
+
'yarn.lock',
|
|
5
|
+
'pnpm-lock.yaml',
|
|
6
|
+
'Pipfile.lock',
|
|
7
|
+
'poetry.lock',
|
|
8
|
+
'Cargo.lock',
|
|
9
|
+
'composer.lock',
|
|
10
|
+
'Gemfile.lock',
|
|
11
|
+
'go.sum',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const BUILD_DIRS = [
|
|
15
|
+
'dist/**',
|
|
16
|
+
'build/**',
|
|
17
|
+
'out/**',
|
|
18
|
+
'target/**',
|
|
19
|
+
'bin/**',
|
|
20
|
+
'obj/**',
|
|
21
|
+
'.next/**',
|
|
22
|
+
'.nuxt/**',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const CACHE_DIRS = [
|
|
26
|
+
'.cache/**',
|
|
27
|
+
'.pytest_cache/**',
|
|
28
|
+
'.mypy_cache/**',
|
|
29
|
+
'.gradle/**',
|
|
30
|
+
'.idea/**',
|
|
31
|
+
'.vscode/**',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const DEP_DIRS = ['node_modules/**', 'vendor/**', '.venv/**', 'venv/**'];
|
|
35
|
+
|
|
36
|
+
const TEMP_FILES = ['*.log', '*.tmp', '*.temp', '*.swp'];
|
|
37
|
+
|
|
38
|
+
const GENERATED_FILES = ['*.map', '*.class', '*.o', '*.pyc', '*.dll', '*.exe'];
|
|
39
|
+
|
|
40
|
+
export const NOISE_PATTERNS = [
|
|
41
|
+
...LOCK_FILES,
|
|
42
|
+
...BUILD_DIRS,
|
|
43
|
+
...CACHE_DIRS,
|
|
44
|
+
...DEP_DIRS,
|
|
45
|
+
...TEMP_FILES,
|
|
46
|
+
...GENERATED_FILES,
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
import { minimatch } from 'minimatch';
|
|
50
|
+
|
|
51
|
+
export const isNoiseFile = (file: string) => {
|
|
52
|
+
return NOISE_PATTERNS.some((pattern) => minimatch(file, pattern));
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const filterNoiseFiles = (files: string[]) => {
|
|
56
|
+
const meaningful = files.filter((f) => !isNoiseFile(f));
|
|
57
|
+
return meaningful.length ? meaningful : files;
|
|
58
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { log } from './helper';
|
|
3
|
+
|
|
4
|
+
export const printFileList = (filesList: { status: string; file: string }[]) => {
|
|
5
|
+
filesList.forEach(({ status, file }) => {
|
|
6
|
+
if (status === '??' || status === 'A') {
|
|
7
|
+
log(chalk.green(file));
|
|
8
|
+
} else if (status === 'M') {
|
|
9
|
+
log(chalk.yellow(file));
|
|
10
|
+
} else if (status === 'D') {
|
|
11
|
+
log(chalk.red(file));
|
|
12
|
+
} else {
|
|
13
|
+
log(file);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
export const buildCommitPrompt = (summary: any[]) => {
|
|
2
|
+
const formatted = summary
|
|
3
|
+
.map(
|
|
4
|
+
(s) => `
|
|
5
|
+
File: ${s.file}
|
|
6
|
+
+${s.additions} -${s.deletions}
|
|
7
|
+
Signals: ${s.signals.join(', ')}
|
|
8
|
+
|
|
9
|
+
Snippet:
|
|
10
|
+
${s.snippet.join('\n')}
|
|
11
|
+
`,
|
|
12
|
+
)
|
|
13
|
+
.join('\n');
|
|
14
|
+
|
|
15
|
+
return `
|
|
16
|
+
Generate a conventional commit message.
|
|
17
|
+
|
|
18
|
+
Rules:
|
|
19
|
+
- one line
|
|
20
|
+
- under 72 characters
|
|
21
|
+
- conventional commit format
|
|
22
|
+
|
|
23
|
+
Changes:
|
|
24
|
+
${formatted}
|
|
25
|
+
`;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type BranchSummary = {
|
|
29
|
+
file: string;
|
|
30
|
+
signals: string[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const buildBranchPrompt = (
|
|
34
|
+
summary: BranchSummary[],
|
|
35
|
+
existingBranches: string[],
|
|
36
|
+
currentBranch: string,
|
|
37
|
+
commitMessage: string,
|
|
38
|
+
) => {
|
|
39
|
+
const changeList = summary
|
|
40
|
+
.map((s, i) => {
|
|
41
|
+
const signals = s.signals.length ? s.signals.join(', ') : 'code change';
|
|
42
|
+
return `${i + 1}. ${s.file} : ${signals}`;
|
|
43
|
+
})
|
|
44
|
+
.join('\n');
|
|
45
|
+
|
|
46
|
+
const branchList = existingBranches.slice(0, 30).join('\n'); // limit tokens
|
|
47
|
+
|
|
48
|
+
return `
|
|
49
|
+
You are a Git expert.
|
|
50
|
+
|
|
51
|
+
Generate a short git branch name that summarizes the main intent of the change.
|
|
52
|
+
Focus on the most important modification.
|
|
53
|
+
|
|
54
|
+
Rules:
|
|
55
|
+
- use kebab-case
|
|
56
|
+
- max 40 characters
|
|
57
|
+
- prefix with:
|
|
58
|
+
feature/
|
|
59
|
+
fix/
|
|
60
|
+
refactor/
|
|
61
|
+
chore/
|
|
62
|
+
docs/
|
|
63
|
+
- avoid existing branch names
|
|
64
|
+
- return ONLY the branch name
|
|
65
|
+
- no explanation
|
|
66
|
+
- no quotes
|
|
67
|
+
|
|
68
|
+
Current commit message:
|
|
69
|
+
${commitMessage}
|
|
70
|
+
|
|
71
|
+
Current branch:
|
|
72
|
+
${currentBranch}
|
|
73
|
+
|
|
74
|
+
Existing branches:
|
|
75
|
+
${branchList}
|
|
76
|
+
|
|
77
|
+
Changes:
|
|
78
|
+
${changeList}
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
feature/add-commit-generator
|
|
82
|
+
fix/git-diff-parser
|
|
83
|
+
refactor/commit-analysis-pipeline
|
|
84
|
+
chore/update-config
|
|
85
|
+
docs/update-readme
|
|
86
|
+
`;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const buildCommitPromptGemma = (summary: any[]) => {
|
|
90
|
+
const formatted = summary
|
|
91
|
+
.map(
|
|
92
|
+
(s) => `
|
|
93
|
+
File: ${s.file}
|
|
94
|
+
Additions: ${s.additions}
|
|
95
|
+
Deletions: ${s.deletions}
|
|
96
|
+
Signals: ${s.signals.join(', ')}
|
|
97
|
+
`,
|
|
98
|
+
)
|
|
99
|
+
.join('\n');
|
|
100
|
+
|
|
101
|
+
return `
|
|
102
|
+
You generate git commit messages.
|
|
103
|
+
|
|
104
|
+
Task:
|
|
105
|
+
Write a Conventional Commit message describing the changes.
|
|
106
|
+
|
|
107
|
+
Rules:
|
|
108
|
+
- one line only
|
|
109
|
+
- under 72 characters
|
|
110
|
+
- imperative tense
|
|
111
|
+
- lowercase commit type
|
|
112
|
+
- no explanation
|
|
113
|
+
- no additional text
|
|
114
|
+
|
|
115
|
+
Format:
|
|
116
|
+
type: message
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
feat: add commit generation using AI
|
|
120
|
+
fix: correct git diff parsing
|
|
121
|
+
refactor: simplify diff analyzer logic
|
|
122
|
+
chore: update dependencies
|
|
123
|
+
|
|
124
|
+
Changes:
|
|
125
|
+
${formatted}
|
|
126
|
+
|
|
127
|
+
Output exactly one line like:
|
|
128
|
+
feat: add ollama integration
|
|
129
|
+
`;
|
|
130
|
+
};
|
|
131
|
+
export const buildBranchPromptGemma = (
|
|
132
|
+
summary: BranchSummary[],
|
|
133
|
+
existingBranches: string[],
|
|
134
|
+
currentBranch: string,
|
|
135
|
+
commitMessage: string,
|
|
136
|
+
) => {
|
|
137
|
+
const changeList = summary
|
|
138
|
+
.map((s, i) => {
|
|
139
|
+
const signals = s.signals.length ? s.signals.join(', ') : 'code change';
|
|
140
|
+
return `${i + 1}. ${s.file}: ${signals}`;
|
|
141
|
+
})
|
|
142
|
+
.join('\n');
|
|
143
|
+
|
|
144
|
+
const branchList = existingBranches.slice(0, 30).join('\n');
|
|
145
|
+
|
|
146
|
+
return `
|
|
147
|
+
You generate git branch names.
|
|
148
|
+
|
|
149
|
+
Goal:
|
|
150
|
+
Create a concise branch name describing the change.
|
|
151
|
+
|
|
152
|
+
Rules:
|
|
153
|
+
- kebab-case
|
|
154
|
+
- max 40 characters
|
|
155
|
+
- must start with:
|
|
156
|
+
feature/
|
|
157
|
+
fix/
|
|
158
|
+
refactor/
|
|
159
|
+
chore/
|
|
160
|
+
docs/
|
|
161
|
+
- do not match existing branches
|
|
162
|
+
- no explanation
|
|
163
|
+
- no quotes
|
|
164
|
+
|
|
165
|
+
Commit message:
|
|
166
|
+
${commitMessage}
|
|
167
|
+
|
|
168
|
+
Current branch:
|
|
169
|
+
${currentBranch}
|
|
170
|
+
|
|
171
|
+
Existing branches:
|
|
172
|
+
${branchList}
|
|
173
|
+
|
|
174
|
+
Changed files:
|
|
175
|
+
${changeList}
|
|
176
|
+
|
|
177
|
+
Output format:
|
|
178
|
+
feature/branch-name
|
|
179
|
+
|
|
180
|
+
Examples:
|
|
181
|
+
feature/add-commit-generator
|
|
182
|
+
fix/git-diff-parser
|
|
183
|
+
refactor/commit-analysis-pipeline
|
|
184
|
+
chore/update-config
|
|
185
|
+
docs/update-readme
|
|
186
|
+
|
|
187
|
+
Return ONLY the branch name.
|
|
188
|
+
`;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const pRPrompt = ({
|
|
192
|
+
commitMessage,
|
|
193
|
+
branchName,
|
|
194
|
+
summary,
|
|
195
|
+
}: {
|
|
196
|
+
commitMessage: string;
|
|
197
|
+
branchName: string;
|
|
198
|
+
summary: any;
|
|
199
|
+
}) => {
|
|
200
|
+
return `
|
|
201
|
+
You are an expert software engineer.
|
|
202
|
+
|
|
203
|
+
Based on the following code changes, generate a high-quality pull request.
|
|
204
|
+
|
|
205
|
+
Inputs:
|
|
206
|
+
- Commit message: ${commitMessage}
|
|
207
|
+
- Branch name: ${branchName}
|
|
208
|
+
- File changes:
|
|
209
|
+
${JSON.stringify(summary, null, 2)}
|
|
210
|
+
|
|
211
|
+
Instructions:
|
|
212
|
+
- Write a clear and concise PR title
|
|
213
|
+
- Write a structured PR description
|
|
214
|
+
- Do NOT include unnecessary explanations
|
|
215
|
+
- Do NOT repeat the same information
|
|
216
|
+
- Keep it professional and minimal
|
|
217
|
+
- Keep total description under 120 words
|
|
218
|
+
|
|
219
|
+
Output format:
|
|
220
|
+
|
|
221
|
+
TITLE:
|
|
222
|
+
<one-line PR title>
|
|
223
|
+
|
|
224
|
+
DESCRIPTION:
|
|
225
|
+
## Summary
|
|
226
|
+
<what this PR does>
|
|
227
|
+
|
|
228
|
+
## Changes
|
|
229
|
+
<bullet list of key changes>
|
|
230
|
+
|
|
231
|
+
## Notes
|
|
232
|
+
<optional, only if needed>
|
|
233
|
+
`;
|
|
234
|
+
};
|