After the resolve tool became xd:// devices, ToolView.executeXdevDispatch
unwraps xd://resolve/reject/propose writes so the card model lives on the
unwrapped inner details and the device name, but tools/resolve.tsx still
read action/reason from args, rendering a "?"/warn badge. The renderer now
derives the card kind (apply/discard/propose) from inner details first,
falling back to args and to the device-name default for running cards, and
surfaces propose plan metadata. registry.ts also registers reject/propose
and the historical hub-family aliases (irc, job, await, poll, cancel_job)
so those transcript names stop falling back to generic JSON.
Fixes#5640
Both onKeyDown handlers in Composer.tsx committed on Enter without checking
IME composition state, so confirming a Korean/Japanese/Chinese composition
with Enter re-committed the composing character (한글 -> 한글글).
Extract a shouldSubmitOnEnter predicate that returns false while
nativeEvent.isComposing or a composing ref is set, and a useCompositionGuard
hook that tracks compositionstart/compositionend with a deferred reset for
the WebKit case where the confirming Enter keydown fires after
compositionend. Wire both AskEditor and Composer to it.
Fixes#6163
- Added the `xd://` virtual device protocol (`internal-urls/xd-protocol.ts`, `tools/xdev.ts`): tools declaring `loadMode: "discoverable"` are unmounted from the request tools array and driven via `read xd://` (list/docs+schema) and `write xd://<tool>` (execute), gated by the `tools.xdev` setting (default on) and inlined into the system prompt.
- Merged the `irc`, `job`, and `launch` tools into a single `hub` tool (`tools/hub/`, `async/job-manager.ts`): messaging keeps `send`/`inbox`/`list`, job control maps to `wait`/`cancel`/`jobs`, process supervision keeps `start`/`logs`/`stop`/`restart`/`describe` with `ps`, and the unified `wait` races background jobs against peer messages; SDK `IrcTool`/`JobTool`/`LaunchTool` are replaced by `HubTool`.
- Removed the hidden `resolve` tool in favor of the `xd://resolve`/`xd://reject`/`xd://propose` resolution devices, auto-including `write` whenever a deferrable tool or plan mode is present.
- Removed the BM25 tool-discovery system: the `search_tool_bm25` tool, the `tool-discovery` module, the `tools.discoveryMode`/`mcp.discoveryMode`/`mcp.discoveryDefaultServers`/`tools.essentialOverride` settings, per-tool MCP selection, and the `mcp_tool_selection` message type.
- Unified tool presentation on `ToolLoadMode` (`essential`|`discoverable`), replacing the custom-tool `xdev?: boolean` opt-out; custom, extension, MCP, RPC host, image-generation, and TTS tools now default to `discoverable`, and added a `satisfies` predicate to `SoftToolRequirement`.
- Removed the standalone `ssh` command tool and `ssh/ssh-executor` (the `ssh://` read/write/search protocol stays), and made `--tools` address hidden built-ins.
- Updated collab-web to render `xd://` dispatches and `hub` op families, dropped the `search_tool_bm25`/`ssh`/`report-finding` renderers, refreshed tool docs and prompts, and migrated the affected tests and changelogs.
- Routed user and custom message text through the sanitized Markdown renderer.
- Increased spacing between adjacent assistant content blocks.
- Added host and guest Markdown regression coverage.
Fixes#5559
- Render deduped active tool cards with the execution args carried by ActiveTool.
- Covered differing raw assistant args and effective active args in the transcript regression test.
Fixes#4948
- Dedup active tools against committed assistant tool calls as well as the stream ghost.
- Hide the working shimmer while active tools are rendering, preserving it for between-tool model work.
- Added focused Transcript regression coverage for duplicate cards and stale shimmer.
Fixes#4948
- Added `normalizeSingleStringField` to dynamically map misplaced string inputs to required schema fields for single-argument tools.
- Integrated argument normalization into `validateToolArguments` to handle model-specific variations in JSON payloads during validation passes.
- Updated `coding-agent` streaming and rendering components to recognize `_input` as a legacy alias for `input` across various UI paths and logic flows.
- Refactored `hashlineEditParamsSchema` to strictly enforce the `input` field while maintaining support for legacy aliases via runtime coercion rather than schema definition.
- Corrected unit tests to reflect that `_input` is rejected by the strict schema but handled gracefully by the validation layer.
- Replaced `grep`, `glob`, and `ast_grep` `paths` inputs with optional single `path` strings while preserving default workspace-root behavior.
- Added shared `toPathList` normalization for legacy arrays and JSON-encoded arrays across tool execution and TUI renderers.
- Updated prompts, fixtures, shims, transcript summaries, and tests to send and display the new `path` argument.
- Updated collab-web search tool cards to read `path` while falling back to legacy `paths` for historical transcripts.
- Recorded the contiguous coding-agent changelog run for the tool-path breaking change and adjacent TTS entries.
- Extracted `AskEditor` into a standalone, key-bound component keyed by `reqId`.
- Preserved user-typed draft state across duplicate incoming host requests of the same ID.
- Reset the editor draft state only when a genuinely new request ID arrives.
- Simplified `Composer` autosizing logic and state orchestration by isolating editor-specific hooks.
- Adjusted integration tests to match HTML structure changes of the submit action.
- Prevents connection hangs during initial join by immediately failing when a host rejects a guest prior to welcome.
- Short-circuits the connection welcome timeout upon receiving a pre-welcome error frame.
- Surfaces exact protocol mismatch and hello rejection reasons directly to the joining guest interface.
- Ensures `CollabGuestLink` and `GuestClient` transition immediately to ended/failed states with host error details.
Dropped trim and empty gating in the collab web composer so custom ask editor responses ship exactly what the user typed, matching HookEditor's local submit.
- Renamed the `find` and `search` tools to `glob` and `grep` respectively across the codebase to improve command clarity.
- Implemented full-stack support for the renamed tools, including CLI arguments, system prompts, SDK exports, and tool registration.
- Added automated migration logic in `settings` to transform legacy `find` and `search` configuration keys to their new equivalents.
- Updated the `collab-web` renderer registry to ensure backwards compatibility with legacy tool outputs.
Stripped advisory wrapper tags in the collab web Markdown renderer while preserving escaped advisory content and existing raw HTML escaping.
Added a regression test for assistant advisory blocks in the collab transcript renderer and documented the fix in the collab-web changelog.
Fixes#3559
- Transitioned the eval tool from batch multi-cell execution to a single-step input structure with flat parameters.
- Updated core agent logic, UI components, and documentation to support state persistence across incremental eval calls.
- Restricted bash tool capabilities by requiring explicit use of `read` or `find` instead of `ls` or `find`.
- Added support for Ruby and Julia language runtimes to the eval tool and associated web renderers.
- Refactored `todo` tool to accept a single operation object instead of an `ops` array.
- Implemented parameter normalization to maintain backward compatibility with legacy array-based tool calls.
- Updated tool instructions, documentation, and UI rendering components to reflect the new interface.
- Added compatibility tests to verify rendering and execution for both legacy and current operation formats.
The web guest cleared the welcome timeout as soon as metadata arrived,
but non-empty snapshots had no replacement progress clock while waiting
for snapshot-chunk.final. If the relay stalled after welcome or after a
partial chunk, the client stayed stuck in its loading phase forever.
Mirror the TUI guest's snapshot progress timeout: arm it for non-empty
welcome frames, reset it on each non-final chunk, clear it on final and
on close/end, and end the web session with the same session-snapshot
timeout reason when no chunk progress arrives.
Fixes#3144
The host used to ship the entire transcript inside a single welcome
frame, so a multi-MB session spent the guest's 30s first-welcome
timeout on the relay transfer itself: ~1.3 MB took ~3s, ~4.2 MB took
~12s, and ~13.6 MB never arrived before the guest gave up with
'timed out waiting for the host's welcome'.
Bump COLLAB_PROTO to 2 and split the welcome:
- welcome carries metadata only (header, state, agents, entryCount,
readOnly) and lands in well under one second.
- a train of snapshot-chunk frames (SNAPSHOT_CHUNK_BYTES = 512 KB,
oversize entries ship alone) carries the transcript. Last chunk
flips final: true; an empty snapshot still emits one final chunk.
- the host queues welcome + chunks synchronously inside #handleHello,
preserving the host comment's ordering invariant (later broadcast
frames cannot interleave between them).
- the TUI guest accumulates chunks under a SNAPSHOT_PROGRESS_TIMEOUT_MS
that resets per chunk; only after final does it write the replica
jsonl, switchSession, and render. The first-welcome timeout still
guards arrival of the small welcome.
- the collab-web GuestClient streams entries into the snapshot as
chunks arrive and flips phase to 'live' on final.
Includes a contract test (in-process relay) asserting the welcome is
metadata-only, the chunk train fans the 1.5 MB synthetic transcript
across multiple frames with only the last marked final, and the
flattened entries match the source snapshot.
Fixes#3144
- Stripped `<span>` and `<text>` tags from rendered markdown while preserving their contents.
- Updated HTML entity normalization to handle common special characters and numeric codes within the TUI.
- Ensured whitespace surrounding stripped inline tags is preserved, preventing content merging.
- Renamed the global `INTENT_FIELD` constant from `_i` to `i`.
- Updated documentation strings, type annotations, and test expectations across packages to reflect the new field name.
- Ensured consistent usage of the constant in tool schema construction and intent serialization.
- Moved the `INTENT_FIELD` constant from `@oh-my-pi/pi-agent-core` to the specialized `@oh-my-pi/pi-wire` package to permit broader usage across the monorepo.
- Updated all references across `agent`, `ai`, `coding-agent`, `collab-web`, and `snapcompact` packages to import the constant from the new location.
- Added `@oh-my-pi/pi-wire` as a dependency to all affected packages.
- Added collab.webUrl and rendered browser links as web UI wrappers whose fragments carry relay links.
- Added one-shot /collab qrcode and /collab qrcode-view commands with terminal QR rendering.
- Updated coding-agent and collab-web parsers to prefer parseable wrapper fragments while preserving legacy links.
- Added regression tests and changelog entries for split-host collab links and QR commands.
- Removed render_mermaid from tool discovery, task definitions, and registries.
- Removed renderMermaid setting and prompt/docs references tied to the deleted tool.
- Added maxWidth and theme color options to Mermaid ASCII resolution in markdown flow.
- Re-rendered Mermaid ASCII in both directions and clipped output to available width.
A long session title set the grid column's min-content floor, forcing the
header, transcript, and composer wider than narrow/in-app mobile viewports
and clipping text on the right edge. Pin the single column to the container
width so the title ellipsizes instead of widening every row.
- 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 '-'.
- 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 `packages/collab-web/src/tool-render/`: a per-tool React renderer suite (one view per built-in tool) with common `ToolView` chrome, a `tv-` CSS design system, a registry, and an `<omp-tool-view>` web-component wrapper (`element.tsx`, `standalone.tsx`).
- Switched collab-web transcript `ToolCard` to the per-tool renderers instead of the generic args/result JSON dump, and threaded a `ToolRenderHost` through `Transcript`/`AgentDrawer`/`app.tsx` so task-card agent chips drill into the matching subagent drawer.
- Added `scripts/build-tool-views.ts` plus the `build:tool-views` script bundling the renderers (React included, `</script` escaped) into the gitignored `coding-agent/src/export/html/tool-views.generated.js`.
- Modernized the coding-agent HTML export chrome in `template.html/css/js` to the tool-card design language and added the `<template-tool-views/>` injection point.
- Showed the standard done checkmark for completed rows in the `job` tool renderer; its changelog line shares a changed run with the restyle entries.
- The session-operations doc gained two adjacent lines; the subagent-transcript one belongs to the upcoming /share commit but is inseparable from the tool-view line.
- 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.
- Set chat, composer, and input focus states to use transparent focus-visible outlines with ring border coloring.
- Tuned shell and agent visual tokens including gauge and banner styles.
- Updated relay test WebSocket helpers to queue incoming messages per socket and fetch them through a timeout-aware next-message helper.