chore(deps): update dependency can1357/oh-my-pi to v15.11.4 #60
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "renovate/can1357-oh-my-pi-15.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:
15.11.3→15.11.4Release Notes
can1357/oh-my-pi (can1357/oh-my-pi)
v15.11.4Compare Source
@oh-my-pi/pi-agent-core
Added
hasSteeringMessagestoAgentLoopConfig(wired byAgentto its steering queue): a peek used by the immediate-interrupt poll during tool execution, so the loop can detect queued steering without dequeuing and the queue keeps owning its messages until the injection boundarystopReason: "stop"withstopDetails: { type: "pause_turn" }, emitted by the Codex providers forend_turn: falsecommentary-only responses): the assistant message is committed to history and the model is called again without ending the turn. Consecutive pause continuations without an intervening tool call are capped at 8 to bound a backend that never stops pausing.Changed
hasSteeringMessages. Consumers constructingAgentLoopConfigdirectly with onlygetSteeringMessagesno longer get mid-batch interrupts — steering degrades to boundary-only delivery until they also supplyhasSteeringMessagesApiKey(static string or resolver) instead of a pre-resolved string, so a 401 mid-compaction force-refreshes and rotates the credential through the central auth-retry policy before any model-level fallback. The remote OpenAI compaction request is wrapped inwithAuthand its HTTP failures now carry.status, so the retry classifier actually fires on remote-compaction 401s.transformProviderContextnow receives the dispatch model as a second argument ((context, model) => Context), so per-request transforms can gate on model capabilities (vision input, provider, API family). Existing single-argument implementations keep working unchanged.ProviderHttpErrorinstead of mutating plainErrors with a.statusproperty; the genericrequestRemoteCompactionerror now carries.status(and response headers) too.Fixed
@oh-my-pi/pi-ai
Added
end_turn: falseon the terminal stream event (Codex backend signal for "response ended, turn didn't" — commentary-only progress updates) tostopDetails: { type: "pause_turn" }with stopReason"stop", so the agent loop can re-sample instead of ending the turn. Wired inopenai-codex-responsesandprocessResponsesStream(openai-responses/azure-openai-responses); inert for backends that never send the field.openai-codex-responses(tracking codex-rs as of June 2026):onModerationMetadatacallback surfacingresponse.metadata→openai_chatgpt_moderation_metadataon both transports;reasoningContextoption emittingreasoning.context(auto/current_turn/all_turns);clientMetadataoption emittingclient_metadatain the request body (canonicalx-codex-turn-metadataenvelope) without breaking the websocket append fast-path; and an opt-inresponsesLitemode mirroring codex-rs — lite header on HTTP requests and the websocket upgrade,ws_request_header_*marker inresponse.createclient metadata, lite-keyed socket pooling, image-detail stripping, forced serial tool calls, andreasoning.context: all_turnsdefault. Dormant until OpenAI flipsuse_responses_litein the model catalog.withOAuthAccess— thewithAuthcounterpart for OAuth-access consumers: runs an operation through the central a/b/c auth-retry policy (resolve → force-refresh same account → rotate to a sibling) while handing the attempt the fullOAuthAccess(bearer plusaccountId/projectId/enterpriseUrlidentity metadata). Use it instead of hand-rolledgetOAuthAccess+ fetch flows so 401s and usage-limits rotate credentials instead of failing the call.ProviderHttpError— a typed HTTP error carryingstatus,headers, andcode— replacing the ad-hocas Error & { status?... }/Object.assignhacks at provider throw sites, with per-provider subclassesCodexApiError,AuthGatewayError,GoogleApiError,GeminiCliApiError,OllamaApiError, andBedrockApiError;AnthropicApiErrornow extends it. Google, Gemini CLI, Ollama, and Bedrock HTTP errors now also carry response headers, so server-suggestedretry-afterdelays are visible to retry classification on those paths. The internalwithHttpStatushelper was removed.PI_CODEX_STATEFUL=0orstatefulResponses: false): SSE requests now reuseprevious_response_idwith delta-only input instead of replaying the full transcript, mirroring the websocket fast-path via a shared transport-aware builder. Any history mutation or option change falls back to a full replay; a server-sideprevious_response_not_found(HTTP or in-stream) resets the chain and retries the turn with full context, and three consecutive stale failures disable chaining for the session.previous_response_idchaining to the platform OpenAI Responses provider (openai-responses): on by default against the official api.openai.com endpoint (forcesstore: true, which chaining requires), off for other Responses endpoints; override withstatefulResponsesorPI_OPENAI_STATEFUL. Chain detection compares the wire form of the conversation arguments alone — per-turn trailing scaffolding such as the GPT-5 "Juice: 0" developer item is excluded from the append-baseline prefix check and re-appended to the delta — and a rejected/stale previous response falls back to a one-shot full replay with the same circuit breaker.AuthStorage.getOAuthAccountIdentity()and theOAuthAccountIdentitytype — a read-only lookup returning theaccountId/email/projectIdof the OAuth credential a session is currently routed to, for display and metadata paths.Changed
applyResponsesReasoningParamsis now gated on the resolvedcompat.requiresJuiceZeroHackflag (auto-detected from GPT-5-family model names by@oh-my-pi/pi-catalog, overridable per model) instead of an inline model-name check.Fixed
client_metadatachanges between turnsonModerationMetadatahandling so exceptions thrown by callback observers no longer terminate the response streamompprocess refreshed and persisted the same row.AuthStoragenow syncs the selected row from storage before returning or force-refreshing OAuth credentials, so concurrent sessions pick up peer-rotated tokens instead of surfacing a one-turn401 Invalid authentication credentials.OAuth preflight refresh failed) so stale-refresh-token replays from concurrent sessions are diagnosable.@oh-my-pi/pi-catalog
Fixed
low|medium|highthinking efforts. Their upstreams rejectminimal,xhigh, and Fireworks'minimal → nonewire mapping, sofireworks/minimax-m2.7as the smol auto-thinking classifier model 400ed on every turn. OpenAI-compatible provider effort maps (Groq qwen/qwen3-32b, DeepSeek-family, OpenRouter Anthropic adaptive, Fireworksminimal → none) now bake intothinking.effortMapin catalog metadata instead ofbuildOpenAICompat, and request builders read that field directly. Regeneratedmodels.jsonnow makesdisableReasoningchooselowfor those families while leaving GLM-5.x and other Fireworks models on the existingminimal → nonepath (#2315).Added
requiresJuiceZeroHackResponses-API compat flag, resolved bybuildOpenAIResponsesCompatfrom GPT-5-family model names and overridable via sparse modelcompatconfig. Replaces the request-timemodel.name.startsWith("gpt-5")sniff that gated the trailing# Juice: 0 !importantno-reasoning developer item.@oh-my-pi/pi-coding-agent
Added
/settings, including tab and setting row hover highlighting, wheel scrolling, and left-click activation for entries and submenus/settingsmouse-event handling so scrolling and clicks work in an alternate-screen overlayModelRegistry.resolvernow accepts a model directly —resolver(model, sessionId)— derivingprovider,baseUrl, andmodelIdfrom it; all model-scoped call sites migrated from the verboseresolver(model.provider, { sessionId, baseUrl, modelId })form.snapcompact.systemPromptandsnapcompact.toolResultssettings (off by default,/settings→ Context → Experimental) that render the system prompt and large historical tool results as dense snapcompact PNG frames on vision-capable models to cut token cost. Frames are built per-request in the provider-context transform, cached across turns, capped by a per-provider image budget, and gated on a token-savings estimate — they never reachsession.jsonl./settings(Model → Prompt):default(the previous built-in reply style),friendly,pragmatic, ornone. The selected spec renders into a dedicated<personality>system-prompt block (extracted from the former<reply-guidelines>section) and applies to the live session immediately; subagents always omit the block.mnemopi.polyphonicRecallandmnemopi.enhancedRecallconfig.yml settings (off by default,/settings→ Memory → Mnemopi) that enable the mnemopi 4-voice polyphonic recall engine and the tiered query result cache without environment variables;MNEMOPI_POLYPHONIC_RECALL/MNEMOPI_ENHANCED_RECALLstill override the configured values when set (#2323).Changed
Changed
/settingskeyboard navigation soTabandShift+Tabtoggle focus between section headings and setting rows in sectioned lists, with↑/↓jumping sections,←/→switching tabs, and status text reflecting the active controlsThe
tasktool description now mandates batching parallel spawns into one call'stasks[](sharingcontextonce) instead of presenting multipletaskcalls per message as an equal alternative; separate calls are reserved for different agent types or unrelated contextUpdated
/settingson-screen navigation hints to match the new section-focus behavior (↑/↓andTab/Enter) and tab-switching arrowsChanged
/settingsto open as a full-screen overlay on the alternate screen so it no longer shares space with the underlying transcriptCodex, Gemini, and Perplexity web search now route their OAuth bearers through the new
withOAuthAccessdriver: a 401 or usage-limit force-refreshes the same account and then rotates to a sibling instead of failing the search, while identity metadata (chatgpt-account-id, GoogleprojectId) is re-derived from the refreshed credential on every retry.Kagi web search, the xAI TTS tool, and model-discovery list fetches now resolve their bearers through
withAuthwith an auth-storage resolver instead of a one-shot key snapshot, gaining the same force-refresh + rotate retry on 401.Compaction, handoff, and branch-summarization call sites now hand the compactor a per-candidate API-key resolver (availability still gated on a key snapshot), so credential refresh happens before the #986 fallback-model loop advances.
The mnemopi backend now passes an OpenRouter resolver for default embedding/extraction setups (AuthStorage-stored keys included), keeping pinned literal keys and custom endpoints unchanged.
Reorganized the
/settingspanel for findability: every tab now has titled sections backed by a per-tab layout contract (TAB_GROUPS); on wide terminals the panel renders a section sidebar with the active section's settings beside it (narrow terminals keep a flat list with inline headings), and PgUp/PgDn jump section-to-section. The Editing tab became Files (edit/read/LSP) and a new Shell tab hosts bash, eval, and Python settings. Misplaced settings were rehomed: bash toggles united under Shell, tool approval mode and policies together under Interaction → Approvals, marketplace auto-update next to startup update checks, and the todo auto-clear delay beside the other todo settings.Restyled the
/settingschrome: the tab strip moved below the content as a label-less footer, the panel keeps one constant height across navigation, value changes, and submenus (no more viewport jumps after each change), and typing now runs a global cross-tab search — results group under per-tab headings, the footer shows live match counts with non-matching tabs muted, Tab hops between matching tabs, and Esc exits search landing on the selected result's tab.Normalized
/settingslabels and descriptions: consistent Title Case labels (e.g. "Todo Auto-Clear Delay", "GitHub View Cache"), uniform unit placement, articles and verb-first phrasing in descriptions ("If false…"/"Whether to…" rewritten), and a stale browser-tool description (Ulixee Hero) corrected to the actual puppeteer/Chromium implementation./settingssection headings are now underlined — the active section's heading stays bold, and headings outside the active section render dim with the same underline — so section boundaries read at a glance./settings: Tab now toggles keyboard focus between section headings and the setting rows — while headings are focused, ↑/↓ jump whole sections and Enter/Esc drop back into the rows — instead of cycling tabs. ←/→ still switch tabs everywhere, tabs without sections (e.g. Plugins) keep Tab as tab-switching, and the footer hint follows the focus state.Image-generation (Antigravity, xAI, OpenRouter, Gemini) and xAI TTS request failures now throw pi-ai's typed
ProviderHttpErrorcarrying status and response headers instead ofObject.assign-patchedErrors.Collapsed bash, ssh, and eval previews now cap the command/code section to a viewport-sized tail window (terminal rows minus a chrome reserve) that renders identically while streaming and after completion, with
ctrl+oas the only way to uncap. Previously bash/ssh capped the command only while streaming and snapped it fully open the moment the tool finished, and eval never capped cell code at all.The
jobrenderer now shimmers running-job labels while the poll block is live, freezing to static once the block seals, and drops the id column when the label repeats it — task jobs label themselves with their agent id, so rows read⟨task⟩ SessionTreeinstead ofSessionTree ⟨task⟩ SessionTree.Task progress rows now render static text with the task icon instead of shimmering the description or showing the pending/hourglass status glyph.
app.clipboard.pasteImage(Ctrl+V) now falls back to pasting clipboard text when no image is present, so hosts that deliver only that chord (VS Code's integrated terminal forwardingCtrl+V, Windows clipboard history viaWin+V) cover both payload kinds; WSL text reads now reach the Windows clipboard through host PowerShell like image reads already did (#1628).Changed
/usageto show the OAuth account currently selected for the active model provider when usage reports include multiple accounts, making multi-account sessions easier to verify without marking unrelated providers.Fixed
/treeand the HTML export: flattened chain rows under a last-sibling (└─) branch drew a dangling│in the corner column itself and shifted columns once the chain branched deeper; the chain anchor now sits one level right, below the branch head's content, so connectors terminate at└─and indentation stays stable (#2325).clearQueue()andpopLastQueuedMessage()now hand queued images back alongside the text, and the restore paths return them to the pending-image buffer instead of silently discarding them./settingsby locking sidebar width to the widest group name so switching tabs no longer shifts the layoutlsp.formatOnWritesending a hardcodedtabSize: 3, insertSpaces: trueon everytextDocument/formattingrequest, which silently re-indented 2-space YAML (and any LSP-formatted file) to 3-space on every write/edit through formatter-aware servers likeyaml-language-server. Format options are now resolved per-file from.editorconfig(indent_size,indent_style,tab_width), falling back to the indent sniffed from the in-memory content the agent is about to write, then to a 2-space default. The duplicateDEFAULT_FORMAT_OPTIONSconstant inlsp/index.tsandlsp/clients/lsp-linter-client.tsis replaced with a single sharedresolveFormatOptionshelper (#2329).Item with id 'rs_...' not found.by resetting the provider session and retrying without advancing fallback chains./settingsEscape handling so an open submenu receives Esc and returns to the settings list before a second Esc closes the panel (#2331)./settingson the Plugins tab while the async plugin list is still loading:PluginSettingsComponentnow closes on Esc while no child view is mounted, and an npm plugin registry listing failure is caught (like marketplace failures) so a bad registry no longer leaves the tab permanently blank (#2331).pi/smol,pi/slow, andpi/designeragent model roles using cloud-priority defaults before the user's configuredmodelRoles.default, which could route local-default setups to authenticated paid providers (#2336).issue://reads failing on older GitHub CLI releases that reject the optionalstateReasonissue JSON field; single issue reads now retry without it and issue listings no longer request it (#2333)./login-stored OpenRouter and Google API keys: provider selection and requests now resolve through the model registry (with env-var fallback) instead of environment variables only.taskasync spawn) progress snapshots repainting commit-eligible rows after the block leaves the live transcript region; later partial snapshots are dropped while the final completion snapshot still applies.def,shape, methods stringified asundefined) or silently reading nothing:/dumpand the RPCget_statedumpToolspayload now convert parameters through the same wire-schema conversion providers receive; context-usage token estimation no longer stringifies the Zoddeftree (overcounting tool schema tokens in the status line); tool-discovery search indexing recoversschemaKeysfrom Zod tools (previously empty, weakening BM25 ranking); and the extension inspector panel renders Zod tool arguments instead of "(no arguments)".@oh-my-pi/hashline
Added
insert after block N:: a body indented deeper than the block's closing line now slides back across the block's trailing closer lines and lands inside the block at its claimed depth, with a warning naming the landing line. Same conservative guards as the outward shift — comparable indentation only, closers only, abandoned when another hunk targets a crossed line; plaininsert after M:stays literalinsert after block N:: anchoring on a pure closing-delimiter line (where no block begins, so resolution previously failed the whole patch) now applies as plaininsert after N:with a warning teaching the opener-only rule.resolveBlockEditsgained anonWarningcallback; apply, preview, and patcher paths surface it onwarningsChanged
<critical>recap; landing-correction mechanics are no longer described to the agent@oh-my-pi/pi-mnemopi
Added
configureRecallFeatures()(exported from the package root,core, andconfig) so hosts can enable the polyphonic recall engine and the enhanced recall query cache programmatically.polyphonicRecallEnabled(),enhancedRecallEnabled(), andisEnhancedRecallEnabled()now fall back to these configured defaults, with theMNEMOPI_POLYPHONIC_RECALL/MNEMOPI_ENHANCED_RECALLenvironment variables still taking precedence whenever they are set. (#2323)Fixed
catch {}blocks (runEmbedding(),getLocalModel(), and the local-model path ofembed()) swallowing failures with zero diagnostics. These best-effort paths still degrade gracefully (returnnull/ skip the write), but now emit structuredlogger.debugentries with the error and per-site context (item count, model name). Themnemopi.debugconfig flag now propagates into the core library via runtime options (MnemopiOptions.debug→ResolvedMnemopiRuntimeOptions.debug) and escalates these logs towarnso they surface at the default log level. (#2322)Changed
ApiKey(static string or resolver) and resolve it per request throughwithAuth, so 401s force-refresh and rotate credentials via the central auth-retry policy instead of failing with a stale key. Empty-key setups (local/proxy endpoints withoutAuthorization) and pinned literal keys behave exactly as before.ProviderHttpErrorinstead ofObject.assign-patchedErrors, keeping the same structural.statuscontract for the auth-retry classifier.core/shmr) now uses the real embedding provider when one is configured instead of always hashing:embed(), the newembedBatch(),clusterBySimilarity(),computeHarmonyScore(),harmonize(), andrecallBeliefs()are now async, batch-embed candidate texts in a single provider call, and reuse precomputed vectors frommemory_embeddingsfor episodic candidates. The SHA1 bag-of-words hash remains as the deterministic fallback when no provider is available or embedding fails. (#2324)@oh-my-pi/pi-natives
Fixed
blockRangeAt(and thus the edit tool'sreplace block/insert after blockops) failing on extensionless shell rc/profile files.Path::extensionreturnsNonefor both bare (zshrc) and dotfile (.zshrc,.bashrc) forms, so language inference fell through to "unrecognized" and block resolution was permanently unresolvable on those files — an agent retrying the block op would loop on the same error. Known shell rc/profile basenames (zshrc/zshenv/zprofile/zlogin/zlogout/bashrc/bash_profile/bash_login/bash_logout/bash_aliases/profile/kshrc/mkshrc/shrc, with or without a leading dot) now resolve to the bash grammar.@oh-my-pi/snapcompact
Breaking Changes
snapcompact/Snapcompact/SNAPCOMPACT_qualifier — the package is meant to be consumed viaimport * as snapcompact from "@​oh-my-pi/snapcompact". Functions:snapcompactCompact→compact,renderSnapcompactFrame→render,snapcompactGeometry→geometry,normalizeForSnapcompact→normalize,serializeSnapcompactConversation→serializeConversation,snapcompactImages→images,getPreservedSnapcompactArchive→getPreservedArchive,isSnapcompactShape→isShape,resolveSnapcompactShape→resolveShape,createSnapcompactFileOps→createFileOps,computeSnapcompactFileLists→computeFileLists,upsertSnapcompactFileOperations→upsertFileOperations. Types:SnapcompactShape→Shape,SnapcompactFrame→Frame,SnapcompactArchive→Archive,SnapcompactGeometry→Geometry,SnapcompactOptions→Options,SnapcompactSerializeOptions→SerializeOptions,SnapcompactFileOperations→FileOperations,SnapcompactCompactionDetails/Preparation/Result→CompactionDetails/CompactionPreparation/CompactionResult,SnapcompactConvertToLlm→ConvertToLlm. Constants:SNAPCOMPACT_X→X(SHAPES,FRAME_SIZE,MAX_FRAMES,FRAME_TOKEN_ESTIMATE,PRESERVE_KEY,TOOL_RESULT_MAX_CHARS,TOOL_ARG_MAX_CHARS,TOOL_CALL_MAX_CHARS,TRUNCATE_HEAD_RATIO,DIM_ON,DIM_OFF).Added
renderMany()for paging arbitrary text into snapcompact PNG frames as LLM image blocks, andframes()for predicting the frame count without rendering@oh-my-pi/pi-tui
Added
partialHoldTimeouttoStdinBufferOptionsto control the maximum extra delay held for unambiguous incomplete escape sequences before they are flushedSettingsList.sidebarWidthoption for a fixed split-layout sidebar widthSettingsListwithsetHoverItem,hitTest,hoverTest, androuteSubmenuMousefor row targeting and submenu routingSettingsList.setMaxVisible(rows)andSettingsList.handleWheel(delta)for dynamic viewport sizing and mouse-wheel step selectionTab.shortlabels andTabBar.selectTab(id)for id-based activation of non-muted tabsTabBarwithsetHoverTab,tabAt, andhoverTabthemeparseSgrMouse,SgrMouseEvent, andMouseRoutableSettingsList:SettingItem.headingrows split the list into sections, PgUp/PgDn (tui.select.pageUp/pageDown) jump between sections (or page when none exist), and wide renders use a split layout — section sidebar on the left, the active section's items on the right — falling back to inline heading rows when the width cannot fit both panes. Headings are skipped by navigation, excluded from search, and styled through the optionalSettingsListTheme.heading(which receives adimmedflag for headings outside the active section) andsection.SettingsList: aSettingsListOptionsconstructor arg (layoutto force the flat layout,typeToSearch: falseto hand the query to a parent,emptyText,hint),selectItem(id),getSelectedItem(),onSelectionChange,hasOpenSubmenu(), and the exportedgetSettingItemFilterTexthelper.SettingsList:toggleSectionFocus()/sectionFocused/hasSectionFocusTargets()flip Up/Down between row navigation and whole-section jumps — the cursor glyph parks on the active sidebar entry (or the active heading row in the flat layout) while the row cursor hides, Enter/Esc drop focus back to the rows, and any explicit row selection (selectItem, wheel, filtering) exits it.TabBar(Tab.muted+TabBarTheme.mutedTab, skipped by keyboard navigation),setTabs(tabs, activeId?)/setActiveById(id)for re-rendering the strip without firingonTabChange, an optional empty label (drops theLabel:prefix), and ashowHintswitch for the trailing "(tab to cycle)" hint.Changed
SettingsListsection-focused keyboard handling soUp/Downnow jump between sections andEnter/Escapeexit section focus before confirming or cancelling a settingSettingsListsplit layout at wide widths to render the full list in the right pane and dim items outside the active section instead of showing only the active-section rowsSettingsListto omit the default hint row (and preceding blank line) whenoptions.hintis set to an empty stringshortforms before wrapping to multiple linesFixed
StdinBufferhandling of split SGR mouse reports so fragmented sequences are reassembled instead of leaking their tail bytes as literal input/settingson kitty-protocol terminals (Ghostty/kitty): the kitty keyboard mode stack is per-screen, so entering the alternate screen silently reverted keys to legacy encoding while the app still parsed them as kitty input. The TUI now re-pushes the active kitty flags right after\x1b[?1049hand pops them before\x1b[?1049l.StdinBuffertearing a buffered bareESCfollowed by another escape sequence: the\x1b\x1bcandidate was consumed as alt+esc before the CSI/SS3 continuation byte was ever inspected, swallowing the Esc keypress and leaking the follower's tail ([B,[<35;22;17M) as typed text into focused components. Meta-CSI chords (\x1b\x1b[A) now stay whole, andESC+ SGR mouse report is split into a real Esc keypress plus a parseable report.PARTIAL_HOLD_MAX_MSfrom 500ms to 150ms so a dangling escape partial that never completes (e.g. a bareESCarriving while the kitty-active flag is stale) is delivered after at most ~200ms instead of half a second.ESCso it can be joined with subsequent CSI mouse/kitty input instead of being emitted as a standalone sequenceSettingsListto clear section-focus state when filtering items, changing data, scrolling with the mouse wheel, or selecting by ID so stale heading focus does not persist across interactionsSettingsListnow renders every state — list, open submenu, filtered results, empty — at one stable height, so interacting with a bottom-anchored settings panel no longer resizes the live terminal region on each keystroke (which forced re-anchoring and could strand stale scrollback rows).@oh-my-pi/pi-utils
Added
getEditorConfigFormatting(file): returns the.editorconfig-pinnedtabSize/insertSpaces(both optional, no fallback) so LSP-format callers can layer per-file defaults under it without paving over silence with the renderer's display tab width (#2329).What's Changed
New Contributors
Full Changelog: https://github.com/can1357/oh-my-pi/compare/v15.11.3...v15.11.4
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.