git-coco 0.12.0 → 0.13.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 +2 -2
- package/dist/index.esm.mjs +128 -107
- package/dist/index.js +128 -107
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { OllamaInput } from '@langchain/community/llms/ollama';
|
|
|
4
4
|
import { BaseLLMParams } from '@langchain/core/language_models/llms';
|
|
5
5
|
import * as _langchain_openai from '@langchain/openai';
|
|
6
6
|
import { TiktokenModel, OpenAIInput, ChatOpenAI } from '@langchain/openai';
|
|
7
|
-
import { ChatOllama } from '@langchain/ollama';
|
|
8
7
|
import { SimpleGit } from 'simple-git';
|
|
8
|
+
import { ChatOllama } from '@langchain/ollama';
|
|
9
9
|
import { Color } from 'chalk';
|
|
10
10
|
import { TiktokenModel as TiktokenModel$1 } from 'tiktoken';
|
|
11
11
|
|
|
@@ -285,7 +285,7 @@ interface BaseParserInput {
|
|
|
285
285
|
}
|
|
286
286
|
interface FileChangeParserInput extends BaseParserInput {
|
|
287
287
|
changes: FileChange[];
|
|
288
|
-
commit: '--staged' | string;
|
|
288
|
+
commit: '--staged' | '--unstaged' | '--untracked' | string;
|
|
289
289
|
}
|
|
290
290
|
interface CommitLogParserInput extends BaseParserInput {
|
|
291
291
|
range: {
|
package/dist/index.esm.mjs
CHANGED
|
@@ -2608,100 +2608,6 @@ async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 204
|
|
|
2608
2608
|
return directoryDiffs.map(handleOutput).join('');
|
|
2609
2609
|
}
|
|
2610
2610
|
|
|
2611
|
-
class DiffTreeNode {
|
|
2612
|
-
constructor(path) {
|
|
2613
|
-
this.path = [];
|
|
2614
|
-
this.files = [];
|
|
2615
|
-
this.children = new Map();
|
|
2616
|
-
if (path)
|
|
2617
|
-
this.path = path;
|
|
2618
|
-
}
|
|
2619
|
-
addFile(file) {
|
|
2620
|
-
this.files.push(file);
|
|
2621
|
-
}
|
|
2622
|
-
addChild(part, node) {
|
|
2623
|
-
this.children.set(part, node);
|
|
2624
|
-
}
|
|
2625
|
-
getChild(part) {
|
|
2626
|
-
return this.children.get(part);
|
|
2627
|
-
}
|
|
2628
|
-
getPath() {
|
|
2629
|
-
return this.path.join('/');
|
|
2630
|
-
}
|
|
2631
|
-
print(indentation = 0) {
|
|
2632
|
-
const indent = ' '.repeat(indentation);
|
|
2633
|
-
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
2634
|
-
if (this.files.length > 0) {
|
|
2635
|
-
output += `${indent} Files:\n`;
|
|
2636
|
-
for (const file of this.files) {
|
|
2637
|
-
output += `${indent} - ${file.summary}\n`;
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
if (this.children.size > 0) {
|
|
2641
|
-
output += `${indent} Children:\n`;
|
|
2642
|
-
for (const [, child] of this.children) {
|
|
2643
|
-
output += child.print(indentation + 4);
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
return output;
|
|
2647
|
-
}
|
|
2648
|
-
}
|
|
2649
|
-
const createDiffTree = (changes) => {
|
|
2650
|
-
const root = new DiffTreeNode();
|
|
2651
|
-
for (const change of changes) {
|
|
2652
|
-
let currentParent = root;
|
|
2653
|
-
const parts = change.filePath.split('/');
|
|
2654
|
-
parts.pop();
|
|
2655
|
-
for (const part of parts) {
|
|
2656
|
-
let childNode = currentParent.getChild(part);
|
|
2657
|
-
if (!childNode) {
|
|
2658
|
-
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
2659
|
-
currentParent.addChild(part, childNode);
|
|
2660
|
-
}
|
|
2661
|
-
currentParent = childNode;
|
|
2662
|
-
}
|
|
2663
|
-
// Create a NodeFile object and add it to the parent
|
|
2664
|
-
currentParent.addFile({
|
|
2665
|
-
filePath: change.filePath,
|
|
2666
|
-
oldFilePath: change.oldFilePath,
|
|
2667
|
-
summary: change.summary,
|
|
2668
|
-
status: change.status,
|
|
2669
|
-
});
|
|
2670
|
-
}
|
|
2671
|
-
return root;
|
|
2672
|
-
};
|
|
2673
|
-
|
|
2674
|
-
/**
|
|
2675
|
-
* Asynchronously collect diffs for a given node and its children.
|
|
2676
|
-
*/
|
|
2677
|
-
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
2678
|
-
// Collect diffs for the files of the current node
|
|
2679
|
-
const diffPromises = node.files.map(async (nodeFile) => {
|
|
2680
|
-
const diff = await getFileDiff(nodeFile);
|
|
2681
|
-
const tokenCount = tokenizer(diff);
|
|
2682
|
-
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
2683
|
-
color: 'magenta',
|
|
2684
|
-
});
|
|
2685
|
-
return {
|
|
2686
|
-
file: nodeFile.filePath,
|
|
2687
|
-
summary: nodeFile.summary,
|
|
2688
|
-
diff,
|
|
2689
|
-
tokenCount,
|
|
2690
|
-
};
|
|
2691
|
-
});
|
|
2692
|
-
// Collect diffs for the children of the current node
|
|
2693
|
-
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
2694
|
-
const [diffs, children] = await Promise.all([
|
|
2695
|
-
Promise.all(diffPromises),
|
|
2696
|
-
Promise.all(childrenPromises),
|
|
2697
|
-
]);
|
|
2698
|
-
return {
|
|
2699
|
-
path: node.getPath(),
|
|
2700
|
-
diffs,
|
|
2701
|
-
children,
|
|
2702
|
-
};
|
|
2703
|
-
}
|
|
2704
|
-
|
|
2705
2611
|
/**
|
|
2706
2612
|
* Base interface that all chains must implement.
|
|
2707
2613
|
*/
|
|
@@ -5950,6 +5856,100 @@ function getTextSplitter(options = {}) {
|
|
|
5950
5856
|
return new RecursiveCharacterTextSplitter(options);
|
|
5951
5857
|
}
|
|
5952
5858
|
|
|
5859
|
+
/**
|
|
5860
|
+
* Asynchronously collect diffs for a given node and its children.
|
|
5861
|
+
*/
|
|
5862
|
+
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
5863
|
+
// Collect diffs for the files of the current node
|
|
5864
|
+
const diffPromises = node.files.map(async (nodeFile) => {
|
|
5865
|
+
const diff = await getFileDiff(nodeFile);
|
|
5866
|
+
const tokenCount = tokenizer(diff);
|
|
5867
|
+
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
5868
|
+
color: 'magenta',
|
|
5869
|
+
});
|
|
5870
|
+
return {
|
|
5871
|
+
file: nodeFile.filePath,
|
|
5872
|
+
summary: nodeFile.summary,
|
|
5873
|
+
diff,
|
|
5874
|
+
tokenCount,
|
|
5875
|
+
};
|
|
5876
|
+
});
|
|
5877
|
+
// Collect diffs for the children of the current node
|
|
5878
|
+
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
5879
|
+
const [diffs, children] = await Promise.all([
|
|
5880
|
+
Promise.all(diffPromises),
|
|
5881
|
+
Promise.all(childrenPromises),
|
|
5882
|
+
]);
|
|
5883
|
+
return {
|
|
5884
|
+
path: node.getPath(),
|
|
5885
|
+
diffs,
|
|
5886
|
+
children,
|
|
5887
|
+
};
|
|
5888
|
+
}
|
|
5889
|
+
|
|
5890
|
+
class DiffTreeNode {
|
|
5891
|
+
constructor(path) {
|
|
5892
|
+
this.path = [];
|
|
5893
|
+
this.files = [];
|
|
5894
|
+
this.children = new Map();
|
|
5895
|
+
if (path)
|
|
5896
|
+
this.path = path;
|
|
5897
|
+
}
|
|
5898
|
+
addFile(file) {
|
|
5899
|
+
this.files.push(file);
|
|
5900
|
+
}
|
|
5901
|
+
addChild(part, node) {
|
|
5902
|
+
this.children.set(part, node);
|
|
5903
|
+
}
|
|
5904
|
+
getChild(part) {
|
|
5905
|
+
return this.children.get(part);
|
|
5906
|
+
}
|
|
5907
|
+
getPath() {
|
|
5908
|
+
return this.path.join('/');
|
|
5909
|
+
}
|
|
5910
|
+
print(indentation = 0) {
|
|
5911
|
+
const indent = ' '.repeat(indentation);
|
|
5912
|
+
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
5913
|
+
if (this.files.length > 0) {
|
|
5914
|
+
output += `${indent} Files:\n`;
|
|
5915
|
+
for (const file of this.files) {
|
|
5916
|
+
output += `${indent} - ${file.summary}\n`;
|
|
5917
|
+
}
|
|
5918
|
+
}
|
|
5919
|
+
if (this.children.size > 0) {
|
|
5920
|
+
output += `${indent} Children:\n`;
|
|
5921
|
+
for (const [, child] of this.children) {
|
|
5922
|
+
output += child.print(indentation + 4);
|
|
5923
|
+
}
|
|
5924
|
+
}
|
|
5925
|
+
return output;
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
const createDiffTree = (changes) => {
|
|
5929
|
+
const root = new DiffTreeNode();
|
|
5930
|
+
for (const change of changes) {
|
|
5931
|
+
let currentParent = root;
|
|
5932
|
+
const parts = change.filePath.split('/');
|
|
5933
|
+
parts.pop();
|
|
5934
|
+
for (const part of parts) {
|
|
5935
|
+
let childNode = currentParent.getChild(part);
|
|
5936
|
+
if (!childNode) {
|
|
5937
|
+
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
5938
|
+
currentParent.addChild(part, childNode);
|
|
5939
|
+
}
|
|
5940
|
+
currentParent = childNode;
|
|
5941
|
+
}
|
|
5942
|
+
// Create a NodeFile object and add it to the parent
|
|
5943
|
+
currentParent.addFile({
|
|
5944
|
+
filePath: change.filePath,
|
|
5945
|
+
oldFilePath: change.oldFilePath,
|
|
5946
|
+
summary: change.summary,
|
|
5947
|
+
status: change.status,
|
|
5948
|
+
});
|
|
5949
|
+
}
|
|
5950
|
+
return root;
|
|
5951
|
+
};
|
|
5952
|
+
|
|
5953
5953
|
/**
|
|
5954
5954
|
* Parses the default file diff for a given nodeFile.
|
|
5955
5955
|
*
|
|
@@ -5959,8 +5959,15 @@ function getTextSplitter(options = {}) {
|
|
|
5959
5959
|
* @returns A Promise that resolves to the file diff as a string.
|
|
5960
5960
|
*/
|
|
5961
5961
|
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
5962
|
-
if (commit
|
|
5963
|
-
return await git.diff([
|
|
5962
|
+
if (commit === '--staged') {
|
|
5963
|
+
return await git.diff(['--staged', nodeFile.filePath]);
|
|
5964
|
+
}
|
|
5965
|
+
else if (commit === '--unstaged') {
|
|
5966
|
+
return await git.diff([nodeFile.filePath]);
|
|
5967
|
+
}
|
|
5968
|
+
else if (commit === '--untracked') {
|
|
5969
|
+
// For untracked files, return the entire file content
|
|
5970
|
+
return await git.show([`:${nodeFile.filePath}`]);
|
|
5964
5971
|
}
|
|
5965
5972
|
return await git.diff([commit, nodeFile.filePath]);
|
|
5966
5973
|
}
|
|
@@ -6041,10 +6048,6 @@ async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
|
6041
6048
|
const MAX_TOKENS_PER_SUMMARY = 12288;
|
|
6042
6049
|
async function fileChangeParser({ changes, commit, options: { tokenizer, git, llm: model, logger }, }) {
|
|
6043
6050
|
const textSplitter = getTextSplitter({ chunkSize: 10000, chunkOverlap: 250 });
|
|
6044
|
-
// const textSplitter = new TokenTextSplitter({
|
|
6045
|
-
// chunkSize: 10000,
|
|
6046
|
-
// chunkOverlap: 250,
|
|
6047
|
-
// });
|
|
6048
6051
|
const summarizationChain = getSummarizationChain(model, {
|
|
6049
6052
|
type: 'map_reduce',
|
|
6050
6053
|
combineMapPrompt: SUMMARIZE_PROMPT,
|
|
@@ -6326,7 +6329,10 @@ const handler$2 = async (argv, logger) => {
|
|
|
6326
6329
|
parser,
|
|
6327
6330
|
});
|
|
6328
6331
|
const appendedText = argv.append ? `\n\n${argv.append}` : '';
|
|
6329
|
-
|
|
6332
|
+
const branchName = await getCurrentBranchName({ git });
|
|
6333
|
+
const ticketId = extractTicketIdFromBranchName(branchName);
|
|
6334
|
+
const ticketFooter = argv.appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
|
|
6335
|
+
return `${commitMsg.title}\n\n${commitMsg.body}${appendedText}${ticketFooter}`;
|
|
6330
6336
|
},
|
|
6331
6337
|
noResult: async () => {
|
|
6332
6338
|
await noResult$1({ git, logger });
|
|
@@ -6365,6 +6371,10 @@ const options$2 = {
|
|
|
6365
6371
|
description: 'Add content to the end of the generated commit message',
|
|
6366
6372
|
type: 'string',
|
|
6367
6373
|
},
|
|
6374
|
+
appendTicket: {
|
|
6375
|
+
description: 'Append ticket ID from branch name to the commit message',
|
|
6376
|
+
type: 'boolean',
|
|
6377
|
+
},
|
|
6368
6378
|
additional: {
|
|
6369
6379
|
description: 'Add extra contextual information to the prompt',
|
|
6370
6380
|
type: 'string',
|
|
@@ -6887,13 +6897,25 @@ const handler = async (argv, logger) => {
|
|
|
6887
6897
|
case 'current':
|
|
6888
6898
|
const { staged, unstaged, untracked } = await getChanges({ git });
|
|
6889
6899
|
logger.log(`Staged: ${staged.length}, Unstaged: ${unstaged?.length || 0}, Untracked: ${untracked?.length || 0}`);
|
|
6890
|
-
const
|
|
6891
|
-
changes:
|
|
6892
|
-
commit: '
|
|
6900
|
+
const unstagedChanges = await fileChangeParser({
|
|
6901
|
+
changes: unstaged || [],
|
|
6902
|
+
commit: '--unstaged',
|
|
6903
|
+
options: { tokenizer, git, llm, logger },
|
|
6904
|
+
});
|
|
6905
|
+
const unstagedResponse = `Unstaged changes:\n${unstagedChanges}`;
|
|
6906
|
+
const untrackedChanges = await fileChangeParser({
|
|
6907
|
+
changes: untracked || [],
|
|
6908
|
+
commit: '--untracked',
|
|
6909
|
+
options: { tokenizer, git, llm, logger },
|
|
6910
|
+
});
|
|
6911
|
+
const untrackedResponse = `Untracked changes:\n${untrackedChanges}`;
|
|
6912
|
+
const stagedChanges = await fileChangeParser({
|
|
6913
|
+
changes: staged,
|
|
6914
|
+
commit: '--staged',
|
|
6893
6915
|
options: { tokenizer, git, llm, logger },
|
|
6894
6916
|
});
|
|
6895
|
-
|
|
6896
|
-
return [
|
|
6917
|
+
const stagedResponse = `Staged changes:\n${stagedChanges}`;
|
|
6918
|
+
return [unstagedResponse, untrackedResponse, stagedResponse];
|
|
6897
6919
|
case 'yesterday':
|
|
6898
6920
|
const yesterday = new Date();
|
|
6899
6921
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
@@ -6915,7 +6937,6 @@ const handler = async (argv, logger) => {
|
|
|
6915
6937
|
}
|
|
6916
6938
|
}
|
|
6917
6939
|
async function parser(changes) {
|
|
6918
|
-
console.log({ changes });
|
|
6919
6940
|
return changes.join('\n');
|
|
6920
6941
|
}
|
|
6921
6942
|
const recap = await generateAndReviewLoop({
|
package/dist/index.js
CHANGED
|
@@ -2629,100 +2629,6 @@ async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 204
|
|
|
2629
2629
|
return directoryDiffs.map(handleOutput).join('');
|
|
2630
2630
|
}
|
|
2631
2631
|
|
|
2632
|
-
class DiffTreeNode {
|
|
2633
|
-
constructor(path) {
|
|
2634
|
-
this.path = [];
|
|
2635
|
-
this.files = [];
|
|
2636
|
-
this.children = new Map();
|
|
2637
|
-
if (path)
|
|
2638
|
-
this.path = path;
|
|
2639
|
-
}
|
|
2640
|
-
addFile(file) {
|
|
2641
|
-
this.files.push(file);
|
|
2642
|
-
}
|
|
2643
|
-
addChild(part, node) {
|
|
2644
|
-
this.children.set(part, node);
|
|
2645
|
-
}
|
|
2646
|
-
getChild(part) {
|
|
2647
|
-
return this.children.get(part);
|
|
2648
|
-
}
|
|
2649
|
-
getPath() {
|
|
2650
|
-
return this.path.join('/');
|
|
2651
|
-
}
|
|
2652
|
-
print(indentation = 0) {
|
|
2653
|
-
const indent = ' '.repeat(indentation);
|
|
2654
|
-
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
2655
|
-
if (this.files.length > 0) {
|
|
2656
|
-
output += `${indent} Files:\n`;
|
|
2657
|
-
for (const file of this.files) {
|
|
2658
|
-
output += `${indent} - ${file.summary}\n`;
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
if (this.children.size > 0) {
|
|
2662
|
-
output += `${indent} Children:\n`;
|
|
2663
|
-
for (const [, child] of this.children) {
|
|
2664
|
-
output += child.print(indentation + 4);
|
|
2665
|
-
}
|
|
2666
|
-
}
|
|
2667
|
-
return output;
|
|
2668
|
-
}
|
|
2669
|
-
}
|
|
2670
|
-
const createDiffTree = (changes) => {
|
|
2671
|
-
const root = new DiffTreeNode();
|
|
2672
|
-
for (const change of changes) {
|
|
2673
|
-
let currentParent = root;
|
|
2674
|
-
const parts = change.filePath.split('/');
|
|
2675
|
-
parts.pop();
|
|
2676
|
-
for (const part of parts) {
|
|
2677
|
-
let childNode = currentParent.getChild(part);
|
|
2678
|
-
if (!childNode) {
|
|
2679
|
-
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
2680
|
-
currentParent.addChild(part, childNode);
|
|
2681
|
-
}
|
|
2682
|
-
currentParent = childNode;
|
|
2683
|
-
}
|
|
2684
|
-
// Create a NodeFile object and add it to the parent
|
|
2685
|
-
currentParent.addFile({
|
|
2686
|
-
filePath: change.filePath,
|
|
2687
|
-
oldFilePath: change.oldFilePath,
|
|
2688
|
-
summary: change.summary,
|
|
2689
|
-
status: change.status,
|
|
2690
|
-
});
|
|
2691
|
-
}
|
|
2692
|
-
return root;
|
|
2693
|
-
};
|
|
2694
|
-
|
|
2695
|
-
/**
|
|
2696
|
-
* Asynchronously collect diffs for a given node and its children.
|
|
2697
|
-
*/
|
|
2698
|
-
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
2699
|
-
// Collect diffs for the files of the current node
|
|
2700
|
-
const diffPromises = node.files.map(async (nodeFile) => {
|
|
2701
|
-
const diff = await getFileDiff(nodeFile);
|
|
2702
|
-
const tokenCount = tokenizer(diff);
|
|
2703
|
-
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
2704
|
-
color: 'magenta',
|
|
2705
|
-
});
|
|
2706
|
-
return {
|
|
2707
|
-
file: nodeFile.filePath,
|
|
2708
|
-
summary: nodeFile.summary,
|
|
2709
|
-
diff,
|
|
2710
|
-
tokenCount,
|
|
2711
|
-
};
|
|
2712
|
-
});
|
|
2713
|
-
// Collect diffs for the children of the current node
|
|
2714
|
-
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
2715
|
-
const [diffs, children] = await Promise.all([
|
|
2716
|
-
Promise.all(diffPromises),
|
|
2717
|
-
Promise.all(childrenPromises),
|
|
2718
|
-
]);
|
|
2719
|
-
return {
|
|
2720
|
-
path: node.getPath(),
|
|
2721
|
-
diffs,
|
|
2722
|
-
children,
|
|
2723
|
-
};
|
|
2724
|
-
}
|
|
2725
|
-
|
|
2726
2632
|
/**
|
|
2727
2633
|
* Base interface that all chains must implement.
|
|
2728
2634
|
*/
|
|
@@ -5971,6 +5877,100 @@ function getTextSplitter(options = {}) {
|
|
|
5971
5877
|
return new RecursiveCharacterTextSplitter(options);
|
|
5972
5878
|
}
|
|
5973
5879
|
|
|
5880
|
+
/**
|
|
5881
|
+
* Asynchronously collect diffs for a given node and its children.
|
|
5882
|
+
*/
|
|
5883
|
+
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
5884
|
+
// Collect diffs for the files of the current node
|
|
5885
|
+
const diffPromises = node.files.map(async (nodeFile) => {
|
|
5886
|
+
const diff = await getFileDiff(nodeFile);
|
|
5887
|
+
const tokenCount = tokenizer(diff);
|
|
5888
|
+
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
5889
|
+
color: 'magenta',
|
|
5890
|
+
});
|
|
5891
|
+
return {
|
|
5892
|
+
file: nodeFile.filePath,
|
|
5893
|
+
summary: nodeFile.summary,
|
|
5894
|
+
diff,
|
|
5895
|
+
tokenCount,
|
|
5896
|
+
};
|
|
5897
|
+
});
|
|
5898
|
+
// Collect diffs for the children of the current node
|
|
5899
|
+
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
5900
|
+
const [diffs, children] = await Promise.all([
|
|
5901
|
+
Promise.all(diffPromises),
|
|
5902
|
+
Promise.all(childrenPromises),
|
|
5903
|
+
]);
|
|
5904
|
+
return {
|
|
5905
|
+
path: node.getPath(),
|
|
5906
|
+
diffs,
|
|
5907
|
+
children,
|
|
5908
|
+
};
|
|
5909
|
+
}
|
|
5910
|
+
|
|
5911
|
+
class DiffTreeNode {
|
|
5912
|
+
constructor(path) {
|
|
5913
|
+
this.path = [];
|
|
5914
|
+
this.files = [];
|
|
5915
|
+
this.children = new Map();
|
|
5916
|
+
if (path)
|
|
5917
|
+
this.path = path;
|
|
5918
|
+
}
|
|
5919
|
+
addFile(file) {
|
|
5920
|
+
this.files.push(file);
|
|
5921
|
+
}
|
|
5922
|
+
addChild(part, node) {
|
|
5923
|
+
this.children.set(part, node);
|
|
5924
|
+
}
|
|
5925
|
+
getChild(part) {
|
|
5926
|
+
return this.children.get(part);
|
|
5927
|
+
}
|
|
5928
|
+
getPath() {
|
|
5929
|
+
return this.path.join('/');
|
|
5930
|
+
}
|
|
5931
|
+
print(indentation = 0) {
|
|
5932
|
+
const indent = ' '.repeat(indentation);
|
|
5933
|
+
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
5934
|
+
if (this.files.length > 0) {
|
|
5935
|
+
output += `${indent} Files:\n`;
|
|
5936
|
+
for (const file of this.files) {
|
|
5937
|
+
output += `${indent} - ${file.summary}\n`;
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5940
|
+
if (this.children.size > 0) {
|
|
5941
|
+
output += `${indent} Children:\n`;
|
|
5942
|
+
for (const [, child] of this.children) {
|
|
5943
|
+
output += child.print(indentation + 4);
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
return output;
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
const createDiffTree = (changes) => {
|
|
5950
|
+
const root = new DiffTreeNode();
|
|
5951
|
+
for (const change of changes) {
|
|
5952
|
+
let currentParent = root;
|
|
5953
|
+
const parts = change.filePath.split('/');
|
|
5954
|
+
parts.pop();
|
|
5955
|
+
for (const part of parts) {
|
|
5956
|
+
let childNode = currentParent.getChild(part);
|
|
5957
|
+
if (!childNode) {
|
|
5958
|
+
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
5959
|
+
currentParent.addChild(part, childNode);
|
|
5960
|
+
}
|
|
5961
|
+
currentParent = childNode;
|
|
5962
|
+
}
|
|
5963
|
+
// Create a NodeFile object and add it to the parent
|
|
5964
|
+
currentParent.addFile({
|
|
5965
|
+
filePath: change.filePath,
|
|
5966
|
+
oldFilePath: change.oldFilePath,
|
|
5967
|
+
summary: change.summary,
|
|
5968
|
+
status: change.status,
|
|
5969
|
+
});
|
|
5970
|
+
}
|
|
5971
|
+
return root;
|
|
5972
|
+
};
|
|
5973
|
+
|
|
5974
5974
|
/**
|
|
5975
5975
|
* Parses the default file diff for a given nodeFile.
|
|
5976
5976
|
*
|
|
@@ -5980,8 +5980,15 @@ function getTextSplitter(options = {}) {
|
|
|
5980
5980
|
* @returns A Promise that resolves to the file diff as a string.
|
|
5981
5981
|
*/
|
|
5982
5982
|
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
5983
|
-
if (commit
|
|
5984
|
-
return await git.diff([
|
|
5983
|
+
if (commit === '--staged') {
|
|
5984
|
+
return await git.diff(['--staged', nodeFile.filePath]);
|
|
5985
|
+
}
|
|
5986
|
+
else if (commit === '--unstaged') {
|
|
5987
|
+
return await git.diff([nodeFile.filePath]);
|
|
5988
|
+
}
|
|
5989
|
+
else if (commit === '--untracked') {
|
|
5990
|
+
// For untracked files, return the entire file content
|
|
5991
|
+
return await git.show([`:${nodeFile.filePath}`]);
|
|
5985
5992
|
}
|
|
5986
5993
|
return await git.diff([commit, nodeFile.filePath]);
|
|
5987
5994
|
}
|
|
@@ -6062,10 +6069,6 @@ async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
|
6062
6069
|
const MAX_TOKENS_PER_SUMMARY = 12288;
|
|
6063
6070
|
async function fileChangeParser({ changes, commit, options: { tokenizer, git, llm: model, logger }, }) {
|
|
6064
6071
|
const textSplitter = getTextSplitter({ chunkSize: 10000, chunkOverlap: 250 });
|
|
6065
|
-
// const textSplitter = new TokenTextSplitter({
|
|
6066
|
-
// chunkSize: 10000,
|
|
6067
|
-
// chunkOverlap: 250,
|
|
6068
|
-
// });
|
|
6069
6072
|
const summarizationChain = getSummarizationChain(model, {
|
|
6070
6073
|
type: 'map_reduce',
|
|
6071
6074
|
combineMapPrompt: SUMMARIZE_PROMPT,
|
|
@@ -6347,7 +6350,10 @@ const handler$2 = async (argv, logger) => {
|
|
|
6347
6350
|
parser,
|
|
6348
6351
|
});
|
|
6349
6352
|
const appendedText = argv.append ? `\n\n${argv.append}` : '';
|
|
6350
|
-
|
|
6353
|
+
const branchName = await getCurrentBranchName({ git });
|
|
6354
|
+
const ticketId = extractTicketIdFromBranchName(branchName);
|
|
6355
|
+
const ticketFooter = argv.appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
|
|
6356
|
+
return `${commitMsg.title}\n\n${commitMsg.body}${appendedText}${ticketFooter}`;
|
|
6351
6357
|
},
|
|
6352
6358
|
noResult: async () => {
|
|
6353
6359
|
await noResult$1({ git, logger });
|
|
@@ -6386,6 +6392,10 @@ const options$2 = {
|
|
|
6386
6392
|
description: 'Add content to the end of the generated commit message',
|
|
6387
6393
|
type: 'string',
|
|
6388
6394
|
},
|
|
6395
|
+
appendTicket: {
|
|
6396
|
+
description: 'Append ticket ID from branch name to the commit message',
|
|
6397
|
+
type: 'boolean',
|
|
6398
|
+
},
|
|
6389
6399
|
additional: {
|
|
6390
6400
|
description: 'Add extra contextual information to the prompt',
|
|
6391
6401
|
type: 'string',
|
|
@@ -6908,13 +6918,25 @@ const handler = async (argv, logger) => {
|
|
|
6908
6918
|
case 'current':
|
|
6909
6919
|
const { staged, unstaged, untracked } = await getChanges({ git });
|
|
6910
6920
|
logger.log(`Staged: ${staged.length}, Unstaged: ${unstaged?.length || 0}, Untracked: ${untracked?.length || 0}`);
|
|
6911
|
-
const
|
|
6912
|
-
changes:
|
|
6913
|
-
commit: '
|
|
6921
|
+
const unstagedChanges = await fileChangeParser({
|
|
6922
|
+
changes: unstaged || [],
|
|
6923
|
+
commit: '--unstaged',
|
|
6924
|
+
options: { tokenizer, git, llm, logger },
|
|
6925
|
+
});
|
|
6926
|
+
const unstagedResponse = `Unstaged changes:\n${unstagedChanges}`;
|
|
6927
|
+
const untrackedChanges = await fileChangeParser({
|
|
6928
|
+
changes: untracked || [],
|
|
6929
|
+
commit: '--untracked',
|
|
6930
|
+
options: { tokenizer, git, llm, logger },
|
|
6931
|
+
});
|
|
6932
|
+
const untrackedResponse = `Untracked changes:\n${untrackedChanges}`;
|
|
6933
|
+
const stagedChanges = await fileChangeParser({
|
|
6934
|
+
changes: staged,
|
|
6935
|
+
commit: '--staged',
|
|
6914
6936
|
options: { tokenizer, git, llm, logger },
|
|
6915
6937
|
});
|
|
6916
|
-
|
|
6917
|
-
return [
|
|
6938
|
+
const stagedResponse = `Staged changes:\n${stagedChanges}`;
|
|
6939
|
+
return [unstagedResponse, untrackedResponse, stagedResponse];
|
|
6918
6940
|
case 'yesterday':
|
|
6919
6941
|
const yesterday = new Date();
|
|
6920
6942
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
@@ -6936,7 +6958,6 @@ const handler = async (argv, logger) => {
|
|
|
6936
6958
|
}
|
|
6937
6959
|
}
|
|
6938
6960
|
async function parser(changes) {
|
|
6939
|
-
console.log({ changes });
|
|
6940
6961
|
return changes.join('\n');
|
|
6941
6962
|
}
|
|
6942
6963
|
const recap = await generateAndReviewLoop({
|