A Qwen-family model served through llama.cpp ships a jinja chat template that
defaults `enable_thinking: true`, but `discoverLlamaCppModels` stamped every
local model with `reasoning: false` and an empty compat, so `--thinking off`
never reached the wire and the model kept emitting a reasoning block.
Route Qwen-family ids (plus the Qwen3.6-derived PrismLM Ternary Bonsai GGUFs,
matched with a scoped pattern rather than broadening the global
`isQwenModelId`) through a shared `applyLlamaCppQwenThinking` upgrade. It gives
them `reasoning: true` with the `qwen-template-false` disable dialect and
`qwenPreserveThinking`, since omp emits `preserve_thinking` inside
`chat_template_kwargs` for Qwen, and switches them to the chat-completions API
because the implicit llama.cpp provider defaults to `openai-responses`, whose
disable path has no Qwen encoding. The runtime base URL gains a `/v1` suffix so
the completions request does not POST to the native root, which serves
`/models` and `/props` but not `/chat/completions`; a model kept on a custom
transport (e.g. `pi-native`, whose client appends `/v1/pi/stream`) retains its
base URL so the suffix is not doubled. Non-Qwen local models keep the
configured api, base URL, and minimal compat.
The upgrade is idempotent and re-applied as the outermost transform after
discovery merges, provider/transport overrides, and cache fallbacks, so a
configured native-root `baseUrl` (which wins in `mergeDiscoveredModel`) or a
fallback to a pre-fix cached row cannot leave the routed model on the old
`openai-responses` / `reasoning: false` spec. Because routed models carry a
`/v1` base URL, the runtime metadata refresh probes the native `/models`
endpoint (stripping `/v1`, matching the existing `/props` probe) so a model's
`meta`, `status.args`, and `architecture.input_modalities` fields are not lost.
Adds discovery tests pinning the resolved reasoning/api/base URL/compat for
Qwen and non-Qwen local ids, that a configured native-root provider keeps the
`/v1` runtime URL, that a pi-native-transport model keeps its gateway URL, and
that the runtime metadata refresh for a routed model stays on native `/models`.
Signed-off-by: Christian Stewart <christian@aperture.us>
Built-in xd:// devices are mounted before the SDK wraps registry tools in ExtensionToolWrapper, so Cursor executed them via tool.execute() without the deny/prompt approval gate that write xd:// enforces. Wrap unwrapped devices in the Cursor resolver, skipping already-wrapped dynamic mounts.
Fixes#5650
Forwarded the session xd registry into Cursor provider tool contexts.
Routed Cursor MCP execution through the mounted registry fallback and added regression coverage for built-in devices and external MCP tools.
Fixes#5650
Print-mode assistant-error/aborted exit, RPC pi.shutdown() and stdin-EOF
shutdowns, and the extension command-context shutdown() called
process.exit() before (or racing) session.dispose(), skipping the bounded
browser reaper (releaseTabsForOwner) installed in dispose(). An OMP-owned
Chromium could survive the parent and reparent to PID 1.
Route all four graceful paths through the idempotent, promise-memoized
session.dispose() and await it before the final exit. The RPC
performShutdown no longer emits session_shutdown directly (dispose() emits
it), avoiding a double emit.
Fixes#5643
- restored capability reset import in agent-session refreshSkills
- fixed renamed credential entry reference in auth-storage org fields
- aligned xai web-search fetch mock and refresh-race test with current typings
The new isParking/has checks consulted the global lifecycle for every send, so a custom-registry IrcBus (which falls back to the global manager) could gate a live recipient on unrelated global park state for the same id. Add AgentLifecycleManager.manages(registry) and apply the mid-park/adopted gate only when the lifecycle owns this bus's registry; the parked-status path (read from the bus's own registry) is unchanged.
Fixes#5633
The v17 rename (46ad908) of dev.autoqa.consent -> dev.autoqaConsent and
todo.reminders.max -> todo.remindersMax added no case to
Settings.#migrateRawSettings, so pre-rename nested or quoted-dotted config
left the leaf beneath the parent path. The parent then resolved to an
object, making dev.autoqa truthy (isAutoQaEnabled saw Auto QA enabled) and
discarding the reminder limit.
Lift both legacy leaves onto the new keys during raw settings load via a
shared migrateNestedLeafRename helper: an explicit new key wins, a
separately configured parent boolean is preserved, an irrecoverable
object-valued parent is dropped so the schema default applies, and only the
new representation persists on save.
Fixes#5632
park() detached the live session only after session.dispose() resolved,
so during the dispose window the registry still exposed ref.session at
idle status. Concurrent ensureLive()/hub-send handed out or injected into
the dying session, reporting success while the message was dropped once
detach committed.
- Replace the #parking Set guard with a #parks map of in-flight park state
that is cancelable until the session is detached.
- park() now yields a cancel window, then detaches + flips status to
parked BEFORE dispose(), and coalesces concurrent park calls.
- ensureLive() cancels a pre-detach park (keeps the live session) or waits
for detach+dispose then performs one coalesced revive; never returns a
disposing session.
- release()/dispose() drain any in-flight park; the idle re-arm skips while
a park owns the transition.
- IrcBus.send() gates parkable recipients through ensureLive and derives
the revived receipt from session identity, so receipts/unread counts
reflect actual delivery.
Fixes#5633