Skip to content

[feat] Automations on mobile, and one automation instead of two triggers - #6716

Open
ashrafchowdury wants to merge 113 commits into
mainfrom
feat/mobile-automations
Open

[feat] Automations on mobile, and one automation instead of two triggers#6716
ashrafchowdury wants to merge 113 commits into
mainfrom
feat/mobile-automations

Conversation

@ashrafchowdury

Copy link
Copy Markdown
Contributor

Context

The mobile app had no automations at all. You could talk to an agent, but you could not see what ran it on a schedule or on an app event, let alone change it from a phone.

On desktop, one idea existed as two. A subscription (an app event runs an agent) and a schedule (a cron runs an agent) each had their own Settings section, their own drawer, and their own form, and the agent panel listed them in two more places. Someone who wanted "run this agent when a GitHub issue opens, and again every Monday" had to learn two screens that did the same job.

What this adds

One automation, two ways to start it. Subscriptions and schedules are now a single automation edited in a single drawer. A "Runs when" control switches the kind in place instead of sending you to a different form.

Before: Settings → Triggers with separate Subscriptions and Schedules sections, plus TriggerEventsDrawer, TriggerScheduleDrawer and TriggerSubscriptionDrawer behind roughly 2,500 lines of form code.

After: one AutomationDrawer, one list, one editor. The Triggers settings page is gone and the old forms are deleted.

Automations on mobile. A list, a detail screen, a draft screen for a new one, run history with each run's conversation, a test run, and delete. A test run now opens the session with its instruction sitting in the composer, unsent, so you can read and change it before committing to a run.

A shared package. The screens live in a new @agenta/automation-ui so both apps render the same thing. Mobile cannot use antd, so the package is antd-free and presentational; data comes in through props and hooks the host owns.

A shared filter menu. @agenta/ui/filter-menu is one popover that carries filtering, sorting and grouping together, because they are the same kind of question about a list. Rows open their options on hover, the search field matches both row labels and option labels, reset is a row rather than a footnote, and under 640px the rows drill in instead of fanning a flyout out over the panel they came from. The automations list and the run history both use it, and the sessions rail now opens its filters from it too.

Grouping is remembered in localStorage; filters are not. A list that reopens already narrowed looks broken, because the rows are missing and the reason is a menu away.

Tests

  • pnpm --filter @agenta/settings test covers the navigation entry the Triggers page left behind.
  • Storybook stories added for FilterMenu and GroupMenu.
  • The list, detail, drawer, run history, filter menu and event picker were exercised in the running app.
  • The last stretch of commits (the drill-in filter, the confirm modal, ?view=runs, the no-match state, the table restyle, the save bar, grouping persistence, column spacing) is parse-checked but not yet checked in a browser. The dev server was down while they were written. Worth a look during QA.
  • Test run and Delete have not been exercised end to end, since both touch real data.

Demo

Outstanding. Captures to follow.

What to QA

  • Open /m/p/<project>/automations. The list matches the sessions list's frame: borderless rows, a search field on the table's own column, a filter button at the end of the header row.
  • Filter by status, then group by agent. Reload the page. The grouping comes back, the filter does not.
  • Narrow the window under 640px and open the filter menu. Rows drill in and carry a back link instead of opening a flyout beside the panel.
  • Open an automation, change the instruction, and try to leave. The unsaved guard stops you. Save and Discard sit on screen the whole time and are disabled until there is an edit.
  • Delete an automation from the row's kebab. The confirmation is a modal, not a drawer.
  • Open run history from the row's kebab. It lands in the history panel, not the plain detail page, and centres itself when no run is selected.
  • Regression, desktop: open an agent's panel and edit an automation there. Both kinds open in the same drawer, and the app catalog opens from inside it rather than replacing it.
  • Regression, desktop: Settings no longer lists Triggers, and nothing links to it.

@vercel

vercel Bot commented Sep 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 10, 2026 12:34pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Summary

Summary by CodeRabbit

  • New Features

    • Added a dedicated Automations area with searchable, filterable lists, templates, creation and editing flows, activation controls, deletion, test runs, and run history.
    • Added unified automation drawers for schedules and event-based automations, including app/event selection and configuration.
    • Added draft instruction support when starting test sessions.
    • Added reusable filtering, confirmation, and responsive interfaces with improved loading, error, empty, and failure states.
  • Changes

    • Removed the separate Triggers settings area and consolidated automation management elsewhere.
    • Replaced destructive-action confirmation sheets with modal dialogs.

Walkthrough

The change adds a shared automation UI package, new mobile automation routes and screens, unified automation drawers, removal of legacy trigger settings, and reusable filter-menu and input-group components.

Changes

Automation package

Layer / File(s) Summary
Automation models and persistence
web/packages/agenta-automation-ui/src/automation*.ts, web/packages/agenta-automation-ui/src/run*.ts, web/packages/agenta-automation-ui/src/useAutomation*.ts
Adds normalized automation and run models, list derivation, create/edit payload builders, draft state, editor hooks, run queries, and package exports.
Automation editor and run history
web/packages/agenta-automation-ui/src/Automation*.tsx, web/packages/agenta-automation-ui/src/pickers/*, web/packages/agenta-automation-ui/src/states/*
Adds shared fields, drawers, event selection, templates, run-history views, conversation states, and responsive picker behavior.

Mobile automation surfaces

Layer / File(s) Summary
Routes and list/detail screens
web/mobile/src/pages/w/.../automations/*, web/mobile/src/features/automations/*
Adds automation list, draft, detail, actions, filtering, run history, test runs, unsaved-navigation protection, and project navigation.
Mobile host integration
web/mobile/src/features/chat/*, web/mobile/src/features/sessions/*, web/mobile/src/features/settings/*
Mounts the shared automation drawer, seeds chat drafts for test runs, and replaces confirmation sheets with modal dialogs while removing the mobile triggers tab.

Legacy trigger migration

Layer / File(s) Summary
OSS and entity host wiring
web/oss/src/*, web/packages/agenta-entity-ui/src/DrillInView/*, web/packages/agenta-playground-ui/src/*
Mounts the shared drawer, adds automation creation from agent operations, and changes trigger management to a unified automation list.
Legacy trigger removal
web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/*, web/packages/agenta-settings-ui/src/triggers/*, web/packages/agenta-settings/src/*
Removes the former schedule and subscription editors, settings sections, trigger navigation, and related exports.

Shared UI primitives

Layer / File(s) Summary
Filter and input controls
web/packages/agenta-ui/src/filter-menu/*, web/packages/agenta-ui/src/components/ui/input-group.tsx
Adds responsive filter and group menus, keyboard navigation, persisted view state, input-group controls, public exports, and Storybook stories.
Schema and presentation updates
web/packages/agenta-entity-ui/src/gatewayTool/*, web/packages/agenta-ui/src/components/ui/accordion.tsx
Adds optional-field labels, shared validation text, accordion caret placement, and related layout updates.

Priority: ➖ Normal

Estimated code review effort: 5 (Critical) | ~120 minutes

Severity of issue fixed: Medium

Merge Risk: 🟡 Moderate · up to f4713

The unified automation migration can currently fail to build, bind an automation to the wrong connected account, and prevent users from reaching events in long picker lists. These issues should be resolved before merge.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 24 functions across 75 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: mobile automations and unification of schedules and subscriptions into one automation model.
Description check ✅ Passed The description is detailed and directly explains the unified automation model, mobile features, shared packages, removed trigger screens, testing, and remaining QA work.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mobile-automations

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ashrafchowdury
ashrafchowdury added this pull request to stack #6717 September 9, 2026 06:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🧹 Nitpick comments (6)
web/packages/agenta-ui/src/filter-menu/GroupMenu.tsx (1)

111-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Merge className with the base popover classes instead of replacing them.

className ?? "w-[220px] p-0" drops p-0 whenever a consumer passes any class. The popover then falls back to its default p-1 padding, and the option list adds its own p-1, so the panel renders with double padding. Merge with cn so a consumer can override width without losing the layout reset.

Note also that className targets the popover surface here, but FilterMenu forwards className to FilterMenuPanel (FilterMenu.tsx line 105). Consider documenting that difference on the prop.

♻️ Proposed fix
-import {Popover, PopoverContent} from "../components/ui/popover"
+import {Popover, PopoverContent} from "../components/ui/popover"
+import {cn} from "../components/ui/utils"
-                className={className ?? "w-[220px] p-0"}
+                className={cn("w-[220px] p-0", className)}
web/storybook/stories/FilterMenu.stories.tsx (1)

128-130: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import ComponentProps instead of referencing the React namespace.

web/storybook/tsconfig.json includes story files, enables strict, and does not enable allowUmdGlobalAccess. The React.ComponentProps reference therefore causes a TypeScript UMD-global error. Import ComponentProps directly.

♻️ Proposed fix
-import {useState} from "react"
+import {useState, type ComponentProps} from "react"
-}: {withGroup?: boolean; emptyAgents?: boolean} & Partial<
-    React.ComponentProps<typeof FilterMenu>
->) => {
+}: {withGroup?: boolean; emptyAgents?: boolean} & Partial<ComponentProps<typeof FilterMenu>>) => {
web/packages/agenta-automation-ui/src/states/AutomationStates.tsx (1)

19-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Export this grid template once and consume it in the list screen.

web/mobile/src/features/automations/AutomationListScreen.tsx lines 73-74 hold a byte-identical copy of this string. The skeleton must match the table cell for cell, so the two copies can drift without any test noticing. Export the constant from this package and import it in the screen.

web/packages/agenta-automation-ui/src/AutomationAgentField.tsx (1)

18-29: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reduce the multi-line comment blocks to one short line each. The new package files carry multi-paragraph rationale comments. The coding guideline for web/**/*.{ts,tsx} sets a hard limit of one short line per comment. Move the longer rationale to the package README or a design note.

  • web/packages/agenta-automation-ui/src/AutomationAgentField.tsx#L18-L29: reduce the AutomationAgentField docblock to one line; the same applies to the inline block at L54-56.
  • web/packages/agenta-automation-ui/src/AutomationCreateBody.tsx#L11-L18: reduce the AutomationCreateBody docblock to one line; the same applies to the inline block at L36-37.
  • web/packages/agenta-automation-ui/src/AutomationField.tsx#L3-L9: reduce the AutomationField docblock to one line.
  • web/packages/agenta-automation-ui/src/AutomationTitle.tsx#L8-L14: reduce the AutomationTitle docblock to one line; the same applies to the inline block at L81-82.

As per coding guidelines: "Hard rule. At most ONE short line per comment."

Source: Coding guidelines

web/packages/agenta-automation-ui/package.json (1)

25-25: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Align the lucide-react range with the other workspaces.

web/pnpm-lock.yaml resolves both lucide-react@0.475.0 and lucide-react@0.479.0. The consuming web/oss and web/mobile applications import @agenta/automation-ui, whose source imports lucide-react, so both versions can enter their bundles. Use the shared range and regenerate the lockfile.

♻️ Proposed change
-        "lucide-react": "^0.475.0"
+        "lucide-react": "^0.479.0"
web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/ScheduleBuilderField.tsx (1)

291-298: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The next-run line now renders twice in ScheduleBuilderField.

The panel prints the "Next run …" footer. ScheduleBuilderField still prints the same nextLine under the popover trigger at lines 345-349. While the popover is open, the user sees the sentence twice.

AutomationRunsWhenField relies on the panel owning this line, so the footer belongs here. Remove the duplicate from ScheduleBuilderField.

♻️ Proposed change in `ScheduleBuilderField`
                 </Popover>
-
-                {nextLine ? (
-                    <span className="text-xs leading-snug text-[var(--ag-colorTextDescription)]">
-                        {nextLine}
-                    </span>
-                ) : null}
             </div>

Then drop nextLine from the destructure at line 311.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 90a21abd-eedf-4181-94ff-3702370a1de3

📥 Commits

Reviewing files that changed from the base of the PR and between 0c85a59 and 4da80ee.

⛔ Files ignored due to path filters (1)
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (139)
  • web/mobile/next.config.ts
  • web/mobile/package.json
  • web/mobile/src/components/StatusTag.tsx
  • web/mobile/src/components/ui/dialog.tsx
  • web/mobile/src/components/ui/input-group.tsx
  • web/mobile/src/features/automations/AutomationActionsMenu.tsx
  • web/mobile/src/features/automations/AutomationDetailScreen.tsx
  • web/mobile/src/features/automations/AutomationDraftScreen.tsx
  • web/mobile/src/features/automations/AutomationFilterMenu.tsx
  • web/mobile/src/features/automations/AutomationListScreen.tsx
  • web/mobile/src/features/automations/AutomationRunConversation.tsx
  • web/mobile/src/features/automations/AutomationTestRunButton.tsx
  • web/mobile/src/features/automations/useUnsavedGuard.ts
  • web/mobile/src/features/chat/ConfigPane.tsx
  • web/mobile/src/features/chat/useStartBlankSession.ts
  • web/mobile/src/features/nav/useMobileNavItems.tsx
  • web/mobile/src/features/sessions/SessionAutomationDrawers.tsx
  • web/mobile/src/features/settings/ConfirmModal.tsx
  • web/mobile/src/features/settings/ConfirmSheet.tsx
  • web/mobile/src/features/settings/LlmProvidersTab.tsx
  • web/mobile/src/features/settings/SecretsTab.tsx
  • web/mobile/src/features/settings/SettingsScreen.tsx
  • web/mobile/src/features/settings/WebhooksTab.tsx
  • web/mobile/src/features/settings/settingsTabs.ts
  • web/mobile/src/features/settings/useConfirmModal.tsx
  • web/mobile/src/pages/w/[workspace_id]/p/[project_id]/automations/[automation_id].tsx
  • web/mobile/src/pages/w/[workspace_id]/p/[project_id]/automations/index.tsx
  • web/mobile/src/pages/w/[workspace_id]/p/[project_id]/automations/new.tsx
  • web/mobile/src/styles/globals.css
  • web/oss/next.config.ts
  • web/oss/package.json
  • web/oss/src/components/Playground/Components/PlaygroundVariantConfig/index.tsx
  • web/oss/src/components/pages/sessions/components/SessionAutomationDrawers.tsx
  • web/oss/src/components/pages/settings/README.md
  • web/oss/src/components/pages/settings/Triggers/Triggers.tsx
  • web/oss/src/components/pages/settings/Triggers/components/GatewayTriggersSection.tsx
  • web/oss/src/components/pages/settings/Triggers/components/useAgentNameById.ts
  • web/oss/src/components/pages/settings/hooks/useSettingsAccess.ts
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx
  • web/oss/tailwind.config.ts
  • web/packages/agenta-automation-ui/eslint.config.mjs
  • web/packages/agenta-automation-ui/package.json
  • web/packages/agenta-automation-ui/src/AutomationAgentField.tsx
  • web/packages/agenta-automation-ui/src/AutomationBackLink.tsx
  • web/packages/agenta-automation-ui/src/AutomationCreateBody.tsx
  • web/packages/agenta-automation-ui/src/AutomationDetailBody.tsx
  • web/packages/agenta-automation-ui/src/AutomationDrawer.tsx
  • web/packages/agenta-automation-ui/src/AutomationFailureBanner.tsx
  • web/packages/agenta-automation-ui/src/AutomationField.tsx
  • web/packages/agenta-automation-ui/src/AutomationInstructionField.tsx
  • web/packages/agenta-automation-ui/src/AutomationMetaRow.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunFilterMenu.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunHistoryCard.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunHistoryView.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunList.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunPane.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunRow.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunsWhenField.tsx
  • web/packages/agenta-automation-ui/src/AutomationSaveBar.tsx
  • web/packages/agenta-automation-ui/src/AutomationTemplateCard.tsx
  • web/packages/agenta-automation-ui/src/AutomationTitle.tsx
  • web/packages/agenta-automation-ui/src/AutomationTriggerDrawers.tsx
  • web/packages/agenta-automation-ui/src/automationEdit.ts
  • web/packages/agenta-automation-ui/src/automationListView.ts
  • web/packages/agenta-automation-ui/src/automationModel.ts
  • web/packages/agenta-automation-ui/src/index.ts
  • web/packages/agenta-automation-ui/src/lib/interactive.ts
  • web/packages/agenta-automation-ui/src/lib/useMediaQuery.ts
  • web/packages/agenta-automation-ui/src/lib/utils.ts
  • web/packages/agenta-automation-ui/src/pickers/AppIcon.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventAppRail.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventList.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventPickerPanel.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventRow.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventSearchGroup.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventSearchResults.tsx
  • web/packages/agenta-automation-ui/src/pickers/PickerOverlay.tsx
  • web/packages/agenta-automation-ui/src/pickers/connectedApps.ts
  • web/packages/agenta-automation-ui/src/runListView.ts
  • web/packages/agenta-automation-ui/src/runModel.ts
  • web/packages/agenta-automation-ui/src/states/AutomationRunStates.tsx
  • web/packages/agenta-automation-ui/src/states/AutomationStates.tsx
  • web/packages/agenta-automation-ui/src/templates.ts
  • web/packages/agenta-automation-ui/src/useAutomation.ts
  • web/packages/agenta-automation-ui/src/useAutomationCreate.ts
  • web/packages/agenta-automation-ui/src/useAutomationDraft.ts
  • web/packages/agenta-automation-ui/src/useAutomationEditor.ts
  • web/packages/agenta-automation-ui/src/useAutomationRuns.ts
  • web/packages/agenta-automation-ui/src/useAutomations.ts
  • web/packages/agenta-automation-ui/tsconfig.json
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/AgentOperationsSections.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/TriggerManagementSection.tsx
  • web/packages/agenta-entity-ui/src/drawers/shared/HelpTip.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/FormItem.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/SchemaForm.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/ScheduleBuilderField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerEventsDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerScheduleDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerSubscriptionDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/schedule/ScheduleForm.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/schedule/constants.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/AgentField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/FormSkeleton.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/VersionField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/normalizeJson.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/useShapeChange.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/EventFieldList.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/InputsMappingField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/MappingSection.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/PillEditor.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SourceBrowsePage.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SourceField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SubscriptionForm.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/constants.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/helpers.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/index.ts
  • web/packages/agenta-playground-ui/src/components/AgentBuildPanel.tsx
  • web/packages/agenta-settings-ui/src/index.ts
  • web/packages/agenta-settings-ui/src/triggers/TriggerConnectionsSection.tsx
  • web/packages/agenta-settings-ui/src/triggers/TriggerSchedulesSection.tsx
  • web/packages/agenta-settings-ui/src/triggers/TriggerSubscriptionsSection.tsx
  • web/packages/agenta-settings/src/access.tsx
  • web/packages/agenta-settings/src/navigation.ts
  • web/packages/agenta-settings/src/sidebar.tsx
  • web/packages/agenta-settings/tests/unit/navigation.test.ts
  • web/packages/agenta-ui/package.json
  • web/packages/agenta-ui/src/filter-menu/FilterMenu.tsx
  • web/packages/agenta-ui/src/filter-menu/FilterMenuOptionList.tsx
  • web/packages/agenta-ui/src/filter-menu/FilterMenuPanel.tsx
  • web/packages/agenta-ui/src/filter-menu/FilterMenuRow.tsx
  • web/packages/agenta-ui/src/filter-menu/FilterMenuTrigger.tsx
  • web/packages/agenta-ui/src/filter-menu/GroupMenu.tsx
  • web/packages/agenta-ui/src/filter-menu/index.ts
  • web/packages/agenta-ui/src/filter-menu/types.ts
  • web/packages/agenta-ui/src/filter-menu/useFilterMenuView.ts
  • web/storybook/stories/FilterMenu.stories.tsx
  • web/storybook/stories/GroupMenu.stories.tsx
  • web/storybook/stories/entity-ui/TriggerManagementSection.stories.tsx
  • web/turbo.json
💤 Files with no reviewable changes (32)
  • web/oss/src/components/pages/settings/Triggers/Triggers.tsx
  • web/packages/agenta-settings-ui/src/index.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/schedule/constants.ts
  • web/oss/src/components/pages/settings/hooks/useSettingsAccess.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/normalizeJson.ts
  • web/packages/agenta-settings/src/sidebar.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/MappingSection.tsx
  • web/oss/src/components/pages/settings/Triggers/components/GatewayTriggersSection.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/PillEditor.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SubscriptionForm.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerSubscriptionDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/AgentField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/FormSkeleton.tsx
  • web/oss/src/components/pages/settings/Triggers/components/useAgentNameById.ts
  • web/packages/agenta-settings-ui/src/triggers/TriggerSchedulesSection.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SourceBrowsePage.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/VersionField.tsx
  • web/mobile/src/features/settings/ConfirmSheet.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/useShapeChange.ts
  • web/packages/agenta-settings/src/navigation.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/InputsMappingField.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/helpers.ts
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerScheduleDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/SourceField.tsx
  • web/packages/agenta-settings-ui/src/triggers/TriggerConnectionsSection.tsx
  • web/packages/agenta-settings/src/access.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/EventFieldList.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerEventsDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/subscription/constants.ts
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/schedule/ScheduleForm.tsx
  • web/packages/agenta-settings-ui/src/triggers/TriggerSubscriptionsSection.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Comment thread web/mobile/src/components/ui/dialog.tsx Outdated
Comment thread web/mobile/src/components/ui/dialog.tsx Outdated
Comment thread web/mobile/src/features/automations/useUnsavedGuard.ts
Comment thread web/oss/src/components/pages/settings/README.md
Comment thread web/packages/agenta-automation-ui/src/AutomationCreateBody.tsx Outdated
Comment thread web/packages/agenta-automation-ui/src/runListView.ts
Comment thread web/packages/agenta-automation-ui/src/runListView.ts Outdated
Comment thread web/packages/agenta-ui/src/filter-menu/FilterMenuOptionList.tsx
Comment thread web/packages/agenta-ui/src/filter-menu/FilterMenuRow.tsx Outdated
Comment thread web/packages/agenta-ui/src/filter-menu/FilterMenuRow.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/packages/agenta-ui/src/filter-menu/useFilterMenuView.ts (1)

50-50: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the setView dependencies. The react-hooks/exhaustive-deps rule is disabled for web, so this is not a lint failure. If persist changes while key stays the same, setView uses the stale key list and writes incorrect fields. Add persist to the setView dependency array; keep the mount-only effect unchanged.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 51dfa6d6-f311-46fb-823a-ad38a6d9e3a6

📥 Commits

Reviewing files that changed from the base of the PR and between 4da80ee and a621816.

📒 Files selected for processing (13)
  • web/mobile/src/features/automations/AutomationActionsMenu.tsx
  • web/mobile/src/features/automations/AutomationDetailScreen.tsx
  • web/mobile/src/features/automations/AutomationListScreen.tsx
  • web/mobile/src/features/chat/ConfigPane.tsx
  • web/mobile/src/features/settings/ConfirmModal.tsx
  • web/packages/agenta-automation-ui/src/AutomationRunHistoryView.tsx
  • web/packages/agenta-automation-ui/src/AutomationSaveBar.tsx
  • web/packages/agenta-automation-ui/src/runListView.ts
  • web/packages/agenta-automation-ui/src/states/AutomationStates.tsx
  • web/packages/agenta-settings/tests/unit/navigation.test.ts
  • web/packages/agenta-ui/src/components/ui/index.ts
  • web/packages/agenta-ui/src/components/ui/input-group.tsx
  • web/packages/agenta-ui/src/filter-menu/useFilterMenuView.ts
💤 Files with no reviewable changes (1)
  • web/mobile/src/features/automations/AutomationDetailScreen.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • web/packages/agenta-automation-ui/src/AutomationRunHistoryView.tsx
  • web/packages/agenta-automation-ui/src/AutomationSaveBar.tsx
  • web/packages/agenta-automation-ui/src/runListView.ts
  • web/packages/agenta-settings/tests/unit/navigation.test.ts
  • web/mobile/src/features/chat/ConfigPane.tsx
  • web/packages/agenta-automation-ui/src/states/AutomationStates.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-pr-6716.up.railway.app/w
Project agenta-oss-clone-spike
Image tag pr-6716-919f9e0
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-09-10T12:46:41.843Z

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: e52fef5f-12ed-4cab-9dcf-c39329b1c7bd

📥 Commits

Reviewing files that changed from the base of the PR and between 19e016c and 0845cfb.

📒 Files selected for processing (9)
  • web/mobile/src/features/automations/AutomationDraftScreen.tsx
  • web/packages/agenta-automation-ui/src/AutomationDrawer.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventAppRail.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventList.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventPickerPanel.tsx
  • web/packages/agenta-automation-ui/src/states/EventPickerStates.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/FormItem.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/SchemaForm.tsx
  • web/packages/agenta-ui/src/components/ui/accordion.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/packages/agenta-entity-ui/src/gatewayTool/components/FormItem.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/SchemaForm.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Comment thread web/mobile/src/features/automations/AutomationDraftScreen.tsx
Comment thread web/mobile/src/features/automations/AutomationDraftScreen.tsx
Comment thread web/mobile/src/features/automations/AutomationDraftScreen.tsx
Comment thread web/packages/agenta-automation-ui/src/pickers/EventPickerPanel.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 7be5260b-2a6a-4938-9b91-778ad73d31e5

📥 Commits

Reviewing files that changed from the base of the PR and between 0845cfb and f471307.

📒 Files selected for processing (15)
  • web/mobile/src/components/FilterChip.tsx
  • web/mobile/src/components/ui/button.tsx
  • web/mobile/src/features/automations/AutomationFilterMenu.tsx
  • web/mobile/src/features/chat/ToolLine.tsx
  • web/mobile/src/features/chat/TurnRow.tsx
  • web/mobile/src/features/context/ContextResolver.tsx
  • web/mobile/src/features/nav/NavDrawer.tsx
  • web/packages/agenta-automation-ui/src/AutomationTitle.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventAppRail.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventList.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventPickerPanel.tsx
  • web/packages/agenta-automation-ui/src/pickers/PickerOverlay.tsx
  • web/packages/agenta-entity-ui/src/agent/AgentOverviewSkeleton.tsx
  • web/packages/agenta-entity-ui/src/agent/NextTriggersSection.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/SchemaForm.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • web/packages/agenta-automation-ui/src/AutomationTitle.tsx
  • web/packages/agenta-entity-ui/src/gatewayTool/components/SchemaForm.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventPickerPanel.tsx
  • web/packages/agenta-automation-ui/src/pickers/EventAppRail.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Comment thread web/mobile/src/components/ui/button.tsx
Comment thread web/packages/agenta-automation-ui/src/pickers/EventList.tsx
Comment thread web/packages/agenta-automation-ui/src/pickers/PickerOverlay.tsx
Adds the model, hooks, route shells and nav entry the Automations screens
build on. A cron schedule and an event subscription are separate rows on
separate endpoints, but a reader sees one list of things that run an agent,
so automationModel maps both onto a single Automation type and every screen
reads that instead of branching per entity.

Delivery outcomes read status.message rather than the shared
deliveryStatusColor helper, which reads a status.type the backend never
sets and so returns neutral for every row.
Renders both trigger kinds in one table — name, status, when it runs, and
the agent it runs — over the shared DataTable the settings trigger sections
already use, with search across name, description and agent.

Gives StatusTag a failed tone so a broken automation reads red. attention
maps to the accent, which asks for a look rather than reporting a fault, and
the two must not collapse once run outcomes land.

The empty state is plain markup rather than EmptyState: its image slot is
sized for a 184x152 illustration, and opting a 48px tile out of that took
more overrides than the markup it replaced.
Config lives on the automation's own page rather than in a drawer, so
creating and editing one later share a single surface. The name renames in
place, ActiveToggle owns start/stop, and the three fields reuse the shared
controls: ScheduleBuilderField for the cadence and MessageComposer for the
instruction.

Both trigger endpoints take a full PUT, so buildAutomationEdit copies every
stored field off the source row and overlays only what changed - a rename
must not drop the cron, the message or the agent binding.

Neither field repeats the helper line its shared control already prints,
and an unbound automation reads Pick an agent rather than naming one that
isn't there.
…ents

Both screens were built on default control sizing, which left every heading,
row and gap a few pixels off. Sizes, weights, letter-spacing, padding, radii
and the table's column ratios now come from the design.

The list drops DataTable for a plain CSS grid. The shared table lays out a
real table with a fixed-pixel colgroup, so it cannot express the design's
minmax()/fr columns without being fought at every cell; one GRID constant
now feeds the header, the rows and the skeleton so they cannot drift.

Status in a column of its own is a dot and a coloured word, not a pill -
the pill exists to separate a status from a sentence, and there is no
sentence here.
Both pickers open as a popover on a wide screen and a bottom sheet on a
phone, sharing one overlay helper - an anchored popover is the wrong
affordance at phone width, and the design was drawn wide.

The event side composes the package's own SourceBrowsePage and SchemaForm
rather than reimplementing a catalog browser and a filter form; the two
symbols it needed are added to the export block already kept for hosts
outside the drawer. Agent rebinding goes through buildTriggerReferences so
a pick writes a resolvable reference rather than an artifact-only one.

A binding whose id is missing from the agent roster now reads Unknown
agent. It used to read as unbound, which both misreported the automation
and offered a rebind that would have replaced something real.
New automation and the template cards routed to /automations/new, which
had no route - the dynamic segment caught it, read "new" as an id, and
rendered "This automation no longer exists". A static route wins over the
dynamic one and now renders the draft.

Create and edit are the same surface, as the design draws them: the draft
is the detail screen minus what a draft has not earned - no meta row, no
failure banner, no run history - plus a footer whose Create stays disabled
until an agent is bound.

The create payload sits beside buildAutomationEdit so both PUT and POST
shapes are read in one place, and the blank draft seeds its weekday cron in
the comma form: cronToBuilder parses a plain int list, so 1-5 comes back
unrepresentable and the field would open on a raw expression.
…story card

The meta row states whether an automation is on, so it takes a switch,
which shows that at rest. ActiveToggle is a play/pause button - right in a
row of actions, wrong in a status line - so the pending guard and the
messages it owned move here with it.

The run history card is drawn two lines tall, a title over a run count. It
collapses to one row until that count is wired, because a box sized for two
lines holding one reads as padding around nothing.
The design opens Runs when on a choice between a schedule and an app event.
Without it a schedule can never become an event trigger, which is the point
of that control.

ScheduleBuilderField is split into useScheduleBuilder + ScheduleBuilderPanel
so its panel can sit inside a different popover, with the field itself
rebuilt on the same pair - one implementation, and the existing drawer keeps
its behaviour. Kind stays switchable only on a draft: the two kinds are
separate rows on separate endpoints, so converting a saved one is a create,
a delete and a redirect, not a PUT.

The agent field is a real Select rather than a hand-rolled list, so it
closes on pick, matches the schedule control's height, and drops a heading
the design never had. Both overlays open at their trigger's width.

Unknown agent now waits for the roster to answer. Reading it mid-load
flashed a resolvable binding as broken.
Every button this feature added had picked up its own size or weight - sm
here, a font override there - so no two agreed. They all sit at the default
size now, with the normal weight the design draws, and carry no per-call
geometry of their own.
24px was loud for a name that sits under a back link and above a short
field stack. The rename input moves with it so the swap does not resize.
The rename field was a shadcn Input overridden to imitate the heading it
replaced, which only made the swap a resize. It is the stock input now.

The heading's tap target drops the shared FOCUS_RING for the soft ring the
inputs use: a hard 2px outline in the near-black ring colour reads as a
border around the title rather than as focus.
The panel was rendering the subscription drawer's integration catalog - a
marketplace of ninety apps with descriptions, categories and action counts.
That answers how to connect an app, not which event should run this
automation, so it is replaced by what the design asks for: the apps this
workspace has already connected, that app's events, and a search across
them. Connect another app... is now the only route to the catalog, and it
opens the real drawer.

Apps are named and marked from the integrations catalog rather than the
connection: a connection is named for the account it authorises, so the rail
was reading gmail-main where it meant Gmail. Every event in a list wears its
app's mark, and a mark that has not loaded is a skeleton, not a letter tile
that looks like a broken icon.
…vision

An automation created from the automations page failed on every run with 'No user message
to send (prompt/messages empty)'. The instruction was saved as {"message": "…"}; the runner
reads `prompt` or `messages` and never `message`.

The key came from the workflow molecule, which reads a CACHED entity and never fetches. The
create screen knows the agent only from the agents list, whose rows carry neither
`flags.is_chat` nor an input schema, so `executionMode` returned its "completion" default
and the composer fell through to the literal "message". The playground drawer wrote
`messages` for the same agent, because there the agent was already open.

The field now resolves the agent's latest revision and reads the flag and the schema off it,
and stays disabled until that lands rather than guessing. `remapMessageShape` is wired back
in — it existed and was tested but lost its only caller when the old drawers were deleted —
so a message typed before the revision arrives is migrated rather than left under a dead key.

References bind the latest revision's own variant instead of 'the agent happens to have
exactly one', so an automation runs the newest revision whatever the variant count.
Uppercased in the model, so the heading could not be restyled without changing the data.
Choosing an agent was about to be re-implemented per screen — a Select here, a list there —
which is how the search, the glyphs and the create affordance drift apart. AgentPicker is
the one answer, in @agenta/entity-ui because it fetches its own agents: a picker whose host
hands it a list is a picker every host populates differently.

The design's two densities are one component. 'relaxed' prints each agent's description under
its name for a screen with room to explain; 'compact' prints the name alone for a toolbar.
The trigger is a field or a pill. Nothing else differs, so a reader who learns one has
learned both. A description that does not exist still takes its line, saying so, or the rows
change height and a blank reads as one that failed to load.

A Popover rather than a Select, for the reason @agenta/ui/filter-menu is: a select's
typeahead competes with the search field for every keystroke. Search covers the description
as well as the name — an agent is often easier to recall by what it does. Focus lands in the
field on open, a frame late, because Radix focuses the content wrapper first.

Every row wears a chip, the agent's own colour when it has one and a neutral tile when not:
a column where some rows have one reads as a rendering fault. The bound row keeps a tint of
its own so 'which one is this set to' survives the pointer moving down the list.

The automations agent field is now this component in that screen's frame.
A centred line of grey said the same thing for two different facts. A project with no agents
and a search that matched none of the ones it has now read differently: one offers to make an
agent, the other quotes what was typed, says the search covers names AND descriptions, and
clears itself. Same frame as the other pickers here — a glyph in a tile, the fact, what to do.
…mode

`bg-muted` sits within a hair of the popover's own surface there, so the tiles for agents
without an icon disappeared while the coloured ones stayed — the column read as half-drawn.
`colorFillSecondary` is the fill the agent chrome already uses for an unpicked icon, and it
composites a clear step above the surface in both themes.
The Agent column drew a bare glyph while the control that set it drew a tinted tile, so the
same agent looked like two different things a click apart.

AgentChip comes out of the picker for it. The tile is not the picker's — any list that names
agents wants the same one, and a second implementation is how two columns of the same agents
stop matching.
Sessions wants the same table, so the frame moves to @agenta/ui/list-table where the filter
menu lives: presentational, antd-free, and column-agnostic. It knows a list has columns of
some width, that rows sit under headings that collapse, and that a row opens something. It
never learns what the rows ARE — the columns and the cells are the consumer's, which is why
renderRow is a prop and not a set of cell types.

ListTableToolbar is the row above it: the search field, then a slot. Not a filter prop —
this row does not know what narrows the list, only that something does.

A CSS grid rather than a <table>. shadcn's table was tried and dropped: the columns are
minmax()/fr, the rows carry no cell borders, and a group heading spans the full width
between two runs of rows — none of which a table layout gives without fighting it, and it
turns every cell into a <td> a consumer has to remember to wrap.

The automations list is the first consumer; nothing about it looks different.
Loading is a state of the table, not a screen beside it, so the frame draws it: the real
columns in the real row rhythm, so the list arrives into the shape it was already occupying
instead of snapping a spinner into a table under the reader's cursor. Bar widths cycle down
each column, or five identical pills read as a grid rather than as text.

Uses SkeletonBlock, not Skeleton. Skeleton is antd's composite (avatar + title + paragraph)
and paints nothing of its own — a bare one renders a transparent box, which is exactly what
the first attempt drew.

Replaces the automations list's own AutomationListSkeleton, which restated the columns a
second time and would have drifted from them.
Every one of them drew a transparent box. `Skeleton` from @agenta/ui is antd's composite
(avatar + title + paragraph) and paints nothing of its own; `SkeletonBlock active` is the
bar. The agent surfaces in entity-ui already used it, so this brings the rest into line.

Six files: the run history's rows and day headings, the automations list and detail, the
event picker's app rail, its event list and its app icons, and the agent picker.
…state in the table

Three example cards sat on the emptiest screen in the product, asking the reader to choose
before they knew what they were choosing between. They were also the only thing that ever
set ?template=, so the seed, the card, the catalog and the query param all go together.

What is left says what an automation IS, which is the one thing that screen has to do, and
sits UNDER the column header rather than replacing the table: the columns are still true,
and a project with no automations is a table with no rows, not a different screen. No button
of its own either — New automation is already in the page header, and the same action twice
on one screen reads as two different ones.

An empty list is not the same as a search that matched nothing: the query is narrowed
server-side, so a term with no matches empties the list too and used to claim the project
had none.
The kind glyph sat bare beside a tinted agent tile, so two marks on one row read as two
different kinds of thing. It gets a tile now, and the two kinds take their own tint: down a
column, colour separates 'when something happens' from 'on a schedule' faster than two small
glyphs do. The agent's tile stays at 20px — it is the second mark on a row, not the first.
Each said more than it needed to, and the instruction's line changed shape with the agent —
naming the input key on a completion agent, which is a detail of the wire format rather than
anything the reader chose. All three now state the one fact the control cannot.
A permanent bar sat over the right edge of every row and clipped the times to "17:0". The
app's own ag-scroll-quiet keeps it invisible until the pointer is in the column.
The triggers worker built its dispatcher without a dispatch_fn, so it invoked the workflow
INLINE — a POST to the runner behind a 60s httpx timeout. Any agent run longer than a minute
raised a timeout whose string is empty, and the dispatcher's except branch wrote the delivery
as 500/failed with a blank error while the runner carried on and finished the job. Every
scheduled run of a real agent read as a failure: 20 of 20 on the account I checked, including
one that demonstrably sent its email.

It now dispatches detached, exactly as the interactions worker already does, and the delivery
settles at 202/dispatched.

That is honest but incomplete, and the gap is worth naming: nothing writes the run's terminal
outcome afterwards, so a delivery stays 'dispatched' for good. The UI already treats anything
that is neither succeeded nor failed as in-flight, so it needs no new state — but the word is
now Running rather than Pending, because the runner has the work rather than queuing it.
Closing a delivery on completion needs a durable callback the API does not have yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant