Skip to content

Conversation

@Abhi1992002
Copy link
Contributor

@Abhi1992002 Abhi1992002 commented Nov 26, 2025

Changes πŸ—οΈ

This PR adds a comprehensive interactive tutorial for the new Builder UI to help users learn how to create agents. Key changes include:

  • Added a tutorial button to the canvas controls that launches a step-by-step guide
  • Created a Shepherd.js-based tutorial with multiple steps covering:
    • Adding blocks from the Block Menu
    • Understanding input and output handles
    • Configuring block values
    • Connecting blocks together
    • Saving and running agents
  • Added data-id attributes to key UI elements for tutorial targeting
  • Implemented tutorial state management with a new tutorialStore
  • Added helper functions for tutorial navigation and block manipulation
  • Created CSS styles for tutorial tooltips and highlights
  • Integrated with the Run Input dialog to support tutorial flow
  • Added prefetching of tutorial blocks for better performance
Screen.Recording.2026-01-13.at.12.17.11.PM.mov

Checklist πŸ“‹

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • Complete the tutorial from start to finish
    • Test tutorial on different screen sizes
    • Verify all tutorial steps work correctly
    • Ensure tutorial can be canceled and restarted
    • Check that tutorial doesn't interfere with normal builder functionality

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

Adds a Shepherd.js-driven interactive tutorial to the FlowEditor, including a tutorial Zustand store, many DOM/canvas/menu/save helper modules, new tutorial step definitions/styles, and instrumentation (data-id / data-tutorial-id) plus small control-panel and store flags to coordinate forced-open UI flows.

Changes

Cohort / File(s) Summary
Builder Actions & Run Dialog
autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/BuilderActions.tsx, .../AgentOutputs/AgentOutputs.tsx, .../RunGraph/RunGraph.tsx, .../RunGraph/useRunGraph.ts, .../RunInputDialog/RunInputDialog.tsx, .../ScheduleGraph/ScheduleGraph.tsx
Added data-id attributes to action buttons and run/stop states; integrated tutorial store with run input dialog (effect + wrapped setter) and added PublishToMarketplace to BuilderActions render tree.
FlowEditor Controls & Node UI
.../Flow/components/CustomControl.tsx, .../handlers/NodeHandle.tsx, .../nodes/CustomNode/components/NodeContainer.tsx, .../NodeOutput/NodeOutput.tsx, nodes/FormCreator.tsx, nodes/OutputHandler.tsx
Wired tutorial running/loading state into controls, added tutorial click handler and loading states, toggled icons/labels, and added data-id / data-tutorial-id attributes to controls and node elements for tutorial targeting.
Tutorial Core: Constants, Styles, Icons, CSS
.../tutorial/constants.ts, .../tutorial/styles.ts, .../tutorial/icons.ts, .../tutorial/tutorial.css, .../tutorial/index.ts
New centralized tutorial constants/selectors/config, style injection and HTML builders (banners/requirements/status), icon map, CSS for highlights/pulses, and orchestration (start/prefetch/load lifecycle).
Tutorial Helpers
.../tutorial/helpers/*.ts (dom.ts,canvas.ts,blocks.ts,highlights.ts,menu.ts,save.ts,state.ts,connections.ts,index.ts)
Added DOM wait/typing/observe helpers, canvas/node polling and positioning, block prefetching/instantiation and lookup, highlight/pulse utilities, menu/save control helpers, connection detection, tutorial state handlers, and an index re-export.
Tutorial Steps
.../tutorial/steps/*.ts (welcome.ts,block-menu.ts,block-basics.ts,configure-calculator.ts,second-calculator.ts,connections.ts,save.ts,run.ts,completion.ts,index.ts)
New Shepherd.js step definitions covering welcome, block menu, block basics, configuring calculator blocks (including polling & gating), adding a second calculator, connecting blocks, save flow, run/output steps, and completion; include lifecycle hooks, DOM waits, and subscriptions.
Control Panel / Block Menu / MenuItem
.../NewControlPanel/NewBlockMenu/Block.tsx, .../BlockMenu/BlockMenu.tsx, .../BlockMenuSearch/BlockMenuSearch.tsx, .../BlockMenuSearchBar/BlockMenuSearchBar.tsx, .../BlockMenuSidebar/BlockMenuSidebar.tsx, .../MenuItem.tsx
Added data-id attributes for block cards and search, introduced forceOpenBlockMenu handling to force the block menu open, added optional menuItemType prop and data-id generation on MenuItem.
Save Control & Control Panel Store
.../NewSaveControl/NewSaveControl.tsx, .../UndoRedoButtons.tsx, stores/controlPanelStore.ts
Added forceOpenSave flag to store and forced-open handling for save Popover; Popover open/onOpenChange respect forced-open; version output annotated with data-tutorial-id; undo/redo buttons gained data-id.
Stores: Tutorial & Node Enhancements
stores/tutorialStore.ts, stores/nodeStore.ts
New useTutorialStore (isTutorialRunning, currentStep, forceOpenRunInputDialog, tutorialInputValues); added setNodeCounter setter to nodeStore.
Legacy/Other UI touches
legacy-builder/BuildActionBar.tsx, legacy-builder/tutorial.ts, components/molecules/TallyPoup/TallyPopup.tsx, components/renderers/InputRenderer/FormRenderer.tsx, components/renderers/.../TitleField.tsx
Replaced/added data-tutorial-id selectors for run button and form/input elements; TallyPopup hides tutorial button in new-builder view; removed stray console.log; added small DOM attributes for tutorial targeting.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Tutorial as Tutorial Orchestrator
    participant Store as Zustand Stores
    participant FlowUI as FlowEditor UI
    participant Canvas as Node/Edge Canvas
    participant API as Block API

    User->>Tutorial: startTutorial()
    Tutorial->>Store: setIsTutorialRunning(true)
    Tutorial->>API: prefetchTutorialBlocks()
    API-->>Tutorial: blocks
    Tutorial->>Store: cache prefetched blocks
    Tutorial->>FlowUI: inject styles & initialize Shepherd tour
    FlowUI-->>User: show Welcome step
    User->>FlowUI: open block menu / add block
    FlowUI->>Store: node added (useNodeStore)
    Store->>Canvas: render node
    Tutorial->>FlowUI: highlight elements, forceOpenBlockMenu(true)
    User->>FlowUI: configure node inputs
    FlowUI->>Store: setTutorialInputValues(...)
    Tutorial->>Store: poll node values via helpers
    User->>Canvas: connect nodes
    Canvas->>Tutorial: edge detected (edgeStore subscription)
    Tutorial->>FlowUI: forceOpenSave(true)
    User->>FlowUI: save & run
    Tutorial->>FlowUI: wait for output element, show run/output step
    User->>Tutorial: complete/skip/cancel
    Tutorial->>Store: cleanup UI state and persist outcome
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

platform/blocks

Suggested reviewers

  • 0ubbe
  • Swiftyos
  • ntindle

Poem

πŸ‡ A rabbit hops through builder lanes,
Highlighting nodes and pulsing veins,
Blocks pop in, the shepherd explains,
Click, connect, save β€” no more refrains,
Hop along β€” the tutorial gains!

πŸš₯ Pre-merge checks | βœ… 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (2 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly summarizes the main change: adding an interactive tutorial for the new builder interface.
Description check βœ… Passed The description is comprehensive and directly related to the changeset, detailing the tutorial implementation, key features, and a completed test plan.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • πŸ“ Generate docstrings


πŸ“œ Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between e4c9b99 and 446f2ac.

πŸ“’ Files selected for processing (7)
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/FormCreator.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/OutputHandler.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/components/renderers/InputRenderer/base/standard/TitleField.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/OutputHandler.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/FormCreator.tsx
  • autogpt_platform/frontend/src/components/renderers/InputRenderer/base/standard/TitleField.tsx
🧰 Additional context used
πŸ““ Path-based instructions (8)
autogpt_platform/frontend/**/*.{ts,tsx}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: Always run pnpm install before frontend development, then use pnpm dev to start development server on port 3000
For frontend code formatting and linting, always run pnpm format

If adding protected frontend routes, update frontend/lib/supabase/middleware.ts

autogpt_platform/frontend/**/*.{ts,tsx}: Use generated API hooks from @/app/api/__generated__/endpoints/ for data fetching in frontend
Use function declarations (not arrow functions) for components and handlers in frontend
Only use Phosphor Icons in frontend; never use other icon libraries
Never use src/components/__legacy__/* or deprecated BackendAPI in frontend

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/**/*.{ts,tsx,json}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

Use Node.js 21+ with pnpm package manager for frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from @/app/api/__generated__/endpoints/ (generated via Orval from backend OpenAPI spec). Pattern: use{Method}{Version}{OperationName} (e.g., useGetV2ListLibraryAgents). Regenerate with: pnpm generate:api. Never use deprecated BackendAPI or src/lib/autogpt-server-api/*
Use function declarations for components and handlers (not arrow functions). Only arrow functions for small inline lambdas (map, filter, etc.)
Use PascalCase for components, camelCase with use prefix for hooks
No barrel files or index.ts re-exports in frontend
For frontend render errors, use component. For mutation errors, display with toast notifications. For manual exceptions, use Sentry.captureException()
Default to client components (use client). Use server components only for SEO or extreme TTFB needs. Use React Query for server state via generated hooks. Co-locate UI state in components/hooks

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/**/*.{js,ts,jsx,tsx}

πŸ“„ CodeRabbit inference engine (AGENTS.md)

Format frontend code using pnpm format

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/**

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

autogpt_platform/frontend/**: Install frontend dependencies using pnpm i instead of npm
Generate API client from OpenAPI spec using pnpm generate:api
Regenerate API client hooks using pnpm generate:api when OpenAPI spec changes

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/**/*.{ts,tsx,css}

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

Use only Tailwind CSS for styling in frontend, with design tokens and Phosphor Icons

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/src/**/*.tsx

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

Use design system components from src/components/ (atoms, molecules, organisms) in frontend

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
autogpt_platform/frontend/src/app/**/*.tsx

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

Create frontend pages in src/app/(platform)/feature-name/page.tsx with corresponding usePageName.ts hook and local components/ subfolder

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx
  • autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx
🧬 Code graph analysis (1)
autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx (3)
autogpt_platform/frontend/src/app/(platform)/build/stores/tutorialStore.ts (1)
  • useTutorialStore (19-32)
autogpt_platform/frontend/src/components/renderers/InputRenderer/FormRenderer.tsx (1)
  • FormRenderer (17-48)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/uiSchema.ts (1)
  • uiSchema (1-12)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: types
  • GitHub Check: chromatic
  • GitHub Check: test
  • GitHub Check: Seer Code Review
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
πŸ”‡ Additional comments (10)
autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/BuildActionBar.tsx (1)

85-86: LGTM!

The data-tutorial-id attribute correctly targets this button for the Shepherd.js tutorial flow.

Minor observation: both data-testid and data-tutorial-id share the same value. If the tutorial system could leverage data-testid selectors, this would avoid duplication. However, keeping them separate does provide clearer separation of concerns between testing and tutorial infrastructure.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/handlers/NodeHandle.tsx (2)

29-29: LGTM!

The data-tutorial-id attribute follows a clear, consistent naming pattern (input-handler-${nodeId}-${cleanedHandleId}) that enables precise targeting by the Shepherd.js tutorial system. Using the already-sanitized cleanedHandleId is appropriate here.


66-66: LGTM!

The data-tutorial-id attribute for output handles maintains naming consistency with the input handle pattern. This enables the tutorial to target specific output handles for demonstration purposes.

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx (6)

11-12: LGTM!

Imports are correctly specified. The useTutorialStore path is consistent with the store definition.


42-55: LGTM!

The tutorial integration is well-implemented:

  • Uses the selector pattern correctly to avoid unnecessary re-renders.
  • The useEffect dependency array is complete and accurate.
  • Conditional sync (if (isTutorialRunning)) ensures the store is only updated during active tutorials.

68-68: LGTM!

The data-id attribute follows a clear naming convention and enables tutorial step targeting without affecting functionality.


70-91: LGTM!

The data-id attributes on the credentials section provide granular targeting for tutorial steps with consistent naming. The form rendering logic remains unchanged.


94-114: LGTM!

The inputs section follows the same consistent data-id naming pattern established in the credentials section. The FormRenderer configuration and behavior remain unchanged.


116-148: LGTM!

The actions section has comprehensive data-id attributes on both the container and individual buttons, enabling precise tutorial step targeting. Button functionality and event handling remain unchanged.

autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts (1)

50-50: LGTM β€” simple setter for tutorial state management.

The implementation correctly follows the existing store patterns (identical to setNodes). Verification confirms the tutorial code properly resets state before setting the counter: setNodes([]) clears nodes first, then setNodeCounter(0) resets the counter, preventing any ID collision risk.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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 and usage tips.

@netlify
Copy link

netlify bot commented Nov 26, 2025

βœ… Deploy Preview for auto-gpt-docs-dev canceled.

Name Link
πŸ”¨ Latest commit 78c3fab
πŸ” Latest deploy log https://app.netlify.com/projects/auto-gpt-docs-dev/deploys/693182b04ed16600089c28e2

@github-actions github-actions bot added the platform/frontend AutoGPT Platform - Front end label Nov 26, 2025
@netlify
Copy link

netlify bot commented Nov 26, 2025

βœ… Deploy Preview for auto-gpt-docs canceled.

Name Link
πŸ”¨ Latest commit 78c3fab
πŸ” Latest deploy log https://app.netlify.com/projects/auto-gpt-docs/deploys/693182b0f5e71000080a91ff

@deepsource-io
Copy link

deepsource-io bot commented Nov 26, 2025

Here's the code health analysis summary for commits 6588110..78c3fab. View details on DeepSourceΒ β†—.

Analysis Summary

AnalyzerStatusSummaryLink
DeepSource JavaScript LogoJavaScriptβœ…Β Success
❗ 30 occurences introduced
🎯 6 occurences resolved
View CheckΒ β†—
DeepSource Python LogoPythonβœ…Β SuccessView CheckΒ β†—

πŸ’‘ If you’re a repository administrator, you can configure the quality gates from the settings.

@AutoGPT-Agent
Copy link

Thank you for adding this tutorial functionality to the new builder! This looks like a valuable feature that will help users get familiar with the builder interface.

However, before this PR can be approved, there are some issues with the PR description that need to be addressed:

  1. Missing description of changes: Please add a clear explanation of what the tutorial does in the "Changes" section of the PR description.

  2. Uncompleted checklist: The PR template checklist needs to be filled out completely. Please:

    • Check the box confirming you've listed your changes
    • Make a test plan
    • Check the box confirming you've tested according to the plan
    • Detail your test plan in the provided section
  3. No test plan: Please provide a test plan that explains how you've verified this tutorial works correctly. This should include steps like:

    • Testing the complete tutorial flow from beginning to end
    • Testing individual tutorial steps
    • Testing on different browsers/screen sizes (if applicable)
    • Any edge cases you've tested

The code changes themselves look well-structured and comprehensive. I particularly like how you've organized the tutorial helpers into separate modules and created detailed, step-by-step guidance for users.

Please update the PR description with the requested information, and then this PR should be ready for approval.

@AutoGPT-Agent
Copy link

Thank you for your contribution adding a tutorial feature to the new builder interface! This looks like a comprehensive implementation of an interactive tutorial system that will help users understand how to use the builder.

However, before we can merge this PR, a few things need to be addressed:

Missing PR Description

  • Please add a clear explanation of why these changes are needed in the PR description
  • Fill out the "Changes" section with a concise summary of what your PR adds (e.g., "Adds an interactive tutorial system to guide new users through the builder interface")

Incomplete Checklist

  • The checklist in the PR description needs to be completed
  • Please check the boxes for relevant items (code changes, test plan)
  • Add your test plan detailing how you verified the tutorial works correctly

Your code looks well-structured with a comprehensive implementation of the tutorial system. The tutorial steps, helpers, and styles are organized in a maintainable way. I particularly like the attention to detail with the different tutorial steps and the visual guidance provided to users.

Once you've updated the PR description and completed the checklist, we'll be happy to review this again for merging.

@AutoGPT-Agent
Copy link

Thank you for adding the tutorial feature to the new builder! This looks like a comprehensive implementation that will help users get started with building agents.

However, before we can merge this PR, please update the PR description to:

  1. Explain the need for this tutorial feature (why it's important)
  2. Provide a concise description of the changes you've made
  3. Complete the checklist items, particularly:
    • Confirming you've listed the changes
    • Noting that you've made a test plan
    • Checking the boxes for testing your changes

Also, could you provide some details about how you tested this feature? For example:

  • Testing the tutorial flow from beginning to end
  • Testing on different screen sizes
  • Any edge cases you checked

The code changes themselves look good - I like how you've structured the tutorial with separate steps and helper functions, and the data-id attributes should make the tutorial elements easy to target.

@AutoGPT-Agent
Copy link

Hi @Abhi1992002, thanks for adding this comprehensive tutorial to the frontend builder!

PR Description Issues

Before this can be merged, you'll need to update your PR description with the following:

  1. Explanation of the changes: Please add a clear explanation of why we need this tutorial and what problem it solves.

  2. List of changes: Add a concise description of what you've implemented, such as:

    • Tutorial system with step-by-step guidance for new users
    • Multi-step tutorial covering adding blocks, connections, and execution
    • Visual highlighting and UI guidance
    • Integration with existing state management
  3. Fill out the checklist: The checklist items need to be checked off to indicate you've completed them. At minimum, fill out the code changes section including your test plan.

Code Implementation

The code itself looks well-structured and comprehensive. You've created a complete tutorial system with:

  • Step-by-step guidance through the builder workflow
  • Helper functions to manage tutorial state
  • Clear tutorial stages (welcome, block menu, configuration, connections, etc.)
  • Visual highlighting to guide users

The implementation appears to follow best practices and integrates well with the existing codebase.

Once you've updated the PR description with the missing information and completed the checklist, this should be ready for review again.

Let me know if you have any questions!

@AutoGPT-Agent
Copy link

Thank you for implementing this comprehensive tutorial for the new builder interface! The code implementation looks well-structured and thorough, with a good separation of concerns between the different parts of the tutorial system.

However, before this PR can be merged, there are a few issues that need to be addressed:

Missing PR Description Information

  1. Please add a clear explanation of the need for these changes in the PR description. Why is this tutorial being added? What problem does it solve?

  2. Complete the checklist in the PR description:

    • Check the box for "I have clearly listed my changes in the PR description" after adding a description of your changes
    • Check the box for "I have made a test plan" and include your test plan
    • Fill in the test plan section with specific steps to test the tutorial functionality

Suggestions for Test Plan

Your test plan should include steps like:

  • Opening the new builder and starting the tutorial
  • Verifying each tutorial step appears correctly and guides the user
  • Confirming the tutorial can be completed end-to-end
  • Testing edge cases like skipping steps or canceling the tutorial

Other Notes

The implementation itself looks good and aligns with the codebase's patterns and practices. I particularly like:

  • The organized structure of the tutorial steps
  • The helper functions for managing DOM interactions
  • The integration with existing components via data attributes
  • The attention to detail in the UI/UX of the tutorial

Once you've addressed the PR description issues, this should be ready to merge.

@github-actions github-actions bot added the conflicts Automatically applied to PRs with merge conflicts label Dec 4, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

…feature flags

- Added a "Start Tutorial" button in the CustomControls component to toggle tutorial state.
- Updated TallyPopup to prevent tutorial display in the new builder view.
- Enabled feature flags for the new flow editor and builder view switch.
- Added `forceOpenBlockMenu` state to control BlockMenu visibility based on tutorial status.
- Updated `CustomControls` to start the tutorial and set the tutorial running state when the "Start Tutorial" button is clicked.
- Improved BlockMenu behavior to respect the new `forceOpenBlockMenu` state for better user experience.
- Added `data-id` attributes to various components for improved accessibility and testing.
- Updated tutorial steps to include new interactions and better guidance for users.
- Enhanced control panel functionality to support new tutorial features and improve user experience.
- Introduced BLOCK_IDS for better management of tutorial block identifiers.
- Implemented prefetching of Agent Input and Agent Output blocks at the start of the tutorial.
- Updated tutorial steps to guide users through adding and configuring Agent Input and Output blocks.
- Enhanced connection checks between blocks to improve user experience during the tutorial.
- Added `data-id` attributes to custom nodes for improved accessibility and testing.
- Updated tutorial constants to include selectors for custom nodes.
- Removed unused tutorial helper functions and steps to streamline the tutorial experience.
- Enhanced the NodeContainer component to support new data attributes for better identification.
…a attributes

- Added `data-id` attributes to the OutputHandler component for better identification.
- Updated tutorial constants with new selectors for output handlers and input fields.
- Modified tutorial steps to utilize new selectors for improved user guidance during connections.
- Enhanced modal overlay padding for better visual alignment in tutorial steps.
- Integrated tutorial features to force open the run input dialog based on tutorial state.
- Updated the RunInputDialog to track input values for tutorial progress.
- Added data attributes for better accessibility and testing in various components.
- Improved connection status handling and visual feedback during tutorial steps.
- Enhanced the run steps to include checks for input values and execution feedback.
@Abhi1992002 Abhi1992002 force-pushed the abhimanyuyadav/open-2840-add-tutorial-in-new-builder branch from 78c3fab to 7166748 Compare January 13, 2026 04:21
@github-actions github-actions bot removed the conflicts Automatically applied to PRs with merge conflicts label Jan 13, 2026
@github-actions
Copy link
Contributor

Conflicts have been resolved! πŸŽ‰ A maintainer will review the pull request shortly.

- Integrated new tutorial steps for connecting multiple Calculator blocks.
- Added data attributes for improved accessibility and testing across various components.
- Updated tutorial constants and selectors to reflect new component structures.
- Enhanced user guidance during tutorial interactions, including connection and execution steps.
- Streamlined tutorial steps to focus on the new Calculator functionality and user experience.
…perience

- Added new icons for Builder Actions, Block & Save Panel, Canvas Controls, and Info sections to improve visual guidance in the tutorial.
- Removed outdated CSS styles related to the tutorial, streamlining the stylesheet for better maintainability.
- Adjusted CSS properties for Shepherd.js elements to enhance layout and spacing in the tutorial flow.
- Updated tutorial steps to ensure consistency and clarity in user interactions.
@Abhi1992002 Abhi1992002 requested review from 0ubbe, kcze and majdyz and removed request for a team, kcze and majdyz January 13, 2026 06:33
@qodo-code-review
Copy link

PR Reviewer Guide πŸ”

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 πŸ”΅πŸ”΅πŸ”΅πŸ”΅βšͺ
πŸ§ͺΒ No relevant tests
πŸ”’Β Security concerns

XSS / HTML injection:
Multiple steps build HTML strings that are rendered by Shepherd (via text template strings) and include raw SVG markup from ICONS. While the icon strings are static in this PR, the pattern is inherently risky if any of the interpolated content ever becomes user-controlled (e.g., names/descriptions, block titles). Consider using Shepherd's safer APIs (DOM nodes) or strict sanitization/escaping for any dynamic values inserted into text.

⚑ Recommended focus areas for review

Data Loss Risk

Starting the tutorial clears nodes/edges and resets the node counter in the global stores. This is risky if a user launches the tutorial in an existing flow (potentially wiping unsaved work). Confirm the tutorial runs in an isolated sandbox graph, or gate this behind an explicit confirmation and/or restore previous state on cancel/complete.

export const startTutorial = async () => {
  isTutorialLoading = true;
  tutorialLoadingCallback?.(true);

  useNodeStore.getState().setNodes([]);
  useEdgeStore.getState().setEdges([]);
  useNodeStore.getState().setNodeCounter(0);
Cleanup / Leaks

Step logic relies on polling intervals and global window variables to track them. This can leak intervals or collide across multiple tutorials/steps if cancellation, step switching, or multiple tours occur unexpectedly. Prefer storing interval IDs on the step instance (similar to the edge unsubscribe approach) and ensure cleanup runs on cancel/complete as well as hide.

show: () => {
  const node = getFirstNode();
  if (node) {
    highlightElement(`[data-id="custom-node-${node.id}"]`);
  }

  let wasComplete = false;

  // Start polling to update requirements UI and button visibility
  const checkInterval = setInterval(() => {
    const node = getFirstNode();
    if (!node) return;

    const hardcodedValues = node.data?.hardcodedValues || {};
    const hasA =
      hardcodedValues.a !== undefined &&
      hardcodedValues.a !== null &&
      hardcodedValues.a !== "";
    const hasB =
      hardcodedValues.b !== undefined &&
      hardcodedValues.b !== null &&
      hardcodedValues.b !== "";
    const hasOp =
      hardcodedValues.operation !== undefined &&
      hardcodedValues.operation !== null &&
      hardcodedValues.operation !== "";

    const allComplete = hasA && hasB && hasOp;

    // Update requirement icons
    const reqA = document.querySelector("#req-a .req-icon");
    const reqB = document.querySelector("#req-b .req-icon");
    const reqOp = document.querySelector("#req-op .req-icon");

    if (reqA) reqA.textContent = hasA ? "βœ“" : "β—‹";
    if (reqB) reqB.textContent = hasB ? "βœ“" : "β—‹";
    if (reqOp) reqOp.textContent = hasOp ? "βœ“" : "β—‹";

    // Update styling for completed items
    const reqAEl = document.querySelector("#req-a");
    const reqBEl = document.querySelector("#req-b");
    const reqOpEl = document.querySelector("#req-op");

    if (reqAEl) {
      reqAEl.classList.toggle("text-green-600", hasA);
      reqAEl.classList.toggle("text-amber-600", !hasA);
    }
    if (reqBEl) {
      reqBEl.classList.toggle("text-green-600", hasB);
      reqBEl.classList.toggle("text-amber-600", !hasB);
    }
    if (reqOpEl) {
      reqOpEl.classList.toggle("text-green-600", hasOp);
      reqOpEl.classList.toggle("text-amber-600", !hasOp);
    }

    // Update box to success state when all complete
    if (allComplete && !wasComplete) {
      updateToSuccessState();
      wasComplete = true;
    } else if (!allComplete && wasComplete) {
      updateToWarningState();
      wasComplete = false;
    }

    // Show/hide the next button based on completion
    const nextBtn = document.querySelector(
      ".shepherd-button-primary",
    ) as HTMLButtonElement;
    if (nextBtn) {
      nextBtn.style.opacity = allComplete ? "1" : "0.5";
      nextBtn.style.pointerEvents = allComplete ? "auto" : "none";
    }
  }, 300);

  // Store interval ID for cleanup
  (window as any).__tutorialCheckInterval = checkInterval;
},
hide: () => {
  removeAllHighlights();
  if ((window as any).__tutorialCheckInterval) {
    clearInterval((window as any).__tutorialCheckInterval);
    delete (window as any).__tutorialCheckInterval;
  }
Selector Fragility

Several selectors appear brittle or potentially incorrect (hardcoded node ids, extra whitespace in selectors, and reliance on β€œpre-save” ids). This can cause the tutorial to break with minor UI changes. Consider basing targeting on stable data attributes added to components (e.g., data-tutorial-id) and fix any selector typos/whitespace.

export const TUTORIAL_SELECTORS = {
  // Custom nodes - These are all before saving
  INPUT_NODE: '[data-id="custom-node-2"]',
  OUTPUT_NODE: '[data-id="custom-node-3 "]',
  CALCULATOR_NODE: '[data-id="custom-node-1"]',

  // Paricular field selector
  NAME_FIELD_OUTPUT_NODE: '[data-id="field-3-root_name"]',

  // Output Handlers
  SECOND_CALCULATOR_RESULT_OUTPUT_HANDLER:
    '[data-tutorial-id="output-handler-2-result"]',
  FIRST_CALCULATOR_RESULT_OUTPUT_HANDLER:
    '[data-tutorial-id="output-handler-1-result"]',

  // Input Handler
  SECOND_CALCULATOR_NUMBER_A_INPUT_HANDLER:
    '[data-tutorial-id="input-handler-2-a"]',
  OUTPUT_VALUE_INPUT_HANDLEER: '[data-tutorial-id="label-3-root_value"]',

  // Block Menu
  BLOCKS_TRIGGER: '[data-id="blocks-control-popover-trigger"]',
  BLOCKS_CONTENT: '[data-id="blocks-control-popover-content"]',
  BLOCKS_SEARCH_INPUT:
    '[data-id="blocks-control-search-bar"] input[type="text"]',
  BLOCKS_SEARCH_INPUT_BOX: '[data-id="blocks-control-search-bar"]',

  // Add a new selector that checks within search results

  // Block Menu Sidebar
  MENU_ITEM_INPUT_BLOCKS: '[data-id="menu-item-input_blocks"]',
  MENU_ITEM_ALL_BLOCKS: '[data-id="menu-item-all_blocks"]',
  MENU_ITEM_ACTION_BLOCKS: '[data-id="menu-item-action_blocks"]',
  MENU_ITEM_OUTPUT_BLOCKS: '[data-id="menu-item-output_blocks"]',
  MENU_ITEM_INTEGRATIONS: '[data-id="menu-item-integrations"]',
  MENU_ITEM_MY_AGENTS: '[data-id="menu-item-my_agents"]',
  MENU_ITEM_MARKETPLACE: '[data-id="menu-item-marketplace_agents"]',
  MENU_ITEM_SUGGESTION: '[data-id="menu-item-suggestion"]',

  // Block Cards
  BLOCK_CARD_PREFIX: '[data-id^="block-card-"]',
  BLOCK_CARD_AGENT_INPUT: '[data-id="block-card-AgentInputBlock"]',
  // Calculator block - legacy ID used in old tutorial
  BLOCK_CARD_CALCULATOR:
    '[data-id="block-card-b1ab9b1967a6406dabf52dba76d00c79"]',
  BLOCK_CARD_CALCULATOR_IN_SEARCH:
    '[data-id="blocks-control-search-results"] [data-id="block-card-b1ab9b1967a6406dabf52dba76d00c79"]',

  // Save Control
  SAVE_TRIGGER: '[data-id="save-control-popover-trigger"]',
  SAVE_CONTENT: '[data-id="save-control-popover-content"]',
  SAVE_AGENT_BUTTON: '[data-id="save-control-save-agent"]',
  SAVE_NAME_INPUT: '[data-id="save-control-name-input"]',
  SAVE_DESCRIPTION_INPUT: '[data-id="save-control-description-input"]',

  // Builder Actions (Run, Schedule, Outputs)
  BUILDER_ACTIONS: '[data-id="builder-actions"]',
  RUN_BUTTON: '[data-id="run-graph-button"]',
  STOP_BUTTON: '[data-id="stop-graph-button"]',
  SCHEDULE_BUTTON: '[data-id="schedule-graph-button"]',
  AGENT_OUTPUTS_BUTTON: '[data-id="agent-outputs-button"]',

  // Run Input Dialog
  RUN_INPUT_DIALOG_CONTENT: '[data-id="run-input-dialog-content"]',
  RUN_INPUT_CREDENTIALS_SECTION: '[data-id="run-input-credentials-section"]',
  RUN_INPUT_CREDENTIALS_FORM: '[data-id="run-input-credentials-form"]',
  RUN_INPUT_INPUTS_SECTION: '[data-id="run-input-inputs-section"]',
  RUN_INPUT_INPUTS_FORM: '[data-id="run-input-inputs-form"]',
  RUN_INPUT_ACTIONS_SECTION: '[data-id="run-input-actions-section"]',
  RUN_INPUT_MANUAL_RUN_BUTTON: '[data-id="run-input-manual-run-button"]',
  RUN_INPUT_SCHEDULE_BUTTON: '[data-id="run-input-schedule-button"]',

  // Custom Controls (bottom left)
  CUSTOM_CONTROLS: '[data-id="custom-controls"]',
  ZOOM_IN_BUTTON: '[data-id="zoom-in-button"]',
  ZOOM_OUT_BUTTON: '[data-id="zoom-out-button"]',
  FIT_VIEW_BUTTON: '[data-id="fit-view-button"]',
  LOCK_BUTTON: '[data-id="lock-button"]',
  TUTORIAL_BUTTON: '[data-id="tutorial-button"]',

  // Canvas
  REACT_FLOW_CANVAS: ".react-flow__pane",
  REACT_FLOW_NODE: ".react-flow__node",
  REACT_FLOW_NODE_FIRST: '[data-testid^="rf__node-"]:first-child',
  REACT_FLOW_EDGE: '[data-testid^="rf__edge-"]',

  // Node elements
  NODE_CONTAINER: '[data-id^="custom-node-"]',
  NODE_HEADER: '[data-id^="node-header-"]',
  NODE_INPUT_HANDLES: '[data-tutorial-id="input-handles"]',
  NODE_OUTPUT_HANDLE: '[data-handlepos="right"]',
  NODE_INPUT_HANDLE: "[data-nodeid]",
  FIRST_CALCULATOR_NODE_OUTPUT: '[data-tutorial-id="node-output"]',
  // These are the Id's of the nodes before saving
  CALCULATOR_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-1-node"]', // <-- Add this line
  AGENT_INPUT_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-2-node"]', // <-- Add this line
  AGENT_OUTPUT_NODE_FORM_CONTAINER:
    '[data-id^="form-creator-container-3-node"]', // <-- Add this line

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

πŸ€– Fix all issues with AI agents
In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts:
- Line 14: Fix the typo in the inline comment that currently reads "Paricular
field selector" by updating it to "Particular field selector"; locate the
comment in the FlowEditor tutorial constants file (look for the comment above
the field selector-related constants) and correct the spelling only.
- Line 11: The OUTPUT_NODE constant's selector string includes a trailing space
('[data-id="custom-node-3 "]') which prevents matching elements with
data-id="custom-node-3"; update the OUTPUT_NODE constant in constants.ts
(OUTPUT_NODE) to remove the extra space inside the quotes so the selector is
'[data-id="custom-node-3"]'.
- Line 26: Rename the constant OUTPUT_VALUE_INPUT_HANDLEER to
OUTPUT_VALUE_INPUT_HANDLER and update any references to it (e.g., imports or
usages in the FlowEditor tutorial code) so the identifier is spelled correctly;
ensure the string value '[data-tutorial-id="label-3-root_value"]' remains
unchanged and run tests/compile to catch any missed references.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/connections.ts:
- Around line 11-26: The exported isConnectionMade function is dead or flawed:
either remove the unused export, or modify isConnectionMade to accept concrete
node IDs (instead of block IDs) or handle multiple nodes per block by using
nodes.filter to collect all sourceNodes and targetNodes and then verify any edge
links any sourceNode.id to any targetNode.id (using
useEdgeStore.getState().edges and useNodeStore.getState().nodes); update callers
to pass node IDs if you choose the node-ID approach and keep the export if it
will be used.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts:
- Around line 70-79: The selector used in highlightFirstBlockInSearch currently
queries TUTORIAL_SELECTORS.BLOCK_CARD_PREFIX globally; narrow it to only
search-result blocks by querying the search results container for block cards
(e.g., '[data-id="blocks-control-search-results"] [data-id^="block-card-"]').
Update the selector in highlightFirstBlockInSearch to scope the query to the
search results element so only blocks inside that panel are found, then keep the
existing logic that adds CSS_CLASSES.PULSE and calls scrollIntoView.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts:
- Around line 177-221: The when.show handler registers a useNodeStore.subscribe
and stores its unsubscribe as (tour.getCurrentStep() as any)._nodeUnsubscribe
but there is no when.hide to clean it up; add a when.hide handler for this step
that retrieves the stored unsubscribe (if any), calls it, clears the
_nodeUnsubscribe property, and performs the same UI cleanup (enableAllBlocks()
and forceBlockMenuOpen(false)) so the subscription is removed if the user
cancels or navigates away. Ensure you reference the same identifiers
(useNodeStore.subscribe, _nodeUnsubscribe, enableAllBlocks, forceBlockMenuOpen,
tour.next) and guard against calling an already-invoked unsubscribe.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/completion.ts:
- Line 3: The parameter type for createCompletionSteps is currently loose (tour:
any); change it to use the Tour type from shepherd.js for proper type safety by
importing Tour from 'shepherd.js' and updating the signature to use Tour (i.e.,
createCompletionSteps(tour: Tour): StepOptions[]). Ensure any places that call
tour methods inside createCompletionSteps still compile and fix any minor type
mismatches exposed by the stronger type.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/save.ts:
- Line 60: The beforeShowPromise in the save-details tutorial step currently
returns waitForElement(TUTORIAL_SELECTORS.SAVE_CONTENT) without handling
rejections, causing unhandled promise rejections if the element never appears;
make it consistent with the open-save step by attaching a rejection handler
(e.g., .catch(() => {})) or otherwise handling the error so the tutorial flow
won't breakβ€”update the beforeShowPromise callback referenced by the save-details
step to call waitForElement(TUTORIAL_SELECTORS.SAVE_CONTENT).catch(() => {}) (or
an equivalent handler).

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts:
- Around line 162-182: The polling in beforeShowPromise uses checkNode and can
hang forever; add a watchdog timeout (e.g., 5–10s) and stop polling when
expired: start a timeout timer when beforeShowPromise begins, clear it when
resolved, and if it fires reject or resolve with a fallback so the tutorial
proceeds; update checkNode to stop calling setTimeout once the timeout has
elapsed, reference the beforeShowPromise function, the checkNode inner function,
getSecondCalculatorNode(), and the
`[data-id="form-creator-container-${secondNode.id}-node"]` selector when
implementing this change.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts:
- Around line 54-67: The banner() function currently interpolates icon and
content directly into HTML; add a JSDoc above banner() that explicitly states
icon and content MUST be developer-controlled hardcoded values (no
user-controlled input), and mention the safe alternative: if you ever need to
render dynamic/user data, use an HTML-escape helper (e.g., escapeHtml) for
content or render SVG/icon nodes safely instead of string interpolation; update
the docblock to reference banner() and bannerStyles so future maintainers know
the constraint and the fallback mitigation.
🧹 Nitpick comments (45)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/CustomNode/components/NodeOutput/NodeOutput.tsx (1)

26-29: LGTM! Minor style nit: template literal is unnecessary for a static string.

The data-tutorial-id attribute is correctly placed for tutorial targeting. Consider using a plain string instead of template literal since the value is static:

-      data-tutorial-id={`node-output`}
+      data-tutorial-id="node-output"
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/nodes/OutputHandler.tsx (1)

49-53: LGTM with a note on selector robustness.

The data-tutorial-id attribute placement is appropriate for tutorial targeting. However, fieldTitle may contain dots or spaces (e.g., from nested properties or schema titles), which could complicate CSS attribute selectors if the tutorial needs to target specific fields.

If precise targeting becomes problematic, consider using fullKey instead or sanitizing fieldTitle to remove special characters:

-            data-tutorial-id={`output-handler-${nodeId}-${fieldTitle}`}
+            data-tutorial-id={`output-handler-${nodeId}-${fullKey}`}

This is optional unless the tutorial step definitions encounter issues selecting these elements.

autogpt_platform/frontend/src/app/(platform)/build/components/NewControlPanel/NewBlockMenu/BlockMenuSearchBar/BlockMenuSearchBar.tsx (1)

3-5: Consider migrating away from legacy components.

Lines 3 and 5 import from @/components/__legacy__/ui/, which the coding guidelines indicate should not be used. While this is pre-existing code and outside the scope of this PR, consider migrating to the design system components from src/components/ (atoms, molecules, organisms) in a follow-up.

As per coding guidelines: "Never use src/components/__legacy__/* or deprecated BackendAPI in frontend."

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/AgentOutputs/AgentOutputs.tsx (1)

9-18: Consider migrating away from legacy components.

This file uses several components from @/components/__legacy__/ui/ (Label, ScrollArea, Sheet, etc.). As per coding guidelines, these should be migrated to the design system components from src/components/ when feasible.

This is pre-existing code and not introduced by this PR, so it can be addressed in a future cleanup effort.

autogpt_platform/frontend/src/app/(platform)/build/components/NewControlPanel/NewBlockMenu/Block.tsx (1)

1-2: Consider migrating away from legacy UI components.

As per coding guidelines, src/components/__legacy__/* should not be used in frontend code. While this is pre-existing in this file and not introduced by your PR, consider migrating Button and Skeleton imports to the design system components from src/components/ (atoms, molecules, organisms) in a follow-up.

autogpt_platform/frontend/src/app/(platform)/build/components/NewControlPanel/NewBlockMenu/BlockMenuSidebar/BlockMenuSidebar.tsx (1)

4-4: Consider migrating away from legacy Skeleton component.

The coding guidelines indicate that @/components/__legacy__/* imports should not be used. While this import is pre-existing and not introduced by this PR, consider migrating to a design system component in a follow-up.

autogpt_platform/frontend/src/app/(platform)/build/components/NewControlPanel/NewBlockMenu/MenuItem.tsx (1)

3-3: Consider migrating to the design system Button component.

The coding guidelines indicate that @/components/__legacy__/* imports should not be used. A newer Button component exists at @/components/atoms/Button/Button.tsx (per the relevant code snippet). While this import is pre-existing, consider migrating in a follow-up to align with the design system. As per coding guidelines, frontend should use design system components from src/components/ (atoms, molecules, organisms).

autogpt_platform/frontend/src/app/(platform)/build/components/NewControlPanel/UndoRedoButtons.tsx (2)

1-1: Legacy component import should be replaced.

The Separator is imported from @/components/__legacy__/ui/separator. Per coding guidelines, legacy components should not be used. Consider migrating to a design system equivalent or creating a new atom component.


13-13: Consider using function declaration for component.

Per coding guidelines, frontend components should use function declarations rather than arrow functions. This is a minor stylistic note that can be addressed in a follow-up.

♻️ Suggested refactor
-export const UndoRedoButtons = () => {
+export function UndoRedoButtons() {
autogpt_platform/frontend/src/components/molecules/TallyPoup/TallyPopup.tsx (1)

10-13: Minor redundancy: pathname is fetched in both component and hook.

The useTallyPopup hook already calls usePathname() internally (see useTallyPopup.ts line 16). Consider either:

  1. Exposing pathname from the hook's return value, or
  2. Moving the isNewBuilder logic into the hook

This avoids two separate usePathname() calls in the same render tree.

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/RunGraph.tsx (1)

13-13: Consider using function declaration for component.

Per coding guidelines, components should use function declarations rather than arrow functions. This is a minor stylistic note consistent with other components in the codebase.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/completion.ts (3)

13-20: Redundant list bullet styling.

The list items use both HTML <li> elements and manual β€’ bullet characters. Since <li> elements naturally render bullets when styled properly, consider removing the manual bullets.

♻️ Suggested fix
-          <ul class="text-[0.8125rem] text-green-600 m-0 pl-4 mt-2 space-y-1">
-            <li>β€’ Add blocks from the Block Menu</li>
-            <li>β€’ Understand input and output handles</li>
-            <li>β€’ Configure block values</li>
-            <li>β€’ Connect blocks together</li>
-            <li>β€’ Save and run your agent</li>
-            <li>β€’ View execution status and output</li>
+          <ul class="text-[0.8125rem] text-green-600 m-0 pl-4 mt-2 space-y-1 list-disc">
+            <li>Add blocks from the Block Menu</li>
+            <li>Understand input and output handles</li>
+            <li>Configure block values</li>
+            <li>Connect blocks together</li>
+            <li>Save and run your agent</li>
+            <li>View execution status and output</li>

26-35: Direct DOM manipulation for opacity could be fragile.

The when.show callback directly mutates the modal overlay's style. This approach works but could be fragile if the class name changes or if multiple steps manipulate the same element. Consider:

  1. Using Shepherd's built-in modal options if available
  2. Adding/removing a CSS class instead of inline style manipulation

This is acceptable for now given Shepherd.js patterns, but worth noting for maintainability.


39-42: Restart action timing could be improved.

The setTimeout delay of 100ms is a magic number without explanation. Consider:

  1. Adding a comment explaining why the delay is needed (likely to allow cancel animation to complete)
  2. Using a named constant for the delay value
♻️ Suggested improvement
+const TOUR_RESTART_DELAY_MS = 100; // Allow cancel animation to complete

       {
         text: "Restart Tutorial",
         action: () => {
           tour.cancel();
-          setTimeout(() => tour.start(), 100);
+          setTimeout(() => tour.start(), TOUR_RESTART_DELAY_MS);
         },
autogpt_platform/frontend/src/components/renderers/InputRenderer/base/standard/TitleField.tsx (1)

32-36: Undefined attribute value may render as string "undefined".

When nodeId is falsy, tutorialId becomes undefined. In React, setting data-tutorial-id={undefined} may still render the attribute with the literal string "undefined" depending on the React version and rendering context. This could interfere with tutorial selectors.

Consider using a conditional spread or explicit null check:

♻️ Suggested fix
   return (
-    <div className="flex items-center" data-tutorial-id={tutorialId}>
+    <div className="flex items-center" {...(tutorialId && { 'data-tutorial-id': tutorialId })}>
autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/useRunGraph.ts (1)

53-58: Consider using function declaration for handler.

Based on coding guidelines, handlers should use function declarations rather than arrow functions.

♻️ Suggested refactor
-  // Reset tutorial state when dialog closes
-  const handleSetOpenRunInputDialog = (isOpen: boolean) => {
-    setOpenRunInputDialog(isOpen);
-    if (!isOpen && forceOpenRunInputDialog) {
-      setForceOpenRunInputDialog(false);
-    }
-  };
+  // Reset tutorial state when dialog closes
+  function handleSetOpenRunInputDialog(isOpen: boolean) {
+    setOpenRunInputDialog(isOpen);
+    if (!isOpen && forceOpenRunInputDialog) {
+      setForceOpenRunInputDialog(false);
+    }
+  }
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (1)

102-105: Remove development artifact comments.

The // <-- Add this line comments appear to be leftover development notes and should be removed.

♻️ Proposed cleanup
-  CALCULATOR_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-1-node"]', // <-- Add this line
-  AGENT_INPUT_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-2-node"]', // <-- Add this line
-  AGENT_OUTPUT_NODE_FORM_CONTAINER:
-    '[data-id^="form-creator-container-3-node"]', // <-- Add this line
+  CALCULATOR_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-1-node"]',
+  AGENT_INPUT_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-2-node"]',
+  AGENT_OUTPUT_NODE_FORM_CONTAINER: '[data-id^="form-creator-container-3-node"]',
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/Flow/components/CustomControl.tsx (1)

35-38: Cleanup callback could be more defensive.

Setting an empty callback on cleanup might cause issues if the tutorial system calls it after component unmount. Consider using a null check pattern.

♻️ Alternative cleanup pattern
 useEffect(() => {
   setTutorialLoadingCallback(setIsTutorialLoading);
-  return () => setTutorialLoadingCallback(() => {});
+  return () => setTutorialLoadingCallback(null);
 }, []);

This requires updating setTutorialLoadingCallback to accept null and adding a null check before invocation.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/tutorial.css (1)

1-149: CSS file is acceptable for third-party library styling.

While the coding guidelines prefer Tailwind CSS, this raw CSS file is justified for overriding Shepherd.js's built-in styles. The styles correctly use the project's design tokens (zinc color palette, Geist/Poppins fonts) and the class names align with CSS_CLASSES in constants.ts.

Consider adding a comment at the top of the file explaining why raw CSS is used here.

♻️ Add explanatory comment
+/**
+ * Custom styles for Shepherd.js tutorial tour.
+ * Raw CSS is used here because Shepherd.js requires CSS overrides
+ * that cannot be achieved with Tailwind utility classes alone.
+ */
+
 .new-builder-tutorial-highlight * {
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (2)

48-54: Bidirectional partial match logic may be too permissive.

The condition currentValue.includes(target) || target.includes(currentValue) allows matches in both directions. For example, if target="Calculator" and user types "Calc", target.includes(currentValue) is true. But if user types "CalculatorBlock", currentValue.includes(target) would also match. Consider if this is the intended behavior.

Also, the magic number 4 for minimum characters could be extracted to a constant.

♻️ Suggested clarification
+// Minimum characters required before considering a match
+const MIN_SEARCH_CHARS = 4;
+
 export const waitForInputValue = (
   selector: string,
   targetValue: string,
   timeout = 30000,
 ): Promise<void> => {
   return new Promise((resolve) => {
     const startTime = Date.now();

     const checkInput = () => {
       const input = document.querySelector(selector) as HTMLInputElement;
       if (input) {
         const currentValue = input.value.toLowerCase().trim();
         const target = targetValue.toLowerCase().trim();

-        if (currentValue.includes(target) || target.includes(currentValue)) {
-          // Check if user has typed enough characters (at least 4 chars or the full string)
-          if (currentValue.length >= 4 || currentValue === target) {
+        // Match when target starts with what user typed (prefix match)
+        if (target.startsWith(currentValue) || currentValue === target) {
+          if (currentValue.length >= MIN_SEARCH_CHARS || currentValue === target) {
             resolve();
             return;
           }

155-180: Potential race condition in observeElement.

The immediate check on lines 173-177 could trigger the callback, but if an element appears between setting up the observer and the immediate check, the callback might be invoked twice before disconnect() is called.

♻️ Suggested fix
 export const observeElement = (
   selector: string,
   callback: (element: Element) => void,
 ): MutationObserver => {
+  let called = false;
+  
+  const invokeCallback = (element: Element) => {
+    if (called) return;
+    called = true;
+    callback(element);
+  };
+
   const observer = new MutationObserver((mutations, obs) => {
     const element = document.querySelector(selector);
     if (element) {
-      callback(element);
+      invokeCallback(element);
       obs.disconnect();
     }
   });

   observer.observe(document.body, {
     childList: true,
     subtree: true,
   });

   // Also check immediately
   const element = document.querySelector(selector);
   if (element) {
-    callback(element);
+    invokeCallback(element);
     observer.disconnect();
   }

   return observer;
 };
autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/tutorial.ts (1)

60-71: Consider consolidating waitForElement implementations.

The legacy builder has its own waitForElement with a hardcoded 10ms polling interval, while the FlowEditor tutorial helper (in FlowEditor/tutorial/helpers/dom.ts) uses a configurable 50ms interval with timeout support. Both tutorials coexist in the codebase. If they will continue to coexist, consider importing from the shared helper for consistency and to avoid maintaining multiple polling implementations.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts (1)

6-31: Consider extracting shared cleanup logic to reduce duplication.

All three handlers share identical cleanup logic (close menus, remove highlights, enable blocks). Extracting this into a shared helper would improve maintainability:

♻️ Suggested refactor
+const resetTutorialState = () => {
+  closeBlockMenu();
+  closeSaveControl();
+  forceSaveOpen(false);
+  removeAllHighlights();
+  enableAllBlocks();
+};
+
 export const handleTutorialCancel = (_tour?: any) => {
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
+  resetTutorialState();
   storage.set(Key.SHEPHERD_TOUR, "canceled");
 };
 
 export const handleTutorialSkip = (_tour?: any) => {
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
+  resetTutorialState();
   storage.set(Key.SHEPHERD_TOUR, "skipped");
 };
 
 export const handleTutorialComplete = () => {
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
+  resetTutorialState();
   storage.set(Key.SHEPHERD_TOUR, "completed");
 };

Also, the _tour parameter is unused but may be required by Shepherd.js callback signatures. If so, consider adding handleTutorialComplete(_tour?: any) for consistency, or add a brief comment explaining the signature requirement.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (1)

103-110: Consider adding a null check before invoking click().

While the if (fitViewButton) check exists, the cast to HTMLButtonElement happens before the null check. This is fine, but for defensive coding, you could move the cast inside:

♻️ Minor defensive improvement
 export const fitViewToScreen = () => {
-  const fitViewButton = document.querySelector(
-    TUTORIAL_SELECTORS.FIT_VIEW_BUTTON,
-  ) as HTMLButtonElement;
-  if (fitViewButton) {
+  const fitViewButton = document.querySelector(
+    TUTORIAL_SELECTORS.FIT_VIEW_BUTTON,
+  );
+  if (fitViewButton instanceof HTMLButtonElement) {
     fitViewButton.click();
   }
 };
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/blocks.ts (1)

70-73: The reliance on array order is safe in this tutorial context, but consider documenting the assumption or using a more explicit approach if this logic expands.

The function assumes calculator nodes maintain insertion order (with the second added at index [1]). While this is valid in the current tutorial workflowβ€”where blocks are added sequentially via addSecondCalculatorBlock() with defensive checksβ€”it creates implicit ordering assumptions. If tutorial steps change or this helper is reused elsewhere, this could fail silently if nodes are reordered.

Consider adding a comment documenting that this assumes insertion order, or refactor to store the second calculator's ID explicitly when created (e.g., via addSecondCalculatorBlock()).

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)

1-25: Raw SVG strings are acceptable for Shepherd.js HTML content, but add a maintenance note.

Per coding guidelines, the frontend should use Phosphor Icons from @phosphor-icons/react. However, since Shepherd.js step content uses raw HTML template strings (as seen in welcome.ts), embedding SVG strings is a reasonable workaround.

Consider adding a comment documenting:

  1. Why raw SVGs are used instead of React components (Shepherd.js limitation)
  2. The source version of these icons for future updates
πŸ“ Suggested documentation improvement
-// These are SVG Phosphor icons
+/**
+ * Raw SVG strings for Phosphor icons used in Shepherd.js tutorial steps.
+ *
+ * Note: We use raw SVG strings here instead of @phosphor-icons/react components
+ * because Shepherd.js step content requires HTML template strings, not React elements.
+ *
+ * Source: Phosphor Icons (https://phosphoricons.com/) - Regular weight, 16x16/20x20
+ * If updating icons, copy the SVG markup from the Phosphor website.
+ */
 
 export const ICONS = {
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/welcome.ts (1)

11-11: Use proper Shepherd.js Tour type instead of any for better type safety.

The tour parameter is typed as any, which loses type information. Shepherd.js v14.5.1 exports a Tour type that should be used here. The file already imports from "shepherd.js", so add the Tour type import alongside the existing StepOptions import.

-import { StepOptions } from "shepherd.js";
+import { StepOptions, Tour } from "shepherd.js";

-export const createWelcomeSteps = (tour: any): StepOptions[] => [
+export const createWelcomeSteps = (tour: Tour): StepOptions[] => [
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/save.ts (1)

11-11: Consider adding type for tour parameter.

The tour parameter is typed as any. While Shepherd.js types can be complex, you could use Shepherd.Tour for better type safety.

Proposed improvement
+import Shepherd from "shepherd.js";
 import { StepOptions } from "shepherd.js";
 // ...
-export const createSaveSteps = (tour: any): StepOptions[] => [
+export const createSaveSteps = (tour: Shepherd.Tour): StepOptions[] => [

Also applies to: 19-19, 74-74

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts (1)

69-72: Minor: Redundant bullet markers in list.

The <ul> already implies list items, and the <li> elements include explicit β€’ characters. This creates visual redundancy if CSS adds default list-style bullets.

Suggested fix
-          <ul class="text-[0.8125rem] text-zinc-500 m-0 mt-1 pl-4">
-            <li>β€’ The calculated result</li>
-            <li>β€’ Execution timestamp</li>
+          <ul class="text-[0.8125rem] text-zinc-500 m-0 mt-1 pl-4 list-disc">
+            <li>The calculated result</li>
+            <li>Execution timestamp</li>
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts (2)

170-172: Consider using a scoped reference instead of polluting window.

Storing the interval ID on window as __tutorialCheckInterval works but pollutes the global namespace. A module-scoped variable or WeakMap keyed by tour instance would be cleaner.

Alternative approach
+// Module-scoped storage for cleanup
+let checkInterval: NodeJS.Timeout | null = null;
+
 export const createConfigureCalculatorSteps = (tour: any): StepOptions[] => [
   {
     // ...
     when: {
       show: () => {
         // ...
-        const checkInterval = setInterval(() => {
+        checkInterval = setInterval(() => {
           // ...
         }, 300);
-
-        // Store interval ID for cleanup
-        (window as any).__tutorialCheckInterval = checkInterval;
       },
       hide: () => {
         removeAllHighlights();
-        if ((window as any).__tutorialCheckInterval) {
-          clearInterval((window as any).__tutorialCheckInterval);
-          delete (window as any).__tutorialCheckInterval;
+        if (checkInterval) {
+          clearInterval(checkInterval);
+          checkInterval = null;
         }
       },
     },

Also applies to: 175-178


109-120: Duplicate validation logic between polling and button action.

The same validation checks for hasA, hasB, and hasOp are duplicated in both the polling interval (Lines 109-120) and the button action (Lines 194-205). Consider extracting this into a helper function.

Proposed refactor
+// Helper to check if all required fields are filled
+const checkFieldCompletion = (node: any) => {
+  const hardcodedValues = node?.data?.hardcodedValues || {};
+  const hasA = hardcodedValues.a !== undefined && hardcodedValues.a !== null && hardcodedValues.a !== "";
+  const hasB = hardcodedValues.b !== undefined && hardcodedValues.b !== null && hardcodedValues.b !== "";
+  const hasOp = hardcodedValues.operation !== undefined && hardcodedValues.operation !== null && hardcodedValues.operation !== "";
+  return { hasA, hasB, hasOp, allComplete: hasA && hasB && hasOp };
+};

 // In the polling interval:
-          const hardcodedValues = node.data?.hardcodedValues || {};
-          const hasA = /* ... */;
-          const hasB = /* ... */;
-          const hasOp = /* ... */;
-          const allComplete = hasA && hasB && hasOp;
+          const { hasA, hasB, hasOp, allComplete } = checkFieldCompletion(node);

 // In the button action:
-          const hardcodedValues = node.data?.hardcodedValues || {};
-          const hasA = /* ... */;
-          const hasB = /* ... */;
-          const hasOp = /* ... */;
-          if (hasA && hasB && hasOp) {
+          const { allComplete } = checkFieldCompletion(node);
+          if (allComplete) {
             tour.next();
           }

Also applies to: 194-205

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/index.ts (1)

26-39: Consider using function declaration instead of arrow function for exported function.

Per coding guidelines, function declarations are preferred over arrow functions for components and handlers in frontend code. However, this is a minor stylistic point.

♻️ Suggested refactor
-export const startTutorial = async () => {
+export async function startTutorial() {
   isTutorialLoading = true;
   tutorialLoadingCallback?.(true);
   // ... rest of function
-};
+}
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/index.ts (1)

12-22: Consider adding proper typing for the tour parameter.

Using any for the tour parameter loses type safety. Consider importing and using Shepherd.Tour type.

♻️ Suggested improvement
+import Shepherd from "shepherd.js";
 import { StepOptions } from "shepherd.js";
 // ... other imports

-export const createTutorialSteps = (tour: any): StepOptions[] => [
+export function createTutorialSteps(tour: Shepherd.Tour): StepOptions[] {
+  return [
   ...createWelcomeSteps(tour),
   ...createBlockMenuSteps(tour),
   ...createBlockBasicsSteps(tour),
   ...createConfigureCalculatorSteps(tour),
   ...createSecondCalculatorSteps(tour),
   ...createConnectionSteps(tour),
   ...createSaveSteps(tour),
   ...createRunSteps(tour),
   ...createCompletionSteps(tour),
-];
+  ];
+}
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts (1)

77-80: Silent error swallowing may hide issues during tutorial execution.

The .catch(() => {}) silently ignores errors when waiting for elements. Consider logging these failures for debugging purposes, especially during development.

♻️ Suggested improvement
     beforeShowPromise: () =>
       waitForElement(TUTORIAL_SELECTORS.NODE_INPUT_HANDLE, 3000).catch(
-        () => {},
+        (err) => {
+          console.debug("Tutorial: Input handle not found, continuing...", err);
+        },
       ),
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/save.ts (1)

45-49: Inconsistent selector usage - consider using a constant from TUTORIAL_SELECTORS.

The selector '[data-tutorial-id="save-control-version-output"]' is hardcoded here while other helpers use TUTORIAL_SELECTORS constants. Consider adding this selector to the constants file for consistency and maintainability.

♻️ Suggested improvement

Add to constants.ts:

SAVE_VERSION_OUTPUT: '[data-tutorial-id="save-control-version-output"]',

Then update this file:

 export const isAgentSaved = (): boolean => {
   const versionInput = document.querySelector(
-    '[data-tutorial-id="save-control-version-output"]',
+    TUTORIAL_SELECTORS.SAVE_VERSION_OUTPUT,
   ) as HTMLInputElement;
   return !!(versionInput && versionInput.value && versionInput.value !== "-");
 };
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/connections.ts (2)

117-127: Store subscription cleanup pattern works but uses type assertion.

Storing the unsubscribe function on the step object with as any is functional but loses type safety. Consider using a WeakMap or module-level Map keyed by step ID for cleaner cleanup management.


264-267: Unnecessary Promise.resolve() wrapping.

The beforeShowPromise already calls fitViewToScreen() which is synchronous. The return Promise.resolve() is redundant since async functions already return promises.

♻️ Suggested fix
       beforeShowPromise: async () => {
         fitViewToScreen();
-        return Promise.resolve();
       },
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts (1)

140-146: Avoid using window object for storing tutorial state.

Using (window as any).__tutorialCalcInterval pollutes the global namespace and is a code smell. Consider using a module-level variable or a Map keyed by step ID instead.

♻️ Suggested improvement
+// At module level
+let calcCheckInterval: ReturnType<typeof setInterval> | null = null;

 // In show handler:
-        (window as any).__tutorialCalcInterval = checkForCalculator;
+        calcCheckInterval = checkForCalculator;

 // In hide handler:
-        if ((window as any).__tutorialCalcInterval) {
-          clearInterval((window as any).__tutorialCalcInterval);
-          delete (window as any).__tutorialCalcInterval;
+        if (calcCheckInterval) {
+          clearInterval(calcCheckInterval);
+          calcCheckInterval = null;
         }
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (1)

1-78: This barrel file pattern may conflict with frontend coding guidelines.

Based on learnings, the guideline states "No barrel files or index.ts re-exports in frontend." However, this is a self-contained feature module where the barrel provides a clean API surface. Consider whether the convenience of centralized imports outweighs the guideline in this context.

If strict adherence is required, consumers would import directly from each helper file (e.g., from "./helpers/dom", from "./helpers/blocks").

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts (6)

18-36: Mixed return types may cause issues with Shepherd.js attachTo.

The function returns either HTMLElement or string, but when returning a selector string (lines 26, 35), Shepherd.js may not find the element if it doesn't exist yet. Consider consistently returning a function for dynamic resolution or ensuring the element exists before returning.


54-70: Static analysis: innerHTML usage is safe here but consider textContent.

The static analyzer flagged innerHTML usage. While the content is hardcoded (not user input) so XSS risk is minimal, using textContent would be more defensive and align with best practices.

πŸ”§ Suggested fix using textContent
   if (reqBox && reqTitle) {
     reqBox.classList.remove("bg-amber-50", "ring-amber-200");
     reqBox.classList.add("bg-green-50", "ring-green-200");
     reqTitle.classList.remove("text-amber-600");
     reqTitle.classList.add("text-green-600");
-    reqTitle.innerHTML = "πŸŽ‰ Hurray! All values are completed!";
+    reqTitle.textContent = "πŸŽ‰ Hurray! All values are completed!";
     if (reqList) {
       reqList.classList.add("hidden");
     }
   }

72-88: Same innerHTML concern as aboveβ€”prefer textContent for consistency.

πŸ”§ Suggested fix
-    reqTitle.innerHTML = "⚠️ Required to continue:";
+    reqTitle.textContent = "⚠️ Required to continue:";

93-93: Type tour parameter instead of using any.

Using any loses type safety. Import and use Shepherd.Tour from shepherd.js for proper typing.

πŸ”§ Suggested fix
+import Shepherd from "shepherd.js";
 import { StepOptions } from "shepherd.js";
 // ...

-export const createSecondCalculatorSteps = (tour: any): StepOptions[] => [
+export const createSecondCalculatorSteps = (tour: Shepherd.Tour): StepOptions[] => [

253-259: Global window property for interval storage is fragile.

Using (window as any).__tutorialSecondCalcInterval works but pollutes the global namespace and bypasses type safety. Consider using a module-scoped variable or a WeakMap keyed by the tour instance for cleaner state management.


271-288: Continue button silently fails when secondNode is missing.

If getSecondCalculatorNode() returns undefined (line 273), the function exits silently with no user feedback. Consider logging a warning or showing a toast to help diagnose issues during the tutorial.

- Removed unnecessary comments and documentation from tutorial helper files to enhance code clarity and maintainability.
- Simplified tutorial steps by eliminating redundant comments and improving the overall structure.
- Updated tutorial steps to ensure a more concise and focused user experience during the tutorial flow.
- Enhanced the organization of helper functions related to canvas, connections, DOM manipulation, highlights, and state management.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

πŸ€– Fix all issues with AI agents
In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts:
- Around line 164-197: The step's show handler subscribes via
useNodeStore.subscribe and saves the unsubscribe to (tour.getCurrentStep() as
any)._nodeUnsubscribe but never cleans it up; add a when.hide handler that looks
up (tour.getCurrentStep() as any)._nodeUnsubscribe and, if present, calls it and
clears the reference, and also restore UI state by calling enableAllBlocks() and
forceBlockMenuOpen(false) so the subscription is removed when the user navigates
away without adding the calculator block.

In
@autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts:
- Around line 147-166: The beforeShowPromise polling in beforeShowPromise uses
checkNode with setTimeout loops and can hang forever; modify beforeShowPromise
(and the inner checkNode logic) to add a maximum wait (e.g., timeoutMs or
maxAttempts) and stop polling when that limit is reached: track elapsed time or
attempt count when calling getSecondCalculatorNode and checking the form
container, and if exceeded reject or resolve to a failure state (and clear any
pending timers) so the tutorial doesn't wait indefinitely; ensure
fitViewToScreen remains called and that any cleanup (clearing timers) happens in
both success and timeout paths.
🧹 Nitpick comments (12)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts (3)

6-19: Consider using module-level variables instead of window globals.

Storing interval IDs on (window as any) pollutes the global namespace and bypasses TypeScript's type checking. A cleaner approach is to use module-level variables:

♻️ Suggested refactor
+// Module-level interval storage
+const tutorialIntervals: Record<string, ReturnType<typeof setInterval> | undefined> = {
+  calc: undefined,
+  check: undefined,
+  secondCalc: undefined,
+};
+
+export function setTutorialInterval(
+  key: keyof typeof tutorialIntervals,
+  id: ReturnType<typeof setInterval>,
+) {
+  tutorialIntervals[key] = id;
+}
+
-const clearTutorialIntervals = () => {
-  const intervalKeys = [
-    "__tutorialCalcInterval",
-    "__tutorialCheckInterval",
-    "__tutorialSecondCalcInterval",
-  ];
-
-  intervalKeys.forEach((key) => {
-    if ((window as any)[key]) {
-      clearInterval((window as any)[key]);
-      delete (window as any)[key];
-    }
-  });
-};
+function clearTutorialIntervals() {
+  Object.keys(tutorialIntervals).forEach((key) => {
+    const k = key as keyof typeof tutorialIntervals;
+    if (tutorialIntervals[k]) {
+      clearInterval(tutorialIntervals[k]);
+      tutorialIntervals[k] = undefined;
+    }
+  });
+}

21-49: Reduce code duplication across lifecycle handlers.

The three handlers share identical cleanup logic, differing only in the storage value. Extract the common sequence into a shared helper. Based on learnings, use function declarations instead of arrow functions for handlers.

♻️ Suggested refactor
+function cleanupTutorialState() {
+  clearTutorialIntervals();
+  closeBlockMenu();
+  closeSaveControl();
+  forceSaveOpen(false);
+  removeAllHighlights();
+  enableAllBlocks();
+}
+
-export const handleTutorialCancel = (_tour?: any) => {
-  clearTutorialIntervals();
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
-  storage.set(Key.SHEPHERD_TOUR, "canceled");
-};
+export function handleTutorialCancel() {
+  cleanupTutorialState();
+  storage.set(Key.SHEPHERD_TOUR, "canceled");
+}
 
-export const handleTutorialSkip = (_tour?: any) => {
-  clearTutorialIntervals();
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
-  storage.set(Key.SHEPHERD_TOUR, "skipped");
-};
+export function handleTutorialSkip() {
+  cleanupTutorialState();
+  storage.set(Key.SHEPHERD_TOUR, "skipped");
+}
 
-export const handleTutorialComplete = () => {
-  clearTutorialIntervals();
-  closeBlockMenu();
-  closeSaveControl();
-  forceSaveOpen(false);
-  removeAllHighlights();
-  enableAllBlocks();
-  storage.set(Key.SHEPHERD_TOUR, "completed");
-};
+export function handleTutorialComplete() {
+  cleanupTutorialState();
+  storage.set(Key.SHEPHERD_TOUR, "completed");
+}

21-21: Remove the unused _tour parameter or import and properly type it as Tour from Shepherd.js.

The _tour parameter is unused in both handleTutorialCancel and handleTutorialSkip. Shepherd.js events "complete" and "cancel" don't pass any arguments to callbacks (both have () => void signatures), so the parameter serves no purpose. Either remove it entirely or, if you intend to keep it for future flexibility, properly type it as Tour from the shepherd.js package instead of any.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts (2)

63-63: Consider typing the tour parameter.

Using any for the tour parameter loses type safety. Shepherd.js provides a Tour type that can be used here.

Suggested improvement
+import Shepherd from "shepherd.js";
+import { StepOptions } from "shepherd.js";
-export const createConfigureCalculatorSteps = (tour: any): StepOptions[] => [
+export const createConfigureCalculatorSteps = (tour: Shepherd.Tour): StepOptions[] => [

96-109: Extract duplicated validation logic into a helper.

The same validation logic for hasA, hasB, and hasOp is repeated in both the polling interval (lines 96-109) and the Continue button action (lines 176-188). Consider extracting this into a helper function to reduce duplication.

Example extraction
const getNodeCompletionStatus = (node: Node | null) => {
  if (!node) return { hasA: false, hasB: false, hasOp: false, allComplete: false };
  const hardcodedValues = node.data?.hardcodedValues || {};
  const hasA = hardcodedValues.a !== undefined && hardcodedValues.a !== null && hardcodedValues.a !== "";
  const hasB = hardcodedValues.b !== undefined && hardcodedValues.b !== null && hardcodedValues.b !== "";
  const hasOp = hardcodedValues.operation !== undefined && hardcodedValues.operation !== null && hardcodedValues.operation !== "";
  return { hasA, hasB, hasOp, allComplete: hasA && hasB && hasOp };
};

Also applies to: 176-188

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (1)

57-65: Add explicit return types for clarity.

The return types for getFirstNode and getNodeById are inferred but could be explicit for better documentation.

Suggested types
-export const getFirstNode = () => {
+export const getFirstNode = (): ReturnType<typeof useNodeStore.getState>['nodes'][number] | null => {
   const nodes = useNodeStore.getState().nodes;
   return nodes.length > 0 ? nodes[0] : null;
 };

-export const getNodeById = (nodeId: string) => {
+export const getNodeById = (nodeId: string): ReturnType<typeof useNodeStore.getState>['nodes'][number] | undefined => {
   const nodes = useNodeStore.getState().nodes;
   return nodes.find((n) => n.id === nodeId);
 };
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (2)

3-22: Inconsistent timeout behavior across wait functions.

waitForElement rejects on timeout while waitForSearchResult and waitForAnyBlockCard resolve with null. This inconsistency could lead to unhandled promise rejections if callers don't use .catch(). Consider aligning the behavior or documenting the difference.

Option: Resolve with null for consistency
 export const waitForElement = (
   selector: string,
   timeout = 10000,
-): Promise<Element> => {
-  return new Promise((resolve, reject) => {
+): Promise<Element | null> => {
+  return new Promise((resolve) => {
     const startTime = Date.now();

     const checkElement = () => {
       const element = document.querySelector(selector);
       if (element) {
         resolve(element);
       } else if (Date.now() - startTime > timeout) {
-        reject(new Error(`Element ${selector} not found within ${timeout}ms`));
+        resolve(null);
       } else {
         setTimeout(checkElement, TUTORIAL_CONFIG.ELEMENT_CHECK_INTERVAL);
       }
     };
     checkElement();
   });
 };

38-42: Magic number 4 for input length threshold should be documented.

The currentValue.length >= 4 check is unclear without context. Consider adding a comment explaining this heuristic or extracting it as a named constant.

+        // Minimum characters before considering a partial match valid
+        const MIN_PARTIAL_MATCH_LENGTH = 4;
-        if (currentValue.length >= 4 || currentValue === target) {
+        if (currentValue.length >= MIN_PARTIAL_MATCH_LENGTH || currentValue === target) {
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts (2)

30-31: Silent error swallowing may hide issues during development.

The .catch(() => {}) suppresses all errors from waitForElement. Consider logging in development mode or using a named error handler for easier debugging.

     beforeShowPromise: () =>
-      waitForElement(TUTORIAL_SELECTORS.RUN_BUTTON, 3000).catch(() => {}),
+      waitForElement(TUTORIAL_SELECTORS.RUN_BUTTON, 3000).catch((err) => {
+        console.debug("Tutorial: Run button not found, continuing anyway", err);
+      }),

71-81: Nested setTimeout with waitForElement could be simplified.

The 300ms delay before waiting for the element adds complexity. If this is intentional (e.g., waiting for DOM updates after run), consider documenting the reason.

     beforeShowPromise: () =>
       new Promise((resolve) => {
+        // Wait for execution to start and output to render
         setTimeout(() => {
           waitForElement(TUTORIAL_SELECTORS.FIRST_CALCULATOR_NODE_OUTPUT, 5000)
             .then(() => {
               fitViewToScreen();
               resolve(undefined);
             })
             .catch(resolve);
         }, 300);
       }),
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts (1)

28-33: Arbitrary delay after node detection should be documented.

The 300ms delay on line 31 after waitForNodeOnCanvas is presumably for DOM stabilization or animation completion. Consider adding a comment explaining the purpose.

     beforeShowPromise: async () => {
       closeBlockMenu();
       await waitForNodeOnCanvas(5000);
+      // Allow time for node rendering and layout stabilization
       await new Promise((resolve) => setTimeout(resolve, 300));
       fitViewToScreen();
     },
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts (1)

32-79: Significant code duplication with configure-calculator.ts.

The requirements HTML template, updateToSuccessState, and updateToWarningState functions are nearly identical between this file and configure-calculator.ts. Consider extracting shared utilities.

Suggested extraction to a shared module

Create a shared helper, e.g., tutorial/helpers/requirements-ui.ts:

export const createRequirementsHtml = (id: string, requirements: Array<{id: string, label: string, example: string}>, note?: string) => `...`;
export const updateToSuccessState = (boxId: string, listId: string) => { ... };
export const updateToWarningState = (boxId: string, listId: string) => { ... };

This would reduce ~80 lines of duplication across the two files.

πŸ“œ Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between e890a41 and e4c9b99.

πŸ“’ Files selected for processing (17)
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/connections.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/save.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/index.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/save.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/welcome.ts
βœ… Files skipped from review due to trivial changes (1)
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/index.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/welcome.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/save.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/save.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/connections.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts
🧰 Additional context used
πŸ““ Path-based instructions (6)
autogpt_platform/frontend/**/*.{ts,tsx}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: Always run pnpm install before frontend development, then use pnpm dev to start development server on port 3000
For frontend code formatting and linting, always run pnpm format

If adding protected frontend routes, update frontend/lib/supabase/middleware.ts

autogpt_platform/frontend/**/*.{ts,tsx}: Use generated API hooks from @/app/api/__generated__/endpoints/ for data fetching in frontend
Use function declarations (not arrow functions) for components and handlers in frontend
Only use Phosphor Icons in frontend; never use other icon libraries
Never use src/components/__legacy__/* or deprecated BackendAPI in frontend

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
autogpt_platform/frontend/**/*.{ts,tsx,json}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

Use Node.js 21+ with pnpm package manager for frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}

πŸ“„ CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from @/app/api/generated/endpoints/ (generated via Orval from backend OpenAPI spec). Pattern: use{Method}{Version}{OperationName} (e.g., useGetV2ListLibraryAgents). Regenerate with: pnpm generate:api. Never use deprecated BackendAPI or src/lib/autogpt-server-api/*
Use function declarations for components and handlers (not arrow functions). Only arrow functions for small inline lambdas (map, filter, etc.)
Use PascalCase for components, camelCase with use prefix for hooks
No barrel files or index.ts re-exports in frontend
For frontend render errors, use component. For mutation errors, display with toast notifications. For manual exceptions, use Sentry.captureException()
Default to client components (use client). Use server components only for SEO or extreme TTFB needs. Use React Query for server state via generated hooks. Co-locate UI state in components/hooks

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
autogpt_platform/frontend/**/*.{js,ts,jsx,tsx}

πŸ“„ CodeRabbit inference engine (AGENTS.md)

Format frontend code using pnpm format

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
autogpt_platform/frontend/**

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

autogpt_platform/frontend/**: Install frontend dependencies using pnpm i instead of npm
Generate API client from OpenAPI spec using pnpm generate:api
Regenerate API client hooks using pnpm generate:api when OpenAPI spec changes

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
autogpt_platform/frontend/**/*.{ts,tsx,css}

πŸ“„ CodeRabbit inference engine (autogpt_platform/CLAUDE.md)

Use only Tailwind CSS for styling in frontend, with design tokens and Phosphor Icons

Files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
🧠 Learnings (3)
πŸ“š Learning: 2025-11-25T08:49:03.583Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/CLAUDE.md:0-0
Timestamp: 2025-11-25T08:49:03.583Z
Learning: Applies to autogpt_platform/frontend/**/*.stories.{ts,tsx} : Add Storybook stories for new frontend components and Playwright E2E tests for features

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts
  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts
πŸ“š Learning: 2025-11-25T08:48:33.246Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T08:48:33.246Z
Learning: Applies to autogpt_platform/frontend/**/*.stories.{ts,tsx} : Add or update Storybook stories for UI components (pnpm storybook). Run Playwright E2E tests with pnpm test

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts
πŸ“š Learning: 2025-11-25T08:48:33.246Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T08:48:33.246Z
Learning: Applies to autogpt_platform/frontend/src/**/*.{ts,tsx} : Use function declarations for components and handlers (not arrow functions). Only arrow functions for small inline lambdas (map, filter, etc.)

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts
🧬 Code graph analysis (8)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts (6)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts (1)
  • banner (54-67)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)
  • ICONS (3-7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (2)
  • fitViewToScreen (76-83)
  • getFirstNode (57-60)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (4)
  • fitViewToScreen (42-42)
  • getFirstNode (39-39)
  • highlightElement (16-16)
  • removeAllHighlights (17-17)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (1)
  • TUTORIAL_SELECTORS (8-114)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts (2)
  • highlightElement (25-30)
  • removeAllHighlights (32-39)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts (6)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts (1)
  • banner (54-67)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)
  • ICONS (3-7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (1)
  • TUTORIAL_SELECTORS (8-114)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (1)
  • waitForElement (3-22)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts (2)
  • highlightElement (25-30)
  • removeAllHighlights (32-39)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (1)
  • fitViewToScreen (76-83)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts (7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (1)
  • TUTORIAL_SELECTORS (8-114)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/menu.ts (1)
  • closeBlockMenu (12-15)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (2)
  • waitForNodeOnCanvas (4-30)
  • fitViewToScreen (76-83)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts (2)
  • highlightElement (25-30)
  • removeAllHighlights (32-39)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (1)
  • waitForElement (3-22)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts (1)
  • banner (54-67)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)
  • ICONS (3-7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts (6)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts (1)
  • banner (54-67)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)
  • ICONS (3-7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (3)
  • TUTORIAL_SELECTORS (8-114)
  • TUTORIAL_CONFIG (122-129)
  • BLOCK_IDS (2-6)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (9)
  • highlightElement (16-16)
  • removeAllHighlights (17-17)
  • waitForElement (2-2)
  • forceBlockMenuOpen (48-48)
  • focusElement (6-6)
  • disableOtherBlocks (14-14)
  • pulseElement (18-18)
  • enableAllBlocks (15-15)
  • highlightFirstBlockInSearch (19-19)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/menu.ts (1)
  • forceBlockMenuOpen (4-6)
autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts (1)
  • useNodeStore (77-379)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts (5)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (6)
  • getSecondCalculatorNode (30-30)
  • addSecondCalculatorBlock (28-28)
  • waitForNodesCount (37-37)
  • fitViewToScreen (42-42)
  • highlightElement (16-16)
  • removeAllHighlights (17-17)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/blocks.ts (2)
  • getSecondCalculatorNode (70-73)
  • addSecondCalculatorBlock (49-63)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/styles.ts (1)
  • banner (54-67)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/icons.ts (1)
  • ICONS (3-7)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts (2)
  • highlightElement (25-30)
  • removeAllHighlights (32-39)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (1)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (2)
  • TUTORIAL_CONFIG (122-129)
  • TUTORIAL_SELECTORS (8-114)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (3)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (7)
  • waitForNodeOnCanvas (36-36)
  • waitForNodesCount (37-37)
  • getNodesCount (38-38)
  • getFirstNode (39-39)
  • getNodeById (40-40)
  • nodeHasValues (41-41)
  • fitViewToScreen (42-42)
autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts (1)
  • useNodeStore (77-379)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/constants.ts (2)
  • TUTORIAL_SELECTORS (8-114)
  • TUTORIAL_CONFIG (122-129)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/state.ts (5)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/index.ts (6)
  • handleTutorialCancel (63-63)
  • closeBlockMenu (50-50)
  • closeSaveControl (56-56)
  • forceSaveOpen (57-57)
  • removeAllHighlights (17-17)
  • enableAllBlocks (15-15)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/menu.ts (1)
  • closeBlockMenu (12-15)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/save.ts (2)
  • closeSaveControl (8-11)
  • forceSaveOpen (13-15)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/highlights.ts (2)
  • removeAllHighlights (32-39)
  • enableAllBlocks (13-23)
autogpt_platform/frontend/src/services/storage/local-storage.ts (1)
  • storage (44-48)
πŸͺ› ast-grep (0.40.4)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts

[warning] 38-38: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: reqTitle.innerHTML = "πŸŽ‰ Hurray! All values are completed!"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 55-55: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: reqTitle.innerHTML = "⚠️ Required to continue:"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 38-38: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: reqTitle.innerHTML = "πŸŽ‰ Hurray! All values are completed!"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 55-55: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: reqTitle.innerHTML = "⚠️ Required to continue:"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts

[warning] 56-56: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: reqTitle.innerHTML = "πŸŽ‰ Hurray! All values are completed!"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 73-73: Direct modification of innerHTML or outerHTML properties detected. Modifying these properties with unsanitized user input can lead to XSS vulnerabilities. Use safe alternatives or sanitize content first.
Context: reqTitle.innerHTML = "⚠️ Required to continue:"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://owasp.org/www-community/xss-filter-evasion-cheatsheet
- https://cwe.mitre.org/data/definitions/79.html

(dom-content-modification)


[warning] 56-56: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: reqTitle.innerHTML = "πŸŽ‰ Hurray! All values are completed!"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)


[warning] 73-73: Direct HTML content assignment detected. Modifying innerHTML, outerHTML, or using document.write with unsanitized content can lead to XSS vulnerabilities. Use secure alternatives like textContent or sanitize HTML with libraries like DOMPurify.
Context: reqTitle.innerHTML = "⚠️ Required to continue:"
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/
- https://cwe.mitre.org/data/definitions/79.html

(unsafe-html-content-assignment)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: test
  • GitHub Check: chromatic
  • GitHub Check: types
  • GitHub Check: Seer Code Review
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
πŸ”‡ Additional comments (9)
autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/configure-calculator.ts (2)

29-44: Static analysis false positive β€” innerHTML assigns hardcoded strings only.

The innerHTML assignments on lines 39 and 56 use static emoji/text literals, not user input. This is safe and the XSS warning can be dismissed. Using textContent would lose the emoji rendering in some edge cases; the current approach is acceptable.


153-159: Storing interval on window is a pragmatic workaround but consider alternatives.

Using (window as any).__tutorialCheckInterval works but pollutes the global namespace. The cleanup in hide is correct. An alternative would be storing the interval ID on the step object itself via Shepherd's step metadata, but the current approach is acceptable for tutorial code.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/canvas.ts (1)

4-30: Well-structured async polling with proper timeout handling.

The waitForNodeOnCanvas function correctly handles both the store state and DOM presence checks, with proper timeout resolution. The pattern is consistent across the helper functions.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/helpers/dom.ts (1)

126-150: Good MutationObserver pattern with immediate check.

The observeElement function correctly handles the race condition by checking for the element immediately after setting up the observer. The cleanup via obs.disconnect() is proper.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/run.ts (1)

12-96: Run steps implementation looks correct.

The two-step flow for running and viewing output is well-structured with appropriate highlighting, element waiting, and cleanup. The lifecycle hooks are properly implemented.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-basics.ts (1)

14-113: Well-structured three-step block basics tutorial.

The progression from focusing the new block to explaining input and output handles is logical and educational. The use of the banner helper for the drag tip (line 91) enhances the instructional value.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/second-calculator.ts (1)

47-62: Static analysis false positive β€” innerHTML uses hardcoded strings.

Same as in configure-calculator.ts, the innerHTML assignments use static text literals, not user input. The XSS warning can be safely dismissed.

autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/tutorial/steps/block-menu.ts (2)

80-139: Good interval cleanup pattern in search-calculator step.

The search-calculator step correctly stores the interval ID and cleans it up in the hide handler (lines 130-136). This pattern should be applied consistently to the select-calculator step's subscription.


18-45: Clean implementation of the open-block-menu step.

The advanceOn click handler combined with highlighting creates a clear user flow. The cleanup in hide is properly implemented.

@github-actions github-actions bot added the conflicts Automatically applied to PRs with merge conflicts label Jan 14, 2026
@github-actions
Copy link
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

@github-actions github-actions bot removed the conflicts Automatically applied to PRs with merge conflicts label Jan 15, 2026
@github-actions
Copy link
Contributor

Conflicts have been resolved! πŸŽ‰ A maintainer will review the pull request shortly.

Copy link
Contributor

@0ubbe 0ubbe left a comment

Choose a reason for hiding this comment

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

βœ…

@github-project-automation github-project-automation bot moved this from πŸ†• Needs initial review to πŸ‘πŸΌ Mergeable in AutoGPT development kanban Jan 15, 2026
@Abhi1992002 Abhi1992002 enabled auto-merge January 15, 2026 07:47
@Abhi1992002 Abhi1992002 added this pull request to the merge queue Jan 15, 2026
Merged via the queue into dev with commit 631f1bd Jan 15, 2026
23 of 24 checks passed
@Abhi1992002 Abhi1992002 deleted the abhimanyuyadav/open-2840-add-tutorial-in-new-builder branch January 15, 2026 08:31
@github-project-automation github-project-automation bot moved this from πŸ‘πŸΌ Mergeable to βœ… Done in AutoGPT development kanban Jan 15, 2026
@github-project-automation github-project-automation bot moved this to Done in Frontend Jan 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: βœ… Done
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants