- Coalesced repeated interrupt-and-flush calls into one queued-steer resume flow.
- Retried queued continues on AgentBusyError after waitForIdle up to a 30s timeout.
- Handled queue-flush failures in input controllers with warning logs and TUI error display.
- Applied a finite 64,000-token fallback for OpenAI completion requests when model maxTokens is unavailable.
- Refactored stream max-token computation to use a shared helper and preserve a finite cap when caller and model limits are null.
- Added regression coverage for null maxTokens flows and bumped the model-cache schema to invalidate entries using retired unknown-limit sentinels.
- Updated AgentSession.setModel and setModelTemporary to validate credentials with hasConfiguredAuth instead of eagerly resolving API keys.
- Changed ModelRegistry.hasConfiguredAuth to probe configured credentials without executing command-backed key programs or refreshing OAuth tokens.
- Added model switch auth tests that verify resolver calls were removed and unconfigured models are rejected synchronously.
- Replaced unknown model contextWindow/maxTokens sentinels with nullable values across types and catalog data.
- Mapped request token calculations to treat null maxTokens as unlimited output caps.
- Updated remote compaction and context checks to ignore unknown limits by using Infinity/0 fallbacks.
- Adjusted CLI/model registry flows to skip cap enforcement for null limits and render unknown values as '-'.
- Added `omp models` command with `ls`, `find`, `canonical`, and `refresh` actions.
- Removed top-level `--list-models` parsing from CLI args, launch, and main command flow.
- Implemented action-driven model listing with provider filtering, extension loading, and `--json` output.
- Updated unknown provider/model errors and tests to direct users to `omp models` guidance.
- InputController now acknowledged empty-submit interrupts before flushing queued steering or queued-abort paths to preserve interrupting feedback.
- EventController now recreated the loading animation on interrupt acknowledgement and deferred end-of-turn teardown while queued resume recovery was still arming.
- AgentSession exposed an isResumingQueuedMessages phase around interruptAndFlushQueuedMessages so stale agent_end events no longer tear down the loader prematurely.
beautiful-mermaid@1.1.3 measures label width in UTF-16 code units, but
terminals render East Asian characters (Hangul/CJK/kana) and emoji 2
columns wide, so fenced mermaid blocks in assistant messages and
render_mermaid tool output had misaligned box borders for non-Latin
labels (upstream: lukilabs/beautiful-mermaid#119, #122).
Adds a patchedDependencies entry rebuilding the ASCII renderer to
measure terminal display columns: grapheme-cluster segmentation
(Intl.Segmenter), wcwidth-style policy (East Asian Wide + emoji
presentation + ZWJ/VS16/flag sequences = 2 columns; text-presentation
symbols like the renderer's own arrowheads stay narrow), and atomic
wide-glyph cell pairs so label collisions cannot shift row widths.
The patch modifies only existing files (bun cannot patch in new files,
and the exports "bun" condition loads src/ directly, so both src and
dist are patched). It mirrors the upstream PR and should be dropped
once the fix ships in a beautiful-mermaid release; a new CJK alignment
regression test keeps that transition honest.
Verified: bun test packages/coding-agent/test/modes/components/
assistant-message-mermaid.test.ts (8 pass, incl. new display-column
alignment regression test); bun test packages/utils (154 pass); Korean
flowchart renders with uniform display-column row widths through the
patched package.
- Replaced Azure and OpenAI provider calls with `postOpenAIStream` flow.
- Fixed stream error handling by retaining status, headers, and body on failures.
- Fixed stream parsing by handling raw JSON SSE frames and `[DONE]` events.
- Added `OpenAIHttpError` with parsed messages and timeout-aware retry behavior.
- Added remote-compaction tests for timeout, abort, and 500-fallback behavior.
- Removed `userMessageId` from `AcpAgent` prompt state and response payloads.
- Removed `models` from new/load/resume/fork session responses and deleted model-state building.
- Removed `unstable_setSessionModel` and routed model changes through `setSessionConfigOption`.
Fell back to the PowerShell clipboard bridge when the native Windows clipboard reader reports no image, preserving Ctrl+V image paste in PowerShell terminals.\n\nFixes #2429
The bank id used to be hashed from
`git.repo.resolveSync(cwd)?.repoRoot ?? path.resolve(cwd)`, so adding or
removing a `.git` anywhere above the working directory silently
repointed the same conversation to a new bank and stranded its
memories. Same cwd `/home/x/projects/repo` flipped between
`projects-<hash>` and `repo-<hash>` depending on whether the parent
directory still looked like a repo.
`packages/coding-agent/src/mnemopi/config.ts` now hashes
`path.resolve(cwd)` directly. Session startup also widens the recall
set with any sibling bank under `<dbDir>/banks/` whose
`working_memory` rows already carry the active cwd in
`metadata_json.$.cwd`, so memories stranded by the old, less-stable
derivation become visible again on the next session without manual
migration.
Fixes#2412
Pre-fix `loadSkills` in `extensibility/skills.ts` gated the OMP-native
`agents` provider (the canonical `~/.agent[s]/skills` and project-walkup
`.agent[s]/skills`) on the `anyBuiltInSkillSourceEnabled` fall-through —
the OR of `enableCodexUser`/`enableClaudeUser`/`enableClaudeProject`/
`enablePiUser`/`enablePiProject`. A user who turned off the named
third-party toggles to clean noise from other CLIs silently lost their
own canonical OMP-native skills, so typing `/` showed no `/skill:<name>`
entries for `~/.agents/skills/*/SKILL.md`.
- Added `skills.enableAgentsUser` and `skills.enableAgentsProject` to
the settings schema (default true) and to the `SkillsSettings` shape.
- Routed `isSourceEnabled` to the new toggles for `provider === "agents"`
(per level). The fall-through still covers providers without a
dedicated toggle (`claude-plugins`, `opencode`, `gemini`, `github`, …);
agents joins claude/codex/native at the named-source layer where it
always belonged.
- Updated `docs/skills.md` to document the new toggles and the corrected
enablement rule.
- Refactored `test/skills.test.ts` to share a `DISABLE_ALL_BUILTIN_SKILLS`
helper (so the isolation tests stay correct when new toggles are
added) and added two regression tests: one asserting that the
pre-fix scenario (named third-party toggles off, agents defaulted) now
loads `~/.agents/skills/<name>/SKILL.md`, and one pinning the explicit
`enableAgentsUser: false` opt-out.
Fixes#2401
- InputController now clears typed editor text and triggers a render when Esc is pressed with content, then resets the double-Esc timer.
- The double-Esc selector path was updated to reset the terminal display before opening tree or branch message selectors.
- Escape handling tests were expanded with settings setup/teardown to verify default, branch, and draft-clearing Esc scenarios.
The host schedules a debounced state broadcast right after hello; on slow
runners it lands between a guest's mutating frame and the directed error
reply, so nextFrame() saw "state" instead of "error". Guests now drop
broadcast-only frames (state/agents/entry/event/bus) and wait solely on
directed welcome/error replies.
- Re-polled steering at the loop yield boundary and included it in the pre-stop pending batch so late messages are processed immediately.
- Added session-side draining for stranded queued messages, scheduling an auto-continue when a prompt settles and follow-ups or steers remain.
- Added a regression test for late steering injection at yield and updated mid-turn collab prompt handling to keep steering messages in the pending display queue until consumed.
- Changed the link grammar from `<roomId>#<key>` / `host[:port]/r/<roomId>#<key>` to dot-joined `<roomId>.<key>` in `formatCollabLink`/`parseCollabLink` (`packages/coding-agent/src/collab/protocol.ts`) and the collab-web mirror (`packages/collab-web/src/lib/link.ts`): RFC 3986 forbids a raw `#` inside a fragment, so strict URL stacks (macOS Foundation behind terminal click-to-open) percent-encoded the second `#`.
- Kept legacy `#`-joined links parseable via `BARE_LINK_RE` and added lenient `%23` → `#` decoding for mangled deep links.
- Updated the `ConnectScreen` placeholder, `app.tsx` deep-link comment, `DEFAULT_RELAY_URL` doc in `packages/wire`, `docs/collab.md` examples, and both package CHANGELOGs.
- Extended `crypto.test.ts` and `link.test.ts` with dot-joined, legacy-hash, and `%23`-mangled link coverage.
- Added optional `useless` flags to tool result types and payload builders.
- Added `pruneUseless` and `dropUeless` options to control uneventful result pruning.
- Changed compaction and shake passes to prune or ignore non-error useless tool results.
- Changed conversation serialization to omit useless toolCall/toolResult pairs from output.
- Added coverage for useless tagging, pruning, and serialization behavior.
Restored the default double-Esc action to the editable message-history selector and covered the default controller route with a regression test.
Fixes#2396
- Added a focused-agent left-key input listener that consumes double left taps when the input is empty.
- Routed focused session left-tap behavior through #handleFocusedLeftTap so it matches the Esc-style unfocus timing.
- Updated tests/fixtures for the new listener flow and refreshed a hashline block-edit error assertion.
- Added a SessionFocusController to switch transcript and input context between main and subagent sessions.
- Added agent-hub Enter activation and double-left return behavior for focused local agents.
- Added view-session-based event and render logic to avoid stale focus-session state.
- Added status-line focused agent display with ghost icon and focused-mode border dimming.
- Updated `codexResets.autoRedeem` from a boolean to `unset`/`yes`/`no` in schema and settings types, with updated description text.
- Adjusted Codex auto-reset evaluation to skip checks in `no` mode and to prompt once in `unset` mode before spending, while preserving immediate spend for `yes`.
- Migrated legacy boolean config values to tri-state during settings load and added tests for mode defaults, helper behavior, and migration results.
- Added `src/export/share.ts`: `/share` now snapshots the session JSON, gzips and seals it with a fresh AES-256-GCM key, and pushes the blob to a secret gist or the share server (1 MB cap with image/string/entry truncation via `sealToFit`); links are `<serverUrl>/<id>#<key>` with the key only in the fragment.
- Added `share-loader.js` and `scripts/generate-share-viewer.ts` building the static viewer the relay serves at `GET /s/<id>`: it fetches the sealed blob, decrypts in-browser, and hands the JSON to the export template via `window.__OMP_SESSION_DATA__`.
- Reworked the `/share` command in `command-controller.ts`/`builtin-registry.ts` off the plaintext-gist HTML upload, exported `LoadedCustomShare`, and exposed the session `SecretObfuscator` getter on `AgentSession` for redaction.
- Added `share.serverUrl` and `share.redactSecrets` settings backed by `DEFAULT_SHARE_URL` from pi-wire.
- HTML exports now embed subagent transcripts: `collectSubSessions` walks `<session>/<AgentId>.jsonl` recursively into `SessionData.subSessions`, with `includeSubSessions` opt-out and the exported `buildSessionData` reused by share snapshots.
- Added `share.test.ts` (snapshot/seal/server-url contracts) and `export-subsessions.test.ts`.
- Changed `DEFAULT_RELAY_URL` in `@oh-my-pi/pi-wire` from `wss://relay.omp.sh` to `wss://my.omp.sh` and updated the constants, collab-link, and join-command tests asserting the old origin.
- Added `DEFAULT_SHARE_URL` (`https://my.omp.sh/s`) to pi-wire with its changelog entry; it shares a changed run with the relay constant and is consumed by the upcoming /share work.
- Updated collab-web canonical/OG/twitter URLs in `index.html`, `robots.txt`, `sitemap.xml`, README, and the `local-relay.ts` doc comment to the new domain.
- Refreshed the `/collab` entry in the coding-agent changelog to reference the new relay origin.
- Added detached spawn metadata to lifecycle, progress, and executor session payloads so task and evaluator runs can mark background jobs.
- Updated subagent session tracking and HUD rendering to only show active detached spawns.
- Extended HUD tests to verify non-detached sync and eval spawns are excluded while detached flags propagate through events.
- Changed collapsed progress rendering to keep the most recent live agents visible, adding a summary line for folded-away rows.
- Updated collapsed result rendering to preserve failed and aborted agents in the visible set while trimming other completions.
- Refreshed job polling text to document waiting on all running jobs when `poll` is omitted and added tests for both collapsed progress and result display behavior.
- Extended `parseCollabLink` test coverage to reject 16-byte and 40-byte fragments instead of only rejecting short keys.
- Added coverage for full-link fragments to ensure key and write token are parsed when present.
- Updated `GuestClient` test setup so `welcomeFrame` carries a `readOnly` flag into snapshot assertions.
- Enabled read-only mode by wiring snapshot.readOnly through AgentDrawer and Composer to block prompts and controls.
- Added read-only indicators in the header and participant titles for view-only sessions.
- Added SEO and app metadata assets by updating index.html head tags, manifest, robots.txt, and sitemap.xml.
- Updated brand presentation by adding new favicon/OG assets and switching theme tokens to new OMP colors.
- Added write-token generation and validation to distinguish writable and read-only guests.
- Added deep-link support using `https://<relay>/#<link>` with 32/48-byte collab secrets.
- Added full-link and key-only semantics where full links grant writes and key-only links are view-only.
- Added /collab view/status/stop command updates with read-only participant status and join hints.
Gated the Model scope banner suffix on the original scope's explicitThinkingLevel flag and switched the display source back to the pre-default ScopedModel[] so non-explicit scope entries no longer render the global default thinking level.
Fixes#2385
Respect startup.quiet when building the interactive model-scope notification so quiet launches do not emit startup chrome for large enabledModels scopes.\n\nFixes #2386
Fixed the interactive Model scope formatter so unset thinking levels omit the suffix and explicit levels render as id:level.
Added regression coverage for the startup banner list formatter.
Fixes#2385
- Recomputed `tools.discoveryMode: "auto"` in the deferred MCP closure in `sdk.ts` once the real tool count is known: a toolset crossing the threshold now flips discovery on, registers and activates `search_tool_bm25`, and skips `activateAll` instead of force-activating every MCP tool.
- Guarded the deferred MCP task against disposed sessions: added `AgentSession.isDisposed` and `enableMCPDiscovery()`, and the late connect now calls `disconnectAll()` instead of refreshing tools onto a dead session.
- Cleared `#fastPathKey`/`#fastPathItems` in `AssistantMessageComponent.invalidate()` so theme/symbol changes rebuild reused Markdown children instead of keeping stale captured themes.
- Memoized unusable read summaries as a `false` sentinel in `read.ts` so the per-session LRU no longer retains full sources of unsummarizable files.
- Broadened `HAS_REF_DEF` in `markdown.ts` to match backslash-escaped reference labels (`[a\]b]: x`) and cleared frozen stream-lex state on blank `setText()`.
- Added regression tests: deferred auto-discovery flip and mid-connect dispose (`sdk-mcp-auto-discovery.test.ts` + `many-tools-mcp.ts` fixture), fast-path child rebuild on invalidate, and escaped-ref-def incremental-lex equivalence.
Reviewer flagged that the bracketed-paste path is untrusted terminal input —
ANSI escapes, control chars, newlines/tabs, or a multi-hundred-char path
would corrupt the status line (per AGENTS.md TUI sanitization rules) and
leak the absolute home-dir path.
The new ENOENT diagnostic now feeds the path through sanitizeText (strip
ANSI/C0/C1 controls), collapses CR/LF/TAB to single spaces, runs it
through shortenPath (collapse home → '~'), and truncateToWidth-clamps it
to TRUNCATE_LENGTHS.CONTENT (80) before interpolating into either the SSH
or local status string. Added a third assertion to the repro test
defending the contract: ANSI/control bytes never reach the status, and
the displayed path is bounded below the input length.
Refs PR #2376
- Added optional `isError` markers on inline tool-result and message models.
- Skipped error-marked tool results during swap planning, savings estimation, and live transformations.
- Added tests confirming large error tool results stay text-only and are not considered for inline swaps.
When a local terminal forwards a bracketed-paste containing an image-file
path and the omp process is itself running on the remote end of an SSH
session, the path is on the user's local machine and unreachable from the
remote filesystem. The path-as-text fallback in handleImagePathPaste then
made it look like the image was attached when in fact only a useless
absolute path entered the editor and the bytes never crossed.
Distinguish ENOENT from other read failures: drop the misleading
path-as-text degrade, and surface a clear status that names the file and
— when SSH_CONNECTION/SSH_TTY/SSH_CLIENT indicate the remote end of an
SSH session — points the user at the clipboard image-paste shortcut so
the bytes actually cross. The ImageInputTooLargeError and unknown-error
branches keep their existing fallback so genuine type issues still
yield the user's input back to them.
Fixes#2375
Dynamically assigns segment colors by sweeping across the full HSV hue spectrum based on their track position. This ensures each segment has a distinct, predictable hue and removes the need for explicit `color` assignments.