git-coco 0.21.3 → 0.22.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.d.ts +4 -0
- package/dist/index.esm.mjs +284 -198
- package/dist/index.js +284 -198
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -173,6 +173,10 @@ interface ChangelogOptions extends BaseCommandOptions {
|
|
|
173
173
|
range: string;
|
|
174
174
|
branch: string;
|
|
175
175
|
sinceLastTag: boolean;
|
|
176
|
+
withDiff?: boolean;
|
|
177
|
+
onlyDiff?: boolean;
|
|
178
|
+
additional?: string;
|
|
179
|
+
author?: boolean;
|
|
176
180
|
}
|
|
177
181
|
type ChangelogArgv = Arguments<ChangelogOptions>;
|
|
178
182
|
|
package/dist/index.esm.mjs
CHANGED
|
@@ -48,7 +48,7 @@ import { pathToFileURL } from 'url';
|
|
|
48
48
|
/**
|
|
49
49
|
* Current build version from package.json
|
|
50
50
|
*/
|
|
51
|
-
const BUILD_VERSION = "0.
|
|
51
|
+
const BUILD_VERSION = "0.22.0";
|
|
52
52
|
|
|
53
53
|
const isInteractive = (config) => {
|
|
54
54
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -1018,6 +1018,15 @@ const schema$1 = {
|
|
|
1018
1018
|
"apiKey": {
|
|
1019
1019
|
"type": "string",
|
|
1020
1020
|
"description": "API key to use when making requests to OpenAI. Defaults to the value of `OPENAI_API_KEY` environment variable."
|
|
1021
|
+
},
|
|
1022
|
+
"verbosity": {
|
|
1023
|
+
"type": "string",
|
|
1024
|
+
"enum": [
|
|
1025
|
+
"low",
|
|
1026
|
+
"medium",
|
|
1027
|
+
"high"
|
|
1028
|
+
],
|
|
1029
|
+
"description": "The verbosity of the model's response."
|
|
1021
1030
|
}
|
|
1022
1031
|
}
|
|
1023
1032
|
},
|
|
@@ -6054,6 +6063,26 @@ const options$4 = {
|
|
|
6054
6063
|
description: 'Generate changelog for all commits since the last tag',
|
|
6055
6064
|
default: false,
|
|
6056
6065
|
},
|
|
6066
|
+
withDiff: {
|
|
6067
|
+
type: 'boolean',
|
|
6068
|
+
description: 'Include the diff for each commit in the prompt',
|
|
6069
|
+
default: false,
|
|
6070
|
+
},
|
|
6071
|
+
onlyDiff: {
|
|
6072
|
+
type: 'boolean',
|
|
6073
|
+
description: 'Generate a changelog based only on the diff of the entire branch',
|
|
6074
|
+
default: false,
|
|
6075
|
+
},
|
|
6076
|
+
additional: {
|
|
6077
|
+
type: 'string',
|
|
6078
|
+
alias: 'a',
|
|
6079
|
+
description: 'Add extra contextual information to the prompt',
|
|
6080
|
+
},
|
|
6081
|
+
author: {
|
|
6082
|
+
type: 'boolean',
|
|
6083
|
+
description: 'Include author attribution in the changelog',
|
|
6084
|
+
default: false,
|
|
6085
|
+
},
|
|
6057
6086
|
i: {
|
|
6058
6087
|
type: 'boolean',
|
|
6059
6088
|
alias: 'interactive',
|
|
@@ -6958,45 +6987,39 @@ const getChangesSinceLastTag = async ({ git }) => {
|
|
|
6958
6987
|
};
|
|
6959
6988
|
|
|
6960
6989
|
/**
|
|
6961
|
-
* Retrieves the commit log range between two specified commits (inclusive of both commits).
|
|
6990
|
+
* Retrieves the detailed commit log range between two specified commits (inclusive of both commits).
|
|
6962
6991
|
*
|
|
6963
6992
|
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6964
6993
|
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6965
6994
|
* @param options - Additional options for retrieving the commit log range.
|
|
6966
|
-
* @returns A promise that resolves to an array of commit
|
|
6995
|
+
* @returns A promise that resolves to an array of commit details objects.
|
|
6967
6996
|
* @throws If there is an error retrieving the commit log range.
|
|
6968
6997
|
*/
|
|
6969
|
-
async function
|
|
6998
|
+
async function getCommitLogRangeDetails(from, to, { noMerges, git }) {
|
|
6970
6999
|
try {
|
|
6971
|
-
// Use from^..to to include the 'from' commit in the range
|
|
6972
|
-
// This works because from^..to means "commits reachable from 'to' but not from the parent of 'from'"
|
|
6973
7000
|
const logOptions = {
|
|
6974
7001
|
from: `${from}^`,
|
|
6975
7002
|
to,
|
|
6976
7003
|
'--no-merges': noMerges
|
|
6977
7004
|
};
|
|
6978
7005
|
const commitLog = await git.log(logOptions);
|
|
6979
|
-
return commitLog.all
|
|
7006
|
+
return [...commitLog.all];
|
|
6980
7007
|
}
|
|
6981
7008
|
catch (error) {
|
|
6982
|
-
// If from^ fails (e.g., 'from' is the first commit), fall back to using from..to and manually adding the 'from' commit
|
|
6983
7009
|
if (error instanceof Error && error.message.includes('unknown revision')) {
|
|
6984
7010
|
try {
|
|
6985
|
-
// Get the 'from' commit separately
|
|
6986
7011
|
const fromCommitLog = await git.log({ from: from, maxCount: 1 });
|
|
6987
7012
|
const fromCommit = fromCommitLog.latest;
|
|
6988
|
-
// Get the range from..to (excluding 'from')
|
|
6989
7013
|
const rangeLogOptions = {
|
|
6990
7014
|
from,
|
|
6991
7015
|
to,
|
|
6992
7016
|
'--no-merges': noMerges
|
|
6993
7017
|
};
|
|
6994
7018
|
const rangeCommitLog = await git.log(rangeLogOptions);
|
|
6995
|
-
// Combine the 'from' commit with the range commits
|
|
6996
7019
|
const allCommits = fromCommit
|
|
6997
7020
|
? [fromCommit, ...rangeCommitLog.all]
|
|
6998
|
-
: rangeCommitLog.all;
|
|
6999
|
-
return allCommits
|
|
7021
|
+
: [...rangeCommitLog.all];
|
|
7022
|
+
return allCommits;
|
|
7000
7023
|
}
|
|
7001
7024
|
catch (fallbackError) {
|
|
7002
7025
|
throw fallbackError;
|
|
@@ -7023,7 +7046,7 @@ async function getCurrentBranchName({ git }) {
|
|
|
7023
7046
|
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
7024
7047
|
* @param {Logger} options.logger - The logger for logging messages.
|
|
7025
7048
|
* @param {string} options.targetBranch - The target branch to compare against.
|
|
7026
|
-
* @returns {Promise<
|
|
7049
|
+
* @returns {Promise<CommitDetails[]>} The array of commit messages in the commit log.
|
|
7027
7050
|
*/
|
|
7028
7051
|
async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
7029
7052
|
try {
|
|
@@ -7042,7 +7065,7 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
7042
7065
|
return [];
|
|
7043
7066
|
}
|
|
7044
7067
|
// Retrieve commit log with messages
|
|
7045
|
-
return await
|
|
7068
|
+
return await getCommitLogRangeDetails(firstCommit, lastCommit, { git, noMerges: true });
|
|
7046
7069
|
}
|
|
7047
7070
|
catch (error) {
|
|
7048
7071
|
logger?.log('Encountered an error getting commit log between branches', { color: 'red' });
|
|
@@ -7058,7 +7081,7 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
7058
7081
|
* @param {Logger} options.logger - The logger for logging messages.
|
|
7059
7082
|
* @param {string} [options.comparisonBranch='main'] - The branch to compare against.
|
|
7060
7083
|
* @param {string} [options.comparisonRemote='origin'] - The remote to compare against.
|
|
7061
|
-
* @returns {Promise<
|
|
7084
|
+
* @returns {Promise<CommitDetails[]>} The array of commit messages in the commit log.
|
|
7062
7085
|
*/
|
|
7063
7086
|
async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main', comparisonRemote = 'origin', }) {
|
|
7064
7087
|
try {
|
|
@@ -7094,7 +7117,7 @@ async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main
|
|
|
7094
7117
|
});
|
|
7095
7118
|
return [];
|
|
7096
7119
|
}
|
|
7097
|
-
return await
|
|
7120
|
+
return await getCommitLogRangeDetails(firstCommit, lastCommit, { git, noMerges: true });
|
|
7098
7121
|
}
|
|
7099
7122
|
catch (error) {
|
|
7100
7123
|
logger?.log('Encountered an error getting commit log from current branch', { color: 'red' });
|
|
@@ -7460,18 +7483,202 @@ async function handleResult({ result, mode, interactiveModeCallback }) {
|
|
|
7460
7483
|
}
|
|
7461
7484
|
}
|
|
7462
7485
|
|
|
7463
|
-
|
|
7486
|
+
/**
|
|
7487
|
+
* Fetches the diff for the given commit ID.
|
|
7488
|
+
*
|
|
7489
|
+
* @param commitId The commit ID for which the diff is to be retrieved.
|
|
7490
|
+
* @returns A promise that resolves to the diff of the commit.
|
|
7491
|
+
*/
|
|
7492
|
+
async function getDiffForCommit(commitId, { git, }) {
|
|
7493
|
+
try {
|
|
7494
|
+
return await git.diff(['-p', `${commitId}^..${commitId}`]);
|
|
7495
|
+
}
|
|
7496
|
+
catch (error) {
|
|
7497
|
+
throw new Error(`Error fetching diff for commit ${commitId}: ${error.message}`);
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7464
7500
|
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
-
|
|
7501
|
+
/**
|
|
7502
|
+
* Determines the status of a file based on its changes in the Git repository.
|
|
7503
|
+
*
|
|
7504
|
+
* @param file - The file to check the status of.
|
|
7505
|
+
* @param location - The location to check the status in ('index' or 'working_dir'). Defaults to 'index'.
|
|
7506
|
+
* @returns The status of the file ('added', 'deleted', 'modified', 'renamed', 'untracked', or 'unknown').
|
|
7507
|
+
* @throws Error if the file type is invalid.
|
|
7508
|
+
*/
|
|
7509
|
+
function getStatus(file, location = 'index') {
|
|
7510
|
+
if ('index' in file && 'working_dir' in file) {
|
|
7511
|
+
const statusCode = file[location];
|
|
7512
|
+
switch (statusCode) {
|
|
7513
|
+
case 'A':
|
|
7514
|
+
return 'added';
|
|
7515
|
+
case 'D':
|
|
7516
|
+
return 'deleted';
|
|
7517
|
+
case 'M':
|
|
7518
|
+
return 'modified';
|
|
7519
|
+
case 'R':
|
|
7520
|
+
return 'renamed';
|
|
7521
|
+
case '?':
|
|
7522
|
+
return 'untracked';
|
|
7523
|
+
default:
|
|
7524
|
+
return 'unknown';
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
else if ('changes' in file && 'binary' in file) {
|
|
7528
|
+
if (file.changes === 0)
|
|
7529
|
+
return 'untracked';
|
|
7530
|
+
if (file.file.includes('=>'))
|
|
7531
|
+
return 'renamed';
|
|
7532
|
+
if (file.deletions === 0 && file.insertions > 0)
|
|
7533
|
+
return 'added';
|
|
7534
|
+
if (file.insertions === 0 && file.deletions > 0)
|
|
7535
|
+
return 'deleted';
|
|
7536
|
+
if ((file.insertions > 0 && file.deletions > 0) || file.changes > 0)
|
|
7537
|
+
return 'modified';
|
|
7538
|
+
return 'unknown';
|
|
7539
|
+
}
|
|
7540
|
+
else {
|
|
7541
|
+
throw new Error('Invalid file type');
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7470
7544
|
|
|
7545
|
+
/**
|
|
7546
|
+
* Returns the summary text for a file change.
|
|
7547
|
+
*
|
|
7548
|
+
* @param file - The file status or diff result.
|
|
7549
|
+
* @param change - The partial file change object.
|
|
7550
|
+
* @returns The summary text for the file change.
|
|
7551
|
+
* @throws Error if the file type is invalid.
|
|
7552
|
+
*/
|
|
7553
|
+
function getSummaryText(file, change) {
|
|
7554
|
+
const status = change.status || getStatus(file);
|
|
7555
|
+
let filePath;
|
|
7556
|
+
if ('path' in file) {
|
|
7557
|
+
filePath = file.path;
|
|
7558
|
+
}
|
|
7559
|
+
else if ('file' in file) {
|
|
7560
|
+
filePath = change?.filePath || file.file;
|
|
7561
|
+
}
|
|
7562
|
+
else {
|
|
7563
|
+
throw new Error('Invalid file type');
|
|
7564
|
+
}
|
|
7565
|
+
if (change.oldFilePath) {
|
|
7566
|
+
return `${status}: ${change.oldFilePath} -> ${filePath}`;
|
|
7567
|
+
}
|
|
7568
|
+
return `${status}: ${filePath}`;
|
|
7569
|
+
}
|
|
7570
|
+
|
|
7571
|
+
/**
|
|
7572
|
+
* Retrieves the diff between the current branch and a specified target branch.
|
|
7573
|
+
*
|
|
7574
|
+
* @param {Object} options - The options for retrieving the diff.
|
|
7575
|
+
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
7576
|
+
* @param {Logger} options.logger - The logger for logging messages.
|
|
7577
|
+
* @param {string} options.baseBranch - The base branch to compare against.
|
|
7578
|
+
* @param {string} options.headBranch - The head branch to compare.
|
|
7579
|
+
* @param {string[]} options.ignoredFiles - Array of specific files to ignore.
|
|
7580
|
+
* @param {string[]} options.ignoredExtensions - Array of file extensions to ignore.
|
|
7581
|
+
* @returns {Promise<GetChangesResult>} The diff between the current branch and the target branch.
|
|
7582
|
+
*/
|
|
7583
|
+
async function getDiffForBranch({ git, logger, baseBranch, headBranch, options, }) {
|
|
7584
|
+
try {
|
|
7585
|
+
logger?.verbose(`Getting diff for branches: baseBranch="${baseBranch}", headBranch="${headBranch}"`, {
|
|
7586
|
+
color: 'blue',
|
|
7587
|
+
});
|
|
7588
|
+
// Validate branch names
|
|
7589
|
+
if (!baseBranch || !headBranch) {
|
|
7590
|
+
throw new Error(`Invalid branch names: baseBranch="${baseBranch}", headBranch="${headBranch}"`);
|
|
7591
|
+
}
|
|
7592
|
+
const { ignoredFiles = [], ignoredExtensions = [] } = options || {};
|
|
7593
|
+
// Prepare ignore patterns
|
|
7594
|
+
const ignorePatterns = [
|
|
7595
|
+
...ignoredFiles.map((file) => `:!${file}`),
|
|
7596
|
+
...ignoredExtensions.map((ext) => `:!*${ext}`),
|
|
7597
|
+
];
|
|
7598
|
+
// Construct the diff command
|
|
7599
|
+
const diffArgs = [`${baseBranch}..${headBranch}`];
|
|
7600
|
+
if (ignorePatterns.length > 0) {
|
|
7601
|
+
diffArgs.push('--');
|
|
7602
|
+
diffArgs.push(...ignorePatterns);
|
|
7603
|
+
}
|
|
7604
|
+
logger?.verbose(`Running git diff with args: ${diffArgs.join(' ')}`, {
|
|
7605
|
+
color: 'blue',
|
|
7606
|
+
});
|
|
7607
|
+
// Get the diff
|
|
7608
|
+
const diff = await git.diff(diffArgs);
|
|
7609
|
+
logger?.verbose(`Generated diff between "${headBranch}" and "${baseBranch}"`, {
|
|
7610
|
+
color: 'blue',
|
|
7611
|
+
});
|
|
7612
|
+
const changes = diff.split('diff --git').slice(1).map((fileDiff) => {
|
|
7613
|
+
const lines = fileDiff.split('\n');
|
|
7614
|
+
const filePathLine = lines[0];
|
|
7615
|
+
const filePath = filePathLine.split('b/')[1]?.split(' ')[0];
|
|
7616
|
+
const oldFilePath = filePathLine.split('a/')[1]?.split(' ')[0];
|
|
7617
|
+
// Determine status based on diff headers
|
|
7618
|
+
let status = 'modified';
|
|
7619
|
+
if (fileDiff.includes('new file mode')) {
|
|
7620
|
+
status = 'added';
|
|
7621
|
+
}
|
|
7622
|
+
else if (fileDiff.includes('deleted file mode')) {
|
|
7623
|
+
status = 'deleted';
|
|
7624
|
+
}
|
|
7625
|
+
else if (fileDiff.includes('rename from')) {
|
|
7626
|
+
status = 'renamed';
|
|
7627
|
+
}
|
|
7628
|
+
return {
|
|
7629
|
+
filePath: filePath || '',
|
|
7630
|
+
oldFilePath: oldFilePath || '',
|
|
7631
|
+
status,
|
|
7632
|
+
summary: getSummaryText({ path: filePath || '', index: '', working_dir: '' }, { filePath: filePath || '', status }),
|
|
7633
|
+
};
|
|
7634
|
+
});
|
|
7635
|
+
return {
|
|
7636
|
+
staged: changes,
|
|
7637
|
+
unstaged: [],
|
|
7638
|
+
untracked: [],
|
|
7639
|
+
};
|
|
7640
|
+
}
|
|
7641
|
+
catch (error) {
|
|
7642
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7643
|
+
console.error('Error in getDiffForBranch:', error);
|
|
7644
|
+
logger?.log(`Encountered an error getting diff between branches: ${errorMessage}`, { color: 'red' });
|
|
7645
|
+
logger?.log(`Branch details: baseBranch="${baseBranch}", headBranch="${headBranch}"`, { color: 'red' });
|
|
7646
|
+
// Re-throw the error so the caller can handle it appropriately
|
|
7647
|
+
throw error;
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7650
|
+
|
|
7651
|
+
const template$3 = `You are a highly skilled software engineer tasked with writing a git changelog. Your response should be informative, well-structured, and in the imperative.
|
|
7652
|
+
|
|
7653
|
+
## Input
|
|
7654
|
+
You will be provided with a summary of changes. This summary can be one of the following:
|
|
7655
|
+
1. A list of commits, each with its author, hash, message, and body.
|
|
7656
|
+
2. A list of commits, each with its details AND the full diff of the changes.
|
|
7657
|
+
3. A single, comprehensive diff for an entire branch.
|
|
7658
|
+
|
|
7659
|
+
## Rules
|
|
7660
|
+
- Create a descriptive title for the changelog that gives a high-level overview of the changes.
|
|
7661
|
+
- **BREAKING CHANGES**: Identify any commits that introduce breaking changes. These must be listed first under a "### 💥 BREAKING CHANGES" heading.
|
|
7662
|
+
- **Grouping**: Logically group related changes under descriptive headings (e.g., ### Features, ### Fixes, ### Refactors).
|
|
7663
|
+
- **Dependencies**: Group all dependency updates (e.g., changes to package.json, go.mod) under a "### Dependencies" section.
|
|
7664
|
+
- **Summaries**: For each change, provide a concise summary.
|
|
7665
|
+
- **Attribution**: {{author_instructions}}
|
|
7666
|
+
- **Technical Details**: If provided with diffs, use them to understand the technical details and provide a more accurate and detailed description of the changes.
|
|
7667
|
+
- **Clarity**: Avoid generalizations like "various bug fixes," "improvements," or "enhancements." Be specific.
|
|
7668
|
+
- **Formatting**: Your entire response must be valid Markdown.
|
|
7669
|
+
|
|
7670
|
+
## Formatting Instructions
|
|
7471
7671
|
{{format_instructions}}
|
|
7472
7672
|
|
|
7673
|
+
{{additional_context}}
|
|
7674
|
+
|
|
7473
7675
|
"""{{summary}}"""`;
|
|
7474
|
-
const inputVariables$2 = [
|
|
7676
|
+
const inputVariables$2 = [
|
|
7677
|
+
'format_instructions',
|
|
7678
|
+
'summary',
|
|
7679
|
+
'additional_context',
|
|
7680
|
+
'author_instructions',
|
|
7681
|
+
];
|
|
7475
7682
|
const CHANGELOG_PROMPT = new PromptTemplate({
|
|
7476
7683
|
template: template$3,
|
|
7477
7684
|
inputVariables: inputVariables$2,
|
|
@@ -7495,48 +7702,68 @@ const handler$4 = async (argv, logger) => {
|
|
|
7495
7702
|
}
|
|
7496
7703
|
async function factory() {
|
|
7497
7704
|
const branchName = await getCurrentBranchName({ git });
|
|
7498
|
-
if (
|
|
7499
|
-
logger.verbose(`Generating
|
|
7705
|
+
if (argv.onlyDiff) {
|
|
7706
|
+
logger.verbose(`Generating changelog based on branch diff`, { color: 'yellow' });
|
|
7707
|
+
const diff = await getDiffForBranch({ git, logger, baseBranch: argv.branch || 'main', headBranch: branchName });
|
|
7500
7708
|
return {
|
|
7501
7709
|
branch: branchName,
|
|
7502
|
-
|
|
7710
|
+
diff: JSON.stringify(diff.staged, null, 2),
|
|
7503
7711
|
};
|
|
7504
7712
|
}
|
|
7505
|
-
|
|
7713
|
+
let commits = [];
|
|
7714
|
+
if (config.sinceLastTag) {
|
|
7715
|
+
logger.verbose(`Generating commit log since the last tag`, { color: 'yellow' });
|
|
7716
|
+
// This function returns string[], needs to be adapted or replaced
|
|
7717
|
+
// For now, this path will have limited details.
|
|
7718
|
+
const commitMessages = await getChangesSinceLastTag({ git, logger });
|
|
7719
|
+
commits = commitMessages.map(msg => ({ message: msg }));
|
|
7720
|
+
}
|
|
7721
|
+
else if (config.range && config.range.includes(':')) {
|
|
7506
7722
|
const [from, to] = config.range.split(':');
|
|
7507
7723
|
if (!from || !to) {
|
|
7508
7724
|
logger.log(`Invalid range provided. Expected format is <from>:<to>`, { color: 'red' });
|
|
7509
7725
|
process.exit(1);
|
|
7510
7726
|
}
|
|
7511
|
-
|
|
7512
|
-
branch: branchName,
|
|
7513
|
-
commits: await getCommitLogRange(from, to, { git, noMerges: true }),
|
|
7514
|
-
};
|
|
7727
|
+
commits = await getCommitLogRangeDetails(from, to, { git, noMerges: true });
|
|
7515
7728
|
}
|
|
7516
|
-
if (argv.branch) {
|
|
7729
|
+
else if (argv.branch) {
|
|
7517
7730
|
logger.verbose(`Generating commit log against branch: ${argv.branch}`, { color: 'yellow' });
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7731
|
+
commits = await getCommitLogAgainstBranch({ git, logger, targetBranch: argv.branch });
|
|
7732
|
+
}
|
|
7733
|
+
else {
|
|
7734
|
+
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
7735
|
+
color: 'yellow',
|
|
7736
|
+
});
|
|
7737
|
+
commits = await getCommitLogCurrentBranch({ git, logger });
|
|
7738
|
+
}
|
|
7739
|
+
let commitsWithDiffText = commits;
|
|
7740
|
+
if (argv.withDiff) {
|
|
7741
|
+
commitsWithDiffText = await Promise.all(commits.map(async (commit) => ({
|
|
7742
|
+
...commit,
|
|
7743
|
+
diffText: await getDiffForCommit(commit.hash, { git }),
|
|
7744
|
+
})));
|
|
7522
7745
|
}
|
|
7523
|
-
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
7524
|
-
color: 'yellow',
|
|
7525
|
-
});
|
|
7526
|
-
const commits = await getCommitLogCurrentBranch({ git, logger });
|
|
7527
7746
|
return {
|
|
7528
7747
|
branch: branchName,
|
|
7529
|
-
commits,
|
|
7748
|
+
commits: commitsWithDiffText,
|
|
7749
|
+
withDiff: argv.withDiff,
|
|
7530
7750
|
};
|
|
7531
7751
|
}
|
|
7532
|
-
async function parser(
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
result = `## ${branch}\n\nNo commits found.`;
|
|
7752
|
+
async function parser(data) {
|
|
7753
|
+
if (data.diff) {
|
|
7754
|
+
return `## Diff for ${data.branch}\n\n${data.diff}`;
|
|
7536
7755
|
}
|
|
7537
|
-
|
|
7538
|
-
|
|
7756
|
+
if (!data.commits || data.commits.length === 0) {
|
|
7757
|
+
return `## ${data.branch}\n\nNo commits found.`;
|
|
7539
7758
|
}
|
|
7759
|
+
let result = `## ${data.branch}\n\n`;
|
|
7760
|
+
result += data.commits.map(commit => {
|
|
7761
|
+
let commitStr = `Author: ${commit.author_name}\nCommit: ${commit.hash}\nMessage: ${commit.message}\n${commit.body}`;
|
|
7762
|
+
if (data.withDiff && commit.diffText) {
|
|
7763
|
+
commitStr += `\nDiff:\n${commit.diffText}`;
|
|
7764
|
+
}
|
|
7765
|
+
return commitStr.trim();
|
|
7766
|
+
}).join('\n\n---\n\n');
|
|
7540
7767
|
return result;
|
|
7541
7768
|
}
|
|
7542
7769
|
const changelogMsg = await generateAndReviewLoop({
|
|
@@ -7560,12 +7787,21 @@ const handler$4 = async (argv, logger) => {
|
|
|
7560
7787
|
fallback: CHANGELOG_PROMPT,
|
|
7561
7788
|
});
|
|
7562
7789
|
const formatInstructions = "Only respond with a valid JSON object, containing two fields: 'title' an escaped string, no more than 65 characters, and 'content' also an escaped string.";
|
|
7790
|
+
let additional_context = '';
|
|
7791
|
+
if (argv.additional) {
|
|
7792
|
+
additional_context = `## Additional Context\n${argv.additional}`;
|
|
7793
|
+
}
|
|
7794
|
+
const author_instructions = argv.author
|
|
7795
|
+
? 'At the end of each item, attribute the author and include a reference to the commit hash, like this: `by @author_name (f6dbe61)`. Use the first 7 characters of the hash.'
|
|
7796
|
+
: 'At the end of each item, include a reference to the commit hash, like this: `(f6dbe61)`. Use the first 7 characters of the hash.';
|
|
7563
7797
|
const changelog = await executeChain({
|
|
7564
7798
|
llm,
|
|
7565
7799
|
prompt,
|
|
7566
7800
|
variables: {
|
|
7567
7801
|
summary: context,
|
|
7568
7802
|
format_instructions: formatInstructions,
|
|
7803
|
+
additional_context: additional_context,
|
|
7804
|
+
author_instructions: author_instructions,
|
|
7569
7805
|
},
|
|
7570
7806
|
parser,
|
|
7571
7807
|
});
|
|
@@ -10877,76 +11113,6 @@ async function createCommit(message, git) {
|
|
|
10877
11113
|
return await git.commit(message);
|
|
10878
11114
|
}
|
|
10879
11115
|
|
|
10880
|
-
/**
|
|
10881
|
-
* Determines the status of a file based on its changes in the Git repository.
|
|
10882
|
-
*
|
|
10883
|
-
* @param file - The file to check the status of.
|
|
10884
|
-
* @param location - The location to check the status in ('index' or 'working_dir'). Defaults to 'index'.
|
|
10885
|
-
* @returns The status of the file ('added', 'deleted', 'modified', 'renamed', 'untracked', or 'unknown').
|
|
10886
|
-
* @throws Error if the file type is invalid.
|
|
10887
|
-
*/
|
|
10888
|
-
function getStatus(file, location = 'index') {
|
|
10889
|
-
if ('index' in file && 'working_dir' in file) {
|
|
10890
|
-
const statusCode = file[location];
|
|
10891
|
-
switch (statusCode) {
|
|
10892
|
-
case 'A':
|
|
10893
|
-
return 'added';
|
|
10894
|
-
case 'D':
|
|
10895
|
-
return 'deleted';
|
|
10896
|
-
case 'M':
|
|
10897
|
-
return 'modified';
|
|
10898
|
-
case 'R':
|
|
10899
|
-
return 'renamed';
|
|
10900
|
-
case '?':
|
|
10901
|
-
return 'untracked';
|
|
10902
|
-
default:
|
|
10903
|
-
return 'unknown';
|
|
10904
|
-
}
|
|
10905
|
-
}
|
|
10906
|
-
else if ('changes' in file && 'binary' in file) {
|
|
10907
|
-
if (file.changes === 0)
|
|
10908
|
-
return 'untracked';
|
|
10909
|
-
if (file.file.includes('=>'))
|
|
10910
|
-
return 'renamed';
|
|
10911
|
-
if (file.deletions === 0 && file.insertions > 0)
|
|
10912
|
-
return 'added';
|
|
10913
|
-
if (file.insertions === 0 && file.deletions > 0)
|
|
10914
|
-
return 'deleted';
|
|
10915
|
-
if ((file.insertions > 0 && file.deletions > 0) || file.changes > 0)
|
|
10916
|
-
return 'modified';
|
|
10917
|
-
return 'unknown';
|
|
10918
|
-
}
|
|
10919
|
-
else {
|
|
10920
|
-
throw new Error('Invalid file type');
|
|
10921
|
-
}
|
|
10922
|
-
}
|
|
10923
|
-
|
|
10924
|
-
/**
|
|
10925
|
-
* Returns the summary text for a file change.
|
|
10926
|
-
*
|
|
10927
|
-
* @param file - The file status or diff result.
|
|
10928
|
-
* @param change - The partial file change object.
|
|
10929
|
-
* @returns The summary text for the file change.
|
|
10930
|
-
* @throws Error if the file type is invalid.
|
|
10931
|
-
*/
|
|
10932
|
-
function getSummaryText(file, change) {
|
|
10933
|
-
const status = change.status || getStatus(file);
|
|
10934
|
-
let filePath;
|
|
10935
|
-
if ('path' in file) {
|
|
10936
|
-
filePath = file.path;
|
|
10937
|
-
}
|
|
10938
|
-
else if ('file' in file) {
|
|
10939
|
-
filePath = change?.filePath || file.file;
|
|
10940
|
-
}
|
|
10941
|
-
else {
|
|
10942
|
-
throw new Error('Invalid file type');
|
|
10943
|
-
}
|
|
10944
|
-
if (change.oldFilePath) {
|
|
10945
|
-
return `${status}: ${change.oldFilePath} -> ${filePath}`;
|
|
10946
|
-
}
|
|
10947
|
-
return `${status}: ${filePath}`;
|
|
10948
|
-
}
|
|
10949
|
-
|
|
10950
11116
|
/**
|
|
10951
11117
|
* Retrieves the changes in the Git repository.
|
|
10952
11118
|
*
|
|
@@ -11984,86 +12150,6 @@ const getChangesByTimestamp = async ({ since, git }) => {
|
|
|
11984
12150
|
return formatCommitLog(commitLog);
|
|
11985
12151
|
};
|
|
11986
12152
|
|
|
11987
|
-
/**
|
|
11988
|
-
* Retrieves the diff between the current branch and a specified target branch.
|
|
11989
|
-
*
|
|
11990
|
-
* @param {Object} options - The options for retrieving the diff.
|
|
11991
|
-
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
11992
|
-
* @param {Logger} options.logger - The logger for logging messages.
|
|
11993
|
-
* @param {string} options.baseBranch - The base branch to compare against.
|
|
11994
|
-
* @param {string} options.headBranch - The head branch to compare.
|
|
11995
|
-
* @param {string[]} options.ignoredFiles - Array of specific files to ignore.
|
|
11996
|
-
* @param {string[]} options.ignoredExtensions - Array of file extensions to ignore.
|
|
11997
|
-
* @returns {Promise<GetChangesResult>} The diff between the current branch and the target branch.
|
|
11998
|
-
*/
|
|
11999
|
-
async function getDiffForBranch({ git, logger, baseBranch, headBranch, options, }) {
|
|
12000
|
-
try {
|
|
12001
|
-
logger?.verbose(`Getting diff for branches: baseBranch="${baseBranch}", headBranch="${headBranch}"`, {
|
|
12002
|
-
color: 'blue',
|
|
12003
|
-
});
|
|
12004
|
-
// Validate branch names
|
|
12005
|
-
if (!baseBranch || !headBranch) {
|
|
12006
|
-
throw new Error(`Invalid branch names: baseBranch="${baseBranch}", headBranch="${headBranch}"`);
|
|
12007
|
-
}
|
|
12008
|
-
const { ignoredFiles = [], ignoredExtensions = [] } = options || {};
|
|
12009
|
-
// Prepare ignore patterns
|
|
12010
|
-
const ignorePatterns = [
|
|
12011
|
-
...ignoredFiles.map((file) => `:!${file}`),
|
|
12012
|
-
...ignoredExtensions.map((ext) => `:!*${ext}`),
|
|
12013
|
-
];
|
|
12014
|
-
// Construct the diff command
|
|
12015
|
-
const diffArgs = [`${baseBranch}..${headBranch}`];
|
|
12016
|
-
if (ignorePatterns.length > 0) {
|
|
12017
|
-
diffArgs.push('--');
|
|
12018
|
-
diffArgs.push(...ignorePatterns);
|
|
12019
|
-
}
|
|
12020
|
-
logger?.verbose(`Running git diff with args: ${diffArgs.join(' ')}`, {
|
|
12021
|
-
color: 'blue',
|
|
12022
|
-
});
|
|
12023
|
-
// Get the diff
|
|
12024
|
-
const diff = await git.diff(diffArgs);
|
|
12025
|
-
logger?.verbose(`Generated diff between "${headBranch}" and "${baseBranch}"`, {
|
|
12026
|
-
color: 'blue',
|
|
12027
|
-
});
|
|
12028
|
-
const changes = diff.split('diff --git').slice(1).map((fileDiff) => {
|
|
12029
|
-
const lines = fileDiff.split('\n');
|
|
12030
|
-
const filePathLine = lines[0];
|
|
12031
|
-
const filePath = filePathLine.split('b/')[1]?.split(' ')[0];
|
|
12032
|
-
const oldFilePath = filePathLine.split('a/')[1]?.split(' ')[0];
|
|
12033
|
-
// Determine status based on diff headers
|
|
12034
|
-
let status = 'modified';
|
|
12035
|
-
if (fileDiff.includes('new file mode')) {
|
|
12036
|
-
status = 'added';
|
|
12037
|
-
}
|
|
12038
|
-
else if (fileDiff.includes('deleted file mode')) {
|
|
12039
|
-
status = 'deleted';
|
|
12040
|
-
}
|
|
12041
|
-
else if (fileDiff.includes('rename from')) {
|
|
12042
|
-
status = 'renamed';
|
|
12043
|
-
}
|
|
12044
|
-
return {
|
|
12045
|
-
filePath: filePath || '',
|
|
12046
|
-
oldFilePath: oldFilePath || '',
|
|
12047
|
-
status,
|
|
12048
|
-
summary: getSummaryText({ path: filePath || '', index: '', working_dir: '' }, { filePath: filePath || '', status }),
|
|
12049
|
-
};
|
|
12050
|
-
});
|
|
12051
|
-
return {
|
|
12052
|
-
staged: changes,
|
|
12053
|
-
unstaged: [],
|
|
12054
|
-
untracked: [],
|
|
12055
|
-
};
|
|
12056
|
-
}
|
|
12057
|
-
catch (error) {
|
|
12058
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
12059
|
-
console.error('Error in getDiffForBranch:', error);
|
|
12060
|
-
logger?.log(`Encountered an error getting diff between branches: ${errorMessage}`, { color: 'red' });
|
|
12061
|
-
logger?.log(`Branch details: baseBranch="${baseBranch}", headBranch="${headBranch}"`, { color: 'red' });
|
|
12062
|
-
// Re-throw the error so the caller can handle it appropriately
|
|
12063
|
-
throw error;
|
|
12064
|
-
}
|
|
12065
|
-
}
|
|
12066
|
-
|
|
12067
12153
|
async function noResult$1({ logger }) {
|
|
12068
12154
|
logger.log('No repo changes detected. 👀', { color: 'blue' });
|
|
12069
12155
|
throw new Error('NO_CHANGES_DETECTED');
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
|
|
|
70
70
|
/**
|
|
71
71
|
* Current build version from package.json
|
|
72
72
|
*/
|
|
73
|
-
const BUILD_VERSION = "0.
|
|
73
|
+
const BUILD_VERSION = "0.22.0";
|
|
74
74
|
|
|
75
75
|
const isInteractive = (config) => {
|
|
76
76
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -1040,6 +1040,15 @@ const schema$1 = {
|
|
|
1040
1040
|
"apiKey": {
|
|
1041
1041
|
"type": "string",
|
|
1042
1042
|
"description": "API key to use when making requests to OpenAI. Defaults to the value of `OPENAI_API_KEY` environment variable."
|
|
1043
|
+
},
|
|
1044
|
+
"verbosity": {
|
|
1045
|
+
"type": "string",
|
|
1046
|
+
"enum": [
|
|
1047
|
+
"low",
|
|
1048
|
+
"medium",
|
|
1049
|
+
"high"
|
|
1050
|
+
],
|
|
1051
|
+
"description": "The verbosity of the model's response."
|
|
1043
1052
|
}
|
|
1044
1053
|
}
|
|
1045
1054
|
},
|
|
@@ -6076,6 +6085,26 @@ const options$4 = {
|
|
|
6076
6085
|
description: 'Generate changelog for all commits since the last tag',
|
|
6077
6086
|
default: false,
|
|
6078
6087
|
},
|
|
6088
|
+
withDiff: {
|
|
6089
|
+
type: 'boolean',
|
|
6090
|
+
description: 'Include the diff for each commit in the prompt',
|
|
6091
|
+
default: false,
|
|
6092
|
+
},
|
|
6093
|
+
onlyDiff: {
|
|
6094
|
+
type: 'boolean',
|
|
6095
|
+
description: 'Generate a changelog based only on the diff of the entire branch',
|
|
6096
|
+
default: false,
|
|
6097
|
+
},
|
|
6098
|
+
additional: {
|
|
6099
|
+
type: 'string',
|
|
6100
|
+
alias: 'a',
|
|
6101
|
+
description: 'Add extra contextual information to the prompt',
|
|
6102
|
+
},
|
|
6103
|
+
author: {
|
|
6104
|
+
type: 'boolean',
|
|
6105
|
+
description: 'Include author attribution in the changelog',
|
|
6106
|
+
default: false,
|
|
6107
|
+
},
|
|
6079
6108
|
i: {
|
|
6080
6109
|
type: 'boolean',
|
|
6081
6110
|
alias: 'interactive',
|
|
@@ -6980,45 +7009,39 @@ const getChangesSinceLastTag = async ({ git }) => {
|
|
|
6980
7009
|
};
|
|
6981
7010
|
|
|
6982
7011
|
/**
|
|
6983
|
-
* Retrieves the commit log range between two specified commits (inclusive of both commits).
|
|
7012
|
+
* Retrieves the detailed commit log range between two specified commits (inclusive of both commits).
|
|
6984
7013
|
*
|
|
6985
7014
|
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6986
7015
|
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6987
7016
|
* @param options - Additional options for retrieving the commit log range.
|
|
6988
|
-
* @returns A promise that resolves to an array of commit
|
|
7017
|
+
* @returns A promise that resolves to an array of commit details objects.
|
|
6989
7018
|
* @throws If there is an error retrieving the commit log range.
|
|
6990
7019
|
*/
|
|
6991
|
-
async function
|
|
7020
|
+
async function getCommitLogRangeDetails(from, to, { noMerges, git }) {
|
|
6992
7021
|
try {
|
|
6993
|
-
// Use from^..to to include the 'from' commit in the range
|
|
6994
|
-
// This works because from^..to means "commits reachable from 'to' but not from the parent of 'from'"
|
|
6995
7022
|
const logOptions = {
|
|
6996
7023
|
from: `${from}^`,
|
|
6997
7024
|
to,
|
|
6998
7025
|
'--no-merges': noMerges
|
|
6999
7026
|
};
|
|
7000
7027
|
const commitLog = await git.log(logOptions);
|
|
7001
|
-
return commitLog.all
|
|
7028
|
+
return [...commitLog.all];
|
|
7002
7029
|
}
|
|
7003
7030
|
catch (error) {
|
|
7004
|
-
// If from^ fails (e.g., 'from' is the first commit), fall back to using from..to and manually adding the 'from' commit
|
|
7005
7031
|
if (error instanceof Error && error.message.includes('unknown revision')) {
|
|
7006
7032
|
try {
|
|
7007
|
-
// Get the 'from' commit separately
|
|
7008
7033
|
const fromCommitLog = await git.log({ from: from, maxCount: 1 });
|
|
7009
7034
|
const fromCommit = fromCommitLog.latest;
|
|
7010
|
-
// Get the range from..to (excluding 'from')
|
|
7011
7035
|
const rangeLogOptions = {
|
|
7012
7036
|
from,
|
|
7013
7037
|
to,
|
|
7014
7038
|
'--no-merges': noMerges
|
|
7015
7039
|
};
|
|
7016
7040
|
const rangeCommitLog = await git.log(rangeLogOptions);
|
|
7017
|
-
// Combine the 'from' commit with the range commits
|
|
7018
7041
|
const allCommits = fromCommit
|
|
7019
7042
|
? [fromCommit, ...rangeCommitLog.all]
|
|
7020
|
-
: rangeCommitLog.all;
|
|
7021
|
-
return allCommits
|
|
7043
|
+
: [...rangeCommitLog.all];
|
|
7044
|
+
return allCommits;
|
|
7022
7045
|
}
|
|
7023
7046
|
catch (fallbackError) {
|
|
7024
7047
|
throw fallbackError;
|
|
@@ -7045,7 +7068,7 @@ async function getCurrentBranchName({ git }) {
|
|
|
7045
7068
|
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
7046
7069
|
* @param {Logger} options.logger - The logger for logging messages.
|
|
7047
7070
|
* @param {string} options.targetBranch - The target branch to compare against.
|
|
7048
|
-
* @returns {Promise<
|
|
7071
|
+
* @returns {Promise<CommitDetails[]>} The array of commit messages in the commit log.
|
|
7049
7072
|
*/
|
|
7050
7073
|
async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
7051
7074
|
try {
|
|
@@ -7064,7 +7087,7 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
7064
7087
|
return [];
|
|
7065
7088
|
}
|
|
7066
7089
|
// Retrieve commit log with messages
|
|
7067
|
-
return await
|
|
7090
|
+
return await getCommitLogRangeDetails(firstCommit, lastCommit, { git, noMerges: true });
|
|
7068
7091
|
}
|
|
7069
7092
|
catch (error) {
|
|
7070
7093
|
logger?.log('Encountered an error getting commit log between branches', { color: 'red' });
|
|
@@ -7080,7 +7103,7 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
7080
7103
|
* @param {Logger} options.logger - The logger for logging messages.
|
|
7081
7104
|
* @param {string} [options.comparisonBranch='main'] - The branch to compare against.
|
|
7082
7105
|
* @param {string} [options.comparisonRemote='origin'] - The remote to compare against.
|
|
7083
|
-
* @returns {Promise<
|
|
7106
|
+
* @returns {Promise<CommitDetails[]>} The array of commit messages in the commit log.
|
|
7084
7107
|
*/
|
|
7085
7108
|
async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main', comparisonRemote = 'origin', }) {
|
|
7086
7109
|
try {
|
|
@@ -7116,7 +7139,7 @@ async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main
|
|
|
7116
7139
|
});
|
|
7117
7140
|
return [];
|
|
7118
7141
|
}
|
|
7119
|
-
return await
|
|
7142
|
+
return await getCommitLogRangeDetails(firstCommit, lastCommit, { git, noMerges: true });
|
|
7120
7143
|
}
|
|
7121
7144
|
catch (error) {
|
|
7122
7145
|
logger?.log('Encountered an error getting commit log from current branch', { color: 'red' });
|
|
@@ -7482,18 +7505,202 @@ async function handleResult({ result, mode, interactiveModeCallback }) {
|
|
|
7482
7505
|
}
|
|
7483
7506
|
}
|
|
7484
7507
|
|
|
7485
|
-
|
|
7508
|
+
/**
|
|
7509
|
+
* Fetches the diff for the given commit ID.
|
|
7510
|
+
*
|
|
7511
|
+
* @param commitId The commit ID for which the diff is to be retrieved.
|
|
7512
|
+
* @returns A promise that resolves to the diff of the commit.
|
|
7513
|
+
*/
|
|
7514
|
+
async function getDiffForCommit(commitId, { git, }) {
|
|
7515
|
+
try {
|
|
7516
|
+
return await git.diff(['-p', `${commitId}^..${commitId}`]);
|
|
7517
|
+
}
|
|
7518
|
+
catch (error) {
|
|
7519
|
+
throw new Error(`Error fetching diff for commit ${commitId}: ${error.message}`);
|
|
7520
|
+
}
|
|
7521
|
+
}
|
|
7486
7522
|
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
-
|
|
7523
|
+
/**
|
|
7524
|
+
* Determines the status of a file based on its changes in the Git repository.
|
|
7525
|
+
*
|
|
7526
|
+
* @param file - The file to check the status of.
|
|
7527
|
+
* @param location - The location to check the status in ('index' or 'working_dir'). Defaults to 'index'.
|
|
7528
|
+
* @returns The status of the file ('added', 'deleted', 'modified', 'renamed', 'untracked', or 'unknown').
|
|
7529
|
+
* @throws Error if the file type is invalid.
|
|
7530
|
+
*/
|
|
7531
|
+
function getStatus(file, location = 'index') {
|
|
7532
|
+
if ('index' in file && 'working_dir' in file) {
|
|
7533
|
+
const statusCode = file[location];
|
|
7534
|
+
switch (statusCode) {
|
|
7535
|
+
case 'A':
|
|
7536
|
+
return 'added';
|
|
7537
|
+
case 'D':
|
|
7538
|
+
return 'deleted';
|
|
7539
|
+
case 'M':
|
|
7540
|
+
return 'modified';
|
|
7541
|
+
case 'R':
|
|
7542
|
+
return 'renamed';
|
|
7543
|
+
case '?':
|
|
7544
|
+
return 'untracked';
|
|
7545
|
+
default:
|
|
7546
|
+
return 'unknown';
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7549
|
+
else if ('changes' in file && 'binary' in file) {
|
|
7550
|
+
if (file.changes === 0)
|
|
7551
|
+
return 'untracked';
|
|
7552
|
+
if (file.file.includes('=>'))
|
|
7553
|
+
return 'renamed';
|
|
7554
|
+
if (file.deletions === 0 && file.insertions > 0)
|
|
7555
|
+
return 'added';
|
|
7556
|
+
if (file.insertions === 0 && file.deletions > 0)
|
|
7557
|
+
return 'deleted';
|
|
7558
|
+
if ((file.insertions > 0 && file.deletions > 0) || file.changes > 0)
|
|
7559
|
+
return 'modified';
|
|
7560
|
+
return 'unknown';
|
|
7561
|
+
}
|
|
7562
|
+
else {
|
|
7563
|
+
throw new Error('Invalid file type');
|
|
7564
|
+
}
|
|
7565
|
+
}
|
|
7492
7566
|
|
|
7567
|
+
/**
|
|
7568
|
+
* Returns the summary text for a file change.
|
|
7569
|
+
*
|
|
7570
|
+
* @param file - The file status or diff result.
|
|
7571
|
+
* @param change - The partial file change object.
|
|
7572
|
+
* @returns The summary text for the file change.
|
|
7573
|
+
* @throws Error if the file type is invalid.
|
|
7574
|
+
*/
|
|
7575
|
+
function getSummaryText(file, change) {
|
|
7576
|
+
const status = change.status || getStatus(file);
|
|
7577
|
+
let filePath;
|
|
7578
|
+
if ('path' in file) {
|
|
7579
|
+
filePath = file.path;
|
|
7580
|
+
}
|
|
7581
|
+
else if ('file' in file) {
|
|
7582
|
+
filePath = change?.filePath || file.file;
|
|
7583
|
+
}
|
|
7584
|
+
else {
|
|
7585
|
+
throw new Error('Invalid file type');
|
|
7586
|
+
}
|
|
7587
|
+
if (change.oldFilePath) {
|
|
7588
|
+
return `${status}: ${change.oldFilePath} -> ${filePath}`;
|
|
7589
|
+
}
|
|
7590
|
+
return `${status}: ${filePath}`;
|
|
7591
|
+
}
|
|
7592
|
+
|
|
7593
|
+
/**
|
|
7594
|
+
* Retrieves the diff between the current branch and a specified target branch.
|
|
7595
|
+
*
|
|
7596
|
+
* @param {Object} options - The options for retrieving the diff.
|
|
7597
|
+
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
7598
|
+
* @param {Logger} options.logger - The logger for logging messages.
|
|
7599
|
+
* @param {string} options.baseBranch - The base branch to compare against.
|
|
7600
|
+
* @param {string} options.headBranch - The head branch to compare.
|
|
7601
|
+
* @param {string[]} options.ignoredFiles - Array of specific files to ignore.
|
|
7602
|
+
* @param {string[]} options.ignoredExtensions - Array of file extensions to ignore.
|
|
7603
|
+
* @returns {Promise<GetChangesResult>} The diff between the current branch and the target branch.
|
|
7604
|
+
*/
|
|
7605
|
+
async function getDiffForBranch({ git, logger, baseBranch, headBranch, options, }) {
|
|
7606
|
+
try {
|
|
7607
|
+
logger?.verbose(`Getting diff for branches: baseBranch="${baseBranch}", headBranch="${headBranch}"`, {
|
|
7608
|
+
color: 'blue',
|
|
7609
|
+
});
|
|
7610
|
+
// Validate branch names
|
|
7611
|
+
if (!baseBranch || !headBranch) {
|
|
7612
|
+
throw new Error(`Invalid branch names: baseBranch="${baseBranch}", headBranch="${headBranch}"`);
|
|
7613
|
+
}
|
|
7614
|
+
const { ignoredFiles = [], ignoredExtensions = [] } = options || {};
|
|
7615
|
+
// Prepare ignore patterns
|
|
7616
|
+
const ignorePatterns = [
|
|
7617
|
+
...ignoredFiles.map((file) => `:!${file}`),
|
|
7618
|
+
...ignoredExtensions.map((ext) => `:!*${ext}`),
|
|
7619
|
+
];
|
|
7620
|
+
// Construct the diff command
|
|
7621
|
+
const diffArgs = [`${baseBranch}..${headBranch}`];
|
|
7622
|
+
if (ignorePatterns.length > 0) {
|
|
7623
|
+
diffArgs.push('--');
|
|
7624
|
+
diffArgs.push(...ignorePatterns);
|
|
7625
|
+
}
|
|
7626
|
+
logger?.verbose(`Running git diff with args: ${diffArgs.join(' ')}`, {
|
|
7627
|
+
color: 'blue',
|
|
7628
|
+
});
|
|
7629
|
+
// Get the diff
|
|
7630
|
+
const diff = await git.diff(diffArgs);
|
|
7631
|
+
logger?.verbose(`Generated diff between "${headBranch}" and "${baseBranch}"`, {
|
|
7632
|
+
color: 'blue',
|
|
7633
|
+
});
|
|
7634
|
+
const changes = diff.split('diff --git').slice(1).map((fileDiff) => {
|
|
7635
|
+
const lines = fileDiff.split('\n');
|
|
7636
|
+
const filePathLine = lines[0];
|
|
7637
|
+
const filePath = filePathLine.split('b/')[1]?.split(' ')[0];
|
|
7638
|
+
const oldFilePath = filePathLine.split('a/')[1]?.split(' ')[0];
|
|
7639
|
+
// Determine status based on diff headers
|
|
7640
|
+
let status = 'modified';
|
|
7641
|
+
if (fileDiff.includes('new file mode')) {
|
|
7642
|
+
status = 'added';
|
|
7643
|
+
}
|
|
7644
|
+
else if (fileDiff.includes('deleted file mode')) {
|
|
7645
|
+
status = 'deleted';
|
|
7646
|
+
}
|
|
7647
|
+
else if (fileDiff.includes('rename from')) {
|
|
7648
|
+
status = 'renamed';
|
|
7649
|
+
}
|
|
7650
|
+
return {
|
|
7651
|
+
filePath: filePath || '',
|
|
7652
|
+
oldFilePath: oldFilePath || '',
|
|
7653
|
+
status,
|
|
7654
|
+
summary: getSummaryText({ path: filePath || '', index: '', working_dir: '' }, { filePath: filePath || '', status }),
|
|
7655
|
+
};
|
|
7656
|
+
});
|
|
7657
|
+
return {
|
|
7658
|
+
staged: changes,
|
|
7659
|
+
unstaged: [],
|
|
7660
|
+
untracked: [],
|
|
7661
|
+
};
|
|
7662
|
+
}
|
|
7663
|
+
catch (error) {
|
|
7664
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7665
|
+
console.error('Error in getDiffForBranch:', error);
|
|
7666
|
+
logger?.log(`Encountered an error getting diff between branches: ${errorMessage}`, { color: 'red' });
|
|
7667
|
+
logger?.log(`Branch details: baseBranch="${baseBranch}", headBranch="${headBranch}"`, { color: 'red' });
|
|
7668
|
+
// Re-throw the error so the caller can handle it appropriately
|
|
7669
|
+
throw error;
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7672
|
+
|
|
7673
|
+
const template$3 = `You are a highly skilled software engineer tasked with writing a git changelog. Your response should be informative, well-structured, and in the imperative.
|
|
7674
|
+
|
|
7675
|
+
## Input
|
|
7676
|
+
You will be provided with a summary of changes. This summary can be one of the following:
|
|
7677
|
+
1. A list of commits, each with its author, hash, message, and body.
|
|
7678
|
+
2. A list of commits, each with its details AND the full diff of the changes.
|
|
7679
|
+
3. A single, comprehensive diff for an entire branch.
|
|
7680
|
+
|
|
7681
|
+
## Rules
|
|
7682
|
+
- Create a descriptive title for the changelog that gives a high-level overview of the changes.
|
|
7683
|
+
- **BREAKING CHANGES**: Identify any commits that introduce breaking changes. These must be listed first under a "### 💥 BREAKING CHANGES" heading.
|
|
7684
|
+
- **Grouping**: Logically group related changes under descriptive headings (e.g., ### Features, ### Fixes, ### Refactors).
|
|
7685
|
+
- **Dependencies**: Group all dependency updates (e.g., changes to package.json, go.mod) under a "### Dependencies" section.
|
|
7686
|
+
- **Summaries**: For each change, provide a concise summary.
|
|
7687
|
+
- **Attribution**: {{author_instructions}}
|
|
7688
|
+
- **Technical Details**: If provided with diffs, use them to understand the technical details and provide a more accurate and detailed description of the changes.
|
|
7689
|
+
- **Clarity**: Avoid generalizations like "various bug fixes," "improvements," or "enhancements." Be specific.
|
|
7690
|
+
- **Formatting**: Your entire response must be valid Markdown.
|
|
7691
|
+
|
|
7692
|
+
## Formatting Instructions
|
|
7493
7693
|
{{format_instructions}}
|
|
7494
7694
|
|
|
7695
|
+
{{additional_context}}
|
|
7696
|
+
|
|
7495
7697
|
"""{{summary}}"""`;
|
|
7496
|
-
const inputVariables$2 = [
|
|
7698
|
+
const inputVariables$2 = [
|
|
7699
|
+
'format_instructions',
|
|
7700
|
+
'summary',
|
|
7701
|
+
'additional_context',
|
|
7702
|
+
'author_instructions',
|
|
7703
|
+
];
|
|
7497
7704
|
const CHANGELOG_PROMPT = new prompts$1.PromptTemplate({
|
|
7498
7705
|
template: template$3,
|
|
7499
7706
|
inputVariables: inputVariables$2,
|
|
@@ -7517,48 +7724,68 @@ const handler$4 = async (argv, logger) => {
|
|
|
7517
7724
|
}
|
|
7518
7725
|
async function factory() {
|
|
7519
7726
|
const branchName = await getCurrentBranchName({ git });
|
|
7520
|
-
if (
|
|
7521
|
-
logger.verbose(`Generating
|
|
7727
|
+
if (argv.onlyDiff) {
|
|
7728
|
+
logger.verbose(`Generating changelog based on branch diff`, { color: 'yellow' });
|
|
7729
|
+
const diff = await getDiffForBranch({ git, logger, baseBranch: argv.branch || 'main', headBranch: branchName });
|
|
7522
7730
|
return {
|
|
7523
7731
|
branch: branchName,
|
|
7524
|
-
|
|
7732
|
+
diff: JSON.stringify(diff.staged, null, 2),
|
|
7525
7733
|
};
|
|
7526
7734
|
}
|
|
7527
|
-
|
|
7735
|
+
let commits = [];
|
|
7736
|
+
if (config.sinceLastTag) {
|
|
7737
|
+
logger.verbose(`Generating commit log since the last tag`, { color: 'yellow' });
|
|
7738
|
+
// This function returns string[], needs to be adapted or replaced
|
|
7739
|
+
// For now, this path will have limited details.
|
|
7740
|
+
const commitMessages = await getChangesSinceLastTag({ git, logger });
|
|
7741
|
+
commits = commitMessages.map(msg => ({ message: msg }));
|
|
7742
|
+
}
|
|
7743
|
+
else if (config.range && config.range.includes(':')) {
|
|
7528
7744
|
const [from, to] = config.range.split(':');
|
|
7529
7745
|
if (!from || !to) {
|
|
7530
7746
|
logger.log(`Invalid range provided. Expected format is <from>:<to>`, { color: 'red' });
|
|
7531
7747
|
process.exit(1);
|
|
7532
7748
|
}
|
|
7533
|
-
|
|
7534
|
-
branch: branchName,
|
|
7535
|
-
commits: await getCommitLogRange(from, to, { git, noMerges: true }),
|
|
7536
|
-
};
|
|
7749
|
+
commits = await getCommitLogRangeDetails(from, to, { git, noMerges: true });
|
|
7537
7750
|
}
|
|
7538
|
-
if (argv.branch) {
|
|
7751
|
+
else if (argv.branch) {
|
|
7539
7752
|
logger.verbose(`Generating commit log against branch: ${argv.branch}`, { color: 'yellow' });
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7753
|
+
commits = await getCommitLogAgainstBranch({ git, logger, targetBranch: argv.branch });
|
|
7754
|
+
}
|
|
7755
|
+
else {
|
|
7756
|
+
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
7757
|
+
color: 'yellow',
|
|
7758
|
+
});
|
|
7759
|
+
commits = await getCommitLogCurrentBranch({ git, logger });
|
|
7760
|
+
}
|
|
7761
|
+
let commitsWithDiffText = commits;
|
|
7762
|
+
if (argv.withDiff) {
|
|
7763
|
+
commitsWithDiffText = await Promise.all(commits.map(async (commit) => ({
|
|
7764
|
+
...commit,
|
|
7765
|
+
diffText: await getDiffForCommit(commit.hash, { git }),
|
|
7766
|
+
})));
|
|
7544
7767
|
}
|
|
7545
|
-
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
7546
|
-
color: 'yellow',
|
|
7547
|
-
});
|
|
7548
|
-
const commits = await getCommitLogCurrentBranch({ git, logger });
|
|
7549
7768
|
return {
|
|
7550
7769
|
branch: branchName,
|
|
7551
|
-
commits,
|
|
7770
|
+
commits: commitsWithDiffText,
|
|
7771
|
+
withDiff: argv.withDiff,
|
|
7552
7772
|
};
|
|
7553
7773
|
}
|
|
7554
|
-
async function parser(
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
result = `## ${branch}\n\nNo commits found.`;
|
|
7774
|
+
async function parser(data) {
|
|
7775
|
+
if (data.diff) {
|
|
7776
|
+
return `## Diff for ${data.branch}\n\n${data.diff}`;
|
|
7558
7777
|
}
|
|
7559
|
-
|
|
7560
|
-
|
|
7778
|
+
if (!data.commits || data.commits.length === 0) {
|
|
7779
|
+
return `## ${data.branch}\n\nNo commits found.`;
|
|
7561
7780
|
}
|
|
7781
|
+
let result = `## ${data.branch}\n\n`;
|
|
7782
|
+
result += data.commits.map(commit => {
|
|
7783
|
+
let commitStr = `Author: ${commit.author_name}\nCommit: ${commit.hash}\nMessage: ${commit.message}\n${commit.body}`;
|
|
7784
|
+
if (data.withDiff && commit.diffText) {
|
|
7785
|
+
commitStr += `\nDiff:\n${commit.diffText}`;
|
|
7786
|
+
}
|
|
7787
|
+
return commitStr.trim();
|
|
7788
|
+
}).join('\n\n---\n\n');
|
|
7562
7789
|
return result;
|
|
7563
7790
|
}
|
|
7564
7791
|
const changelogMsg = await generateAndReviewLoop({
|
|
@@ -7582,12 +7809,21 @@ const handler$4 = async (argv, logger) => {
|
|
|
7582
7809
|
fallback: CHANGELOG_PROMPT,
|
|
7583
7810
|
});
|
|
7584
7811
|
const formatInstructions = "Only respond with a valid JSON object, containing two fields: 'title' an escaped string, no more than 65 characters, and 'content' also an escaped string.";
|
|
7812
|
+
let additional_context = '';
|
|
7813
|
+
if (argv.additional) {
|
|
7814
|
+
additional_context = `## Additional Context\n${argv.additional}`;
|
|
7815
|
+
}
|
|
7816
|
+
const author_instructions = argv.author
|
|
7817
|
+
? 'At the end of each item, attribute the author and include a reference to the commit hash, like this: `by @author_name (f6dbe61)`. Use the first 7 characters of the hash.'
|
|
7818
|
+
: 'At the end of each item, include a reference to the commit hash, like this: `(f6dbe61)`. Use the first 7 characters of the hash.';
|
|
7585
7819
|
const changelog = await executeChain({
|
|
7586
7820
|
llm,
|
|
7587
7821
|
prompt,
|
|
7588
7822
|
variables: {
|
|
7589
7823
|
summary: context,
|
|
7590
7824
|
format_instructions: formatInstructions,
|
|
7825
|
+
additional_context: additional_context,
|
|
7826
|
+
author_instructions: author_instructions,
|
|
7591
7827
|
},
|
|
7592
7828
|
parser,
|
|
7593
7829
|
});
|
|
@@ -10899,76 +11135,6 @@ async function createCommit(message, git) {
|
|
|
10899
11135
|
return await git.commit(message);
|
|
10900
11136
|
}
|
|
10901
11137
|
|
|
10902
|
-
/**
|
|
10903
|
-
* Determines the status of a file based on its changes in the Git repository.
|
|
10904
|
-
*
|
|
10905
|
-
* @param file - The file to check the status of.
|
|
10906
|
-
* @param location - The location to check the status in ('index' or 'working_dir'). Defaults to 'index'.
|
|
10907
|
-
* @returns The status of the file ('added', 'deleted', 'modified', 'renamed', 'untracked', or 'unknown').
|
|
10908
|
-
* @throws Error if the file type is invalid.
|
|
10909
|
-
*/
|
|
10910
|
-
function getStatus(file, location = 'index') {
|
|
10911
|
-
if ('index' in file && 'working_dir' in file) {
|
|
10912
|
-
const statusCode = file[location];
|
|
10913
|
-
switch (statusCode) {
|
|
10914
|
-
case 'A':
|
|
10915
|
-
return 'added';
|
|
10916
|
-
case 'D':
|
|
10917
|
-
return 'deleted';
|
|
10918
|
-
case 'M':
|
|
10919
|
-
return 'modified';
|
|
10920
|
-
case 'R':
|
|
10921
|
-
return 'renamed';
|
|
10922
|
-
case '?':
|
|
10923
|
-
return 'untracked';
|
|
10924
|
-
default:
|
|
10925
|
-
return 'unknown';
|
|
10926
|
-
}
|
|
10927
|
-
}
|
|
10928
|
-
else if ('changes' in file && 'binary' in file) {
|
|
10929
|
-
if (file.changes === 0)
|
|
10930
|
-
return 'untracked';
|
|
10931
|
-
if (file.file.includes('=>'))
|
|
10932
|
-
return 'renamed';
|
|
10933
|
-
if (file.deletions === 0 && file.insertions > 0)
|
|
10934
|
-
return 'added';
|
|
10935
|
-
if (file.insertions === 0 && file.deletions > 0)
|
|
10936
|
-
return 'deleted';
|
|
10937
|
-
if ((file.insertions > 0 && file.deletions > 0) || file.changes > 0)
|
|
10938
|
-
return 'modified';
|
|
10939
|
-
return 'unknown';
|
|
10940
|
-
}
|
|
10941
|
-
else {
|
|
10942
|
-
throw new Error('Invalid file type');
|
|
10943
|
-
}
|
|
10944
|
-
}
|
|
10945
|
-
|
|
10946
|
-
/**
|
|
10947
|
-
* Returns the summary text for a file change.
|
|
10948
|
-
*
|
|
10949
|
-
* @param file - The file status or diff result.
|
|
10950
|
-
* @param change - The partial file change object.
|
|
10951
|
-
* @returns The summary text for the file change.
|
|
10952
|
-
* @throws Error if the file type is invalid.
|
|
10953
|
-
*/
|
|
10954
|
-
function getSummaryText(file, change) {
|
|
10955
|
-
const status = change.status || getStatus(file);
|
|
10956
|
-
let filePath;
|
|
10957
|
-
if ('path' in file) {
|
|
10958
|
-
filePath = file.path;
|
|
10959
|
-
}
|
|
10960
|
-
else if ('file' in file) {
|
|
10961
|
-
filePath = change?.filePath || file.file;
|
|
10962
|
-
}
|
|
10963
|
-
else {
|
|
10964
|
-
throw new Error('Invalid file type');
|
|
10965
|
-
}
|
|
10966
|
-
if (change.oldFilePath) {
|
|
10967
|
-
return `${status}: ${change.oldFilePath} -> ${filePath}`;
|
|
10968
|
-
}
|
|
10969
|
-
return `${status}: ${filePath}`;
|
|
10970
|
-
}
|
|
10971
|
-
|
|
10972
11138
|
/**
|
|
10973
11139
|
* Retrieves the changes in the Git repository.
|
|
10974
11140
|
*
|
|
@@ -12006,86 +12172,6 @@ const getChangesByTimestamp = async ({ since, git }) => {
|
|
|
12006
12172
|
return formatCommitLog(commitLog);
|
|
12007
12173
|
};
|
|
12008
12174
|
|
|
12009
|
-
/**
|
|
12010
|
-
* Retrieves the diff between the current branch and a specified target branch.
|
|
12011
|
-
*
|
|
12012
|
-
* @param {Object} options - The options for retrieving the diff.
|
|
12013
|
-
* @param {SimpleGit} options.git - The SimpleGit instance.
|
|
12014
|
-
* @param {Logger} options.logger - The logger for logging messages.
|
|
12015
|
-
* @param {string} options.baseBranch - The base branch to compare against.
|
|
12016
|
-
* @param {string} options.headBranch - The head branch to compare.
|
|
12017
|
-
* @param {string[]} options.ignoredFiles - Array of specific files to ignore.
|
|
12018
|
-
* @param {string[]} options.ignoredExtensions - Array of file extensions to ignore.
|
|
12019
|
-
* @returns {Promise<GetChangesResult>} The diff between the current branch and the target branch.
|
|
12020
|
-
*/
|
|
12021
|
-
async function getDiffForBranch({ git, logger, baseBranch, headBranch, options, }) {
|
|
12022
|
-
try {
|
|
12023
|
-
logger?.verbose(`Getting diff for branches: baseBranch="${baseBranch}", headBranch="${headBranch}"`, {
|
|
12024
|
-
color: 'blue',
|
|
12025
|
-
});
|
|
12026
|
-
// Validate branch names
|
|
12027
|
-
if (!baseBranch || !headBranch) {
|
|
12028
|
-
throw new Error(`Invalid branch names: baseBranch="${baseBranch}", headBranch="${headBranch}"`);
|
|
12029
|
-
}
|
|
12030
|
-
const { ignoredFiles = [], ignoredExtensions = [] } = options || {};
|
|
12031
|
-
// Prepare ignore patterns
|
|
12032
|
-
const ignorePatterns = [
|
|
12033
|
-
...ignoredFiles.map((file) => `:!${file}`),
|
|
12034
|
-
...ignoredExtensions.map((ext) => `:!*${ext}`),
|
|
12035
|
-
];
|
|
12036
|
-
// Construct the diff command
|
|
12037
|
-
const diffArgs = [`${baseBranch}..${headBranch}`];
|
|
12038
|
-
if (ignorePatterns.length > 0) {
|
|
12039
|
-
diffArgs.push('--');
|
|
12040
|
-
diffArgs.push(...ignorePatterns);
|
|
12041
|
-
}
|
|
12042
|
-
logger?.verbose(`Running git diff with args: ${diffArgs.join(' ')}`, {
|
|
12043
|
-
color: 'blue',
|
|
12044
|
-
});
|
|
12045
|
-
// Get the diff
|
|
12046
|
-
const diff = await git.diff(diffArgs);
|
|
12047
|
-
logger?.verbose(`Generated diff between "${headBranch}" and "${baseBranch}"`, {
|
|
12048
|
-
color: 'blue',
|
|
12049
|
-
});
|
|
12050
|
-
const changes = diff.split('diff --git').slice(1).map((fileDiff) => {
|
|
12051
|
-
const lines = fileDiff.split('\n');
|
|
12052
|
-
const filePathLine = lines[0];
|
|
12053
|
-
const filePath = filePathLine.split('b/')[1]?.split(' ')[0];
|
|
12054
|
-
const oldFilePath = filePathLine.split('a/')[1]?.split(' ')[0];
|
|
12055
|
-
// Determine status based on diff headers
|
|
12056
|
-
let status = 'modified';
|
|
12057
|
-
if (fileDiff.includes('new file mode')) {
|
|
12058
|
-
status = 'added';
|
|
12059
|
-
}
|
|
12060
|
-
else if (fileDiff.includes('deleted file mode')) {
|
|
12061
|
-
status = 'deleted';
|
|
12062
|
-
}
|
|
12063
|
-
else if (fileDiff.includes('rename from')) {
|
|
12064
|
-
status = 'renamed';
|
|
12065
|
-
}
|
|
12066
|
-
return {
|
|
12067
|
-
filePath: filePath || '',
|
|
12068
|
-
oldFilePath: oldFilePath || '',
|
|
12069
|
-
status,
|
|
12070
|
-
summary: getSummaryText({ path: filePath || '', index: '', working_dir: '' }, { filePath: filePath || '', status }),
|
|
12071
|
-
};
|
|
12072
|
-
});
|
|
12073
|
-
return {
|
|
12074
|
-
staged: changes,
|
|
12075
|
-
unstaged: [],
|
|
12076
|
-
untracked: [],
|
|
12077
|
-
};
|
|
12078
|
-
}
|
|
12079
|
-
catch (error) {
|
|
12080
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
12081
|
-
console.error('Error in getDiffForBranch:', error);
|
|
12082
|
-
logger?.log(`Encountered an error getting diff between branches: ${errorMessage}`, { color: 'red' });
|
|
12083
|
-
logger?.log(`Branch details: baseBranch="${baseBranch}", headBranch="${headBranch}"`, { color: 'red' });
|
|
12084
|
-
// Re-throw the error so the caller can handle it appropriately
|
|
12085
|
-
throw error;
|
|
12086
|
-
}
|
|
12087
|
-
}
|
|
12088
|
-
|
|
12089
12175
|
async function noResult$1({ logger }) {
|
|
12090
12176
|
logger.log('No repo changes detected. 👀', { color: 'blue' });
|
|
12091
12177
|
throw new Error('NO_CHANGES_DETECTED');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-coco",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "zero-effort git commits with coco.",
|
|
5
5
|
"author": "gfargo <ghfargo@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
66
66
|
"rollup-plugin-preserve-shebangs": "^0.2.0",
|
|
67
67
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
68
|
-
"rollup-plugin-visualizer": "^
|
|
68
|
+
"rollup-plugin-visualizer": "^6.0.3",
|
|
69
69
|
"ts-jest": "^29.1.0",
|
|
70
70
|
"ts-json-schema-generator": "^2.3.0",
|
|
71
71
|
"ts-node": "^10.9.1",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@langchain/community": "^0.3.32",
|
|
82
82
|
"@langchain/core": "^0.3.40",
|
|
83
83
|
"@langchain/ollama": "^0.2.0",
|
|
84
|
-
"@langchain/openai": "^0.
|
|
84
|
+
"@langchain/openai": "^0.6.7",
|
|
85
85
|
"ajv": "^8.16.0",
|
|
86
86
|
"chalk": "4.1.2",
|
|
87
87
|
"diff": "8.0.2",
|