feat(app): edit automations inline and add full list row actions#1270
Conversation
The Automations panel was read-only after creation: detail fields (title, prompt, schedule, model) were static text and list rows only offered a pause toggle, even though the server has long shipped a full PUT /automation/:id update route. Detail page edits in place, one field per patch, no edit mode: - Title and instructions render as transparent always-editable inputs; blur commits, Escape or an empty value reverts. - The Repeats row opens the create card's schedule controls in a popover. The kind is fixed by the server (no oneshot<->recurring conversion), so the frequency switch only offers what the kind supports, and an arbitrary cron keeps its rhythm until the user explicitly picks a picker frequency (scheduleDraftFromDefinition returns undefined for it). - The Model row reuses the composer's ModelSelectorPopover; switching models clears the variant, picking a thinking level patches it alone. - Project stays read-only: update cannot move an automation across per-project server instances. List rows surface the same three actions as the detail header (delete via the shared confirm dialog, pause/resume, run now) as ghost icon buttons fading in on hover where the schedule summary fades out, replacing the lone text-styled pause button. The surface's capture-phase Escape handler now also yields to open popovers/pickers and to focused inputs, so Escape closes the top layer instead of unwinding the detail view. Verified: bun test automations (15 pass), app typecheck, eslint, e2e automations-panel suite (15 pass, two new user-path tests for inline edit and row actions), snap automations-surface with two new shots (detail-schedule, detail-model) reviewed.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds inline editing for automation title, prompt, schedule, and model; schedule round-trip utilities; per-row hover actions (run-now, pause/resume, delete); a globalSync.automation.update helper; a folder-picker variant for detail rows; and E2E tests plus updated snapshots validating these flows. ChangesInline Automation Editing
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Suggested priority: P2 (includes user-path files (packages/app/src/context/global-sync.tsx, packages/app/src/pages/automations/automation-detail-editors.tsx, packages/app/src/pages/automations/automation-detail.tsx, packages/app/src/pages/automations/automation-list.tsx, packages/app/src/pages/automations/automation-schedule-controls.tsx, packages/app/src/pages/automations/automation-schedule-form.test.ts, packages/app/src/pages/automations/automation-schedule-form.ts, packages/app/src/pages/automations/automations-surface.tsx)).
P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.
There was a problem hiding this comment.
Code Review
This pull request introduces inline editing for automation details (title, prompt, schedule, and model) and exposes quick actions (run, pause, delete) on hover for automation list rows, supported by new end-to-end and unit tests. Feedback highlights a potential issue in EditableText where a failed asynchronous commit could overwrite active user typing if they refocus the input, and suggests a cleaner payload structure when updating the model in ModelEditorRow by only passing the required providerID and modelID fields.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The schedule trigger read as plain text next to the Model row's chevron, hiding that it is clickable (real-window feedback on PR #1270).
The server has no cross-project move (per-project instances; update rejects a foreign projectID), and one is not needed: moving only has to affect future runs. The Project row becomes the create card's folder picker (new "row" trigger variant) and moving recreates the definition in the target project, then deletes the source. Create-first so a failure loses nothing; if the source delete fails the fresh copy is rolled back instead of leaving a duplicate. The id changes and the run list starts empty; past runs' sessions survive. Paused state is re-applied after the move. A continue automation stays read-only (it loops inside a conversation that only exists in its source project), as does everything when no other project is open. E2E: real-path move test (pick target project in the detail row, assert the definition lands in the target SDK, vanishes from the source, and the detail stays open on the recreated automation).
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/app/e2e/automations/automations-panel.spec.ts (1)
192-193:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReplace fixed sleeps with observable waits in these test paths.
Line 192 and Line 333 use
page.waitForTimeout(...). In this suite, that’s a reliability risk and violates the E2E rule to wait on observable state (locatorassertions /expect.poll(...)/ existing helpers) instead of arbitrary delays.As per coding guidelines, “Never use
page.waitForTimeout(...)to make a test pass; instead wait for observable state with locator assertions,expect.poll(...), or existing helpers.”Also applies to: 333-334
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/app/e2e/automations/automations-panel.spec.ts` around lines 192 - 193, Replace the fixed sleep with an observable wait: remove page.waitForTimeout(250) and instead wait until the expected state is observed (for example use expect.poll(() => runListRequests).toBe(1) or, preferably, assert a DOM change via a locator like await expect(someRunListLocator).toHaveCount(...) / toBeVisible()). Update both occurrences around the expect(runListRequests).toBe(1) so the test waits on observable state (expect.poll or locator assertion) rather than a fixed timeout.Source: Coding guidelines
packages/app/src/pages/automations/automation-list.tsx (1)
46-53:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winShow the action buttons when the row itself has keyboard focus.
Line 46 hides the schedule summary on group focus, but Line 53 only reveals the action row on hover or when one of its own buttons is already focused. Tabbing onto the row leaves the right side blank and makes the next tab stop invisible.
Suggested fix
- <div class="absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100"> + <div class="absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100 group-focus-within/automation:opacity-100">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/app/src/pages/automations/automation-list.tsx` around lines 46 - 53, The action buttons container currently only becomes visible on hover or when its own children are focused; update the div whose class includes "opacity-0 transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100" to also include "group-focus/automation:opacity-100" so the actions are revealed when the row (the group trigger button) receives keyboard focus; adjust the class string in the component in automation-list.tsx (the div next to formatScheduleSummary(automation, language.t)) to include that token.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/app/e2e/automations/automations-panel.spec.ts`:
- Around line 192-193: Replace the fixed sleep with an observable wait: remove
page.waitForTimeout(250) and instead wait until the expected state is observed
(for example use expect.poll(() => runListRequests).toBe(1) or, preferably,
assert a DOM change via a locator like await
expect(someRunListLocator).toHaveCount(...) / toBeVisible()). Update both
occurrences around the expect(runListRequests).toBe(1) so the test waits on
observable state (expect.poll or locator assertion) rather than a fixed timeout.
In `@packages/app/src/pages/automations/automation-list.tsx`:
- Around line 46-53: The action buttons container currently only becomes visible
on hover or when its own children are focused; update the div whose class
includes "opacity-0 transition-opacity focus-within:opacity-100
group-hover/automation:opacity-100" to also include
"group-focus/automation:opacity-100" so the actions are revealed when the row
(the group trigger button) receives keyboard focus; adjust the class string in
the component in automation-list.tsx (the div next to
formatScheduleSummary(automation, language.t)) to include that token.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 39ef1e21-00b8-4844-9b4a-cbc741e49ea5
📒 Files selected for processing (10)
packages/app/e2e/automations/automations-panel.spec.tspackages/app/e2e/snap/automations-surface.snap.tspackages/app/src/context/global-sync.tsxpackages/app/src/pages/automations/automation-detail-editors.tsxpackages/app/src/pages/automations/automation-detail.tsxpackages/app/src/pages/automations/automation-list.tsxpackages/app/src/pages/automations/automation-schedule-controls.tsxpackages/app/src/pages/automations/automation-schedule-form.test.tspackages/app/src/pages/automations/automation-schedule-form.tspackages/app/src/pages/automations/automations-surface.tsx
The row variant inherited picker.css's pill hover via data-picker-trigger while Repeats/Model use the sidebar's underline hover. Drop the attribute for the row variant and use the same underline affordance.
…a11y) Code review follow-ups on the inline editors: - Schedule (P2): a rhythm the picker cannot express (hourly, interval, arbitrary cron) now renders the Repeats row read-only instead of pre-selecting DEFAULT_SCHEDULE behind a trigger, which let any knob change silently rewrite an hourly cron to daily/weekly. - Move (P2): a paused source that fails to re-pause on the target now fails the whole move (copy rolled back, source kept) instead of swallowing the error and leaving a silenced automation live elsewhere. - Inline text (P2): a failed save only rolls the control back if it still shows the failed value, so a retype while the request was in flight is no longer clobbered by the stale value. - Model (P3): the update payload is built from providerID/modelID explicitly rather than spreading the picker item. - List a11y (P3): the hover action cluster also reveals on row keyboard focus (group-focus-within), so a keyboard user does not face a blank slot where the schedule summary hid. E2E: hourly-cron read-only row; paused move keeps paused; failed-pause move rolls back with a visible error toast; row focus reveals actions.
Summary
The Automations panel was read-only after creation: detail fields (title, prompt, schedule, model) were static text, and list rows only offered a pause toggle — even though the server has long shipped a full
PUT /automation/:idupdate route. This PR makes the panel editable in place and gives list rows the same three actions as the detail header.Related: complements #1249 (conversation-side
automate_manage), which explicitly scopes panel UI out; #1249's v1 design deferseditto "a panel action" — this is that panel action. No dependency between the two: both wrap the same existing Automation service.Changes
Detail page — inline editing, one field per patch, no edit mode
AutomationScheduleControls) in a popover. The kind is fixed by the server (no oneshot↔recurring conversion), so the frequency switch only offers what the kind supports; an arbitrary cron (hourly, day-of-month…) keeps its rhythm until the user explicitly picks a picker frequency.ModelSelectorPopover. Switching models clears the variant; picking a thinking level patches the variant alone.List rows — delete (shared confirm dialog), pause/resume, and run-now ghost icon buttons fade in on hover where the schedule summary fades out, replacing the lone text-styled pause button.
Plumbing —
globalSync.automation.updatewrapper (revision-gated apply, same pattern as pause/delete);scheduleDraftFromDefinitioninverse mapping with unit tests; the surface's capture-phase Escape handler now yields to open popovers/pickers and focused inputs so Escape closes the top layer instead of unwinding the detail view.No new i18n keys — all labels reuse existing
automations.*strings. The create dialog is untouched.Verification
bun test src/pages/automations— 15 pass (newautomation-schedule-form.test.tscovers cron↔draft round-trips and non-mapping crons)bun run typecheck(packages/app) andeslinton touched files — cleane2e/automations/automations-panel.spec.ts— 15 pass locally, including three new user-path tests: cross-project move (definition lands in the target SDK, vanishes from the source, detail stays open on the recreated automation), detail inline edit (title/prompt/schedule/model committed through the real UI, asserted via SDK polls; recurring popover offers no "Once") and list row hover actions (run now / pause / delete through the confirm dialog)bun run snap automations-surfacewith two new shots (detail-schedule,detail-model); reviewed the grid — list-hover shows the three ghost icons, the schedule popover renders Daily | Weekdays | Weekly + time token, the model picker opens anchored to the Model rowResidual risk
Summary by CodeRabbit
New Features
Tests