- theme.ts mixed symbol presets, JSON schema, color math, the Theme class,
loading, global state, appearance handling and TUI adapters in 3171 lines.
- Symbols, schema, color, theme-class, loader and tui-adapters are now
siblings; theme.ts keeps global state, the watcher, appearance handling and
HTML export at 745 lines, with all 44 exports intact.
- Left appearance and export-colors in place: both read private mutable
auto-theme state, so extracting them would have required new exported
internals or DI rather than a straight move.
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers.
- Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies.
- Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
- Introduce `@oh-my-pi/omptype` as a new ArkType-compatible schema validation package featuring a lazy JIT runtime, JSON Schema emission, and compatibility adapters.
- Replace `arktype` across workspace packages and test utilities with `@oh-my-pi/omptype`.
- Add benchmark suites, tests, and documentation for the new validation engine and adapters.
- Update workspace build, test runner, and release configurations to include the new package.
Reverted branch-side edits to spawn-policy prompts/tests, settings tab
groups, mermaid cache typing, prewalk todo gating, and packages/ai test
churn back to merge-base content; trimmed their changelog entries. These
repaired stale CI against an older main and are stale or conflicting
against current main.
- Added `tui.scrollbackRebuild` configuration with interactive startup/controller wiring to apply `setScrollbackRebuild`.
- Exposed prewalk session state in `SegmentContext` and rendered a dedicated prewalk segment/icon in the status line.
- Added divergence-aware TUI full-paint logic that enables scrollback erase-and-replay rebuilds for non-multiplexer divergence cases.
- Updated rendering and streaming tests to verify rebuild behavior (`3J`) and eliminate stale marker expectations under drift scenarios.
- Implemented a consolidated TUI renderer for launch tool operations to unify status headers and metadata.
- Added tracking for unfulfilled readiness conditions to distinguish between timeout causes and daemon states.
- Enhanced timeout reporting to explicitly surface specific unmet log or port conditions.
- Included comprehensive unit and regression tests for tool rendering and start-timeout diagnostics.
- Replaced the legacy model selector with a full-screen Model Hub, introducing mouse support and a fuzzy-searchable browser.
- Integrated comprehensive model management, including role assignment, thinking-level visualization, and manual provider discovery.
- Implemented a cancellable OAuth login flow and integrated it directly into the Model Hub for provider authentication.
- Centralized model logic and migrated existing tests to support the new component architecture.
- Transitioned DeepSeek models to an explicit `[High, Max]` effort ladder, removing stale alias maps.
- Updated the OpenAI compatibility layer to enforce authoritative `supportsReasoningEffort` and `omitReasoningEffort` flags.
- Synchronized `models.json` definitions to reflect accurate reasoning effort capabilities across the catalog.
- Introduced `Max` as a first-class reasoning effort tier across all packages, including AI providers, coding agent configurations, and RPC protocols.
- Refactored model effort ladders to use wire-exact mappings and removed legacy effort aliasing (e.g., `max-to-xhigh` mapping).
- Updated model registry and provider configurations to support `Max` tier routing, color themes, and UI icon associations.
- Expanded test suites to provide end-to-end coverage for the new reasoning tier, including updated compatibility and fallback scenarios.
Timer-driven reveal and spinner ticks (streaming reveal, tool-args reveal,
tool-execution spinner, todo strike animation) now hand the changed
component to `TUI.requestComponentRender(component)` instead of forcing a
full-tree render at 30fps. Every other root subtree reuses its previous
frame rows, cutting the Box/Container tree walk out of the compose
pipeline while the transcript grows.
Shimmer:
- Intern the working-message palette per accent (WeakMap-keyed) so the
Symbol-slot compiled-ANSI cache in `shimmerSegments.compile` actually
hits between frames — the fresh palette literal in `renderWorkingMessage`
guaranteed a per-tick miss.
- Add an `activeBand` fast-path: outside the sweep window the intensity
is guaranteed zero, so those code points coalesce into a single low-tier
run without running `intensityFn` or `tierFor`. On the typical ~60-char
working message the classic band is 12 cells wide, so ~80% of the per-char
loop disappears.
Widen `ToolExecutionHandle` to extend `Component` (matches every
concrete impl — `ToolExecutionComponent`, `ReadToolGroupComponent` —
which already extend `Container`) so the reveal controller callback
sites are type-checked.
Fixes#4377
- Introduced a dedicated advisor rail symbol to differentiate note cards from thinking output.
- Applied bold custom header tags and severity-tinted rails to distinguish advisor notes from surrounding text.
- Shifted note body text to the default content color to prevent blending with dimmed thinking-output styles.
Four tightly-scoped hot-path fixes covering the highest-impact items in the
reporter's CPU profile (13.1 s profiled / 30 s window):
1. `event-controller.ts:handleEvent` no longer fires a blanket
`statusLine.invalidate() + ui.requestRender()` before every session event.
The pre-render was a leftover from #4145 when `updateEditorTopBorder()`
still eagerly rebuilt the border; the lazy provider added in #4145 made
it redundant. It fired on every `message_update`/`tool_execution_update`
during streaming — the pre-render's frame ran while the handler was
awaiting, then the handler's own `requestRender` scheduled a second
identical frame. Every handler that mutates visible state already calls
`requestRender()`.
2. `shimmer.ts:shimmerSegments` iterates the segment string in place instead
of building a code-point array with `Array.from(seg.text)` every animation
frame. Runs of same-tier chars are emitted via a single `slice` per run
rather than accumulating into `runBuf`. Surrogate pairs stay atomic — the
code-point index still advances by 1 per emoji. Microbench over 30k
frames: 45 ms → 18 ms (2.53x), allocation rate down from ~N-per-frame to
a handful per frame. New tests cover mixed BMP+surrogate and all-emoji
inputs. `Array.from` was the #1 self-time hotspot in the reporter's
profile at 10.2%.
3. `Markdown.setText` gains an equality guard mirroring `Text.setText`
(returns `false` when `text === #text`). Providers re-emit identical text
on ticks with no delta (throttled frames, reconciled tool-execution
updates); each of those now short-circuits instead of dropping
`#cachedLines` and forcing a full lex + wrap on the accumulated paragraph
(the reporter's #3 hotspot at 8.4%). New test asserts render-reference
stability + return-value semantics.
4. `SPINNER_RENDER_INTERVAL_MS` aligned with `SPINNER_GLYPH_ADVANCE_MS`
(both 80 ms). The previous 33 ms cadence emitted ~2.4 paints per glyph
step; the differential-output dedup only skips the write, not the
compose walk. Visually identical (glyph advance was already 12.5fps),
halves paints during tool execution.
Skipped (out of scope for a bug fix, deserve dedicated PRs):
- Freezing streaming prefix on single `\n` boundaries — correctness-bound
to `\n\n` block separators (CommonMark loose-list continuation).
- Compose-phase idle gate + adaptive-backpressure moving-average — need a
component-level dirty flag; the 200 ms cap in `#scheduleRender` was set
for a reason (#4145 tail-latency guard).
Tests updated: two IRC-expiry tests in event-controller-message-start.test.ts
that were asserting the pre-render's second `requestRender` call now expect
one.
Fixes#4353
Add the read.renderMarkdown setting (off by default) to render Markdown read results as formatted terminal Markdown previews instead of raw source.
Centralize Markdown detection in isMarkdownPath() (now covering .md, .markdown, .mdx, .mdc, .mkd, .mdown) and use it consistently across the read tool and all internal-URL protocols (local, memory, skill, ssh, vault) so the preview renderer recognizes Markdown files uniformly. Markdown read results stay verbatim for the model; only the TUI rendering changes.
- Added `git.repo.linkedWorktreeSync` to identify and resolve git worktree metadata without spawning subprocesses.
- Updated `StatusLineComponent` to detect linked worktrees and resolve project/worktree context names.
- Modified path segment rendering to collapse nested git worktree paths and display the worktree name when it diverges from the active branch.
- Introduced `icon.worktree` symbol across themes to visually distinguish git worktree paths.
- Enhanced the edit renderer to support visual tracking of delete and move/rename operations.
- Updated diff computation to correctly handle file-level changes and suppress erroneous "No changes" warnings.
- Improved terminal output with a clearer activity indicator and accurate state representation during multi-file operations.
- Extended the rendering pipeline to display source-to-destination paths for file renames and added validation tests for edit workflows.
Reconcile the friendlyName secret feature with upstream's secret-obfuscation
refactor (7302a7ae96):
- obfuscator.ts: keep upstream's typed message-transformer layer
(deobfuscateAgentMessages/AssistantContent/ToolArguments, obfuscateMessages,
narrow obfuscateProviderContext, obfuscateToolArguments, mapJsonStrings) as
the canonical API; retain the PR's SecretObfuscator class internals
(friendlyName + keyed-hash placeholders, case hints, legacy aliases,
idempotent re-obfuscation, replace-mode hardening).
- Integrate upstream's <8-char secret toning + hasRealSec into the class.
- Thread allowLegacyAliases through the typed deobfuscation transformers so
display-only transcripts still restore legacy index-derived aliases while
agent-feeding paths stay keyed-only.
- Lengthen friendlyName test secrets to >=8 chars to satisfy toning; tool-result
content is no longer deobfuscated (typed transformers walk assistant/summary
roles only).
- Introduced `web-palette.ts` to implement the collab-web pink/purple brand identity for HTML exports.
- Updated `generateThemeVars` to support a `palette` option, allowing users to choose between the brand-web aesthetic and a specific TUI theme.
- Configured public exports and the share-viewer script to default to the brand-web palette rather than inheriting the user's terminal theme.
- Refactored `AgentSession.exportToHtml` to align with the new branding defaults while allowing for per-export theme overrides.
- Adjusted `dark.json` background values to ensure better visual consistency across internal surfaces.
- Switch all UI components and tests from sharp box corners (`boxSharp`) to rounded ones (`boxRound`).
- Update `Theme` to re-export sharp junction symbols (tees and cross) under `boxRound` to ensure consistent divider rendering in rounded boxes.
- Remove outdated architectural notes regarding forced tool-choice queues in documentation.
- Added `display.cacheMissMarker` setting to enable visual indicators for prompt cache invalidation in assistant messages.
- Included updated theme symbols to represent cache misses across supported icon sets.
- Configured the selector controller to rebuild the chat display when the marker visibility setting is toggled.
- Added `typeof theme === "undefined"` guards to all four theme getters.
- Fallbacks return a usable plain-ASCII or plain-text theme instead of crashing.
- Added a pre-init test asserting the getters never throw.
- Added `#disposed` flags and guards to `StatusLineComponent` to stop async callbacks running post-dispose.
- Updated `onThemeChange` to return an unsubscribe function and registered it in `InteractiveMode`.
- Fixed schema validation for `spinnerFramesSchema` to narrower types instead of dynamic or-validation.
- Resolved settings leaks by saving and restoring `tuiTight` state in tests.
- Added regression tests verifying that pending async microtasks do not trigger updates after disposal.
- Migrated all wire protocol, schema definitions, and tools validation from Zod to ArkType across multiple packages.
- Updated extension runtimes, custom tools loader, and TypeBox compatibility shim to expose and use ArkType instances.
- Added a comprehensive ArkType migration guide, validation parity tests, and helper utilities.
- Removed redundant PDF asset routing and parsing implementations from the read tool.