Commit Graph

487 Commits

Author SHA1 Message Date
can1357 ae0898e3a5 Merge PR #2456: fix(coding-agent): attach clipboard image on stale screenshot paste path 2026-06-14 17:44:28 +02:00
art-wiedzmin e31926e698 fix(coding-agent/modes): fall back to clipboard image when pasted screenshot path is missing 2026-06-14 17:33:17 +02:00
Asaf Mahlev 3c53218e19 feat(extensions): add read-only ctx.models query facade
Expose `ctx.models` to extensions: list() / current() / resolve(spec) /
family(model). Lets extension tools select models the same way core does
(settings-backed aliases, match preferences, canonical-identity family
classification) without reaching into the mutable registry.

- types.ts: ExtensionModelQuery interface + `models` on ExtensionContext
- model-api.ts: createExtensionModelQuery facade
- runner.ts: thread optional Settings; build `models` in createContext()
- sdk.ts + agent-session.ts + extension-ui-controller.ts: pass settings / build models on the direct context literals
- catalog identity: modelFamilyToken() — coarse canonical-backed lineage token
- docs + changelog + tests

Implements #2406.
2026-06-14 17:24:48 +02:00
can1357 b830f7912b feat: unified speech setup and introduced local STT/TTS capabilities
- Added unified `omp setup speech` flow with JSON/check modes and model picker.
- Added local STT pipeline with sherpa workers, recorder/download flow, and streaming inference.
- Added local TTS pipeline with `omp say`, backend selection, and streaming vocalization.
- Replaced legacy speech settings with unified `speech`/`speechgen` configuration keys.
2026-06-14 16:07:44 +02:00
can1357 ff0fc74f53 feat(coding-agent/modes): implemented space-bar hold push-to-talk STT gesture
- Added a space-hold gesture state machine in CustomEditor, tracking repeated spaces, detecting holds beyond SPACE_HOLD_THRESHOLD, and firing start/end callbacks via a release timer.
- Hooked editor space-hold callbacks in InputController so STT toggles on hold start and again on release when STT is enabled.
- Added tests for space-hold start/stop behavior and updated keybinding docs to describe the hold-to-record STT workflow.
2026-06-14 08:34:56 +02:00
can1357 e2e37dcde6 fix(coding-agent): fixed stale loader recovery and updated catalog model constraints
- Stopped and cleared the working loader before auto-compaction and auto-retry.
- Ensured stale loadingAnimation is removed so agent_start recreates the Working loader.
- Set catalog model input/output costs to 0.09/0.18 and reduced maxTokens to 65536.
2026-06-14 06:59:26 +02:00
can1357 c4ef8839d5 feat(tui): added large-paste collapse flow with threshold and attachment fallback
- Added `paste.largeMenuThreshold` setting with default 100 and values 0/100/250/500/1000.
- Added `Editor.onLargePaste` and `Editor.insertPaste` to intercept oversized pastes and expand markers.
- Added threshold-based large-paste routing to show the menu and wrap oversized content for code/XML or attachment fallback.
- Added tests for large-paste interception, fallback behavior, short-paste handling, and marker expansion.
2026-06-14 05:20:55 +02: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 0ee1b111ba fix(coding-agent): fixed duplicate model-role cycle track in chat scrollback
- Moved the ctrl+p model-role cycle rendering from `showStatus` to a dedicated anchored cycle container above the editor.
- Updated InteractiveMode to rebuild the cycle container in place and auto-clear the track after 4 seconds.
- Added tests that validate no scrollback stacking, in-place replacement, and timer-based clearing behavior.
2026-06-14 05:02:04 +02:00
can1357 323c666ebf fix(coding-agent): hardened left-double-tap gesture handling against bursty arrow events
- Hardened left-arrow double-tap handling with a new detector that only fires on a second tap in a 40--500ms window.
- Reused that detector for both Agent Hub opening and focused-subagent return so terminal-synthesized burst taps no longer trigger navigation.
- Added gesture tests for deliberate doubles, burst suppression, minimum-gap filtering, and focused-subagent unfocus behavior.
2026-06-14 04:27:39 +02:00
can1357 98fc23899f Merge PR #2533: renumber image markers when restoring queued messages
# Conflicts:
#	packages/coding-agent/test/input-controller-compaction-image.test.ts
2026-06-14 02:59:17 +02:00
can1357 7ca0ca3b06 Merge PR #2530: restore compaction-queued messages on Alt+Up dequeue 2026-06-14 02:57:25 +02:00
can1357 83b00e79a1 Merge PR #2520: run plan-approval compaction on the plan model 2026-06-14 02:57:19 +02:00
can1357 4d01e5e703 Merge PR #2490: clean up compaction UI lifecycle 2026-06-14 02:57:18 +02:00
can1357 eb5cc85eed Merge PR #2528: emit per-turn token-usage row as standalone block 2026-06-14 02:56:50 +02:00
roboomp 2e431c0c21 fix(coding-agent): renumber image markers when restoring queued messages
`restoreQueuedMessagesToEditor` prepended queued text but appended queued
images to `pendingImages`. Positional `[Image #N]` lookup at submit time
therefore broke whenever the editor draft already held pending image(s):
queued markers (numbered 1..K against their own image list) collided with
draft markers (1..M) and resolved to the wrong images; queued images
landing past slot M were orphaned.

Add `shiftImageMarkers(text, offset)` to `image-references.ts` and have
`restoreQueuedMessagesToEditor` walk each queued message in order,
shifting its markers by the running pending-image count (existing draft
images plus images already pulled in from earlier queued messages). Draft
markers stay untouched because draft images keep their original slots.
Paste markers are left alone — those are owned by the editor's paste store,
not the pending-image buffer, and queued message text never carries
unmaterialized `[Paste #N]` because the editor expands paste markers in
`getExpandedText()` before `onSubmit` fires.

Regression test seeds a draft image + a queued image-message in
`input-controller-compaction-image.test.ts` (per acceptance) and locks the
marker -> image mapping after restore. Unit tests for
`shiftImageMarkers` cover the WxH tail, Paste-marker passthrough, and
the zero-offset no-op.

Fixes #2531
2026-06-14 00:24:28 +00: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
metaphorics f6d69620f9 fix(coding-agent): restore compaction-queued messages on Alt+Up dequeue
restoreQueuedMessagesToEditor only drained the agent steering/follow-up
queue via session.clearQueue(), but the "Alt+Up to edit" pending-bar
hint is rendered for both that queue and ctx.compactionQueuedMessages.
Messages typed while the session was compacting -- including /skill:*
follow-ups, which the follow-up path routes to the compaction queue
before its skill check -- were advertised by the hint yet unreachable,
so Alt+Up reported "No queued messages to restore".

Drain compactionQueuedMessages alongside the agent queue, merged in the
same order the pending bar renders (session-steer, compaction-steer,
session-follow-up, compaction-follow-up). The existing text-join, image
hand-back, and abort paths operate on the merged list unchanged.
2026-06-14 08:39:18 +09:00
metaphorics 0ad4c8525c fix(coding-agent): restore model on compaction cancel and before queue flush
Addresses Codex review on #2520:

- Cancel path: `#approvePlan` returned on `compactOutcome === "cancelled"`
  without restoring the deferred pre-plan model, stranding the next turn on
  the plan model and leaking `#planModePreviousModelState`. The model
  transition now runs for the cancelled outcome too (the operator aborted
  only the compaction, not the approval) before the early return.
- Queue-flush ordering: `executeCompaction` flushes input queued during
  compaction before returning, so the post-return model switch landed after
  the queued turn began streaming (deferred one turn via #pendingModelSwitch).
  Added a `beforeFlush(outcome)` hook to `executeCompaction`/`handleCompactCommand`;
  `#approvePlan` runs the transition through it (and idempotently re-runs it
  afterward to cover the message-count short-circuit).

Tests cover the cancel restore and the before-flush ordering.
2026-06-14 08:33:10 +09:00
metaphorics 67cf33ed2d fix(coding-agent): clean up compaction UI lifecycle
executeCompaction added a transcript Spacer(1) the handoff path never adds; it leaked as an orphan blank line on cancelled/failed compaction (only the OK branch cleared it via rebuildChatFromMessages). Removed it, and on the OK branch the loader is stopped + statusContainer cleared before the rebuild so the live loader no longer composites over the reconciled transcript. The finally block stays as the idempotent cancel/fail safety net.
2026-06-14 08:25:57 +09:00
metaphorics 35307b60a7 fix: emit per-turn token-usage row as a standalone block
With display.showTokenUsage on, the usage row was rendered inside the
assistant block above the turn's tool blocks. Finalizing the assistant
block was therefore deferred, and the late append recommitted the
already-committed tool rows, duplicating them in scrollback (worst with
parallel tool calls).

The assistant block now always finalizes as soon as a tool-call appears,
and the usage row is emitted as a standalone finalized block below the
turn's tool blocks across all three render paths (live event-controller,
transcript rebuild, agent-hub). The now-dead setUsageInfo/#usageInfo path
on AssistantMessageComponent is removed.
2026-06-14 08:17:36 +09:00
can1357 705750453d fix(coding-agent-turn-interrupt/queue-ux): resolved steering abort state
- Replaced queued-message interrupt flow with session abort calls on empty submit and escape.
- Removed interrupting state and notifyInterrupting teardown paths from abort handling.
- Updated AgentSession queue operations to use shared steering and follow-up queue views.
- Propagated isAborting through session state and collab payloads to suppress late updates.
2026-06-13 17:31:25 +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 82d3502897 wip: fsync 2026-06-13 16:48:41 +02:00
can1357 e30c642126 fix: corrected assistant render and reveal logic to skip blank thinking
- Filtered dot-only or blank thinking blocks so they no longer render as assistant thought.
- Adjusted assistant-message and streaming-reveal logic to use visible-thinking helpers for consistency.
2026-06-13 16:26:51 +02:00
can1357 39efdfe91b fix(coding-agent): coalesced queued steer flushes to avoid AgentBusyError interrupt races
- 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.
2026-06-13 15:52:25 +02:00
can1357 21a839fdce fix(coding-agent): preserved working loader during interrupt-queued resumption
- 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.
2026-06-13 14:52:40 +02:00
can1357 a2e63c70b0 feat(coding-agent): enabled discovered MCP server auth and namespaced reauth targets
- Allowed colon-separated MCP server names in validation and updated validation errors.
- Added discovery-aware MCP config resolution for /mcp auth, test, and unauth flows.
- Changed streaming behavior so superseded agent_end events don't stop active loaders.
2026-06-13 14:31:33 +02:00
can1357 bcabe9c4be fix(coding-agent/modes): skipped interrupted agent_end teardown during active streaming
- Short-circuited agent-end handling when a session was still streaming.
- Skipped turn-teardown steps for superseded agent_end events that arrived out of order.
2026-06-13 14:21:06 +02:00
can1357 f573e17e21 fix(coding-agent/modes): fixed Esc handling for compaction, handoff, and retry cancellation
- InputController now dispatched Esc to active viewSession operations, aborting compaction, handoff, and retry directly.
- Removed competing onEscape handler swaps across command and event controllers so overlapping auto/manual flow events no longer overwrote cancellation callbacks.
- Compaction now propagated fetch options and rethrew aborted signals so cancellations were not treated as remote failures.
2026-06-13 00:33:07 +02:00
can1357 e914bf0c32 fix(coding-agent): fixed double-Esc draft clearing and selector display reset
- 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.
2026-06-12 18:12:49 +02:00
can1357 31ff08ef8c fix(coding-agent/modes): fixed focused left-tap handling for subagent sessions
- 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.
2026-06-12 15:41:50 +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 162c9ca422 feat(coding-agent): sealed /share behind encrypted links and embedded subagent transcripts in exports
- 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`.
2026-06-12 15:00:41 +02:00
can1357 09aa87103c feat: added read-only and write-token-based collab links for view-only sessions
- 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.
2026-06-12 13:34:43 +02:00
can1357 612fa22900 chore(coding-agent): removed unused getRoleInfo import in input-controller
- Dropped the dead `getRoleInfo` import from `input-controller.ts` that was failing `biome check` on main.
2026-06-12 11:24:49 +02:00
can1357 d214e2f022 Merge branch 'pr-2182'
# Conflicts:
#	packages/coding-agent/package.json
#	packages/coding-agent/src/config/model-registry.ts
#	packages/coding-agent/src/main.ts
#	packages/coding-agent/src/modes/components/assistant-message.ts
#	packages/coding-agent/src/sdk.ts
#	packages/tui/src/components/markdown.ts
2026-06-12 11:24:26 +02:00
can1357 d9cc9960a0 Merge remote-tracking branch 'origin/farm/4c1bfb4b/fix-remote-image-attachment' 2026-06-12 11:14:09 +02:00
can1357 34ea78e01c Merge remote-tracking branch 'origin/farm/4c1bfb4b/fix-remote-image-attachment' 2026-06-12 11:08:48 +02:00
roboomp 78171daffa style: bun run fix 2026-06-12 09:05:16 +00:00
roboomp 8babcdcbd2 fix(coding-agent): sanitized pasted image path before splicing into TUI status
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
2026-06-12 09:05:07 +00:00
roboomp 8359fb5822 fix(coding-agent): surfaced unreachable image-path pastes over SSH instead of silently inserting the local path
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
2026-06-12 08:56:38 +00: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
can1357 9f79c5e353 feat(coding-agent): Color segment track segments by position on HSV hue band
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.
2026-06-12 10:37:21 +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
can1357 49af8b56d5 feat(packages/coding-agent): enabled model-tuned snapcompact budget limits
- Updated snapcompact selectors and previews to pass `ShapeTarget` into `resolveShape` so `auto` is model-tuned.
- Applied `providerFrameBudget` in session compaction so generated archives stay within provider image caps.
- Replaced inline hard-coded image limits with `providerImageBudget` and skipped rasterization at cap.
- Added OpenRouter inline-transformer tests for cap exhaustion and existing-image budget exhaustion behavior.
2026-06-12 09:00:05 +02:00
can1357 360954c113 feat(coding-agent): added a live snapcompact shape preview to the settings selector
- Added `SnapcompactShapePreview` (`snapcompact-shape-preview.ts`), rendering the highlighted shape variant over the sample text in `snapcompact-shape-preview-doc.md`; `auto` resolves to the active model's winning shape.
- Wired the preview as a footer component below the interactive rows in `settings-selector.ts`.
- Passed `modelApi`, `imageBudget`, and `requestRender` through `SelectorController` so the preview can rasterize against the session model and request repaints.
2026-06-12 07:36:51 +02:00
can1357 35d3afc929 feat(coding-agent): refactored usage command into show/reset subcommands
- Added `handleUsageResetCommand` support to list and redeem usage reset credits.
- Refactored `/usage` into `show` and `reset` subcommands and removed `/reset-usage`.
- Handled ACP/TUI `/usage` flows so `show` reports usage and `reset` redeems credits.
- Kept selected theme setting values dirty-colored while selected in the UI list.
2026-06-12 06:18:44 +02:00
can1357 e6ff1cb47b feat(coding-agent): added live saved-reset listing for all Codex accounts
- Added AuthStorage.listResetCredits to query each stored Codex account from the reset-credits endpoint and return live availability plus active or error state.
- Exposed the new status fetch through AgentSession and switched reset-usage selectors and commands to consume it via toResetUsageAccounts.
- Updated reset-usage UI and slash-command output to show per-account errors and updated empty-state messaging when resets could not be loaded.
2026-06-12 05:32:33 +02:00
can1357 212e05dbbb feat: added Codex saved reset-credit redemption flow to usage tooling
- Added Codex reset-credit models, endpoints, and redemption methods.
- Added reset-credit usage data and cache invalidation for successful redemption.
- Added `/reset-usage` slash command and interactive account selector flow.
- Added contract tests for reset-credit listing, fallback, and consume outcomes.
2026-06-12 05:20:08 +02:00