Commit Graph
144 Commits
Author SHA1 Message Date
chan1103 044d722a36 fix(ai): scope Anthropic credential identity by organization
One Anthropic account email can hold multiple organizations (a Team seat
plus a personal Max plan), each with its own org-scoped OAuth token and
independent 5h/7d limit pools. Credentials were deduped by bare email, so
logging in with the second subscription silently replaced the first, and
usage reports from the two pools merged into one row with mixed numbers.

- capture organization uuid/name at login (token exchange response, with
  a claude_cli/bootstrap fallback); token refreshes never rewrite it
- key anthropic credential identity as email + org; a legacy email-keyed
  row is claimed in place by the first org-scoped login with the same
  email, and org-less credentials never clobber org-scoped rows
- partition usage-report dedupe and the per-credential usage cache by
  org so the two subscriptions' limit pools stay distinct for rotation
- show the organization in omp usage (redaction-safe) and name the
  stored account/org in the login success message
2026-07-11 22:49:12 +09:00
can1357 59d08172c1 feat(coding-agent): introduced model hub for unified management and search
- 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.
2026-07-11 15:10:53 +02:00
roboomp 497d385ce0 fix(auth): decoupled login success from model refresh
Switched interactive OAuth login to start model discovery in the background after credentials are saved.

Added a regression test that keeps model refresh pending and asserts the success transcript appears immediately.

Fixes #4989
2026-07-09 22:12:17 +00:00
can1357 ba7a8fc420 merge PR #4693: fix(tui): dispose stale session UI renderers 2026-07-08 15:19:40 +02:00
can1357 92b2923f7b fix(coding-agent): normalize fallback chain picker writes 2026-07-08 15:19:39 +02:00
can1357 8d484435c2 merge PR #4535: fix(coding-agent): restore fallback model selection 2026-07-08 15:19:38 +02:00
roboomp 568226abb9 fix(tui): disposed stale session ui renderers
Stopped new-session and session-switch UI paths from detaching active loader/render components without running their disposal hooks.

Added container and loader coverage for disposing children before destructive transcript/status replacement.

Fixes #4686
2026-07-06 08:49:02 +00:00
can1357 f3e372e7bf fix(tui): preserve agent hub persisted gating 2026-07-05 13:39:10 +02:00
roboomp 1ac9802508 fix(coding-agent): restored fallback model selection
- Exposed retry fallback chains in the model settings panel.
- Added a /model action that assigns the selected model as the default retry fallback.
- Cleared retry cooldown suppression when users manually switch models.

Fixes #4533
2026-07-04 16:42:38 +00:00
roboomp 721f6d4a08 fix(mcp): make full URL the primary OAuth copy target so SSH sessions work
Codex review flagged that advertising `launchUrl`
(http://localhost:<omp-port>/launch) as the visible `Copy URL:` breaks
SSH/WSL/headless users: their local browser resolves the URL against
the local machine (no OMP listening) and fails before ever hitting the
provider. On terminals without OSC 8 support, they lose the manual
`/login <redirect>` path entirely.

Every OAuth-facing surface now shows the full authorization URL as the
primary copy target and offers `launchUrl` as an additional "Local
shortcut (this machine only)" line for wide-terminal local users who
want the truncation-safe convenience:

- MCPAuthorizationLinkPrompt renders `Copy URL:` with the full URL and
  appends the local-shortcut row only when `launchUrl` differs. OSC 52
  clipboard staging in the MCP onAuth handler switches to the full URL
  (OSC 52 is a wire-level protocol — the terminal writes to the
  caller's LOCAL clipboard even when OMP is on a remote SSH box).
- LoginDialogComponent.showAuth, selector-controller onAuth,
  setup-wizard sign-in, and the auth-broker CLI mirror the pattern:
  full URL first, launchUrl as an optional local shortcut.
- Setup wizard uses `wrapTextWithAnsi`, not truncation, so the RFC
  7636 §4.3 downgrade bug that motivated launchUrl is unreachable
  through it; still surfaces launchUrl for wide-terminal convenience.

Regression tests in
`packages/coding-agent/test/modes/controllers/mcp-authorization-link.test.ts`
now assert:
- Full URL is the primary `Copy URL:` line so SSH sessions can complete.
- launchUrl still appears beneath as `Local shortcut (this machine only): …`
  when it differs from the full URL.
- No shortcut row when launchUrl is absent OR equals the full URL.
2026-07-03 08:57:55 +00:00
roboomp 97c1d08cce fix(mcp): surface a short launch URL and log Windows opener failures for OAuth
Two independent defects broke /mcp reauth against S256-only providers on
Windows boxes whose PATH no longer references System32:

1. openPath spawned bare rundll32 and swallowed the
   `Executable not found in $PATH` throw with a bare `catch {}`, so the MCP
   controller's outer try/catch was dead and the transcript unconditionally
   claimed "Opening browser automatically...".
2. TUI#prepareLine silently truncates any composed row wider than the
   viewport. MCPAuthorizationLinkPrompt rendered `Copy URL: <full URL>` as a
   single ~271-column line whose trailing parameter is
   code_challenge_method=S256. On the reporter's 270-col terminal the cut
   landed inside that parameter, dropping the method while keeping
   code_challenge — which RFC 7636 §4.3 treats as plain PKCE, which Linear
   correctly rejects with "The plain PKCE method is not allowed. Use S256
   instead."

OAuthCallbackFlow now hosts a `GET /launch` route on the same loopback
callback server it already runs; the route 302-redirects to the pending
authorization URL and is advertised as `OAuthAuthInfo.launchUrl` — a
~30-char copy target no viewport can meaningfully truncate. The MCP OAuth
fallback, /login, setup wizard, auth-broker CLI, and login-dialog all
prefer the launch URL for the visible copy target, keep the full URL in
the OSC 8 hyperlink for click-through, and the MCP flow additionally
stages the copy target on the clipboard via OSC 52 (same pattern the
setup wizard uses).

openPath now resolves rundll32.exe through %SystemRoot%\System32 (with a
C:\Windows fallback when SystemRoot is unset) and logs both synchronous
spawn throws and non-zero exits via the shared logger, so silent
misconfigurations show up in ~/.omp/logs/omp.*.log. The dead try/catch
around openPath in the MCP controller is removed.

Fixes #4418
2026-07-03 08:19:14 +00:00
can1357 51684b4b1d refactor(coding-agent): streamlined codebase by deduplicating helper logic and shims
- Consolidated duplicated inline thinking level comparisons into a unified `concreteThinkingLevel` helper.
- Enhanced legacy tool shims to respect isolated session settings and support legacy options.
- Cleaned up redundant UI render requests and extra status-line updates.
- Refactored `grep` tool shim to configure context dynamically via isolated settings.
- Disabled platform-incompatible shell shim tests on Windows environments.
2026-07-02 02:40:08 +02:00
roboomp 809a8a348d fix(tui): coalesce editor top-border rebuild to render tempo
EventController.handleEvent rebuilt the editor's status-line top border
synchronously on every session event via updateEditorTopBorder(). During
a long-running eval that fires 5-10 events/s, each rebuild ran
StatusLine.getTopBorder → #buildSegmentContext → getCachedContextBreakdown
→ session.getContextUsage → estimateTokens (with JSON.stringify per
toolCall block) — the render pipeline is throttled to ~30 fps, so most
rebuilds were dropped before painting. Combined with a scheduler that
collapsed cadenceDelay to zero whenever a frame overran the 33ms budget,
the TUI busy-looped at ~40-50% CPU.

Fix:
- Editor gains setTopBorderProvider(): a lazy builder invoked once per
  editor render. InteractiveMode installs it in the constructor and on
  setEditorComponent, so the rebuild coalesces to the render tempo
  regardless of event rate.
- Delete updateEditorTopBorder wrapper (now equivalent to
  ui.requestRender) and inline every call site.
- Add adaptive render backpressure: a frame that exceeds
  MIN_RENDER_INTERVAL_MS inflates the next scheduling delay to
  2 * last_frame_cost, capped at 200 ms, targeting a 50% render duty
  cycle instead of pinning the CPU at t=0.

New regression tests:
- editor-top-border-provider.test.ts: provider fires exactly once per
  render, wins over eager setTopBorder, falls back when cleared, gets
  the correct availableWidth.
- adaptive-render-backpressure.test.ts: cheap frames keep the 33 ms
  cadence, a slow frame idles proportionally, pathological frames are
  capped at 200 ms.

Verified with bun test packages/tui/test (all 246 relevant tests pass)
and bun test packages/coding-agent/test/modes (455 tests pass). Three
pre-existing agent-session-handoff snapcompact failures on main are
unrelated (snapcompactSupportedChars binding).

Fixes #4145
2026-07-01 13:51:43 +00:00
can1357 ef7636805b feat(coding-agent): removed canonical model variant selection and tracking
- Removed the canonical model variant indexing, selection, and tracking logic from the model registry and resolver.
- Eliminated the `canonical` sub-command, tab view, search tokens, and equivalence configuration structures from the CLI and model selector components.
- Refined model identification, lookup, and provider fallback resolution to bind exclusively to standard, raw model IDs.
- Relocated the equivalence utility script within the catalog package to support script-only policy generation.
2026-07-01 05:22:42 +02:00
can1357 407c44547b feat(coding-agent/modes): opened the in-session resume picker in a fullscreen overlay
- Migrated the `/resume` session selector from an inline component to a fullscreen overlay.
- Enabled alternate screen buffer borrowing and mouse tracking support for the picker.
- Ensured proper cleanup of the fullscreen overlay during normal termination or shutdown.
- Configured the selector layout to pin keybinding hints and the footer to the bottom of the screen.
2026-06-30 20:39:45 +02:00
can1357 fbad280b57 feat: implemented multi-advisor concurrent runtime with tui management
- Introduced comprehensive support for multiple concurrent, independently-configured advisors via `WATCHDOG.yml` files.
- Implemented a full-screen TUI overlay for managing advisor rosters, models, tools, and instructions.
- Added session-wide advisor initialization, telemetry aggregation, and named transcript isolation.
- Enhanced advisor security and observability with secret redaction in tool results and secure XML attribute encoding.
2026-06-28 12:55:09 +02:00
roboomp f82086f805 refactor(coding-agent): moved Alt+M context gate into setModel
Replaced the controller-side switchActiveModel flag with a currentContextTokens hint on AgentSession.setModel, so the over-context decision is computed against the refreshed candidate metadata. setModel returns whether the live switch happened, and the Alt+M default-role path uses that to gate the live side effects.
2026-06-28 07:13:03 +00:00
roboomp 3765d80cbc fix(coding-agent): fixed alt-m default over context
Decoupled default-role persistence from live model switching when the selected model is below the current session context window.

Updated the model selector regression coverage so the Alt+M Default action remains selectable and advances to thinking selection.

Fixes #3708
2026-06-28 07:04:31 +00:00
can1357 1852329c8c feat(coding-agent): added compact status line thinking level setting
- Added `statusLine.compactThinkingLevel` setting to render the thinking level as a leading icon.
- Replaced the verbose ` · <level>` suffix with a single glyph when compact mode is enabled.
- Updated the status line controller and component to resolve and propagate the new configuration.
2026-06-28 08:04:55 +02:00
roboomp 68db2ce649 fix(tui): track active processing time for time_spent status segment
The time_spent segment rendered Date.now() - sessionStartTime, so an
idle session displayed hours of "time spent" while the agent did
nothing — the only inputs were wall-clock and the unmoving session
start.

Replace sessionStartTime with activeMs in SegmentContext and accumulate
inside StatusLineComponent across agent_start -> agent_end windows.
markActivityStart/markActivityEnd are idempotent (reentrant agent_start
events and superseded agent_end events never double-count); the segment
ticks live during an open window and freezes when the agent yields.
The session-boundary hook drops the now-meaningless wall-clock argument
and is renamed setSessionStartTime -> resetActiveTime; it zeroes the
accumulator and drops any in-flight window so /clear / fresh-session /
joined-collab paths start the meter at zero.

Fixes #3681
2026-06-27 20:50:19 +00:00
can1357 b72b83884d Merge PR #3216: feat: add provider in-flight request limits (@H4vC)
# Conflicts:
#	packages/coding-agent/src/modes/components/settings-selector.ts
2026-06-27 01:39:32 +02:00
can1357 6a83a27e91 Merge PR #3314: fix(tui): auto-hide provider thinking blocks when thinking is off (@oldschoola) 2026-06-26 23:27:40 +02:00
arg3t e894753603 feat(tui): add mermaid rendering toggle 2026-06-26 04:34:44 -07:00
can1357 27ed9f7af7 feat(coding-agent): enabled mouse navigation and fullscreen mode for extension dashboard
- Implemented SGR mouse event routing for dashboard interaction, including tab selection and pane scrolling.
- Added mouse-driven list manipulation in the extension viewer with selection highlighting, click toggling, and wheel navigation.
- Enabled fullscreen alternate-screen behavior and host terminal mouse tracking for the dashboard overlay.
- Integrated hit-testing and row selection logic into the extension list to support unified mouse and keyboard inputs.
2026-06-25 04:02:34 +02:00
roboomp 1b24e0044a fix(coding-agent): restore focus to the live editor-slot owner when a fullscreen overlay closes
When /settings (or the Extensions/Agents dashboard) is open and a tool
approval prompt fires, ExtensionUiController.showHookSelector swaps the
editor out of editorContainer for the HookSelectorComponent. On exit,
the overlay's done() called overlayHandle.hide() + setFocus(editor),
both pointing at the editor captured as preFocus when the overlay
opened — now no longer mounted. The visible approval prompt then sat
unreachable: Up/Down/Enter/Esc routed to the unmounted editor and only
Ctrl+C escaped (issue #3349).

SelectorController now exposes focusActiveEditorArea(), which restores
focus to editorContainer.children[0] (the live slot owner) or falls
back to the editor. Wired into showSettingsSelector, showExtensionsDashboard,
and showAgentsDashboard close paths after overlay.hide().

Tests: unit test verifying focusActiveEditorArea picks the live slot
owner; TUI overlay-focus regression pinning the post-fix contract plus
a 'pre-fix snapshot' test pinning the broken pre-fix behavior so the
restore-from-preFocus assumption can't silently change.

Fixes #3349
2026-06-24 14:24:15 +00:00
oldschoola 579ba6a1dc fix(tui): auto-hide thinking blocks when thinking level is off
Some providers (MiniMax, GLM, DeepSeek) return thinking blocks in
their responses even when reasoning is disabled — the model generates
thinking content regardless of the reasoning_effort parameter.

When the user sets thinking level to "off", they expect no thinking
content to be visible. Previously, thinking blocks would still appear
because the hideThinkingBlock setting was independent of the thinking
level and defaulted to false (show).

Fix: add effectiveHideThinkingBlock computed property that returns
true when hideThinkingBlock is true OR the session thinking level is
"off". All render paths (streaming, transcript rebuild, component
construction) now read the effective value instead of the raw setting.

The toggle (Ctrl+T) is guarded: when thinking is off, it shows a
status message ("Thinking is off — enable thinking to show blocks")
instead of silently no-op'ing or corrupting the persisted setting.

Fixes #626
2026-06-23 16:02:10 -07:00
Brit b1deca6606 feat: add provider in-flight request limits 2026-06-22 02:11:41 +02:00
can1357 5207a98fd8 refactor(coding-agent): simplified temporary model status message
- Inlined the temporary model status formatting logic directly into the controller.
- Removed the unused `formatTemporaryModelStatus` utility function and its associated test.
2026-06-21 07:42:46 +02:00
can1357 176d0a98a0 Merge PR #2995: fix(coding-agent): clarify temporary model picker (@riverpilot) 2026-06-20 22:13:07 +02:00
can1357 31bb2144e7 Merge PR #3100: fix(coding-agent): keep /resume picker scoped to the current folder (@roboomp) 2026-06-20 22:13:01 +02:00
can1357 b717a65fc3 feat(coding-agent): introduced prose-only thinking mode
- Added a `proseOnlyThinking` configuration setting to suppress raw code blocks in AI thinking traces.
- Implemented `formatThinkingForDisplay` utility to replace code blocks with ellipses in the UI.
- Integrated runtime toggling and live refreshing of message components via streaming reveal controllers.
- Added a live tokens-per-second indicator to the assistant thinking pulse.
- Verified logic with new unit and integration tests for thinking block presentation.
2026-06-20 08:51:15 +02:00
can1357 282963ee2f feat(coding-agent): supported omitting thinking summaries
- Added `omitThinking` setting to allow instruction of upstream providers to omit thinking summaries.
- Decoupled UI-level thinking block visibility from backend data retrieval.
- Updated session creation to use `omitThinking` for configuring provider-side summaries.
2026-06-20 08:14:54 +02:00
roboomp de03b0c8ee fix(coding-agent): kept /resume picker scoped to the current folder
The session picker auto-switched into all-projects scope whenever the
current cwd had no sessions, so /resume from a fresh project silently
surfaced every other project's history. The empty-folder hint already
tells users to Tab into all-projects, but the auto-switch made it
unreachable. Both call sites (the /resume slash command and `omp
--resume` startup) now always open in folder scope; `omp --resume`
keeps the global probe only to early-exit with 'No sessions found' when
nothing exists anywhere. The component-level `startInAllScope` option
is deleted along with its callers.

Fixes #3099
2026-06-20 03:43:59 +00:00
Alexander Kirilin a34e5e81a2 fix(coding-agent): resolve temp picker branch conflicts 2026-06-19 20:28:00 -04:00
can1357 9478e3cc5c refactor: replaced ReturnType<typeof setTimeout> with Timer type
- Replaced usage of `ReturnType<typeof setTimeout>` and `ReturnType<typeof setInterval>` with the explicit `Timer` type across the codebase.
- Updated several type definitions and function signatures to use concrete types instead of inferred return types for improved clarity and maintainability.
2026-06-19 17:38:07 +02:00
Alexander Kirilin 21b51b9846 Merge branch 'main' of https://github.com/can1357/oh-my-pi into HEAD 2026-06-19 08:14:15 -04:00
can1357 a9c493db13 feat(coding-agent): added toggleable prompt cache miss markers
- 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.
2026-06-19 07:54:32 +02:00
can1357 bc96f52cb7 feat(coding-agent): forced display reset on thinking visibility toggle
- Replace individual component invalidation with a full display reset when toggling thinking block visibility.
- Ensure stale snapshots of thinking blocks in terminal scrollback are retired correctly.
2026-06-19 04:12:25 +02:00
Alexander Kirilin 395836e593 fix(coding-agent): clarify temporary model picker 2026-06-18 14:18:00 -04:00
can1357 9f16ca4797 feat(tui): enabled tight layout mode with optional 1-char padding reduction
- Added new `tui.tight` setting with default `false` and documented behavior.
- Added global tight-mode APIs and `setIgnoreTight` propagation across Box, Text, and Markdown.
- Handled `tui.tight` updates to refresh UI borders and trigger rerendering.
- Updated key message components to ignore tight mode selectively and preserve intended spacing.
2026-06-17 15:09:55 +02:00
can1357 48decd15d7 fix(coding-agent): fixed context usage tracking to keep status and selector totals in sync
- Added context snapshot metadata to AssistantMessage for prompt and non-message token history.
- Anchored context usage calculations on assistant snapshots and computed percent numerically.
- Updated status-line, /context, selector, and interactive mode flows to share session usage totals.
- Extended status-line cache fingerprinting and invalidation for assistant usage and prompt/tool/skill changes.
2026-06-17 12:24:20 +02:00
roboompandcan1357 51ac8d7995 fix(tui): refreshed git toggle changes live
Routed git.enabled through the status-line settings refresh path so runtime toggles close existing watchers and redraw the top border immediately.

Fixes #2847
2026-06-17 12:24:19 +02:00
can1357 3225e6b4be fix(agent-hub-ui): corrected agent hub render flow in editorContainer
- Fixed Agent Hub display to render in editorContainer instead of floating ui overlay.
- Fixed close flow to clear editorContainer, re-add the editor, and restore editor focus.
- Updated Agent Hub activation tests and removed the probe test fixture.
2026-06-16 23:03:11 +02:00
Bharat Suri b3fa871e48 Fix live web search exclusion updates 2026-06-14 21:31:25 -07:00
can1357 86245d722a fix(coding-agent): gated agent hub opening when no subagents are available
- Added an `isEmpty` getter on `AgentHubOverlayComponent` to report whether no subagent rows were loaded.
- Extended `showAgentHub` with an optional `requireContent` flag so the overlay is disposed early when empty under the double-<- path.
- Added tests for double-<- gating behavior with no subagents, with subagents, and explicit hub-open behavior.
2026-06-14 05:18:35 +02:00
can1357 24c8bb24c6 feat(session): added modular session APIs and rebuilt listing/persistence behavior
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
2026-06-14 02:02:53 +02:00
can1357 3def4a6979 feat(coding-agent-logout/auth-ux): enabled selective OAuth account logout
- Added a credential-picker `/logout` flow for selecting one OAuth account.
- Added optional `/logout` provider argument and unknown-provider error handling.
- Changed logout handling to delete only the chosen credential and keep others.
- Added AuthStorage APIs to list and remove credentials by id, with remote deletion hook.
2026-06-13 17:31:18 +02:00
can1357 c938fe4d27 feat(coding-agent): added focused subagent session mode for main-agent hub navigation
- 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.
2026-06-12 15:37:56 +02:00
can1357 3e90371f5c feat(coding-agent): added collaborative sessions with host and guest command support
- Added AES-GCM room-key crypto, relay link parsing, and invalid-link validation.
- Added `/collab`, `/join`, and `/leave` command handling for collaborative sessions.
- Added startup `join` argument wiring to execute `/join` during interactive launch.
- Added status-line, prompt, and command-routing updates for guest/host collaboration UX.
2026-06-12 10:54:28 +02:00
roboomp 9bec08a952 fix(tui): preserved pending message on thinking toggle
Updated thinking visibility toggles to refresh assistant blocks in place instead of rebuilding the transcript, preserving pending user submissions and loaders before streaming starts. Added a regression test for the Ctrl+T pre-stream gap.\n\nFixes #2370
2026-06-12 07:30:54 +00:00