diff --git a/config/codex/config.toml b/config/codex/config.toml index 6e24acf1c..ddf654370 100644 --- a/config/codex/config.toml +++ b/config/codex/config.toml @@ -9,6 +9,7 @@ suppress_unstable_features_warning = true web_search = "cached" model = "gpt-5.3-codex" model_reasoning_effort = "xhigh" +oss_provider = "lmstudio" [features] ghost_commit = false @@ -50,14 +51,7 @@ name = "OpenRouter" base_url = "https://openrouter.ai/api/v1" env_key = "OPENROUTER_API_KEY" -[profiles.gpt-oss-20b] -model = "gpt-oss:20b" -model_provider = "ollama" - -[profiles.gpt-oss-120b] -model = "openai/gpt-oss-120b" -model_provider = "lmstudio" - -[profiles.glm-4-7-flash] -model = "zai-org/glm-4.7-flash" +[profiles.qwen-local] +model = "qwen/qwen3.5-9b" model_provider = "lmstudio" +model_reasoning_effort = "minimal" diff --git a/config/codex/config.tpl.toml b/config/codex/config.tpl.toml index e026b13cf..e8ac75d3d 100644 --- a/config/codex/config.tpl.toml +++ b/config/codex/config.tpl.toml @@ -9,6 +9,7 @@ suppress_unstable_features_warning = true web_search = "cached" model = "__GPT_CODEX__" model_reasoning_effort = "xhigh" +oss_provider = "lmstudio" [features] ghost_commit = false @@ -50,14 +51,7 @@ name = "OpenRouter" base_url = "https://openrouter.ai/api/v1" env_key = "OPENROUTER_API_KEY" -[profiles.gpt-oss-20b] -model = "gpt-oss:20b" -model_provider = "ollama" - -[profiles.gpt-oss-120b] -model = "openai/gpt-oss-120b" -model_provider = "lmstudio" - -[profiles.glm-4-7-flash] -model = "zai-org/glm-4.7-flash" +[profiles.qwen-local] +model = "__QWEN_LOCAL__" model_provider = "lmstudio" +model_reasoning_effort = "minimal" diff --git a/config/opencode/opencode.jsonc b/config/opencode/opencode.jsonc index f27febcb6..c6fa6060e 100644 --- a/config/opencode/opencode.jsonc +++ b/config/opencode/opencode.jsonc @@ -94,14 +94,8 @@ "baseURL": "http://127.0.0.1:1234/v1" }, "models": { - "openai/gpt-oss-20b": { - "name": "OpenAI: gpt-oss-20b" - }, - "openai/gpt-oss-120b": { - "name": "OpenAI: gpt-oss-120b" - }, - "zai-org/glm-4.7-flash": { - "name": "GLM-4.7 Flash (via LM Studio)" + "qwen/qwen3.5-9b": { + "name": "Qwen 3.5 9B (via LM Studio)" } } }, @@ -111,11 +105,7 @@ "options": { "baseURL": "http://localhost:11434/v1" }, - "models": { - "openai/gpt-oss-20b": { - "name": "OpenAI: gpt-oss-20b" - } - } + "models": {} }, "openai": { "options": { diff --git a/config/opencode/opencode.tpl.jsonc b/config/opencode/opencode.tpl.jsonc index d8133ad0e..ade38e8e1 100644 --- a/config/opencode/opencode.tpl.jsonc +++ b/config/opencode/opencode.tpl.jsonc @@ -94,14 +94,8 @@ "baseURL": "http://127.0.0.1:1234/v1" }, "models": { - "openai/gpt-oss-20b": { - "name": "OpenAI: gpt-oss-20b" - }, - "openai/gpt-oss-120b": { - "name": "OpenAI: gpt-oss-120b" - }, - "zai-org/glm-4.7-flash": { - "name": "GLM-4.7 Flash (via LM Studio)" + "__QWEN_LOCAL__": { + "name": "Qwen 3.5 9B (via LM Studio)" } } }, @@ -111,11 +105,7 @@ "options": { "baseURL": "http://localhost:11434/v1" }, - "models": { - "openai/gpt-oss-20b": { - "name": "OpenAI: gpt-oss-20b" - } - } + "models": {} }, "openai": { "options": { diff --git a/home-manager/programs/fish/default.nix b/home-manager/programs/fish/default.nix index 2953d78f2..b90e21348 100644 --- a/home-manager/programs/fish/default.nix +++ b/home-manager/programs/fish/default.nix @@ -115,7 +115,9 @@ kyberd = "_kyberd_function"; kyberm = "_kyberm_function"; ocxe = "_ocxe_function"; + ocxel = "_ocxel_function"; ocxeh = "_ocxeh_function"; + ocxelh = "_ocxelh_function"; pixe = "_pixe_function"; pixeh = "_pixeh_function"; sag = "_ssh_add_github"; @@ -209,7 +211,9 @@ "_kyberd_function" "_kyberm_function" "_ocxe_function" + "_ocxel_function" "_ocxeh_function" + "_ocxelh_function" "_pixe_function" "_pixeh_function" "_ssh_add_github" diff --git a/home-manager/programs/fish/functions/_coxel_function.fish b/home-manager/programs/fish/functions/_coxel_function.fish index 1ce8b8fb0..31b5ee90b 100644 --- a/home-manager/programs/fish/functions/_coxel_function.fish +++ b/home-manager/programs/fish/functions/_coxel_function.fish @@ -1,11 +1,11 @@ -function _coxel_function --description "Run Codex with a free-form prompt using the local glm-4-7-flash model" - # Run Codex with a free-form prompt (spaces allowed) using the local glm-4-7-flash model +function _coxel_function --description "Run Codex with a free-form prompt using the local Qwen model" + # Run Codex with a free-form prompt (spaces allowed) using the local Qwen model # Usage: cxel [] if test (count $argv) -eq 0 - codex --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental + codex --oss --local-provider lmstudio --model 'qwen/qwen3.5-9b' --full-auto -c model_reasoning_effort=minimal else set -l prompt (string join " " -- $argv) - codex exec --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt" + codex exec --oss --local-provider lmstudio --model 'qwen/qwen3.5-9b' --full-auto -c model_reasoning_effort=minimal -- "$prompt" end end diff --git a/home-manager/programs/fish/functions/_coxel_function.tpl.fish b/home-manager/programs/fish/functions/_coxel_function.tpl.fish new file mode 100644 index 000000000..4bf71affe --- /dev/null +++ b/home-manager/programs/fish/functions/_coxel_function.tpl.fish @@ -0,0 +1,11 @@ +function _coxel_function --description "Run Codex with a free-form prompt using the local Qwen model" + # Run Codex with a free-form prompt (spaces allowed) using the local Qwen model + # Usage: cxel [] + + if test (count $argv) -eq 0 + codex --oss --local-provider lmstudio --model '__QWEN_LOCAL__' --full-auto -c model_reasoning_effort=minimal + else + set -l prompt (string join " " -- $argv) + codex exec --oss --local-provider lmstudio --model '__QWEN_LOCAL__' --full-auto -c model_reasoning_effort=minimal -- "$prompt" + end +end diff --git a/home-manager/programs/fish/functions/_coxelh_function.fish b/home-manager/programs/fish/functions/_coxelh_function.fish index 4ed09bd1f..bb4c0b1c2 100644 --- a/home-manager/programs/fish/functions/_coxelh_function.fish +++ b/home-manager/programs/fish/functions/_coxelh_function.fish @@ -1,5 +1,5 @@ -function _coxelh_function --description "Run Codex headlessly with local glm-4-7-flash model" - # Prompt for input and run Codex with local model +function _coxelh_function --description "Run Codex headlessly with the local Qwen model" + # Prompt for input and run Codex with the local Qwen model # Usage: coxelh read -P "Prompt: " prompt @@ -8,5 +8,5 @@ function _coxelh_function --description "Run Codex headlessly with local glm-4-7 return 1 end - codex exec --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt" + codex exec --oss --local-provider lmstudio --model 'qwen/qwen3.5-9b' --full-auto -c model_reasoning_effort=minimal -- "$prompt" end diff --git a/home-manager/programs/fish/functions/_coxelh_function.tpl.fish b/home-manager/programs/fish/functions/_coxelh_function.tpl.fish new file mode 100644 index 000000000..a4363bf1f --- /dev/null +++ b/home-manager/programs/fish/functions/_coxelh_function.tpl.fish @@ -0,0 +1,12 @@ +function _coxelh_function --description "Run Codex headlessly with the local Qwen model" + # Prompt for input and run Codex with the local Qwen model + # Usage: coxelh + + read -P "Prompt: " prompt + if test -z "$prompt" + echo "No prompt provided, aborting." >&2 + return 1 + end + + codex exec --oss --local-provider lmstudio --model '__QWEN_LOCAL__' --full-auto -c model_reasoning_effort=minimal -- "$prompt" +end diff --git a/home-manager/programs/fish/functions/_ocxel_function.fish b/home-manager/programs/fish/functions/_ocxel_function.fish new file mode 100644 index 000000000..31138b2ab --- /dev/null +++ b/home-manager/programs/fish/functions/_ocxel_function.fish @@ -0,0 +1,11 @@ +function _ocxel_function --description "Run OpenCode with a free-form prompt using the local Qwen model" + # Run OpenCode with a free-form prompt (spaces allowed) using the local Qwen model + # Usage: ocxel [] + + if test (count $argv) -eq 0 + opencode -m 'lmstudio/qwen/qwen3.5-9b' + else + set -l prompt (string join " " -- $argv) + opencode run "$prompt" -m 'lmstudio/qwen/qwen3.5-9b' + end +end diff --git a/home-manager/programs/fish/functions/_ocxel_function.tpl.fish b/home-manager/programs/fish/functions/_ocxel_function.tpl.fish new file mode 100644 index 000000000..dc8f44cbd --- /dev/null +++ b/home-manager/programs/fish/functions/_ocxel_function.tpl.fish @@ -0,0 +1,11 @@ +function _ocxel_function --description "Run OpenCode with a free-form prompt using the local Qwen model" + # Run OpenCode with a free-form prompt (spaces allowed) using the local Qwen model + # Usage: ocxel [] + + if test (count $argv) -eq 0 + opencode -m 'lmstudio/__QWEN_LOCAL__' + else + set -l prompt (string join " " -- $argv) + opencode run "$prompt" -m 'lmstudio/__QWEN_LOCAL__' + end +end diff --git a/home-manager/programs/fish/functions/_ocxelh_function.fish b/home-manager/programs/fish/functions/_ocxelh_function.fish new file mode 100644 index 000000000..a095869b6 --- /dev/null +++ b/home-manager/programs/fish/functions/_ocxelh_function.fish @@ -0,0 +1,12 @@ +function _ocxelh_function --description "Run OpenCode headlessly with the local Qwen model" + # Prompt for input and run OpenCode with the local Qwen model + # Usage: ocxelh + + read -P "Prompt: " prompt + if test -z "$prompt" + echo "No prompt provided, aborting." >&2 + return 1 + end + + opencode run "$prompt" -m 'lmstudio/qwen/qwen3.5-9b' +end diff --git a/home-manager/programs/fish/functions/_ocxelh_function.tpl.fish b/home-manager/programs/fish/functions/_ocxelh_function.tpl.fish new file mode 100644 index 000000000..fc1e56bfc --- /dev/null +++ b/home-manager/programs/fish/functions/_ocxelh_function.tpl.fish @@ -0,0 +1,12 @@ +function _ocxelh_function --description "Run OpenCode headlessly with the local Qwen model" + # Prompt for input and run OpenCode with the local Qwen model + # Usage: ocxelh + + read -P "Prompt: " prompt + if test -z "$prompt" + echo "No prompt provided, aborting." >&2 + return 1 + end + + opencode run "$prompt" -m 'lmstudio/__QWEN_LOCAL__' +end diff --git a/models.json b/models.json index 75fb04431..ef317bbe8 100644 --- a/models.json +++ b/models.json @@ -7,5 +7,6 @@ "gemini-pro": "gemini-3.1-pro-preview", "gemini-flash": "gemini-3.1-flash-preview", "glm": "glm-4.7", - "minimax": "minimax-m2.5" + "minimax": "minimax-m2.5", + "qwen-local": "qwen/qwen3.5-9b" } diff --git a/scripts/llm-update.sh b/scripts/llm-update.sh index 170fad5d2..684400b78 100755 --- a/scripts/llm-update.sh +++ b/scripts/llm-update.sh @@ -60,8 +60,12 @@ declare -A TEMPLATES=( ["config/pi/settings.tpl.json"]=config/pi/settings.json ["home-manager/programs/fish/functions/_coxe_function.tpl.fish"]=home-manager/programs/fish/functions/_coxe_function.fish ["home-manager/programs/fish/functions/_coxeh_function.tpl.fish"]=home-manager/programs/fish/functions/_coxeh_function.fish + ["home-manager/programs/fish/functions/_coxel_function.tpl.fish"]=home-manager/programs/fish/functions/_coxel_function.fish + ["home-manager/programs/fish/functions/_coxelh_function.tpl.fish"]=home-manager/programs/fish/functions/_coxelh_function.fish ["home-manager/programs/fish/functions/_ocxe_function.tpl.fish"]=home-manager/programs/fish/functions/_ocxe_function.fish + ["home-manager/programs/fish/functions/_ocxel_function.tpl.fish"]=home-manager/programs/fish/functions/_ocxel_function.fish ["home-manager/programs/fish/functions/_ocxeh_function.tpl.fish"]=home-manager/programs/fish/functions/_ocxeh_function.fish + ["home-manager/programs/fish/functions/_ocxelh_function.tpl.fish"]=home-manager/programs/fish/functions/_ocxelh_function.fish ["home-manager/programs/fish/functions/_pixe_function.tpl.fish"]=home-manager/programs/fish/functions/_pixe_function.fish ["home-manager/programs/fish/functions/_pixeh_function.tpl.fish"]=home-manager/programs/fish/functions/_pixeh_function.fish ) diff --git a/spec/fish/_coxel_function.tpl_test.fish b/spec/fish/_coxel_function.tpl_test.fish new file mode 100644 index 000000000..08629868a --- /dev/null +++ b/spec/fish/_coxel_function.tpl_test.fish @@ -0,0 +1,28 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_coxel_function.tpl.fish + +# ── no args: interactive mode ───────────────────────────── +set log1 (mktemp) +function codex; echo $argv >> $log1; end + +_coxel_function + +@test "no args uses QWEN_LOCAL placeholder" (grep -c "__QWEN_LOCAL__" $log1) -ge 1 +@test "no args enables oss mode" (grep -c -- "--oss" $log1) -ge 1 +@test "no args uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log1) -ge 1 +@test "no args lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log1) -ge 1 + +# ── with args: exec mode ────────────────────────────────── +set log2 (mktemp) +function codex; echo $argv >> $log2; end + +_coxel_function hello world + +@test "with args uses exec subcommand" (grep -c "^exec " $log2) -ge 1 +@test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses QWEN_LOCAL placeholder" (grep -c "__QWEN_LOCAL__" $log2) -ge 1 +@test "with args enables oss mode" (grep -c -- "--oss" $log2) -ge 1 +@test "with args uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log2) -ge 1 +@test "with args lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log2) -ge 1 + +rm -f $log1 $log2 diff --git a/spec/fish/_coxel_function_test.fish b/spec/fish/_coxel_function_test.fish index 3bfaa647a..264425950 100644 --- a/spec/fish/_coxel_function_test.fish +++ b/spec/fish/_coxel_function_test.fish @@ -7,7 +7,10 @@ function codex; echo $argv >> $log1; end _coxel_function -@test "no args calls codex with local profile" (grep -c "glm-4-7-flash" $log1) -ge 1 +@test "no args uses substituted Qwen model" (grep -c "qwen/qwen3.5-9b" $log1) -ge 1 +@test "no args enables oss mode" (grep -c -- "--oss" $log1) -ge 1 +@test "no args uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log1) -ge 1 +@test "no args lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log1) -ge 1 # ── with args: exec mode ────────────────────────────────── set log2 (mktemp) @@ -17,5 +20,9 @@ _coxel_function hello world @test "with args uses exec subcommand" (grep -c "^exec " $log2) -ge 1 @test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses substituted Qwen model" (grep -c "qwen/qwen3.5-9b" $log2) -ge 1 +@test "with args enables oss mode" (grep -c -- "--oss" $log2) -ge 1 +@test "with args uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log2) -ge 1 +@test "with args lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log2) -ge 1 rm -f $log1 $log2 diff --git a/spec/fish/_coxelh_function.tpl_test.fish b/spec/fish/_coxelh_function.tpl_test.fish new file mode 100644 index 000000000..6284609a1 --- /dev/null +++ b/spec/fish/_coxelh_function.tpl_test.fish @@ -0,0 +1,19 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_coxelh_function.tpl.fish + +@test "empty prompt rejects" (echo "" | _coxelh_function 2>&1) = "No prompt provided, aborting." +@test "empty prompt returns 1" (echo "" | _coxelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function codex; echo $argv >> $log1; end + +echo "hello world" | _coxelh_function + +@test "non-empty prompt uses exec subcommand" (grep -c "^exec " $log1) -ge 1 +@test "non-empty prompt uses QWEN_LOCAL placeholder" (grep -c "__QWEN_LOCAL__" $log1) -ge 1 +@test "non-empty prompt enables oss mode" (grep -c -- "--oss" $log1) -ge 1 +@test "non-empty prompt uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log1) -ge 1 +@test "non-empty prompt lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log1) -ge 1 +@test "non-empty prompt forwards prompt" (grep -c "hello world" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_coxelh_function_test.fish b/spec/fish/_coxelh_function_test.fish index d4cc2ce5e..ba7e0a05e 100644 --- a/spec/fish/_coxelh_function_test.fish +++ b/spec/fish/_coxelh_function_test.fish @@ -3,3 +3,17 @@ source $fn/_coxelh_function.fish @test "empty prompt rejects" (echo "" | _coxelh_function 2>&1) = "No prompt provided, aborting." @test "empty prompt returns 1" (echo "" | _coxelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function codex; echo $argv >> $log1; end + +echo "hello world" | _coxelh_function + +@test "non-empty prompt uses exec subcommand" (grep -c "^exec " $log1) -ge 1 +@test "non-empty prompt uses substituted Qwen model" (grep -c "qwen/qwen3.5-9b" $log1) -ge 1 +@test "non-empty prompt enables oss mode" (grep -c -- "--oss" $log1) -ge 1 +@test "non-empty prompt uses lmstudio local provider" (grep -c -- "local-provider lmstudio" $log1) -ge 1 +@test "non-empty prompt lowers reasoning effort" (grep -c "model_reasoning_effort=minimal" $log1) -ge 1 +@test "non-empty prompt forwards prompt" (grep -c "hello world" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_ocxel_function.tpl_test.fish b/spec/fish/_ocxel_function.tpl_test.fish new file mode 100644 index 000000000..e4075c885 --- /dev/null +++ b/spec/fish/_ocxel_function.tpl_test.fish @@ -0,0 +1,23 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_ocxel_function.tpl.fish + +# ── no args: interactive mode ───────────────────────────── +set log1 (mktemp) +function opencode; echo $argv >> $log1; end + +_ocxel_function + +@test "no args calls opencode with templated local Qwen model" (grep -c "lmstudio/__QWEN_LOCAL__" $log1) -ge 1 +@test "no args skips run subcommand" (grep -c "^run " $log1) -eq 0 + +# ── with args: run mode ────────────────────────────────── +set log2 (mktemp) +function opencode; echo $argv >> $log2; end + +_ocxel_function hello world + +@test "with args uses run subcommand" (grep -c "^run " $log2) -ge 1 +@test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses templated local Qwen model" (grep -c "lmstudio/__QWEN_LOCAL__" $log2) -ge 1 + +rm -f $log1 $log2 diff --git a/spec/fish/_ocxel_function_test.fish b/spec/fish/_ocxel_function_test.fish new file mode 100644 index 000000000..3a4bf28d9 --- /dev/null +++ b/spec/fish/_ocxel_function_test.fish @@ -0,0 +1,23 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_ocxel_function.fish + +# ── no args: interactive mode ───────────────────────────── +set log1 (mktemp) +function opencode; echo $argv >> $log1; end + +_ocxel_function + +@test "no args calls opencode with local Qwen model" (grep -c "lmstudio/qwen/qwen3.5-9b" $log1) -ge 1 +@test "no args skips run subcommand" (grep -c "^run " $log1) -eq 0 + +# ── with args: run mode ────────────────────────────────── +set log2 (mktemp) +function opencode; echo $argv >> $log2; end + +_ocxel_function hello world + +@test "with args uses run subcommand" (grep -c "^run " $log2) -ge 1 +@test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses local Qwen model" (grep -c "lmstudio/qwen/qwen3.5-9b" $log2) -ge 1 + +rm -f $log1 $log2 diff --git a/spec/fish/_ocxelh_function.tpl_test.fish b/spec/fish/_ocxelh_function.tpl_test.fish new file mode 100644 index 000000000..6ea2c0374 --- /dev/null +++ b/spec/fish/_ocxelh_function.tpl_test.fish @@ -0,0 +1,16 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_ocxelh_function.tpl.fish + +@test "empty prompt rejects" (echo "" | _ocxelh_function 2>&1) = "No prompt provided, aborting." +@test "empty prompt returns 1" (echo "" | _ocxelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function opencode; echo $argv >> $log1; end + +echo "hello world" | _ocxelh_function + +@test "non-empty prompt uses run subcommand" (grep -c "^run " $log1) -ge 1 +@test "non-empty prompt builds prompt" (grep -c "hello world" $log1) -ge 1 +@test "non-empty prompt uses templated local Qwen model" (grep -c "lmstudio/__QWEN_LOCAL__" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_ocxelh_function_test.fish b/spec/fish/_ocxelh_function_test.fish new file mode 100644 index 000000000..b41912c5e --- /dev/null +++ b/spec/fish/_ocxelh_function_test.fish @@ -0,0 +1,16 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_ocxelh_function.fish + +@test "empty prompt rejects" (echo "" | _ocxelh_function 2>&1) = "No prompt provided, aborting." +@test "empty prompt returns 1" (echo "" | _ocxelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function opencode; echo $argv >> $log1; end + +echo "hello world" | _ocxelh_function + +@test "non-empty prompt uses run subcommand" (grep -c "^run " $log1) -ge 1 +@test "non-empty prompt builds prompt" (grep -c "hello world" $log1) -ge 1 +@test "non-empty prompt uses local Qwen model" (grep -c "lmstudio/qwen/qwen3.5-9b" $log1) -ge 1 + +rm -f $log1