tsdoc/ts/aidocs_classes/commit.ts

135 lines
5.2 KiB
TypeScript
Raw Permalink Normal View History

2024-06-22 11:11:22 +00:00
import * as plugins from '../plugins.js';
import { AiDoc } from '../classes.aidoc.js';
import { ProjectContext } from './projectcontext.js';
2024-06-22 19:21:52 +00:00
export interface INextCommitObject {
2024-06-23 10:20:06 +00:00
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
2024-06-23 10:27:26 +00:00
recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
recommendedNextVersionMessage: string; // the commit message. Don't put fix() feat() or BREAKING CHANGE in the message. Please just the message itself.
recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
2024-06-23 10:27:26 +00:00
recommendedNextVersion: string; // the recommended next version of the project, x.x.x
changelog?: string; // the changelog for the next version
2024-06-22 19:21:52 +00:00
}
2024-06-22 11:11:22 +00:00
export class Commit {
private aiDocsRef: AiDoc;
private projectDir: string;
constructor(aiDocsRef: AiDoc, projectDirArg: string) {
this.aiDocsRef = aiDocsRef;
this.projectDir = projectDirArg;
}
2024-06-22 19:21:52 +00:00
public async buildNextCommitObject(): Promise<INextCommitObject> {
const smartgitInstance = new plugins.smartgit.Smartgit();
await smartgitInstance.init();
const gitRepo = await plugins.smartgit.GitRepo.fromOpeningRepoDir(
smartgitInstance,
this.projectDir
);
const diffStringArray = await gitRepo.getUncommittedDiff([
'pnpm-lock.yaml',
'package-lock.json',
]);
2024-06-22 11:11:22 +00:00
const projectContext = new ProjectContext(this.projectDir);
2024-06-22 19:21:52 +00:00
let contextString = await projectContext.update();
contextString = `
${contextString}
Below is the diff of the uncommitted changes. If nothing is changed, there are no changes:
${diffStringArray[0] ? diffStringArray.join('\n\n') : 'No changes.'}
`;
2024-06-22 11:11:22 +00:00
let result = await this.aiDocsRef.openaiInstance.chat({
systemMessage: `
You create a commit message for a git commit.
The commit message should be based on the files in the project.
You should not include any licensing information.
You should not include any personal information.
Important: Answer only in valid JSON.
Your answer should be parseable with JSON.parse() without modifying anything.
Here is the structure of the JSON you should return:
interface {
2024-06-23 10:20:06 +00:00
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
2024-06-23 10:27:26 +00:00
recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
recommendedNextVersionMessage: string; // the commit message. Don't put fix() feat() or BREAKING CHANGE in the message. Please just the message itself.
recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
2024-06-23 10:27:26 +00:00
recommendedNextVersion: string; // the recommended next version of the project, x.x.x
2024-06-22 11:11:22 +00:00
}
For the recommendedNextVersionDetails, please only add a detail entries to the array if it has an obvious value to the reader.
2024-06-22 11:11:22 +00:00
You are being given the files of the project. You should use them to create the commit message.
Also you are given a diff
`,
messageHistory: [],
userMessage: contextString,
});
2024-06-22 19:21:52 +00:00
// console.log(result.message);
const resultObject: INextCommitObject = JSON.parse(
result.message.replace('```json', '').replace('```', '')
);
2024-06-22 19:21:52 +00:00
const previousChangelogPath = plugins.path.join(this.projectDir, 'changelog.md');
let previousChangelog: plugins.smartfile.SmartFile;
if (await plugins.smartfile.fs.fileExists(previousChangelogPath)) {
previousChangelog = await plugins.smartfile.SmartFile.fromFilePath(previousChangelogPath);
}
if (!previousChangelog) {
// lets build the changelog based on that
const commitMessages = await gitRepo.getAllCommitMessages();
console.log(JSON.stringify(commitMessages, null, 2));
let result2 = await this.aiDocsRef.openaiInstance.chat({
messageHistory: [],
systemMessage: `
You are building a changelog.md file for the project.
Omit commits and versions that lack relevant changes, but make sure to mention them as a range with a summarizing message instead.
2024-06-22 19:21:52 +00:00
A changelog entry should look like this:
2024-06-22 19:21:52 +00:00
## yyyy-mm-dd - x.x.x - scope here
main descriptiom here
- detailed bullet points follow
2024-06-22 11:11:22 +00:00
You are given:
* the commit messages of the project
2024-06-22 11:11:22 +00:00
Only return the changelog file, so it can be written directly to changelog.md`,
userMessage: `
Here are the commit messages:
2024-06-22 11:11:22 +00:00
${JSON.stringify(commitMessages, null, 2)}
`,
});
previousChangelog = await plugins.smartfile.SmartFile.fromString(
previousChangelogPath,
result2.message.replaceAll('```markdown', '').replaceAll('```', ''),
'utf8'
);
}
let oldChangelog = previousChangelog.contents.toString().replace('# Changelog\n\n', '');
if (oldChangelog.startsWith('\n')) {
oldChangelog = oldChangelog.replace('\n', '');
}
let newDateString = new plugins.smarttime.ExtendedDate().exportToHyphedSortableDate();
let newChangelog = `# Changelog\n\n${`## ${newDateString} - {{nextVersion}} - {{nextVersionScope}}
{{nextVersionMessage}}
{{nextVersionDetails}}`}\n\n${oldChangelog}`;
resultObject.changelog = newChangelog;
2024-06-22 19:21:52 +00:00
return resultObject;
2024-06-22 11:11:22 +00:00
}
}