chore(deps): update dependency can1357/oh-my-pi to v18.2.1 #181
Loading…
Reference in a new issue
No description provided.
Delete branch "renovate/can1357-oh-my-pi-18.x"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR contains the following updates:
18.2.0→18.2.1Release Notes
can1357/oh-my-pi (can1357/oh-my-pi)
v18.2.1Compare Source
@oh-my-pi/pi-agent-core
Added
Fixed
message_updatesnapshots now deep-clone only the blocks the stream actually touched instead of the entire accumulated message, eliminating the quadratic cloning work that could freeze the TUI for tens of seconds to minutes while a subagent streams (#10605)./clearboundaries. (#11525 by @rpie9)/responses/compactendpoint after V2 failures.@oh-my-pi/pi-ai
Added
Fixed
reasoning_extractionclassifier on Fable, leaked reasoning into visible answers on Opus, Sonnet and Haiku, and broke the prompt cache prefix on every tool-calling turn. Replayed assistant turns now carry the model id the request resolves to and astopReasonderived from the turn's own tool calls, so same-model thinking blocks keep their signatures and replay natively (#12115 by @Zhu-Aemon).400 Invalid signature in thinking blockafter a failover proxy swapped upstream models mid-conversation (e.g. Claude -> GLM -> Claude): when the unsigned-demotion retry fails identically, the anthropic-messages transport now retries once with replayed thinking dropped and pins that mode for the session, so the conversation continues without starting a new session (#12006 by @Damin-Lee).string_above_max_length) when replaying tool call IDs exceeding 64 characters or containing composite delimiters (|,\n) by sanitizing and deterministically clamping call IDs on the wire (#11342).400 Referenced reasoning item ... was not found or has expiredon Meta Muse Spark models by suppressing reasoning reconstruction when history is filtered and synthetic replay is disallowed, while preserving Anthropic and DeepSeek replay (#10966).pi-nativetransport used by containerized and robomp deployments, because the state cannot cross the wire and the gateway kept none of its own (#12058 by @camjac251).400 Provider returned errorafter the session history contains a tool-call turn from another provider, by no longer sending a fabricated reasoning item id (#11791 by @brndnmtthws).response.completed, upstream stream interrupted or ended before its terminal chunk, socket disconnected before the secure TLS handshake) classifying as terminal errors, so they now retry like their status-tagged twins instead of settling the turn (#11805).ReasoningEffortin CamelCase now trigger effort-downgrade retries instead of terminating turns with HTTP 400 (#11804).function_callandfunction_call_output, which broke round pairing on strict validators (e.g. DeepSeek) with400 No tool output found for tool call …: orphan-output/call repair now runs before the interleaved-message hoist, so any injected note is relocated out of the tool-call batch (#11473).tier:fable,tier:mythos) is now cleared once a live usage report shows headroom on both the tier row and the shared windows, instead of idling a usable account until the reported reset. Healing requires a live report, and a credential held by an unscoped block spends no usage request on a probe that cannot lift it (#11334 by @AshishKumar4).retry.fallbackChains: a{"error":{…}}/{"code":429}chunk or a plain-text throttle frame (429 Too Many Requests, an nginx page) is now classified as a retryable 429/5xx through the same path an HTTP-status 429 takes, so a busy provider backs off and fails over instead of ending the session. Only bodies the provider actually reported are used: no status is inferred from error wording, and an unreadable body can no longer consume a credential.complete()andcompleteSimple()while streaming responses.content: nullon/v1/responsesand/v1/chat/completionsmessage items with a 400; Codex and other OpenAI clients that emit null content on empty turns now work, matching OpenAI's tolerance (#10956).nonereasoning effort, which Azure rejects with HTTP 400 (#11052).ENOENTwhen another process removes a stale shared concurrency lock during acquisition.@oh-my-pi/pi-catalog
Added
deepseek-flash) now accepts image inputs and resolves its reasoning metadata, name, and effort ladder from upstream instead of shipping as a text-only row without them.Fixed
deepseek/deepseek-v4.1-flashrow exposing its documented low/high/max thinking levels and image input, and made live discovery resolve the reasoning contract its rules declare (#1666, #11703 by @aliefe04).api.meta.ai/v1accepts onlytool_choice: "auto", sonone,required, and named choices (subagent final-retryyield, forced tools, structured output, compaction handoff) are now omitted instead of sent (#11635 by @quantmind-br).maxOutputTokens=65536, which the endpoint rejects with a 400; the output cap is clamped to 65535 (#10595 by @WeMingT).400 Referenced reasoning item ... was not found or has expired: replayed Responses reasoning history is now filtered for the muse-spark family, matching the existing Anthropic-on-OpenRouter treatment (#10675 by @Giardi77).minimal/low/medium/higheffort ladder for every thinking-capable model, which shadowed the per-model compat rules and mademaxunreachable on the DeepSeek V4 line (including the serveddeepseek-v4.1-flash,deepseek-v4-flash:0731, anddeepseek-v4-pro:0813ids): discovery now leaves the ladder to the rule tree, so those models advertise the wire-exactlow/high/maxand GLM-5.3 exposeslow/high/max(#8334).api.meta.ai/v1accepts onlytool_choice: "auto", sonone,required, and named choices (subagent final-retryyield, forced tools, structured output, compaction handoff) are now omitted instead of sent.reasoning_effort: "none"(#11052).xhighandmaxinstead of the unsupportedminimallevel. (#10788 by @voonfoo)anthropic-messagesproviders whose adaptive effort ladder exposesminimalsendingoutput_config.effort: "minimal", which the Anthropic Messages API rejects with400 level "minimal" not supported; the adaptive effort mapper now clampsminimaltolow(#10994).metadata.discountfraction is now applied to input, output, and cache-read rates (#10935).@oh-my-pi/pi-coding-agent
Breaking Changes
/dropslash command to/deleteso that "drop" is no longer overloaded between deleting the session and dropping a goal (/goal drop).details.truncation.content; use resultcontentordetails.displayContentinstead. (#11255 by @jiwangyihao)DEL,DEL.BLK,COPY, andCOPY.BLKhashline edit operations. UseCUT/CUT.BLKfor deletion; removed content remains available toPASTE.Added
<SM:AFTER>to insert new lines after an anchor without repeating or replacing it.APPEND_SYSTEM.md,--append-system-prompt) now render under their own## User Instructionsheading whenever generated blocks precede them, instead of trailing the## MCP Server Instructionssection and reading as server-supplied, unverified content (#11832 by @iacore).models.ymldiscovery:provider (e.g.openai-models-list):buildSessionOptionsruns a cache-aware refresh for the provider named by the selector and retries, instead of disabling prewalk with aModel "…" not foundwarning for idsomp modelslists (#11820).yieldno longer fails a run withSYSTEM WARNING: Subagent called yield with null data.when a data-lessuseLastTurnfinalize (e.g.{type:"result"}) lands on a thinking-only turn with no text; the tool now rejects it at the boundary so the child is reminded to resubmit withdata(#11150).--continueno longer treats a merely-missing breadcrumb cwd as a project move. Re-root now requires the continue directory to be the same device+inode the breadcrumb recorded (git worktree move/ same-filesystemmv). A cross-filesystemmv(copy+unlink, new inode) is intentionally not re-rooted: the session stays in the original bucket,header.cwdis not rewritten, and a warn is logged (#11565)./newrevivals no longer write<id>.mdoutside the revived agent's tree (#11563).settings.json→config.ymlmigration now writes the YAML first and only then archives the JSON, surfaces failures instead of swallowing them, and recovers from an orphanedsettings.json.bakwhenconfig.ymlis missing (#11569).settings.json→config.ymlmigration now writes the YAML first and only then archives the JSON, and surfaces failures instead of swallowing them (#11569).MaaS Slacksurvive/mcp reauthwrite-back instead of being rejected by the config writer (#11731).Read (N)tree are now clickable OSC 8 hyperlinks, matching standalone Read rows; delimited reads carry a resolved link target per row so both live output and rebuilt transcripts link correctly (#11732)./mcpcommands (enable,disable,test,remove,reconnect,reauth,unauth) using configured and runtime-discovered MCP servers.CUTandPASTEops to the hashline edit tool for moving code without retyping it:CUT N.=M(and.BLKblock forms) capture lines into a clipboard register, andPASTEoperations insert them. The register flows across sections within a patch (cross-file moves) and persists across edit calls per session.--from-claudeand--from-codexsession imports (including compaction state for Codex), also available from/resume @claudeand/resume @codex./login exa, opening the official key dashboard and saving pasted keys for authenticated web search while preservingEXA_API_KEYand explicit-selection public MCP fallback behavior (#1798).ExtensionContext.getAsyncJobSnapshot()so extensions can read the owning session's async-job state without relying on process-global job-manager identitytui.codexResetFireworkscelebrations for unscheduled Codex weekly usage resets and newly banked saved resets, shown in a theme-aware top-third modal until Escape (#6858 by @joshrzemien).pi_read/pi_ls→read,pi_bash→bash,pi_edit→edit,pi_write→write,pi_grep→grep, andpi_find→glob. The frames are a separate wire family from the legacy args, not aliases, so each mapping is a real translation —pi_grep'signore_caseis the inverse of the local tool's case-sensitivity flag,pi_findsearches filenames rather than contents, andpi_edit's replacements are renamed to the local snake_case pairs.providers.autoThinkingMaxEffort(xhigh|max, defaultxhigh) raises the ceiling of theautothinking classifier.maxbecame a first-class effort tier after the classifier prompt was written, soautocould never reach it on models that expose the tier — only theultrathinkkeyword could. Opting in addsmaxto the classifier's vocabulary, gated on the target model actually supporting it; the default keeps today's prompt byte-for-byte. The ceiling is enforced inside the effort clamp rather than on the classifier's answer, so a sparse ladder cannot snap an excluded request back up, and the Low floor is still resolved against the model's own ladder. The on-device 3-bucket classifier stays capped atxhighregardless of the setting. The ceiling governs whatautoresolves: a ladder with nothing underneath it yields no auto level, and athinking.requiresEffortmodel still gets its lowest supported effort from the transport.ts-no-local-is-recordTTSR rule, which catches localisRecordfunction and lambda definitions and directs agents to shared guards plus explicit shape validation.tool_callhandler (extension or hook) can now returninputto revise the arguments a tool executes with, not justblockit. The returned object is the raw execution input passed to the tool (ignored whenblockis set, and not applied tocomputertool calls), enabling wrappers that normalize or rewrite a built-in's arguments without reimplementing the tool. For model-issued calls the event fires at arg-prep time in the agent loop, so a revision is revalidated against the tool schema and is what concurrency scheduling,tool_execution_start/transcripts, the persisted assistant message, and the approval gate all observe — the user approves exactly what runs, and a revision that changes a tool's functional concurrency (e.g. bashpty) schedules correctly. A revised nestedwrite xd://device dispatch forfeits the outer write gate's approval and faces the full prompt again (#6681 by @psyrendust).sample(1) call-tree reports to the read tool:*.sample.txtreads now return a compact bottleneck summary — per-thread hot paths with on-CPU sample counts (blocked syscall time excluded), demangled Rust v0/legacy symbols, flattened direct recursion, merged call-site siblings, idle-thread classification, and a process-wide top-functions-by-self-samples table.:rawstill reads the original report, and files that merely carry the extension fall back to plain text..cpuprofilesupport to the read tool (Node/Bun--cpu-prof, Chrome DevTools, CDPProfiler.stopoutput): reads now return a compact bottleneck summary — hot-path call tree with on-CPU milliseconds ((idle)time excluded), collapsed pass-through chains, flattened direct recursion, shortened file URLs, and a top-functions-by-self-time table.:rawstill reads the original JSON, and files that merely carry the extension fall back to plain text.$2.67 (sub) + $0.41 (adv)while keeping already-incurred Advisor cost across runtime disablement and same-session history rewrites.inspect_imagetool (inspect_image.timeoutMs, default 5 minutes; set to 0 to disable) so a stalled vision-model provider fails fast with a clear error instead of blocking until manual abort (#4165).Changed
browser/computercalls now say what happened (open main https://…,main.id(5).click(),close all) with a globe/computer icon instead of a barebrowserlabel; preludes with nothing to show record no row, while failures still surface.--mode rpcsession with an unhandled rejection (#11654 by @sjawhar).[provider/model]error and ahistory://<id>pointer) to whoever woke it, so ahub send await:truewaiter learns why there is no answer instead of a generic "stopped without replying" (#11290).stream-revision) keep the old behaviour (#11276).hubtool injection into read-only subagents (#11044, closes #10257).startup.changelogMode(summary|expanded|hidden) to control them; legacycollapseChangelogchoices migrate automatically (#6771).xd://dispatch now share one canonical tool map:write xd://<tool>executes any enabled top-level or mounted tool, andread xd://<tool>returns its docs, instead of failing when the name was exposed through the other layer. Mounted names are presentation metadata only, so tool replacement and disconnection cannot leave stale device instances; disabled tools remain unreachable, and bothxd://and Cursor/top-level fallback execution retain the tool's approval and ACP permission gates.xd://device docs now render the parameter schema as a comment-annotated TypeScript type (viajsonSchemaToTypeScript, the same renderer the in-band tool inventory uses) instead of a raw JSON Schema dump, shrinking system-prompt device sections while keeping descriptions inline./vision [on|off|auto|status]slash command for session-scoped control of theinspect_imagevision-delegation tool, modeled on/computer:on/offforce the tool for the current session only,autoreturns to the persisted setting, andstatusreports the effective mode, session override, tool state, and active-model image capability.inspect_image.enabledboolean with the tri-stateinspect_image.mode(auto|on|off, defaultauto). Inautothe tool is registered only when the active model lacks native image input, so vision-capable models (e.g.kimi-code/k3) read images inline with their own capabilities instead of delegating to a separate vision model; the tool set is re-evaluated on every model switch with a status notice when it flips. Thereadtool now follows the effective state dynamically rather than the raw setting, so it returns decoded image blocks again wheneverinspect_imageis hidden. Existinginspect_image.enabled: true/falseconfigs migrate toinspect_image.mode: on/off.effortparameter opt-in throughtask.enableEffort, which defaults to false and omits the field from flat and batch schemas and tool guidance until enabled.SetConsoleTitleWthroughbun:ffiinstead of OSC writes on Windows. Windows working titles now keep a static:separator instead of scheduling spinner updates; other platforms retain the animated separator.task.maxEffortto cap the task tool's optional per-spawn effort hint after model-specific resolution, so operators can enable effort hints without allowing them to exceed a configured ceiling; the ceiling now also rides into the spawned session so retry-fallback model swaps re-clamp to it instead of escalating past the cap (#6580, #6794 by @wolfiesch).<user_interjection>...<message>...</message>...wrapper around user text is now a<system-notice>explaining the interjection followed by the user's raw message unwrapped, matching the existing<system-notice>/<system-directive>convention instead of nesting the literal message inside its own tag pair, which some models found confusing.Fixed
/loginand the setup wizard with isolated browser sign-in and automatic session capture, supporting both secure-prefixed and unprefixed session cookies without manual cookie copying. (#12064 by @lance0)omp read skill://<name>failing withUnknown skillby discovering configured skills before resolving the URI (#10961).runningafter their final result is accepted; a finished run reaches a terminal state without the parent having to send a status message (#11079)./loopnever resubmitting after a/skill:<name>prompt: the loop prompt is now captured for skill invocations, and resubmitted skill prompts are dispatched the same way the composer sends them instead of as literal text./force:<tool>now reports that the current model cannot force a tool on hosts that only accept automatic tool selection (Meta Model API, Muse Code), instead of announcing a forced turn that the request silently drops (#11635 by @quantmind-br)./move, or re-rooting on resume when its directory is gone) into a project it lived in before no longer fails withENOTEMPTY; the two artifact directories are merged instead (#12035 by @sjawhar).sendUserMessage) no longer clear the composer draft; in-progress text and pasted images are preserved.--resume,--modeland the other dynamic value flags work again. (#12113 by @Huang-404-Q).gitdirectories and broken gitfiles no longer appear as the active project in the status line or agent instructions (#12105 by @bobbyhuang-dev).http/sseMCP server that drops while the session is idle (a restart, a redeploy, a laptop waking) now reconnects on its own with a backoff instead of staying disconnected until the next tool call or/mcp reconnect, so its resource subscriptions and notifications come back with it (#11803 by @sjawhar)./tannow waits for descendant results before returning its final answer and remains cancellable while waiting (#12090 by @ryxli).skill://resources (#10215)./pluginin the TUI andomp pluginson the CLI (#12092 by @XL-Lewis).models,status,rewind), which previously offered a command that ran the builtin instead of the configured handler (#12092 by @XL-Lewis)./compact(slash command, RPCcompact, extensionctx.compact()) issued while a turn is in flight now resumes that turn once the summary is committed, or immediately when there was nothing to compact — a queued steer/follow-up drives the resume, otherwise the same auto-continue nudge context-full compaction uses — instead of leaving the agent idle on a half-finished tool loop until the user types "continue". A prompt or extension-triggered turn that lands first takes the session instead.compaction.autoContinue: falsestill disables the resume; plan-mode "Approve and compact context" keeps dispatching its own execution turn (#11873 by @brndnmtthws).!commands now keep their transcript block mutable until queued PTY replay finishes, preventing successful and nonzero stdout/stderr from disappearing into immutable terminal history (#12062; #12080 by @Dante-dan).repeatGaphas elapsed (#12065 by @Dante-dan).model:frontmatter instead of always inheriting@default; only Claude Code-format plugins (declaring.claude-plugin/plugin.json) keep dropping their provider-specific aliases (#12028).--resume/--continuecombined with--no-sessionnow fail with--resume requires session persistenceinstead of silently starting a fresh empty session and discarding the resumed history (#12008).Could not resolve: "chalk"in hermetic installs (e.g.nix run) by importing chalk from the in-repo@oh-my-pi/pi-utils/chalkreimplementation instead of the undeclared npmchalkpackage (#12001).edit.modelVariantsand other model-dependent system-prompt policy going stale after an automatic retry or usage-aware fallback swapped the model, so a session that fell back to a variant-pinned model now rebuilds its prompt for the model actually serving the turn (#11983).omp auth-gateway servenow picks up credential logins and logouts made by another process within ~10s instead of serving its boot-time credential set until restart: broker-backed clients implementpollExternalChanges(), and the gateway polls it to reload credentials and rebuild its served catalog so a newly-logged-in provider becomes routable and a logged-out one stops being advertised and used (#11781).omp benchandomp if-benchrejecting models thatomp modelslists (e.g. llama.cpp, Ollama, LM Studio,models.ymlservers) by retrying model resolution through a live discovery pass when the local cache can't restore their credentials (#11598 by @yomgui1).omp --forkwith a missing session path now fails withSession "<path>" not found.instead of silently opening an empty parentless session (#11944 by @onlyysaurabh).omp read <mcp-resource>now waits for a still-handshaking MCP server to finish connecting instead of reportingNo MCP server has resourcewhen the connect outlasts the startup race (#11950).memory://rootis now advertised in URL completion only onmemory.backend=local, and reading it onhindsight/mnemopireports the file-backed root as local-only (pointing atrecall/reflect) instead of telling you to enable memories that are already enabled; the memory glob validator now names the expected form (memory://root/**) instead of echoing the rejected input (#11909).retry.maxDelayMs/retry.maxRetries), latching the quota-exhausted state only when the block is a genuine long quota window (#11947).display()values now stay bounded in session history while remaining available through output artifacts, preventing slow--resumestartup (#11920).<mental_models>block is frozen for the session lifetime (a background reflect applies to the next session;/memory mm reloadremains the explicit in-session refresh), and volatilelast_refreshed_atmetadata no longer enters the model-facing prompt (#11961)./extensionsnow shows an enabled context file as active when its higher-priority competitor is disabled (#11870).contextextension handlers append per-call messages (#11897).cwdis a secondary Git worktree no longer inherit the agent's ownGIT_DIR/GIT_WORK_TREEand related repo-location overrides, so a failed cherry-pick stays in the worktree where it ran instead of contaminating the primary one (#11082).hub startfailing with a rawconnect ENOENT …/broker.sockwhen the project daemon broker's lease was stale: the lease is now a process-owned lock the OS releases however the broker dies, a stale lease no longer blocks startup, and a broker that still cannot start reports its scope path plus recovery commands (#11080)./pintoggles from multiple omp instances silently dropping each other's pins, and crashes mid-write corrupting the pins file.ExtensionExitErrorunhandled-rejection storm (#11789).@earendil-works/pi-coding-agentshim now exportsfindCutPoint(adapted to upstream Pi's tokenizer-less 4-arg signature) andsessionEntryToContextMessages, so extensions targeting upstream Pi 0.84.2's compaction/session APIs (e.g. NVlabs/SoL-Pi) install instead of failing validation (#11796).writenow rejects exact incomplete read projections before they can replace and truncate an existing file (#11792).omp read <image>?q=<question>no longer fails with "Model registry is unavailable for image questions."; the read CLI now wires a model registry so image questions resolvemodelRoles.vision/@defaultlike the agent (#11338).undefined is not an object (evaluating 'e.identity.class')as soon as the model started thinking when an extension provider projects its own catalog throughoauth.modifyModels(pi-provider-kiroand friends); projected models are now materialized like every other catalog source.agent.dbsettings rows are deleted after a successfulconfig.ymlmigration write, so deletingconfig.ymlno longer silently resurrects stale values (#11568)./vibeworkers) that write their report in one turn and then finalize with a data-lessyieldin the next no longer come back asSYSTEM WARNING: Subagent called yield with null datastapled to accumulated narration. The finalize now harvests the last turn that actually reported — prose with no further work started — so mid-run narration can never surface as a final result either (#11746 by @oldschoola)./forceand other forced tool choices refusing every OpenRouter model:buildNamedToolChoicedid not recognise theopenrouterapi. Models whose compat disables tool choice or forced tool choice now report forcing as unsupported instead of queueing a choice the transport discards (#11658 by @datrixlab).baseUrloverrides now scope by API: custom models inheriting the provider URL define which APIs it covers (a provider-levelapicovers override-only providers),transport: pi-nativekeeps its gatewaybaseUrlprovider-wide, and a bundled model no longer routes to another API's endpoint (#11608 by @danilouchoa).AgentSession.waitForIdle()returning before successful retry recovery events and persistence had settled.retry.fallbackChainswhen the tiny/smol primary returns a provider error, instead of failing the background task while the main turn still has a fallback chain.retry.modelFallbackis disabled.retry.fallbackChainsafter that model fails, without merging tiny/commit/smol role defaults onto it (#10938)./exportHTML now renders bold inline code inside ordered-list items followed by fenced code blocks instead of displaying literal<strong>and<code>tags (#11690).Plan mode is paused — run /plan again to fully exit.instead of the staleExit plan mode first.(#11692).omp plugin install <name>for npm packages now bypasses bun's manifest cache, so a reinstall picks up a newly published version instead of a stale one, and installing an explicit<name>@<version>no longer fails to resolve a version that exists on the registry (#11634).argument-hintfrontmatter as inline autocomplete ghost text and ACPinput.hint, not only in the/extensionsinspector (#11647).sourceInfoprovenance thatgetAllRegisteredTools()consumers read (#11661).openai-responses/openai-codex-responsesproviders can now setcompat.supportsConfigurationUpdate: falseinmodels.ymlso auto-thinking effort changes ongpt-6-astraare sent as the top-levelreasoning.effortinstead of aconfiguration_updateinput item the endpoint rejects with HTTP 400; the key is validated as a boolean and documented (#11121).always-askwith an empty policy map (no user grant) instead of silently resolving asyolowith empty policies. The former copies (ExtensionToolWrapper.execute, CursorrefuseByWritePolicy,mcpApprovalPreflight, and eval prelude host calls) share one helper so they cannot drift. A session-bound wrapper that is invoked without context still inherits that session's settings (#10362).agent()after the session reaches its subagent recursion-depth limit.omp config setinstead of silently disappearing (#11579).ast_edit,search, andast_grepno longer fan out into overlapping scans whenpathsmixes a directory with a file inside it and the directory is spelled as an absolute path;ast_editpreviously applied each rewrite twice to the nested file (corrupting it, e.g.wrap(wrap(log(1)))) or reported a spurious stale-preview error (#11584).ls, and redirections) now resolve/tmpto the system temporary directory instead of a drive-roottmpdirectory (#11603)./restartand worker spawning failing with ENOENT after package managers prune the unlinked previous version directory during an upgrade (#10873).Tool <name> not foundresult instead of discarding the whole turn; only hazardous output is still quarantined, and the repeated-quarantine latch is gone.omp plugin install --dry-runnow previews marketplace installs without mutating plugin state.omp sharenow reports missing session paths instead of creating and publishing empty sessions (#11483).omp gc --blobsno longer deletes image blobs still referenced by a session stored via--session-dir/--session, including exact paths without a.jsonlsuffix; relocated transcript files are now recorded in a persistent registry the blob reachability scan reads (issue #11551).--exportnow reports missing input files instead of creating empty sessions and successful transcript-less exports (#11481).AgentLifecycleManager.global()now rebinds to the current global registry after a loneAgentRegistryreset, so a test that resets only the registry can no longer strand the lifecycle manager on a dead instance and hang the collab kill path (#11432).advisormodel roles now honor the configured@slowfallback without inheriting an unconfigured primary model (#11428).set_auto_compactionandset_auto_retryRPC commands are now session-scoped likeset_thinking_level, so a short-lived RPC client no longer silently writescompaction.enabled/retry.enabledto the machine-globalconfig.yml(#11431).omp updatenow bypasses mise'sminimum_release_agegate when updating via mise, so a fresh release published within the freshness window (24h by default) installs instead of being silently skipped (#11316)./moveor cross-project resume completing before memory was rebound, so the next prompt could recall and retain against the previous project's Hindsight bank, the destination project'smemory.backendand Hindsight server were ignored, and a failed rebind was reported as a successful move. Cwd rebinding drains Mnemopi extractions without auto-retaining the transcript during move or rollback, and rejects moves when destination Mnemopi startup fails./moveand/wt.model:lowselector no longer matches a configuredmodel:maxkey (or vice versa), so a 429 retry stays on the same effort instead of escalating to an unrelated chain (#11192).computer.capabilities()returningundefinedwhen called before anycomputer.run; the direct helper now fetches fresh backend and permission state from the desktop worker instead of a run-populated cache (#11169).node_modulessymlink, so a later registry install cannot continue running the linked checkout (#11172)./skill:submission rendering two identical skill cards when the optimistic row retired into scrollback before the canonical message arrived during a slow preflight (#11217)..astrofiles rendering without syntax highlighting in write/edit previews and diffs: a vendored Astro grammar now highlights the---frontmatter and{…}template expressions as TypeScript and the template as HTML, instead of treating the whole file as HTML text (#11164 by @byigitt).mnemopibackend persists a memory, covering theretain/learntools, the automatic transcript retention path, andmemory_edit update. Previously only thelocalandsharpshooterbackends redacted, so a token pasted into a session could be stored verbatim and handed to any provider by a laterrecall./tanforking a mid-turn parent leaving the clone showing the parent's in-flight tool call as its own unresolved work: the fork now pairs the parent's unresolved tool call with a synthetic aborted result so the clone inherits a terminal, well-formed transcript (#11118)./tankeeps its assigned request after automatic compaction instead of returning an empty-request question (#11119).plugin doctornow flags a plugin whoseomp-plugins.lock.jsonversion differs from the version installed innode_modules, instead of reporting the stale copy healthy;--fixreconciles it by reinstalling (#11090).plugin upgradeon an npm-installed plugin (e.g. a scoped@scope/pkg) now points toomp plugin install <pkg> --forceinstead of the opaque "Expected name@marketplace" parse error (#11090).plugin install --forcenow forwards the force request to Bun so stale cached package contents are actually replaced (#11090).retry.waitForUsageResetscheduling Z.AI and Zhipu resets eight hours late when provider responses omit the reset timestamp timezone (#11014).var fs = await import("node:fs/promises")) now persists across cells instead of silently reverting to the injected value on the next cell (#10988).always-ask/writeapproval modes leaving a granted tool call stuckpending: an approved permission now runs the tool instead of re-prompting through the interactive gate that ACP clients cannot answer (#10850).HexRaysSA/claude-marketplaceinstall and update instead of failing withMissing or invalid field "name"(#10827).agent()wait no longer re-emits the same settled progress snapshot as duplicate status events.context7(mcp__context_query_docs→mcp__context7_query_docs) and collapsed servers differing only by a digit onto the same tool names, costing one of them a tool (#10179 by @bitboxx). Usertools.approvaldeny/promptpolicies written against the old digit-stripped names keep applying to the renamed tools;allowentries and exact (non-glob)tools.xdevInlineDevicespatterns need updating to the new names.omp --help | head,omp --version | true,omp <command> | grep -m1) crashing with a fatalEPIPE: broken pipe, writewhen the stdout consumer closed early; a vanished stdout peer now exits cleanly like any other Unix tool (#10930).RULES.mdand other discovered rules are now re-read from disk on/clearand/new, so rules created or edited while omp is running take effect on the next session reset instead of only after a restart (#10940).Read artifact://<id> for full output) when the raw stream was mirrored, matching the tail-truncation notice (#10877).bytesfor streamed bash/eval output,charsforread/grep— instead of always claimingchars, which overstated visible content for multibyte text (#10888).bytesfor streamed bash/eval and grep output,charsforread— instead of always claimingchars, which overstated visible content for multibyte text (#10888).modelRolesentry that references another role (e.g.fast_worker: "@task") now resolves to the referenced role's model even whenretry.modelFallbackis disabled (#10853).app.tools.expand) in theaskdialog only expanding a truncated question header: it now also expands truncated option descriptions in place.--continueresuming a session stored outside an explicit--session-dir, and a breadcrumb recorded for a different session directory suppressing session lookup inside the requested one.Otheroption are answered before the original choice is shown again (#10672 by @Giardi77)./collabhiding the join URL when the QR code is clipped: the one-line fallback now includes the browser link, and the status heading keeps that URL on its first row so transcript pressure cannot drop it.credential_pinsha-256 of the account + org/project scope, so exports carry no plaintext identity) and re-pinned on resume with the session's effective last-use time, so a fresh process no longer re-ranks accounts by usage headroom — which systematically routed away from the just-used account and cold-missed the entire account-scoped cache prefix. Sticky routing was previously stored only in the auth store's KV cache, which is in-memory when a remote auth broker is configured.credential_pinhash) and re-pinned on resume, so a fresh process no longer re-ranks accounts by usage headroom — which systematically routed away from the just-used account and cold-missed the entire account-scoped cache prefix. Sticky routing was previously stored only in the auth store's KV cache, which is in-memory when a remote auth broker is configured.createAgentSessioncalls with the default agent id failing initialization withAgent "Main" was replaced during session initialization— each in-process embedder (e.g. the edit benchmark runner) can now pass a private registry via the newly exportedAgentRegistry, keeping every top-level session's "Main" out of the process-global roster race./tanagents being unable to read parent-sessionlocal://attachments by correctly resolving local protocol options against the parent session's artifacts.xd://device summaries containing control characters and exceeding size budgets by stripping control characters and bounding summaries by UTF-8 bytes.task.softRequestBudgetconfiguration having no effect on bundled scout and sonic subagents.Clocale to ensure predictable, non-interactive command output.xd://mount notices and prompt-cache invalidation when resuming sessions or reconnecting devices.omp ttsr testsilently evaluating source files as prose when their extensions were missing from the allowlist, and expanded the allowlist to support .NET, Shell, SQL, Zig, Dart, Scala, Elixir, and Protobuf files.retry.maxDelayMsnot being forwarded into Anthropic retry handling, so over-budget server retry delays fail fast.get_stateresponses for non-TUI clients.set_fast_modecommand and typed TypeScript/Python client methods for live fast-mode control.fastModeEnabledandfastModeActiveto RPCget_stateresponses.speed: "fast", while allowing explicit re-enable requests to retry priority service.checkpoint,rewind,learn, andmanage_skillwhen explicitly listed in an agent definition'stools:frontmatter. Listing one ofcheckpoint/rewindauto-includes the other. Settings (checkpoint.enabled,autolearn.enabled) remain master toggles.browser.cdpUrlsetting that points browser automation at an already-running CDP endpoint by default, soapp.cdp_urlno longer has to be repeated on every call. Explicitappoptions still take precedence.pi_read'soffset/limitwere ignored, so a ranged read returned the whole file;pi_grep'sliteralwas ignored, so a fixed-string search ran as a regex and matched the wrong lines; and the path/glob join produced a./-prefixed spec. Ranges are now composed ontoread's:N+Kinline selector, literal patterns are escaped, and the join usesnode:path. These areoptional int32fields, so a present0is honored rather than folded into a default:pi_readwithlimit: 0answers with empty output instead of the entire file, andpi_findwithlimit: 0clamps to 1 the way the reference client does.pi_grep'scontextandlimitare honored. Neither is expressible in the model-facinggrepschema — context width comes fromgrep.contextBefore/grep.contextAfterfixed at tool construction — so the bridge builds a per-callgrepfor frames that supply them.GrepToolaccepts these as constructor options; the model-facing schema is unchanged, and a frame that supplies neither keeps the shared instance and the session's defaults.pi_ls'slimitis still not mapped, now deliberately: it caps directory entries, while the localreadtool renders a depth-2 tree with per-directory caps and elision rows and applies a selector as a rendered line slice. Mapping it to:1+Kwould cap a different unit while appearing honored.pi_editframe failing instead of editing. Two independent causes: the session dropseditfrom the tool registry for Cursor so the model uses full-filewrite, but that registry is also the exec bridge's tool source, so the native frame — which the server sends regardless of the advertised catalog — found no tool; and the retained instance followed the session's configured edit mode, whilePiEditExecArgscarriesold_text/new_textpairs that onlyreplaceaccepts (the defaulthashlinetakes a singleinputstring). The bridge now resolves areplace-mode instance through its fallback resolver, still wrapped for approval.pi_grepframe carryingcontextorlimitescaping the approval gate. Honoring those fields needs a per-callgrep, and the per-call instance was built raw while every registry tool is wrapped, so such calls bypassedtools.approval.grepand the exec-tier check for SSH-targeted paths. Both bridge callsites now build it through one shared factory that applies the same wrapper.pi_grep'scontextandlimit. Only the primary session supplied the per-callgrepfactory, so advisor frames silently fell back to session defaults. Advisors now receive the same factory, gated on the advisor actually having been grantedgrep.pi_edit. The advisor roster handed the bridge theeditinstance built for the advisor's own loop, which follows the configurededit.mode(hashlineby default) and rejects the frame'sold_text/new_textpairs — the same mode mismatch the primary bridge already fixed, on the path it missed. The exec map now substitutes areplace-mode instance, gated on the advisor actually having been grantededit, while the advisor's own loop keeps the tool it was given.pi_bashkilling commands that explicitly asked for no deadline.timeoutisoptional int32andbashdocuments0as "disables the command deadline", but a truthiness check folded a supplied0into unset, applying the 300s default instead. A present0now passes through; negatives, which have no local meaning and would otherwise clamp to the 1s floor, still fall back to the default.editandgrepto sessions that withheld them. Both bridge-only tools are constructed rather than looked up, andexecuteToolprefers a constructed override over the registry, so a restricted tool set (toolNameswithout them, orrestrictToolNames) still got a workingpi_edit/pi_grep— native frames arrive regardless of the advertised catalog. Both are now gated on the session having actually granted the tool, matching thedeleteframe's existing check (issue #5680).pi_edit/pi_grepinstances are approval-wrapped, but the wrapper readstools.approvalMode, per-tooltools.approval.<tool>policies andautoApproveonly from the execute-time tool context — which the advisor bridge never supplied, so every native advisor frame resolved asyolowith empty policies and ran past a configuredaskordeny. Advisors now receive the same context store as the primary bridge.list_mcp_resources/read_mcp_resourceframes answering as though the client hosted no MCP servers. The bridge hardcoded an empty catalog andnot_found, so resources from servers the session held live connections to were invisible to the model even while the same session read them throughmcp://. Both frames now answer from the session'sMCPManager— awaiting a server's background resource discovery rather than reading the not-yet-populated cache and reporting "advertises nothing" — and a lookup failure surfaces as an error rather than an empty catalog, which would read as "asked, none exist". A read carryingdownload_pathwrites the resource to that path and answers with the path alone, per the wire contract, instead of putting the payload back in the model's context. That path arrives from the server while the general-purpose resolver deliberately honors absolute paths and.., so downloads are confined to the workspace: the resolved target and its deepest existing ancestor must stay inside it, and a target that is itself a symlink is refused. The write then opensO_NOFOLLOWand refuses a non-regular or hard-linked file before truncating, so the final component cannot be swapped for a link or an inode shared outside after the check. A parent directory replaced by a symlink mid-write is still followed; closing that needsopenat/dirfd walking, which this does not attempt.deleteframe bypassing approval settings. Unlike every other frame it removes the file directly instead of running a registry tool, so no approval wrapper sat in front of it — the bridge'sallowDirectFileMutationgrant answers whether a mutating tool was granted, which is a different question from whether the user's policy allows the call. A configuredtools.approval.delete: deny, or analways-asksession that this channel cannot prompt in, now refuses the frame and keeps the file.read_mcp_resourceframe carryingdownload_pathcreates and overwrites workspace files without running a registry tool — the same hole the nativedeleteframe had — so a session that withheldwrite/edit, or one whosewritetier isdeny/always-ask, still had files written. Both frames now share one grant (allowDirectFileMutation, renamed fromallowNativeDeletenow that it gates more than deletion) and onewrite-tier policy check, and the download refuses before the read so a blocked call does not fetch the resource either. The primary session derives that grant before it rewrites its registry: Cursor moveseditout of the tool map andwritemay be auto-registered later, so reading the map at bridge-construction time would have misjudged both.pi_lsnever reporting that a listing was clipped. The bridge read the entry cap from a flatdetails.resultLimitReached, whichglobsets butread— the tool servingpi_ls— does not: it records the cap throughOutputMetaatdetails.meta.limits.resultLimit.reached. Every capped listing therefore reached Cursor withentry_limit_reachedunset, reading as complete. Both shapes are now checked, the same way the truncation translation already handles its two producers.image/png. Each branch now reports the type of the part it actually sends.pi_read'soffset/limitreturning more lines than the frame asked for. The range is composed onto the localreadtool's inline selector, and a plain:N+Kdeliberately pads with one leading and three trailing context lines — helpful when a human reads a snippet, wrong for a caller that named an exact range: offset 5/limit 20 handed Cursor lines 4-27. Ranged Pi reads now compose:raw:N+K, which slices exactly the requested lines.pi_grepreturning fewer matches than it asked for when they spread across many files. The localgrepwindows results to the first 20 files and tells the caller to paginate withskip, butPiGrepExecArgshas noskipfield — so a frame asking for 100 matches over 25 one-match files got 20,match_limit_reachedunset, and advice it could not act on: output silently short and labelled complete. A search carrying a total match cap now reads enough files to satisfy it (cap+1, so a result landing exactly on the cap is distinguishable from a clipped one) and reports the cap when it actually bites.pi_editfailing after a session switched onto Cursor. The replace-modeeditinstance the frame needs was built only for sessions created on Cursor, and the tool roster is not rebuilt on a model switch — so a session that started elsewhere kept its configured-modeeditin the registry, which the bridge resolves before its fallback, and the frame'sold_text/new_textpairs failed validation against ahashlineschema. The instance is now built from theeditgrant regardless of the session's initial provider (lazily, so a session that never reaches Cursor never constructs one) andpi_editasks for it explicitly through a dedicated accessor. A session that was never grantededitis still refused.edit. That resolver doubles as the agent loop's fallback for any call outside the advertised set, so servingeditfrom it meant a hallucinated call — or one naming a tool the session deselected after startup — could run a replace-mode edit the model was never offered. It is device-only again;pi_edituses its own accessor.readframe ignoring theoffset/limitmodern builds paginate with. Only the Pi variant composed a range, so every page of a legacy read returned the whole file (or its own truncation) and a model walking a large file never advanced past the first window. Both frames now translate a range through the same helper, and the answer setsrange_appliedto describe whether a window was actually composed.grepframe ignoring its paginationoffset. The localgreppaginates by file throughskipand advertises exactly that in its own "use skip=N" advice, so an unforwarded offset re-ran the identical search and answered page one for every page. The answer now reports the offset it applied inoffset_applied.readorgrepframe being recorded as an unpaginated one. The executed call and the transcript block are built separately, so forwarding the frame's range and page fixed only the execution: the block still showed a bare path and an unskipped search, which is what a reloaded session replays and what the next turn reasons from — a slice of a file presented as the whole thing, and results from a later window presented as page one. Both are now synthesized from the same translation that runs them, including alimit: 0read, which is recorded as the zero lines it returns rather than a whole-file read.MCPManager-backed resource adapter, so an advisor'slist_mcp_resourcesreported an empty catalog and itsread_mcp_resourceanot_foundeven though the advisor shares the session's live connections. Advisors now receive the same adapter; it is not gated on a tool grant, since reading what a server advertises is a different permission from calling one of its tools.pi_write,pi_bash) run those instances directly — so an advisor grantedwriteorbashexecuted them regardless of a configuredaskordeny. They now carry the sameExtensionToolWrapperas every other tool.mcp_notificationextension event and multi-listenerMCPManager.addNotificationListenerAPI. The runtime already received MCP server-initiated JSON-RPC notifications at the transport layer but had no path to forward them to extensions; every notification (including server-custom methods) is now delivered as{ server, method, params }after the manager's own list/update handling. For known list-change methods (notifications/tools/list_changed,notifications/resources/list_changed,notifications/prompts/list_changed) the internal refresh promise is awaited before fanout, so a listener acting ontools/list_changedsees freshgetTools(). Notifications received before any listener attaches are buffered (bounded FIFO, cap 100, drop-oldest — matchesIrcBus'sMAILBOX_CAP) and drained into the first subscriber, so startup-time frames aren't lost even if the extension binds after MCP discovery. Extensions can use this to bridge push-capable MCP servers (e.g. peer messaging) into session behavior by injecting a mid-turn steer viapi.sendMessage/pi.sendUserMessage./treenow re-attaches the images to the composer draft: previously only the text (with its[Image #N]markers) was restored, so resubmitting sent the literal marker with no image.Read artifact://N for full outputwhile the footer saidArtifact: N+1. The streaming sink's head and tail windows each had a full budget, so a middle-elided inline body could reachheadBytes + spillThresholdand always re-tripped the final-defense inline byte cap, which truncated a second time (two elision markers), saved a duplicate already-truncated artifact, and left the notice's line ranges stale. The head and tail windows now share the spill-threshold budget (head clamped to half), the cap budget derives from the configured threshold plus notice slack, and when the cap does fire on a sink-spilled result it references the existing raw artifact instead of saving a copy.foowithenabled: falsekeeps the user-levelfoooff while still not starving a differently-named equivalent connection.readandomp readnow resolve server-advertised native resource URIs such asags://capabilities/current-host, while preserving the existingmcp://<resource-uri>form./(e.g.catalog://root/) are now preserved byte-for-byte instead of losing the trailing slash to reconstruction; opaque resource URIs (urn:example:document,custom:item) are recognized by thereadandomp readresolver gates instead of falling through to filesystem handling; and a failingresources/templates/listno longer discards a successfulresources/list, which previously produced a false missing-resource error.languageId: "plaintext"for extensions outside the built-in language map by honoring an optional per-serverlanguageIdinlsp.jsonfor disk and in-memory document opens (#6800).dialogOptions, and cancelled handler-owned dialogs when the extension watchdog times out so stale approval UI cannot outlive a blocked tool call (#6805).ctx.modelgetter, so a handler callingpi.setModel()and then readingctx.modelsaw the stale model; the scoped context now delegates to the base context instead of spreading it.$commands and the eval tool) leaking runner-internal traceback frames. Cell syntax errors now render as the bare caret display with a<cell>filename instead of a_handle_request_async/ast.parsestack dump, and runtime tracebacks start at user code, matching the Ruby runner's user-frame filtering./usageand the other large transcript command panels (/session,/advisor status,/jobs,/changelog,/context,/memory view) duplicating in native scrollback when invoked while an agent turn is streaming. These callsites mounted their finalized panel immediately viapresent()instead of deferring it until the turn ends viapresentCommandOutput()(the path added in #5427 for/tools//mcp), so the panel landed above a still-growing live block and was recommitted lower down (#6767).ModelRegistrywhen restricted sessions intentionally skip extension loading (#6783)./livesideband WebSockets ignoring standard proxy environment variables andNO_PROXY, which left proxied sessions stuck while the rest of the Codex connection succeeded (#6770).killbuiltin rejecting numeric signals and multiple process operands, stopping after the first failed target, and defaulting toSIGKILLinstead of the standardSIGTERM. Negative PID operands (process groups perkill(2)) and the--end-of-options marker are now handled instead of being misparsed as signals (#6779).learned.mdsaves growing a blank line on every write (trailing-newline split artifact) and hoisting all headings/prose above all bullets, which re-scoped lessons under the wrong heading in hand-organized files. Saves are now byte-idempotent and preserve mixed Markdown ordering: non-list lines keep their positions, new lessons insert newest-first at the head of the first bullet run, and dedupe/cap operate on bullet lines in place.globrejecting safememory://root/<directory>/**patterns. Memory globs now resolve their directory prefix inside the project memory root while rejecting traversal and percent-encoded path separators across the complete glob path.omp --resume <id>prompting to fork sessions from another existing directory instead of switching the process and cwd-scoped settings into the resumed session's recorded directory (#6752).EPIPE: broken pipe, writewhen an LSP server closed its stdin between filesystem mutations; LSP writes now observe asynchronousFileSink.write()failures and route them through the existing request/notification failure path.statbuiltin failing on native Windows withstat: unsupported on this platform(exit 1) for every invocation. The vendoreduu-statnow ships a Windows-native backend that maps the GNU format directives ontostd::fs::Metadata, thewindows_by_handlemetadata extensions (inode, hard-link count, and device viaGetFileInformationByHandle), and the Win32 volume APIs for--file-systemmode; Unix behavior is unchanged (#6723).assistant removal missedbut the retry still scheduledcontinue(), which rejected the terminal assistant error message locally (Cannot continue from message role: assistant) before any provider request —auto_retry_endnever fired, the TUI kept showing retry progress, and the in-flightprompt()hung until a manual follow-up. The retry path now strips a still-failed assistant tail positionally after the backoff, and a continuation that still fails locally closes the retry saga with a failedauto_retry_end(#5382).config.ymlfiles being treated as empty settings and then overwritten by the next setting change, which could permanently erase broker tokens, model roles, and provider configuration. Invalid YAML is now moved to a timestamped.broken-*backup, read failures abort without touching the source, pending changes remain retryable with the last successfully loaded settings, atomic writes preserve symlink targets and handle WindowsEPERMreplacement, concurrent startup failures are fully observed and quarantine races fail closed, andomp config set/resetwaits for persistence before reporting success.xd://route map for every live mounted MCP tool—including servers without initialize instructions—and refresh it as catalogs change without disabling schema virtualization.inspect_imageblocking indefinitely when the vision-model API stalls by combining the caller's abort signal with anAbortSignal.timeout()and surfacing a distinct timeoutToolError(separate from user-triggered abort) (#4165).omprefusing to start on Windows when nobash.exeis discoverable — most visibly with scoop-installed Git, whose manifest shimssh.exe/git.exebut neverbash.exe, so PATH lookup missed it. Startup threwNo bash shell foundwhile merely building the bash tool description, even though bash tool commands always execute in the embedded brush-core shell and need no host bash. Shell discovery now also checksGIT_INSTALL_ROOT, scoop and per-user Git for Windows install roots, andsh.exeon PATH, then falls back tocmd.exefor the spawn-only paths (interactive PTY, ACP client terminals) instead of failing; the cmd fallback is never used to wrap user-shell commands — brush runs the POSIX line directly./liverealtime sessions (#6566).lfm2-350m,lfm2-700m,qwen3-0.6b,qwen2.5-0.5b,gemma-270m) now migrate to their closest current models instead of silently skipping session titles.Removed
MCPManager.setOnNotificationsingle-slot setter, which had no callers in the runtime. Replaced byMCPManager.addNotificationListener— multi-listener, per-listener error isolation, returns an unsubscribe function.@oh-my-pi/collab-web
Fixed
@oh-my-pi/pi-mnemopi
Fixed
@oh-my-pi/pi-natives
Added
maxBytestoVcsGitRepo.diffTextoptions: rendering stops and the call rejects with anOutputTooLargeVcsError once the patch crosses the cap, so callers can bound the memory a large change set may consume (#11454 by @sjawhar)..gitdirectory (noHEAD) as a checkout, which made/wtand isolated tasks fail with a raw "No such file or directory (os error 2)" instead of reporting that no Git repository was found. Discovery now skips such entries and keeps walking toward the root, matchinggit rev-parse.vcsDiscoverForDisplay(repoForDisplay): like repository discovery, but equal-root jj+git ties prefer Jujutsu for the status line and footer. Git-safe automation must keep usingvcsDiscover(#11071, #11325 by @boazy).Changed
Fixed
GIT_DIR,GIT_WORK_TREE, and related repo-location overrides from the host process, which madegitrun in a secondary worktree mutate the primary one (#11082)..astrofiles highlight the---TypeScript frontmatter and{…}template expressions instead of falling back to plain HTML (#11164 by @byigitt).$CC(#11869 by @Malix-Labs).@oh-my-pi/omptype
Added
trim(),superRefine(), and one-argumentrecord()support to the Zod compatibility facade (#12011 by @bnivanov).@oh-my-pi/snapcompact
Changed
historyBlocks()now resolves persisted frame payloads lazily, keeps the newest frames within a byte budget, and drops unresolved blob references instead of sending them to providers (#10227 by @lemonleks).@oh-my-pi/omp-stats
Fixed
omp statsblocked by an opaque Bun listener.@oh-my-pi/pi-tui
Added
Editor.deleteCharForward()exposes thetui.editor.deleteCharForwardoperation to hosts that resolve the chord themselves, applying the same transient-state teardown the key dispatch does (pending character jump, spelling-assist popup) and routing through Vim'sxin Normal and Visual modes.Changed
Fixed
CSI Hwith absolute addressing while the application writes nothing, and re-homes the cursor, so the reply reports column 1 and can never be attributed to its probe tag. ConPTY sessions now keep the alternate-screen borrow, whose settled transaction ends in theResizeScrollbackModerebuild, and skip that unattributable anchor probe — except inside a multiplexer, which answers the DSR from its own grid, and underPI_TUI_RESIZE_IN_PLACE=1, which restores the whole pre-change path (#11625 by @bse-ai).WT_SESSION, which caused streaming repaints to overlap when Tabby's terminal chain mishandled DEC 2026.WMUX/WMUX_SURFACE_ID) so its panes take the in-place viewport repaint path instead of the direct-terminal scrollback path.@oh-my-pi/pi-utils
Added
postmortem.exitProcess()utility for host-owned hard exits that must bypass temporary process-exit guards (#11789).readSseJsonOrText: likereadSseJson, but adata:frame that is not valid JSON is yielded as its raw text instead of raising aSyntaxError, so a consumer can classify a reverse proxy's plain-text throttle page (429 Too Many Requests) that arrives after the stream headers were already sent.readSseJsonis unchanged and shares the framing with it.Fixed
filterChildShellEnvforwarding the host process'sGIT_DIR,GIT_WORK_TREE, and related repo-location overrides to child shells, wheregitwould ignore the command'scwd.closed, so in-flight methods such assession/newstill receive a success or explicit error response instead of being dropped on exit 0 (#11567).waitForUsageResetsessions resume up to eight hours late while preserving longest-window semantics for naive UTC timestamps (#11014).registerStdioDisconnectHandling()now drives graceful shutdown fromprocess.stdout's ownerrorevent, so a closed stdout consumer exits cleanly while an unrelated write EPIPE (subprocess stdin, socket) stays fatal (#10930).ptreetimeout cleanup occasionally leaving session-escaped descendants running during subreaper adoption.What's Changed
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate CLI.