@oh-my-pi/pi-agent-core
Added
- Added
shakecompaction primitives (collectShakeRegions,applyShakeRegion,applyShakeRegions,summarizeShakeRegions,DEFAULT_SHAKE_CONFIG,AGGRESSIVE_SHAKE_CONFIG, plus theShakeRegion/ShakeConfig/ShakeSummaryItem/ShakeSummaryComplete/ProtectedToolMatchertypes) under@oh-my-pi/pi-agent-core/compaction. These detect heavy context regions — whole tool-call results plus large fenced/XML blocks — and either elide them with placeholders or extractively compress them through an injected completion backend (no LLM summary cut-point). The compressor is provider-agnostic: callers wire it to a local on-device model. Pure detection/mutation; no I/O.
Fixed
- Fixed tool-output pruning and shake protection for
read: ordinary file/URL reads are now eligible for compaction, whilereadcalls whosepathstarts withskill://remain protected like nativeskillresults.
@oh-my-pi/pi-ai
Changed
- Throttled per-delta streaming JSON re-parsing of OpenAI Responses/Codex tool-call arguments (bounding mid-stream parse cost from O(N²) to O(N)). Finalization via
response.output_item.donenow writes the authoritative full arguments back to the persisted assistant-message block, so tool calls finalized without a trailingresponse.function_call_arguments.doneno longer retain stale/empty ({}) arguments. (#1507)
@oh-my-pi/pi-coding-agent
Added
- Added support for decimal and
k/msuffix turn-budget directives, enabling budgets like+1.5kand+2min eval message parsing - Changed eval budget resolution to honor a user
+Nkdirective over an active Goal Mode limit while falling back to Goal Mode when no per-turn ceiling is set - Added
agent()eval optionsagent_type/agentType,model,context, andlabel, and returned structured JSON whenschemais provided in JS and Python eval cells - Added a live, Task-tool-style progress tree for eval
agent()calls, drawn below the notebook (code cell) box. Each subagent surfaces as a status line (icon · id · tool count · context · cost, plus duration on completion) with its current tool/intent while running, and updates mid-execution rather than only at the cell's final result. Progress events coalesce per subagent id so the persisted event list stays bounded across many throttled ticks. - Added
agent()to theevalruntime so JS and Python cells can spawn one subagent through the existing task executor; JS eval also gained boundedparallel()andpipeline()helpers for orchestrating subagent calls. - Added a
workflowmagic keyword (mirrorsorchestrate/ultrathink): the standalone word glows amber→green in the editor and appends a hidden notice steering the model to author deterministic multi-subagent fan-outs ineval(agent/parallel/pipeline). Matching is whitespace-delimited and case-sensitive (lowercase only); the singular and plural both trigger, but capitalized forms, inflections likeworkflowed, and path-embedded occurrences likeworkflow.tsdo not. - Added
parallel()andpipeline()to the Pythonevalruntime (thread-pool over the synchronousagent()bridge), mirroring the JS helpers: bounded pool (default 4, max 16), input-order preservation, a barrier between everypipelinestage, and contextvar propagation soagent()works inside worker threads. - Added
log(),phase(), and abudgetobject to bothevalruntimes (Python and JS).log/phaseemit progress/phase status lines;budget.total/budget.spent()/budget.remaining()/budget.hardexpose a real per-turn output-token budget. A+Nkdirective in the user's message sets an advisory budget (the model self-limits viabudget.remaining());+Nk!(or an active Goal Mode budget) makes it a hard ceiling that blocks further evalagent()spawns once reached.budget.spent()counts output tokens spent this turn across the main loop and all eval-spawned subagents. - Added search support for virtual internal URLs (including
omp://roots) by resolving and scanning in-memory internal resources as search targets alongside filesystem paths - Added expansion of virtual internal URL search targets so
searchcan match multiple internal documents when givenomp:// - Added
/omfg <complaint>slash command that drafts a TTSR rule from a complaint, validates it against the current conversation, saves it to project or~/.omp/agent/rules, and registers it live. - Added
/shakeslash command and theshake/shake-summarycompaction strategies that reduce context by mechanically dropping heavy content instead of LLM summarization./shake(alias/shake elide) strips heavy tool-call results and large fenced/XML blocks, offloads the originals to one session artifact, and leaves a recoverableartifact://<id>placeholder;/shake summarycompresses the same regions with a local on-device model (providers.shakeSummaryModel, defaultqwen3-1.7b) and falls back to elide per region when the model is unavailable;/shake imagesstrips image blocks. Auto-maintenance honors theshake/shake-summarystrategies (16k protect window); on context overflow a shake that reclaims nothing falls back to context-full summarization. - Added
providers.shakeSummaryModelsetting selecting the local on-device model used by/shake summaryand theshake-summarycompaction strategy. Runs entirely on-device (downloads on first use) and never calls a remote/cloud LLM.
Changed
- Changed the eval cell
timeoutfrom a hard wall-clock deadline to an inactivity (idle) budget: a cell is now interrupted only after going the full window with no progress signal, and every status event —agent()progress snapshots,log()/phase(), and tool-bridge activity — re-arms the watchdog. Longagent()/parallel()fanouts that keep reporting progress no longer time out mid-run (previously the kernel was killed at the fixed deadline even while subagents were actively progressing). Rawprint/stdout does not reset the watchdog, so pure-compute runaway loops stay bounded; the timeout is driven entirely by the abort signal, so neither runtime arms a competing fixed timer. - Fixed turn-budget parsing to match
+Nkdirectives only at token boundaries, preventing values likeversion 1.2.3,c++, and+500kfoofrom triggering a budget rule - Changed overflowing provider, hook-option, branch-message, agent, extension, and session-tree pickers to support fuzzy type-to-filter search.
- Changed Shift+Ctrl+P to cycle role models backward instead of cycling forward without persisting.
- Changed empty prompt input so
?inserts a literal question mark instead of opening/hotkeys; use/hotkeysexplicitly for the shortcut reference. - Changed
searchoutput to preserve full virtual and internal URL paths in grouped results anddetails.filesinstead of collapsing them to file basenames - Changed
/omfgto run up to three generation attempts with validation feedback and only prompt saving when no draft matches assistant history - Changed
/omfgto show a live draft panel with generation/validation/saving status and allow canceling an active rule request withEsc - Changed keybindings config to use
~/.omp/agent/keybindings.yml, with automatic migration from legacykeybindings.jsonand continued support forkeybindings.yaml. - Changed the local SQLite memory backend identifier from
mnemosynetomnemopi. Existing configs are migrated automatically on load:memory.backend: mnemosynebecomesmnemopiand themnemosyne.*settings block is renamed tomnemopi.*(skipped when an explicitmnemopiblock already exists). - Changed the
ultrathink/orchestrate/workflowmagic keywords to be markdown-aware: the standalone word now also glows in the rendered user message bubble (matching the live editor), and neither the glow nor the hidden steering notice triggers when the keyword sits inside a fenced code block, an inline`code`span, or an XML/HTML section.
Fixed
- Fixed Ctrl+O tool-result expansion on POSIX terminals so offscreen tool blocks rebuild native scrollback instead of leaving stale collapsed rows above the viewport.
Removed
- Removed the
/drop-imagesslash command; use/shake images, which strips every image from the session through the samedropImages()path.
Fixed
- Fixed final
agent()completion status emissions in eval cells so the last live progress snapshot now preserves accumulated subagent metrics such as tool count and cost - Fixed
agent()in eval to enforce plan-mode, spawn allowlist, and disabled-agent checks before launching subagents - Fixed recursive
agent()calls from eval by enforcing the existing max subagent depth limit - Fixed runtime model switches (Ctrl+P cycling,
--model,/model, model picker selections, and programmatic changes) so they no longer overwrite the persistedmodelRoles.default; only the model picker's explicit "Set as default" action and settings changes persist the default. - Fixed
searchto honor line-range suffixes on virtual internal URL targets so matches outside the requested ranges are no longer returned - Fixed
searchto handle internal URLs without source files without incorrectly reportingPath not found, returning matches from virtual content instead - Fixed
/omfgparsing to tolerate fenced or noisy model output, normalize generated rule names, and reject invalid regex conditions before saving - Fixed auto-thinking sessions to persist the concrete resolved effort after classification, so resuming the session restores that level instead of returning to pending
auto. - Fixed extension-registered CLI flags (e.g.
--spawn-peer <value>) leaking into the initial prompt: argv is re-parsed once the extension flag set is known so flag values are consumed instead of becoming messages or being misread as@filearguments. Registered flags shadow same-named built-ins, so a colliding flag (e.g. plan-mode's--plan) is parsed with the extension's semantics rather than being consumed by the built-in branch (which would otherwise eat the following message and corrupt the built-in field). Extension flags and@filearguments are now resolved before the session is created, so an unreadable initial@fileexits without leaving a junk session/terminal breadcrumb behind. (#1503) - Fixed footer status-line truncation: the left stats and right model segments now truncate by terminal cell width (via
truncateToWidth) and strip all VT/ANSI escapes (viastripVTControlCharacters) instead of a SGR-only regex plus code-pointsubstring, so wide glyphs, OSC hyperlinks, and non-SGR sequences can no longer overflow the line. - Fixed the streaming edit diff preview rendering a tall, half-empty box (and the earlier "box grows and shrinks repeatedly" stutter). A whole-file Myers re-diff is recomputed on every streamed chunk and its alignment is not monotonic in payload length, so a hunk-aware window that kept whole change segments gained and lost rows tick to tick; the prior high-water row reservation hid that stutter but padded the reserved height with blank rows, leaving a large empty rectangle whenever the diff shrank below its peak. The preview now pins a fixed-height trailing window to the bottom of the diff ("accept from the back"), so the box stays a steady, full window of real diff context instead of blank padding.
- Fixed duplicated/stale scrollback above a streaming tool result on POSIX terminals (macOS/Linux). A tool whose output grows and re-lays-out (e.g. an edit diff gaining hunks) re-renders rows that already scrolled into native scrollback; the unknown-viewport anti-yank deferral left the old copy in place while the new one rendered below, showing the block twice. The event controller now enables the TUI's eager native-scrollback rebuild while a foreground tool is executing (
setEagerNativeScrollbackRebuild), so those offscreen re-renders rebuild history cleanly — a snap to the tail is acceptable mid-tool. Background-running tools and plain assistant-text streaming keep the no-yank deferral; the mode resets at each turn start.
@oh-my-pi/pi-mnemopi
Changed
- Changed embedding result normalization to return
Float32Arrayvectors soembedandembedQuerynow cache and emit float32 rows - Changed the embedding provider contract to a single typed
EmbeddingOutput(AsyncIterable<number[][]>) instead ofunknown, matching fastembed'sembed(), soEmbeddingProvider.embedand theproviderruntime option stream the embedding matrix as async batches (async *embed(texts) { yield texts.map(embedOne); }) - Changed local model cache directory resolution for
fastembedto usegetFastembedCacheDirinstead of the hard-coded~/.hermes/cache/fastembedpath
Fixed
- Fixed cosine similarity behavior across retrieval, clustering, and caching to consistently handle mismatched vector lengths as zero-padded and ignore non-finite values
- Fixed embedding API requests to retry transient failures with backoff via shared retry logic before returning null
- Fixed compiled
ompbinaries losing local Mnemopi embeddings by keepingfastembedandonnxruntime-nodereachable to Bun's static compiler while preserving lazy runtime loading.
@oh-my-pi/pi-tui
Added
- Added
overflowSearchtoSelectListLayoutOptionsto let consumers enable or disable type-to-filter search and search-status rendering per SelectList instance - Added fuzzy type-to-filter search to overflowing
SelectListpickers, with search status and result counts. - Added
TUI.setEagerNativeScrollbackRebuild(enabled)— while enabled, live render frames rebuild native scrollback on offscreen/structural changes even when the viewport position is unobservable (POSIX), instead of deferring to a non-destructive repaint. Trades the anti-yank guarantee for clean, duplicate-free history; intended for windows where output above the fold is actively re-laying out (e.g. a tool whose result is still streaming). A terminal that reports a known-scrolled viewport still defers.
Changed
- Disabled interactive search filtering for editor autocomplete and slash-command
SelectLists by passingoverflowSearch: falsein their layout options
Fixed
- Preserved hidden tmux overlays in the live viewport by removing overlay content from view when an overlay was hidden while keeping pane history intact
- Preserved native scrollback when forced TUI renders coalesce with content growth, and deferred pure tail appends while readers are scrolled into history.
- Preserved existing terminal scrollback during forced and structural TUI renders so preexisting shell lines remained visible after component mutations
- Rebuilt native scrollback for safe bottom-anchored offscreen edits and high-water preview collapses instead of repainting only the viewport, preventing stale or duplicated rows above the live viewport.
- Stripped internal cursor marker sentinels from all rendered lines so offscreen focus markers no longer leak into terminal output
- Truncated all painted lines to terminal width during viewport repaints and append-tail updates so long content no longer overflows or wraps unexpectedly
- Fixed
tui.select.cancelhandling inSelectListso pressing Escape or Ctrl+C closes the list even when no matches are currently shown - Fixed native scrollback corruption when an offscreen row edit and repeated-tail append land in one render frame; ambiguous appended tails now rebuild history instead of splicing stale rows into the buffer.
- Fixed scrolled-up readers being yanked back to the tail whenever streaming content arrived on POSIX terminals (macOS/Linux). Native viewport position is unobservable there (
isNativeViewportAtBottom()returnsundefined), and the planner optimistically treated "unknown" as "at bottom", so every offscreen streaming edit ran a destructivehistoryRebuildthat cleared scrollback and snapped the view to the bottom. Live render frames now treat an unknown viewport as unsafe for a destructive rebuild — they defer to a non-destructive viewport repaint and reconcile native scrollback at the next explicit checkpoint (prompt submit). Resize and checkpoint replays keep the prior behavior. - Fixed native scrollback not rewrapping when the terminal widens on POSIX. A width increase reflows the transcript to fewer lines, which the shrink-across-boundary branch intercepted and (after the unknown-viewport deferral) repainted only the viewport — leaving committed history wrapped at the old width and duplicated above the live viewport. Width changes now rebuild native scrollback at the new geometry even when the viewport position is unknown (a yank is acceptable on an explicit resize); a terminal that can report a scrolled viewport still defers.
@oh-my-pi/pi-utils
Added
- Added
getFastembedCacheDirto return the FastEmbed model cache directory under ~/.omp/cache/fastembed
Fixed
- Fixed
$flagenvironment parsing to accept lowercase truthy values such asy,true,yes, andon
What's Changed
- feat(coding-agent): accept GitHub/git URLs in
plugin installby @oldschoola in #1527 - audit: fix top 5 perf/correctness findings + honorable mentions by @oldschoola in #1507
- fix(coding-agent): strip extension flags from the initial prompt by @erik-sv in #1503
New Contributors
Full Changelog: v15.7.2...v15.7.3