Automations ⚙️#88
Open
paulocastellano wants to merge 16 commits into
Open
Conversation
- Added new automation-related routes and controllers for managing automations. - Introduced automation nodes in the UI with distinct styles and interactions. - Updated sidebar to include navigation for automations. - Enhanced post creation logic to support automation metadata. - Refactored content type and platform enums into types for better type safety. - Added localization for automation-related terms in English, Spanish, and Portuguese. - Improved error handling in various components to accommodate new features.
Conflict resolutions + integration fixes: - CreatePost: kept the branch's merge-into-existing meta persistence (equivalent to main's #86 replace on create, and what the automations flow was built on). - FacebookSettings.vue: kept both new defaults (previewOnly + meta). - RunGenerateNode + GenerateNodeConfig.vue: ContentType::InstagramCarousel was removed on main (#80); an IG carousel is now a multi-image instagram_feed, so the carousel-capable list uses InstagramFeed. - GenerateNodeTest: fixtures use the ContentType enum and the new instagram_feed carousel signal.
… provider Move PostObserver, AutomationRunObserver, and AutomationNodeRunObserver onto their models with the #[ObservedBy] attribute (the Laravel-preferred way) and drop AppServiceProvider::configureObservers() plus its now-unused imports.
…r UX
Generation
- Generate node now produces the full post (text + AI image + carousel)
via a shared PostImagePipeline extracted from StreamPostCreation
- Generate config UI mirrors the /posts/create wizard (carousel slide
count, include-image toggle); drop the decorative format/unsplash keys
Flow correctness
- RSS/HTTP nodes expose named has-items (default) and no-items output
handles, labeled and colored like the Condition node
- AdvanceAutomationRun records a no_matching_edge terminal instead of
completing silently; "0 new items" feedback in the test panel
- Manual/test runs no longer persist the production dedup watermark
Run reliability
- Pause truly halts in-flight runs (production only; manual test runs
always run regardless of automation status)
- ProcessAutomationNode::failed() marks the run failed
- automation:recover-stuck-runs and automation:prune-dry-runs commands
Webhook / HTTP
- Branded User-Agent (config-driven) on outbound webhook + http_request
- Webhook fails on invalid JSON instead of silently sending {}
- HTTP custom headers editor; CodeMirror-based CodeEditor for JSON
Editor UX
- Header Test button only opens the panel; the panel has a Run button
(saves first) and owns the with-real-data toggle
- Clicking a node closes the test panel and opens its config
- Node cards: max-width + truncate so long URLs don't grow the node
…prove node validation - Added support for workflow variables in automations, allowing users to define reusable values. - Implemented validation for Generate nodes to ensure intended image counts align with selected accounts. - Updated automation models and requests to handle new variables, including encryption for sensitive data. - Enhanced UI to display variables and their management within the automation editor. - Improved error handling for webhook and HTTP nodes to prevent requests to invalid URLs. - Refactored various components for better context resolution during automation runs.
Automations editor:
- {{ }} expression autocomplete in CodeMirror, scoped to the braces and
graph-aware (suggests only what upstream nodes provide + variables + now);
migrate the Generate prompt to CodeMirror so it shares the same completions
- Expandable editors: an expand button slides out a side-by-side panel
(matching the sidebar card), with a minimize control; the inline field
collapses to a hint while editing in the panel
- Hover-revealed editor toolbar (expand/copy) with styled tooltips so the
buttons no longer obscure the text while reading
- Beta badge on the Automations sidebar item
- Delete a single connection with Backspace/Delete (edge selection)
- Re-key node config so switching between same-type nodes refreshes the form
HTTP fetch node — cover every JSON response shape:
- Top-level array, object map (items_path=*), array of primitives, and NDJSON
- Key-based dedup via item_key_path (seen-set, FIFO-capped) for feeds without
dates; first poll records a baseline and emits nothing (date path too)
Fan-out test visibility:
- root_run_id links every forked branch back to the run that started a test,
so the test panel aggregates all branches instead of one
Fix a few pre-existing type issues (ScheduleData import, padded minute,
optional created_at).
Replace free-text brand_tone/brand_voice_notes with a single structured brand_voice_traits JSON column backed by the BrandVoiceTrait enum, exposed as choice-chip pills in the brand settings UI and autofillable from a site. Brand voice and visuals become per-automation toggles on the Generate node. Unify the image controls into one 0-10 picker (0 = text-only, 1 = single, 2+ = carousel) and feed the generator the most restrictive selected network so copy fits every platform. Pass that same platform context through the humanizer pass — extracted into a shared ResolvesPlatformCopyBudget trait — so the rewrite can no longer drift past the character cap the generator respected, in both the automation and manual creation flows. Persist the trigger node's schedule editor fields on save (they were silently dropped by validated() for lacking validation rules).
Split the automation detail screen into four route-based tabs behind a shared AutomationHeader: - Workflow: the existing editor canvas. - Invocations: a paginated, filterable run log with expandable per-node detail, a refresh control, and a loading state. - Metrics: KPI cards, a runs-over-time @unovis chart with locale-aware date labels, and a posts-by-platform breakdown over a date range. - Settings: rename, an activate/pause switch, and a danger-zone delete. Invocations and Metrics report only real executions via a new productionRuns scope, so manual test runs (dry or with real data) never leak into the log or the charts. The now-unused excludingDryRuns scope is removed. Generated copy now flows the most-restrictive platform context through the humanizer too, and the editor guide documents every available expression grouped by source node.
- Updated the 'guide' label in English, Spanish, and Portuguese translations to provide clearer context: changed from 'Guide' to 'Learn how it works' and its translations. - Removed the EditorGuide component from the automation form, replacing it with a tooltip that links to the documentation. - Adjusted the icon used for the help button from IconHelp to IconLifebuoy for better visual representation. - Enhanced the tooltip functionality to provide guidance on automation actions directly within the UI.
Wrap the webhook HTTP send in a try/catch so a connection error returns a clean failed result (reason: request_failed) instead of bubbling up as a job failure — matching the HTTP request node. Add tests for the gaps in node-run coverage: - HTTP request: basic auth, PUT/PATCH/DELETE, non-2xx responses, connection exceptions, and an items_path that doesn't resolve to a list. - Webhook: every HTTP method, header expression resolution, and the new connection-failure path. - Fetch RSS: non-2xx feed responses, malformed XML, items without a publish date (skipped), and the link fallback when an item has no guid. - Delay: unknown unit throws. - Publish: dry runs don't publish or queue.
Remove the "Custom (Cron)" schedule field — too technical for the editor. The remaining presets (minutes/hours/days/weeks/months) cover the need and still build the cron string under the hood. Removed at the root: the ScheduleField.Custom enum case, the custom-cron input and select option, the schedule_custom_cron type field and its schedule-summary handling, the backend validation (Rule::in and the schedule_custom_cron rule), the i18n keys, and the custom round-trip test case. Existing automations keep firing — the scheduler runs off the stored cron string, not schedule_field.
Replace the ternary-as-statement with an explicit if/else so @typescript-eslint/no-unused-expressions stops flagging it.
resolveVariable() declares a string return type, but json_encode returns false on malformed UTF-8 (plausible for scraped feed/HTTP payloads), which throws a TypeError under strict_types and fails the node. Encode with JSON_PARTIAL_OUTPUT_ON_ERROR and fall back to an empty string.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds an Automations module — visual, node-based automations that generate and publish posts on triggers.
Includes (so far):
Status
Branch is up to date with
main(merged). Resolutions/integration notes are in the merge commit — notably theContentType::InstagramCarouselremoval frommain(#80): an Instagram carousel is now a multi-imageinstagram_feed, so the carousel-capable detection usesInstagramFeed.Full test suite green (1796 passed); automations suite green (82).
Not done yet
Still WIP — feedback on the node model / UX welcome before final polish.