- Registered and triggered a session-switch reconciler during init and after switch.
- Rebuilt resume flow to restore plan/goal mode state and clear stale mode flags.
- Marked fallback and context-promotion model switches ephemeral and skipped them on restore.
- Added regression tests for temporary model ordering, fallback precedence, and mode cleanup.
- Updated the TUI commit-path guard so unstable overflow falls back to normal commits unless rewrites reach above the viewport top.
- Added a regression test that streams a growing box while scrollback risk is enabled and checks all logical rows stay reachable in history or view.
- Mapped left/right arrows to switch tabs in the extension dashboard.
- Updated agent and extension dashboard footers to show arrow controls.
- Reformatted HTTP transport assignment and reordered an import.
- Aligned handoff, reminder, and system-prompt expectations with shortened copy.
- Added HTTP transport test for required initialize failures.
- Guarded SSE startup timeout against stale connection races.
- Added system-prompt rule mapping user `parallel`/`parallelize` requests to `task` subagent fan-out.
- Clarified that parallel tool calls alone do not satisfy the request.
- Mapped the right arrow key to advance tabs in the agent dashboard.
- Mapped the left arrow key to reverse tabs alongside shift+tab.
- Kept existing tab and shift+tab handling intact for backward-compatible navigation.
- Adjusted session and dashboard renderers to derive heights from live terminal rows.
- Propagated terminal-row callbacks through picker/controller wiring and session selectors.
- Reworked list visibility and page navigation to honor row-based budgets and footer lines.
- Added DECRQM 2031 startup probing and stopped OSC11 polling once support was confirmed.
- Raised default search results to 20 and context size to high.
- Added related questions parsing and return_related_questions request flag.
- Added API-key request-shape tests covering defaults and parsing.
- Added token-aware query matching so highlights mirror `HistoryStorage.search` tokenization.
- Added token highlighting, compact relative timestamps, and selected-row styling in results.
- Added PageUp/PageDown and Home/End selection shortcuts in `HistorySearchComponent`.
- Added selector matchers for `tui.select.pageUp` and `tui.select.pageDown`.
- Changed empty-result messaging to distinguish `No history yet` from `No matching history`.
- Added tests for page/home/end navigation and token-highlighting result rendering.
- Replaced the single-line description Input with Editor in agent-dashboard.ts for multiline entry.
- Added Enter-newline and Ctrl+Enter submit handling to the create-agent editor flow.
- Updated agent-creation-architect.md guidance for concise single-sentence whenToUse output.
- Added integration tests for multiline editor rendering and Ctrl+Enter submission.
- Added assistant-message completion state and stable-line count reporting.
- Added transcript stable-row aggregation and snapshot replay to keep unstable rows out of scrollback.
- Added TUI stable scrollback boundary APIs and stable-prefix commit path.
- Added regression tests proving unstable rows stay out of scrollback until stabilized.
Route '/data/workspaces/can1357__oh-my-pi__1863/.omp-session/2026-06-04T13-36-11-717Z_019e92d9-3fc5-7000-a66f-15cad94b7e75/local' plan artifacts through OMP's session-local storage instead of the editor writeTextFile bridge, preserving ACP bridge routing for regular editor-visible files.
Fixes#1863
- Removed early FTS-only return so prefix and substring matches merge.
- Sorted merged results globally by prompt recency before limiting.
- Added /force, /copy, and /shake tips.
Reviewer noted that an unconditional ExaProvider.isAvailable steered the auto chain into the public MCP fallback before any later-configured provider could run. Restored the credential-gated isAvailable, then split out isExplicitlyAvailable so resolveProviderChain still routes an explicit Exa selection through MCP without affecting other providers.\n\nRefs #1860
- Skipped titling for greeting/filler/empty first messages deterministically, retrying on later user messages.
- Let capable title models decline taskless input via a "none" sentinel.
- Guarded against clobbering a name set by a concurrent attempt.
Narrowed the DashScope text-only Qwen guard to known text-only id families instead of all Qwen ids without vl/omni/audio markers, so compatible-mode multimodal ids such as qwen3.7-plus keep image_url content when model.input advertises image support.
Added a regression counter-case for qwen3.7-plus alongside qwen-vl-max.
Fixes#1859
Restored Exa's unauthenticated MCP fallback when neither auth storage nor EXA_API_KEY provides credentials. Preserved API-key search ordering and bounded the MCP request with the web-search hard timeout. Updated provider copy and regression coverage for the no-key path.\n\nFixes #1860
DashScope's consumer compatible-mode endpoint
(dashscope.aliyuncs.com/compatible-mode/v1) rejects multipart message
content with '400 InternalError.Algo.InvalidParameter: The provided
messages input is invalid. The error info is [Unexpected item type in
content.]' whenever a non-vision Qwen id (qwen-max, qwen3.7-max,
qwen3-coder-*, ...) is asked to consume an image_url part. The agent hit
this whenever a screenshot or other image-bearing tool result was
batched into the synthetic user turn convertMessages emits between
successive turns.
Add isDashscopeCompatibleModeTextOnlyQwen in vision-guard.ts and gate
both supportsImages checks in convertMessages on it, so a misconfigured
custom provider claiming input: ["text", "image"] for a text-only
Qwen on that endpoint falls back to the standard
[image omitted: model does not support vision] placeholder. The
coding-intl.dashscope.aliyuncs.com coding-plan endpoint and explicit
qwen-vl-* / qwen-omni-* / qwen-audio-* ids are unaffected.
Fixes#1859
- Converted compaction, branch, and handoff prompts to fragment voice.
- Replaced "You MUST" phrasing with bare "MUST" directives.
- Applied same rewrite to autoresearch and turn-aborted prompts.
- Sending context-1m-2025-08-07 caused OAuth requests without long-context credits to fail with 429, breaking Sonnet.
- Dropped the beta from agent, OAuth discovery, and usage-API headers.
MCP tool renderers now merge call and result components so completed blocks replace the pending call header with success or error status.
MCP protocol errors now preserve top-level isError so downstream render state can use the error status consistently.
Added renderer coverage for completed MCP success and error blocks.
Fixes#1855
Centralized append-only context auto-mode resolution so SDK sessions, interactive sessions, and the status display use the same provider checks. Auto mode now enables for Xiaomi/SGLang hosts and explicit stored-request compat signals while preserving DeepSeek behavior.
Added focused regression coverage for Xiaomi Token Plan SGLang HiCache endpoints and explicit on/off behavior.
Fixes#1851
Fireworks /v1/models reports max_completion_tokens: 65536 generically for the
Kimi K2 family, but Kimi-on-Fireworks is documented to produce runaway
reasoning traces unless the output budget is bounded. The inflated value
flowed straight through fireworksModelManagerOptions.mapModel (forwarded
verbatim via toPositiveNumber), ended up in the bundled models.json for
fireworks/kimi-k2.5, fireworks/kimi-k2.6, and firepass/kimi-k2.6-turbo,
and was preserved across regenerations by prevModelsJson — so callers (and
the openai-completions default-injection safety net) could ship a budget the
router cannot honor.
Add a Fireworks-family Kimi cap (FIREWORKS_KIMI_MAX_TOKENS = 32_768) plus
isFireworksKimiK2ModelId / clampFireworksKimiMaxTokens helpers that recognize
both the public catalog ids (kimi-k2.5, kimi-k2.6, kimi-k2.6-turbo,
kimi-k2-thinking) and the canonical wire ids
(accounts/fireworks/{models,routers}/kimi-k2…). The Fireworks resolver
clamps every discovered Kimi K2.x model at runtime, and a new
applyFireworksKimiMaxTokensCap pass in generate-models.ts applies the same
ceiling to the fireworks/firepass slice of the assembled catalog so the
firepass static fallback and any future regens stay in sync.
Fixes#1849
Updated regional Xiaomi Token Plan login to open the plan management page where tp- keys are configured, and covered the URL in regression tests.\n\nFixes #1846
Added regional Xiaomi Token Plan login providers and model discovery while preserving the selected provider id. Replayed MiMo reasoning_content for Token Plan OpenAI-compatible tool-call continuations.\n\nFixes #1846
Allowed OpenAI-compatible providers to opt into Anthropic cache_control markers via compat.cacheControlFormat while preserving OpenRouter Anthropic defaults.
Fixes#1845
Marketplace plugin toggles in Settings → Plugins wrote the installed-plugin
registry and then only requested a render through the settings callback. In a
live TUI session that left already-loaded slash commands, hooks, tools, agents,
and SSH tool state unchanged until the user manually reloaded plugins or
restarted.
Make the plugin-change callback awaitable and wire the settings selector to the
same reload pipeline used by the slash-command runtime: clear plugin-root caches
for the active project registry, refresh slash command state, refresh the SSH
tool, then request a render. Await the callback after npm and marketplace
registry writes so Settings → Plugins reflects live plugin state immediately.
Add a regression test proving a marketplace toggle calls setPluginEnabled before
the plugin-change reload callback resolves.
`MarketplacePluginDetailComponent` rendered the raw `installPath` from
the installed-plugin registry, which leaks the user's home directory
into the TUI when the plugin lives under `~/.omp/cache`. Route it
through `shortenPath` so $HOME becomes `~` before the value reaches
`Text`, matching the repo's TUI sanitization rules (per review on #1844).
`PluginSettingsComponent.#showPluginList()` only inspected the npm plugin
registry, so the TUI's `Settings → Plugins` panel rendered "No plugins
installed" whenever the user had no npm plugins — even when many
marketplace plugins were installed. The `/plugins list` slash command,
`omp plugin list` CLI, and the install/uninstall selectors already
merged `PluginManager.list()` with `MarketplaceManager.listInstalledPlugins()`;
the settings panel was the only surface that missed the marketplace
registry when it was added.
Extend the panel to consume both data sources:
- Replace `PluginListComponent`'s `InstalledPlugin[]` input with a tagged
union `PluginListEntry = { kind: "npm"; plugin: InstalledPlugin } | { kind:
"marketplace"; plugin: InstalledPluginSummary }`. Each row now carries an
`[npm]`/`[marketplace]` kind badge, a scope tag, and the shadow indicator
for user installs overridden by a project entry. Widen the SelectList
primary column so long `name@marketplace` ids stay readable.
- Add `MarketplacePluginDetailComponent`: single `Enabled` toggle plus the
read-only `InstalledPluginEntry` metadata (version, install path,
installed-at, last-updated, git commit SHA). The toggle calls
`MarketplaceManager.setPluginEnabled(pluginId, enabled, scope)` — same
path `/plugins enable|disable` uses.
- Update `PluginSettingsComponent` to await both `PluginManager.list()` and
`MarketplaceManager.listInstalledPlugins()` in parallel, build the merged
list, and route selection to the kind-specific detail view. The empty
state now lists both install commands (npm and marketplace).
Fixes#1842