@@ -431,8 +431,8 @@ var require_escape = __commonJS({
431
431
}
432
432
function escapeArgument(arg, doubleEscapeMetaChars) {
433
433
arg = `${arg}`;
434
- arg = arg.replace(/(\\*) "/g, '$1$1\\"');
435
- arg = arg.replace(/(\\*) $/, "$1$1");
434
+ arg = arg.replace(/(?=(\\+?)?)\1 "/g, '$1$1\\"');
435
+ arg = arg.replace(/(?=(\\+?)?)\1 $/, "$1$1");
436
436
arg = `"${arg}"`;
437
437
arg = arg.replace(metaCharsRegExp, "^$1");
438
438
if (doubleEscapeMetaChars) {
@@ -578,7 +578,7 @@ var require_enoent = __commonJS({
578
578
const originalEmit = cp.emit;
579
579
cp.emit = function(name, arg1) {
580
580
if (name === "exit") {
581
- const err = verifyENOENT(arg1, parsed, "spawn" );
581
+ const err = verifyENOENT(arg1, parsed);
582
582
if (err) {
583
583
return originalEmit.call(cp, "error", err);
584
584
}
@@ -1672,7 +1672,7 @@ var require_mappingTable = __commonJS({
1672
1672
var require_tr46 = __commonJS({
1673
1673
"node_modules/node-fetch/node_modules/tr46/index.js"(exports, module2) {
1674
1674
"use strict";
1675
- var punycode = require(" punycode" );
1675
+ const punycode = require(' punycode/' );
1676
1676
var mappingTable = require_mappingTable();
1677
1677
var PROCESSING_OPTIONS = {
1678
1678
TRANSITIONAL: 0,
@@ -1834,7 +1834,7 @@ var require_tr46 = __commonJS({
1834
1834
var require_url_state_machine = __commonJS({
1835
1835
"node_modules/node-fetch/node_modules/whatwg-url/lib/url-state-machine.js"(exports, module2) {
1836
1836
"use strict";
1837
- var punycode = require(" punycode" );
1837
+ const punycode = require(' punycode/' );
1838
1838
var tr46 = require_tr46();
1839
1839
var specialSchemes = {
1840
1840
ftp: 21,
@@ -27389,7 +27389,8 @@ var package_default = {
27389
27389
"test:unit:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:unit",
27390
27390
"test:e2e": "npm run test:e2e:setup && jest test/e2e",
27391
27391
"test:e2e:setup": "sh test/e2e/setup.sh",
27392
- "test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e"
27392
+ "test:e2e:docker": "npm run test:docker-build && DOCKER_CONTENT_TRUST=0 docker run --rm oco-test npm run test:e2e",
27393
+ "mlx:start": "OCO_AI_PROVIDER='mlx' node ./out/cli.cjs"
27393
27394
},
27394
27395
devDependencies: {
27395
27396
"@commitlint/types": "^17.4.4",
@@ -29933,6 +29934,8 @@ var getDefaultModel = (provider) => {
29933
29934
switch (provider) {
29934
29935
case "ollama":
29935
29936
return "";
29937
+ case "mlx":
29938
+ return "";
29936
29939
case "anthropic":
29937
29940
return MODEL_LIST.anthropic[0];
29938
29941
case "gemini":
@@ -29964,7 +29967,7 @@ var configValidators = {
29964
29967
validateConfig(
29965
29968
"OCO_API_KEY",
29966
29969
value,
29967
- '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`'
29970
+ '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`'
29968
29971
);
29969
29972
return value;
29970
29973
},
@@ -30070,8 +30073,8 @@ var configValidators = {
30070
30073
"test",
30071
30074
"flowise",
30072
30075
"groq"
30073
- ].includes(value) || value.startsWith("ollama"),
30074
- `${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
30076
+ ].includes(value) || value.startsWith("ollama") || value.startsWith("mlx") ,
30077
+ `${value} is not supported yet, use 'ollama', 'mlx', anthropic', 'azure', 'gemini', 'flowise' or 'openai' (default)`
30075
30078
);
30076
30079
return value;
30077
30080
},
@@ -30111,6 +30114,7 @@ var OCO_AI_PROVIDER_ENUM = /* @__PURE__ */ ((OCO_AI_PROVIDER_ENUM2) => {
30111
30114
OCO_AI_PROVIDER_ENUM2["TEST"] = "test";
30112
30115
OCO_AI_PROVIDER_ENUM2["FLOWISE"] = "flowise";
30113
30116
OCO_AI_PROVIDER_ENUM2["GROQ"] = "groq";
30117
+ OCO_AI_PROVIDER_ENUM2["MLX"] = "mlx";
30114
30118
return OCO_AI_PROVIDER_ENUM2;
30115
30119
})(OCO_AI_PROVIDER_ENUM || {});
30116
30120
var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
@@ -44524,6 +44528,38 @@ var GroqEngine = class extends OpenAiEngine {
44524
44528
}
44525
44529
};
44526
44530
44531
+ // src/engine/mlx.ts
44532
+ var MLXEngine = class {
44533
+ constructor(config7) {
44534
+ this.config = config7;
44535
+ this.client = axios_default.create({
44536
+ url: config7.baseURL ? `${config7.baseURL}/${config7.apiKey}` : "http://localhost:8080/v1/chat/completions",
44537
+ headers: { "Content-Type": "application/json" }
44538
+ });
44539
+ }
44540
+ async generateCommitMessage(messages) {
44541
+ const params = {
44542
+ messages,
44543
+ temperature: 0,
44544
+ top_p: 0.1,
44545
+ repetition_penalty: 1.5,
44546
+ stream: false
44547
+ };
44548
+ try {
44549
+ const response = await this.client.post(
44550
+ this.client.getUri(this.config),
44551
+ params
44552
+ );
44553
+ const choices = response.data.choices;
44554
+ const message = choices[0].message;
44555
+ return message?.content;
44556
+ } catch (err) {
44557
+ const message = err.response?.data?.error ?? err.message;
44558
+ throw new Error(`MLX provider error: ${message}`);
44559
+ }
44560
+ }
44561
+ };
44562
+
44527
44563
// src/utils/engine.ts
44528
44564
function getEngine() {
44529
44565
const config7 = getConfig();
@@ -44550,6 +44586,8 @@ function getEngine() {
44550
44586
return new FlowiseEngine(DEFAULT_CONFIG2);
44551
44587
case "groq" /* GROQ */:
44552
44588
return new GroqEngine(DEFAULT_CONFIG2);
44589
+ case "mlx" /* MLX */:
44590
+ return new MLXEngine(DEFAULT_CONFIG2);
44553
44591
default:
44554
44592
return new OpenAiEngine(DEFAULT_CONFIG2);
44555
44593
}
@@ -44931,7 +44969,14 @@ var CONVENTIONAL_COMMIT_KEYWORDS = "Do not preface the commit with anything, exc
44931
44969
var getCommitConvention = (fullGitMojiSpec) => config4.OCO_EMOJI ? fullGitMojiSpec ? FULL_GITMOJI_SPEC : GITMOJI_HELP : CONVENTIONAL_COMMIT_KEYWORDS;
44932
44970
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.";
44933
44971
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." : "";
44934
- var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
44972
+ var userInputCodeContext = (context) => {
44973
+ if (context !== "" && context !== " ") {
44974
+ return `Additional context provided by the user: <context>${context}</context>
44975
+ Consider this context when generating the commit message, incorporating relevant information when appropriate.`;
44976
+ }
44977
+ return "";
44978
+ };
44979
+ var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec, context) => ({
44935
44980
role: "system",
44936
44981
content: (() => {
44937
44982
const commitConvention = fullGitMojiSpec ? "GitMoji specification" : "Conventional Commit Convention";
@@ -44941,12 +44986,14 @@ var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
44941
44986
const descriptionGuideline = getDescriptionInstruction();
44942
44987
const oneLineCommitGuideline = getOneLineCommitInstruction();
44943
44988
const generalGuidelines = `Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`;
44989
+ const userInputContext = userInputCodeContext(context);
44944
44990
return `${missionStatement}
44945
44991
${diffInstruction}
44946
44992
${conventionGuidelines}
44947
44993
${descriptionGuideline}
44948
44994
${oneLineCommitGuideline}
44949
- ${generalGuidelines}`;
44995
+ ${generalGuidelines}
44996
+ ${userInputContext}`;
44950
44997
})()
44951
44998
});
44952
44999
var INIT_DIFF_PROMPT = {
@@ -44988,7 +45035,7 @@ var INIT_CONSISTENCY_PROMPT = (translation4) => ({
44988
45035
role: "assistant",
44989
45036
content: getContent(translation4)
44990
45037
});
44991
- var getMainCommitPrompt = async (fullGitMojiSpec) => {
45038
+ var getMainCommitPrompt = async (fullGitMojiSpec, context ) => {
44992
45039
switch (config4.OCO_PROMPT_MODULE) {
44993
45040
case "@commitlint":
44994
45041
if (!await commitlintLLMConfigExists()) {
@@ -45010,7 +45057,7 @@ var getMainCommitPrompt = async (fullGitMojiSpec) => {
45010
45057
];
45011
45058
default:
45012
45059
return [
45013
- INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec),
45060
+ INIT_MAIN_PROMPT2(translation3.localLanguage, fullGitMojiSpec, context ),
45014
45061
INIT_DIFF_PROMPT,
45015
45062
INIT_CONSISTENCY_PROMPT(translation3)
45016
45063
];
@@ -45037,8 +45084,8 @@ function mergeDiffs(arr, maxStringLength) {
45037
45084
var config5 = getConfig();
45038
45085
var MAX_TOKENS_INPUT = config5.OCO_TOKENS_MAX_INPUT;
45039
45086
var MAX_TOKENS_OUTPUT = config5.OCO_TOKENS_MAX_OUTPUT;
45040
- var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => {
45041
- const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
45087
+ var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec, context ) => {
45088
+ const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec, context );
45042
45089
const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
45043
45090
chatContextAsCompletionRequest.push({
45044
45091
role: "user",
@@ -45054,9 +45101,12 @@ var GenerateCommitMessageErrorEnum = ((GenerateCommitMessageErrorEnum2) => {
45054
45101
return GenerateCommitMessageErrorEnum2;
45055
45102
})(GenerateCommitMessageErrorEnum || {});
45056
45103
var ADJUSTMENT_FACTOR = 20;
45057
- var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
45104
+ var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false, context = "" ) => {
45058
45105
try {
45059
- const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
45106
+ const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(
45107
+ fullGitMojiSpec,
45108
+ context
45109
+ );
45060
45110
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
45061
45111
(msg) => tokenCount(msg.content) + 4
45062
45112
).reduce((a4, b7) => a4 + b7, 0);
@@ -45076,7 +45126,8 @@ var generateCommitMessageByDiff = async (diff, fullGitMojiSpec = false) => {
45076
45126
}
45077
45127
const messages = await generateCommitMessageChatCompletionPrompt(
45078
45128
diff,
45079
- fullGitMojiSpec
45129
+ fullGitMojiSpec,
45130
+ context
45080
45131
);
45081
45132
const engine = getEngine();
45082
45133
const commitMessage = await engine.generateCommitMessage(messages);
@@ -45283,6 +45334,7 @@ var checkMessageTemplate = (extraArgs2) => {
45283
45334
var generateCommitMessageFromGitDiff = async ({
45284
45335
diff,
45285
45336
extraArgs: extraArgs2,
45337
+ context = "",
45286
45338
fullGitMojiSpec = false,
45287
45339
skipCommitConfirmation = false
45288
45340
}) => {
@@ -45292,7 +45344,8 @@ var generateCommitMessageFromGitDiff = async ({
45292
45344
try {
45293
45345
let commitMessage = await generateCommitMessageByDiff(
45294
45346
diff,
45295
- fullGitMojiSpec
45347
+ fullGitMojiSpec,
45348
+ context
45296
45349
);
45297
45350
const messageTemplate = checkMessageTemplate(extraArgs2);
45298
45351
if (config6.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") {
@@ -45402,7 +45455,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
45402
45455
process.exit(1);
45403
45456
}
45404
45457
};
45405
- async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec = false, skipCommitConfirmation = false) {
45458
+ async function commit(extraArgs2 = [], context = "", isStageAllFlag = false, fullGitMojiSpec = false, skipCommitConfirmation = false) {
45406
45459
if (isStageAllFlag) {
45407
45460
const changedFiles2 = await getChangedFiles();
45408
45461
if (changedFiles2)
@@ -45433,7 +45486,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec =
45433
45486
if (hD2(isStageAllAndCommitConfirmedByUser))
45434
45487
process.exit(1);
45435
45488
if (isStageAllAndCommitConfirmedByUser) {
45436
- await commit(extraArgs2, true, fullGitMojiSpec);
45489
+ await commit(extraArgs2, context, true, fullGitMojiSpec);
45437
45490
process.exit(1);
45438
45491
}
45439
45492
if (stagedFiles.length === 0 && changedFiles.length > 0) {
@@ -45448,7 +45501,7 @@ async function commit(extraArgs2 = [], isStageAllFlag = false, fullGitMojiSpec =
45448
45501
process.exit(1);
45449
45502
await gitAdd({ files });
45450
45503
}
45451
- await commit(extraArgs2, false, fullGitMojiSpec);
45504
+ await commit(extraArgs2, context, false, fullGitMojiSpec);
45452
45505
process.exit(1);
45453
45506
}
45454
45507
stagedFilesSpinner.stop(
@@ -45459,6 +45512,7 @@ ${stagedFiles.map((file) => ` ${file}`).join("\n")}`
45459
45512
generateCommitMessageFromGitDiff({
45460
45513
diff: await getDiff({ files: stagedFiles }),
45461
45514
extraArgs: extraArgs2,
45515
+ context,
45462
45516
fullGitMojiSpec,
45463
45517
skipCommitConfirmation
45464
45518
})
@@ -45817,6 +45871,12 @@ Z2(
45817
45871
commands: [configCommand, hookCommand, commitlintConfigCommand],
45818
45872
flags: {
45819
45873
fgm: Boolean,
45874
+ context: {
45875
+ type: String,
45876
+ alias: "c",
45877
+ description: "Additional user input context for the commit message",
45878
+ default: ""
45879
+ },
45820
45880
yes: {
45821
45881
type: Boolean,
45822
45882
alias: "y",
@@ -45833,7 +45893,7 @@ Z2(
45833
45893
if (await isHookCalled()) {
45834
45894
prepareCommitMessageHook();
45835
45895
} else {
45836
- commit(extraArgs, false, flags.fgm, flags.yes);
45896
+ commit(extraArgs, flags.context, false, flags.fgm, flags.yes);
45837
45897
}
45838
45898
},
45839
45899
extraArgs
0 commit comments