diff --git a/config/opencode/opencode.tpl.jsonc b/config/opencode/opencode.tpl.jsonc index ade38e8e1..a80b14eca 100644 --- a/config/opencode/opencode.tpl.jsonc +++ b/config/opencode/opencode.tpl.jsonc @@ -182,7 +182,7 @@ }, "models": { "glm-4.7": { - "id": "@preset/glm-4-7", + "id": "@preset/__GLM_NONDOT__", "name": "Preset GLM-4.7 (via OpenRouter)" } } diff --git a/config/pi/models.json b/config/pi/models.json index 19365375c..0e1e5d3e8 100644 --- a/config/pi/models.json +++ b/config/pi/models.json @@ -1,6 +1,6 @@ { "providers": { - "cli-proxy-api": { + "cliproxyapi": { "baseUrl": "http://localhost:8317/v1", "apiKey": "CLIPROXY_API_KEY", "api": "openai-responses", @@ -181,6 +181,30 @@ "maxTokens": 16384 } ] + }, + "lmstudio": { + "baseUrl": "http://127.0.0.1:1234/v1", + "apiKey": "LM_API_TOKEN", + "api": "openai-responses", + "models": [ + { + "id": "qwen/qwen3.5-9b", + "name": "Qwen 3.5 9B (LM Studio)", + "reasoning": true, + "input": [ + "text", + "image" + ], + "cost": { + "input": 0, + "output": 0, + "cacheRead": 0, + "cacheWrite": 0 + }, + "contextWindow": 262144, + "maxTokens": 32768 + } + ] } } } diff --git a/config/pi/models.tpl.json b/config/pi/models.tpl.json index 4dcd42710..22cd999f1 100644 --- a/config/pi/models.tpl.json +++ b/config/pi/models.tpl.json @@ -1,6 +1,6 @@ { "providers": { - "cli-proxy-api": { + "cliproxyapi": { "baseUrl": "http://localhost:8317/v1", "apiKey": "CLIPROXY_API_KEY", "api": "openai-responses", @@ -165,7 +165,7 @@ "api": "openai-completions", "models": [ { - "id": "@preset/glm-4-7", + "id": "@preset/__GLM_NONDOT__", "name": "GLM-4.7 (Z-AI)", "reasoning": false, "input": [ @@ -181,6 +181,30 @@ "maxTokens": 16384 } ] + }, + "lmstudio": { + "baseUrl": "http://127.0.0.1:1234/v1", + "apiKey": "LM_API_TOKEN", + "api": "openai-responses", + "models": [ + { + "id": "__QWEN_LOCAL__", + "name": "Qwen 3.5 9B (LM Studio)", + "reasoning": true, + "input": [ + "text", + "image" + ], + "cost": { + "input": 0, + "output": 0, + "cacheRead": 0, + "cacheWrite": 0 + }, + "contextWindow": 262144, + "maxTokens": 32768 + } + ] } } } diff --git a/config/pi/settings.json b/config/pi/settings.json index 87fafd1af..f9388376c 100644 --- a/config/pi/settings.json +++ b/config/pi/settings.json @@ -1,15 +1,17 @@ { "theme": "dark", "quietStartup": true, - "defaultProvider": "cli-proxy-api", + "defaultProvider": "cliproxyapi", "defaultModel": "glm-4.7", "defaultThinkingLevel": "medium", "enabledModels": [ - "cli-proxy-api/*", + "cliproxyapi/*", + "lmstudio/*", "*gpt-5*", "*gemini*", "*claude*", "*glm*", + "*qwen*", "*kimi*" ], "steeringMode": "one-at-a-time", diff --git a/config/pi/settings.tpl.json b/config/pi/settings.tpl.json index 084f313bd..c09e3727e 100644 --- a/config/pi/settings.tpl.json +++ b/config/pi/settings.tpl.json @@ -1,15 +1,17 @@ { "theme": "dark", "quietStartup": true, - "defaultProvider": "cli-proxy-api", + "defaultProvider": "cliproxyapi", "defaultModel": "__GLM__", "defaultThinkingLevel": "medium", "enabledModels": [ - "cli-proxy-api/*", + "cliproxyapi/*", + "lmstudio/*", "*gpt-5*", "*gemini*", "*claude*", "*glm*", + "*qwen*", "*kimi*" ], "steeringMode": "one-at-a-time", diff --git a/home-manager/programs/fish/default.nix b/home-manager/programs/fish/default.nix index b90e21348..194b3b301 100644 --- a/home-manager/programs/fish/default.nix +++ b/home-manager/programs/fish/default.nix @@ -119,6 +119,8 @@ ocxeh = "_ocxeh_function"; ocxelh = "_ocxelh_function"; pixe = "_pixe_function"; + pixel = "_pixel_function"; + pixelh = "_pixelh_function"; pixeh = "_pixeh_function"; sag = "_ssh_add_github"; shortcuts = "_fish_shortcuts"; @@ -215,6 +217,8 @@ "_ocxeh_function" "_ocxelh_function" "_pixe_function" + "_pixel_function" + "_pixelh_function" "_pixeh_function" "_ssh_add_github" "_tdo_function" diff --git a/home-manager/programs/fish/functions/_pixe_function.fish b/home-manager/programs/fish/functions/_pixe_function.fish index 40b7ee11e..7255f642c 100644 --- a/home-manager/programs/fish/functions/_pixe_function.fish +++ b/home-manager/programs/fish/functions/_pixe_function.fish @@ -1,11 +1,11 @@ -function _pixe_function --description "Run Pi agent with a free-form prompt" - # Run Pi agent with a free-form prompt (spaces allowed) +function _pixe_function --description "Run Pi with a free-form prompt" + # Run Pi with a free-form prompt (spaces allowed) # Usage: pixe [] if test (count $argv) -eq 0 - pi-agent -m 'openrouter-preset/@preset/glm-4-7' + pi --model 'cliproxyapi/glm-4.7' else set -l prompt (string join " " -- $argv) - pi-agent "$prompt" -m 'openrouter-preset/@preset/glm-4-7' + pi --model 'cliproxyapi/glm-4.7' "$prompt" end end diff --git a/home-manager/programs/fish/functions/_pixe_function.tpl.fish b/home-manager/programs/fish/functions/_pixe_function.tpl.fish index 5a516482d..a56fed4d5 100644 --- a/home-manager/programs/fish/functions/_pixe_function.tpl.fish +++ b/home-manager/programs/fish/functions/_pixe_function.tpl.fish @@ -1,11 +1,11 @@ -function _pixe_function --description "Run Pi agent with a free-form prompt" - # Run Pi agent with a free-form prompt (spaces allowed) +function _pixe_function --description "Run Pi with a free-form prompt" + # Run Pi with a free-form prompt (spaces allowed) # Usage: pixe [] if test (count $argv) -eq 0 - pi-agent -m 'openrouter-preset/@preset/__GLM_NONDOT__' + pi --model 'cliproxyapi/__GLM__' else set -l prompt (string join " " -- $argv) - pi-agent "$prompt" -m 'openrouter-preset/@preset/__GLM_NONDOT__' + pi --model 'cliproxyapi/__GLM__' "$prompt" end end diff --git a/home-manager/programs/fish/functions/_pixeh_function.fish b/home-manager/programs/fish/functions/_pixeh_function.fish index 689af98c1..8af0f367b 100644 --- a/home-manager/programs/fish/functions/_pixeh_function.fish +++ b/home-manager/programs/fish/functions/_pixeh_function.fish @@ -1,5 +1,5 @@ -function _pixeh_function --description "Run Pi agent headlessly with a prompted input" - # Prompt for input and run Pi agent +function _pixeh_function --description "Run Pi headlessly with a prompted input" + # Prompt for input and run Pi in print mode # Usage: pixeh read -P "Prompt: " prompt @@ -8,5 +8,5 @@ function _pixeh_function --description "Run Pi agent headlessly with a prompted return 1 end - pi-agent "$prompt" -m 'openrouter-preset/@preset/glm-4-7' + pi --model 'cliproxyapi/glm-4.7' -p "$prompt" end diff --git a/home-manager/programs/fish/functions/_pixeh_function.tpl.fish b/home-manager/programs/fish/functions/_pixeh_function.tpl.fish index f8cca52f1..d5d4367cc 100644 --- a/home-manager/programs/fish/functions/_pixeh_function.tpl.fish +++ b/home-manager/programs/fish/functions/_pixeh_function.tpl.fish @@ -1,5 +1,5 @@ -function _pixeh_function --description "Run Pi agent headlessly with a prompted input" - # Prompt for input and run Pi agent +function _pixeh_function --description "Run Pi headlessly with a prompted input" + # Prompt for input and run Pi in print mode # Usage: pixeh read -P "Prompt: " prompt @@ -8,5 +8,5 @@ function _pixeh_function --description "Run Pi agent headlessly with a prompted return 1 end - pi-agent "$prompt" -m 'openrouter-preset/@preset/__GLM_NONDOT__' + pi --model 'cliproxyapi/__GLM__' -p "$prompt" end diff --git a/home-manager/programs/fish/functions/_pixel_function.fish b/home-manager/programs/fish/functions/_pixel_function.fish new file mode 100644 index 000000000..ae3f63c27 --- /dev/null +++ b/home-manager/programs/fish/functions/_pixel_function.fish @@ -0,0 +1,11 @@ +function _pixel_function --description "Run Pi with a free-form prompt using the local Qwen model" + # Run Pi with a free-form prompt (spaces allowed) using the local Qwen model + # Usage: pixel [] + + if test (count $argv) -eq 0 + pi --model 'lmstudio/qwen/qwen3.5-9b' + else + set -l prompt (string join " " -- $argv) + pi --model 'lmstudio/qwen/qwen3.5-9b' "$prompt" + end +end diff --git a/home-manager/programs/fish/functions/_pixel_function.tpl.fish b/home-manager/programs/fish/functions/_pixel_function.tpl.fish new file mode 100644 index 000000000..73fdd8fa1 --- /dev/null +++ b/home-manager/programs/fish/functions/_pixel_function.tpl.fish @@ -0,0 +1,11 @@ +function _pixel_function --description "Run Pi with a free-form prompt using the local Qwen model" + # Run Pi with a free-form prompt (spaces allowed) using the local Qwen model + # Usage: pixel [] + + if test (count $argv) -eq 0 + pi --model 'lmstudio/__QWEN_LOCAL__' + else + set -l prompt (string join " " -- $argv) + pi --model 'lmstudio/__QWEN_LOCAL__' "$prompt" + end +end diff --git a/home-manager/programs/fish/functions/_pixelh_function.fish b/home-manager/programs/fish/functions/_pixelh_function.fish new file mode 100644 index 000000000..249a8c637 --- /dev/null +++ b/home-manager/programs/fish/functions/_pixelh_function.fish @@ -0,0 +1,12 @@ +function _pixelh_function --description "Run Pi headlessly with the local Qwen model" + # Prompt for input and run Pi in print mode with the local Qwen model + # Usage: pixelh + + read -P "Prompt: " prompt + if test -z "$prompt" + echo "No prompt provided, aborting." >&2 + return 1 + end + + pi --model 'lmstudio/qwen/qwen3.5-9b' -p "$prompt" +end diff --git a/home-manager/programs/fish/functions/_pixelh_function.tpl.fish b/home-manager/programs/fish/functions/_pixelh_function.tpl.fish new file mode 100644 index 000000000..75a4ddfb8 --- /dev/null +++ b/home-manager/programs/fish/functions/_pixelh_function.tpl.fish @@ -0,0 +1,12 @@ +function _pixelh_function --description "Run Pi headlessly with the local Qwen model" + # Prompt for input and run Pi in print mode with the local Qwen model + # Usage: pixelh + + read -P "Prompt: " prompt + if test -z "$prompt" + echo "No prompt provided, aborting." >&2 + return 1 + end + + pi --model 'lmstudio/__QWEN_LOCAL__' -p "$prompt" +end diff --git a/scripts/llm-update.sh b/scripts/llm-update.sh index 684400b78..25f438d2f 100755 --- a/scripts/llm-update.sh +++ b/scripts/llm-update.sh @@ -67,6 +67,8 @@ declare -A TEMPLATES=( ["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/_pixel_function.tpl.fish"]=home-manager/programs/fish/functions/_pixel_function.fish + ["home-manager/programs/fish/functions/_pixelh_function.tpl.fish"]=home-manager/programs/fish/functions/_pixelh_function.fish ["home-manager/programs/fish/functions/_pixeh_function.tpl.fish"]=home-manager/programs/fish/functions/_pixeh_function.fish ) diff --git a/spec/fish/_pixe_function.tpl_test.fish b/spec/fish/_pixe_function.tpl_test.fish index 02ff0a07a..f2628c939 100644 --- a/spec/fish/_pixe_function.tpl_test.fish +++ b/spec/fish/_pixe_function.tpl_test.fish @@ -3,18 +3,19 @@ source $fn/_pixe_function.tpl.fish # ── no args: interactive mode ───────────────────────────── set log1 (mktemp) -function pi-agent; echo $argv >> $log1; end +function pi; echo $argv >> $log1; end _pixe_function -@test "no args calls pi-agent with templated preset" (grep -c "openrouter-preset/@preset/__GLM_NONDOT__" $log1) -ge 1 +@test "no args calls pi with templated cliproxyapi model" (grep -c "cliproxyapi/__GLM__" $log1) -ge 1 # ── with args: builds prompt ────────────────────────────── set log2 (mktemp) -function pi-agent; echo $argv >> $log2; end +function pi; echo $argv >> $log2; end _pixe_function hello world @test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses templated cliproxyapi model" (grep -c "cliproxyapi/__GLM__" $log2) -ge 1 rm -f $log1 $log2 diff --git a/spec/fish/_pixe_function_test.fish b/spec/fish/_pixe_function_test.fish index 2cb89d19b..acfa5a420 100644 --- a/spec/fish/_pixe_function_test.fish +++ b/spec/fish/_pixe_function_test.fish @@ -3,18 +3,19 @@ source $fn/_pixe_function.fish # ── no args: interactive mode ───────────────────────────── set log1 (mktemp) -function pi-agent; echo $argv >> $log1; end +function pi; echo $argv >> $log1; end _pixe_function -@test "no args calls pi-agent with model" (grep -c "openrouter-preset" $log1) -ge 1 +@test "no args calls pi with cliproxyapi model" (grep -c "cliproxyapi/glm-4.7" $log1) -ge 1 # ── with args: builds prompt ────────────────────────────── set log2 (mktemp) -function pi-agent; echo $argv >> $log2; end +function pi; echo $argv >> $log2; end _pixe_function hello world @test "with args builds prompt" (grep -c "hello world" $log2) -ge 1 +@test "with args uses cliproxyapi model" (grep -c "cliproxyapi/glm-4.7" $log2) -ge 1 rm -f $log1 $log2 diff --git a/spec/fish/_pixeh_function.tpl_test.fish b/spec/fish/_pixeh_function.tpl_test.fish index 1df971518..c057c983a 100644 --- a/spec/fish/_pixeh_function.tpl_test.fish +++ b/spec/fish/_pixeh_function.tpl_test.fish @@ -3,3 +3,14 @@ source $fn/_pixeh_function.tpl.fish @test "empty prompt rejects" (echo "" | _pixeh_function 2>&1) = "No prompt provided, aborting." @test "empty prompt returns 1" (echo "" | _pixeh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +echo "hello world" | _pixeh_function + +@test "non-empty prompt builds prompt" (grep -c "hello world" $log1) -ge 1 +@test "non-empty prompt uses templated cliproxyapi model" (grep -c "cliproxyapi/__GLM__" $log1) -ge 1 +@test "non-empty prompt uses print mode" (grep -c -- "-p" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_pixeh_function_test.fish b/spec/fish/_pixeh_function_test.fish index b3db466f3..3b7cca442 100644 --- a/spec/fish/_pixeh_function_test.fish +++ b/spec/fish/_pixeh_function_test.fish @@ -3,3 +3,14 @@ source $fn/_pixeh_function.fish @test "empty prompt rejects" (echo "" | _pixeh_function 2>&1) = "No prompt provided, aborting." @test "empty prompt returns 1" (echo "" | _pixeh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +echo "hello world" | _pixeh_function + +@test "non-empty prompt builds prompt" (grep -c "hello world" $log1) -ge 1 +@test "non-empty prompt uses cliproxyapi model" (grep -c "cliproxyapi/glm-4.7" $log1) -ge 1 +@test "non-empty prompt uses print mode" (grep -c -- "-p" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_pixel_function.tpl_test.fish b/spec/fish/_pixel_function.tpl_test.fish new file mode 100644 index 000000000..364f1cc1c --- /dev/null +++ b/spec/fish/_pixel_function.tpl_test.fish @@ -0,0 +1,21 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_pixel_function.tpl.fish + +# ── no args: interactive mode ───────────────────────────── +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +_pixel_function + +@test "no args calls pi with templated local Qwen model" (grep -c "lmstudio/__QWEN_LOCAL__" $log1) -ge 1 + +# ── with args: builds prompt ────────────────────────────── +set log2 (mktemp) +function pi; echo $argv >> $log2; end + +_pixel_function hello world + +@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/_pixel_function_test.fish b/spec/fish/_pixel_function_test.fish new file mode 100644 index 000000000..8f08ba75e --- /dev/null +++ b/spec/fish/_pixel_function_test.fish @@ -0,0 +1,21 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_pixel_function.fish + +# ── no args: interactive mode ───────────────────────────── +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +_pixel_function + +@test "no args calls pi with local Qwen model" (grep -c "lmstudio/qwen/qwen3.5-9b" $log1) -ge 1 + +# ── with args: builds prompt ────────────────────────────── +set log2 (mktemp) +function pi; echo $argv >> $log2; end + +_pixel_function hello world + +@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/_pixelh_function.tpl_test.fish b/spec/fish/_pixelh_function.tpl_test.fish new file mode 100644 index 000000000..6d2e9ed52 --- /dev/null +++ b/spec/fish/_pixelh_function.tpl_test.fish @@ -0,0 +1,16 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_pixelh_function.tpl.fish + +@test "empty prompt rejects" (echo "" | _pixelh_function 2>&1) = "No prompt provided, aborting." +@test "empty prompt returns 1" (echo "" | _pixelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +echo "hello world" | _pixelh_function + +@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 +@test "non-empty prompt uses print mode" (grep -c -- "-p" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/fish/_pixelh_function_test.fish b/spec/fish/_pixelh_function_test.fish new file mode 100644 index 000000000..231ac7a89 --- /dev/null +++ b/spec/fish/_pixelh_function_test.fish @@ -0,0 +1,16 @@ +set fn (status dirname)/../../home-manager/programs/fish/functions +source $fn/_pixelh_function.fish + +@test "empty prompt rejects" (echo "" | _pixelh_function 2>&1) = "No prompt provided, aborting." +@test "empty prompt returns 1" (echo "" | _pixelh_function 2>/dev/null; echo $status) = 1 + +set log1 (mktemp) +function pi; echo $argv >> $log1; end + +echo "hello world" | _pixelh_function + +@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 +@test "non-empty prompt uses print mode" (grep -c -- "-p" $log1) -ge 1 + +rm -f $log1 diff --git a/spec/llm_update_spec.sh b/spec/llm_update_spec.sh index 4ae613fef..856530e4d 100644 --- a/spec/llm_update_spec.sh +++ b/spec/llm_update_spec.sh @@ -62,9 +62,10 @@ The output should include 'config/llm/default_model.tpl.txt' End It 'includes fish wrapper templates in template mappings' -When run bash -c "grep '_ocxe_function.tpl.fish' '$SCRIPT' && grep '_pixe_function.tpl.fish' '$SCRIPT'" +When run bash -c "grep '_ocxe_function.tpl.fish' '$SCRIPT' && grep '_pixe_function.tpl.fish' '$SCRIPT' && grep '_pixel_function.tpl.fish' '$SCRIPT'" The output should include '_ocxe_function.tpl.fish' The output should include '_pixe_function.tpl.fish' +The output should include '_pixel_function.tpl.fish' End End