Commit Graph
2890 Commits
Author SHA1 Message Date
roboomp 4f20d10454 fix(tui): attached pasted file paths
Converted bracketed non-image filesystem path pastes into session-local attachment references while preserving the existing image path flow.

Added regression coverage for editor routing and controller local file attachment behavior.

Fixes #3360
2026-06-24 14:21:45 +00:00
roboomp bd06c5dd4e fix(coding-agent): honor app.message.followUp chord in ask prompt-style editor
The ask tool's "Other (type your own)" free-text input is a prompt-style
HookEditorComponent. The hook-style branch already called matchesAppFollowUp
(Ctrl+Q / Ctrl+Enter) so Windows Terminal users — which can't deliver a
distinct Ctrl+Enter (#1903 / fixed by #1905) — had a working chord on the
main editor, hook editors, and the agent dashboard. The prompt-style branch
did not, so Ctrl+Q was unbound and Ctrl+Enter fell through to Editor as a
newline that WT silently swallowed: pressing Ctrl+Enter did nothing.

#handlePromptStyleInput now checks matchesAppFollowUp before the rest of
the dispatch (mirroring #handleHookStyleInput), so plain Enter remains the
primary submit and the chord is a secondary submit for cross-terminal
muscle memory. The prompt-style hint now reads "enter or ctrl+q submit"
so the fallback is discoverable.

Fixes #3353
2026-06-24 14:12:05 +00:00
roboomp e261848293 fix(settings): coerced rendered settings values
Coerced malformed YAML-derived settings values to strings before they reach settings row truncation. Added regression coverage for numeric enum display values.

Fixes #3338
2026-06-24 13:53:06 +00:00
roboomp de87923add fix(tui): theme-aware welcome tip line for light-theme legibility
The welcome 'Tip:' line hardcoded #b48cff (label) and #9ccfff (body)
with an additional \x1b[2m dim on the body, ignoring the active theme.
On any light theme this dropped the body to ~1.5:1 contrast on a white
background (WCAG AA needs >=4.5:1), making the line effectively
invisible. Switching between light variants did not help because the
colors were not theme-derived.

renderWelcomeTip in packages/coding-agent/src/modes/components/welcome.ts
now paints the label through theme.fg('customMessageLabel', ...) and the
body through theme.fg('muted', ...), drops the manual dim, and wraps the
whole line with theme.italic(...). Both tokens are tuned per theme, so
the line stays vivid on dark backgrounds and readable on light ones
(e.g. light theme's customMessageLabel #7e57c2 = 5.21:1 on white).

A regression test pins the contract: dark/light themes must produce
different bytes for the same tip, and no manual \x1b[2m may remain.

Fixes #3337
2026-06-24 13:44:21 +00:00
oldschoola 705a2636fb fix: gate resetDisplay on actual thinking visibility transition
Address P2 review: auto-classification (e.g. high→medium) emits
thinking_level_changed without changing effectiveHideThinkingBlock.
The unconditional resetDisplay() turned routine auto-classification
updates into a full terminal replay on direct terminals.

Track #prevHideThinking and only call resetDisplay() when the effective
visibility actually changed. For effort-only changes, use a lightweight
requestRender() instead.
2026-06-23 16:13:41 -07:00
oldschoola f0dfa631ce fix: resync streaming reveal controller when thinking level changes
Address P2 review: StreamingRevealController caches #hideThinkingBlock
in begin()/setTarget(). When thinking level changes mid-stream, the
timer's #tick() kept rendering with the stale cached value, causing
provider-returned thinking to reappear after the off state.

Add resyncVisibility() method to StreamingRevealController that:
- Re-reads #hideThinkingBlock and #proseOnlyThinking from getters
- Recalculates visible units (hiding thinking reduces total)
- Clamps #revealed to new total (prevents over-revealing)
- Re-renders with #renderCurrent() using updated values
- Resyncs timer via #syncTimer()

Call resyncVisibility() in the thinking_level_changed handler instead
of streamingComponent.updateContent().
2026-06-23 16:06:20 -07:00
oldschoola 04c3199511 fix(usage): normalize newlines in provider notes before rendering
sanitizeText preserves newlines (\n) which break TUI line layout when
injected into a single rendered row. All notes rendering sites now
replace \r\n sequences with spaces before sanitization:

- command-controller.ts: provider-wide notes (line 1591) + per-group
  notes (line 1666)
- usage-report.ts: provider-wide notes (line 58) + per-limit notes
  (line 90, previously completely unsanitized)
- usage-cli.ts: provider-wide notes (line 455)
2026-06-23 16:02:26 -07:00
oldschoola 76bbd77eac fix(usage): sanitize report-level notes before TUI rendering
Address review feedback: provider notes could contain tabs, embedded
newlines, or control characters that break TUI rendering. Both note
rendering sites (provider-wide and per-group) now wrap the joined text
through sanitizeText → truncateToWidth → replaceTabs per AGENTS.md
TUI Sanitization rules.
2026-06-23 16:02:25 -07:00
oldschoola 6c3f35dfef fix(usage): dedup provider-wide notes and add report-level notes field
Provider-wide disclaimers (e.g. OpenCode Go's "OMP-observed spend
only") were duplicated onto every UsageLimit, then repeated N times
in the TUI aggregate renderer (once per account × window). With
2 accounts × 3 windows, the same disclaimer appeared 6 times
bullet-joined.

Structural fix:
- Add notes?: string[] to UsageReport (interface + both schema
  copies: usage.ts and auth-broker/wire-schemas.ts) so the field
  survives the broker client's "+": "reject" deserialization gate.
- Move opencode-go's disclaimer from per-limit notes to
  provider-level notes.

Defensive fix:
- Dedup identical per-limit notes in the TUI aggregate renderer
  (command-controller.ts) via [...new Set(...)].
- Render provider-level notes once above per-account sections in
  all three rendering paths: TUI (command-controller), CLI
  (usage-cli), and ACP (usage-report helper).

Regression tests:
- usage-cli.test.ts: provider-level notes render once, not
  duplicated per account or limit; positioned above per-account rows.
- usage-report-notes-schema.test.ts: wire-schema round-trip proving
  notes survives usageResponseSchema validation.

Fixes #3268
2026-06-23 16:02:25 -07:00
oldschoola a6ded987ed fix(usage): move scope fallback before empty-string guard to prevent metadata suppressing valid scoped fallback 2026-06-23 16:02:18 -07:00
oldschoola 7023255d83 fix(usage): replace inline casts with typeof guards in TUI renderer
The TUI usage renderer (command-controller.ts) used 'as string |
undefined' inline casts to read email/accountId/projectId/planType
from UsageReport.metadata (Record<string, unknown>). These casts
fabricated the type without runtime validation, violating the
ts-no-inline-cast-access rule.

Replaced all casts with typeof guards. This also fixes a behavioral
edge case: empty-string metadata values ('') previously passed
through the ?? chain and were displayed as the account label.
With the typeof guard, empty strings are falsy and fall through to
the next fallback (scope.accountId, scope.projectId, or 'account N').

Affected functions:
- formatAccountLabel (limit + report identity resolution)
- formatUnlimitedReportLabel (report-only identity resolution)
- resetAccountLines label (saved-reset credits display)
- unlimitedReports tier (plan type suffix)
2026-06-23 16:02:18 -07:00
oldschoola 437e131c54 fix(usage): use shared resolveUsedFraction in TUI path, fixing missing remainingFraction fallback
The TUI usage renderer (command-controller.ts) had a local
resolveFraction() that was missing the inverted-remaining fallback
present in the shared resolveUsedFraction() from @oh-my-pi/pi-ai:

  // Shared (usage.ts) — has this:
  if (amount.remainingFraction !== undefined)
    return Math.max(0, 1 - amount.remainingFraction);

  // Local (command-controller.ts) — was MISSING this

This meant the TUI path failed to resolve a fraction for limits that
only populate remainingFraction (no usedFraction, used/limit, or
percent+used) — showing an empty bar instead of the correct fill.

The CLI path (usage-cli.ts) already used the shared function and
handled these limits correctly.

Replaced the local resolveFraction with the shared resolveUsedFraction
from @oh-my-pi/pi-ai, eliminating the duplication and fixing the bug.
2026-06-23 16:02:16 -07:00
oldschoola f8ec04871f fix: propagate thinking level changes to existing components and use viewSession
Address 4 P2 review comments on PR #3314:

1. effectiveHideThinkingBlock now uses viewSession.thinkingLevel
   instead of session.thinkingLevel — in focused-agent mode, the
   viewed transcript may have a different thinking level than the
   main session.

2. thinking_level_changed handler now iterates existing
   AssistantMessageComponent children and calls setHideThinkingBlock
   with the new effective value, then resetDisplay() to repaint.
   Previously only new/streaming messages got the updated visibility.

3. Changed AssistantMessageComponent import from type-only to value
   import for instanceof check.

4. Agent Hub callback already uses effectiveHideThinkingBlock which
   now reflects viewSession — no separate fix needed.
2026-06-23 16:02:10 -07:00
oldschoola ff249f19e9 fix(tui): check thinking level directly instead of effectiveHideThinkingBlock
The previous guard used effectiveHideThinkingBlock which combines
hideThinkingBlock preference AND thinking-off state. When thinking
was enabled but hideThinkingBlock was true (user manually hid blocks),
the guard blocked the toggle, preventing users from showing blocks
again via Ctrl+T.

Fix: check session.thinkingLevel === Off directly, so the guard only
fires when thinking is genuinely off. When thinking is on, the toggle
works normally regardless of the current hideThinkingBlock preference.

Updated tests to set thinkingLevel on the mock context.
2026-06-23 16:02:10 -07:00
oldschoola c77fdffea9 fix(tui): guard both no-op cases for thinking toggle when thinking is off 2026-06-23 16:02:10 -07: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
oldschoola eb56da7d18 fix(welcome): replace stale ? shortcut with /hotkeys in tips panel
The welcome panel advertised '? for keyboard shortcuts' even though
the ? shortcut was deliberately removed in commit dcf482c4c
('fix(editor): removed ? shortcut that opened hotkeys when input was
empty'). Users typing ? on an empty prompt got a literal question
mark submitted to the model instead of the help panel they expected.

Replace the stale claim with '/hotkeys for keyboard shortcuts',
matching the actual command that opens the shortcut reference.

Fixes #1614
2026-06-23 16:02:08 -07:00
oldschoola a6bfb8c0e1 fix: record slash commands with inline prompts to history
Address P2 review: when executeBuiltinSlashCommand returns a string
(e.g. /loop 10 fix bug → 'fix bug'), the original slash command text
was not recorded to history — only the extracted prompt was. Now the
original text is added to history before reassigning, so Up Arrow
recalls '/loop 10 fix bug' rather than just 'fix bug'.

Applied to both Enter and Ctrl+Enter submit paths.
2026-06-23 15:23:14 -07:00
oldschoola 00fd6f2263 fix: handle colon-separator bypass and /join secrets in history filter
Address three P1 code review comments on PR #3352:

1. Colon-separator bypass: parseSlashCommand() treats ':' as an argument
   separator, but shouldSkipHistory only split on whitespace. So
   /login:?code=abc&state=xyz bypassed the filter. Now uses the same
   earliest-whitespace-or-colon splitting as parseSlashCommand.

2. /join <link> secret: the collab join link carries a 32-byte room key
   and optional write token. Add /join to the denylist — skip any /join
   with arguments.

3. Added regression tests for colon-separator forms and /join denylist.
2026-06-23 15:01:07 -07:00
oldschoola c6c2c386bc fix: skip all /login args from history (P1 security review)
parseCallbackInput() accepts three forms: redirect URLs, query strings
(?code=...), and raw auth codes — all carry OAuth secrets. The previous
filter only skipped URL-like inputs, leaking query strings and raw codes.

Skip ALL /login commands with any argument. The minor convenience loss
(can't recall /login <provider>) is far less important than the risk of
persisting OAuth authorization codes.
2026-06-23 14:17:35 -07:00
oldschoola 715eb0792c fix: store slash commands in input history (#3148)
Previously only 4 commands (/plan, /goal, /mcp, /ssh) stored their text
in history via per-handler addToHistory calls. All other built-in slash
commands were silently skipped because executeBuiltinSlashCommand returned
true before the input controller's addToHistory was reached.

- Centralize history recording in the input controller after successful
  slash command dispatch, for both Enter and Ctrl+Enter submit paths.
- Remove all 10 per-command addToHistory calls from slash command handlers
  to prevent duplicates.
- Add shouldSkipHistory() security filter to exclude commands that may
  carry secrets: /login <url> (OAuth callback with code=/state= params)
  and /mcp add --token <token> (bearer token).
- Add regression tests for the security filter (8 cases).
- Update 7 existing test files to remove handler-level addToHistory
  assertions (now the input controller's responsibility).
2026-06-23 14:11:12 -07:00
oldschoola 639b6195fa feat(usage): show expiry dates for banked Codex rate-limit resets (#3339)
The /usage display (TUI, ACP text, and omp usage CLI) now shows when
banked Codex rate-limit resets expire, so users can plan when to redeem
them before the 30-day window lapses.

Changes:
- Added UsageResetCreditDetail interface (grantedAt, expiresAt, status)
  and optional credits field to UsageResetCredits in packages/ai
- Updated both ArkType schema copies (usage.ts + wire-schemas.ts)
- The OpenAI Codex usage provider now calls listCodexResetCredits to
  fetch individual credit details when availableCount > 0, filtering
  out redeemed credits. Errors are logged and swallowed (graceful
  degradation: count shows without expiry dates)
- TUI (command-controller.ts): shows per-credit expiry as relative time
  + absolute date under each account line
- ACP text (usage-report.ts): same per-credit expiry rendering
- CLI (usage-cli.ts): shows the soonest expiry date in the account header
- 2 new tests: credit detail fetching with expiry dates, and no extra
  API call when availableCount is 0
2026-06-23 11:58:29 -07:00
Alexander Kirilin 881ae78010 fix(tui): include tiered Codex usage limits 2026-06-23 07:58:11 -04:00
Mathews-Tom ea65e8a2f2 Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names
# Conflicts:
#	packages/coding-agent/src/eval/__tests__/julia-prelude.test.ts
2026-06-23 17:12:13 +05:30
can1357 92d03466b7 Merge branch 'farm/c8a3da70/fix-resume-delete-scroll' into resume picker
Resolve the session-selector.ts conflict by integrating the delete-dialog
content-slot fix (#3283) on top of the fullscreen mouse-picker refactor.

The branch swapped the delete-confirmation dialog INTO a single content
slot (replacing the SessionList) so the picker is always
`chrome + max(list, dialog) + chrome` and never overflows the viewport.
Adjustments baked into this merge:

- Wrap the SessionList in `#contentSlot` and keep the dialog swapping into
  that slot, but preserve the new fullscreen path: mouse hit-testing,
  the pinned footer (`#footerLines`/`#footerStart`), and fill-height
  trimming all still work because the render offset now tracks
  `#contentSlot` (the list lives one level down).
- Keep both CHANGELOG entries (picker mouse/fullscreen + #3283 fix) and
  the ported scroll-stability regression test.
2026-06-23 02:46:56 +02:00
can1357 cffb804d3a feat(coding-agent): added mouse support and fullscreen rendering to session picker
- Enabled fullscreen overlay rendering for the terminal session picker.
- Implemented full mouse support including wheel-based scrolling and click-to-select functionality.
- Anchored the session picker footer to the bottom of the viewport to correct UI flickering.
- Added comprehensive unit tests for mouse interaction and layout constancy during resizing.
2026-06-23 02:25:30 +02:00
roboomp e266782604 fix(session-selector): swap delete dialog into SessionList slot
Earlier rounds shrank the SessionList by the dialog's row count to keep
the picker inside the viewport, but the SessionList could only claw back
whole session rows and bottomed out at zero entries. On a narrow
terminal with a long session title the dialog still wrapped past what
the SessionList could free, the picker overflowed the viewport, and the
TUI committed the header into native scrollback.

The picker now hosts the SessionList inside a single contentSlot
Container. Opening the delete confirmation swaps the dialog INTO that
slot (replacing the SessionList); closing it swaps the SessionList back.
The dialog therefore competes only with the SessionList's rendered
budget, not with the SessionList AND the picker chrome, so the picker
frame stays bounded by terminalRows even when the dialog wraps to many
rows. SessionList's external-reserve plumbing is no longer needed and is
removed.

Addresses PR #3285 second-round review feedback.
2026-06-23 00:05:53 +00:00
roboomp 964dc480c9 fix(session-selector): derive delete-dialog reserve from rendered height
The first round of the issue #3283 fix reserved a fixed 12 SessionList
rows for the delete confirmation dialog. On a narrow terminal or against
a long session name, HookSelectorComponent's Markdown title and help
text wrap past 12 rows; the picker would still overflow even after the
SessionList shrank to zero entries, and the TUI committed the picker
header into native scrollback again.

SessionSelectorComponent now overrides render() to measure the dialog's
actual rendered height at the live width before super.render() walks
the children, and pushes that as the SessionList's external-row reserve.
The dialog's own Container memoization makes the extra pre-render
essentially free.

Addresses PR #3285 review feedback.
2026-06-22 23:56:25 +00:00
roboomp ecdff42513 fix(session-selector): keep /resume header pinned after delete
The delete-confirmation dialog mounted as a sibling below the picker's
bottom border briefly grew the picker past the terminal height. The TUI's
append-only renderer committed the picker's top rows (header + first
sessions) into native scrollback to fit the dialog within the viewport.
When the dialog closed and the picker re-rendered shorter, `windowTop`
stayed pinned at `#committedRows`, leaving the picker stranded below the
committed prefix — the user saw the header scrolled off the top.

SessionList now exposes `setExternalReserveRows`; SessionSelectorComponent
reserves the dialog's worst-case height while the dialog is mounted so
the picker's total rendered output stays within the terminal viewport
and the TUI never commits its rows.

Fixes #3283
2026-06-22 23:38:11 +00:00
can1357 060f4004e7 feat(coding-agent): refactored eval tool to single-step execution
- 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.
2026-06-23 00:59:58 +02:00
can1357 2ff005a354 fix(coding-agent/modes): resolved escape key handling under kitty keyboard protocol
- Update input handler to recognize CSI-u escape sequences using `matchesKey`.
- Ensure legacy bare escape sequences remain supported in environments without the protocol.
- Add test coverage for both CSI-u and legacy escape inputs.
2026-06-23 00:36:54 +02:00
Mathews-Tom 21d8b0e3f5 Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names
# Conflicts:
#	packages/coding-agent/src/eval/__tests__/julia-prelude.test.ts
2026-06-23 02:23:42 +05:30
Jaaneek 5df96e6c25 fix(coding-agent): complete OAuth code login over RPC
Let RPC hosts answer post-auth OAuth code prompts so manual-code providers like xAI OAuth can finish without a local callback listener.
2026-06-22 20:54:36 +01:00
can1357 5c21b28786 feat: optimized handoff generation and harden request safety
- Introduced `generateHandoffFromContext` to enable provider-aware oneshot generation and improved cache hit rates via the live-turn pipeline.
- Updated `buildSideRequestContext` to support pinning custom system prompts, preventing per-turn hook leakage during handoff.
- Added concurrency guards across CLI and RPC modes to block manual `/handoff` requests while a session is actively streaming.
- Standardized handoff execution to force `toolChoice: "none"` and enforce consistent cache-routing behavior.
2026-06-22 20:05:40 +02:00
Mathews-Tom 40f1b34a21 Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names
# Conflicts:
#	packages/coding-agent/src/secrets/obfuscator.ts
2026-06-22 22:10:49 +05:30
can1357 3c98cc556c Merge remote-tracking branch 'origin/farm/0008d917/png-string-paste-image' 2026-06-22 17:44:01 +02:00
can1357 26c72689c2 feat(coding-agent): added share.store setting for session uploads
- Added a `share.store` configuration option (`blob` | `gist`) that allows users to choose between the default share server or a GitHub gist for storing exported session data.
- Changed the default upload target from secret GitHub gists to the share server to avoid GitHub API rate limits for shared sessions.
- Enabled fallback to the share server when a gist upload fails or the GitHub CLI is unavailable.
2026-06-22 17:25:05 +02:00
Mathews-Tom 2584f7e91e Merge remote-tracking branch 'upstream/main' into feat/secret-friendly-names 2026-06-22 19:21:44 +05:30
roboomp 6bc0e56c20 fix(tui): kept partial JSONL tail after full transcript rebuild
When a full rebuild caught the session file mid-append, #loadLocalFull cleared the pending buffer but advanced offset past the headless trailing bytes. The next poll then read only the completion bytes, parsed a headless fragment, and silently dropped the completed entry. Carry the bytes after the last newline as pending so the completion concatenates with them on the next #appendLocal pass.

Fixes #3258
2026-06-22 12:20:07 +00:00
roboomp e65b8e4cc7 fix(tui): cleared remote transcript builder before rotation refetch
The append-based collab-guest path only reset the byte cursor on host transcript rotation/truncation, so the refetched bytes stacked on top of the stale pre-rotation rows still in the ChatTranscriptBuilder. Drop the builder and model state before refetching from byte 0 so rotated host transcripts replace stale history instead of duplicating it.

Fixes #3258
2026-06-22 12:13:58 +00:00
roboomp e5de11c668 fix(tui): anchored transcript tail cursor to bytes actually read
If the session file grew between the earlier statSync and readFileSync inside #loadLocalFull, the rebuild rendered the appended bytes but the tail state recorded the pre-race stat.size. The next poll's #appendLocal would then read from that stale offset and re-render the bytes already in the rebuild, duplicating rows for agents that append during a viewer open or full rebuild. Anchor size/offset to data.byteLength and re-stat for mtime/identity so the post-read clock matches what's on disk.

Fixes #3258
2026-06-22 12:11:28 +00:00
roboomp 3bcbf1515d fix(tui): reduced large transcript stalls
Tail appended transcript JSONL instead of rebuilding rendered history on every poll, collapse compacted history for live chat rendering, and replace synchronous session rewrites so tailers detect historical changes.

Fixes #3258
2026-06-22 12:01:34 +00:00
roboomp fe9ffc7912 fix(tui): preserved bare png filename pastes
Require bracketed image-path paste detection to see an explicit local path separator or file URI before routing .png-like text to image attachment handling.\n\nFixes #3253
2026-06-22 10:46:24 +00:00
can1357 4e54e557bc feat: improved context usage display and update model configurations
- Updated status line to display token usage with an unknown context marker (" 5K/? ") when the model context window is unavailable.
- Updated `fugu` model specifications in `models.json` and catalog constants with corrected pricing, increased context windows, and disabled stream idle timeouts.
- Corrected OpenAI usage accounting by excluding redundant orchestration input tokens in `openai-shared` logic.
2026-06-22 08:04:42 +02:00
can1357 33e2594f03 feat(coding-agent): added support for Julia and display language icons in code cells
- Added Julia language support to the theme symbol maps.
- Enabled language icons in code cell headers for the eval tool renderer.
2026-06-22 06:13:01 +02:00
can1357 1f3f3cf5d1 feat: added ruby and julia language support to coding-agent
- Implemented persistent execution backends for Ruby and Julia using dedicated kernel processes and NDJSON-based IPC.
- Integrated language-specific prelude environments, runtime path resolution, and security-focused environment variable filtering.
- Exposed configuration options, tool schema updates, and lifecycle management for seamless agent interaction with both languages.
- Added comprehensive integration tests and updated prompt documentation to support the new evaluation capabilities.
2026-06-22 06:13:01 +02:00
can1357 93db34b0d5 refactor(coding-agent): consolidated editor state and unify transcript rendering
- Centralized draft state and image management by migrating fields from context to the CustomEditor component.
- Standardized transcript row construction by introducing shared helpers for background jobs, IRC traffic, and file mentions.
- Refactored redundant UI logic and helper functions into reusable utility modules to streamline message submission and component rendering.
- Standardized event handler types by consolidating lifecycle definitions into a shared module while maintaining public API stability.
2026-06-22 06:11:57 +02:00
can1357 be3687a5f1 feat(tui): improved settings list wheel interaction handling
- Implement `handleWheelAt` to restrict wheel scrolling to the settings pane.
- Update selection movement to support clamping when scrolling at boundaries.
- Add tests to verify boundary behavior and spatial constraints.
2026-06-22 06:10:17 +02:00
can1357 2361775e9f refactor(coding-agent): consolidated TUI component shared logic
- Introduced `selector-helpers.ts` to centralize reusable list, dashboard, and selection utilities.
- Refactored `AgentDashboard`, `ExtensionList`, `HistoryResultsList`, and `TreeList` to use standardized rendering and navigation helpers.
- Encapsulated viewport padding, scrolling logic, and key matching to reduce code duplication across TUI components.
- Maintained consistent scrollbar themes and keyboard behaviors while simplifying component-specific implementations.
2026-06-22 05:41:32 +02:00
oldschoola d8f52e8a9b fix(coding-agent): require token boundary for #<number>; add pr/issue qualifier
Address review feedback on #3224 (roboomp + Codex): #<number> now requires a token boundary before # (start/whitespace/quote/paren/</=), matching the internal-URL boundary set, so owner/repo#N, foo#N, C#12, and URL fragments no longer match and corrupt on accept. Also detect a pr/pull/issue qualifier word before the number (pr #3164 / issue #3164); when present, only that kind is offered and the qualifier is consumed on accept.
2026-06-21 18:36:20 -07:00