git-coco 0.14.8 → 0.14.9
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 +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.mjs +192 -60
- package/dist/index.js +191 -59
- package/package.json +5 -5
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -150,6 +150,7 @@ interface BaseCommandOptions extends BaseArgvOptions {
|
|
|
150
150
|
interface ChangelogOptions extends BaseCommandOptions {
|
|
151
151
|
range: string;
|
|
152
152
|
branch: string;
|
|
153
|
+
sinceLastTag: boolean;
|
|
153
154
|
}
|
|
154
155
|
type ChangelogArgv = Arguments<ChangelogOptions>;
|
|
155
156
|
|
|
@@ -166,6 +167,7 @@ interface CommitOptions extends BaseCommandOptions {
|
|
|
166
167
|
openInEditor: boolean;
|
|
167
168
|
ignoredFiles: string[];
|
|
168
169
|
ignoredExtensions: string[];
|
|
170
|
+
withPreviousCommits: number;
|
|
169
171
|
}
|
|
170
172
|
type CommitArgv = Arguments<CommitOptions>;
|
|
171
173
|
|
package/dist/index.esm.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import prettyMilliseconds from 'pretty-ms';
|
|
|
18
18
|
import { ChatAnthropic } from '@langchain/anthropic';
|
|
19
19
|
import { ChatOllama } from '@langchain/ollama';
|
|
20
20
|
import { ChatOpenAI } from '@langchain/openai';
|
|
21
|
-
import { JsonOutputParser, BaseOutputParser } from '@langchain/core/output_parsers';
|
|
21
|
+
import { JsonOutputParser, BaseOutputParser, StringOutputParser } from '@langchain/core/output_parsers';
|
|
22
22
|
import { simpleGit } from 'simple-git';
|
|
23
23
|
import pQueue from 'p-queue';
|
|
24
24
|
import { Document, BaseDocumentTransformer } from '@langchain/core/documents';
|
|
@@ -55,7 +55,7 @@ import * as readline from 'readline';
|
|
|
55
55
|
/**
|
|
56
56
|
* Current build version from package.json
|
|
57
57
|
*/
|
|
58
|
-
const BUILD_VERSION = "0.14.
|
|
58
|
+
const BUILD_VERSION = "0.14.9";
|
|
59
59
|
|
|
60
60
|
const isInteractive = (config) => {
|
|
61
61
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -1860,6 +1860,12 @@ const options$4 = {
|
|
|
1860
1860
|
alias: 'b',
|
|
1861
1861
|
description: 'Target branch to compare against',
|
|
1862
1862
|
},
|
|
1863
|
+
sinceLastTag: {
|
|
1864
|
+
type: 'boolean',
|
|
1865
|
+
alias: 't',
|
|
1866
|
+
description: 'Generate changelog for all commits since the last tag',
|
|
1867
|
+
default: false,
|
|
1868
|
+
},
|
|
1863
1869
|
i: {
|
|
1864
1870
|
type: 'boolean',
|
|
1865
1871
|
alias: 'interactive',
|
|
@@ -1912,6 +1918,7 @@ function getPrompt({ template, variables, fallback }) {
|
|
|
1912
1918
|
? new PromptTemplate({
|
|
1913
1919
|
template,
|
|
1914
1920
|
inputVariables: variables,
|
|
1921
|
+
templateFormat: 'mustache',
|
|
1915
1922
|
})
|
|
1916
1923
|
: fallback);
|
|
1917
1924
|
}
|
|
@@ -1942,6 +1949,35 @@ function extractTicketIdFromBranchName(branchName) {
|
|
|
1942
1949
|
return match ? match[0] : null;
|
|
1943
1950
|
}
|
|
1944
1951
|
|
|
1952
|
+
/**
|
|
1953
|
+
* Formats a commit log into a readable string format.
|
|
1954
|
+
*
|
|
1955
|
+
* @param commitLog - The commit log result containing an array of commit details.
|
|
1956
|
+
* @returns An array of formatted commit log strings.
|
|
1957
|
+
*
|
|
1958
|
+
* Each formatted string includes:
|
|
1959
|
+
* - The date of the commit in square brackets.
|
|
1960
|
+
* - The commit message.
|
|
1961
|
+
* - The commit body.
|
|
1962
|
+
* - The commit hash in parentheses.
|
|
1963
|
+
* - The author's name and email in angle brackets.
|
|
1964
|
+
*/
|
|
1965
|
+
const formatCommitLog = (commitLog) => {
|
|
1966
|
+
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
1967
|
+
};
|
|
1968
|
+
|
|
1969
|
+
const getChangesSinceLastTag = async ({ git }) => {
|
|
1970
|
+
const tags = await git.tags();
|
|
1971
|
+
if (tags.all.length > 0) {
|
|
1972
|
+
const lastTag = tags.latest;
|
|
1973
|
+
const commitLog = await git.log({ from: lastTag });
|
|
1974
|
+
return formatCommitLog(commitLog);
|
|
1975
|
+
}
|
|
1976
|
+
else {
|
|
1977
|
+
return ['No tags found in the repository.'];
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
|
|
1945
1981
|
/**
|
|
1946
1982
|
* Retrieves the commit log range between two specified commits.
|
|
1947
1983
|
*
|
|
@@ -2075,8 +2111,17 @@ const getRepo = () => {
|
|
|
2075
2111
|
return git;
|
|
2076
2112
|
};
|
|
2077
2113
|
|
|
2078
|
-
|
|
2079
|
-
|
|
2114
|
+
/**
|
|
2115
|
+
* Template for generating git commit messages based on code changes
|
|
2116
|
+
*
|
|
2117
|
+
* Variables:
|
|
2118
|
+
* - summary: Contains the diff summary of staged changes
|
|
2119
|
+
* - format_instructions: Instructions for the output format (JSON with title and body)
|
|
2120
|
+
* - additional_context: Optional user-provided context to guide the commit message generation
|
|
2121
|
+
* - commit_history: Optional history of previous commits for context
|
|
2122
|
+
*/
|
|
2123
|
+
const template$4 = `Write informative git commit message, in the imperative, based on the diffs & file changes provided in the "Diff Summary" section.
|
|
2124
|
+
Commit Messages must have a short description that is less than 50 characters and a longer detailed summary around 300 characters, the shorter and more concise the better.
|
|
2080
2125
|
|
|
2081
2126
|
Please follow the guidelines below when writing your commit message:
|
|
2082
2127
|
|
|
@@ -2088,13 +2133,16 @@ Please follow the guidelines below when writing your commit message:
|
|
|
2088
2133
|
|
|
2089
2134
|
{format_instructions}
|
|
2090
2135
|
|
|
2136
|
+
{commit_history}
|
|
2137
|
+
|
|
2091
2138
|
""""""
|
|
2092
2139
|
{summary}
|
|
2093
2140
|
""""""
|
|
2094
2141
|
|
|
2095
|
-
{
|
|
2142
|
+
{additional_context}
|
|
2096
2143
|
`;
|
|
2097
|
-
|
|
2144
|
+
// Define the variables that will be passed to the prompt template
|
|
2145
|
+
const inputVariables$3 = ['summary', 'format_instructions', 'additional_context', 'commit_history'];
|
|
2098
2146
|
const COMMIT_PROMPT = new PromptTemplate({
|
|
2099
2147
|
template: template$4,
|
|
2100
2148
|
inputVariables: inputVariables$3,
|
|
@@ -2260,9 +2308,16 @@ async function generateAndReviewLoop({ label, factory, parser, noResult, agent,
|
|
|
2260
2308
|
result = '';
|
|
2261
2309
|
continue;
|
|
2262
2310
|
}
|
|
2311
|
+
// Only edit the result in interactive mode if approved
|
|
2312
|
+
result = await editResult(result, options);
|
|
2313
|
+
}
|
|
2314
|
+
else {
|
|
2315
|
+
// In non-interactive mode, we return the result as is to be output to stdout by the caller.
|
|
2316
|
+
const displayResult = reviewParser ? reviewParser(result, options) : result;
|
|
2317
|
+
// In non-interactive mode, ensure we return the properly formatted result
|
|
2318
|
+
result = displayResult;
|
|
2263
2319
|
}
|
|
2264
2320
|
// if we're here, we're done.
|
|
2265
|
-
result = await editResult(result, options);
|
|
2266
2321
|
continueLoop = false;
|
|
2267
2322
|
}
|
|
2268
2323
|
return result;
|
|
@@ -2285,7 +2340,8 @@ async function handleResult({ result, mode, interactiveModeCallback }) {
|
|
|
2285
2340
|
break;
|
|
2286
2341
|
case 'stdout':
|
|
2287
2342
|
default:
|
|
2288
|
-
|
|
2343
|
+
// Ensure we write the result to stdout in non-interactive mode
|
|
2344
|
+
process.stdout.write(result + '\n', 'utf8');
|
|
2289
2345
|
break;
|
|
2290
2346
|
}
|
|
2291
2347
|
process.exit(0);
|
|
@@ -2324,6 +2380,13 @@ const handler$4 = async (argv, logger) => {
|
|
|
2324
2380
|
}
|
|
2325
2381
|
async function factory() {
|
|
2326
2382
|
const branchName = await getCurrentBranchName({ git });
|
|
2383
|
+
if (config.sinceLastTag) {
|
|
2384
|
+
logger.verbose(`Generating commit log since the last tag`, { color: 'yellow' });
|
|
2385
|
+
return {
|
|
2386
|
+
branch: branchName,
|
|
2387
|
+
commits: await getChangesSinceLastTag({ git, logger }),
|
|
2388
|
+
};
|
|
2389
|
+
}
|
|
2327
2390
|
if (config.range && config.range.includes(':')) {
|
|
2328
2391
|
const [from, to] = config.range.split(':');
|
|
2329
2392
|
if (!from || !to) {
|
|
@@ -2342,7 +2405,7 @@ const handler$4 = async (argv, logger) => {
|
|
|
2342
2405
|
commits: await getCommitLogAgainstBranch({ git, logger, targetBranch: argv.branch }),
|
|
2343
2406
|
};
|
|
2344
2407
|
}
|
|
2345
|
-
logger.verbose(`No range or
|
|
2408
|
+
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, { color: 'yellow' });
|
|
2346
2409
|
return {
|
|
2347
2410
|
branch: branchName,
|
|
2348
2411
|
commits: await getCommitLogCurrentBranch({ git, logger }),
|
|
@@ -2414,7 +2477,7 @@ const handler$4 = async (argv, logger) => {
|
|
|
2414
2477
|
|
|
2415
2478
|
var changelog = {
|
|
2416
2479
|
command: command$4,
|
|
2417
|
-
desc: 'Generate a changelog from current or target branch
|
|
2480
|
+
desc: 'Generate a changelog from current or target branch, provided commit range, or since the last tag.',
|
|
2418
2481
|
builder: builder$4,
|
|
2419
2482
|
handler: commandExecutor(handler$4),
|
|
2420
2483
|
options: options$4,
|
|
@@ -2452,6 +2515,12 @@ const options$3 = {
|
|
|
2452
2515
|
type: 'string',
|
|
2453
2516
|
alias: 'a',
|
|
2454
2517
|
},
|
|
2518
|
+
withPreviousCommits: {
|
|
2519
|
+
description: 'Include previous commits as context (specify number of commits, 0 for none)',
|
|
2520
|
+
type: 'number',
|
|
2521
|
+
default: 0,
|
|
2522
|
+
alias: 'p',
|
|
2523
|
+
},
|
|
2455
2524
|
};
|
|
2456
2525
|
const builder$3 = (yargs) => {
|
|
2457
2526
|
return yargs.options(options$3).usage(getCommandUsageHeader(command$3));
|
|
@@ -6189,6 +6258,48 @@ async function getChanges({ git, options }) {
|
|
|
6189
6258
|
};
|
|
6190
6259
|
}
|
|
6191
6260
|
|
|
6261
|
+
/**
|
|
6262
|
+
* Format a single commit log entry into a readable string
|
|
6263
|
+
* @param commit - The commit log entry
|
|
6264
|
+
* @returns Formatted commit log string
|
|
6265
|
+
*/
|
|
6266
|
+
function formatSingleCommit(commit) {
|
|
6267
|
+
const { hash, date, message, body, author_name } = commit;
|
|
6268
|
+
const shortHash = hash.substring(0, 7);
|
|
6269
|
+
return `Commit: ${shortHash}
|
|
6270
|
+
Author: ${author_name}
|
|
6271
|
+
Date: ${date}
|
|
6272
|
+
Message: ${message}
|
|
6273
|
+
${body ? `\nDetails: ${body}` : ''}`;
|
|
6274
|
+
}
|
|
6275
|
+
|
|
6276
|
+
/**
|
|
6277
|
+
* Get the specified number of previous commits
|
|
6278
|
+
* @param options - Options for getting previous commits
|
|
6279
|
+
* @returns Formatted commit logs
|
|
6280
|
+
*/
|
|
6281
|
+
async function getPreviousCommits(options) {
|
|
6282
|
+
const { git, count = 1 } = options;
|
|
6283
|
+
if (count <= 0) {
|
|
6284
|
+
return '';
|
|
6285
|
+
}
|
|
6286
|
+
try {
|
|
6287
|
+
const logs = await git.log({ maxCount: count });
|
|
6288
|
+
if (!logs || logs.total === 0) {
|
|
6289
|
+
return '';
|
|
6290
|
+
}
|
|
6291
|
+
// Format the commit logs
|
|
6292
|
+
const formattedLogs = logs.all.map((commit) => {
|
|
6293
|
+
return formatSingleCommit(commit);
|
|
6294
|
+
}).join('\n\n');
|
|
6295
|
+
return formattedLogs;
|
|
6296
|
+
}
|
|
6297
|
+
catch (error) {
|
|
6298
|
+
console.error(`Error getting previous commits: ${error.message}`);
|
|
6299
|
+
return '';
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
|
|
6192
6303
|
/**
|
|
6193
6304
|
* Retrieves a TikToken for the specified model.
|
|
6194
6305
|
*
|
|
@@ -6302,14 +6413,30 @@ const handler$3 = async (argv, logger) => {
|
|
|
6302
6413
|
fallback: COMMIT_PROMPT,
|
|
6303
6414
|
});
|
|
6304
6415
|
const formatInstructions = "Respond with a valid JSON object, containing two fields: 'title' and 'body', both strings.";
|
|
6305
|
-
|
|
6416
|
+
// Get additional context if provided
|
|
6417
|
+
let additional_context = '';
|
|
6418
|
+
if (argv.additional) {
|
|
6419
|
+
additional_context = `## Additional Context\n${argv.additional}`;
|
|
6420
|
+
}
|
|
6421
|
+
// Get commit history if requested
|
|
6422
|
+
let commit_history = '';
|
|
6423
|
+
if (argv.withPreviousCommits > 0) {
|
|
6424
|
+
const commitHistoryData = await getPreviousCommits({
|
|
6425
|
+
git,
|
|
6426
|
+
count: argv.withPreviousCommits
|
|
6427
|
+
});
|
|
6428
|
+
if (commitHistoryData) {
|
|
6429
|
+
commit_history = `## Commit History\n${commitHistoryData}`;
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6306
6432
|
const commitMsg = await executeChain({
|
|
6307
6433
|
llm,
|
|
6308
6434
|
prompt,
|
|
6309
6435
|
variables: {
|
|
6310
6436
|
summary: context,
|
|
6311
6437
|
format_instructions: formatInstructions,
|
|
6312
|
-
|
|
6438
|
+
additional_context: additional_context,
|
|
6439
|
+
commit_history: commit_history,
|
|
6313
6440
|
},
|
|
6314
6441
|
parser,
|
|
6315
6442
|
});
|
|
@@ -6833,40 +6960,11 @@ const builder$1 = (yargs) => {
|
|
|
6833
6960
|
return yargs.options(options$1).usage(getCommandUsageHeader(command$1));
|
|
6834
6961
|
};
|
|
6835
6962
|
|
|
6836
|
-
/**
|
|
6837
|
-
* Formats a commit log into a readable string format.
|
|
6838
|
-
*
|
|
6839
|
-
* @param commitLog - The commit log result containing an array of commit details.
|
|
6840
|
-
* @returns An array of formatted commit log strings.
|
|
6841
|
-
*
|
|
6842
|
-
* Each formatted string includes:
|
|
6843
|
-
* - The date of the commit in square brackets.
|
|
6844
|
-
* - The commit message.
|
|
6845
|
-
* - The commit body.
|
|
6846
|
-
* - The commit hash in parentheses.
|
|
6847
|
-
* - The author's name and email in angle brackets.
|
|
6848
|
-
*/
|
|
6849
|
-
const formatCommitLog = (commitLog) => {
|
|
6850
|
-
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6851
|
-
};
|
|
6852
|
-
|
|
6853
6963
|
const getChangesByTimestamp = async ({ since, git }) => {
|
|
6854
6964
|
const commitLog = await git.log({ '--since': since });
|
|
6855
6965
|
return formatCommitLog(commitLog);
|
|
6856
6966
|
};
|
|
6857
6967
|
|
|
6858
|
-
const getChangesSinceLastTag = async ({ git }) => {
|
|
6859
|
-
const tags = await git.tags();
|
|
6860
|
-
if (tags.all.length > 0) {
|
|
6861
|
-
const lastTag = tags.latest;
|
|
6862
|
-
const commitLog = await git.log({ from: lastTag });
|
|
6863
|
-
return formatCommitLog(commitLog);
|
|
6864
|
-
}
|
|
6865
|
-
else {
|
|
6866
|
-
return ['No tags found in the repository.'];
|
|
6867
|
-
}
|
|
6868
|
-
};
|
|
6869
|
-
|
|
6870
6968
|
async function noResult$1({ logger }) {
|
|
6871
6969
|
logger.log('No repo changes detected. 👀', { color: 'blue' });
|
|
6872
6970
|
}
|
|
@@ -6876,12 +6974,12 @@ The summarization should descibe in a general sense what has changed in the repo
|
|
|
6876
6974
|
|
|
6877
6975
|
Breaking down the changes into categories (e.g. bug fixes, new features, etc.) with markdown headings is encouraged.
|
|
6878
6976
|
|
|
6879
|
-
{timeframe}
|
|
6977
|
+
{{timeframe}}
|
|
6880
6978
|
|
|
6881
|
-
{format_instructions}
|
|
6979
|
+
{{format_instructions}}
|
|
6882
6980
|
|
|
6883
|
-
"""{changes}"""`;
|
|
6884
|
-
const inputVariables$1 = ['
|
|
6981
|
+
"""{{changes}}"""`;
|
|
6982
|
+
const inputVariables$1 = ['timeframe', 'format_instructions', 'changes'];
|
|
6885
6983
|
const RECAP_PROMPT = new PromptTemplate({
|
|
6886
6984
|
template: template$1,
|
|
6887
6985
|
inputVariables: inputVariables$1,
|
|
@@ -6898,10 +6996,13 @@ const handler$1 = async (argv, logger) => {
|
|
|
6898
6996
|
}
|
|
6899
6997
|
const tokenizer = await getTokenCounter(provider === 'openai' ? model : 'gpt-4o');
|
|
6900
6998
|
const llm = getLlm(provider, model, config);
|
|
6901
|
-
const INTERACTIVE = isInteractive(config);
|
|
6999
|
+
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
6902
7000
|
if (INTERACTIVE) {
|
|
6903
7001
|
logger.log(LOGO);
|
|
6904
7002
|
}
|
|
7003
|
+
else {
|
|
7004
|
+
logger.setConfig({ silent: true });
|
|
7005
|
+
}
|
|
6905
7006
|
const { 'last-month': lastMonth, 'last-tag': lastTag, yesterday, 'last-week': lastWeek } = argv;
|
|
6906
7007
|
const timeframe = lastMonth
|
|
6907
7008
|
? 'last-month'
|
|
@@ -6960,7 +7061,7 @@ const handler$1 = async (argv, logger) => {
|
|
|
6960
7061
|
async function parser(changes) {
|
|
6961
7062
|
return changes.join('\n');
|
|
6962
7063
|
}
|
|
6963
|
-
await generateAndReviewLoop({
|
|
7064
|
+
const recapResult = await generateAndReviewLoop({
|
|
6964
7065
|
label: 'recap',
|
|
6965
7066
|
options: {
|
|
6966
7067
|
...config,
|
|
@@ -6985,30 +7086,61 @@ const handler$1 = async (argv, logger) => {
|
|
|
6985
7086
|
factory,
|
|
6986
7087
|
parser,
|
|
6987
7088
|
agent: async (context, options) => {
|
|
6988
|
-
const
|
|
6989
|
-
const formatInstructions = "Respond with a valid JSON object, containing one field: 'summary', a string.";
|
|
7089
|
+
const formatInstructions = 'Respond in a readable format. Include both high level and detailed information. Use markdown to format the response.';
|
|
6990
7090
|
const prompt = getPrompt({
|
|
6991
7091
|
template: options.prompt,
|
|
6992
7092
|
variables: RECAP_PROMPT.inputVariables,
|
|
6993
7093
|
fallback: RECAP_PROMPT,
|
|
6994
7094
|
});
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7095
|
+
try {
|
|
7096
|
+
const stringParser = new StringOutputParser();
|
|
7097
|
+
const response = (await executeChain({
|
|
7098
|
+
llm,
|
|
7099
|
+
prompt,
|
|
7100
|
+
variables: {
|
|
7101
|
+
changes: context,
|
|
7102
|
+
format_instructions: formatInstructions,
|
|
7103
|
+
timeframe,
|
|
7104
|
+
},
|
|
7105
|
+
// NOTE: parser is not optional and JSONOutputParser is expected, however making a union type for `executeChain` breaks type generation downstream.
|
|
7106
|
+
// In the future, we should consider making the parser optional in `executeChain` and better handle parser types.
|
|
7107
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
7108
|
+
// @ts-expect-error - parser is not optional and JSONOutputParser is expected
|
|
7109
|
+
parser: stringParser,
|
|
7110
|
+
}));
|
|
7111
|
+
return `${response || 'no response'}`;
|
|
7112
|
+
}
|
|
7113
|
+
catch (error) {
|
|
7114
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7115
|
+
// Log the error but don't exit
|
|
7116
|
+
logger.log(`Error parsing LLM response: ${errorMessage}`, { color: 'red' });
|
|
7117
|
+
// Always return a fallback message instead of exiting
|
|
7118
|
+
const fallbackMessage = `
|
|
7119
|
+
## Failed to parse the response [timeframe: ${timeframe}]
|
|
7120
|
+
- There are changes in the codebase that couldn't be properly summarized due to a technical issue.
|
|
7121
|
+
- LLM encountered issues when parsing the changes.
|
|
7122
|
+
|
|
7123
|
+
### Error encountered
|
|
7124
|
+
|
|
7125
|
+
${errorMessage}
|
|
7126
|
+
`;
|
|
7127
|
+
return fallbackMessage;
|
|
7128
|
+
}
|
|
7006
7129
|
},
|
|
7007
7130
|
noResult: async () => {
|
|
7008
7131
|
await noResult$1({ git, logger });
|
|
7009
7132
|
process.exit(0);
|
|
7010
7133
|
},
|
|
7011
7134
|
});
|
|
7135
|
+
// Handle the result based on the mode (interactive or stdout)
|
|
7136
|
+
const MODE = (INTERACTIVE && 'interactive') || (config.recap && 'interactive') || config?.mode || 'stdout'; // Default to stdout
|
|
7137
|
+
handleResult({
|
|
7138
|
+
result: recapResult,
|
|
7139
|
+
interactiveModeCallback: async () => {
|
|
7140
|
+
logSuccess();
|
|
7141
|
+
},
|
|
7142
|
+
mode: MODE,
|
|
7143
|
+
});
|
|
7012
7144
|
};
|
|
7013
7145
|
|
|
7014
7146
|
var recap = {
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,7 @@ var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline$1);
|
|
|
77
77
|
/**
|
|
78
78
|
* Current build version from package.json
|
|
79
79
|
*/
|
|
80
|
-
const BUILD_VERSION = "0.14.
|
|
80
|
+
const BUILD_VERSION = "0.14.9";
|
|
81
81
|
|
|
82
82
|
const isInteractive = (config) => {
|
|
83
83
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -1882,6 +1882,12 @@ const options$4 = {
|
|
|
1882
1882
|
alias: 'b',
|
|
1883
1883
|
description: 'Target branch to compare against',
|
|
1884
1884
|
},
|
|
1885
|
+
sinceLastTag: {
|
|
1886
|
+
type: 'boolean',
|
|
1887
|
+
alias: 't',
|
|
1888
|
+
description: 'Generate changelog for all commits since the last tag',
|
|
1889
|
+
default: false,
|
|
1890
|
+
},
|
|
1885
1891
|
i: {
|
|
1886
1892
|
type: 'boolean',
|
|
1887
1893
|
alias: 'interactive',
|
|
@@ -1934,6 +1940,7 @@ function getPrompt({ template, variables, fallback }) {
|
|
|
1934
1940
|
? new prompts$1.PromptTemplate({
|
|
1935
1941
|
template,
|
|
1936
1942
|
inputVariables: variables,
|
|
1943
|
+
templateFormat: 'mustache',
|
|
1937
1944
|
})
|
|
1938
1945
|
: fallback);
|
|
1939
1946
|
}
|
|
@@ -1964,6 +1971,35 @@ function extractTicketIdFromBranchName(branchName) {
|
|
|
1964
1971
|
return match ? match[0] : null;
|
|
1965
1972
|
}
|
|
1966
1973
|
|
|
1974
|
+
/**
|
|
1975
|
+
* Formats a commit log into a readable string format.
|
|
1976
|
+
*
|
|
1977
|
+
* @param commitLog - The commit log result containing an array of commit details.
|
|
1978
|
+
* @returns An array of formatted commit log strings.
|
|
1979
|
+
*
|
|
1980
|
+
* Each formatted string includes:
|
|
1981
|
+
* - The date of the commit in square brackets.
|
|
1982
|
+
* - The commit message.
|
|
1983
|
+
* - The commit body.
|
|
1984
|
+
* - The commit hash in parentheses.
|
|
1985
|
+
* - The author's name and email in angle brackets.
|
|
1986
|
+
*/
|
|
1987
|
+
const formatCommitLog = (commitLog) => {
|
|
1988
|
+
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
1989
|
+
};
|
|
1990
|
+
|
|
1991
|
+
const getChangesSinceLastTag = async ({ git }) => {
|
|
1992
|
+
const tags = await git.tags();
|
|
1993
|
+
if (tags.all.length > 0) {
|
|
1994
|
+
const lastTag = tags.latest;
|
|
1995
|
+
const commitLog = await git.log({ from: lastTag });
|
|
1996
|
+
return formatCommitLog(commitLog);
|
|
1997
|
+
}
|
|
1998
|
+
else {
|
|
1999
|
+
return ['No tags found in the repository.'];
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
|
|
1967
2003
|
/**
|
|
1968
2004
|
* Retrieves the commit log range between two specified commits.
|
|
1969
2005
|
*
|
|
@@ -2097,8 +2133,17 @@ const getRepo = () => {
|
|
|
2097
2133
|
return git;
|
|
2098
2134
|
};
|
|
2099
2135
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2136
|
+
/**
|
|
2137
|
+
* Template for generating git commit messages based on code changes
|
|
2138
|
+
*
|
|
2139
|
+
* Variables:
|
|
2140
|
+
* - summary: Contains the diff summary of staged changes
|
|
2141
|
+
* - format_instructions: Instructions for the output format (JSON with title and body)
|
|
2142
|
+
* - additional_context: Optional user-provided context to guide the commit message generation
|
|
2143
|
+
* - commit_history: Optional history of previous commits for context
|
|
2144
|
+
*/
|
|
2145
|
+
const template$4 = `Write informative git commit message, in the imperative, based on the diffs & file changes provided in the "Diff Summary" section.
|
|
2146
|
+
Commit Messages must have a short description that is less than 50 characters and a longer detailed summary around 300 characters, the shorter and more concise the better.
|
|
2102
2147
|
|
|
2103
2148
|
Please follow the guidelines below when writing your commit message:
|
|
2104
2149
|
|
|
@@ -2110,13 +2155,16 @@ Please follow the guidelines below when writing your commit message:
|
|
|
2110
2155
|
|
|
2111
2156
|
{format_instructions}
|
|
2112
2157
|
|
|
2158
|
+
{commit_history}
|
|
2159
|
+
|
|
2113
2160
|
""""""
|
|
2114
2161
|
{summary}
|
|
2115
2162
|
""""""
|
|
2116
2163
|
|
|
2117
|
-
{
|
|
2164
|
+
{additional_context}
|
|
2118
2165
|
`;
|
|
2119
|
-
|
|
2166
|
+
// Define the variables that will be passed to the prompt template
|
|
2167
|
+
const inputVariables$3 = ['summary', 'format_instructions', 'additional_context', 'commit_history'];
|
|
2120
2168
|
const COMMIT_PROMPT = new prompts$1.PromptTemplate({
|
|
2121
2169
|
template: template$4,
|
|
2122
2170
|
inputVariables: inputVariables$3,
|
|
@@ -2282,9 +2330,16 @@ async function generateAndReviewLoop({ label, factory, parser, noResult, agent,
|
|
|
2282
2330
|
result = '';
|
|
2283
2331
|
continue;
|
|
2284
2332
|
}
|
|
2333
|
+
// Only edit the result in interactive mode if approved
|
|
2334
|
+
result = await editResult(result, options);
|
|
2335
|
+
}
|
|
2336
|
+
else {
|
|
2337
|
+
// In non-interactive mode, we return the result as is to be output to stdout by the caller.
|
|
2338
|
+
const displayResult = reviewParser ? reviewParser(result, options) : result;
|
|
2339
|
+
// In non-interactive mode, ensure we return the properly formatted result
|
|
2340
|
+
result = displayResult;
|
|
2285
2341
|
}
|
|
2286
2342
|
// if we're here, we're done.
|
|
2287
|
-
result = await editResult(result, options);
|
|
2288
2343
|
continueLoop = false;
|
|
2289
2344
|
}
|
|
2290
2345
|
return result;
|
|
@@ -2307,7 +2362,8 @@ async function handleResult({ result, mode, interactiveModeCallback }) {
|
|
|
2307
2362
|
break;
|
|
2308
2363
|
case 'stdout':
|
|
2309
2364
|
default:
|
|
2310
|
-
|
|
2365
|
+
// Ensure we write the result to stdout in non-interactive mode
|
|
2366
|
+
process.stdout.write(result + '\n', 'utf8');
|
|
2311
2367
|
break;
|
|
2312
2368
|
}
|
|
2313
2369
|
process.exit(0);
|
|
@@ -2346,6 +2402,13 @@ const handler$4 = async (argv, logger) => {
|
|
|
2346
2402
|
}
|
|
2347
2403
|
async function factory() {
|
|
2348
2404
|
const branchName = await getCurrentBranchName({ git });
|
|
2405
|
+
if (config.sinceLastTag) {
|
|
2406
|
+
logger.verbose(`Generating commit log since the last tag`, { color: 'yellow' });
|
|
2407
|
+
return {
|
|
2408
|
+
branch: branchName,
|
|
2409
|
+
commits: await getChangesSinceLastTag({ git, logger }),
|
|
2410
|
+
};
|
|
2411
|
+
}
|
|
2349
2412
|
if (config.range && config.range.includes(':')) {
|
|
2350
2413
|
const [from, to] = config.range.split(':');
|
|
2351
2414
|
if (!from || !to) {
|
|
@@ -2364,7 +2427,7 @@ const handler$4 = async (argv, logger) => {
|
|
|
2364
2427
|
commits: await getCommitLogAgainstBranch({ git, logger, targetBranch: argv.branch }),
|
|
2365
2428
|
};
|
|
2366
2429
|
}
|
|
2367
|
-
logger.verbose(`No range or
|
|
2430
|
+
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, { color: 'yellow' });
|
|
2368
2431
|
return {
|
|
2369
2432
|
branch: branchName,
|
|
2370
2433
|
commits: await getCommitLogCurrentBranch({ git, logger }),
|
|
@@ -2436,7 +2499,7 @@ const handler$4 = async (argv, logger) => {
|
|
|
2436
2499
|
|
|
2437
2500
|
var changelog = {
|
|
2438
2501
|
command: command$4,
|
|
2439
|
-
desc: 'Generate a changelog from current or target branch
|
|
2502
|
+
desc: 'Generate a changelog from current or target branch, provided commit range, or since the last tag.',
|
|
2440
2503
|
builder: builder$4,
|
|
2441
2504
|
handler: commandExecutor(handler$4),
|
|
2442
2505
|
options: options$4,
|
|
@@ -2474,6 +2537,12 @@ const options$3 = {
|
|
|
2474
2537
|
type: 'string',
|
|
2475
2538
|
alias: 'a',
|
|
2476
2539
|
},
|
|
2540
|
+
withPreviousCommits: {
|
|
2541
|
+
description: 'Include previous commits as context (specify number of commits, 0 for none)',
|
|
2542
|
+
type: 'number',
|
|
2543
|
+
default: 0,
|
|
2544
|
+
alias: 'p',
|
|
2545
|
+
},
|
|
2477
2546
|
};
|
|
2478
2547
|
const builder$3 = (yargs) => {
|
|
2479
2548
|
return yargs.options(options$3).usage(getCommandUsageHeader(command$3));
|
|
@@ -6211,6 +6280,48 @@ async function getChanges({ git, options }) {
|
|
|
6211
6280
|
};
|
|
6212
6281
|
}
|
|
6213
6282
|
|
|
6283
|
+
/**
|
|
6284
|
+
* Format a single commit log entry into a readable string
|
|
6285
|
+
* @param commit - The commit log entry
|
|
6286
|
+
* @returns Formatted commit log string
|
|
6287
|
+
*/
|
|
6288
|
+
function formatSingleCommit(commit) {
|
|
6289
|
+
const { hash, date, message, body, author_name } = commit;
|
|
6290
|
+
const shortHash = hash.substring(0, 7);
|
|
6291
|
+
return `Commit: ${shortHash}
|
|
6292
|
+
Author: ${author_name}
|
|
6293
|
+
Date: ${date}
|
|
6294
|
+
Message: ${message}
|
|
6295
|
+
${body ? `\nDetails: ${body}` : ''}`;
|
|
6296
|
+
}
|
|
6297
|
+
|
|
6298
|
+
/**
|
|
6299
|
+
* Get the specified number of previous commits
|
|
6300
|
+
* @param options - Options for getting previous commits
|
|
6301
|
+
* @returns Formatted commit logs
|
|
6302
|
+
*/
|
|
6303
|
+
async function getPreviousCommits(options) {
|
|
6304
|
+
const { git, count = 1 } = options;
|
|
6305
|
+
if (count <= 0) {
|
|
6306
|
+
return '';
|
|
6307
|
+
}
|
|
6308
|
+
try {
|
|
6309
|
+
const logs = await git.log({ maxCount: count });
|
|
6310
|
+
if (!logs || logs.total === 0) {
|
|
6311
|
+
return '';
|
|
6312
|
+
}
|
|
6313
|
+
// Format the commit logs
|
|
6314
|
+
const formattedLogs = logs.all.map((commit) => {
|
|
6315
|
+
return formatSingleCommit(commit);
|
|
6316
|
+
}).join('\n\n');
|
|
6317
|
+
return formattedLogs;
|
|
6318
|
+
}
|
|
6319
|
+
catch (error) {
|
|
6320
|
+
console.error(`Error getting previous commits: ${error.message}`);
|
|
6321
|
+
return '';
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
|
|
6214
6325
|
/**
|
|
6215
6326
|
* Retrieves a TikToken for the specified model.
|
|
6216
6327
|
*
|
|
@@ -6324,14 +6435,30 @@ const handler$3 = async (argv, logger) => {
|
|
|
6324
6435
|
fallback: COMMIT_PROMPT,
|
|
6325
6436
|
});
|
|
6326
6437
|
const formatInstructions = "Respond with a valid JSON object, containing two fields: 'title' and 'body', both strings.";
|
|
6327
|
-
|
|
6438
|
+
// Get additional context if provided
|
|
6439
|
+
let additional_context = '';
|
|
6440
|
+
if (argv.additional) {
|
|
6441
|
+
additional_context = `## Additional Context\n${argv.additional}`;
|
|
6442
|
+
}
|
|
6443
|
+
// Get commit history if requested
|
|
6444
|
+
let commit_history = '';
|
|
6445
|
+
if (argv.withPreviousCommits > 0) {
|
|
6446
|
+
const commitHistoryData = await getPreviousCommits({
|
|
6447
|
+
git,
|
|
6448
|
+
count: argv.withPreviousCommits
|
|
6449
|
+
});
|
|
6450
|
+
if (commitHistoryData) {
|
|
6451
|
+
commit_history = `## Commit History\n${commitHistoryData}`;
|
|
6452
|
+
}
|
|
6453
|
+
}
|
|
6328
6454
|
const commitMsg = await executeChain({
|
|
6329
6455
|
llm,
|
|
6330
6456
|
prompt,
|
|
6331
6457
|
variables: {
|
|
6332
6458
|
summary: context,
|
|
6333
6459
|
format_instructions: formatInstructions,
|
|
6334
|
-
|
|
6460
|
+
additional_context: additional_context,
|
|
6461
|
+
commit_history: commit_history,
|
|
6335
6462
|
},
|
|
6336
6463
|
parser,
|
|
6337
6464
|
});
|
|
@@ -6855,40 +6982,11 @@ const builder$1 = (yargs) => {
|
|
|
6855
6982
|
return yargs.options(options$1).usage(getCommandUsageHeader(command$1));
|
|
6856
6983
|
};
|
|
6857
6984
|
|
|
6858
|
-
/**
|
|
6859
|
-
* Formats a commit log into a readable string format.
|
|
6860
|
-
*
|
|
6861
|
-
* @param commitLog - The commit log result containing an array of commit details.
|
|
6862
|
-
* @returns An array of formatted commit log strings.
|
|
6863
|
-
*
|
|
6864
|
-
* Each formatted string includes:
|
|
6865
|
-
* - The date of the commit in square brackets.
|
|
6866
|
-
* - The commit message.
|
|
6867
|
-
* - The commit body.
|
|
6868
|
-
* - The commit hash in parentheses.
|
|
6869
|
-
* - The author's name and email in angle brackets.
|
|
6870
|
-
*/
|
|
6871
|
-
const formatCommitLog = (commitLog) => {
|
|
6872
|
-
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6873
|
-
};
|
|
6874
|
-
|
|
6875
6985
|
const getChangesByTimestamp = async ({ since, git }) => {
|
|
6876
6986
|
const commitLog = await git.log({ '--since': since });
|
|
6877
6987
|
return formatCommitLog(commitLog);
|
|
6878
6988
|
};
|
|
6879
6989
|
|
|
6880
|
-
const getChangesSinceLastTag = async ({ git }) => {
|
|
6881
|
-
const tags = await git.tags();
|
|
6882
|
-
if (tags.all.length > 0) {
|
|
6883
|
-
const lastTag = tags.latest;
|
|
6884
|
-
const commitLog = await git.log({ from: lastTag });
|
|
6885
|
-
return formatCommitLog(commitLog);
|
|
6886
|
-
}
|
|
6887
|
-
else {
|
|
6888
|
-
return ['No tags found in the repository.'];
|
|
6889
|
-
}
|
|
6890
|
-
};
|
|
6891
|
-
|
|
6892
6990
|
async function noResult$1({ logger }) {
|
|
6893
6991
|
logger.log('No repo changes detected. 👀', { color: 'blue' });
|
|
6894
6992
|
}
|
|
@@ -6898,12 +6996,12 @@ The summarization should descibe in a general sense what has changed in the repo
|
|
|
6898
6996
|
|
|
6899
6997
|
Breaking down the changes into categories (e.g. bug fixes, new features, etc.) with markdown headings is encouraged.
|
|
6900
6998
|
|
|
6901
|
-
{timeframe}
|
|
6999
|
+
{{timeframe}}
|
|
6902
7000
|
|
|
6903
|
-
{format_instructions}
|
|
7001
|
+
{{format_instructions}}
|
|
6904
7002
|
|
|
6905
|
-
"""{changes}"""`;
|
|
6906
|
-
const inputVariables$1 = ['
|
|
7003
|
+
"""{{changes}}"""`;
|
|
7004
|
+
const inputVariables$1 = ['timeframe', 'format_instructions', 'changes'];
|
|
6907
7005
|
const RECAP_PROMPT = new prompts$1.PromptTemplate({
|
|
6908
7006
|
template: template$1,
|
|
6909
7007
|
inputVariables: inputVariables$1,
|
|
@@ -6920,10 +7018,13 @@ const handler$1 = async (argv, logger) => {
|
|
|
6920
7018
|
}
|
|
6921
7019
|
const tokenizer = await getTokenCounter(provider === 'openai' ? model : 'gpt-4o');
|
|
6922
7020
|
const llm = getLlm(provider, model, config);
|
|
6923
|
-
const INTERACTIVE = isInteractive(config);
|
|
7021
|
+
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
6924
7022
|
if (INTERACTIVE) {
|
|
6925
7023
|
logger.log(LOGO);
|
|
6926
7024
|
}
|
|
7025
|
+
else {
|
|
7026
|
+
logger.setConfig({ silent: true });
|
|
7027
|
+
}
|
|
6927
7028
|
const { 'last-month': lastMonth, 'last-tag': lastTag, yesterday, 'last-week': lastWeek } = argv;
|
|
6928
7029
|
const timeframe = lastMonth
|
|
6929
7030
|
? 'last-month'
|
|
@@ -6982,7 +7083,7 @@ const handler$1 = async (argv, logger) => {
|
|
|
6982
7083
|
async function parser(changes) {
|
|
6983
7084
|
return changes.join('\n');
|
|
6984
7085
|
}
|
|
6985
|
-
await generateAndReviewLoop({
|
|
7086
|
+
const recapResult = await generateAndReviewLoop({
|
|
6986
7087
|
label: 'recap',
|
|
6987
7088
|
options: {
|
|
6988
7089
|
...config,
|
|
@@ -7007,30 +7108,61 @@ const handler$1 = async (argv, logger) => {
|
|
|
7007
7108
|
factory,
|
|
7008
7109
|
parser,
|
|
7009
7110
|
agent: async (context, options) => {
|
|
7010
|
-
const
|
|
7011
|
-
const formatInstructions = "Respond with a valid JSON object, containing one field: 'summary', a string.";
|
|
7111
|
+
const formatInstructions = 'Respond in a readable format. Include both high level and detailed information. Use markdown to format the response.';
|
|
7012
7112
|
const prompt = getPrompt({
|
|
7013
7113
|
template: options.prompt,
|
|
7014
7114
|
variables: RECAP_PROMPT.inputVariables,
|
|
7015
7115
|
fallback: RECAP_PROMPT,
|
|
7016
7116
|
});
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7117
|
+
try {
|
|
7118
|
+
const stringParser = new output_parsers.StringOutputParser();
|
|
7119
|
+
const response = (await executeChain({
|
|
7120
|
+
llm,
|
|
7121
|
+
prompt,
|
|
7122
|
+
variables: {
|
|
7123
|
+
changes: context,
|
|
7124
|
+
format_instructions: formatInstructions,
|
|
7125
|
+
timeframe,
|
|
7126
|
+
},
|
|
7127
|
+
// NOTE: parser is not optional and JSONOutputParser is expected, however making a union type for `executeChain` breaks type generation downstream.
|
|
7128
|
+
// In the future, we should consider making the parser optional in `executeChain` and better handle parser types.
|
|
7129
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
7130
|
+
// @ts-expect-error - parser is not optional and JSONOutputParser is expected
|
|
7131
|
+
parser: stringParser,
|
|
7132
|
+
}));
|
|
7133
|
+
return `${response || 'no response'}`;
|
|
7134
|
+
}
|
|
7135
|
+
catch (error) {
|
|
7136
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
7137
|
+
// Log the error but don't exit
|
|
7138
|
+
logger.log(`Error parsing LLM response: ${errorMessage}`, { color: 'red' });
|
|
7139
|
+
// Always return a fallback message instead of exiting
|
|
7140
|
+
const fallbackMessage = `
|
|
7141
|
+
## Failed to parse the response [timeframe: ${timeframe}]
|
|
7142
|
+
- There are changes in the codebase that couldn't be properly summarized due to a technical issue.
|
|
7143
|
+
- LLM encountered issues when parsing the changes.
|
|
7144
|
+
|
|
7145
|
+
### Error encountered
|
|
7146
|
+
|
|
7147
|
+
${errorMessage}
|
|
7148
|
+
`;
|
|
7149
|
+
return fallbackMessage;
|
|
7150
|
+
}
|
|
7028
7151
|
},
|
|
7029
7152
|
noResult: async () => {
|
|
7030
7153
|
await noResult$1({ git, logger });
|
|
7031
7154
|
process.exit(0);
|
|
7032
7155
|
},
|
|
7033
7156
|
});
|
|
7157
|
+
// Handle the result based on the mode (interactive or stdout)
|
|
7158
|
+
const MODE = (INTERACTIVE && 'interactive') || (config.recap && 'interactive') || config?.mode || 'stdout'; // Default to stdout
|
|
7159
|
+
handleResult({
|
|
7160
|
+
result: recapResult,
|
|
7161
|
+
interactiveModeCallback: async () => {
|
|
7162
|
+
logSuccess();
|
|
7163
|
+
},
|
|
7164
|
+
mode: MODE,
|
|
7165
|
+
});
|
|
7034
7166
|
};
|
|
7035
7167
|
|
|
7036
7168
|
var recap = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-coco",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.9",
|
|
4
4
|
"description": "zero-effort git commits with coco.",
|
|
5
5
|
"author": "gfargo <ghfargo@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"@types/async": "^3.2.20",
|
|
53
53
|
"@types/chunk-text": "^1.0.0",
|
|
54
54
|
"@types/common-tags": "^1.8.1",
|
|
55
|
-
"@types/diff": "^
|
|
56
|
-
"@types/ini": "^1.
|
|
55
|
+
"@types/diff": "^7.0.1",
|
|
56
|
+
"@types/ini": "^4.1.1",
|
|
57
57
|
"@types/inquirer": "^9.0.3",
|
|
58
58
|
"@types/jest": "^29.5.10",
|
|
59
59
|
"@types/node": "^22.7.5",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
"ajv": "^8.16.0",
|
|
94
94
|
"ajv-formats": "^3.0.1",
|
|
95
95
|
"chalk": "4.1.2",
|
|
96
|
-
"diff": "
|
|
97
|
-
"ini": "
|
|
96
|
+
"diff": "7.0.0",
|
|
97
|
+
"ini": "5.0.0",
|
|
98
98
|
"minimatch": "10.0.1",
|
|
99
99
|
"ora": "5.4.1",
|
|
100
100
|
"p-queue": "5.0.0",
|