@johnowennixon/diffdash 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -13
- package/dist/package.json +15 -15
- package/dist/src/diffdash.js +8 -6
- package/dist/src/lib_datetime.js +2 -10
- package/dist/src/lib_diffdash_cli.js +3 -2
- package/dist/src/lib_diffdash_config.js +4 -3
- package/dist/src/lib_diffdash_llm.js +3 -2
- package/dist/src/lib_diffdash_sequence.js +19 -10
- package/dist/src/lib_error.js +11 -2
- package/dist/src/lib_llm_access.js +13 -13
- package/dist/src/lib_llm_model.js +52 -8
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
A command-line tool to generate Git commit messages using AI.
|
|
4
4
|
|
|
5
|
+
## Demonstration
|
|
6
|
+
|
|
5
7
|

|
|
6
8
|
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Optionally select from a choice of LLM models
|
|
11
|
+
* Generate Git commit messages in natural English
|
|
12
|
+
* Add a footer to the generated commit messages
|
|
13
|
+
* Add a prefix or suffix to the summary line
|
|
14
|
+
* Select from a choice of LLM models
|
|
14
15
|
* Compare messages generated from all configured models
|
|
16
|
+
* Disable or auto-approve various stages
|
|
17
|
+
* Just output the commit message for use in scripts
|
|
15
18
|
* Configuration using standard API provider environment variables
|
|
16
19
|
* Uses the Vercel AI SDK
|
|
17
20
|
* Uses structured JSON with compatible models
|
|
@@ -59,12 +62,6 @@ export GEMINI_API_KEY=your-api-key
|
|
|
59
62
|
# Basic usage (uses defaults)
|
|
60
63
|
diffdash
|
|
61
64
|
|
|
62
|
-
# Add a prefix to the commit message summary line
|
|
63
|
-
diffdash --add-prefix "[FIX]"
|
|
64
|
-
|
|
65
|
-
# Add a suffix to the commit message summary line
|
|
66
|
-
diffdash --add-suffix "(closes #123)"
|
|
67
|
-
|
|
68
65
|
# Automatically stage all changes, but still prompt for commit and push
|
|
69
66
|
diffdash --auto-add
|
|
70
67
|
|
|
@@ -92,6 +89,12 @@ diffdash --disable-push
|
|
|
92
89
|
# Skip git hooks when pushing
|
|
93
90
|
diffdash --no-verify
|
|
94
91
|
|
|
92
|
+
# Add a prefix to the commit message summary line
|
|
93
|
+
diffdash --add-prefix "[FIX]"
|
|
94
|
+
|
|
95
|
+
# Add a suffix to the commit message summary line
|
|
96
|
+
diffdash --add-suffix "(closes #123)"
|
|
97
|
+
|
|
95
98
|
# Display commit messages generated by all models
|
|
96
99
|
diffdash --llm-compare
|
|
97
100
|
|
|
@@ -101,6 +104,9 @@ diffdash --llm-fallback
|
|
|
101
104
|
# Specify the LLM model by name
|
|
102
105
|
diffdash --llm-model claude-3.5-haiku
|
|
103
106
|
|
|
107
|
+
# Just output the commit message for use in scripts
|
|
108
|
+
diffdash --just-output
|
|
109
|
+
|
|
104
110
|
# Debug options
|
|
105
111
|
diffdash --debug-llm-inputs --debug-llm-outputs
|
|
106
112
|
```
|
|
@@ -113,8 +119,6 @@ All command-line arguments are optional.
|
|
|
113
119
|
|--------|-------------|
|
|
114
120
|
| `--help` | show a help message and exit |
|
|
115
121
|
| `--version` | show program version information and exit |
|
|
116
|
-
| `--add-prefix PREFIX` | add a prefix to the commit message summary line |
|
|
117
|
-
| `--add-suffix SUFFIX` | add a suffix to the commit message summary line |
|
|
118
122
|
| `--auto-add` | automatically stage all changes without confirmation |
|
|
119
123
|
| `--auto-commit` | automatically commit changes without confirmation |
|
|
120
124
|
| `--auto-push` | automatically push changes after commit without confirmation |
|
|
@@ -125,12 +129,15 @@ All command-line arguments are optional.
|
|
|
125
129
|
| `--disable-push` | disable pushing changes - exit after making the commit |
|
|
126
130
|
| `--push-no-verify` | bypass git hooks when pushing to Git |
|
|
127
131
|
| `--push-force` | apply force when pushing to Git |
|
|
132
|
+
| `--add-prefix PREFIX` | add a prefix to the commit message summary line |
|
|
133
|
+
| `--add-suffix SUFFIX` | add a suffix to the commit message summary line |
|
|
128
134
|
| `--llm-list` | display a list of available Large Language Models and exit |
|
|
129
135
|
| `--llm-compare` | compare the generated messages from all models - but do not commit |
|
|
130
136
|
| `--llm-router` | prefer to access the LLM via a router rather than direct |
|
|
131
137
|
| `--llm-fallback` | use the fallback LLM model instead of the default |
|
|
132
138
|
| `--llm-model MODEL` | choose the LLM model by name (the default is normally best) |
|
|
133
139
|
| `--llm-excludes MODELS` | models to exclude from comparison (comma separated) |
|
|
140
|
+
| `--just-output` | just output the commit message for use in scripts |
|
|
134
141
|
| `--silent` | suppress all normal output - errors and aborts still display |
|
|
135
142
|
| `--debug-llm-inputs` | show inputs (including all prompts) sent to the LLM |
|
|
136
143
|
| `--debug-llm-outputs` | show outputs received from the LLM |
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnowennixon/diffdash",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A command-line tool to generate Git commit messages using AI",
|
|
5
5
|
"license": "0BSD",
|
|
6
6
|
"author": "John Owen Nixon",
|
|
@@ -40,30 +40,30 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@ai-sdk/anthropic": "1.2.12",
|
|
43
|
-
"@ai-sdk/deepseek": "0.2.
|
|
44
|
-
"@ai-sdk/google": "1.2.
|
|
45
|
-
"@ai-sdk/openai": "1.3.
|
|
43
|
+
"@ai-sdk/deepseek": "0.2.16",
|
|
44
|
+
"@ai-sdk/google": "1.2.22",
|
|
45
|
+
"@ai-sdk/openai": "1.3.23",
|
|
46
46
|
"@openrouter/ai-sdk-provider": "0.7.2",
|
|
47
47
|
"@requesty/ai-sdk": "0.0.9",
|
|
48
|
-
"ai": "4.3.
|
|
48
|
+
"ai": "4.3.19",
|
|
49
49
|
"ansis": "4.1.0",
|
|
50
50
|
"argparse": "2.0.1",
|
|
51
51
|
"cli-table3": "0.6.5",
|
|
52
52
|
"simple-git": "3.28.0",
|
|
53
|
-
"zod": "3.25.
|
|
53
|
+
"zod": "3.25.76"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@biomejs/biome": "2.
|
|
56
|
+
"@biomejs/biome": "2.1.1",
|
|
57
57
|
"@eslint/eslintrc": "3.3.1",
|
|
58
|
-
"@eslint/js": "9.
|
|
58
|
+
"@eslint/js": "9.31.0",
|
|
59
59
|
"@johnowennixon/add-shebangs": "1.1.0",
|
|
60
60
|
"@johnowennixon/chmodx": "2.0.0",
|
|
61
|
-
"@stylistic/eslint-plugin": "5.
|
|
61
|
+
"@stylistic/eslint-plugin": "5.2.0",
|
|
62
62
|
"@types/argparse": "2.0.17",
|
|
63
|
-
"@types/node": "24.0.
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
65
|
-
"@typescript-eslint/parser": "8.
|
|
66
|
-
"eslint": "9.
|
|
63
|
+
"@types/node": "24.0.14",
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "8.37.0",
|
|
65
|
+
"@typescript-eslint/parser": "8.37.0",
|
|
66
|
+
"eslint": "9.31.0",
|
|
67
67
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
68
68
|
"eslint-plugin-import-x": "4.16.1",
|
|
69
69
|
"eslint-plugin-sonarjs": "3.0.4",
|
|
@@ -72,9 +72,9 @@
|
|
|
72
72
|
"knip": "5.61.3",
|
|
73
73
|
"markdownlint-cli2": "0.18.1",
|
|
74
74
|
"npm-run-all2": "8.0.4",
|
|
75
|
-
"oxlint": "1.
|
|
75
|
+
"oxlint": "1.7.0",
|
|
76
76
|
"rimraf": "6.0.1",
|
|
77
77
|
"typescript": "5.8.3",
|
|
78
|
-
"typescript-eslint": "8.
|
|
78
|
+
"typescript-eslint": "8.37.0"
|
|
79
79
|
}
|
|
80
80
|
}
|
package/dist/src/diffdash.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { ansi_blue, ansi_italic, ansi_red } from "./lib_ansi.js";
|
|
3
3
|
import { diffdash_config_get } from "./lib_diffdash_config.js";
|
|
4
|
-
import { diffdash_sequence_compare, diffdash_sequence_normal } from "./lib_diffdash_sequence.js";
|
|
4
|
+
import { diffdash_sequence_compare, diffdash_sequence_normal, diffdash_sequence_output } from "./lib_diffdash_sequence.js";
|
|
5
5
|
import { error_abort } from "./lib_error.js";
|
|
6
6
|
import { tell_okay, tell_plain } from "./lib_tell.js";
|
|
7
7
|
async function main() {
|
|
8
8
|
const config = diffdash_config_get();
|
|
9
|
-
const {
|
|
10
|
-
if (!silent) {
|
|
9
|
+
const { silent, just_output, llm_compare } = config;
|
|
10
|
+
if (!silent && !just_output) {
|
|
11
11
|
const diffdash = ansi_italic(ansi_blue("Diff") + ansi_red("Dash"));
|
|
12
12
|
tell_plain(`This is ${diffdash} - the fast AI Git commit tool`);
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (just_output) {
|
|
15
|
+
await diffdash_sequence_output(config);
|
|
16
|
+
}
|
|
17
|
+
else if (llm_compare) {
|
|
16
18
|
await diffdash_sequence_compare(config);
|
|
17
19
|
}
|
|
18
20
|
else {
|
|
19
21
|
await diffdash_sequence_normal(config);
|
|
20
22
|
}
|
|
21
|
-
if (!silent) {
|
|
23
|
+
if (!silent && !just_output) {
|
|
22
24
|
tell_okay();
|
|
23
25
|
}
|
|
24
26
|
}
|
package/dist/src/lib_datetime.js
CHANGED
|
@@ -32,18 +32,10 @@ export function datetime_format_utc_iso_hms(date) {
|
|
|
32
32
|
return date.toISOString().slice(11, 19);
|
|
33
33
|
}
|
|
34
34
|
export function datetime_format_utc_timestamp_alpha(date) {
|
|
35
|
-
|
|
36
|
-
const s2 = s1.replaceAll(DASH, EMPTY);
|
|
37
|
-
const s3 = s2.replaceAll(COLON, EMPTY);
|
|
38
|
-
const s4 = s3 + "Z";
|
|
39
|
-
return s4;
|
|
35
|
+
return date.toISOString().slice(0, 19).replaceAll(DASH, EMPTY).replaceAll(COLON, EMPTY) + "Z";
|
|
40
36
|
}
|
|
41
37
|
export function datetime_format_utc_timestamp_numeric(date) {
|
|
42
|
-
|
|
43
|
-
const s2 = s1.replaceAll(DASH, EMPTY);
|
|
44
|
-
const s3 = s2.replaceAll(COLON, EMPTY);
|
|
45
|
-
const s4 = s3.replace("T", EMPTY);
|
|
46
|
-
return s4;
|
|
38
|
+
return date.toISOString().slice(0, 19).replaceAll(DASH, EMPTY).replaceAll(COLON, EMPTY).replace("T", EMPTY);
|
|
47
39
|
}
|
|
48
40
|
function datetime_localize(date) {
|
|
49
41
|
return new Date(date.valueOf() - date.getTimezoneOffset() * 60_000);
|
|
@@ -2,8 +2,6 @@ import { cli_boolean, cli_choice_default, cli_make_parser, cli_string } from "./
|
|
|
2
2
|
import { diffdash_llm_model_choices, diffdash_llm_model_default, diffdash_llm_model_fallback, } from "./lib_diffdash_llm.js";
|
|
3
3
|
const diffdash_cli_schema = {
|
|
4
4
|
version: cli_boolean({ help: "show program version information and exit" }),
|
|
5
|
-
add_prefix: cli_string({ help: "add a prefix to the commit message summary line", metavar: "PREFIX" }),
|
|
6
|
-
add_suffix: cli_string({ help: "add a suffix to the commit message summary line", metavar: "SUFFIX" }),
|
|
7
5
|
auto_add: cli_boolean({ help: "automatically stage all changes without confirmation" }),
|
|
8
6
|
auto_commit: cli_boolean({ help: "automatically commit changes without confirmation" }),
|
|
9
7
|
auto_push: cli_boolean({ help: "automatically push changes after commit without confirmation" }),
|
|
@@ -14,6 +12,8 @@ const diffdash_cli_schema = {
|
|
|
14
12
|
disable_push: cli_boolean({ help: "disable pushing changes - exit after making the commit" }),
|
|
15
13
|
push_no_verify: cli_boolean({ help: "bypass git hooks when pushing to Git" }),
|
|
16
14
|
push_force: cli_boolean({ help: "apply force when pushing to Git" }),
|
|
15
|
+
add_prefix: cli_string({ help: "add a prefix to the commit message summary line", metavar: "PREFIX" }),
|
|
16
|
+
add_suffix: cli_string({ help: "add a suffix to the commit message summary line", metavar: "SUFFIX" }),
|
|
17
17
|
llm_list: cli_boolean({ help: "display a list of available Large Language Models and exit" }),
|
|
18
18
|
llm_compare: cli_boolean({ help: "compare the generated messages from all models - but do not commit" }),
|
|
19
19
|
llm_router: cli_boolean({ help: "prefer to access the LLM via a router rather than direct" }),
|
|
@@ -24,6 +24,7 @@ const diffdash_cli_schema = {
|
|
|
24
24
|
default: diffdash_llm_model_default,
|
|
25
25
|
}),
|
|
26
26
|
llm_excludes: cli_string({ help: "models to exclude from comparison (comma separated)", metavar: "MODELS" }),
|
|
27
|
+
just_output: cli_boolean({ help: "just output the commit message for use in scripts" }),
|
|
27
28
|
silent: cli_boolean({ help: "suppress all normal output - errors and aborts still display" }),
|
|
28
29
|
debug_llm_inputs: cli_boolean({ help: "debug inputs (including all prompts) sent to the LLM" }),
|
|
29
30
|
debug_llm_outputs: cli_boolean({ help: "debug outputs received from the LLM" }),
|
|
@@ -7,7 +7,7 @@ import { PACKAGE_NAME, PACKAGE_VERSION } from "./lib_package.js";
|
|
|
7
7
|
import { tell_plain } from "./lib_tell.js";
|
|
8
8
|
export function diffdash_config_get() {
|
|
9
9
|
const pa = diffdash_cli_parser.parsed_args;
|
|
10
|
-
const { version,
|
|
10
|
+
const { version, auto_add, auto_commit, auto_push, disable_add, disable_commit, disable_preview, disable_status, disable_push, push_no_verify, push_force, add_prefix, add_suffix, llm_list, llm_compare, llm_router, llm_fallback, llm_model, llm_excludes, just_output, silent, debug_llm_inputs, debug_llm_outputs, } = pa;
|
|
11
11
|
if (version) {
|
|
12
12
|
tell_plain(`${PACKAGE_NAME} v${PACKAGE_VERSION}`);
|
|
13
13
|
process.exit(0);
|
|
@@ -30,8 +30,6 @@ export function diffdash_config_get() {
|
|
|
30
30
|
debug_channels.llm_inputs = debug_llm_inputs;
|
|
31
31
|
debug_channels.llm_outputs = debug_llm_outputs;
|
|
32
32
|
const config = {
|
|
33
|
-
add_prefix,
|
|
34
|
-
add_suffix,
|
|
35
33
|
auto_add,
|
|
36
34
|
auto_commit,
|
|
37
35
|
auto_push,
|
|
@@ -42,9 +40,12 @@ export function diffdash_config_get() {
|
|
|
42
40
|
disable_push,
|
|
43
41
|
push_no_verify,
|
|
44
42
|
push_force,
|
|
43
|
+
add_prefix,
|
|
44
|
+
add_suffix,
|
|
45
45
|
llm_compare,
|
|
46
46
|
llm_config,
|
|
47
47
|
all_llm_configs,
|
|
48
|
+
just_output,
|
|
48
49
|
silent,
|
|
49
50
|
};
|
|
50
51
|
debug_inspect_when(debug_channels.config, config, "config");
|
|
@@ -5,16 +5,17 @@ const model_name_fallback = "claude-3.5-haiku";
|
|
|
5
5
|
const model_name_options = [
|
|
6
6
|
"claude-3.5-haiku",
|
|
7
7
|
"deepseek-v3",
|
|
8
|
-
"
|
|
8
|
+
"devstral-medium",
|
|
9
9
|
"devstral-small",
|
|
10
|
-
"ernie-4.5-300b",
|
|
11
10
|
"gemini-2.0-flash",
|
|
12
11
|
"gemini-2.5-flash",
|
|
13
12
|
"gpt-4.1-mini", // the best
|
|
14
13
|
"gpt-4.1-nano",
|
|
15
14
|
"gpt-4o-mini",
|
|
16
15
|
"grok-3-mini",
|
|
16
|
+
"kimi-k2",
|
|
17
17
|
"llama-4-maverick",
|
|
18
|
+
"mercury-coder",
|
|
18
19
|
"mistral-medium-3",
|
|
19
20
|
"qwen3-235b-a22b",
|
|
20
21
|
];
|
|
@@ -8,7 +8,7 @@ import { git_message_validate_check, git_message_validate_get_result } from "./l
|
|
|
8
8
|
import { git_simple_open_check_not_bare, git_simple_open_git_repo } from "./lib_git_simple_open.js";
|
|
9
9
|
import { git_simple_staging_create_commit, git_simple_staging_get_staged_diff, git_simple_staging_get_staged_diffstat, git_simple_staging_has_staged_changes, git_simple_staging_has_unstaged_changes, git_simple_staging_push_to_remote, git_simple_staging_stage_all_changes, } from "./lib_git_simple_staging.js";
|
|
10
10
|
import { llm_config_get_model_via } from "./lib_llm_config.js";
|
|
11
|
-
import { stdio_write_stdout_linefeed } from "./lib_stdio_write.js";
|
|
11
|
+
import { stdio_write_stdout, stdio_write_stdout_linefeed } from "./lib_stdio_write.js";
|
|
12
12
|
import { tell_action, tell_info, tell_plain, tell_success, tell_warning } from "./lib_tell.js";
|
|
13
13
|
import { tui_justify_left } from "./lib_tui_justify.js";
|
|
14
14
|
import { tui_readline_confirm } from "./lib_tui_readline.js";
|
|
@@ -115,10 +115,10 @@ async function phase_compare({ config, git }) {
|
|
|
115
115
|
git_message_display({ git_message, teller });
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
-
async function
|
|
119
|
-
const { add_prefix, add_suffix,
|
|
118
|
+
async function phase_generate({ config, git }) {
|
|
119
|
+
const { disable_preview, add_prefix, add_suffix, llm_config, just_output, silent } = config;
|
|
120
120
|
const model_via = llm_config_get_model_via(llm_config);
|
|
121
|
-
if (!silent) {
|
|
121
|
+
if (!silent && !just_output) {
|
|
122
122
|
tell_action(`Generating the Git commit message using ${model_via}`);
|
|
123
123
|
}
|
|
124
124
|
const diffstat = await git_simple_staging_get_staged_diffstat(git);
|
|
@@ -127,18 +127,22 @@ async function phase_commit({ config, git }) {
|
|
|
127
127
|
const result = await git_message_generate_result({ llm_config, inputs });
|
|
128
128
|
const { error_text } = result;
|
|
129
129
|
let { git_message } = result;
|
|
130
|
-
if (error_text) {
|
|
130
|
+
if (error_text || git_message === null) {
|
|
131
131
|
abort_with_error(`Failed to generate a commit message using ${model_via}: ${error_text}`);
|
|
132
132
|
}
|
|
133
|
-
if (!git_message) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
133
|
git_message_validate_check(git_message);
|
|
137
134
|
git_message = diffdash_add_prefix_or_suffix({ git_message, add_prefix, add_suffix });
|
|
138
135
|
git_message = diffdash_add_footer({ git_message, llm_config });
|
|
139
|
-
if (
|
|
136
|
+
if (just_output) {
|
|
137
|
+
stdio_write_stdout(git_message);
|
|
138
|
+
}
|
|
139
|
+
else if (!disable_preview && !silent) {
|
|
140
140
|
git_message_display({ git_message, teller: tell_plain });
|
|
141
141
|
}
|
|
142
|
+
return git_message;
|
|
143
|
+
}
|
|
144
|
+
async function phase_commit({ config, git, git_message, }) {
|
|
145
|
+
const { auto_commit, disable_commit, silent } = config;
|
|
142
146
|
if (disable_commit) {
|
|
143
147
|
return;
|
|
144
148
|
}
|
|
@@ -188,9 +192,14 @@ export async function diffdash_sequence_normal(config) {
|
|
|
188
192
|
const git = await phase_open();
|
|
189
193
|
await phase_add({ config, git });
|
|
190
194
|
await phase_status({ config, git });
|
|
191
|
-
await
|
|
195
|
+
const git_message = await phase_generate({ config, git });
|
|
196
|
+
await phase_commit({ config, git, git_message });
|
|
192
197
|
await phase_push({ config, git });
|
|
193
198
|
}
|
|
199
|
+
export async function diffdash_sequence_output(config) {
|
|
200
|
+
const git = await phase_open();
|
|
201
|
+
await phase_generate({ config, git });
|
|
202
|
+
}
|
|
194
203
|
export async function diffdash_sequence_compare(config) {
|
|
195
204
|
const git = await phase_open();
|
|
196
205
|
await phase_add({ config, git });
|
package/dist/src/lib_error.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { abort_with_error } from "./lib_abort.js";
|
|
2
|
+
import { LF } from "./lib_char_control.js";
|
|
2
3
|
export function error_ignore(_error) {
|
|
3
4
|
/* intentionally left empty */
|
|
4
5
|
}
|
|
@@ -8,7 +9,15 @@ export function error_console(error) {
|
|
|
8
9
|
export function error_get_text(error) {
|
|
9
10
|
return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
10
11
|
}
|
|
12
|
+
export function error_get_message(error) {
|
|
13
|
+
const message_perhaps_multiline = error instanceof Error
|
|
14
|
+
? error.name === "Error"
|
|
15
|
+
? error.message
|
|
16
|
+
: `${error.name}: ${error.message}`
|
|
17
|
+
: String(error);
|
|
18
|
+
return message_perhaps_multiline.split(LF)[0] || "Blank Error";
|
|
19
|
+
}
|
|
11
20
|
export function error_abort(error) {
|
|
12
|
-
const
|
|
13
|
-
abort_with_error(
|
|
21
|
+
const message_perhaps_multiline = `Unhandled error: ${error_get_text(error)}`;
|
|
22
|
+
abort_with_error(message_perhaps_multiline);
|
|
14
23
|
}
|
|
@@ -18,13 +18,13 @@ export function llm_access_available({ llm_model_details, llm_model_name, llm_ex
|
|
|
18
18
|
return true;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
if (
|
|
22
|
-
if (llm_provider_get_api_key("
|
|
21
|
+
if (llm_model_code_openrouter !== null) {
|
|
22
|
+
if (llm_provider_get_api_key("openrouter")) {
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
if (
|
|
27
|
-
if (llm_provider_get_api_key("
|
|
26
|
+
if (llm_model_code_requesty !== null) {
|
|
27
|
+
if (llm_provider_get_api_key("requesty")) {
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -41,29 +41,29 @@ export function llm_access_get({ llm_model_details, llm_model_name, llm_router,
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
if (llm_model_code_requesty !== null) {
|
|
45
|
-
const llm_api_key = llm_provider_get_api_key("requesty");
|
|
46
|
-
if (llm_api_key) {
|
|
47
|
-
return { llm_model_code: llm_model_code_requesty, llm_provider: "requesty", llm_api_key };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
44
|
if (llm_model_code_openrouter !== null) {
|
|
51
45
|
const llm_api_key = llm_provider_get_api_key("openrouter");
|
|
52
46
|
if (llm_api_key) {
|
|
53
47
|
return { llm_model_code: llm_model_code_openrouter, llm_provider: "openrouter", llm_api_key };
|
|
54
48
|
}
|
|
55
49
|
}
|
|
50
|
+
if (llm_model_code_requesty !== null) {
|
|
51
|
+
const llm_api_key = llm_provider_get_api_key("requesty");
|
|
52
|
+
if (llm_api_key) {
|
|
53
|
+
return { llm_model_code: llm_model_code_requesty, llm_provider: "requesty", llm_api_key };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
56
|
if (llm_model_code_direct !== null && llm_provider !== null) {
|
|
57
57
|
const llm_api_key = llm_provider_get_api_key(llm_provider);
|
|
58
58
|
if (llm_api_key) {
|
|
59
59
|
return { llm_model_code: llm_model_code_direct, llm_provider, llm_api_key };
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
const env_requesty = llm_provider_get_api_key_env("requesty");
|
|
63
62
|
const env_openrouter = llm_provider_get_api_key_env("openrouter");
|
|
63
|
+
const env_requesty = llm_provider_get_api_key_env("requesty");
|
|
64
64
|
if (llm_provider !== null) {
|
|
65
65
|
const env_provider = llm_provider_get_api_key_env(llm_provider);
|
|
66
|
-
abort_with_error(`Please set environment variable ${
|
|
66
|
+
abort_with_error(`Please set environment variable ${env_provider}, ${env_openrouter} or ${env_requesty}`);
|
|
67
67
|
}
|
|
68
|
-
abort_with_error(`Please set environment variable ${
|
|
68
|
+
abort_with_error(`Please set environment variable ${env_openrouter} or ${env_requesty}`);
|
|
69
69
|
}
|
|
@@ -66,15 +66,26 @@ const LLM_MODEL_DETAILS = [
|
|
|
66
66
|
cents_output: 219,
|
|
67
67
|
has_structured_json: true,
|
|
68
68
|
},
|
|
69
|
+
{
|
|
70
|
+
llm_model_name: "devstral-medium",
|
|
71
|
+
llm_provider: null,
|
|
72
|
+
llm_model_code_direct: "devstral-medium-latest",
|
|
73
|
+
llm_model_code_requesty: "mistral/devstral-medium-latest",
|
|
74
|
+
llm_model_code_openrouter: "mistralai/devstral-medium",
|
|
75
|
+
context_window: 128_000,
|
|
76
|
+
cents_input: 40,
|
|
77
|
+
cents_output: 200,
|
|
78
|
+
has_structured_json: true,
|
|
79
|
+
},
|
|
69
80
|
{
|
|
70
81
|
llm_model_name: "devstral-small",
|
|
71
82
|
llm_provider: null,
|
|
72
|
-
llm_model_code_direct:
|
|
83
|
+
llm_model_code_direct: "devstral-small-latest",
|
|
73
84
|
llm_model_code_requesty: "mistral/devstral-small-latest",
|
|
74
85
|
llm_model_code_openrouter: "mistralai/devstral-small",
|
|
75
86
|
context_window: 128_000,
|
|
76
|
-
cents_input:
|
|
77
|
-
cents_output:
|
|
87
|
+
cents_input: 10,
|
|
88
|
+
cents_output: 30,
|
|
78
89
|
has_structured_json: true,
|
|
79
90
|
},
|
|
80
91
|
{
|
|
@@ -192,7 +203,7 @@ const LLM_MODEL_DETAILS = [
|
|
|
192
203
|
llm_provider: null,
|
|
193
204
|
llm_model_code_direct: "grok-3",
|
|
194
205
|
llm_model_code_requesty: "xai/grok-3-beta",
|
|
195
|
-
llm_model_code_openrouter: "x-ai/grok-3
|
|
206
|
+
llm_model_code_openrouter: "x-ai/grok-3",
|
|
196
207
|
context_window: 131_072,
|
|
197
208
|
cents_input: 300,
|
|
198
209
|
cents_output: 1500,
|
|
@@ -203,12 +214,34 @@ const LLM_MODEL_DETAILS = [
|
|
|
203
214
|
llm_provider: null,
|
|
204
215
|
llm_model_code_direct: "grok-3-mini",
|
|
205
216
|
llm_model_code_requesty: "xai/grok-3-mini-beta",
|
|
206
|
-
llm_model_code_openrouter: "x-ai/grok-3-mini
|
|
217
|
+
llm_model_code_openrouter: "x-ai/grok-3-mini",
|
|
207
218
|
context_window: 131_072,
|
|
208
219
|
cents_input: 30,
|
|
209
220
|
cents_output: 50,
|
|
210
221
|
has_structured_json: true,
|
|
211
222
|
},
|
|
223
|
+
{
|
|
224
|
+
llm_model_name: "grok-4",
|
|
225
|
+
llm_provider: null,
|
|
226
|
+
llm_model_code_direct: "grok-4",
|
|
227
|
+
llm_model_code_requesty: "xai/grok-4",
|
|
228
|
+
llm_model_code_openrouter: "x-ai/grok-4",
|
|
229
|
+
context_window: 256_000,
|
|
230
|
+
cents_input: 300,
|
|
231
|
+
cents_output: 1500,
|
|
232
|
+
has_structured_json: true,
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
llm_model_name: "kimi-k2",
|
|
236
|
+
llm_provider: null,
|
|
237
|
+
llm_model_code_direct: "kimi-k2-0711-preview",
|
|
238
|
+
llm_model_code_requesty: null /* "novita/moonshotai/kimi-k2-instruct" */,
|
|
239
|
+
llm_model_code_openrouter: "moonshotai/kimi-k2",
|
|
240
|
+
context_window: 131_072,
|
|
241
|
+
cents_input: 60,
|
|
242
|
+
cents_output: 250,
|
|
243
|
+
has_structured_json: true,
|
|
244
|
+
},
|
|
212
245
|
{
|
|
213
246
|
llm_model_name: "llama-4-maverick",
|
|
214
247
|
llm_provider: null,
|
|
@@ -216,8 +249,8 @@ const LLM_MODEL_DETAILS = [
|
|
|
216
249
|
llm_model_code_requesty: "parasail/meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8",
|
|
217
250
|
llm_model_code_openrouter: "meta-llama/llama-4-maverick",
|
|
218
251
|
context_window: 1_048_576,
|
|
219
|
-
cents_input:
|
|
220
|
-
cents_output:
|
|
252
|
+
cents_input: 15,
|
|
253
|
+
cents_output: 60,
|
|
221
254
|
has_structured_json: true,
|
|
222
255
|
},
|
|
223
256
|
{
|
|
@@ -232,7 +265,18 @@ const LLM_MODEL_DETAILS = [
|
|
|
232
265
|
has_structured_json: true,
|
|
233
266
|
},
|
|
234
267
|
{
|
|
235
|
-
llm_model_name: "mercury
|
|
268
|
+
llm_model_name: "mercury",
|
|
269
|
+
llm_provider: null,
|
|
270
|
+
llm_model_code_direct: null,
|
|
271
|
+
llm_model_code_requesty: null,
|
|
272
|
+
llm_model_code_openrouter: "inception/mercury",
|
|
273
|
+
context_window: 32_000,
|
|
274
|
+
cents_input: 25,
|
|
275
|
+
cents_output: 100,
|
|
276
|
+
has_structured_json: false,
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
llm_model_name: "mercury-coder",
|
|
236
280
|
llm_provider: null,
|
|
237
281
|
llm_model_code_direct: null,
|
|
238
282
|
llm_model_code_requesty: null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnowennixon/diffdash",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A command-line tool to generate Git commit messages using AI",
|
|
5
5
|
"license": "0BSD",
|
|
6
6
|
"author": "John Owen Nixon",
|
|
@@ -20,30 +20,30 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@ai-sdk/anthropic": "1.2.12",
|
|
23
|
-
"@ai-sdk/deepseek": "0.2.
|
|
24
|
-
"@ai-sdk/google": "1.2.
|
|
25
|
-
"@ai-sdk/openai": "1.3.
|
|
23
|
+
"@ai-sdk/deepseek": "0.2.16",
|
|
24
|
+
"@ai-sdk/google": "1.2.22",
|
|
25
|
+
"@ai-sdk/openai": "1.3.23",
|
|
26
26
|
"@openrouter/ai-sdk-provider": "0.7.2",
|
|
27
27
|
"@requesty/ai-sdk": "0.0.9",
|
|
28
|
-
"ai": "4.3.
|
|
28
|
+
"ai": "4.3.19",
|
|
29
29
|
"ansis": "4.1.0",
|
|
30
30
|
"argparse": "2.0.1",
|
|
31
31
|
"cli-table3": "0.6.5",
|
|
32
32
|
"simple-git": "3.28.0",
|
|
33
|
-
"zod": "3.25.
|
|
33
|
+
"zod": "3.25.76"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@biomejs/biome": "2.
|
|
36
|
+
"@biomejs/biome": "2.1.1",
|
|
37
37
|
"@eslint/eslintrc": "3.3.1",
|
|
38
|
-
"@eslint/js": "9.
|
|
38
|
+
"@eslint/js": "9.31.0",
|
|
39
39
|
"@johnowennixon/add-shebangs": "1.1.0",
|
|
40
40
|
"@johnowennixon/chmodx": "2.0.0",
|
|
41
|
-
"@stylistic/eslint-plugin": "5.
|
|
41
|
+
"@stylistic/eslint-plugin": "5.2.0",
|
|
42
42
|
"@types/argparse": "2.0.17",
|
|
43
|
-
"@types/node": "24.0.
|
|
44
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
45
|
-
"@typescript-eslint/parser": "8.
|
|
46
|
-
"eslint": "9.
|
|
43
|
+
"@types/node": "24.0.14",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "8.37.0",
|
|
45
|
+
"@typescript-eslint/parser": "8.37.0",
|
|
46
|
+
"eslint": "9.31.0",
|
|
47
47
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
48
48
|
"eslint-plugin-import-x": "4.16.1",
|
|
49
49
|
"eslint-plugin-sonarjs": "3.0.4",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"knip": "5.61.3",
|
|
53
53
|
"markdownlint-cli2": "0.18.1",
|
|
54
54
|
"npm-run-all2": "8.0.4",
|
|
55
|
-
"oxlint": "1.
|
|
55
|
+
"oxlint": "1.7.0",
|
|
56
56
|
"rimraf": "6.0.1",
|
|
57
57
|
"typescript": "5.8.3",
|
|
58
|
-
"typescript-eslint": "8.
|
|
58
|
+
"typescript-eslint": "8.37.0"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "run-s -ls build:clean build:tsc build:shebang build:chmod",
|