origin/main added grok-4.6 as Chat Completions on paid xai and as an
uncurated SuperGrok row. Keep the Responses migration complete by
allowlisting the id, seeding xai-oauth, and baking the same 4-tier
effort map as grok-4.5.
Keep hasAuth() dedicated so SuperGrok is not auto-selected from a paid
key. Explicit preflight uses hasResolvableAuth() so xai-oauth/grok-4.5
can still borrow XAI_API_KEY.
grok-4.20-multi-agent uses reasoning.effort for agent count, and xhigh
is the 16-agent mode. Leave that tier advertised and unmapped while
Grok 4.5 still clamps leftover xhigh/max to high.
xAI's /v1/responses rejects presence/frequency penalties for every Grok
model, not only reasoners. Gate supportsPenaltyAndStopParams on isXaiHost
so xai/grok-2 no longer serializes presence_penalty.
The clamp map is only used when reasoning.effort is sent. Drop it from
catalog rows that set omitReasoningEffort so the exported snapshot does
not advertise a dead mapping.
api.x.ai accepts low/medium/high (and clamps minimal to low). Stop
advertising xhigh on paid xai and SuperGrok Responses rows, and map
leftover xhigh/max requests to high.
origin/main replaced createSimpleOpenAIResponsesOptions with the shared
OpenAI-compatible manager builder. Point xaiModelManagerOptions at that
same helper so XAI_API_KEY still discovers via /v1/responses.
First-party xAI /v1/responses rejects reasoning.summary. Bake
supportsReasoningSummary=false for both xai and xai-oauth so paid
grok-4.5 effort requests send only reasoning.effort, matching SuperGrok.
Paid xAI models.dev regeneration still emitted Completions-era thinking
dials for off-allowlist reasoners. Bake the no-dial policy into the
resolver/generator and refresh the exported catalog snapshot.
- Add `renderPdfPageScreenshot` to render PDF pages via headless Chromium.
- Update `ReadTool` to intercept legacy PDF image paths and return page screenshots.
- Ensure daemon clients are closed on read command exit.
- RpcClient: when stdout closes before ready, race child.exited (which settles only after ptree drains the stderr tail for nonzero exits) for 250ms before rejecting, so the earlier-registered exit watcher rejects with the real stderr text instead of an empty 'Stderr:'.
- mock-rpc-agent fixture: await the stderr pipe write callback before process.exit so failure text cannot be dropped unflushed.
- sdk-tool-activation: restore the default extension-handler budget once the intentionally stalled activation times out, so full-suite machine load cannot also time out the genuine recovery registration.
Both tests flaked only under concurrent full-suite chunk load; 10 concurrent stress runs pass post-fix.
- Replaced Reflect.deleteProperty teardown with the descriptor-preserving restoreProperty pattern used by the other ProcessTerminal suites, so real isTTY/setRawMode/columns/rows own-properties survive on TTY hosts and later test files are not poisoned.
- Replaced the custom MuPDF-WASM PDF extraction and rendering pipeline with the new `pdfToMarkdown` native function from `@oh-my-pi/pi-natives`.
- Removed legacy MuPDF extraction modules, WASM embedding scripts, and PDF image extraction tools.
- Added OCR warnings and browser/text redirection for unsupported PDF image reads.
- Updated native package definitions, documentation, and test suites for the new PDF inspection capability.
Passed the cmd.exe /s /c command line through Bun verbatim so configured editors and temporary paths retain their quotes.
Added command-line regression coverage and documented the fix.
Fixes#8544
The private-CSI reassembly gate and the DA1 swallow were both guarded by
`#da1SentinelOwners.length > 0`, so a Device-Attributes reply that arrived
after the startup capability-probe sentinel FIFO drained fell through to the
input handler and leaked into the composer as literal text (e.g.
`1;22;...;52c`). The extra latency of an SSH/zmx PTY chain makes the race
observable.
`CSI ? ... c` and split private-CSI responses are terminal->host reports,
never keystrokes, so they are now consumed regardless of whether a sentinel
is still outstanding.
Fixes#8542
-[DCDevice isSupported] synchronously opens an XPC connection to the per-user DeviceCheck metadata daemon, which exists only in an interactive GUI login session. From a session without graphic access (SSH, launchd LaunchDaemon, CI runner, service account, sandbox) the connection setup hits _xpc_api_misuse and aborts the process with SIGTRAP before any completion handler runs, so the promise never rejects and every openai-codex/* OAuth model becomes unusable.
Check the caller's security session for the sessionHasGraphicAccess attribute via SessionGetInfo before touching DeviceCheck; resolve { supported: false, error } when it is absent, mirroring the non-macOS stub and letting the caller send an error-coded attestation instead of dying.
Fixes#8353
The /hotkeys table described app.exit (Ctrl+D) as "Exit (when editor is
empty)", implying readline/EOF-style conditional exit. The handler exits
unconditionally and snapshots the current prompt as a resumable draft
regardless of editor content (custom-editor.ts fires onExit for app.exit
with no empty check; input-controller.ts handleCtrlD calls shutdown()
unconditionally, which persists the draft). Corrected the line to
"Exit (saves current prompt as draft)".
Fixes#8530
buildWhere() appended a redundant hard `channel_id = ?` clause on top of
the `(session_id = ? OR scope = 'global' OR channel_id = ?)` visibility
clause. The hard AND nullified the `scope='global'` branch, so any global
row whose channel_id differed from the recall channelId — including rows
imported via importFromDict() with channel_id NULL — was silently dropped.
Channel isolation is fully preserved by the visibility OR-clause alone
(other-channel, non-global, cross-session rows still fail all three
disjuncts), so removing the hard clause restores global visibility without
leaking other channels.
Fixes#8525
The OpenRouter non-Flash DeepSeek V4 effort override forced HIGH_ONLY for every id, so getModelDefinedEfforts clamped deepseek-v4-pro-0813 to high even though OpenRouter's /models advertises reasoning.supported_efforts [low,high,max] and the route accepts them. Carve out the dated SKU to the wire-exact low/high/max ladder while keeping the undated deepseek-v4-pro route high-only.
Fixes#8517
GLM-5.3 introduces three key API changes from GLM-5.2:
- Uniform wire-exact low/high/max reasoning_effort ladder on every host
(replacing GLM-5.2's host-specific dialects)
- Thinking can no longer be disabled (thinking.type must always be "enabled")
- Default effort is max
Changes:
- Add isGlm53ReasoningEffortModelId classifier (>=5.3, base/air/turbo, non-vision)
- getModelDefinedEfforts: GLM-5.3 returns LOW_HIGH_MAX uniformly
- impliesMandatoryReasoning: GLM-5.3 floors thinking-off to lowest effort
- deriveThinking/fillThinkingWireDefaults: defaultLevel=max for GLM-5.3
- generated-policies: pin glm-5.3 to 1M context (zai + zhipu-coding-plan)
- descriptors: zai defaultModel -> glm-5.3
- generate-models: curated seed (glm-5.3 is live but not in /models discovery)
- models.json: bundled glm-5.3 entry
- Tests: catalog thinking-metadata + AI wire-mapping (5 new tests)
Moved the optional Streamable HTTP GET listener after the initialized notification so stateful servers do not terminate the session during setup.
Added regression coverage for a server that rejects pre-initialization GET traffic.
Fixes#8514
- Updated `RemoteAuthCredentialStore` to track broker usage accounts across snapshots and streams before account-pool filtering.
- Replaced `#countUsageAccounts` with dynamic tracking methods `#replaceBrokerUsageAccounts`, `#upsertBrokerUsageAccount`, and `#removeBrokerUsageAccount`.
- Refactored `AuthStorage.#fetchUsageCached` to accept an options object for `timeoutMs` and `forceRefresh`.
- Updated dockerignore patterns to exclude `**/.venv/` and ensure depth-agnostic `.env` secret exclusion.