Compare commits

...

7 Commits

Author SHA1 Message Date
di-sukharev
98afbe21ea 3.2.4 2024-12-14 20:03:34 +01:00
di-sukharev
041465a81c 3.2.3 2024-12-14 20:03:11 +01:00
GPT8
40fa275b4f 3.2.3 (#431)
* 378: fix hook env (#402)

* fix(prepare-commit-msg-hook): update error handling to provide clearer instructions for setting API keys and improve user guidance

* Fix: a bug that causes an error when pushing without setting git remote (#396)

* update deploy commands

* feat(cli): add context flag for providing additional commit message input

* Fix [Bug]: punycode` module is deprecated #426 (#433)

Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>

* npm audit fix (#432)

Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>

* Feat: Add an option to `Don't push` when there are multiple git remotes (#434)

---------

Co-authored-by: GPT8 <57486732+di-sukharev@users.noreply.github.com>

* feat(engine): add support for MLX AI provider (#437)

---------

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

* feat(config, engine): add support for Mistral AI provider and engine (#436)

* docs(CONTRIBUTING.md): update `TODO.md` reference (#435)

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

* feat(config, engine): add support for Mistral AI provider and engine

* ```
feat(package): add mistralai and zod dependencies
```

* fix: recreate package-lock.json with node20

* fix: recreate package-lock.json with node v20.18.1 based on branch dev

---------

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: pedro-valentim <>

---------

Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Takanori Matsumoto <matscube@gmail.com>
Co-authored-by: BILLY Maxime <ozeliurs@gmail.com>
Co-authored-by: Welington Sampaio <welington.sampaio@icloud.com>
Co-authored-by: Tiger Kaovilai <passawit.kaovilai@gmail.com>
Co-authored-by: albi ️ <sigismondi.alberto@gmail.com>
Co-authored-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Pedro Valentim Silva Leite <18179935+pedro-valentim@users.noreply.github.com>
2024-12-14 20:02:25 +01:00
Emmanuel Ferdman
6f16191af2 docs(CONTRIBUTING.md): update TODO.md reference (#435)
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
2024-11-29 21:33:39 +01:00
di-sukharev
25105e4c3a docs(CONTRIBUTING.md): update links to point to the correct repository name for consistency and clarity 2024-09-07 19:11:37 +03:00
GPT8
2769121842 3.2.2 (#413)
* feat(config): add support for groq AI provider, including config validation and engine implementation (#381)

* fix migrations (#414)

---------

Co-authored-by: Takanori Matsumoto <matscube@gmail.com>
Co-authored-by: BILLY Maxime <ozeliurs@gmail.com>
2024-09-07 18:17:17 +03:00
di-sukharev
8ae927e2dc build 2024-09-06 13:59:28 +03:00
18 changed files with 690 additions and 623 deletions

View File

@@ -18,7 +18,7 @@ To get started, follow these steps:
1. Clone the project repository locally.
2. Install dependencies with `npm install`.
3. Run the project with `npm run dev`.
4. See [issues](https://github.com/di-sukharev/open-commit/issues) or [TODO.md](../TODO.md) to help the project.
4. See [issues](https://github.com/di-sukharev/opencommit/issues) or [TODO.md](TODO.md) to help the project.
## Commit message guidelines
@@ -30,7 +30,7 @@ If you encounter any issues while using the project, please report them on the G
## Contacts
If you have any questions about contributing to the project, please contact by [creating an issue](https://github.com/di-sukharev/open-commit/issues) on the GitHub issue tracker.
If you have any questions about contributing to the project, please contact by [creating an issue](https://github.com/di-sukharev/opencommit/issues) on the GitHub issue tracker.
## License

View File

@@ -431,8 +431,8 @@ var require_escape = __commonJS({
}
function escapeArgument(arg, doubleEscapeMetaChars) {
arg = `${arg}`;
arg = arg.replace(/(\\*)"/g, '$1$1\\"');
arg = arg.replace(/(\\*)$/, "$1$1");
arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
arg = `"${arg}"`;
arg = arg.replace(metaCharsRegExp, "^$1");
if (doubleEscapeMetaChars) {
@@ -578,7 +578,7 @@ var require_enoent = __commonJS({
const originalEmit = cp.emit;
cp.emit = function(name, arg1) {
if (name === "exit") {
const err = verifyENOENT(arg1, parsed, "spawn");
const err = verifyENOENT(arg1, parsed);
if (err) {
return originalEmit.call(cp, "error", err);
}
@@ -1672,7 +1672,7 @@ var require_mappingTable = __commonJS({
var require_tr46 = __commonJS({
"node_modules/node-fetch/node_modules/tr46/index.js"(exports, module2) {
"use strict";
var punycode = require("punycode");
const punycode = require('punycode/');
var mappingTable = require_mappingTable();
var PROCESSING_OPTIONS = {
TRANSITIONAL: 0,
@@ -1834,7 +1834,7 @@ var require_tr46 = __commonJS({
var require_url_state_machine = __commonJS({
"node_modules/node-fetch/node_modules/whatwg-url/lib/url-state-machine.js"(exports, module2) {
"use strict";
var punycode = require("punycode");
const punycode = require('punycode/');
var tr46 = require_tr46();
var specialSchemes = {
ftp: 21,
@@ -27331,7 +27331,7 @@ function G3(t2, e3) {
// package.json
var package_default = {
name: "opencommit",
version: "3.1.2",
version: "3.2.2",
description: "Auto-generate impressive commits in 1 second. Killing lame commits with AI \u{1F92F}\u{1F52B}",
keywords: [
"git",
@@ -27377,8 +27377,9 @@ var package_default = {
"dev:gemini": "OCO_AI_PROVIDER='gemini' ts-node ./src/cli.ts",
build: "rimraf out && node esbuild.config.js",
"build:push": "npm run build && git add . && git commit -m 'build' && git push",
deploy: "npm run build:push && git push --tags && npm publish --tag latest",
"deploy:patch": "npm version patch && npm run deploy",
deploy: "npm publish --tag latest",
"deploy:build": "npm run build:push && git push --tags && npm run deploy",
"deploy:patch": "npm version patch && npm run deploy:build",
lint: "eslint src --ext ts && tsc --noEmit",
format: "prettier --write src",
test: "node --no-warnings --experimental-vm-modules $( [ -f ./node_modules/.bin/jest ] && echo ./node_modules/.bin/jest || which jest ) test/unit",
@@ -27388,7 +27389,8 @@ var package_default = {
"test:unit:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:unit",
"test:e2e": "npm run test:e2e:setup && jest test/e2e",
"test:e2e:setup": "sh test/e2e/setup.sh",
"test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e"
"test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e",
"mlx:start": "OCO_AI_PROVIDER='mlx' node ./out/cli.cjs"
},
devDependencies: {
"@commitlint/types": "^17.4.4",
@@ -29917,16 +29919,29 @@ var MODEL_LIST = {
"gemini-1.0-pro",
"gemini-pro-vision",
"text-embedding-004"
],
groq: [
"llama3-70b-8192",
"llama3-8b-8192",
"llama-guard-3-8b",
"llama-3.1-8b-instant",
"llama-3.1-70b-versatile",
"gemma-7b-it",
"gemma2-9b-it"
]
};
var getDefaultModel = (provider) => {
switch (provider) {
case "ollama":
return "";
case "mlx":
return "";
case "anthropic":
return MODEL_LIST.anthropic[0];
case "gemini":
return MODEL_LIST.gemini[0];
case "groq":
return MODEL_LIST.groq[0];
default:
return MODEL_LIST.openai[0];
}
@@ -29952,7 +29967,7 @@ var configValidators = {
validateConfig(
"OCO_API_KEY",
value,
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "mlx" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
);
return value;
},
@@ -30050,10 +30065,16 @@ var configValidators = {
value = "openai";
validateConfig(
"OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */,
["openai", "anthropic", "gemini", "azure", "test", "flowise"].includes(
value
) || value.startsWith("ollama"),
`${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
[
"openai",
"anthropic",
"gemini",
"azure",
"test",
"flowise",
"groq"
].includes(value) || value.startsWith("ollama") || value.startsWith("mlx"),
`${value} is not supported yet, use 'ollama', 'mlx', anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
);
return value;
},
@@ -30092,6 +30113,8 @@ var OCO_AI_PROVIDER_ENUM = /* @__PURE__ */ ((OCO_AI_PROVIDER_ENUM2) => {
OCO_AI_PROVIDER_ENUM2["AZURE"] = "azure";
OCO_AI_PROVIDER_ENUM2["TEST"] = "test";
OCO_AI_PROVIDER_ENUM2["FLOWISE"] = "flowise";
OCO_AI_PROVIDER_ENUM2["GROQ"] = "groq";
OCO_AI_PROVIDER_ENUM2["MLX"] = "mlx";
return OCO_AI_PROVIDER_ENUM2;
})(OCO_AI_PROVIDER_ENUM || {});
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
@@ -30108,7 +30131,6 @@ var DEFAULT_CONFIG = {
OCO_AI_PROVIDER: "openai" /* OPENAI */,
OCO_ONE_LINE_COMMIT: false,
OCO_TEST_MOCK_TYPE: "commit-message",
OCO_FLOWISE_ENDPOINT: ":",
OCO_WHY: false,
OCO_GITPUSH: true
};
@@ -30168,6 +30190,25 @@ var mergeConfigs = (main, fallback) => {
return acc;
}, {});
};
var cleanUndefinedValues = (config7) => {
return Object.fromEntries(
Object.entries(config7).map(([_7, v5]) => {
try {
if (typeof v5 === "string") {
if (v5 === "undefined")
return [_7, void 0];
if (v5 === "null")
return [_7, null];
const parsedValue = JSON.parse(v5);
return [_7, parsedValue];
}
return [_7, v5];
} catch (error) {
return [_7, v5];
}
})
);
};
var getConfig = ({
envPath = defaultEnvPath,
globalPath = defaultConfigPath
@@ -30175,7 +30216,8 @@ var getConfig = ({
const envConfig = getEnvConfig(envPath);
const globalConfig = getGlobalConfig(globalPath);
const config7 = mergeConfigs(envConfig, globalConfig);
return config7;
const cleanConfig = cleanUndefinedValues(config7);
return cleanConfig;
};
var setConfig = (keyValues, globalConfigPath = defaultConfigPath) => {
const config7 = getConfig({
@@ -44470,7 +44512,51 @@ var OpenAiEngine = class {
}
};
this.config = config7;
this.client = new OpenAI({ apiKey: config7.apiKey });
if (!config7.baseURL) {
this.client = new OpenAI({ apiKey: config7.apiKey });
} else {
this.client = new OpenAI({ apiKey: config7.apiKey, baseURL: config7.baseURL });
}
}
};
// src/engine/groq.ts
var GroqEngine = class extends OpenAiEngine {
constructor(config7) {
config7.baseURL = "https://api.groq.com/openai/v1";
super(config7);
}
};
// src/engine/mlx.ts
var MLXEngine = class {
constructor(config7) {
this.config = config7;
this.client = axios_default.create({
url: config7.baseURL ? `${config7.baseURL}/${config7.apiKey}` : "http://localhost:8080/v1/chat/completions",
headers: { "Content-Type": "application/json" }
});
}
async generateCommitMessage(messages) {
const params = {
messages,
temperature: 0,
top_p: 0.1,
repetition_penalty: 1.5,
stream: false
};
try {
const response = await this.client.post(
this.client.getUri(this.config),
params
);
const choices = response.data.choices;
const message = choices[0].message;
return message?.content;
} catch (err) {
const message = err.response?.data?.error ?? err.message;
throw new Error(`MLX provider error: ${message}`);
}
}
};
@@ -44498,6 +44584,10 @@ function getEngine() {
return new AzureEngine(DEFAULT_CONFIG2);
case "flowise" /* FLOWISE */:
return new FlowiseEngine(DEFAULT_CONFIG2);
case "groq" /* GROQ */:
return new GroqEngine(DEFAULT_CONFIG2);
case "mlx" /* MLX */:
return new MLXEngine(DEFAULT_CONFIG2);
default:
return new OpenAiEngine(DEFAULT_CONFIG2);
}
@@ -44879,7 +44969,14 @@ var CONVENTIONAL_COMMIT_KEYWORDS = "Do not preface the commit with anything, exc
var getCommitConvention = (fullGitMojiSpec) => config4.OCO_EMOJI ? fullGitMojiSpec ? FULL_GITMOJI_SPEC : GITMOJI_HELP : CONVENTIONAL_COMMIT_KEYWORDS;
var getDescriptionInstruction = () => config4.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.";
var getOneLineCommitInstruction = () => config4.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : "";
var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
var userInputCodeContext = (context) => {
if (context !== "" && context !== " ") {
return `Additional context provided by the user: <context>${context}</context>
Consider this context when generating the commit message, incorporating relevant information when appropriate.`;
}
return "";
};
var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec, context) => ({
role: "system",
content: (() => {
const commitConvention = fullGitMojiSpec ? "GitMoji specification" : "Conventional Commit Convention";
@@ -44889,12 +44986,14 @@ var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
const descriptionGuideline = getDescriptionInstruction();
const oneLineCommitGuideline = getOneLineCommitInstruction();
const generalGuidelines = `Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`;
const userInputContext = userInputCodeContext(context);
return `${missionStatement}
${diffInstruction}
${conventionGuidelines}
${descriptionGuideline}
${oneLineCommitGuideline}
${generalGuidelines}`;
${generalGuidelines}
${userInputContext}`;
})()
});
var INIT_DIFF_PROMPT = {
@@ -44936,7 +45035,7 @@ var INIT_CONSISTENCY_PROMPT = (translation4) => ({
role: "assistant",
content: getContent(translation4)
});
var getMainCommitPrompt = async (fullGitMojiSpec) => {
var getMainCommitPrompt = async (fullGitMojiSpec, context) => {
switch (config4.OCO_PROMPT_MODULE) {
case "@commitlint":
if (!await commitlintLLMConfigExists()) {
@@ -44958,7 +45057,7 @@ var getMainCommitPrompt = async (fullGitMojiSpec) => {
];
default:
return [
INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec),
INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec, context),
INIT_DIFF_PROMPT,
INIT_CONSISTENCY_PROMPT(translation3)
];
@@ -44985,8 +45084,8 @@ function mergeDiffs(arr, maxStringLength) {
var config5 = getConfig();
var MAX_TOKENS_INPUT = config5.OCO_TOKENS_MAX_INPUT;
var MAX_TOKENS_OUTPUT = config5.OCO_TOKENS_MAX_OUTPUT;
var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec, context) => {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec, context);
const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
chatContextAsCompletionRequest.push({
role: "user",
@@ -45002,9 +45101,12 @@ var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => {
return GenerateCommitMessageErrorEnum2;
})(GenerateCommitMessageErrorEnum || {});
var ADJUSTMENT_FACTOR = 20;
var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false, context = "") => {
try {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(
fullGitMojiSpec,
context
);
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
(msg) => tokenCount(msg.content) + 4
).reduce((a4, b7) => a4 + b7, 0);
@@ -45024,7 +45126,8 @@ var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
}
const messages = await generateCommitMessageChatCompletionPrompt(
diff,
fullGitMojiSpec
fullGitMojiSpec,
context
);
const engine = getEngine();
const commitMessage = await engine.generateCommitMessage(messages);
@@ -45231,6 +45334,7 @@ var checkMessageTemplate = (extraArgs2) => {
var generateCommitMessageFromGitDiff = async ({
diff,
extraArgs: extraArgs2,
context = "",
fullGitMojiSpec = false,
skipCommitConfirmation = false
}) => {
@@ -45240,7 +45344,8 @@ var generateCommitMessageFromGitDiff = async ({
try {
let commitMessage = await generateCommitMessageByDiff(
diff,
fullGitMojiSpec
fullGitMojiSpec,
context
);
const messageTemplate = checkMessageTemplate(extraArgs2);
if (config6.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") {
@@ -45277,13 +45382,15 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
);
ce(stdout);
const remotes = await getGitRemotes();
if (config6.OCO_GITPUSH === false)
return;
if (!remotes.length) {
const { stdout: stdout2 } = await execa("git", ["push"]);
if (stdout2)
ce(stdout2);
process.exit(0);
}
if (remotes.length === 1 && config6.OCO_GITPUSH !== true) {
if (remotes.length === 1) {
const isPushConfirmedByUser = await Q3({
message: "Do you want to run `git push`?"
});
@@ -45339,13 +45446,16 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
}
}
} catch (error) {
commitGenerationSpinner.stop("\u{1F4DD} Commit message generated");
commitGenerationSpinner.stop(
`${source_default.red("\u2716")} Failed to generate the commit message`
);
console.log(error);
const err = error;
ce(`${source_default.red("\u2716")} ${err?.message || err}`);
process.exit(1);
}
};
async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec = false, skipCommitConfirmation = false) {
async function commit(extraArgs2 = [], context = "", isStageAllFlag = false, fullGitMojiSpec = false, skipCommitConfirmation = false) {
if (isStageAllFlag) {
const changedFiles2 = await getChangedFiles();
if (changedFiles2)
@@ -45376,7 +45486,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec =
if (hD2(isStageAllAndCommitConfirmedByUser))
process.exit(1);
if (isStageAllAndCommitConfirmedByUser) {
await commit(extraArgs2, true, fullGitMojiSpec);
await commit(extraArgs2, context, true, fullGitMojiSpec);
process.exit(1);
}
if (stagedFiles.length === 0 && changedFiles.length > 0) {
@@ -45391,7 +45501,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec =
process.exit(1);
await gitAdd({ files });
}
await commit(extraArgs2, false, fullGitMojiSpec);
await commit(extraArgs2, context, false, fullGitMojiSpec);
process.exit(1);
}
stagedFilesSpinner.stop(
@@ -45402,6 +45512,7 @@ ${stagedFiles.map((file) => ` ${file}`).join("\n")}`
generateCommitMessageFromGitDiff({
diff: await getDiff({ files: stagedFiles }),
extraArgs: extraArgs2,
context,
fullGitMojiSpec,
skipCommitConfirmation
})
@@ -45674,11 +45785,12 @@ function set_missing_default_values_default() {
const entriesToSet = [];
for (const entry of Object.entries(DEFAULT_CONFIG)) {
const [key, _value] = entry;
if (config7[key] === "undefined")
if (config7[key] === "undefined" || config7[key] === void 0)
entriesToSet.push(entry);
}
if (entriesToSet.length > 0)
setConfig(entriesToSet);
console.log(entriesToSet);
};
setDefaultConfigValues(getGlobalConfig());
}
@@ -45735,6 +45847,7 @@ var runMigrations = async () => {
ce(
`${source_default.red("Failed to apply migration")} ${migration.name}: ${error}`
);
process.exit(1);
}
isMigrated = true;
}
@@ -45758,6 +45871,12 @@ Z2(
commands: [configCommand, hookCommand, commitlintConfigCommand],
flags: {
fgm: Boolean,
context: {
type: String,
alias: "c",
description: "Additional user input context for the commit message",
default: ""
},
yes: {
type: Boolean,
alias: "y",
@@ -45774,7 +45893,7 @@ Z2(
if (await isHookCalled()) {
prepareCommitMessageHook();
} else {
commit(extraArgs, false, flags.fgm, flags.yes);
commit(extraArgs, flags.context, false, flags.fgm, flags.yes);
}
},
extraArgs

View File

@@ -20487,7 +20487,7 @@ var require_mappingTable = __commonJS({
var require_tr46 = __commonJS({
"node_modules/node-fetch/node_modules/tr46/index.js"(exports, module2) {
"use strict";
var punycode = require("punycode");
const punycode = require('punycode/');
var mappingTable = require_mappingTable();
var PROCESSING_OPTIONS = {
TRANSITIONAL: 0,
@@ -20649,7 +20649,7 @@ var require_tr46 = __commonJS({
var require_url_state_machine = __commonJS({
"node_modules/node-fetch/node_modules/whatwg-url/lib/url-state-machine.js"(exports, module2) {
"use strict";
var punycode = require("punycode");
const punycode = require('punycode/');
var tr46 = require_tr46();
var specialSchemes = {
ftp: 21,
@@ -48730,16 +48730,29 @@ var MODEL_LIST = {
"gemini-1.0-pro",
"gemini-pro-vision",
"text-embedding-004"
],
groq: [
"llama3-70b-8192",
"llama3-8b-8192",
"llama-guard-3-8b",
"llama-3.1-8b-instant",
"llama-3.1-70b-versatile",
"gemma-7b-it",
"gemma2-9b-it"
]
};
var getDefaultModel = (provider) => {
switch (provider) {
case "ollama":
return "";
case "mlx":
return "";
case "anthropic":
return MODEL_LIST.anthropic[0];
case "gemini":
return MODEL_LIST.gemini[0];
case "groq":
return MODEL_LIST.groq[0];
default:
return MODEL_LIST.openai[0];
}
@@ -48765,7 +48778,7 @@ var configValidators = {
validateConfig(
"OCO_API_KEY",
value,
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "mlx" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
);
return value;
},
@@ -48863,10 +48876,16 @@ var configValidators = {
value = "openai";
validateConfig(
"OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */,
["openai", "anthropic", "gemini", "azure", "test", "flowise"].includes(
value
) || value.startsWith("ollama"),
`${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
[
"openai",
"anthropic",
"gemini",
"azure",
"test",
"flowise",
"groq"
].includes(value) || value.startsWith("ollama") || value.startsWith("mlx"),
`${value} is not supported yet, use 'ollama', 'mlx', anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
);
return value;
},
@@ -48911,7 +48930,6 @@ var DEFAULT_CONFIG = {
OCO_AI_PROVIDER: "openai" /* OPENAI */,
OCO_ONE_LINE_COMMIT: false,
OCO_TEST_MOCK_TYPE: "commit-message",
OCO_FLOWISE_ENDPOINT: ":",
OCO_WHY: false,
OCO_GITPUSH: true
};
@@ -48971,6 +48989,25 @@ var mergeConfigs = (main, fallback) => {
return acc;
}, {});
};
var cleanUndefinedValues = (config6) => {
return Object.fromEntries(
Object.entries(config6).map(([_3, v2]) => {
try {
if (typeof v2 === "string") {
if (v2 === "undefined")
return [_3, void 0];
if (v2 === "null")
return [_3, null];
const parsedValue = JSON.parse(v2);
return [_3, parsedValue];
}
return [_3, v2];
} catch (error) {
return [_3, v2];
}
})
);
};
var getConfig = ({
envPath = defaultEnvPath,
globalPath = defaultConfigPath
@@ -48978,7 +49015,8 @@ var getConfig = ({
const envConfig = getEnvConfig(envPath);
const globalConfig = getGlobalConfig(globalPath);
const config6 = mergeConfigs(envConfig, globalConfig);
return config6;
const cleanConfig = cleanUndefinedValues(config6);
return cleanConfig;
};
var setConfig = (keyValues, globalConfigPath = defaultConfigPath) => {
const config6 = getConfig({
@@ -63273,7 +63311,51 @@ var OpenAiEngine = class {
}
};
this.config = config6;
this.client = new OpenAI({ apiKey: config6.apiKey });
if (!config6.baseURL) {
this.client = new OpenAI({ apiKey: config6.apiKey });
} else {
this.client = new OpenAI({ apiKey: config6.apiKey, baseURL: config6.baseURL });
}
}
};
// src/engine/groq.ts
var GroqEngine = class extends OpenAiEngine {
constructor(config6) {
config6.baseURL = "https://api.groq.com/openai/v1";
super(config6);
}
};
// src/engine/mlx.ts
var MLXEngine = class {
constructor(config6) {
this.config = config6;
this.client = axios_default.create({
url: config6.baseURL ? `${config6.baseURL}/${config6.apiKey}` : "http://localhost:8080/v1/chat/completions",
headers: { "Content-Type": "application/json" }
});
}
async generateCommitMessage(messages) {
const params = {
messages,
temperature: 0,
top_p: 0.1,
repetition_penalty: 1.5,
stream: false
};
try {
const response = await this.client.post(
this.client.getUri(this.config),
params
);
const choices = response.data.choices;
const message = choices[0].message;
return message?.content;
} catch (err) {
const message = err.response?.data?.error ?? err.message;
throw new Error(`MLX provider error: ${message}`);
}
}
};
@@ -63301,6 +63383,10 @@ function getEngine() {
return new AzureEngine(DEFAULT_CONFIG2);
case "flowise" /* FLOWISE */:
return new FlowiseEngine(DEFAULT_CONFIG2);
case "groq" /* GROQ */:
return new GroqEngine(DEFAULT_CONFIG2);
case "mlx" /* MLX */:
return new MLXEngine(DEFAULT_CONFIG2);
default:
return new OpenAiEngine(DEFAULT_CONFIG2);
}
@@ -63682,7 +63768,14 @@ var CONVENTIONAL_COMMIT_KEYWORDS = "Do not preface the commit with anything, exc
var getCommitConvention = (fullGitMojiSpec) => config4.OCO_EMOJI ? fullGitMojiSpec ? FULL_GITMOJI_SPEC : GITMOJI_HELP : CONVENTIONAL_COMMIT_KEYWORDS;
var getDescriptionInstruction = () => config4.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.";
var getOneLineCommitInstruction = () => config4.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : "";
var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
var userInputCodeContext = (context2) => {
if (context2 !== "" && context2 !== " ") {
return `Additional context provided by the user: <context>${context2}</context>
Consider this context when generating the commit message, incorporating relevant information when appropriate.`;
}
return "";
};
var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec, context2) => ({
role: "system",
content: (() => {
const commitConvention = fullGitMojiSpec ? "GitMoji specification" : "Conventional Commit Convention";
@@ -63692,12 +63785,14 @@ var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
const descriptionGuideline = getDescriptionInstruction();
const oneLineCommitGuideline = getOneLineCommitInstruction();
const generalGuidelines = `Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`;
const userInputContext = userInputCodeContext(context2);
return `${missionStatement}
${diffInstruction}
${conventionGuidelines}
${descriptionGuideline}
${oneLineCommitGuideline}
${generalGuidelines}`;
${generalGuidelines}
${userInputContext}`;
})()
});
var INIT_DIFF_PROMPT = {
@@ -63739,7 +63834,7 @@ var INIT_CONSISTENCY_PROMPT = (translation4) => ({
role: "assistant",
content: getContent(translation4)
});
var getMainCommitPrompt = async (fullGitMojiSpec) => {
var getMainCommitPrompt = async (fullGitMojiSpec, context2) => {
switch (config4.OCO_PROMPT_MODULE) {
case "@commitlint":
if (!await commitlintLLMConfigExists()) {
@@ -63761,7 +63856,7 @@ var getMainCommitPrompt = async (fullGitMojiSpec) => {
];
default:
return [
INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec),
INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec, context2),
INIT_DIFF_PROMPT,
INIT_CONSISTENCY_PROMPT(translation3)
];
@@ -63788,8 +63883,8 @@ function mergeDiffs(arr, maxStringLength) {
var config5 = getConfig();
var MAX_TOKENS_INPUT = config5.OCO_TOKENS_MAX_INPUT;
var MAX_TOKENS_OUTPUT = config5.OCO_TOKENS_MAX_OUTPUT;
var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec, context2) => {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec, context2);
const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
chatContextAsCompletionRequest.push({
role: "user",
@@ -63805,9 +63900,12 @@ var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => {
return GenerateCommitMessageErrorEnum2;
})(GenerateCommitMessageErrorEnum || {});
var ADJUSTMENT_FACTOR = 20;
var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false, context2 = "") => {
try {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(
fullGitMojiSpec,
context2
);
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
(msg) => tokenCount(msg.content) + 4
).reduce((a3, b3) => a3 + b3, 0);
@@ -63827,7 +63925,8 @@ var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
}
const messages = await generateCommitMessageChatCompletionPrompt(
diff,
fullGitMojiSpec
fullGitMojiSpec,
context2
);
const engine = getEngine();
const commitMessage = await engine.generateCommitMessage(messages);

592
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "opencommit",
"version": "3.2.1",
"version": "3.2.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "opencommit",
"version": "3.2.1",
"version": "3.2.4",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
@@ -17,9 +17,9 @@
"@clack/prompts": "^0.6.1",
"@dqbd/tiktoken": "^1.0.2",
"@google/generative-ai": "^0.11.4",
"@mistralai/mistralai": "^1.3.5",
"@octokit/webhooks-schemas": "^6.11.0",
"@octokit/webhooks-types": "^6.11.0",
"ai": "^2.2.14",
"axios": "^1.3.4",
"chalk": "^5.2.0",
"cleye": "^1.3.2",
@@ -28,7 +28,9 @@
"ignore": "^5.2.4",
"ini": "^3.0.1",
"inquirer": "^9.1.4",
"openai": "^4.57.0"
"openai": "^4.57.0",
"punycode": "^2.3.1",
"zod": "^3.23.8"
},
"bin": {
"oco": "out/cli.cjs",
@@ -108,6 +110,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -574,6 +577,7 @@
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz",
"integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1728,6 +1732,7 @@
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -1741,6 +1746,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -1749,6 +1755,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -1756,12 +1763,14 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -1778,6 +1787,16 @@
"node": ">= 0.4"
}
},
"node_modules/@mistralai/mistralai": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.3.5.tgz",
"integrity": "sha512-yC91oJ5ScEPqbXmv3mJTwTFgu/ZtsYoOPOhaVXSsy6x4zXTqTI57yEC1flC9uiA8GpG/yhpn2BBUXF95+U9Blw==",
"peerDependencies": {
"react": "^18 || ^19",
"react-dom": "^18 || ^19",
"zod": ">= 3"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2013,12 +2032,6 @@
"@babel/types": "^7.20.7"
}
},
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"peer": true
},
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -2333,117 +2346,6 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"dev": true
},
"node_modules/@vue/compiler-core": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
"integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
"peer": true,
"dependencies": {
"@babel/parser": "^7.23.9",
"@vue/shared": "3.4.21",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-core/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"peer": true
},
"node_modules/@vue/compiler-dom": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz",
"integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==",
"peer": true,
"dependencies": {
"@vue/compiler-core": "3.4.21",
"@vue/shared": "3.4.21"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz",
"integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==",
"peer": true,
"dependencies": {
"@babel/parser": "^7.23.9",
"@vue/compiler-core": "3.4.21",
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-ssr": "3.4.21",
"@vue/shared": "3.4.21",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.7",
"postcss": "^8.4.35",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"peer": true
},
"node_modules/@vue/compiler-ssr": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz",
"integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.4.21",
"@vue/shared": "3.4.21"
}
},
"node_modules/@vue/reactivity": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz",
"integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
"peer": true,
"dependencies": {
"@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
"integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.4.21",
"@vue/shared": "3.4.21"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
"integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
"peer": true,
"dependencies": {
"@vue/runtime-core": "3.4.21",
"@vue/shared": "3.4.21",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
"integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
"peer": true,
"dependencies": {
"@vue/compiler-ssr": "3.4.21",
"@vue/shared": "3.4.21"
},
"peerDependencies": {
"vue": "3.4.21"
}
},
"node_modules/@vue/shared": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"peer": true
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -2459,6 +2361,7 @@
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2506,43 +2409,6 @@
"node": ">= 8.0.0"
}
},
"node_modules/ai": {
"version": "2.2.37",
"resolved": "https://registry.npmjs.org/ai/-/ai-2.2.37.tgz",
"integrity": "sha512-JIYm5N1muGVqBqWnvkt29FmXhESoO5TcDxw74OE41SsM+uIou6NPDDs0XWb/ABcd1gmp6k5zym64KWMPM2xm0A==",
"dependencies": {
"eventsource-parser": "1.0.0",
"nanoid": "3.3.6",
"solid-swr-store": "0.10.7",
"sswr": "2.0.0",
"swr": "2.2.0",
"swr-store": "0.10.6",
"swrv": "1.0.4"
},
"engines": {
"node": ">=14.6"
},
"peerDependencies": {
"react": "^18.2.0",
"solid-js": "^1.7.7",
"svelte": "^3.0.0 || ^4.0.0",
"vue": "^3.3.4"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"solid-js": {
"optional": true
},
"svelte": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2629,15 +2495,6 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/aria-query": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"peer": true,
"dependencies": {
"dequal": "^2.0.3"
}
},
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -2671,15 +2528,6 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axobject-query": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz",
"integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==",
"peer": true,
"dependencies": {
"dequal": "^2.0.3"
}
},
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -3256,19 +3104,6 @@
"node": ">= 0.12.0"
}
},
"node_modules/code-red": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
"peer": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15",
"@types/estree": "^1.0.1",
"acorn": "^8.10.0",
"estree-walker": "^3.0.3",
"periscopic": "^3.1.0"
}
},
"node_modules/collect-v8-coverage": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
@@ -3390,9 +3225,10 @@
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -3408,25 +3244,6 @@
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
},
"node_modules/css-tree": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"peer": true,
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"peer": true
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -3512,14 +3329,6 @@
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"engines": {
"node": ">=6"
}
},
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -3606,18 +3415,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -4259,15 +4056,6 @@
"node": ">=4.0"
}
},
"node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"peer": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -4285,14 +4073,6 @@
"node": ">=6"
}
},
"node_modules/eventsource-parser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.0.0.tgz",
"integrity": "sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==",
"engines": {
"node": ">=14.18"
}
},
"node_modules/execa": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
@@ -5156,15 +4936,6 @@
"node": ">=0.10.0"
}
},
"node_modules/is-reference": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
"peer": true,
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
@@ -6826,12 +6597,6 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"peer": true
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -6928,6 +6693,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -6954,18 +6720,6 @@
"lz-string": "bin/bin.js"
}
},
"node_modules/magic-string": {
"version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"peer": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"engines": {
"node": ">=12"
}
},
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
@@ -6996,12 +6750,6 @@
"tmpl": "1.0.5"
}
},
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"peer": true
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -7017,12 +6765,13 @@
}
},
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.2",
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -7093,23 +6842,6 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -7494,17 +7226,6 @@
"node": ">=8"
}
},
"node_modules/periscopic": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
"peer": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^3.0.0",
"is-reference": "^3.0.0"
}
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -7595,52 +7316,6 @@
"node": ">=8"
}
},
"node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -7701,7 +7376,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
@@ -7757,9 +7432,10 @@
]
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
@@ -7768,6 +7444,20 @@
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.3.1"
}
},
"node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
@@ -7993,6 +7683,16 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
@@ -8026,27 +7726,6 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/seroval": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.0.5.tgz",
"integrity": "sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==",
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/seroval-plugins": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.0.5.tgz",
"integrity": "sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==",
"peer": true,
"engines": {
"node": ">=10"
},
"peerDependencies": {
"seroval": "^1.0"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -8168,29 +7847,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/solid-js": {
"version": "1.8.16",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.16.tgz",
"integrity": "sha512-rja94MNU9flF3qQRLNsu60QHKBDKBkVE1DldJZPIfn2ypIn3NV2WpSbGTQIvsyGPBo+9E2IMjwqnqpbgfWuzeg==",
"peer": true,
"dependencies": {
"csstype": "^3.1.0",
"seroval": "^1.0.4",
"seroval-plugins": "^1.0.3"
}
},
"node_modules/solid-swr-store": {
"version": "0.10.7",
"resolved": "https://registry.npmjs.org/solid-swr-store/-/solid-swr-store-0.10.7.tgz",
"integrity": "sha512-A6d68aJmRP471aWqKKPE2tpgOiR5fH4qXQNfKIec+Vap+MGQm3tvXlT8n0I8UgJSlNAsSAUuw2VTviH2h3Vv5g==",
"engines": {
"node": ">=10"
},
"peerDependencies": {
"solid-js": "^1.2",
"swr-store": "^0.10"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -8200,15 +7856,6 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
@@ -8225,17 +7872,6 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"node_modules/sswr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/sswr/-/sswr-2.0.0.tgz",
"integrity": "sha512-mV0kkeBHcjcb0M5NqKtKVg/uTIYNlIIniyDfSGrSfxpEdM9C365jK0z55pl9K0xAkNTJi2OAOVFQpgMPUk+V0w==",
"dependencies": {
"swrev": "^4.0.0"
},
"peerDependencies": {
"svelte": "^4.0.0"
}
},
"node_modules/stack-utils": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@@ -8367,66 +8003,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svelte": {
"version": "4.2.12",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
"integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
"@jridgewell/trace-mapping": "^0.3.18",
"@types/estree": "^1.0.1",
"acorn": "^8.9.0",
"aria-query": "^5.3.0",
"axobject-query": "^4.0.0",
"code-red": "^1.0.3",
"css-tree": "^2.3.1",
"estree-walker": "^3.0.3",
"is-reference": "^3.0.1",
"locate-character": "^3.0.0",
"magic-string": "^0.30.4",
"periscopic": "^3.1.0"
},
"engines": {
"node": ">=16"
}
},
"node_modules/swr": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/swr/-/swr-2.2.0.tgz",
"integrity": "sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==",
"dependencies": {
"use-sync-external-store": "^1.2.0"
},
"peerDependencies": {
"react": "^16.11.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/swr-store": {
"version": "0.10.6",
"resolved": "https://registry.npmjs.org/swr-store/-/swr-store-0.10.6.tgz",
"integrity": "sha512-xPjB1hARSiRaNNlUQvWSVrG5SirCjk2TmaUyzzvk69SZQan9hCJqw/5rG9iL7xElHU784GxRPISClq4488/XVw==",
"dependencies": {
"dequal": "^2.0.3"
},
"engines": {
"node": ">=10"
}
},
"node_modules/swrev": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/swrev/-/swrev-4.0.0.tgz",
"integrity": "sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA=="
},
"node_modules/swrv": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/swrv/-/swrv-1.0.4.tgz",
"integrity": "sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==",
"peerDependencies": {
"vue": ">=3.2.26 < 4"
}
},
"node_modules/terminal-columns": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/terminal-columns/-/terminal-columns-1.4.1.tgz",
@@ -8667,7 +8243,7 @@
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"devOptional": true,
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -8736,14 +8312,6 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -8777,27 +8345,6 @@
"node": ">=10.12.0"
}
},
"node_modules/vue": {
"version": "3.4.21",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz",
"integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-sfc": "3.4.21",
"@vue/runtime-dom": "3.4.21",
"@vue/server-renderer": "3.4.21",
"@vue/shared": "3.4.21"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/walker": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
@@ -8960,6 +8507,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zod": {
"version": "3.23.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "opencommit",
"version": "3.2.1",
"version": "3.2.4",
"description": "Auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
"keywords": [
"git",
@@ -58,7 +58,8 @@
"test:unit:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:unit",
"test:e2e": "npm run test:e2e:setup && jest test/e2e",
"test:e2e:setup": "sh test/e2e/setup.sh",
"test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e"
"test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e",
"mlx:start": "OCO_AI_PROVIDER='mlx' node ./out/cli.cjs"
},
"devDependencies": {
"@commitlint/types": "^17.4.4",
@@ -87,6 +88,7 @@
"@clack/prompts": "^0.6.1",
"@dqbd/tiktoken": "^1.0.2",
"@google/generative-ai": "^0.11.4",
"@mistralai/mistralai": "^1.3.5",
"@octokit/webhooks-schemas": "^6.11.0",
"@octokit/webhooks-types": "^6.11.0",
"axios": "^1.3.4",
@@ -97,6 +99,8 @@
"ignore": "^5.2.4",
"ini": "^3.0.1",
"inquirer": "^9.1.4",
"openai": "^4.57.0"
"openai": "^4.57.0",
"punycode": "^2.3.1",
"zod": "^3.23.8"
}
}

View File

@@ -20,6 +20,12 @@ cli(
commands: [configCommand, hookCommand, commitlintConfigCommand],
flags: {
fgm: Boolean,
context: {
type: String,
alias: 'c',
description: 'Additional user input context for the commit message',
default: ''
},
yes: {
type: Boolean,
alias: 'y',
@@ -37,7 +43,7 @@ cli(
if (await isHookCalled()) {
prepareCommitMessageHook();
} else {
commit(extraArgs, false, flags.fgm, flags.yes);
commit(extraArgs, flags.context, false, flags.fgm, flags.yes);
}
},
extraArgs

View File

@@ -39,6 +39,7 @@ const checkMessageTemplate = (extraArgs: string[]): string | false => {
interface GenerateCommitMessageFromGitDiffParams {
diff: string;
extraArgs: string[];
context?: string;
fullGitMojiSpec?: boolean;
skipCommitConfirmation?: boolean;
}
@@ -46,6 +47,7 @@ interface GenerateCommitMessageFromGitDiffParams {
const generateCommitMessageFromGitDiff = async ({
diff,
extraArgs,
context = '',
fullGitMojiSpec = false,
skipCommitConfirmation = false
}: GenerateCommitMessageFromGitDiffParams): Promise<void> => {
@@ -56,7 +58,8 @@ const generateCommitMessageFromGitDiff = async ({
try {
let commitMessage = await generateCommitMessageByDiff(
diff,
fullGitMojiSpec
fullGitMojiSpec,
context
);
const messageTemplate = checkMessageTemplate(extraArgs);
@@ -135,8 +138,7 @@ ${chalk.grey('——————————————————')}`
]);
pushSpinner.stop(
`${chalk.green('✔')} Successfully pushed all commits to ${
remotes[0]
`${chalk.green('✔')} Successfully pushed all commits to ${remotes[0]
}`
);
@@ -146,26 +148,29 @@ ${chalk.grey('——————————————————')}`
process.exit(0);
}
} else {
const skipOption = `don't push`
const selectedRemote = (await select({
message: 'Choose a remote to push to',
options: remotes.map((remote) => ({ value: remote, label: remote }))
options: [...remotes, skipOption].map((remote) => ({ value: remote, label: remote })),
})) as string;
if (isCancel(selectedRemote)) process.exit(1);
const pushSpinner = spinner();
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
const { stdout } = await execa('git', ['push', selectedRemote]);
if (stdout) outro(stdout);
pushSpinner.stop(
`${chalk.green(
'✔'
)} successfully pushed all commits to ${selectedRemote}`
);
if (selectedRemote !== skipOption) {
const pushSpinner = spinner();
pushSpinner.start(`Running 'git push ${selectedRemote}'`);
const { stdout } = await execa('git', ['push', selectedRemote]);
if (stdout) outro(stdout);
pushSpinner.stop(
`${chalk.green(
'✔'
)} successfully pushed all commits to ${selectedRemote}`
);
}
}
} else {
const regenerateMessage = await confirm({
@@ -183,7 +188,11 @@ ${chalk.grey('——————————————————')}`
}
}
} catch (error) {
commitGenerationSpinner.stop('📝 Commit message generated');
commitGenerationSpinner.stop(
`${chalk.red('✖')} Failed to generate the commit message`
);
console.log(error);
const err = error as Error;
outro(`${chalk.red('✖')} ${err?.message || err}`);
@@ -193,6 +202,7 @@ ${chalk.grey('——————————————————')}`
export async function commit(
extraArgs: string[] = [],
context: string = '',
isStageAllFlag: Boolean = false,
fullGitMojiSpec: boolean = false,
skipCommitConfirmation: boolean = false
@@ -234,7 +244,7 @@ export async function commit(
if (isCancel(isStageAllAndCommitConfirmedByUser)) process.exit(1);
if (isStageAllAndCommitConfirmedByUser) {
await commit(extraArgs, true, fullGitMojiSpec);
await commit(extraArgs, context, true, fullGitMojiSpec);
process.exit(1);
}
@@ -252,7 +262,7 @@ export async function commit(
await gitAdd({ files });
}
await commit(extraArgs, false, fullGitMojiSpec);
await commit(extraArgs, context, false, fullGitMojiSpec);
process.exit(1);
}
@@ -266,6 +276,7 @@ export async function commit(
generateCommitMessageFromGitDiff({
diff: await getDiff({ files: stagedFiles }),
extraArgs,
context,
fullGitMojiSpec,
skipCommitConfirmation
})

View File

@@ -76,6 +76,58 @@ export const MODEL_LIST = {
'gemini-1.0-pro',
'gemini-pro-vision',
'text-embedding-004'
],
groq: [
'llama3-70b-8192', // Meta Llama 3 70B (default one, no daily token limit and 14 400 reqs/day)
'llama3-8b-8192', // Meta Llama 3 8B
'llama-guard-3-8b', // Llama Guard 3 8B
'llama-3.1-8b-instant', // Llama 3.1 8B (Preview)
'llama-3.1-70b-versatile', // Llama 3.1 70B (Preview)
'gemma-7b-it', // Gemma 7B
'gemma2-9b-it' // Gemma 2 9B
],
mistral: [
'ministral-3b-2410',
'ministral-3b-latest',
'ministral-8b-2410',
'ministral-8b-latest',
'open-mistral-7b',
'mistral-tiny',
'mistral-tiny-2312',
'open-mistral-nemo',
'open-mistral-nemo-2407',
'mistral-tiny-2407',
'mistral-tiny-latest',
'open-mixtral-8x7b',
'mistral-small',
'mistral-small-2312',
'open-mixtral-8x22b',
'open-mixtral-8x22b-2404',
'mistral-small-2402',
'mistral-small-2409',
'mistral-small-latest',
'mistral-medium-2312',
'mistral-medium',
'mistral-medium-latest',
'mistral-large-2402',
'mistral-large-2407',
'mistral-large-2411',
'mistral-large-latest',
'pixtral-large-2411',
'pixtral-large-latest',
'codestral-2405',
'codestral-latest',
'codestral-mamba-2407',
'open-codestral-mamba',
'codestral-mamba-latest',
'pixtral-12b-2409',
'pixtral-12b',
'pixtral-12b-latest',
'mistral-embed',
'mistral-moderation-2411',
'mistral-moderation-latest',
]
};
@@ -83,10 +135,16 @@ const getDefaultModel = (provider: string | undefined): string => {
switch (provider) {
case 'ollama':
return '';
case 'mlx':
return '';
case 'anthropic':
return MODEL_LIST.anthropic[0];
case 'gemini':
return MODEL_LIST.gemini[0];
case 'groq':
return MODEL_LIST.groq[0];
case 'mistral':
return MODEL_LIST.mistral[0];
default:
return MODEL_LIST.openai[0];
}
@@ -126,7 +184,7 @@ export const configValidators = {
validateConfig(
'OCO_API_KEY',
value,
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "mlx" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
);
return value;
@@ -241,10 +299,17 @@ export const configValidators = {
validateConfig(
CONFIG_KEYS.OCO_AI_PROVIDER,
['openai', 'anthropic', 'gemini', 'azure', 'test', 'flowise'].includes(
value
) || value.startsWith('ollama'),
`${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
[
'openai',
'mistral',
'anthropic',
'gemini',
'azure',
'test',
'flowise',
'groq'
].includes(value) || value.startsWith('ollama'),
`${value} is not supported yet, use 'ollama', 'mlx', 'anthropic', 'azure', 'gemini', 'flowise', 'mistral' or 'openai' (default)`
);
return value;
@@ -288,7 +353,10 @@ export enum OCO_AI_PROVIDER_ENUM {
GEMINI = 'gemini',
AZURE = 'azure',
TEST = 'test',
FLOWISE = 'flowise'
FLOWISE = 'flowise',
GROQ = 'groq',
MISTRAL = 'mistral',
MLX = 'mlx'
}
export type ConfigType = {
@@ -352,7 +420,6 @@ export const DEFAULT_CONFIG = {
OCO_AI_PROVIDER: OCO_AI_PROVIDER_ENUM.OPENAI,
OCO_ONE_LINE_COMMIT: false,
OCO_TEST_MOCK_TYPE: 'commit-message',
OCO_FLOWISE_ENDPOINT: ':',
OCO_WHY: false,
OCO_GITPUSH: true // todo: deprecate
};
@@ -444,6 +511,25 @@ interface GetConfigOptions {
setDefaultValues?: boolean;
}
const cleanUndefinedValues = (config: ConfigType) => {
return Object.fromEntries(
Object.entries(config).map(([_, v]) => {
try {
if (typeof v === 'string') {
if (v === 'undefined') return [_, undefined];
if (v === 'null') return [_, null];
const parsedValue = JSON.parse(v);
return [_, parsedValue];
}
return [_, v];
} catch (error) {
return [_, v];
}
})
);
};
export const getConfig = ({
envPath = defaultEnvPath,
globalPath = defaultConfigPath
@@ -453,7 +539,9 @@ export const getConfig = ({
const config = mergeConfigs(envConfig, globalConfig);
return config;
const cleanConfig = cleanUndefinedValues(config);
return cleanConfig as ConfigType;
};
export const setConfig = (

View File

@@ -3,6 +3,7 @@ import { OpenAIClient as AzureOpenAIClient } from '@azure/openai';
import { GoogleGenerativeAI as GeminiClient } from '@google/generative-ai';
import { AxiosInstance as RawAxiosClient } from 'axios';
import { OpenAI as OpenAIClient } from 'openai';
import { Mistral as MistralClient } from '@mistralai/mistralai';
export interface AiEngineConfig {
apiKey: string;
@@ -17,7 +18,8 @@ type Client =
| AzureOpenAIClient
| AnthropicClient
| RawAxiosClient
| GeminiClient;
| GeminiClient
| MistralClient;
export interface AiEngine {
config: AiEngineConfig;

10
src/engine/groq.ts Normal file
View File

@@ -0,0 +1,10 @@
import { OpenAiConfig, OpenAiEngine } from './openAi';
interface GroqConfig extends OpenAiConfig {}
export class GroqEngine extends OpenAiEngine {
constructor(config: GroqConfig) {
config.baseURL = 'https://api.groq.com/openai/v1';
super(config);
}
}

82
src/engine/mistral.ts Normal file
View File

@@ -0,0 +1,82 @@
import axios from 'axios';
import { Mistral } from '@mistralai/mistralai';
import { OpenAI } from 'openai';
import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff';
import { tokenCount } from '../utils/tokenCount';
import { AiEngine, AiEngineConfig } from './Engine';
import {
AssistantMessage as MistralAssistantMessage,
SystemMessage as MistralSystemMessage,
ToolMessage as MistralToolMessage,
UserMessage as MistralUserMessage
} from '@mistralai/mistralai/models/components';
export interface MistralAiConfig extends AiEngineConfig {}
export type MistralCompletionMessageParam = Array<
| (MistralSystemMessage & { role: "system" })
| (MistralUserMessage & { role: "user" })
| (MistralAssistantMessage & { role: "assistant" })
| (MistralToolMessage & { role: "tool" })
>
export class MistralAiEngine implements AiEngine {
config: MistralAiConfig;
client: Mistral;
constructor(config: MistralAiConfig) {
this.config = config;
if (!config.baseURL) {
this.client = new Mistral({ apiKey: config.apiKey });
} else {
this.client = new Mistral({ apiKey: config.apiKey, serverURL: config.baseURL });
}
}
public generateCommitMessage = async (
messages: Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>
): Promise<string | null> => {
const params = {
model: this.config.model,
messages: messages as MistralCompletionMessageParam,
topP: 0.1,
maxTokens: this.config.maxTokensOutput
};
try {
const REQUEST_TOKENS = messages
.map((msg) => tokenCount(msg.content as string) + 4)
.reduce((a, b) => a + b, 0);
if (
REQUEST_TOKENS >
this.config.maxTokensInput - this.config.maxTokensOutput
)
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
const completion = await this.client.chat.complete(params);
if (!completion.choices)
throw Error('No completion choice available.')
const message = completion.choices[0].message;
if (!message || !message.content)
throw Error('No completion choice available.')
return message.content as string;
} catch (error) {
const err = error as Error;
if (
axios.isAxiosError<{ error?: { message: string } }>(error) &&
error.response?.status === 401
) {
const mistralError = error.response.data.error;
if (mistralError) throw new Error(mistralError.message);
}
throw err;
}
};
}

47
src/engine/mlx.ts Normal file
View File

@@ -0,0 +1,47 @@
import axios, { AxiosInstance } from 'axios';
import { OpenAI } from 'openai';
import { AiEngine, AiEngineConfig } from './Engine';
import { chown } from 'fs';
interface MLXConfig extends AiEngineConfig {}
export class MLXEngine implements AiEngine {
config: MLXConfig;
client: AxiosInstance;
constructor(config) {
this.config = config;
this.client = axios.create({
url: config.baseURL
? `${config.baseURL}/${config.apiKey}`
: 'http://localhost:8080/v1/chat/completions',
headers: { 'Content-Type': 'application/json' }
});
}
async generateCommitMessage(
messages: Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>):
Promise<string | undefined> {
const params = {
messages,
temperature: 0,
top_p: 0.1,
repetition_penalty: 1.5,
stream: false
};
try {
const response = await this.client.post(
this.client.getUri(this.config),
params
);
const choices = response.data.choices;
const message = choices[0].message;
return message?.content;
} catch (err: any) {
const message = err.response?.data?.error ?? err.message;
throw new Error(`MLX provider error: ${message}`);
}
}
}

View File

@@ -4,7 +4,7 @@ import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitD
import { tokenCount } from '../utils/tokenCount';
import { AiEngine, AiEngineConfig } from './Engine';
interface OpenAiConfig extends AiEngineConfig {}
export interface OpenAiConfig extends AiEngineConfig {}
export class OpenAiEngine implements AiEngine {
config: OpenAiConfig;
@@ -12,7 +12,12 @@ export class OpenAiEngine implements AiEngine {
constructor(config: OpenAiConfig) {
this.config = config;
this.client = new OpenAI({ apiKey: config.apiKey });
if (!config.baseURL) {
this.client = new OpenAI({ apiKey: config.apiKey });
} else {
this.client = new OpenAI({ apiKey: config.apiKey, baseURL: config.baseURL });
}
}
public generateCommitMessage = async (

View File

@@ -11,9 +11,10 @@ const MAX_TOKENS_OUTPUT = config.OCO_TOKENS_MAX_OUTPUT;
const generateCommitMessageChatCompletionPrompt = async (
diff: string,
fullGitMojiSpec: boolean
fullGitMojiSpec: boolean,
context: string
): Promise<Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>> => {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec, context);
const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
@@ -36,10 +37,14 @@ const ADJUSTMENT_FACTOR = 20;
export const generateCommitMessageByDiff = async (
diff: string,
fullGitMojiSpec: boolean = false
fullGitMojiSpec: boolean = false,
context: string = ""
): Promise<string> => {
try {
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(
fullGitMojiSpec,
context
);
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
(msg) => tokenCount(msg.content as string) + 4
@@ -69,7 +74,8 @@ export const generateCommitMessageByDiff = async (
const messages = await generateCommitMessageChatCompletionPrompt(
diff,
fullGitMojiSpec
fullGitMojiSpec,
context,
);
const engine = getEngine();

View File

@@ -10,10 +10,12 @@ export default function () {
const entriesToSet: [key: string, value: string | boolean | number][] = [];
for (const entry of Object.entries(DEFAULT_CONFIG)) {
const [key, _value] = entry;
if (config[key] === 'undefined') entriesToSet.push(entry);
if (config[key] === 'undefined' || config[key] === undefined)
entriesToSet.push(entry);
}
if (entriesToSet.length > 0) setConfig(entriesToSet);
console.log(entriesToSet);
};
setDefaultConfigValues(getGlobalConfig());

View File

@@ -53,6 +53,7 @@ export const runMigrations = async () => {
migration.name
}: ${error}`
);
process.exit(1);
}
isMigrated = true;

View File

@@ -111,9 +111,24 @@ const getOneLineCommitInstruction = () =>
? 'Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change.'
: '';
/**
* Get the context of the user input
* @param extraArgs - The arguments passed to the command line
* @example
* $ oco -- This is a context used to generate the commit message
* @returns - The context of the user input
*/
const userInputCodeContext = (context: string) => {
if (context !== '' && context !== ' ') {
return `Additional context provided by the user: <context>${context}</context>\nConsider this context when generating the commit message, incorporating relevant information when appropriate.`;
}
return '';
};
const INIT_MAIN_PROMPT = (
language: string,
fullGitMojiSpec: boolean
fullGitMojiSpec: boolean,
context: string
): OpenAI.Chat.Completions.ChatCompletionMessageParam => ({
role: 'system',
content: (() => {
@@ -127,15 +142,16 @@ const INIT_MAIN_PROMPT = (
const descriptionGuideline = getDescriptionInstruction();
const oneLineCommitGuideline = getOneLineCommitInstruction();
const generalGuidelines = `Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`;
const userInputContext = userInputCodeContext(context);
return `${missionStatement}\n${diffInstruction}\n${conventionGuidelines}\n${descriptionGuideline}\n${oneLineCommitGuideline}\n${generalGuidelines}`;
return `${missionStatement}\n${diffInstruction}\n${conventionGuidelines}\n${descriptionGuideline}\n${oneLineCommitGuideline}\n${generalGuidelines}\n${userInputContext}`;
})()
});
export const INIT_DIFF_PROMPT: OpenAI.Chat.Completions.ChatCompletionMessageParam =
{
role: 'user',
content: `diff --git a/src/server.ts b/src/server.ts
{
role: 'user',
content: `diff --git a/src/server.ts b/src/server.ts
index ad4db42..f3b18a9 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -159,7 +175,7 @@ export const INIT_DIFF_PROMPT: OpenAI.Chat.Completions.ChatCompletionMessagePara
+app.listen(process.env.PORT || PORT, () => {
+ console.log(\`Server listening on port \${PORT}\`);
});`
};
};
const getContent = (translation: ConsistencyPrompt) => {
const fix = config.OCO_EMOJI
@@ -185,7 +201,8 @@ const INIT_CONSISTENCY_PROMPT = (
});
export const getMainCommitPrompt = async (
fullGitMojiSpec: boolean
fullGitMojiSpec: boolean,
context: string
): Promise<Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>> => {
switch (config.OCO_PROMPT_MODULE) {
case '@commitlint':
@@ -207,14 +224,14 @@ export const getMainCommitPrompt = async (
INIT_DIFF_PROMPT,
INIT_CONSISTENCY_PROMPT(
commitLintConfig.consistency[
translation.localLanguage
translation.localLanguage
] as ConsistencyPrompt
)
];
default:
return [
INIT_MAIN_PROMPT(translation.localLanguage, fullGitMojiSpec),
INIT_MAIN_PROMPT(translation.localLanguage, fullGitMojiSpec, context),
INIT_DIFF_PROMPT,
INIT_CONSISTENCY_PROMPT(translation)
];

View File

@@ -6,7 +6,10 @@ import { FlowiseEngine } from '../engine/flowise';
import { GeminiEngine } from '../engine/gemini';
import { OllamaEngine } from '../engine/ollama';
import { OpenAiEngine } from '../engine/openAi';
import { MistralAiEngine } from '../engine/mistral';
import { TestAi, TestMockType } from '../engine/testAi';
import { GroqEngine } from '../engine/groq';
import { MLXEngine } from '../engine/mlx';
export function getEngine(): AiEngine {
const config = getConfig();
@@ -39,6 +42,15 @@ export function getEngine(): AiEngine {
case OCO_AI_PROVIDER_ENUM.FLOWISE:
return new FlowiseEngine(DEFAULT_CONFIG);
case OCO_AI_PROVIDER_ENUM.GROQ:
return new GroqEngine(DEFAULT_CONFIG);
case OCO_AI_PROVIDER_ENUM.MISTRAL:
return new MistralAiEngine(DEFAULT_CONFIG);
case OCO_AI_PROVIDER_ENUM.MLX:
return new MLXEngine(DEFAULT_CONFIG);
default:
return new OpenAiEngine(DEFAULT_CONFIG);
}