Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d4c070b
feat(demo): switch openCodeMlx default model to Qwen3.8-27B-8bit via …
perNyfelt Aug 16, 2026
8cffc9d
feat(openCodeMlx): speculative decoding + bind downloads to en7
perNyfelt Aug 16, 2026
bf5e511
fix(openCodeMlx): make download interface binding opt-in, not en7 by …
perNyfelt Aug 16, 2026
bffd87f
feat(models): consolidate model config, tune GPU offload, add /benchmark
perNyfelt Aug 28, 2026
905a01e
fix(models,benchmark): address review findings on the config/benchmar…
perNyfelt Aug 28, 2026
bb095dc
fix(openCodeMlx): shared-venv transformers pin, draft-model gating/mi…
perNyfelt Aug 28, 2026
4d408bb
feat(repl): wire /model, /context, /version, /stage, /revert, /commit…
perNyfelt Aug 28, 2026
dee6966
fix(openCodeMlx): disable speculative decoding by default, net perf loss
perNyfelt Aug 28, 2026
d77709c
fix(openCodeMlx): _quant_suffix no longer aborts main() under set -e
perNyfelt Aug 28, 2026
b5a42a6
fix(repl): /git-push --confirm false was silently forced back to true
perNyfelt Aug 28, 2026
3bf4296
fix(openCodeMlx): _quant_suffix now matches DWQ-style quant suffixes
perNyfelt Aug 28, 2026
0800ed2
revert(openCodeMlx): un-loosen LOCAL_MODEL_PROMPT, restore strict rules
perNyfelt Aug 28, 2026
14bdd54
fix(repl): last three Elvis-boolean/int truthiness sites in CommandEx…
perNyfelt Aug 28, 2026
3b7a5fe
test(scripts): run demo/test_*.sh as part of ./mvnw test
perNyfelt Aug 28, 2026
3fccae3
fix(demo): stop three not-installed test scenarios from inheriting am…
perNyfelt Aug 28, 2026
3b1d672
fix(scripts): bound DemoTestScriptsSpec's process wait, pin discovery…
perNyfelt Aug 28, 2026
328d54f
fix(scripts): DemoTestScriptsSpec's own git subprocess had the bug it…
perNyfelt Aug 28, 2026
90ced21
fix(demo): make opencode's not-installed test scenarios skip only in …
perNyfelt Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 252 additions & 17 deletions demo/openCodeMlx

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions demo/test_quant_suffix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -u
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./test_helpers.sh
source ./openCodeMlx

check "extracts a 4bit suffix" "4bit" "$(_quant_suffix 'mlx-community/Qwen3.8-27B-4bit')"
check "extracts an 8bit suffix" "8bit" "$(_quant_suffix 'mlx-community/Qwen3.8-27B-8bit')"
check "extracts a multi-digit bit suffix" "16bit" "$(_quant_suffix 'mlx-community/Some-Model-16bit')"
check "empty for a model id with no quant suffix" "" "$(_quant_suffix 'mlx-community/Qwen3-Coder-Next')"
check "does not match a mid-string bit token" "" "$(_quant_suffix 'mlx-community/8bit-prefixed-model')"
check "extracts the bit count from a DWQ-qualified id" "4bit" "$(_quant_suffix 'mlx-community/Qwen3.8-27B-4bit-DWQ')"
check "extracts the bit count from an underscore-qualified id" "8bit" "$(_quant_suffix 'mlx-community/Qwen3.8-27B-8bit_dwq')"
check "does not treat a multi-word non-quant tail as a qualifier" "" "$(_quant_suffix 'mlx-community/8bit-prefixed-model-name')"

# Regression guard: main() runs under `set -e`, and its call sites assign the result via bare
# "main_quant=$(_quant_suffix "$MLX_MODEL")" - not inside an if/while condition, so under set -e
# the assignment's exit status must never be non-zero, or a no-match model id (any checkpoint
# id that doesn't end in "<N>bit") would silently kill the whole script right after the
# multi-GB model download, with no error message and no cleanup trap installed yet.
_quant_suffix 'mlx-community/Qwen3.8-27B-4bit' >/dev/null
check "exits 0 on a matching model id" "0" "$?"
_quant_suffix 'mlx-community/Qwen3-Coder-Next' >/dev/null
check "exits 0 (not 1) on a non-matching model id, so set -e callers survive" "0" "$?"
check "a bare assignment under set -e still reaches the next line" "REACHED" \
"$(set -e; no_suffix_quant=$(_quant_suffix 'mlx-community/Qwen3-Coder-Next'); echo "REACHED")"

report
8 changes: 7 additions & 1 deletion demo/test_updates_mlxlm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ REAL_PATH="/usr/bin:/bin:/usr/local/bin"
bin_a="$work/a"; mkdir -p "$bin_a"
log_a="$work/a.log"
make_stub "$bin_a" pip 0 "$log_a"
# no mlx_lm.server stub -> `command -v`/direct exec fails, simulating "not installed"
# Explicitly stub mlx_lm.server to fail ensure_mlx_lm_current's "mlx_lm.server --help"
# check, rather than relying on it being absent from $REAL_PATH: "not installed" is a
# property of this test's stub, not of whatever the machine running it happens to have
# on PATH. A machine with a real mlx_lm.server on /usr/local/bin would otherwise
# silently take the "already installed" branch instead, making this scenario a no-op.
make_stub "$bin_a" mlx_lm.server 1 "$log_a"
(
PATH="$bin_a:$REAL_PATH" ensure_mlx_lm_current >/dev/null 2>&1
)
Expand All @@ -26,6 +31,7 @@ check "not-installed + pip install succeeds -> pip was invoked with --upgrade" "
bin_b="$work/b"; mkdir -p "$bin_b"
log_b="$work/b.log"
make_stub "$bin_b" pip 1 "$log_b"
make_stub "$bin_b" mlx_lm.server 1 "$log_b" # force "not installed", see scenario A
(
PATH="$bin_b:$REAL_PATH" ensure_mlx_lm_current >/dev/null 2>&1
)
Expand Down
79 changes: 79 additions & 0 deletions demo/test_updates_mlxvlm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
set -u
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./test_helpers.sh
source ./openCodeMlx

work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
# Stub dirs are prepended to a real system PATH, not used exclusively:
# ensure_mlx_vlm_current itself shells out to other real commands, which an
# exclusive stub-only PATH would hide too.
REAL_PATH="/usr/bin:/bin:/usr/local/bin"

# Scenario A: mlx-vlm missing, pip install stub succeeds -> returns 0, and pip is invoked with
# the same transformers pin ensure_mlx_lm_current carries. This is the actual fix under test:
# both packages share one venv, so an unconstrained "pip install mlx-vlm" is free to upgrade
# transformers past the version mlx-lm's AutoTokenizer.register call tolerates, silently
# breaking mlx_lm.server (still used unconditionally for the small background model).
bin_a="$work/a"; mkdir -p "$bin_a"
log_a="$work/a.log"
make_stub "$bin_a" pip 0 "$log_a"
# Explicitly stub python3 to fail ensure_mlx_vlm_current's "python3 -m mlx_vlm.server
# --help" check, rather than relying on the real system python3 lacking mlx_vlm: "not
# installed" is a property of this test's stub, not of whatever python3 environment the
# machine running it happens to have. A machine where mlx_vlm is importable from the
# default python3 (e.g. a shared/activated venv) would otherwise silently take the
# "already installed" branch instead, making this scenario a no-op.
make_stub "$bin_a" python3 1 "$log_a"
(
PATH="$bin_a:$REAL_PATH" ensure_mlx_vlm_current >/dev/null 2>&1
)
check "not-installed + pip install succeeds -> returns 0" "0" "$?"
check "not-installed -> pip carries the shared transformers pin" "1" "$(grep -c 'transformers>=5.7,<5.13' "$log_a")"

# Scenario B: mlx-vlm missing, pip install stub fails -> hard error (returns 1).
bin_b="$work/b"; mkdir -p "$bin_b"
log_b="$work/b.log"
make_stub "$bin_b" pip 1 "$log_b"
make_stub "$bin_b" python3 1 "$log_b" # force "not installed", see scenario A
(
PATH="$bin_b:$REAL_PATH" ensure_mlx_vlm_current >/dev/null 2>&1
)
check "not-installed + pip install fails -> returns 1 (hard error)" "1" "$?"

# Scenario C: mlx-vlm present, pip install stub fails -> still returns 0 (warn+continue).
bin_c="$work/c"; mkdir -p "$bin_c"
log_c="$work/c.log"
make_stub "$bin_c" python3 0 "$log_c"
make_stub "$bin_c" pip 1 "$log_c"
(
PATH="$bin_c:$REAL_PATH" ensure_mlx_vlm_current >/dev/null 2>&1
)
check "already-installed + pip update fails -> still returns 0 (warn and continue)" "0" "$?"

# Scenario D: mlx-vlm present, pip install stub succeeds -> pip was still invoked (not skipped)
# and still carries the transformers pin.
bin_d="$work/d"; mkdir -p "$bin_d"
log_d="$work/d.log"
make_stub "$bin_d" python3 0 "$log_d"
make_stub "$bin_d" pip 0 "$log_d"
(
PATH="$bin_d:$REAL_PATH" ensure_mlx_vlm_current >/dev/null 2>&1
)
check "already-installed + pip update succeeds -> returns 0" "0" "$?"
check "already-installed -> pip is still invoked (update not skipped)" "1" "$(grep -c '^pip ' "$log_d")"
check "already-installed -> pip update still carries the shared transformers pin" "1" "$(grep -c 'transformers>=5.7,<5.13' "$log_d")"

# Scenario E: mlx-vlm present, called in install-only mode -> pip upgrade must NOT be attempted.
bin_e="$work/e"; mkdir -p "$bin_e"
log_e="$work/e.log"
make_stub "$bin_e" python3 0 "$log_e"
make_stub "$bin_e" pip 1 "$log_e"
(
PATH="$bin_e:$REAL_PATH" ensure_mlx_vlm_current install-only >/dev/null 2>&1
)
check "already-installed + install-only mode -> returns 0" "0" "$?"
check "already-installed + install-only mode -> pip was NOT invoked" "0" "$(grep -c '^pip ' "$log_e")"

report
77 changes: 53 additions & 24 deletions demo/test_updates_opencode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set -e
source ./test_helpers.sh
source ./openCodeMlx
_install_opencode_via_curl() { return 1; }
PATH="/usr/bin:/bin:/usr/local/bin" HOME="$1" ensure_opencode_current 2>&1
PATH="/usr/bin:/bin" HOME="$1" ensure_opencode_current 2>&1
TESTEOF

# Run it; with the bug (bare call), set -e aborts before printing error.
Expand All @@ -48,30 +48,55 @@ trap 'rm -rf "$work"' EXIT
# Step 3), which tests override directly as a bash function instead.
REAL_PATH="/usr/bin:/bin:/usr/local/bin"

# Scenario A: opencode not on PATH; the install override actually creates a
# working $HOME/.opencode/bin/opencode (simulating a real successful install).
home_a="$work/a_home"
_install_opencode_via_curl() {
mkdir -p "$home_a/.opencode/bin"
cat > "$home_a/.opencode/bin/opencode" <<'INNER'
# Scenarios A/B/E need a PATH where opencode is NOT resolvable, so that
# ensure_opencode_current takes its "not found -> install" branch, but where coreutils
# (mkdir/cat/chmod, used by the install-simulation overrides above) still are. Deliberately
# excludes /usr/local/bin, unlike REAL_PATH above: it's the one realistic place a
# system-wide `opencode` might actually be symlinked to on this project's target platform
# (macOS/Homebrew) - the official installer puts it in ~/.opencode/bin, which was never on
# REAL_PATH to begin with. /usr/bin and /bin alone cover the coreutils these scenarios need.
NOT_INSTALLED_PATH="/usr/bin:/bin"

# Guarded rather than assumed outright: even /usr/bin:/bin could theoretically contain a
# real `opencode` on some machine this hasn't been tested against. If so, skip (not fail)
# rather than let these scenarios silently exercise the "already installed -> opencode
# upgrade" branch instead - a REAL network-touching command against whatever opencode
# install actually exists, run under a test that thinks it's simulating "not installed".
if PATH="$NOT_INSTALLED_PATH" command -v opencode >/dev/null 2>&1; then
echo "SKIP: a real 'opencode' is resolvable on PATH=$NOT_INSTALLED_PATH in this" >&2
echo "environment - scenarios A, B and E cannot safely simulate 'not installed' here" >&2
echo "(would run a real 'opencode upgrade' instead). Skipping those three checks." >&2
NOT_INSTALLED_SCENARIOS_SAFE=0
else
NOT_INSTALLED_SCENARIOS_SAFE=1
fi

if [[ "$NOT_INSTALLED_SCENARIOS_SAFE" -eq 1 ]]; then
# Scenario A: opencode not on PATH; the install override actually creates a
# working $HOME/.opencode/bin/opencode (simulating a real successful install).
home_a="$work/a_home"
_install_opencode_via_curl() {
mkdir -p "$home_a/.opencode/bin"
cat > "$home_a/.opencode/bin/opencode" <<'INNER'
#!/usr/bin/env bash
exit 0
INNER
chmod +x "$home_a/.opencode/bin/opencode"
}
(
PATH="$REAL_PATH" HOME="$home_a" ensure_opencode_current >/dev/null 2>&1
)
check "not-installed + install produces a binary -> returns 0" "0" "$?"
chmod +x "$home_a/.opencode/bin/opencode"
}
(
PATH="$NOT_INSTALLED_PATH" HOME="$home_a" ensure_opencode_current >/dev/null 2>&1
)
check "not-installed + install produces a binary -> returns 0" "0" "$?"

# Scenario B: opencode not on PATH; the install override is a no-op
# (simulates a failed install -- opencode still isn't findable afterward).
home_b="$work/b_home"
_install_opencode_via_curl() { :; }
(
PATH="$REAL_PATH" HOME="$home_b" ensure_opencode_current >/dev/null 2>&1
)
check "not-installed + install produces no binary -> returns 1 (hard error)" "1" "$?"
# Scenario B: opencode not on PATH; the install override is a no-op
# (simulates a failed install -- opencode still isn't findable afterward).
home_b="$work/b_home"
_install_opencode_via_curl() { :; }
(
PATH="$NOT_INSTALLED_PATH" HOME="$home_b" ensure_opencode_current >/dev/null 2>&1
)
check "not-installed + install produces no binary -> returns 1 (hard error)" "1" "$?"
fi

# Scenario C: opencode already on PATH, `opencode upgrade` stub succeeds.
bin_c="$work/c"; mkdir -p "$bin_c"
Expand Down Expand Up @@ -108,8 +133,12 @@ check "already-installed + install-only mode -> upgrade was NOT invoked" "0" "$(
# Scenario E: opencode not on PATH, install fails (returns 1), ensure_opencode_current
# is called under `set -e`. Verify that the function's return 1 is reached (not aborted
# by set -e when _install_opencode_via_curl exits with status 1). The function should
# return 1 to the outer subshell (not die uncontrolled).
test_set_e_with_failed_install
check "install fails under set -e -> function returns 1 (not aborted by set -e)" "0" "$?"
# return 1 to the outer subshell (not die uncontrolled). Same NOT_INSTALLED_PATH
# assumption as scenarios A/B (test_set_e_with_failed_install hardcodes the same
# "/usr/bin:/bin" internally) - guarded above, so only run this when that guard held.
if [[ "$NOT_INSTALLED_SCENARIOS_SAFE" -eq 1 ]]; then
test_set_e_with_failed_install
check "install fails under set -e -> function returns 1 (not aborted by set -e)" "0" "$?"
fi

report
127 changes: 99 additions & 28 deletions models.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
#!/bin/sh

force=false
while [ $# -gt 0 ]; do
case "$1" in
-f|--force)
force=true
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [-f|--force]"
exit 1
;;
esac
shift
done

# Model names/contexts are not duplicated here: src/main/bin/lca is the canonical
# source (it must be self-contained since it's distributed standalone), so we read
# its named variables via a targeted grep+eval.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LCA_SCRIPT="$SCRIPT_DIR/src/main/bin/lca"
if [ ! -f "$LCA_SCRIPT" ]; then
echo "Error: canonical model config not found at $LCA_SCRIPT" >&2
exit 1
fi
eval "$(grep -E '^(BASE_CHAT_MODEL|BASE_FALLBACK_MODEL|EMBEDDING_MODEL|CUSTOM_CHAT_MODEL|CUSTOM_CHAT_CONTEXT|QWEN_EXTRA_PARAMS|CUSTOM_FALLBACK_MODEL|CUSTOM_FALLBACK_CONTEXT|REVIEW_MODEL|REVIEW_CONTEXT|DEFAULT_CONTEXT_WINDOW|MODEL_STATE_DIR)=' "$LCA_SCRIPT")"

# Guard against a variable being renamed/added in lca without updating the grep alternation
# above (which would silently eval to empty) or a value in lca referencing another variable
# defined later in that file (which would also evaluate to empty here). QWEN_EXTRA_PARAMS is
# deliberately excluded: an empty extra-params string is a legitimate value, not a bug.
for _v in BASE_CHAT_MODEL BASE_FALLBACK_MODEL EMBEDDING_MODEL CUSTOM_CHAT_MODEL \
CUSTOM_CHAT_CONTEXT CUSTOM_FALLBACK_MODEL CUSTOM_FALLBACK_CONTEXT REVIEW_MODEL \
REVIEW_CONTEXT DEFAULT_CONTEXT_WINDOW MODEL_STATE_DIR; do
eval "_val=\$$_v"
if [ -z "$_val" ]; then
echo "Error: $_v not resolved from $LCA_SCRIPT" >&2
exit 1
fi
done

os=""
case "$(uname -s)" in
Darwin)
Expand Down Expand Up @@ -41,6 +81,11 @@ if ! command -v ollama >/dev/null 2>&1; then
esac
fi

get_model_id() {
model="$1"
ollama list 2>/dev/null | awk -v m="$model" '$1 == m {print $2; exit}'
}

checkAndInstall() {
model="$1"
echo "Checking for $model model..."
Expand All @@ -57,52 +102,78 @@ createCustomModel() {
base_model="$1"
custom_name="$2"
context_size="$3"
extra_params="${4:-}"

current_id="$(get_model_id "$base_model")"
if [ -z "$current_id" ]; then
echo "Warning: could not retrieve ID for $base_model. Skipping $custom_name."
return
fi

echo "Creating custom model $custom_name from $base_model with context size $context_size..."
# Mirrors src/main/bin/lca's rebuild_custom_model_if_changed: fingerprint the full desired
# Modelfile recipe (base id + context + extra params), not just the base model's id, so a
# context/parameter-only change is detected even when the base model itself hasn't changed.
# Shares lca's MODEL_STATE_DIR so the two scripts agree on whether a custom model is stale.
desired_signature="${current_id}|${context_size}|${extra_params}"
state_file="${MODEL_STATE_DIR}/${custom_name}.id"
saved_signature=""
if [ -f "$state_file" ]; then
saved_signature="$(cat "$state_file")"
fi

# Check if custom model already exists
if ollama list 2>/dev/null | grep -q "^$custom_name"; then
echo "$custom_name already exists."
custom_exists="no"
if ollama list 2>/dev/null | awk '{print $1}' | grep -Fxq "${custom_name}:latest"; then
custom_exists="yes"
fi

if [ "$force" != true ] && [ "$desired_signature" = "$saved_signature" ] && [ "$custom_exists" = "yes" ]; then
echo "$custom_name is up to date."
return
fi

if [ "$custom_exists" = "yes" ]; then
echo "Rebuilding $custom_name (base model, context, or parameters changed; or --force)..."
ollama rm "$custom_name"
else
echo "$custom_name not found. Creating..."
fi

# Create a temporary Modelfile
modelfile=$(mktemp)
cat > "$modelfile" << EOF
FROM $base_model
PARAMETER num_ctx $context_size
EOF
{
echo "FROM $base_model"
echo "PARAMETER num_ctx $context_size"
if [ -n "$extra_params" ]; then
old_ifs="$IFS"
IFS=';'
for kv in $extra_params; do
key="${kv%%=*}"
value="${kv#*=}"
echo "PARAMETER $key $value"
done
IFS="$old_ifs"
fi
} > "$modelfile"

# Create the custom model
ollama create "$custom_name" -f "$modelfile"

# Clean up
rm "$modelfile"
mkdir -p "$MODEL_STATE_DIR"
printf '%s\n' "$desired_signature" > "$state_file"

echo "$custom_name created successfully."
}

# Install base models
#checkAndInstall deepseek-coder:6.7b
checkAndInstall qwen3.6:35b-a3b
checkAndInstall gpt-oss:20b
checkAndInstall nomic-embed-text:latest
checkAndInstall "$BASE_CHAT_MODEL"
checkAndInstall "$BASE_FALLBACK_MODEL"
checkAndInstall "$EMBEDDING_MODEL"

# Create custom models with larger context (128k=131072, 64k=65536)
createCustomModel qwen3.6:35b-a3b qwen3.6-128k 131072
createCustomModel gpt-oss:20b gpt-oss-64k 65536
# Create custom models with larger context
createCustomModel "$BASE_CHAT_MODEL" "$CUSTOM_CHAT_MODEL" "$CUSTOM_CHAT_CONTEXT" "$QWEN_EXTRA_PARAMS"
createCustomModel "$BASE_FALLBACK_MODEL" "$CUSTOM_FALLBACK_MODEL" "$CUSTOM_FALLBACK_CONTEXT"

# Create review model with thinking disabled and smaller context for faster response
echo "Creating review model qwen3.6-review from qwen3.6:35b-a3b..."
if ollama list 2>/dev/null | grep -q "^qwen3.6-review"; then
echo "qwen3.6-review already exists."
else
modelfile=$(mktemp)
cat > "$modelfile" << EOF
FROM qwen3.6:35b-a3b
PARAMETER num_ctx 65536
EOF
ollama create qwen3.6-review -f "$modelfile"
rm "$modelfile"
echo "qwen3.6-review created successfully."
fi
createCustomModel "$BASE_CHAT_MODEL" "$REVIEW_MODEL" "$REVIEW_CONTEXT" "$QWEN_EXTRA_PARAMS"
Loading