New Open Source LLM Release April 2026: What Gemma 4, GLM-5.1, Qwen 3.6-Plus and DeepSeek V3.2 Actually Look Like Inside a Shipping Consumer Mac AI App
Every April 2026 open-source LLM roundup lists params, license, and benchmark scores. None of them show what those releases look like from inside a real consumer Mac AI agent. Fazm’s answer is two small pieces of code: acp-bridge/src/index.ts line 1274 (the entire bridge allowlist is one !== condition) and ShortcutSettings.swift lines 159 to 163 (a three-row substring table). Together they decide whether your Gemma 4 or GLM-5.1 lands as a first-class “Smart” button or at sort order 99 with its raw modelId.
What open-source actually shipped in April 2026
Six major releases across labs. Each one reaches Fazm through the same pipe and lives or dies by the same two pieces of code.
The substring table: seven lines that decide Gemma 4’s label
This is the literal source from Desktop/Sources/FloatingControlBar/ShortcutSettings.swift, lines 157 to 163. It recognizes exactly three substrings. Anything else lands in the fallback branch.
“Filter out the 'default' pseudo-model - it's not a real selectable model”
acp-bridge/src/index.ts, comment above line 1274
The bridge allowlist: one condition, end of list
This is the complete model-filtering logic on the Node side. Eleven lines total, one condition that matters. Every April 2026 open-source LLM rides through this unchanged.
The Swift side: substring match or fallback to order 99
This is where the label on a “Gemma 4 27B” or “GLM-5.1 Chat” button is decided. Every non-Claude modelId falls through to line 187-189.
How four April 2026 open-source LLMs route through the pipe
Four sources on the left: the big April 2026 open-source releases. Four destinations on the right: the picker positions they can land in. The hub is the substring-match gate. Only the fourth destination (order 99) ever fires for a non-Claude modelId.
April 2026 open-source LLM → substring-match gate → picker bucket
Each April 2026 release, mapped to its Fazm-side fate
Six cards. Each one is a specific open-source release plus the exact line in Fazm that decides what it looks like in the Settings picker.
Google Gemma 4 (Apache 2.0, April 2)
Multimodal open weights in 2B/9B/27B sizes. Through a LiteLLM proxy exposing an Anthropic /messages shape for Gemma 4, the modelId 'gemma-4-27b' reaches emitModelsIfChanged at index.ts:1279. ShortcutSettings.swift:183 runs 'gemma-4-27b'.contains('haiku'/'sonnet'/'opus') → all three false. Falls to line 189. Button: 'Gemma 4 27B'. Position: 99.
Zhipu GLM-5.1 (MIT, 754B MoE)
37B active params, MIT license. Served through vLLM 0.8.x plus an OpenAI-to-Anthropic shim, the modelId 'glm-5.1-chat' hits the unknown-family branch. Button renders as 'GLM-5.1 Chat' at order 99. The 754B total weights are irrelevant to Fazm; only the modelId string and the proxy's /messages response shape matter at this boundary.
Alibaba Qwen 3.6-Plus (1M-ctx)
1M-token context survives the Fazm session hop because ACP stores conversation memory in the SDK's ~/.claude/projects/ file, not in the bridge process. The modelId 'qwen-3.6-plus' sorts to 99; the context capacity rides through session/prompt unchanged.
DeepSeek V3.2 (April 11)
Chinese-lab flagship, DeepSeek license. Via OpenRouter or a self-hosted shim, surfaces as 'deepseek-chat-v3.2'. No substring match. Fallback branch. The user can flip floating onto DeepSeek for one question, observer stays on Sonnet, main stays on Sonnet, because the three sessions are role-keyed at ChatProvider.swift:1047-1051.
Mistral Small 3.2 + PrismML Bonsai 8B + Llama 4 fine-tunes
Three smaller Apache 2.0 releases. Each arrives as a raw modelId; each sorts to 99. Bonsai 8B's practical pitch (runs on 16GB MacBook via llama.cpp Q4) is visible only as the label string — the runtime cost is hidden from Fazm behind the proxy. The bridge has no 'local vs hosted' awareness at this layer.
The one that does NOT surface
modelId = 'default'. Line 1274 strips it. This is an ACP SDK pseudo-model that represents whatever the subprocess is running. If a misconfigured proxy reports 'default' for a real model, that model disappears. Everything else — every actual Claude, every April 2026 open-source LLM — flows through.
Same input shape, two fates: Claude-native vs April 2026 open-source
Identical flow, identical data structure, different outcome. The substring match at line 183 is the single branch that decides which bucket a new open-source LLM lands in.
The same updateModels call, two branches, two picker positions
// Input: Claude-native modelId
// acpModels = [{ modelId: "claude-opus-4-7", name: "Claude Opus 4.7" }]
// ShortcutSettings.swift:183
if let match = modelFamilyMap.first(where: {
modelId.contains($0.substring) // "claude-opus-4-7".contains("opus") == true
}) {
// match = (substring: "opus", short: "Smart", family: "Opus", order: 2)
let label = "Smart (Opus, latest)"
return (ModelOption(
id: "claude-opus-4-7",
label: "Smart (Opus, latest)",
shortLabel: "Smart"
), 2)
}
// Renders at position 2 in the picker with a tier alias.What a new open-source LLM needs to surface in Fazm’s picker
Eight requirements. None of them live inside Fazm. All of them live in the proxy that fronts the model.
Requirements on the proxy side
- Proxy exposes Anthropic-compatible /v1/messages endpoint
- Proxy implements ACP session/new returning { sessionId, models: { availableModels: [...] } }
- Proxy implements ACP session/prompt streaming text deltas
- Proxy implements ACP session/set_model for mid-chat swaps
- Claude Agent SDK pointed at the proxy's base URL
- Model's modelId is not literally the string 'default' (would hit the index.ts:1274 filter)
- Model's modelId string can contain anything else (the substring table only recognizes haiku/sonnet/opus)
- Model's returned name field becomes the picker label; empty name falls back to modelId
Watching Gemma 4 land in the bridge log
This is a clipped log from a Fazm dev build (/tmp/fazm-dev.log) on a boot where the Claude Agent SDK is pointed at a LiteLLM proxy that fronts Claude plus four April 2026 open-source LLMs. The raw-list and emit log lines come from index.ts lines 1272 and 1280.
Timeline: open-source weights → Fazm picker button
Seven steps. Five of them happen outside Fazm. The two inside Fazm (steps 4 and 6) are the ones with the exact file:line anchors.
1. Open-source lab publishes weights
April 2: Google ships Gemma 4 under Apache 2.0. April 11: DeepSeek ships V3.2. Each release is on Hugging Face within hours. Serving stack (vLLM 0.8.x, llama.cpp) lights up architecture support within days. Nothing inside Fazm knows yet.
2. User points ACP SDK at an Anthropic-compatible proxy
LiteLLM, Cloudflare AI Gateway, or a hand-rolled shim that translates Anthropic /v1/messages into whatever Gemma 4 or GLM-5.1 speaks. The proxy also has to implement the ACP session methods that the Claude Agent SDK uses: session/new, session/prompt, session/set_model. Without the last one, Fazm's mid-chat model swap breaks.
3. Proxy enumerates available models to the SDK
On session/new, the proxy returns result.models.availableModels = [claude family, gemma-4-27b, glm-5.1-chat, qwen-3.6-plus, deepseek-chat-v3.2]. The Claude Agent SDK hands this list back through its stdio RPC to acp-bridge. No transformation happens in the SDK; it is a pass-through.
4. acp-bridge logs the raw list and filters
index.ts:1272 writes 'Raw models from ACP SDK: [...]' to stderr. Line 1274 removes any entry with modelId === 'default'. Line 1276 stringifies and diffs against lastEmittedModelsJson. If different, line 1279 sends the models_available event to the Swift side. The JSON diff cache means a list that repeats across multiple session warm-ups emits once.
5. ACPBridge.swift decodes and forwards to ShortcutSettings
The Swift side receives the JSON line, decodes the models array, and calls ShortcutSettings.updateModels. updateModels (line 178) iterates acpModels, applies the substring match, builds a new [ModelOption, Int] tuple per entry, sorts by the Int, and strips the Int to produce the final [ModelOption] array.
6. Substring match decides each model's fate
'claude-haiku-4-5' → 'haiku' match → ('Scary (Haiku, latest)', 0). 'claude-sonnet-4-6' → 'sonnet' → ('Fast (Sonnet, latest)', 1). 'claude-opus-4-7' → 'opus' → ('Smart (Opus, latest)', 2). 'gemma-4-27b' → no match → ('Gemma 4 27B', 99). Same fallback for GLM-5.1, Qwen 3.6-Plus, DeepSeek V3.2.
7. Sort and publish
Line 191 sorts by the Int. Line 192 strips the Int. Line 196 assigns to availableModels (a @Published var). SwiftUI re-renders SettingsPage.swift:2025 where ForEach(availableModels) draws the picker. The user sees: Scary, Fast, Smart, Gemma 4 27B, GLM-5.1 Chat, Qwen 3.6-Plus, DeepSeek V3.2. Click any one; next message routes through it via session/set_model.
Full trace: from Hugging Face to a picker click to a session/set_model call
Fifteen messages across seven actors. The proxy implements Anthropic’s /messages plus ACP; the Claude Agent SDK does not know it is talking to anything other than its usual endpoint; acp-bridge applies the one-condition filter; ShortcutSettings applies the three-substring match and the order-99 fallback.
Gemma 4 arrives via LiteLLM, becomes a picker button, gets clicked
The path most desktop AI agents take vs the path Fazm took
The split is at whether the model roster lives in app code or in an external proxy. If it lives in app code, every new open-source LLM release is an app-release event. If it lives in a proxy (via a permissive substring table), releases decouple entirely.
New open-source LLM ships: 'Gemma 4, April 2, 2026'
Naive desktop-agent architecture: A hardcoded enum of supported modelIds. New open-source LLM ships. User has to wait for a new app build that adds 'gemma-4-27b' to the enum, re-signs the binary, goes through code signing and notarization, and ships a point release. Meanwhile the model has been on Hugging Face for a week.
- Hardcoded modelId enum
- New release blocked on app-update
- Notarization gates every vendor adapter
- Users stuck on last-shipped models
Fazm’s path vs the hardcoded-roster path
Eight rows. Each row is a concrete behavioral difference, each tied to a file:line anchor that a reader can verify inside the shipping open-source repo at github.com/mediar-ai/fazm.
| Feature | Hardcoded-roster path | Fazm (permissive table path) |
|---|---|---|
| Bridge-side filter | Hardcoded vendor allowlist or a model manifest file | One condition: modelId !== 'default' (index.ts:1274) |
| Claude-family detection | Enum of exact modelIds that requires an update per release | Substring match against 3 rows (ShortcutSettings.swift:159-163) |
| Unknown-family fallback | Rejected, hidden from picker, or thrown as an error | Raw modelId as label, order 99, renders at end (line 189) |
| App update needed when Gemma 4 ships | New app build with the new modelId wired into an enum | None; arrives via proxy, surfaces automatically next launch |
| Observer session target when user flips to Gemma 4 | Follows the foreground pick or has no separate observer | Still claude-sonnet-4-6 (hardcoded at ChatProvider.swift:1050) |
| Where to verify the open-source-model UI fate | Scattered across vendor adapters and UI code | Two files, seven lines total (ShortcutSettings.swift:159-163,189 + index.ts:1274) |
| What appears when two April 2026 open-source LLMs arrive together | One absorbs the other or both get a generic 'Other' label | Two buttons, both order 99, stable order preserved |
| Source visibility | Closed source or selectively published adapters only | github.com/mediar-ai/fazm (ChatPrompts.swift:172, OnboardingView.swift:456) |
See a Gemma 4 or GLM-5.1 button appear in a live Fazm picker
Book a 20-minute demo. We will point the Claude Agent SDK at a LiteLLM proxy in front of an April 2026 open-source LLM and watch the new button show up in Settings at order 99 with its raw modelId.
Book a call →FAQ
Frequently asked questions
What new open source LLMs shipped in April 2026?
The most significant April 2026 open-source releases: Google Gemma 4 (Apache 2.0, April 2), Zhipu GLM-5.1 (MIT, 754B MoE with 37B active), Alibaba Qwen 3.6-Plus (1M-token context, Tongyi license), DeepSeek V3.2 (DeepSeek license, April 11), Mistral Small 3.2 (Apache 2.0, early April), and PrismML Bonsai 8B (Apache 2.0). On the tooling layer, vLLM 0.8.x and llama.cpp both shipped architecture support within days. Fazm's bridge does not care which of these a user routes through; the allowlist at acp-bridge/src/index.ts line 1274 filters only modelId !== 'default'.
Can Fazm use a new open source LLM from April 2026 without a Fazm update?
Yes, via an Anthropic-compatible proxy. The Claude Agent SDK that acp-bridge spawns accepts a custom base URL. Point that at a proxy like LiteLLM, Cloudflare AI Gateway, or a self-hosted OpenAI-to-Anthropic shim, configure the proxy to route to Gemma 4 or GLM-5.1, and the bridge will emit the model as-is through emitModelsIfChanged at index.ts line 1271. The Swift side at ShortcutSettings.swift line 178 accepts any modelId without validation and renders a button for it. No Fazm rebuild required.
Why does Fazm ship with only Claude support in the model picker today?
The default path uses Anthropic's Claude Agent SDK over ACP (Agent Client Protocol), and that SDK's availableModels response returns the three Claude families. Fazm does not maintain its own model adapter layer; it forwards whatever the ACP SDK hands back. This is a deliberate choice: every model that Fazm surfaces has already passed the ACP SDK's tool-calling and session-state contracts. For an April 2026 open-source LLM to appear, it has to be fronted by a proxy that speaks Anthropic's /messages shape and respects the ACP session/prompt and session/set_model methods.
What happens to a new open source LLM's name in Fazm's picker?
ShortcutSettings.swift line 183 runs modelId.contains(substring) against the three-entry modelFamilyMap at lines 159 to 163. The substrings are exactly 'haiku', 'sonnet', 'opus'. 'gemma-4-27b' contains none of those, so line 187 to 189 kicks in: the label becomes the API 'name' field (or the raw modelId if name is empty), shortLabel becomes the same string, sort order becomes 99. Visually, Gemma 4 renders at the bottom of the picker as a full-width button with 'gemma-4-27b' as its label, no tier alias. GLM-5.1 would be 'glm-5.1-chat'. Qwen 3.6-Plus would be 'qwen-3.6-plus'. DeepSeek V3.2 would be 'deepseek-chat-v3.2'.
What is the exact allowlist on the bridge side?
One line: acp-bridge/src/index.ts line 1274 reads const filtered = availableModels.filter(m => m.modelId !== 'default'). That is the entire model filter. There is no family check, no Claude check, no vendor check, no version check. Anything the ACP SDK hands back (minus the 'default' pseudo-model) gets forwarded to the Swift picker via send({ type: 'models_available', models: filtered }) at line 1279. For a new open-source LLM to be rejected, the proxy fronting it would have to report its modelId as literally the string 'default'.
How many substrings does the Swift side actually recognize?
Three. ShortcutSettings.swift lines 159 to 163 define private static let modelFamilyMap with exactly three rows: ('haiku', 'Scary', 'Haiku', 0), ('sonnet', 'Fast', 'Sonnet', 1), ('opus', 'Smart', 'Opus', 2). Any modelId that does not contain one of those three substrings falls to the line 187-189 branch: (ModelOption(id: modelId, label: displayName, shortLabel: displayName), 99). A contributor who wanted to add 'Gemma' as a first-class family ('Fast-OSS', order 3) would add exactly one row to this table.
What does the log line look like when a new open source LLM arrives via proxy?
Two lines at index.ts line 1272 and line 1280, both going to stderr which becomes /tmp/fazm-dev.log. Line 1272: 'Raw models from ACP SDK: [{modelId:"gemma-4-27b",name:"Gemma 4 27B",description:"..."},{modelId:"claude-sonnet-4-6",name:"..."},...]'. Line 1280: 'Emitted models_available: gemma-4-27b=Gemma 4 27B, claude-sonnet-4-6=Claude Sonnet 4.6, ...'. Then on the Swift side ShortcutSettings.swift line 198 logs: 'ShortcutSettings: updated availableModels to [claude-haiku-4-5 = Scary (Haiku, latest), claude-sonnet-4-6 = Fast (Sonnet, latest), claude-opus-4-7 = Smart (Opus, latest), gemma-4-27b = Gemma 4 27B]'.
Why does the unknown-family branch return order 99?
Lines 159 to 163 assign orders 0, 1, 2 to Haiku, Sonnet, Opus respectively. Line 191 sorts availableModels by the numeric order field. Anything with a higher order sorts later. The line 189 fallback uses 99 as a deliberately large bucket so every non-Claude model lands after every Claude model, without needing per-vendor ordering. An open-source LLM like Gemma 4 arriving through a proxy renders after 'Smart (Opus, latest)' even if it was handed back first in the API response. If two non-Claude models arrive together, they both get order 99 and their relative order is the stable order Swift's sort preserves.
Is Fazm itself open source?
Yes, 100%. Source at github.com/mediar-ai/fazm, referenced from three places inside the Desktop app: ChatPrompts.swift line 172 ('Fazm is 100% open source (github.com/mediar-ai/fazm) and local-first'), OnboardingView.swift line 450 ('Fazm is fully open source. You can inspect exactly what data is collected and how it is processed by reviewing our source code on GitHub'), and OnboardingView.swift line 456 which opens the GitHub URL from a button. The bridge (acp-bridge/src/index.ts) and the Swift Desktop sources are both in the same public repo. Every file:line anchor on this page is grep-able from there.
What does 'a model passes the ACP contract' mean in practice for a new open source LLM?
Two methods need to work. session/new has to accept mcpServers and return a sessionId plus availableModels. session/prompt has to stream text deltas and respect tool-call structure. session/set_model has to mutate the model bound to an existing sessionId. A proxy like LiteLLM implements all three on top of any OpenAI-compatible backend. A raw llama.cpp server does not; it speaks an OpenAI-compatible /v1/chat/completions and stops there. The bridge only knows about ACP, so getting Gemma 4 in front of Fazm means either an ACP-native adapter or a shim that turns the model's native API into ACP RPC. The bridge forwards identically either way.
Why does the observer session never see the new open source LLM button?
ChatProvider.swift line 1050 hardcodes the observer's model to 'claude-sonnet-4-6'. The observer runs silently in the background summarizing chat. It is warmed once at app launch, it registers with sessionKey 'observer', and it never reads ShortcutSettings.selectedModel. The open-source LLM button appearing in the picker changes the user's UserDefaults and the foreground 'floating' session binding; it cannot reach the observer. This is by design: a user flipping to Qwen 3.6-Plus for one question should not retarget the cost-gated background summarization loop.
What are the grep commands to verify everything on this page?
grep -n 'modelFamilyMap' /Users/matthewdi/fazm/Desktop/Sources/FloatingControlBar/ShortcutSettings.swift returns line 159. grep -n 'm.modelId !== "default"' /Users/matthewdi/fazm/acp-bridge/src/index.ts returns line 1274. grep -n 'shortLabel: displayName' ShortcutSettings.swift returns line 189 (the order 99 fallback). grep -n 'github.com/mediar-ai/fazm' Desktop/Sources/ returns ChatPrompts.swift:172 and OnboardingView.swift:456. grep -n 'emitModelsIfChanged' acp-bridge/src/index.ts returns the function definition at line 1271 and every callsite. Every number on this page is a direct file:line reference in the shipping codebase.
Related guides
New LLM Model Release April 2026
The sibling guide: how a NEW release (Claude Opus 4.7) swaps into a running 17-message chat on line 1503 of the same bridge, without destroying the transcript. Same pipeline, different branch.
New LLM Releases April 2026
Cross-vendor release landscape for April 2026 and how Fazm's role-keyed sessions let a user burn Opus 4.7 on a foreground chat while the observer stays on Sonnet.
Open Source AI Model Release April 2026
The release roundup with the inference-engine and MCP-server layer: what shipped, what it runs on, and how the composable OSS stack lands next to the model list.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.