Commit Graph

5232 Commits

Author SHA1 Message Date
Peter Steinberger 3daf60adda test(ui): restore synthetic window globals (#125616) 2026-08-17 22:21:02 -07:00
Vyctor H. Brzezowski cbe3116e14 feat(ui): add Markdown table interactions (#125245)
* feat(ui): add Markdown table interactions

* fix(ui): scope table interactions to transcripts

* fix(ui): complete table interaction contracts

* chore: refresh PR head

* fix(ui): satisfy table interaction gates

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-17 22:20:32 -07:00
Vyctor H. Brzezowski e97b42a43a fix(ui): show users typing in the transcript (#125244)
* fix(ui): move typing status into transcript

* fix(ui): complete transcript typing lifecycle

* fix(ui): finish transcript typing presentation

* fix(ui): refine typing bubble tail

* fix(ui): complete transcript typing invariants

* fix(ui): satisfy transcript typing gates

* fix(ui): keep typing presence ownership bounded

* fix(ui): keep typing presence dependencies private

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-17 22:19:37 -07:00
Peter Steinberger e6a427c493 perf(ui): defer offscreen plugin row rendering (#125585)
Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 21:50:54 -07:00
Peter Steinberger f007b0f7a8 perf(ui): paginate grouped sessions (#125572)
Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-18 04:38:57 +00:00
Peter Steinberger 0776c4680a fix(ui): stop restart errors from masquerading as model auth (#125513)
* fix(ui): distinguish model catalog freshness errors

* test(ui): cover refreshed configured model load

* fix(ui): wait for fresh model catalogs before auth gating

* fix(ui): import pane ids from composer owner
2026-08-17 21:35:49 -07:00
Peter Steinberger ca8bd59df5 improve(ui): reduce startup stylesheet size (#125539)
* perf(ui): lazy-load settings workspace styles

Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

* fix(ui): keep picker styles route scoped

Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 21:32:46 -07:00
Peter Steinberger 90526f3a9c fix(ui): stop composer mic hover shift and stray red hover (#125565)
* fix(ui): stop composer mic hover shift and stray red hover

The device-picker chevron collapsed to width 0 while idle and grew to
20px on hover, shoving the right-aligned mic button 20px left under
the cursor on every mouse-over. Detach the picker into its own
fixed-width ghost button beside the mic instead of morphing the mic's
shape into a split pill; hover only fades the picker's opacity, so the
reserved layout never shifts.

Also fixes the mic showing the send button's loud accent-red hover in
dark/openknot themes: those themes overrode .chat-send-btn:hover
directly, which outranked every variant's own hover rule (including
the intentional neutral mic hover and the stop button's danger hover).
Theme overrides now set a --chat-send-hover-background variable that
each variant's hover rule can still take precedence over.

* chore(scripts): register composer mic hover proof script

Missing package.json entry made the deadcode full-tree scan flag the
new capture script as an unused file, same as the existing
ui:proof:workboard sibling.
2026-08-17 21:09:17 -07:00
Peter Steinberger 6611e409d0 test(ui): cover discussion cold-open without URL (#125498) 2026-08-17 21:08:39 -07:00
Peter Steinberger 33e2e6b0f9 fix(ui): show session hovercards for every sidebar row beside the rail (#125563)
* fix(ui): show session hovercards for every sidebar row beside the rail

Sidebar session rows were excluded from session-link hovercards, so only
the Home (main) row showed a card, and it overlaid the sidebar itself.
Hovercards now open for all sidebar session rows and position to the
right of the sidebar so navigation stays visible.

* fix(ui): yield sidebar previews to active progress hovercards

Sidebar rows already open a progress hovercard when the session has an
active progress card; the new preview card stacked on top of it. The
preview now probes the shared progress-card store (deduped with the
progress provider's own load) and opens only when the row has none.
2026-08-17 21:06:41 -07:00
Vyctor H. Brzezowski c75d4dc911 improve(ui): align chat branch and PR rows (#125232)
* improve(ui): align chat branch and PR rows

* improve(ui): collapse absent PR number slot

* improve(ui): give Create PR a neutral chip surface

* improve(ui): rebalance merged PR row contrast

* improve(ui): use standard squircle for PR rows

* fix(ui): consolidate static PR link styling
2026-08-17 20:52:00 -07:00
Peter Steinberger aa2d3df8e6 test(ui): wait for persisted new-session drafts (#125548) 2026-08-17 20:49:32 -07:00
Ayaan Zaidi 8575ead129 fix(ui): show skill mentions in the new-session composer (#125554)
The /new page renders its own composer, which never wired the `$skill` mention menu owned by the chat composer, so typing `$` there did nothing while /chat offered completions. Narrow the skill-menu module to a small host contract shared by both composers, drive it from the new-session textarea, and refresh commands.list on the first `$`. Also moves `paneDomId` to the composer DOM helpers to break a types→skill-menu→slash-menu→state import cycle.
2026-08-18 03:48:37 +00:00
Peter Steinberger a0c5937fd1 fix(ui): restore full chat history after cached layout changes (#125536)
Cached Control UI transcripts no longer show a large blank region or hide earlier loaded messages after layout/transcript-shape changes.

Closes #125533
2026-08-17 20:33:05 -07:00
Peter Steinberger 974a52f64f refactor(ui): deduplicate session menus and hovercards (#125478)
* refactor(ui): share session menu and hovercard mechanics

* test(ui): align fixtures with gateway hello contract

* fix(ui): close session access and focus gaps

* test(ui): advertise sidebar custodian method

* refactor(ui): split chat pane layout rendering

* fix(ui): align rebased chat render checks
2026-08-17 20:15:04 -07:00
Peter Steinberger e859f2bab3 fix(ui): restore task suggestion checks (#125538) 2026-08-17 20:10:01 -07:00
Jesse Merhi a928da457f Show worktree option only for Git group folders (#125280)
* feat(ui): show worktrees only for Git group folders

* feat(ui): enrich group environment picker

* fix(ui): preserve worktree defaults on probe errors

* fix(ui): reject stale group repository probes

* test(ui): type repository inspection helper
2026-08-17 19:50:15 -07:00
Peter Steinberger 93f7492570 fix(ui): keep side panel tab labels visible (#125511)
Restore the block-axis padding reset lost in #125368 so Web Awesome tab labels remain vertically legible while retaining logical inline spacing. Add LTR and RTL browser geometry coverage for the visible label boundary.
2026-08-17 19:29:18 -07:00
Vyctor H. Brzezowski 47399310a0 improve(ui): redesign suggested task cards (#125231)
* improve(ui): redesign suggested task cards

* fix(ui): preserve suggested task navigation

* fix(ui): refine suggested task card surfaces

* fix(ui): clarify suggested task instruction layers

* fix(ui): normalize task instruction disclosure

* fix(ui): keep split divider stable on hover

* fix(ui): refine suggested task split shape

* fix(ui): tighten task instruction underlap

* fix(ui): smooth suggested task swaps

* fix(ui): wrap suggested task project label

* fix(ui): signal overflowing task paths

* fix(ui): stabilize suggested task stack height

* fix(ui): separate suggested task surface contrast

* fix(ui): narrow suggested task cards

* fix(ui): allow suggested task text selection

* fix(ui): use restrained brand task action

* fix(ui): align dark task action branding

* fix(ui): deepen dark task action color
2026-08-17 23:25:28 -03:00
Vyctor H. Brzezowski 71eab1118d fix(ui): contain session suggestions to composer width (#125225)
* fix(ui): align session suggestions with composer

* fix(ui): match suggestion phone gutters
2026-08-17 23:15:36 -03:00
Vyctor H. Brzezowski 127931c13d fix(ui): keep side panel tab labels legible (#125505) 2026-08-17 23:04:19 -03:00
Peter Steinberger b5b17c654b fix: keep Workboard visible in the sidebar (#125473)
* fix(ui): keep workboard in sidebar navigation

* test(ui): align workboard navigation ownership

* fix(ui): preserve saved workboard sidebar slots

* test(ui): shrink assertion safety baseline

* fix(plugins): bind native routes to bundled owners

* refactor(plugins): isolate native route policy
2026-08-17 18:44:39 -07:00
Peter Steinberger 49cdd54259 feat(control-ui): move the Ask OpenClaw toggle to the sidebar footer (#125486)
* feat(control-ui): move the Ask OpenClaw toggle to the sidebar footer

The sidebar bottom now mirrors its top: big agent selector with inline
chevron + small new-session square above, big account identity card with
inline chevron + small lobster toggle below. The account chevron moves
from the row's far right to directly after the name, matching the top
header treatment; the freed edge hosts the toggle. The old top-left
shell-chrome placement is removed along with its four-button width
reservation (which read-scoped clients paid for without seeing the
button). Scope gating, palette entry, and panel wiring are unchanged;
gating regressions moved to the sidebar cases.

* fix(control-ui): keep Ask OpenClaw reachable while the nav is collapsed

Address the ClawSweeper P1: desktop collapse hides the sidebar entirely
(display:none, no rail), which would have removed the toggle's only
persistent surface. The lobster now joins the chrome strip exactly while
the nav is collapsed — the footer stays its home — and the strip's
collapsed width reserves four controls for that state. Regression covers
collapsed-present/expanded-absent/read-scope-absent.
2026-08-17 18:26:53 -07:00
Peter Steinberger 05b9b39a9e test(ui): synchronize cloud worker settings saves (#125456) 2026-08-17 18:19:49 -07:00
Peter Steinberger fab7fa9910 improve(ui): rebuild agent GitHub identity panel on settings primitives (#125472)
The panel from #125199 rendered raw wire enums in code tags, used
form-grid/field markup whose styles the agents page never loads (bare
unstyled inputs outside the card), referenced non-existent avatar
classes, and put callouts inside the settings group. Rebuild it on the
canonical settings primitives: status rows with dot status and friendly
source/evidence labels, a System/This Agent segmented scope control,
the settings secret input (gains a disabled prop), a danger status row
for errors, and a quiet-inherit + primary-save action row. Retitle to
"GitHub Identity" and move it below Tool Access and Available Right
Now. Add a .settings-account primitive for the 20px round avatar.

Live-tested on an isolated dev gateway: native-credential verify via
the GitHub API, segmented scope switching, and the empty-token error
row. Controller behavior unchanged.
2026-08-17 18:09:22 -07:00
Vyctor H. Brzezowski 86fb87c602 improve(ui): simplify Markdown table styling (#125219)
* improve(ui): simplify Markdown table styling

* fix(ui): scope table styling to transcripts

* fix(ui): keep transcript tables full width

* fix(ui): size transcript tables to content

* fix(ui): gate table fades on overflow

* fix(ui): make table fades theme neutral

* fix(ui): correct table overflow edges

* fix(ui): keep wide table cells readable

* fix(ui): stretch transcript tables full width

* fix(ui): balance transcript table columns

* fix(ui): enforce full-width table layout

* fix(ui): preserve wide table column sizing

* fix(ui): prevent cramped table columns

* fix(ui): align table first column with prose

* fix(ui): use natural table column sizing

* fix(ui): increase transcript table row spacing

* fix(ui): increase table row padding

* fix(ui): keep table restyle CSS-only

* fix(ui): drop table overflow behavior
2026-08-17 22:07:06 -03:00
Peter Steinberger 6b72d65ffe feat(ui): preserve composer drafts across restarts (#125332)
* feat(ui): preserve composer drafts across restarts

Persist draft text and attachment Blobs in browser-local IndexedDB, scoped to Gateway credentials and session or New Session targets. Clean up durable data after successful send or creation, attachment removal, and session deletion.

* fix(ui): preserve text when draft attachments exceed cap

preserve text-only durable fallback for oversized attachments; serialize visible Incognito transition with its storage fence; document retention and disposal.

* test(ui): make draft retirement proof isolate-safe

The shared isolate:false UI suite exposed an order-dependent module mock; exercise and settle the real IndexedDB boundary instead.

* style(ui): format session mutation imports

* fix(ui): keep incognito drafts memory-only

* perf(ui): lazy-load durable draft storage

* fix(ui): sequence durable draft transitions

* fix(ui): restore text-only new session drafts

Programmatic draft restoration must not advance the user-mutation generation; real user input continues through setMessage.

Move navigation transition ownership into the existing handoff module as a behavior-neutral extraction that keeps the submission owner within max-lines.

* fix(ui): restore text-only drafts without import cycles

Complete the text-only restore fix by moving started-session route transitions into a leaf module. This keeps max-lines ownership clean without reintroducing the Madge cycle.

* fix(ui): reconcile attachment handoffs with durable drafts

Restore programmatic attachment handoffs without recording a user mutation. Cover stale navigation state losing to newer durable drafts across two pages and a fresh page.

* fix(ui): start durable attachment writes before teardown

Start each CAS IndexedDB write and retirement immediately so text and attachment transactions register before page teardown. IndexedDB readwrite ordering and draft revisions keep snapshots serialized.

* fix(ui): persist New Session drafts before teardown

Accept the committed predecessor or a known in-flight local write ID atomically so New Session writes can start before teardown without spurious local-lineage conflicts.

Reset cached lineage when authoritative storage is missing and re-snapshot the still-current edit.
2026-08-17 17:56:20 -07:00
Peter Steinberger 850faa0367 fix(ui): guard browser ResizeObserver construction (#125480) 2026-08-17 17:55:09 -07:00
Vyctor H. Brzezowski 3dd95d7bf7 improve(ui): refine Markdown prose presentation (#125242)
* improve(ui): refine Markdown prose styling

* improve(ui): polish Markdown prose spacing

* improve(ui): normalize nested list rhythm

* fix(ui): fill Markdown image fallback width

* improve(ui): mute checked task styling

* fix(ui): align Markdown list markers

* fix(ui): preserve Markdown list rhythm with tasks

* improve(ui): clarify Markdown block rhythm

* test(ui): update Markdown disclosure geometry

* test(ui): match compact Markdown indent

* fix(ui): consolidate task list styling

* style(ui): format Markdown presentation

* test(ui): match Markdown block rhythm

* test(ui): enforce uniform Markdown rhythm
2026-08-17 21:49:21 -03:00
Josh Lehman 02ec1b6166 fix(ui): keep acknowledged sends pending during stale history (#125426) 2026-08-17 17:33:40 -07:00
Peter Steinberger b228c83bfc feat(dashboard): add session:progress board tile rendering the live progress card (#125438)
* feat(dashboard): add session:progress board tile rendering the live progress card

Advertise the core-owned widget kind via hello controlUiWidgetKinds at operator.read.
Render it inline without an iframe from the session-progress-cards store.
Pin it with dashboard tool widget_put using pluginKind session:progress and optional props.sessionKey.
Follow up the progress-card unification from #125125.

* fix(dashboard): surface session progress load failures

Record protected progress-card read failures in the shared per-session store.
Render an actionable board-tile error with retry instead of indefinite loading.
Cover the rejected-read and successful-retry flow at the widget boundary.

* fix(dashboard): honor progress tile access and activity

Avoid progress-card reads while a retained board is inactive.
Distinguish sharing denial from transient load failures and show the correct remedy.
Qualify cross-session pinning docs and cover activation plus denial behavior.
2026-08-17 16:56:23 -07:00
Peter Steinberger 389fed29cf fix(ui): keep composer footer controls readable (#125445)
* fix(ui): move permission picker to footer left

* chore: drop changelog edit (release-owned)
2026-08-17 16:43:04 -07:00
Peter Steinberger 3a431bc5c0 test(control-ui): pin repeated same-method e2e waits with after-cursor (#125439)
waitForRequest(method) is satisfied by ANY prior request of that method
and returns the latest match, so a second same-method wait in one page
context can return a stale earlier request on slow runners. Add the
opt-in { after: priorCount } cursor (same shape as PR #125107's helper
change) and pin the 11 genuinely stale-prone waits: chat-composer-
capability-menu, claude-sessions (3), desktop-panel, model-providers (3,
replacing expect.poll count workarounds), session-management.group-
defaults (3). Skipped: cloud-workers-settings (owned by PR #125107),
chat-attachment-read-lifecycle (ring asserted empty), login-gate (waits
follow app-initiated stale-build reloads, which restart the ring).
2026-08-17 16:31:24 -07:00
Peter Steinberger aeee426180 feat(control-ui): persistent Ask OpenClaw companion with global toggle (#125107)
* feat(control-ui): persistent Ask OpenClaw companion with global toggle

The custodian surface now behaves like the persistent machine-wide agent it
already is on the Gateway: the session id persists in localStorage so a
reopened surface rebinds to the live engine (wizard and approval state
survive close/reopen), the durable transcript is refetched when a surface
opens or the gateway reconnects (idle-gated so active question/wizard cards
are never clobbered), and the panel toggles from anywhere via the shared
panel-toggle contract, a command-palette action, and an admin-gated lobster
chrome button.

One server-side line: the openclaw.chat owner-mismatch rejection now carries
the existing structured session-invalidated details so persisted clients
re-mint their id from a closed code instead of matching error prose.

No gateway events, no protocol schema changes, no polling. Splits
(session-identity/variant modules, session-lifecycle and panel-toggle test
files) keep the touched files under the max-lines ratchet.

* fix(control-ui): coerce custodian toggle detail without a type assertion

The assertion-safety ratchet holds custodian-panel.ts at zero uncommented
assertions; parse the toggle CustomEvent detail through the canonical
record-coerce guard and literal narrowing instead of casting.

* fix(control-ui): delete unused CustodianPanelToggleDetail export

The record-coerce toggle parsing left the exported type without a
production consumer; the deadcode gate rightly flags it. The palette test
keeps a local shape.

* test(control-ui): select the palette custodian item via keyboard

Async session-search results can reflow the palette list mid-click on slow
CI runners, silently dropping the positional click; keyboard selection of
the asserted-active item is atomic against reflow. Also stage the reopen
wait (panel section, then text) for sharper failure localization.

* fix(control-ui): project live wizard state on rejoin and scope-gate the toggles

Address both ClawSweeper P1 findings. The welcome-only rejoin of an
existing session now routes through engine.decorateRejoinReply (the
existing ChatWizardHost projection), so a reconnecting client re-renders
the live wizard/question controls the session still awaits; the stale
welcome question only fills in when no interaction is live. The chrome
button, palette action, and deferred panel loading now use the
scope-aware canCallGatewayMethod gate (operator.admin) that the session
store already used, so advertised-but-read-scoped clients see nothing.

* test(control-ui): fix the cloud-workers e2e flake at both roots

The mocked config.get stayed frozen at the empty initial config while
patch responses advanced, so a config-store reconciliation refetch could
flap the snapshot to empty and saveProfile silently dropped the next
save; the mock now stays consistent before each patch resolution. Also
give waitForRequest an opt-in after-cursor: it is satisfied by any prior
same-method request and returns the latest match, so a second wait could
assert against the stale earlier request; the cloud-workers waits pin it
(15x green locally, previously failing 1-in-3).

* fix(ci): cover rejoin projection in sibling engine mocks; bump startup baseline

The greeting-welcome and session-ownership suites' engine mocks now
export decorateRejoinReply like the handler requires. The Control UI
startup-JS baseline moves 337511 -> 338920 B via the documented update
command: the shell chrome toggle, palette action, and scope-aware gating
are genuine startup surface (~1.4 KiB gzip, within the committed
ceiling).

* fix(control-ui): settle interrupted structured replies and racing turns on rejoin

Address both ClawSweeper reconnect P1s. A submitted question/wizard reply
with an unknown outcome now triggers a full session rejoin on reconnect
instead of being blocked by its own uncertainty flag: the Gateway projects
whether the answer was consumed and which control is live. A restored
persisted id also arms a one-shot rejoin barrier: the welcome-only request
queues behind any in-flight turn on the Gateway's per-session queue, so a
post-response history refresh deterministically surfaces rows a racing
turn persisted after the initial fetch. The open-agent handoff moved to
custodian-navigation (its owner) to keep the store under the size cap.
Live-Gateway proof (isolated state dir, real gpt-5.6-luna turns): video
and screenshots on the PR.

* test(control-ui): reopen via the chrome toggle in the custodian e2e

The palette click-through composition proved timing-flaky on loaded CI
runners in three different ways while adding no coverage: the palette
action's dispatch is pinned by the palette unit test and the event-opens-
panel path by the chrome-toggle step. Keep the gated palette entry
assertion + screenshot; reopen through the chrome path.

* fix(control-ui): keep the agent-handoff path helper module-local

The store now routes through performCustodianAgentHandoff, leaving the
path builder without external callers; the deadcode gate rightly flags
the export.

* fix(control-ui): run the rejoin barrier even when a live control projects

The racing-history refresh happens before the reply/control message is
appended, so skipping it for projected wizard/question rejoins had no
purpose and lost rows a turn persisted while the page was closed mid-
wizard. Regression covers the live-step rejoin reconciling racing rows.
2026-08-17 16:28:43 -07:00
Vyctor H. Brzezowski d975d9ba4a improve(ui): simplify message chrome and actions (#125241)
* improve(ui): simplify message chrome

* fix(ui): clear loading bubble shadow
2026-08-17 20:19:31 -03:00
Peter Steinberger 6e458d84bf feat(agents): configure per-agent GitHub identities (#125199)
* feat(agents): add managed GitHub identities

* fix(agents): use opaque GitHub setup handles

* style(codex): format managed shell environment call

* refactor(agents): own managed GitHub process identity

* chore(config): refresh baseline after rebase

* fix(ci): satisfy managed GitHub identity gates

* fix(ci): repair managed GitHub identity checks

* test(agents): align GitHub identity CI coverage

* fix(codex): scope login shell isolation

* fix(agents): let managed gh profiles authenticate

* fix(agents): harden GitHub identity setup

* test(gateway): align method suffix counts

* fix(ui): serialize GitHub identity mutations

* fix(protocol): generate GitHub configure requests

* test(ui): restore timers after identity tests

* fix(ui): preserve GitHub identity mutation ownership

* fix(agents): preserve native GitHub CLI auth
2026-08-17 15:54:03 -07:00
Peter Steinberger 57e862980b feat(gateway): carry machine class through session moves (#125292)
* feat(gateway): carry machine class through session moves

Profile move targets accept an optional machineClass with new-session
parity: validated in the protocol, persisted on the durable move intent
(bare nullable column, lazy same-version ALTER), replayed exactly by
restart recovery, and selectable from the Control UI move dialog.
Moving to the current profile with a different class resizes the
session's worker.

* fix(gateway): project placement facts on chat startup

chat.startup and chat.history built sessionInfo without the placement
projection sessions.list applies, so clients merging that row erased a
live worker placement and its move intent — the Runs on Cloud chip
disappeared after any turn until a full reload.

Reuse the canonical ensureColumn helper for the move table's additive
column instead of a hand-rolled PRAGMA read.
2026-08-17 14:25:13 -07:00
Alix-007 bb03085015 fix(ui): stop hidden chat stream repainting (#125088)
* fix(ui): defer hidden chat stream paints

* fix(webui): defer hidden chat invalidations

* fix(ui): defer all hidden chat renders

* fix(ui): finish hidden update lifecycle

---------

Co-authored-by: vyctorbrzezowski <krzyszchweski@gmail.com>
2026-08-17 17:50:18 -03:00
ClawSweeper 248966d300 fix(ui): show menus for child sessions in the sidebar (#125033)
* fix(ui): add child session sidebar menus

* fix(ui): tailor child session menus

* test(ui): align child session menu expectations

---------

Co-authored-by: ClawSweeper <280513762+clawsweeper@users.noreply.github.com>
2026-08-17 12:59:38 -07:00
ClawSweeper 29fc91fe99 fix(ui): balance side panel tab pill padding (#125368)
Fixes crowded side-panel tab close padding and keeps the joined pill balanced in LTR and RTL.

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-17 14:51:27 -05:00
Peter Steinberger de9b367214 fix(ui): generic mock chat sends show a visible outcome (#125347)
* fix(ui): make generic mock chat sends observable

* test(ui): stabilize control UI e2e timing
2026-08-17 11:40:56 -07:00
ClawSweeper 1ea18c8cd8 fix(ui): keep mobile side chat interactive in tabbed panel (#124785)
Keep embedded mobile Side chat inside its tabbed panel so the main composer and shared controls stay tappable.

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-17 12:00:36 -05:00
Jacqueline Henriksen 03f43ee21c fix(ui): edit queued messages in place (#124298)
* fix(ui): restore cancelled queued message drafts

* fix(ui): edit queued messages in place

* fix(ui): isolate composer sends from row edits

* fix(ui): isolate queued edit submission guard

* fix(ui): preserve reply context for queued edits

* fix(ui): fence steer during queued edits

* fix(ui): abort stale queued edit submissions

* fix(ui): fence queued edits across panes

* fix(ui): fence peer-pane queued steers

* fix(ui): fence command-like queued edits

* fix(ui): fence removal of edited queue rows

* docs(proof): record queued edit live verification

* docs(proof): attach queued edit browser evidence

* fix(ui): fence queued row reordering during edits

* fix(ui): fence peer edits during queue reordering

* fix(ui): report cross-pane reorder conflicts

* test(ui): exercise rejected inline edit submit

* fix(ui): surface reorder conflicts in chat state

* docs(proof): record real queued-edit behavior

* docs(proof): record exact-head queue behavior

* fix(chat): fence retry during queued-row edits

* fix(chat): fence stop aliases in queued edits

* fix(chat): surface peer steer conflicts

* fix(chat): fence draft changes during history load

* fix(chat): fence annotated queue edits

* test(chat): record exact-head queue proof

* Revert "test(chat): record exact-head queue proof"

This reverts commit d7278ad9082fae40e28e6b98ca5a74e855817e6c.

* fix(chat): clear stale queued edit tokens

* fix(chat): fence stale queued edit versions

* fix(chat): invalidate rejected queued edits

* fix(ui): clarify queued edit conflict guidance

* fix(ui): report peer-edited queue reorder conflicts

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-17 10:00:00 -07:00
Peter Steinberger 7170a6231a feat(agents): unify agent status into a durable progress_card (#125125)
* feat(agents): unify agent status into a durable progress_card

Replace the write-only update_plan to-do tool and the fragmented plan
rendering with one durable status artifact per session: progress_card
({plan?, markdown?}, replace-on-write, 8 KiB markdown / 50-step caps).
Cards persist in a lazy-additive session_progress_cards table in the
per-agent DB (no schema-version bump), broadcast progressCard.changed,
and render from the store with exactly one live placement per view
(session rail when visible, else the composer-adjacent bar); transcripts
collapse to one-line receipts, and the sidebar hovercard shows other
sessions' cards inline (markdown + <progress>, DOMPurify allowlist, no
iframes). The three stream-derived plan renderers and their dedup
heuristics are deleted.

Codex runs disable the native plan tool per thread
(tools.update_plan.enabled=false) and receive progress_card via the
dynamic-tool bridge; compaction restore now reinjects the card (steps +
bounded markdown). Card writes still emit the legacy plan stream event so
native apps and channels keep working until their per-platform
migrations. Policy names map update_plan -> progress_card; the shipped
tools.updatePlan=false kill switch is honored.

Net -277 production LOC; -480 test LOC.

* test(agents): regenerate Codex prompt snapshots for update_plan thread-config disable

* chore(protocol): allowlist progressCard.changed for native apps pending card migration

* fix(ci): repair progress card integration checks

* fix(codex): canonicalize native progress cards

* test(gateway): reconcile progress card method order

* test(codex): stabilize native approval fixture
2026-08-17 09:44:04 -07:00
Peter Steinberger 25e54ef255 fix(ui): gate New Session catalogs on agent roster (#125339) 2026-08-17 09:34:40 -07:00
Peter Steinberger 08622cd766 fix(ui): keep streamed replies ordered across steering (#125197)
* fix(ui): preserve steering stream order

Record exact steering provenance and keep cumulative assistant output on its causal side of persisted user turns across live streaming, terminal events, tool boundaries, and history reloads.

* chore(ci): refresh post-rebase gates

Tighten the inherited environment-variable budget and remove a stale test import exposed by the rebased lint gate.

* fix(ui): preserve terminal steer stream segment

Assert the causal stream rollover when a steer lands and move persisted split-layout normalization off the startup path to keep the Control UI bundle within budget.

* refactor(ui): extract split layout types

Keep the persisted split-layout normalizer off the interactive module cycle while preserving the Control UI startup bundle reduction.

* fix(gateway): resolve steering provenance at injection

* fix(gateway): confirm steering provenance after persistence

* refactor(ui): move live tool filtering to identity owner

* fix(ui): preserve queued user stream ceiling
2026-08-17 06:00:40 -07:00
Peter Steinberger 4b0d573437 feat: session permission modes with worktree-scoped defaults (#124909)
* feat(gateway): add session permission modes

* feat(agents): enforce session permission policies

* test: cover session permission modes

* docs: explain session permission modes

* fix(agents): preserve apply patch default root

* feat(codex): map session permission modes

* feat(ui): add session permission controls

* test: cover session permission surfaces

* fix(agents): enforce session permissions from entry

* fix(codex): pass params object to requirements reader

* fix(codex): honor session permission modes

* fix(codex): preserve exec approval floors

* chore: revert changelog edit (release-owned)

* test: align full-mode promotion with upstream semantics

* chore(protocol): regenerate session permission models

* docs: register session permission modes

* fix(ui): use shared permission dropdown

* fix(sessions): restore permission mode contracts

* fix(ci): record session permission startup JS growth in the budget baseline

* refactor(agents): prepare session exec mode at dispatch

Host dispatch owns permissionMode→exec override preparation; the codex
plugin consumes prepared facts and the SDK barrel export is removed,
keeping the plugin-sdk surface at its recorded budget.

* test: type exec mode fixtures as ExecMode

* fix(codex): require admin scope for yolo permissions

* test: isolate codex permission command state

* ci: refresh PR checks against current main

* ci: refresh checks after gateway test repair

* test: fix main-fallout CI suites

* chore: refresh CI merge ref

* fix(worker): fence permission-mode cloud placements

* fix(sessions): clear worktree policy on detach

* chore(protocol): generate session permission mode enum

* test(gateway): type dispatch fixtures from session entries

* fix(ui): allow clearing session permission mode

* chore: refresh CI merge ref

* fix(ci): record permission picker startup growth in the budget baseline

* fix(gateway): gate session root projections
2026-08-17 04:37:35 -07:00
openclaw-mantis[bot] 5b14551c7c chore(ui): refresh control ui locales (#125213)
* chore(ui): refresh control ui locales

* fix(i18n): localize node host labels

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-17 04:18:55 -07:00
Peter Steinberger 27b77a901e feat(ui): make session references first-class links with titled chips and hovercards (#125014)
* feat(sessions): teach session tools the Control UI link rule

Gate guidance on publicOrigin plus enabled Control UI, with exact literal-URL fallback after short-link misses.

* feat(ui): linkify session keys in chat markdown

Match agent session keys structurally in plain text and inline code, then delegate canonical chat navigation.

Allowlist data-session-key through markdown sanitization.

Pathfinder: keep internal Control UI route anchors in-app by removing target="_blank" and external-link rel attributes while preserving external link behavior.

* feat(ui): session hovercard + titled session chips backed by controlUi.sessionPreview

* fix(gateway): scope controlUi.sessionPreview to caller-visible sessions

Hover previews now apply the same createSessionListEntryFilter predicate as
sessions.list, so identity-bearing non-admin callers cannot preview-by-key
incognito rows or non-owner drafts the sidebar hides. Regression test proves
the viewer/admin split; pre-fix run leaked ok-status metadata.

* feat(sessions): carry the session-link rule in tool result envelopes

Deferred-description mode hides prose tool descriptions at decision time. Carry the shared Control UI session-link sentence in successful session lookup result envelopes so every tool mode sees the rule.

* fix(ui): upgrade session chips on appearance, not first pointer event

* fix(android): regenerate gateway protocol methods

* test(gateway): track session preview release train

* perf(ui): lazy-load session hovercard registration

* fix(ui): keep session hovercards off sidebar navigation

* fix(ui): cancel routed session-link navigation

* fix(sessions): advertise forced-literal ~key URLs so short-ID collisions cannot misroute

* test(sessions): update forced-literal guidance expectation

* fix(ui): collision-proof raw-key navigation and SPA-route internal session URLs

* perf(ui): preserve session route lazy boundary

* fix(ui): defer unseeded session-preview fetches to hover intent

* fix(sessions): hard-cap the model-visible session-link base
2026-08-17 04:05:02 -07:00
Peter Steinberger 34932dfe24 fix(ui): retry first-run model detection once (#125212)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 04:00:28 -07:00