@estebanforge/pi-glm-tweaks
Pi-native tweaks for Z.AI's GLM-5.2. Restricts the Pi thinking-level UI to the three modes GLM-5.2 actually supports (off, high, max), wires the native thinkingFormat:"zai" wire translation, and auto-clamps hidden levels when the model is selected.
Package details
Install @estebanforge/pi-glm-tweaks from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@estebanforge/pi-glm-tweaks- Package
@estebanforge/pi-glm-tweaks- Version
1.2.0- Published
- Jul 23, 2026
- Downloads
- 656/mo · 169/wk
- Author
- estebanforge
- License
- MIT
- Types
- extension
- Size
- 31.4 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@estebanforge/pi-glm-tweaks
Pi-native tweaks for Z.AI's GLM-5.2. Restricts the Pi thinking-level UI to the three modes GLM-5.2 actually supports (off, high, max), wires the native thinkingFormat:"zai" translation, and auto-clamps any stale level when the model is selected.
Install
pi install npm:@estebanforge/pi-glm-tweaks
Works with Pi's built-in zai/glm-5.2 model out of the box, or a custom entry in ~/.pi/agent/models.json. The extension re-registers it with the OpenAI-compat endpoint and the proper thinking map. Other Z.AI models (zai/glm-4.7, zai/glm-5-turbo, zai/glm-5.1, plus any custom entries) are preserved across the re-registration.
What it does
GLM-5.2 ships three thinking modes (per docs.z.ai):
| Pi thinking level | GLM-5.2 wire |
|---|---|
off |
thinking: { type: "disabled" } |
high |
thinking: { type: "enabled" } + reasoning_effort: "high" |
max (Pi xhigh) |
thinking: { type: "enabled" } + reasoning_effort: "max" |
Pi natively exposes six thinking levels (off, minimal, low, medium, high, xhigh). GLM-5.2 doesn't really fit the middle four — low/medium get mapped to high server-side, minimal skips thinking, and xhigh is the only way to reach reasoning_effort: "max".
This extension collapses that mismatch:
- Re-registers
zai/glm-5.2onsession_startwithapi: "openai-completions",baseUrl: https://api.z.ai/api/coding/paas/v4,compat.thinkingFormat: "zai", and a tightthinkingLevelMap:{ minimal: null, // hidden low: null, // hidden medium: null, // hidden high: "high", // → reasoning_effort: "high" xhigh: "max", // → reasoning_effort: "max" // off omitted → supported, sends thinking.type = "disabled" } - Auto-clamps on
model_select— if the current level is one we hid (e.g. you switched from a model that allowedmedium), quietly bump tohighand notify. - Footer hint — sets
ctx.ui.setStatus("glm-thinking", "thinking: off | high | max")while GLM-5.2 is the active model. /glm-tweakscommand — status panel + flag toggle from inside Pi (see/glm-tweakscommand).
Shift+Tab, /thinking, and the level picker all see only the three GLM-5.2 modes.
Token-efficiency tweaks
GLM-5.2 overthinks on long agent loops — it can spend an entire turn on reasoning_content without taking a tool call. The Z.AI API does not expose a max_thinking_tokens parameter, so the post that popularised this observation does it at the provider layer (mid-stream injection). We can't intercept the stream, but we can approximate the win with three opt-in tweaks.
Two of the three default OFF; glm-budget-nudge defaults ON. Per docs.z.ai Thinking Mode, Preserved Thinking (clear_thinking: false) is on by default on the coding endpoint precisely because it "increases cache hit rates — saving tokens in real tasks." The budget nudge keeps that property (it appends a fixed fragment, so the prefix stays byte-stable); glm-clear-thinking and glm-skip-short-thinking do not, so they stay opt-in for users who have measured that thinking tokens, not cache misses, are their real cost driver.
| Flag | Default | What it does |
|---|---|---|
glm-budget-nudge |
true |
Appends a constant thinking-budget fragment to the system prompt on every zai/glm-5.2 turn, steering the model toward committing to a tool call before it spirals into overthinking. Cache: safe — the fragment is a fixed string, so the appended system prompt stays byte-identical turn to turn and the cached prefix is reused. (The earlier mid-loop ratchet that injected a [system reminder: ...] user message was removed in 1.3.0 because its timestamp: Date.now() broke the cache.) |
glm-clear-thinking |
false |
Forces clear_thinking: true on every request, opting out of z.ai Preserved Thinking. Preserved Thinking is the coding endpoint's default and is what keeps the prefix byte-stable across turns (so it caches). Disabling it re-bills the full prefix every turn — usually a net loss. |
glm-skip-short-thinking |
false |
For user prompts under 80 chars, forces thinking.type: "disabled" for that turn. Cache: toggling thinking on/off across turns based on prompt length changes the reasoning_content sequence z.ai caches, so follow-up turns on the same session re-bill instead of hitting the cached prefix. |
All three flags surface in pi config and Pi's flag editor — pi config set glm-clear-thinking true to enable one of the opt-ins. Or flip them from inside Pi with /glm-tweaks.
/glm-tweaks command
An in-session command for inspecting and flipping the flags above without leaving Pi.
| Invocation | Effect |
|---|---|
/glm-tweaks (TUI) |
Opens an interactive settings menu (the same SettingsList component /settings uses). Flip any combination of flags, then a single reload fires on close to apply them all. |
/glm-tweaks (non-TUI / RPC) |
Falls back to a read-only status panel (active model, thinking level vs the off | high | max map, and each flag's on/off state). |
/glm-tweaks toggle <flag> |
One-shot flip: persists, then reloads. |
/glm-tweaks <flag> |
Shorthand one-shot toggle (flag name without the toggle keyword). |
The command offers tab-completion for toggle and the three flag names.
Why a reload per apply. Pi's extension API exposes getFlag but no live setFlag, and flag values are read into memory at load time. So changes persist via pi config set and a /reload picks them up. The interactive menu stages all your flips and reloads once on close; the one-shot toggle reloads immediately. In both cases the command notifies (Applied 2 change(s). Reloading...) before reloading. If you'd rather avoid reload churn entirely, set flags directly in pi config / the flag editor and reload once at your convenience.
What the tweaks cannot do
- Cap thinking tokens at a wire level. Z.AI does not expose a thinking budget param.
- Inject text mid-stream. No Pi hook for streaming chunk mutation.
- Force the model to call a tool. The system prompt can ask; nothing forces it.
- Lower
reasoning_effortper-request. Per KiwiGaze/glm-for-copilot #7 it's a no-op on/chat/completions.
Why this exists
Pi's built-in thinkingFormat: "zai" (in openai-completions.js) already knows the wire translation. The catch is that GLM-5.2's user-defined model in models.json typically lacks a thinkingLevelMap, so the UI shows all six levels and sends invalid combinations on hidden ones. This extension fills that gap automatically — no manual models.json editing.
Compatibility
- Pi (
@earendil-works/pi-coding-agent) — any version withregisterProvidertaking effect post-bind andthinkingFormat: "zai"support, plus thebefore_agent_start/context/before_provider_request/registerFlaghooks. - Z.AI API key — resolved through Pi's standard auth storage (env var
ZAI_API_KEY,/login, ormodels.jsonproviderapiKey). The extension does not configure auth.
License
MIT