From c9b45492a55b94d5e60eb283f8f2cc8013aa96b5 Mon Sep 17 00:00:00 2001 From: mattsalt123 <93153126+mattsalt123@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:06:23 +0000 Subject: [PATCH 1/7] feat: Add Input Token Limit Config Option (#281) --- README.md | 6 ++-- src/commands/config.ts | 42 ++++++++++++++++++++----- src/engine/openAi.ts | 9 +++--- src/generateCommitMessageFromGitDiff.ts | 15 ++++++--- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3302f11..b92f3a7 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,8 @@ Create a `.env` file and add OpenCommit config variables there like this: ```env OCO_OPENAI_API_KEY= -OCO_OPENAI_MAX_TOKENS= +OCO_TOKENS_MAX_INPUT= +OCO_TOKENS_MAX_OUTPUT= OCO_OPENAI_BASE_PATH= OCO_DESCRIPTION= OCO_EMOJI= @@ -329,7 +330,8 @@ jobs: OCO_OPENAI_API_KEY: ${{ secrets.OCO_OPENAI_API_KEY }} # customization - OCO_OPENAI_MAX_TOKENS: 500 + OCO_TOKENS_MAX_INPUT: 4096 + OCO_TOKENS_MAX_OUTPUT: 500 OCO_OPENAI_BASE_PATH: '' OCO_DESCRIPTION: false OCO_EMOJI: false diff --git a/src/commands/config.ts b/src/commands/config.ts index 49c5383..81c27d3 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -15,7 +15,8 @@ dotenv.config(); export enum CONFIG_KEYS { OCO_OPENAI_API_KEY = 'OCO_OPENAI_API_KEY', - OCO_OPENAI_MAX_TOKENS = 'OCO_OPENAI_MAX_TOKENS', + OCO_TOKENS_MAX_INPUT = 'OCO_TOKENS_MAX_INPUT', + OCO_TOKENS_MAX_OUTPUT = 'OCO_TOKENS_MAX_OUTPUT', OCO_OPENAI_BASE_PATH = 'OCO_OPENAI_BASE_PATH', OCO_DESCRIPTION = 'OCO_DESCRIPTION', OCO_EMOJI = 'OCO_EMOJI', @@ -26,13 +27,16 @@ export enum CONFIG_KEYS { OCO_AI_PROVIDER = 'OCO_AI_PROVIDER', } -export const DEFAULT_MODEL_TOKEN_LIMIT = 4096; - export enum CONFIG_MODES { get = 'get', set = 'set' } +export enum DEFAULT_TOKEN_LIMITS { + DEFAULT_MAX_TOKENS_INPUT = 4096, + DEFAULT_MAX_TOKENS_OUTPUT = 500 +} + const validateConfig = ( key: string, condition: any, @@ -75,18 +79,37 @@ export const configValidators = { return value; }, - [CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS](value: any) { + [CONFIG_KEYS.OCO_TOKENS_MAX_INPUT](value: any) { // If the value is a string, convert it to a number. if (typeof value === 'string') { value = parseInt(value); validateConfig( - CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS, + CONFIG_KEYS.OCO_TOKENS_MAX_INPUT, !isNaN(value), 'Must be a number' ); } validateConfig( - CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS, + CONFIG_KEYS.OCO_TOKENS_MAX_INPUT, + value ? typeof value === 'number' : undefined, + 'Must be a number' + ); + + return value; + }, + + [CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT](value: any) { + // If the value is a string, convert it to a number. + if (typeof value === 'string') { + value = parseInt(value); + validateConfig( + CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT, + !isNaN(value), + 'Must be a number' + ); + } + validateConfig( + CONFIG_KEYS.OCO_TOKENS_MAX_OUTPUT, value ? typeof value === 'number' : undefined, 'Must be a number' ); @@ -178,8 +201,11 @@ const configPath = pathJoin(homedir(), '.opencommit'); export const getConfig = (): ConfigType | null => { const configFromEnv = { OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY, - OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS - ? Number(process.env.OCO_OPENAI_MAX_TOKENS) + OCO_TOKENS_MAX_INPUT: process.env.OCO_TOKENS_MAX_INPUT + ? Number(process.env.OCO_TOKENS_MAX_INPUT) + : undefined, + OCO_TOKENS_MAX_OUTPUT: process.env.OCO_TOKENS_MAX_OUTPUT + ? Number(process.env.OCO_TOKENS_MAX_OUTPUT) : undefined, OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH, OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false, diff --git a/src/engine/openAi.ts b/src/engine/openAi.ts index dc79082..4148073 100644 --- a/src/engine/openAi.ts +++ b/src/engine/openAi.ts @@ -11,7 +11,7 @@ import { intro, outro } from '@clack/prompts'; import { CONFIG_MODES, - DEFAULT_MODEL_TOKEN_LIMIT, + DEFAULT_TOKEN_LIMITS, getConfig } from '../commands/config'; import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff'; @@ -20,7 +20,8 @@ import { AiEngine } from './Engine'; const config = getConfig(); -let maxTokens = config?.OCO_OPENAI_MAX_TOKENS; +const MAX_TOKENS_OUTPUT = config?.OCO_TOKENS_MAX_OUTPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT; +const MAX_TOKENS_INPUT = config?.OCO_TOKENS_MAX_INPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT; let basePath = config?.OCO_OPENAI_BASE_PATH; let apiKey = config?.OCO_OPENAI_API_KEY @@ -65,14 +66,14 @@ class OpenAi implements AiEngine { messages, temperature: 0, top_p: 0.1, - max_tokens: maxTokens || 500 + max_tokens: MAX_TOKENS_OUTPUT }; try { const REQUEST_TOKENS = messages .map((msg) => tokenCount(msg.content) + 4) .reduce((a, b) => a + b, 0); - if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - maxTokens) { + if (REQUEST_TOKENS > MAX_TOKENS_INPUT - MAX_TOKENS_OUTPUT) { throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens); } diff --git a/src/generateCommitMessageFromGitDiff.ts b/src/generateCommitMessageFromGitDiff.ts index 1e381c3..fe7bbfb 100644 --- a/src/generateCommitMessageFromGitDiff.ts +++ b/src/generateCommitMessageFromGitDiff.ts @@ -3,13 +3,15 @@ import { ChatCompletionRequestMessageRoleEnum } from 'openai'; -import { DEFAULT_MODEL_TOKEN_LIMIT, getConfig } from './commands/config'; +import { DEFAULT_TOKEN_LIMITS, getConfig } from './commands/config'; import { getMainCommitPrompt } from './prompts'; import { mergeDiffs } from './utils/mergeDiffs'; import { tokenCount } from './utils/tokenCount'; import { getEngine } from './utils/engine'; const config = getConfig(); +const MAX_TOKENS_INPUT = config?.OCO_TOKENS_MAX_INPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_INPUT; +const MAX_TOKENS_OUTPUT = config?.OCO_TOKENS_MAX_OUTPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT; const generateCommitMessageChatCompletionPrompt = async ( diff: string @@ -29,7 +31,8 @@ const generateCommitMessageChatCompletionPrompt = async ( export enum GenerateCommitMessageErrorEnum { tooMuchTokens = 'TOO_MUCH_TOKENS', internalError = 'INTERNAL_ERROR', - emptyMessage = 'EMPTY_MESSAGE' + emptyMessage = 'EMPTY_MESSAGE', + outputTokensTooHigh = `Token limit exceeded, OCO_TOKENS_MAX_OUTPUT must not be much higher than the default ${DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT} tokens.` } const ADJUSTMENT_FACTOR = 20; @@ -45,10 +48,10 @@ export const generateCommitMessageByDiff = async ( ).reduce((a, b) => a + b, 0); const MAX_REQUEST_TOKENS = - DEFAULT_MODEL_TOKEN_LIMIT - + MAX_TOKENS_INPUT - ADJUSTMENT_FACTOR - INIT_MESSAGES_PROMPT_LENGTH - - config?.OCO_OPENAI_MAX_TOKENS; + MAX_TOKENS_OUTPUT; if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( @@ -124,6 +127,10 @@ function splitDiff(diff: string, maxChangeLength: number) { const splitDiffs = []; let currentDiff = ''; + if (maxChangeLength <= 0) { + throw new Error(GenerateCommitMessageErrorEnum.outputTokensTooHigh); + } + for (let line of lines) { // If a single line exceeds maxChangeLength, split it into multiple lines while (tokenCount(line) > maxChangeLength) { From ec699c48bff7a90dc35d553723ba9f60c852e073 Mon Sep 17 00:00:00 2001 From: Jack Lukic Date: Sun, 3 Mar 2024 06:23:44 -0500 Subject: [PATCH 2/7] Bug (commitling) Parse JSON blocks from return response (#297) --- src/modules/commitlint/config.ts | 4 ++++ src/modules/commitlint/utils.ts | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/modules/commitlint/config.ts b/src/modules/commitlint/config.ts index 71f54db..2f6b076 100644 --- a/src/modules/commitlint/config.ts +++ b/src/modules/commitlint/config.ts @@ -61,6 +61,10 @@ export const configureCommitlintIntegration = async (force = false) => { // Cleanup the consistency answer. Sometimes 'gpt-3.5-turbo' sends rule's back. prompts.forEach((prompt) => (consistency = consistency.replace(prompt, ''))); + + // sometimes consistency is preceded by explanatory text like "Here is your JSON:" + consistency = utils.getJSONBlock(consistency); + // ... remaining might be extra set of "\n" consistency = utils.removeDoubleNewlines(consistency); diff --git a/src/modules/commitlint/utils.ts b/src/modules/commitlint/utils.ts index aba2a71..d46d18b 100644 --- a/src/modules/commitlint/utils.ts +++ b/src/modules/commitlint/utils.ts @@ -16,6 +16,16 @@ export const removeDoubleNewlines = (input: string): string => { return input; }; +export const getJSONBlock = (input: string): string => { + const jsonIndex = input.search('```json'); + if(jsonIndex > -1) { + input = input.slice(jsonIndex + 8); + const endJsonIndex = consistency.search('```'); + input = input.slice(0, endJsonIndex); + } + return input; +}; + export const commitlintLLMConfigExists = async (): Promise => { let exists; try { @@ -44,4 +54,4 @@ export const getCommitlintLLMConfig = content.toString() ) as CommitlintLLMConfig; return commitLintLLMConfig; - }; +}; From 0b5adf104a6b7b1e865d09af5b606f3b8b7cd040 Mon Sep 17 00:00:00 2001 From: di-sukharev Date: Sun, 3 Mar 2024 19:36:23 +0800 Subject: [PATCH 3/7] build --- out/cli.cjs | 70 +++++++++++++++++++++++++++++++++---------- out/github-action.cjs | 70 +++++++++++++++++++++++++++++++++---------- 2 files changed, 110 insertions(+), 30 deletions(-) diff --git a/out/cli.cjs b/out/cli.cjs index e6e6c37..6d64b99 100755 --- a/out/cli.cjs +++ b/out/cli.cjs @@ -18650,7 +18650,6 @@ function getI18nLocal(value) { // src/commands/config.ts dotenv.config(); -var DEFAULT_MODEL_TOKEN_LIMIT = 4096; var validateConfig = (key, condition, validationMessage) => { if (!condition) { ce( @@ -18682,17 +18681,33 @@ var configValidators = { ); return value; }, - ["OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */](value) { + ["OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */](value) { if (typeof value === "string") { value = parseInt(value); validateConfig( - "OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */, + "OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */, !isNaN(value), "Must be a number" ); } validateConfig( - "OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */, + "OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */, + value ? typeof value === "number" : void 0, + "Must be a number" + ); + return value; + }, + ["OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */](value) { + if (typeof value === "string") { + value = parseInt(value); + validateConfig( + "OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */, + !isNaN(value), + "Must be a number" + ); + } + validateConfig( + "OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */, value ? typeof value === "number" : void 0, "Must be a number" ); @@ -18729,9 +18744,10 @@ var configValidators = { "gpt-3.5-turbo", "gpt-4", "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613" + "gpt-3.5-turbo-0613", + "gpt-4-1106-preview" ].includes(value), - `${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'` + `${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo' or 'gpt-4-1106-preview'` ); return value; }, @@ -18768,7 +18784,8 @@ var configPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit"); var getConfig = () => { const configFromEnv = { OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY, - OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS ? Number(process.env.OCO_OPENAI_MAX_TOKENS) : void 0, + OCO_TOKENS_MAX_INPUT: process.env.OCO_TOKENS_MAX_INPUT ? Number(process.env.OCO_TOKENS_MAX_INPUT) : void 0, + OCO_TOKENS_MAX_OUTPUT: process.env.OCO_TOKENS_MAX_OUTPUT ? Number(process.env.OCO_TOKENS_MAX_OUTPUT) : void 0, OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH, OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === "true" ? true : false, OCO_EMOJI: process.env.OCO_EMOJI === "true" ? true : false, @@ -19036,6 +19053,15 @@ var removeDoubleNewlines = (input) => { } return input; }; +var getJSONBlock = (input) => { + const jsonIndex = input.search("```json"); + if (jsonIndex > -1) { + input = input.slice(jsonIndex + 8); + const endJsonIndex = consistency.search("```"); + input = input.slice(0, endJsonIndex); + } + return input; +}; var commitlintLLMConfigExists = async () => { let exists; try { @@ -21899,7 +21925,8 @@ function tokenCount(content) { // src/engine/openAi.ts var config3 = getConfig(); -var maxTokens = config3?.OCO_OPENAI_MAX_TOKENS; +var MAX_TOKENS_OUTPUT = config3?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; +var MAX_TOKENS_INPUT = config3?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; var basePath = config3?.OCO_OPENAI_BASE_PATH; var apiKey = config3?.OCO_OPENAI_API_KEY; var [command, mode] = process.argv.slice(2); @@ -21932,11 +21959,11 @@ var OpenAi = class { messages, temperature: 0, top_p: 0.1, - max_tokens: maxTokens || 500 + max_tokens: MAX_TOKENS_OUTPUT }; try { const REQUEST_TOKENS = messages.map((msg) => tokenCount(msg.content) + 4).reduce((a2, b6) => a2 + b6, 0); - if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - maxTokens) { + if (REQUEST_TOKENS > MAX_TOKENS_INPUT - MAX_TOKENS_OUTPUT) { throw new Error("TOO_MUCH_TOKENS" /* tooMuchTokens */); } const { data } = await this.openAI.createChatCompletion(params); @@ -22020,15 +22047,16 @@ var configureCommitlintIntegration = async (force = false) => { const prompts = inferPromptsFromCommitlintConfig(commitLintConfig); const consistencyPrompts = commitlintPrompts.GEN_COMMITLINT_CONSISTENCY_PROMPT(prompts); const engine = getEngine(); - let consistency = await engine.generateCommitMessage(consistencyPrompts) || "{}"; - prompts.forEach((prompt) => consistency = consistency.replace(prompt, "")); - consistency = removeDoubleNewlines(consistency); + let consistency2 = await engine.generateCommitMessage(consistencyPrompts) || "{}"; + prompts.forEach((prompt) => consistency2 = consistency2.replace(prompt, "")); + consistency2 = getJSONBlock(consistency2); + consistency2 = removeDoubleNewlines(consistency2); const commitlintLLMConfig = { hash, prompts, consistency: { [translation2.localLanguage]: { - ...JSON.parse(consistency) + ...JSON.parse(consistency2) } } }; @@ -22127,6 +22155,8 @@ function mergeDiffs(arr, maxStringLength) { // src/generateCommitMessageFromGitDiff.ts var config6 = getConfig(); +var MAX_TOKENS_INPUT2 = config6?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; +var MAX_TOKENS_OUTPUT2 = config6?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; var generateCommitMessageChatCompletionPrompt = async (diff) => { const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT]; @@ -22136,6 +22166,13 @@ var generateCommitMessageChatCompletionPrompt = async (diff) => { }); return chatContextAsCompletionRequest; }; +var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => { + GenerateCommitMessageErrorEnum2["tooMuchTokens"] = "TOO_MUCH_TOKENS"; + GenerateCommitMessageErrorEnum2["internalError"] = "INTERNAL_ERROR"; + GenerateCommitMessageErrorEnum2["emptyMessage"] = "EMPTY_MESSAGE"; + GenerateCommitMessageErrorEnum2[GenerateCommitMessageErrorEnum2["outputTokensTooHigh"] = `Token limit exceeded, OCO_TOKENS_MAX_OUTPUT must not be much higher than the default ${500 /* DEFAULT_MAX_TOKENS_OUTPUT */} tokens.`] = "outputTokensTooHigh"; + return GenerateCommitMessageErrorEnum2; +})(GenerateCommitMessageErrorEnum || {}); var ADJUSTMENT_FACTOR = 20; var generateCommitMessageByDiff = async (diff) => { try { @@ -22143,7 +22180,7 @@ var generateCommitMessageByDiff = async (diff) => { const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map( (msg) => tokenCount(msg.content) + 4 ).reduce((a2, b6) => a2 + b6, 0); - const MAX_REQUEST_TOKENS = DEFAULT_MODEL_TOKEN_LIMIT - ADJUSTMENT_FACTOR - INIT_MESSAGES_PROMPT_LENGTH - config6?.OCO_OPENAI_MAX_TOKENS; + const MAX_REQUEST_TOKENS = MAX_TOKENS_INPUT2 - ADJUSTMENT_FACTOR - INIT_MESSAGES_PROMPT_LENGTH - MAX_TOKENS_OUTPUT2; if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( diff, @@ -22198,6 +22235,9 @@ function splitDiff(diff, maxChangeLength) { const lines = diff.split("\n"); const splitDiffs = []; let currentDiff = ""; + if (maxChangeLength <= 0) { + throw new Error(GenerateCommitMessageErrorEnum.outputTokensTooHigh); + } for (let line of lines) { while (tokenCount(line) > maxChangeLength) { const subLine = line.substring(0, maxChangeLength); diff --git a/out/github-action.cjs b/out/github-action.cjs index 5e660d2..996decc 100644 --- a/out/github-action.cjs +++ b/out/github-action.cjs @@ -24145,7 +24145,6 @@ function getI18nLocal(value) { // src/commands/config.ts dotenv.config(); -var DEFAULT_MODEL_TOKEN_LIMIT = 4096; var validateConfig = (key, condition, validationMessage) => { if (!condition) { ce( @@ -24177,17 +24176,33 @@ var configValidators = { ); return value; }, - ["OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */](value) { + ["OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */](value) { if (typeof value === "string") { value = parseInt(value); validateConfig( - "OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */, + "OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */, !isNaN(value), "Must be a number" ); } validateConfig( - "OCO_OPENAI_MAX_TOKENS" /* OCO_OPENAI_MAX_TOKENS */, + "OCO_TOKENS_MAX_INPUT" /* OCO_TOKENS_MAX_INPUT */, + value ? typeof value === "number" : void 0, + "Must be a number" + ); + return value; + }, + ["OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */](value) { + if (typeof value === "string") { + value = parseInt(value); + validateConfig( + "OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */, + !isNaN(value), + "Must be a number" + ); + } + validateConfig( + "OCO_TOKENS_MAX_OUTPUT" /* OCO_TOKENS_MAX_OUTPUT */, value ? typeof value === "number" : void 0, "Must be a number" ); @@ -24224,9 +24239,10 @@ var configValidators = { "gpt-3.5-turbo", "gpt-4", "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613" + "gpt-3.5-turbo-0613", + "gpt-4-1106-preview" ].includes(value), - `${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo'` + `${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-16k' (default), 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo' or 'gpt-4-1106-preview'` ); return value; }, @@ -24263,7 +24279,8 @@ var configPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit"); var getConfig = () => { const configFromEnv = { OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY, - OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS ? Number(process.env.OCO_OPENAI_MAX_TOKENS) : void 0, + OCO_TOKENS_MAX_INPUT: process.env.OCO_TOKENS_MAX_INPUT ? Number(process.env.OCO_TOKENS_MAX_INPUT) : void 0, + OCO_TOKENS_MAX_OUTPUT: process.env.OCO_TOKENS_MAX_OUTPUT ? Number(process.env.OCO_TOKENS_MAX_OUTPUT) : void 0, OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH, OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === "true" ? true : false, OCO_EMOJI: process.env.OCO_EMOJI === "true" ? true : false, @@ -24531,6 +24548,15 @@ var removeDoubleNewlines = (input) => { } return input; }; +var getJSONBlock = (input) => { + const jsonIndex = input.search("```json"); + if (jsonIndex > -1) { + input = input.slice(jsonIndex + 8); + const endJsonIndex = consistency.search("```"); + input = input.slice(0, endJsonIndex); + } + return input; +}; var commitlintLLMConfigExists = async () => { let exists; try { @@ -27394,7 +27420,8 @@ function tokenCount(content) { // src/engine/openAi.ts var config3 = getConfig(); -var maxTokens = config3?.OCO_OPENAI_MAX_TOKENS; +var MAX_TOKENS_OUTPUT = config3?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; +var MAX_TOKENS_INPUT = config3?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; var basePath = config3?.OCO_OPENAI_BASE_PATH; var apiKey = config3?.OCO_OPENAI_API_KEY; var [command, mode] = process.argv.slice(2); @@ -27427,11 +27454,11 @@ var OpenAi = class { messages, temperature: 0, top_p: 0.1, - max_tokens: maxTokens || 500 + max_tokens: MAX_TOKENS_OUTPUT }; try { const REQUEST_TOKENS = messages.map((msg) => tokenCount(msg.content) + 4).reduce((a2, b2) => a2 + b2, 0); - if (REQUEST_TOKENS > DEFAULT_MODEL_TOKEN_LIMIT - maxTokens) { + if (REQUEST_TOKENS > MAX_TOKENS_INPUT - MAX_TOKENS_OUTPUT) { throw new Error("TOO_MUCH_TOKENS" /* tooMuchTokens */); } const { data } = await this.openAI.createChatCompletion(params); @@ -27515,15 +27542,16 @@ var configureCommitlintIntegration = async (force = false) => { const prompts = inferPromptsFromCommitlintConfig(commitLintConfig); const consistencyPrompts = commitlintPrompts.GEN_COMMITLINT_CONSISTENCY_PROMPT(prompts); const engine = getEngine(); - let consistency = await engine.generateCommitMessage(consistencyPrompts) || "{}"; - prompts.forEach((prompt) => consistency = consistency.replace(prompt, "")); - consistency = removeDoubleNewlines(consistency); + let consistency2 = await engine.generateCommitMessage(consistencyPrompts) || "{}"; + prompts.forEach((prompt) => consistency2 = consistency2.replace(prompt, "")); + consistency2 = getJSONBlock(consistency2); + consistency2 = removeDoubleNewlines(consistency2); const commitlintLLMConfig = { hash, prompts, consistency: { [translation2.localLanguage]: { - ...JSON.parse(consistency) + ...JSON.parse(consistency2) } } }; @@ -27622,6 +27650,8 @@ function mergeDiffs(arr, maxStringLength) { // src/generateCommitMessageFromGitDiff.ts var config6 = getConfig(); +var MAX_TOKENS_INPUT2 = config6?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; +var MAX_TOKENS_OUTPUT2 = config6?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; var generateCommitMessageChatCompletionPrompt = async (diff) => { const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT]; @@ -27631,6 +27661,13 @@ var generateCommitMessageChatCompletionPrompt = async (diff) => { }); return chatContextAsCompletionRequest; }; +var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => { + GenerateCommitMessageErrorEnum2["tooMuchTokens"] = "TOO_MUCH_TOKENS"; + GenerateCommitMessageErrorEnum2["internalError"] = "INTERNAL_ERROR"; + GenerateCommitMessageErrorEnum2["emptyMessage"] = "EMPTY_MESSAGE"; + GenerateCommitMessageErrorEnum2[GenerateCommitMessageErrorEnum2["outputTokensTooHigh"] = `Token limit exceeded, OCO_TOKENS_MAX_OUTPUT must not be much higher than the default ${500 /* DEFAULT_MAX_TOKENS_OUTPUT */} tokens.`] = "outputTokensTooHigh"; + return GenerateCommitMessageErrorEnum2; +})(GenerateCommitMessageErrorEnum || {}); var ADJUSTMENT_FACTOR = 20; var generateCommitMessageByDiff = async (diff) => { try { @@ -27638,7 +27675,7 @@ var generateCommitMessageByDiff = async (diff) => { const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map( (msg) => tokenCount(msg.content) + 4 ).reduce((a2, b2) => a2 + b2, 0); - const MAX_REQUEST_TOKENS = DEFAULT_MODEL_TOKEN_LIMIT - ADJUSTMENT_FACTOR - INIT_MESSAGES_PROMPT_LENGTH - config6?.OCO_OPENAI_MAX_TOKENS; + const MAX_REQUEST_TOKENS = MAX_TOKENS_INPUT2 - ADJUSTMENT_FACTOR - INIT_MESSAGES_PROMPT_LENGTH - MAX_TOKENS_OUTPUT2; if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( diff, @@ -27693,6 +27730,9 @@ function splitDiff(diff, maxChangeLength) { const lines = diff.split("\n"); const splitDiffs = []; let currentDiff = ""; + if (maxChangeLength <= 0) { + throw new Error(GenerateCommitMessageErrorEnum.outputTokensTooHigh); + } for (let line of lines) { while (tokenCount(line) > maxChangeLength) { const subLine = line.substring(0, maxChangeLength); From 9b7337f67f7d433acfa5886bed12d851e17664c1 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:36:55 +0100 Subject: [PATCH 4/7] Support Gitmoji Format in Commit Messages (#249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ๐Ÿ“ docs(prompts.ts): update prompt message to include information about GitMoji convention and descriptions of changes ๐Ÿ“ docs(prompts.ts): update prompt message to include information about GitMoji convention and descriptions of changes * ๐ŸŽจ (prompts.ts): import `removeConventionalCommitWord` function to remove conventional commit word from commit prompts ๐Ÿ› (prompts.ts): remove conventional commit word from `commitFix` and `commitFeat` prompts to improve clarity ๐Ÿ“ (removeConventionalCommitWord.ts): add `removeConventionalCommitWord` function to remove conventional commit word from commit message * ๐Ÿ“ (package.json): update version from 3.0.3 to 3.0.0 to align with the latest release * ๐Ÿ”ง (cli.ts): add a new flag 'fgm' to the 'flags' object to support the '--fgm' flag in the CLI command ๐Ÿ”ง (commit.ts): pass the value of the 'fgm' flag to the 'commit' function to enable or disable full GitMoji specification โ™ป๏ธ (commit.ts): refactor the 'commit' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'commit' function recursively โ™ป๏ธ (generateCommitMessageFromGitDiff.ts): refactor the 'generateCommitMessageByDiff' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'generateCommitMessageChatCompletionPrompt' function โ™ป๏ธ (generateCommitMessageFromGitDiff.ts): refactor the 'generateCommitMessageChatCompletionPrompt' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'getMainCommitPrompt' function โ™ป๏ธ (generateCommitMessageFromGitDiff.ts): refactor the 'getCommitMsgsPromisesFromFileDiffs' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'getMessagesPromisesByChangesInFile' function โ™ป๏ธ (generateCommitMessageFromGitDiff.ts): refactor the 'getMessagesPromisesByChangesInFile' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'generateCommitMessageChatCompletionPrompt' function โ™ป๏ธ (prompts.ts): refactor the 'getMainCommitPrompt' function to accept the 'fullGitMojiSpec' parameter and pass it to the 'INIT_MAIN_PROMPT' function * ๐Ÿ“ (README.md): add documentation for the `--fgm` flag in the `oco` command to enable the use of the full GitMoji specification * ๐Ÿ“ (README.md): update flag description for using full GitMoji specification ๐Ÿ“ (README.md): add link to the GitMoji specification for reference * ๐Ÿ”ง (README.md): fix a typo in the description of the `Use Full GitMoji Specification` flag ๐Ÿ”ง (api.ts): update the default value of the `apiKey` variable to a placeholder value for testing purposes * Revert "๐Ÿ”ง (README.md): fix a typo in the description of the `Use Full GitMoji Specification` flag" This reverts commit 230a4aa449b4718063db22f7aa835bbb68dc1a88. * ๐Ÿ”ง (README.md): fix a typo in the description of the `Use Full GitMoji Specification` flag * ๐Ÿ“ (prompts.ts): update INIT_MAIN_PROMPT content to include information about the fullGitMojiSpec flag and provide instructions on how to choose the right emoji for the commit message --------- Co-authored-by: GPT10 <57486732+di-sukharev@users.noreply.github.com> --- README.md | 13 +++ src/cli.ts | 8 +- src/commands/commit.ts | 15 +-- src/generateCommitMessageFromGitDiff.ts | 30 ++++-- src/prompts.ts | 118 +++++++++++++++++++--- src/utils/removeConventionalCommitWord.ts | 3 + 6 files changed, 154 insertions(+), 33 deletions(-) create mode 100644 src/utils/removeConventionalCommitWord.ts diff --git a/README.md b/README.md index b92f3a7..2e2e389 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ git add oco ``` +Link to the GitMoji specification: https://gitmoji.dev/ + You can also run it with local model through ollama: - install and start ollama @@ -69,6 +71,17 @@ git add AI_PROVIDER='ollama' opencommit ``` +### Flags +There are multiple optional flags that can be used with the `oco` command: + +#### Use Full GitMoji Specification +This flag can only be used if the `OCO_EMOJI` configuration item is set to `true`. This flag allows users to use all emojis in the GitMoji specification, By default, the GitMoji full specification is set to `false`, which only includes 10 emojis (๐Ÿ›โœจ๐Ÿ“๐Ÿš€โœ…โ™ป๏ธโฌ†๏ธ๐Ÿ”ง๐ŸŒ๐Ÿ’ก). +This is due to limit the number of tokens sent in each request. However, if you would like to use the full GitMoji specification, you can use the `--fgm` flag. + +``` +oco --fgm +``` + ## Configuration ### Local per repo configuration diff --git a/src/cli.ts b/src/cli.ts index 5d77666..7baf6e3 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -17,17 +17,19 @@ cli( version: packageJSON.version, name: 'opencommit', commands: [configCommand, hookCommand, commitlintConfigCommand], - flags: {}, + flags: { + fgm: Boolean + }, ignoreArgv: (type) => type === 'unknown-flag' || type === 'argument', help: { description: packageJSON.description } }, - async () => { + async ({ flags }) => { await checkIsLatestVersion(); if (await isHookCalled()) { prepareCommitMessageHook(); } else { - commit(extraArgs); + commit(extraArgs, flags.fgm); } }, extraArgs diff --git a/src/commands/commit.ts b/src/commands/commit.ts index 10ce123..9b696ed 100644 --- a/src/commands/commit.ts +++ b/src/commands/commit.ts @@ -40,14 +40,15 @@ const checkMessageTemplate = (extraArgs: string[]): string | false => { const generateCommitMessageFromGitDiff = async ( diff: string, - extraArgs: string[] + extraArgs: string[], + fullGitMojiSpec: boolean ): Promise => { await assertGitRepo(); const commitSpinner = spinner(); commitSpinner.start('Generating the commit message'); try { - let commitMessage = await generateCommitMessageByDiff(diff); + let commitMessage = await generateCommitMessageByDiff(diff, fullGitMojiSpec); const messageTemplate = checkMessageTemplate(extraArgs); if ( @@ -154,7 +155,8 @@ ${chalk.grey('โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”')}` export async function commit( extraArgs: string[] = [], - isStageAllFlag: Boolean = false + fullGitMojiSpec: boolean = false, + isStageAllFlag: Boolean = false, ) { if (isStageAllFlag) { const changedFiles = await getChangedFiles(); @@ -194,7 +196,7 @@ export async function commit( isStageAllAndCommitConfirmedByUser && !isCancel(isStageAllAndCommitConfirmedByUser) ) { - await commit(extraArgs, true); + await commit(extraArgs, true, fullGitMojiSpec); process.exit(1); } @@ -212,7 +214,7 @@ export async function commit( await gitAdd({ files }); } - await commit(extraArgs, false); + await commit(extraArgs, false, fullGitMojiSpec); process.exit(1); } @@ -225,7 +227,8 @@ export async function commit( const [, generateCommitError] = await trytm( generateCommitMessageFromGitDiff( await getDiff({ files: stagedFiles }), - extraArgs + extraArgs, + fullGitMojiSpec ) ); diff --git a/src/generateCommitMessageFromGitDiff.ts b/src/generateCommitMessageFromGitDiff.ts index fe7bbfb..d953df8 100644 --- a/src/generateCommitMessageFromGitDiff.ts +++ b/src/generateCommitMessageFromGitDiff.ts @@ -14,9 +14,10 @@ const MAX_TOKENS_INPUT = config?.OCO_TOKENS_MAX_INPUT || DEFAULT_TOKEN_LIMITS.DE const MAX_TOKENS_OUTPUT = config?.OCO_TOKENS_MAX_OUTPUT || DEFAULT_TOKEN_LIMITS.DEFAULT_MAX_TOKENS_OUTPUT; const generateCommitMessageChatCompletionPrompt = async ( - diff: string + diff: string, + fullGitMojiSpec: boolean ): Promise> => { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT]; @@ -38,10 +39,11 @@ export enum GenerateCommitMessageErrorEnum { const ADJUSTMENT_FACTOR = 20; export const generateCommitMessageByDiff = async ( - diff: string + diff: string, + fullGitMojiSpec: boolean ): Promise => { try { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map( (msg) => tokenCount(msg.content) + 4 @@ -56,7 +58,8 @@ export const generateCommitMessageByDiff = async ( if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( diff, - MAX_REQUEST_TOKENS + MAX_REQUEST_TOKENS, + fullGitMojiSpec ); const commitMessages = []; @@ -68,7 +71,7 @@ export const generateCommitMessageByDiff = async ( return commitMessages.join('\n\n'); } - const messages = await generateCommitMessageChatCompletionPrompt(diff); + const messages = await generateCommitMessageChatCompletionPrompt(diff, fullGitMojiSpec); const engine = getEngine() const commitMessage = await engine.generateCommitMessage(messages); @@ -85,7 +88,8 @@ export const generateCommitMessageByDiff = async ( function getMessagesPromisesByChangesInFile( fileDiff: string, separator: string, - maxChangeLength: number + maxChangeLength: number, + fullGitMojiSpec: boolean ) { const hunkHeaderSeparator = '@@ '; const [fileHeader, ...fileDiffByLines] = fileDiff.split(hunkHeaderSeparator); @@ -112,7 +116,8 @@ function getMessagesPromisesByChangesInFile( const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map( async (lineDiff) => { const messages = await generateCommitMessageChatCompletionPrompt( - separator + lineDiff + separator + lineDiff, + fullGitMojiSpec ); return engine.generateCommitMessage(messages); @@ -160,7 +165,8 @@ function splitDiff(diff: string, maxChangeLength: number) { export const getCommitMsgsPromisesFromFileDiffs = async ( diff: string, - maxDiffLength: number + maxDiffLength: number, + fullGitMojiSpec: boolean ) => { const separator = 'diff --git '; @@ -177,13 +183,15 @@ export const getCommitMsgsPromisesFromFileDiffs = async ( const messagesPromises = getMessagesPromisesByChangesInFile( fileDiff, separator, - maxDiffLength + maxDiffLength, + fullGitMojiSpec ); commitMessagePromises.push(...messagesPromises); } else { const messages = await generateCommitMessageChatCompletionPrompt( - separator + fileDiff + separator + fileDiff, + fullGitMojiSpec ); const engine = getEngine() diff --git a/src/prompts.ts b/src/prompts.ts index 243ee86..f2d35fc 100644 --- a/src/prompts.ts +++ b/src/prompts.ts @@ -11,6 +11,7 @@ import { configureCommitlintIntegration } from './modules/commitlint/config'; import { commitlintPrompts } from './modules/commitlint/prompts'; import { ConsistencyPrompt } from './modules/commitlint/types'; import * as utils from './modules/commitlint/utils'; +import { removeConventionalCommitWord } from './utils/removeConventionalCommitWord'; const config = getConfig(); const translation = i18n[(config?.OCO_LANGUAGE as I18nLocals) || 'en']; @@ -18,14 +19,97 @@ const translation = i18n[(config?.OCO_LANGUAGE as I18nLocals) || 'en']; export const IDENTITY = 'You are to act as the author of a commit message in git.'; -const INIT_MAIN_PROMPT = (language: string): ChatCompletionRequestMessage => ({ +const INIT_MAIN_PROMPT = ( + language: string, + fullGitMojiSpec: boolean +): ChatCompletionRequestMessage => ({ role: ChatCompletionRequestMessageRoleEnum.System, - content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the conventional commit convention and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. - ${ - config?.OCO_EMOJI - ? 'Use GitMoji convention to preface the commit.' - : 'Do not preface the commit with anything.' - } + content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the ${ + fullGitMojiSpec ? 'GitMoji specification' : 'conventional commit convention' + } and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. + ${ + config?.OCO_EMOJI + ? 'Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): ' + + '๐Ÿ›, Fix a bug; ' + + 'โœจ, Introduce new features; ' + + '๐Ÿ“, Add or update documentation; ' + + '๐Ÿš€, Deploy stuff; ' + + 'โœ…, Add, update, or pass tests; ' + + 'โ™ป๏ธ, Refactor code; ' + + 'โฌ†๏ธ, Upgrade dependencies; ' + + '๐Ÿ”ง, Add or update configuration files; ' + + '๐ŸŒ, Internationalization and localization; ' + + '๐Ÿ’ก, Add or update comments in source code; ' + + `${ + fullGitMojiSpec + ? '๐ŸŽจ, Improve structure / format of the code; ' + + 'โšก๏ธ, Improve performance; ' + + '๐Ÿ”ฅ, Remove code or files; ' + + '๐Ÿš‘๏ธ, Critical hotfix; ' + + '๐Ÿ’„, Add or update the UI and style files; ' + + '๐ŸŽ‰, Begin a project; ' + + '๐Ÿ”’๏ธ, Fix security issues; ' + + '๐Ÿ”, Add or update secrets; ' + + '๐Ÿ”–, Release / Version tags; ' + + '๐Ÿšจ, Fix compiler / linter warnings; ' + + '๐Ÿšง, Work in progress; ' + + '๐Ÿ’š, Fix CI Build; ' + + 'โฌ‡๏ธ, Downgrade dependencies; ' + + '๐Ÿ“Œ, Pin dependencies to specific versions; ' + + '๐Ÿ‘ท, Add or update CI build system; ' + + '๐Ÿ“ˆ, Add or update analytics or track code; ' + + 'โž•, Add a dependency; ' + + 'โž–, Remove a dependency; ' + + '๐Ÿ”จ, Add or update development scripts; ' + + 'โœ๏ธ, Fix typos; ' + + '๐Ÿ’ฉ, Write bad code that needs to be improved; ' + + 'โช๏ธ, Revert changes; ' + + '๐Ÿ”€, Merge branches; ' + + '๐Ÿ“ฆ๏ธ, Add or update compiled files or packages; ' + + '๐Ÿ‘ฝ๏ธ, Update code due to external API changes; ' + + '๐Ÿšš, Move or rename resources (e.g.: files, paths, routes); ' + + '๐Ÿ“„, Add or update license; ' + + '๐Ÿ’ฅ, Introduce breaking changes; ' + + '๐Ÿฑ, Add or update assets; ' + + 'โ™ฟ๏ธ, Improve accessibility; ' + + '๐Ÿป, Write code drunkenly; ' + + '๐Ÿ’ฌ, Add or update text and literals; ' + + '๐Ÿ—ƒ๏ธ, Perform database related changes; ' + + '๐Ÿ”Š, Add or update logs; ' + + '๐Ÿ”‡, Remove logs; ' + + '๐Ÿ‘ฅ, Add or update contributor(s); ' + + '๐Ÿšธ, Improve user experience / usability; ' + + '๐Ÿ—๏ธ, Make architectural changes; ' + + '๐Ÿ“ฑ, Work on responsive design; ' + + '๐Ÿคก, Mock things; ' + + '๐Ÿฅš, Add or update an easter egg; ' + + '๐Ÿ™ˆ, Add or update a .gitignore file; ' + + '๐Ÿ“ธ, Add or update snapshots; ' + + 'โš—๏ธ, Perform experiments; ' + + '๐Ÿ”๏ธ, Improve SEO; ' + + '๐Ÿท๏ธ, Add or update types; ' + + '๐ŸŒฑ, Add or update seed files; ' + + '๐Ÿšฉ, Add, update, or remove feature flags; ' + + '๐Ÿฅ…, Catch errors; ' + + '๐Ÿ’ซ, Add or update animations and transitions; ' + + '๐Ÿ—‘๏ธ, Deprecate code that needs to be cleaned up; ' + + '๐Ÿ›‚, Work on code related to authorization, roles and permissions; ' + + '๐Ÿฉน, Simple fix for a non-critical issue; ' + + '๐Ÿง, Data exploration/inspection; ' + + 'โšฐ๏ธ, Remove dead code; ' + + '๐Ÿงช, Add a failing test; ' + + '๐Ÿ‘”, Add or update business logic; ' + + '๐Ÿฉบ, Add or update healthcheck; ' + + '๐Ÿงฑ, Infrastructure related changes; ' + + '๐Ÿง‘โ€๐Ÿ’ป, Improve developer experience; ' + + '๐Ÿ’ธ, Add sponsorships or money related infrastructure; ' + + '๐Ÿงต, Add or update code related to multithreading or concurrency; ' + + '๐Ÿฆบ, Add or update code related to validation.' + : '' + }` + : 'Do not preface the commit with anything. Conventional commit keywords:' + + 'fix, feat, build, chore, ci, docs, style, refactor, perf, test.' + } ${ config?.OCO_DESCRIPTION ? 'Add a short description of WHY the changes are done after the commit message. Don\'t start it with "This commit", just describe the changes.' @@ -66,14 +150,22 @@ const INIT_CONSISTENCY_PROMPT = ( translation: ConsistencyPrompt ): ChatCompletionRequestMessage => ({ role: ChatCompletionRequestMessageRoleEnum.Assistant, - content: `${config?.OCO_EMOJI ? '๐Ÿ› ' : ''}${translation.commitFix} -${config?.OCO_EMOJI ? 'โœจ ' : ''}${translation.commitFeat} + content: `${ + config?.OCO_EMOJI + ? `๐Ÿ› ${removeConventionalCommitWord(translation.commitFix)}` + : translation.commitFix + } +${ + config?.OCO_EMOJI + ? `โœจ ${removeConventionalCommitWord(translation.commitFeat)}` + : translation.commitFeat +} ${config?.OCO_DESCRIPTION ? translation.commitDescription : ''}` }); -export const getMainCommitPrompt = async (): Promise< - ChatCompletionRequestMessage[] -> => { +export const getMainCommitPrompt = async ( + fullGitMojiSpec: boolean +): Promise => { switch (config?.OCO_PROMPT_MODULE) { case '@commitlint': if (!(await utils.commitlintLLMConfigExists())) { @@ -102,7 +194,7 @@ export const getMainCommitPrompt = async (): Promise< default: // conventional-commit return [ - INIT_MAIN_PROMPT(translation.localLanguage), + INIT_MAIN_PROMPT(translation.localLanguage, fullGitMojiSpec), INIT_DIFF_PROMPT, INIT_CONSISTENCY_PROMPT(translation) ]; diff --git a/src/utils/removeConventionalCommitWord.ts b/src/utils/removeConventionalCommitWord.ts new file mode 100644 index 0000000..3010e1c --- /dev/null +++ b/src/utils/removeConventionalCommitWord.ts @@ -0,0 +1,3 @@ +export function removeConventionalCommitWord(message: string): string { + return message.replace(/^(fix|feat)\((.+?)\):/, '($2):'); +} From 3d49081f6d50b4377ff8940041d902388797dbab Mon Sep 17 00:00:00 2001 From: di-sukharev Date: Sun, 3 Mar 2024 19:39:00 +0800 Subject: [PATCH 5/7] build --- out/cli.cjs | 66 +++++++++++++++++++++++++------------------ out/github-action.cjs | 45 +++++++++++++++++------------ 2 files changed, 66 insertions(+), 45 deletions(-) diff --git a/out/cli.cjs b/out/cli.cjs index 6d64b99..db2cf3e 100755 --- a/out/cli.cjs +++ b/out/cli.cjs @@ -22064,14 +22064,19 @@ var configureCommitlintIntegration = async (force = false) => { spin.stop(`Done - please review contents of ${COMMITLINT_LLM_CONFIG_PATH}`); }; +// src/utils/removeConventionalCommitWord.ts +function removeConventionalCommitWord(message) { + return message.replace(/^(fix|feat)\((.+?)\):/, "($2):"); +} + // src/prompts.ts var config5 = getConfig(); var translation3 = i18n[config5?.OCO_LANGUAGE || "en"]; var IDENTITY = "You are to act as the author of a commit message in git."; -var INIT_MAIN_PROMPT2 = (language) => ({ +var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({ role: import_openai3.ChatCompletionRequestMessageRoleEnum.System, - content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the conventional commit convention and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. - ${config5?.OCO_EMOJI ? "Use GitMoji convention to preface the commit." : "Do not preface the commit with anything."} + content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the ${fullGitMojiSpec ? "GitMoji specification" : "conventional commit convention"} and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. + ${config5?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."} ${config5?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."} Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.` }); @@ -22104,11 +22109,11 @@ var INIT_DIFF_PROMPT = { }; var INIT_CONSISTENCY_PROMPT = (translation4) => ({ role: import_openai3.ChatCompletionRequestMessageRoleEnum.Assistant, - content: `${config5?.OCO_EMOJI ? "\u{1F41B} " : ""}${translation4.commitFix} -${config5?.OCO_EMOJI ? "\u2728 " : ""}${translation4.commitFeat} + content: `${config5?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix} +${config5?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat} ${config5?.OCO_DESCRIPTION ? translation4.commitDescription : ""}` }); -var getMainCommitPrompt = async () => { +var getMainCommitPrompt = async (fullGitMojiSpec) => { switch (config5?.OCO_PROMPT_MODULE) { case "@commitlint": if (!await commitlintLLMConfigExists()) { @@ -22130,7 +22135,7 @@ var getMainCommitPrompt = async () => { ]; default: return [ - INIT_MAIN_PROMPT2(translation3.localLanguage), + INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec), INIT_DIFF_PROMPT, INIT_CONSISTENCY_PROMPT(translation3) ]; @@ -22157,8 +22162,8 @@ function mergeDiffs(arr, maxStringLength) { var config6 = getConfig(); var MAX_TOKENS_INPUT2 = config6?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; var MAX_TOKENS_OUTPUT2 = config6?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; -var generateCommitMessageChatCompletionPrompt = async (diff) => { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); +var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => { + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT]; chatContextAsCompletionRequest.push({ role: import_openai4.ChatCompletionRequestMessageRoleEnum.User, @@ -22174,9 +22179,9 @@ var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => { return GenerateCommitMessageErrorEnum2; })(GenerateCommitMessageErrorEnum || {}); var ADJUSTMENT_FACTOR = 20; -var generateCommitMessageByDiff = async (diff) => { +var generateCommitMessageByDiff = async (diff, fullGitMojiSpec) => { try { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map( (msg) => tokenCount(msg.content) + 4 ).reduce((a2, b6) => a2 + b6, 0); @@ -22184,7 +22189,8 @@ var generateCommitMessageByDiff = async (diff) => { if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( diff, - MAX_REQUEST_TOKENS + MAX_REQUEST_TOKENS, + fullGitMojiSpec ); const commitMessages = []; for (const promise of commitMessagePromises) { @@ -22193,7 +22199,7 @@ var generateCommitMessageByDiff = async (diff) => { } return commitMessages.join("\n\n"); } - const messages = await generateCommitMessageChatCompletionPrompt(diff); + const messages = await generateCommitMessageChatCompletionPrompt(diff, fullGitMojiSpec); const engine = getEngine(); const commitMessage = await engine.generateCommitMessage(messages); if (!commitMessage) @@ -22203,7 +22209,7 @@ var generateCommitMessageByDiff = async (diff) => { throw error; } }; -function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength) { +function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength, fullGitMojiSpec) { const hunkHeaderSeparator = "@@ "; const [fileHeader, ...fileDiffByLines] = fileDiff.split(hunkHeaderSeparator); const mergedChanges = mergeDiffs( @@ -22224,7 +22230,8 @@ function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map( async (lineDiff) => { const messages = await generateCommitMessageChatCompletionPrompt( - separator + lineDiff + separator + lineDiff, + fullGitMojiSpec ); return engine.generateCommitMessage(messages); } @@ -22256,7 +22263,7 @@ function splitDiff(diff, maxChangeLength) { } return splitDiffs; } -var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength) => { +var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength, fullGitMojiSpec) => { const separator = "diff --git "; const diffByFiles = diff.split(separator).slice(1); const mergedFilesDiffs = mergeDiffs(diffByFiles, maxDiffLength); @@ -22266,12 +22273,14 @@ var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength) => { const messagesPromises = getMessagesPromisesByChangesInFile( fileDiff, separator, - maxDiffLength + maxDiffLength, + fullGitMojiSpec ); commitMessagePromises.push(...messagesPromises); } else { const messages = await generateCommitMessageChatCompletionPrompt( - separator + fileDiff + separator + fileDiff, + fullGitMojiSpec ); const engine = getEngine(); commitMessagePromises.push(engine.generateCommitMessage(messages)); @@ -22393,12 +22402,12 @@ var checkMessageTemplate = (extraArgs2) => { } return false; }; -var generateCommitMessageFromGitDiff = async (diff, extraArgs2) => { +var generateCommitMessageFromGitDiff = async (diff, extraArgs2, fullGitMojiSpec) => { await assertGitRepo(); const commitSpinner = le(); commitSpinner.start("Generating the commit message"); try { - let commitMessage = await generateCommitMessageByDiff(diff); + let commitMessage = await generateCommitMessageByDiff(diff, fullGitMojiSpec); const messageTemplate = checkMessageTemplate(extraArgs2); if (config7?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") { commitMessage = messageTemplate.replace( @@ -22480,7 +22489,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2 process.exit(1); } }; -async function commit(extraArgs2 = [], isStageAllFlag = false) { +async function commit(extraArgs2 = [], fullGitMojiSpec = false, isStageAllFlag = false) { if (isStageAllFlag) { const changedFiles2 = await getChangedFiles(); if (changedFiles2) @@ -22509,7 +22518,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false) { message: "Do you want to stage all files and generate commit message?" }); if (isStageAllAndCommitConfirmedByUser && !eD2(isStageAllAndCommitConfirmedByUser)) { - await commit(extraArgs2, true); + await commit(extraArgs2, true, fullGitMojiSpec); process.exit(1); } if (stagedFiles.length === 0 && changedFiles.length > 0) { @@ -22524,7 +22533,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false) { process.exit(1); await gitAdd({ files }); } - await commit(extraArgs2, false); + await commit(extraArgs2, false, fullGitMojiSpec); process.exit(1); } stagedFilesSpinner.stop( @@ -22534,7 +22543,8 @@ ${stagedFiles.map((file) => ` ${file}`).join("\n")}` const [, generateCommitError] = await trytm( generateCommitMessageFromGitDiff( await getDiff({ files: stagedFiles }), - extraArgs2 + extraArgs2, + fullGitMojiSpec ) ); if (generateCommitError) { @@ -22740,16 +22750,18 @@ Z2( version: package_default.version, name: "opencommit", commands: [configCommand, hookCommand, commitlintConfigCommand], - flags: {}, + flags: { + fgm: Boolean + }, ignoreArgv: (type) => type === "unknown-flag" || type === "argument", help: { description: package_default.description } }, - async () => { + async ({ flags }) => { await checkIsLatestVersion(); if (await isHookCalled()) { prepareCommitMessageHook(); } else { - commit(extraArgs); + commit(extraArgs, flags.fgm); } }, extraArgs diff --git a/out/github-action.cjs b/out/github-action.cjs index 996decc..9ee7c66 100644 --- a/out/github-action.cjs +++ b/out/github-action.cjs @@ -27559,14 +27559,19 @@ var configureCommitlintIntegration = async (force = false) => { spin.stop(`Done - please review contents of ${COMMITLINT_LLM_CONFIG_PATH}`); }; +// src/utils/removeConventionalCommitWord.ts +function removeConventionalCommitWord(message) { + return message.replace(/^(fix|feat)\((.+?)\):/, "($2):"); +} + // src/prompts.ts var config5 = getConfig(); var translation3 = i18n[config5?.OCO_LANGUAGE || "en"]; var IDENTITY = "You are to act as the author of a commit message in git."; -var INIT_MAIN_PROMPT2 = (language) => ({ +var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({ role: import_openai3.ChatCompletionRequestMessageRoleEnum.System, - content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the conventional commit convention and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. - ${config5?.OCO_EMOJI ? "Use GitMoji convention to preface the commit." : "Do not preface the commit with anything."} + content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the ${fullGitMojiSpec ? "GitMoji specification" : "conventional commit convention"} and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message. + ${config5?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."} ${config5?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."} Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.` }); @@ -27599,11 +27604,11 @@ var INIT_DIFF_PROMPT = { }; var INIT_CONSISTENCY_PROMPT = (translation4) => ({ role: import_openai3.ChatCompletionRequestMessageRoleEnum.Assistant, - content: `${config5?.OCO_EMOJI ? "\u{1F41B} " : ""}${translation4.commitFix} -${config5?.OCO_EMOJI ? "\u2728 " : ""}${translation4.commitFeat} + content: `${config5?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix} +${config5?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat} ${config5?.OCO_DESCRIPTION ? translation4.commitDescription : ""}` }); -var getMainCommitPrompt = async () => { +var getMainCommitPrompt = async (fullGitMojiSpec) => { switch (config5?.OCO_PROMPT_MODULE) { case "@commitlint": if (!await commitlintLLMConfigExists()) { @@ -27625,7 +27630,7 @@ var getMainCommitPrompt = async () => { ]; default: return [ - INIT_MAIN_PROMPT2(translation3.localLanguage), + INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec), INIT_DIFF_PROMPT, INIT_CONSISTENCY_PROMPT(translation3) ]; @@ -27652,8 +27657,8 @@ function mergeDiffs(arr, maxStringLength) { var config6 = getConfig(); var MAX_TOKENS_INPUT2 = config6?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */; var MAX_TOKENS_OUTPUT2 = config6?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */; -var generateCommitMessageChatCompletionPrompt = async (diff) => { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); +var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => { + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT]; chatContextAsCompletionRequest.push({ role: import_openai4.ChatCompletionRequestMessageRoleEnum.User, @@ -27669,9 +27674,9 @@ var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => { return GenerateCommitMessageErrorEnum2; })(GenerateCommitMessageErrorEnum || {}); var ADJUSTMENT_FACTOR = 20; -var generateCommitMessageByDiff = async (diff) => { +var generateCommitMessageByDiff = async (diff, fullGitMojiSpec) => { try { - const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(); + const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec); const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map( (msg) => tokenCount(msg.content) + 4 ).reduce((a2, b2) => a2 + b2, 0); @@ -27679,7 +27684,8 @@ var generateCommitMessageByDiff = async (diff) => { if (tokenCount(diff) >= MAX_REQUEST_TOKENS) { const commitMessagePromises = await getCommitMsgsPromisesFromFileDiffs( diff, - MAX_REQUEST_TOKENS + MAX_REQUEST_TOKENS, + fullGitMojiSpec ); const commitMessages = []; for (const promise of commitMessagePromises) { @@ -27688,7 +27694,7 @@ var generateCommitMessageByDiff = async (diff) => { } return commitMessages.join("\n\n"); } - const messages = await generateCommitMessageChatCompletionPrompt(diff); + const messages = await generateCommitMessageChatCompletionPrompt(diff, fullGitMojiSpec); const engine = getEngine(); const commitMessage = await engine.generateCommitMessage(messages); if (!commitMessage) @@ -27698,7 +27704,7 @@ var generateCommitMessageByDiff = async (diff) => { throw error; } }; -function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength) { +function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength, fullGitMojiSpec) { const hunkHeaderSeparator = "@@ "; const [fileHeader, ...fileDiffByLines] = fileDiff.split(hunkHeaderSeparator); const mergedChanges = mergeDiffs( @@ -27719,7 +27725,8 @@ function getMessagesPromisesByChangesInFile(fileDiff, separator, maxChangeLength const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map( async (lineDiff) => { const messages = await generateCommitMessageChatCompletionPrompt( - separator + lineDiff + separator + lineDiff, + fullGitMojiSpec ); return engine.generateCommitMessage(messages); } @@ -27751,7 +27758,7 @@ function splitDiff(diff, maxChangeLength) { } return splitDiffs; } -var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength) => { +var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength, fullGitMojiSpec) => { const separator = "diff --git "; const diffByFiles = diff.split(separator).slice(1); const mergedFilesDiffs = mergeDiffs(diffByFiles, maxDiffLength); @@ -27761,12 +27768,14 @@ var getCommitMsgsPromisesFromFileDiffs = async (diff, maxDiffLength) => { const messagesPromises = getMessagesPromisesByChangesInFile( fileDiff, separator, - maxDiffLength + maxDiffLength, + fullGitMojiSpec ); commitMessagePromises.push(...messagesPromises); } else { const messages = await generateCommitMessageChatCompletionPrompt( - separator + fileDiff + separator + fileDiff, + fullGitMojiSpec ); const engine = getEngine(); commitMessagePromises.push(engine.generateCommitMessage(messages)); From c1797de3da38cbfd8f4458b1f212826878ed33a0 Mon Sep 17 00:00:00 2001 From: di-sukharev Date: Sun, 3 Mar 2024 19:43:15 +0800 Subject: [PATCH 6/7] build --- out/cli.cjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/out/cli.cjs b/out/cli.cjs index db2cf3e..62f4ebd 100755 --- a/out/cli.cjs +++ b/out/cli.cjs @@ -16455,8 +16455,8 @@ var package_default = { "@dqbd/tiktoken": "^1.0.2", "@octokit/webhooks-schemas": "^6.11.0", "@octokit/webhooks-types": "^6.11.0", - ai: "^2.2.14", axios: "^1.3.4", + ai: "^2.2.14", chalk: "^5.2.0", cleye: "^1.3.2", crypto: "^1.0.1", @@ -22407,7 +22407,10 @@ var generateCommitMessageFromGitDiff = async (diff, extraArgs2, fullGitMojiSpec) const commitSpinner = le(); commitSpinner.start("Generating the commit message"); try { - let commitMessage = await generateCommitMessageByDiff(diff, fullGitMojiSpec); + let commitMessage = await generateCommitMessageByDiff( + diff, + fullGitMojiSpec + ); const messageTemplate = checkMessageTemplate(extraArgs2); if (config7?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") { commitMessage = messageTemplate.replace( @@ -22489,7 +22492,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2 process.exit(1); } }; -async function commit(extraArgs2 = [], fullGitMojiSpec = false, isStageAllFlag = false) { +async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec = true) { if (isStageAllFlag) { const changedFiles2 = await getChangedFiles(); if (changedFiles2) From a33027b4db60bf7d16fc3e794e2a3e4cbc540330 Mon Sep 17 00:00:00 2001 From: di-sukharev Date: Sun, 3 Mar 2024 19:43:40 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=94=80=20refactor(commit.ts):=20rearr?= =?UTF-8?q?ange=20function=20parameters=20for=20better=20readability=20?= =?UTF-8?q?=F0=9F=8E=A8=20style(commit.ts):=20improve=20code=20formatting?= =?UTF-8?q?=20for=20generateCommitMessageByDiff=20function=20call?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/commit.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/commands/commit.ts b/src/commands/commit.ts index 9b696ed..143bbab 100644 --- a/src/commands/commit.ts +++ b/src/commands/commit.ts @@ -48,7 +48,10 @@ const generateCommitMessageFromGitDiff = async ( commitSpinner.start('Generating the commit message'); try { - let commitMessage = await generateCommitMessageByDiff(diff, fullGitMojiSpec); + let commitMessage = await generateCommitMessageByDiff( + diff, + fullGitMojiSpec + ); const messageTemplate = checkMessageTemplate(extraArgs); if ( @@ -155,8 +158,8 @@ ${chalk.grey('โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”')}` export async function commit( extraArgs: string[] = [], - fullGitMojiSpec: boolean = false, isStageAllFlag: Boolean = false, + fullGitMojiSpec: boolean = false ) { if (isStageAllFlag) { const changedFiles = await getChangedFiles();