Skip to content

Ai sidekick agent granular workflow tools#10113

Open
LetItRock wants to merge 2 commits intonextfrom
ai-sidekick-agent-granular-workflow-tools
Open

Ai sidekick agent granular workflow tools#10113
LetItRock wants to merge 2 commits intonextfrom
ai-sidekick-agent-granular-workflow-tools

Conversation

@LetItRock
Copy link
Contributor

What changed? Why was the change needed?

Novu Sidekick:

  • refactored code and moved workflow update actions to the agent tools
  • added new tools: move step, add step in between, update conditions

Screenshots

@LetItRock LetItRock self-assigned this Feb 26, 2026
@netlify
Copy link

netlify bot commented Feb 26, 2026

Deploy preview added

Name Link
🔨 Latest commit 134da3a
🔍 Latest deploy log https://app.netlify.com/projects/dashboard-v2-novu-staging/deploys/69a0622784d09d00081e88fc
😎 Deploy Preview https://deploy-preview-10113.dashboard-v2.novu-staging.co
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Contributor

Hey there and thank you for opening this pull request! 👋

We require pull request titles to follow specific formatting rules and it looks like your proposed title needs to be adjusted.

Your PR title is: Ai sidekick agent granular workflow tools

Requirements:

  1. Follow the Conventional Commits specification
  2. As a team member, include Linear ticket ID at the end: fixes TICKET-ID or include it in your branch name

Expected format: feat(scope): Add fancy new feature fixes NOV-123

Details:
No release type found in pull request title "Ai sidekick agent granular workflow tools". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • refactor: A code change that neither fixes a bug nor adds a feature
  • perf: A code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
  • ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
    PR title must end with 'fixes TICKET-ID' (e.g., 'fixes NOV-123') or include ticket ID in branch name

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Walkthrough

This pull request extends AI-powered workflow generation with new step manipulation capabilities. It introduces three new workflow tools: ADD_STEP_IN_BETWEEN, UPDATE_STEP_CONDITIONS, and MOVE_STEP. The changes refactor prompt and schema handling to use explicit variable schemas instead of deriving them from draft workflow state. Supporting infrastructure is updated, including condition schema restructuring, new input/output schemas for step operations, and modular helper functions. Environment tag integration is added to the workflow generation flow. Dashboard components are updated to render the new tool types in the chat interface. The AI provider in workflow editing is made optional based on feature flags.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% 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 accurately captures the main objective of this PR - refactoring the AI sidekick agent to use granular workflow tools for step management operations.
Description check ✅ Passed The description clearly relates to the changeset, explaining the refactoring of workflow update actions and listing the new tools (move step, add step in between, update conditions) that were added.

✏️ Tip: You can configure your own custom pre-merge checks in the 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.

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: 1

🧹 Nitpick comments (7)
apps/dashboard/src/components/workflow-editor/workflow-tabs.tsx (1)

468-471: Align AiChatProvider mounting with AI UI visibility.

At Line 489, the provider mounts when the feature flag is on, but AI consumers are still hidden outside dev (Lines 468 and 471). Consider gating provider mount with the same condition to avoid unnecessary chat initialization/fetching in non-dev contexts.

Suggested refactor
-  return isAiWorkflowGenerationEnabled ? <AiChatProvider config={aiChatConfig}>{content}</AiChatProvider> : content;
+  const isAiSidekickEnabled = isAiWorkflowGenerationEnabled && isDevEnvironment;
+
+  return isAiSidekickEnabled ? <AiChatProvider config={aiChatConfig}>{content}</AiChatProvider> : content;

Also applies to: 489-489

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/workflow-editor/workflow-tabs.tsx` around lines
468 - 471, The AiChatProvider is mounted unconditionally while AI UI components
are only rendered when isAiWorkflowGenerationEnabled && isDevEnvironment; update
the mount so AiChatProvider is only instantiated under the same condition to
avoid unnecessary chat initialization and fetching — wrap or gate AiChatProvider
with the same boolean check used for AiSidekickPanel and WorkflowCanvasToast
(referencing AiChatProvider, AiSidekickPanel, WorkflowCanvasToast,
isAiWorkflowGenerationEnabled, isDevEnvironment) so provider and consumers
mount/unmount together.
apps/api/src/app/ai/utils/variable-schema.utils.ts (1)

330-344: Consider the implications of empty stepId values.

When stepId is undefined, it defaults to an empty string. This could cause issues if the step is later used in buildPreviousStepsSchema (line 51-72), where stepId becomes an object property key. Multiple steps without IDs would collide on the empty string key.

If steps without IDs shouldn't contribute to previousSteps schema, consider filtering them out or generating a temporary ID:

♻️ Suggested approach
 export function toGeneratedSteps(
   steps: Array<{
     stepId?: string;
     name: string;
     type: StepTypeEnum;
     controlValues?: Record<string, unknown> | null;
   }>
 ): GeneratedStep[] {
-  return steps.map((s) => ({
-    stepId: s.stepId ?? '',
+  return steps.map((s, index) => ({
+    stepId: s.stepId ?? `step-${index}`,
     name: s.name,
     type: s.type,
     controlValues: (s.controlValues ?? {}) as Record<string, unknown>,
   }));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/utils/variable-schema.utils.ts` around lines 330 - 344,
toGeneratedSteps currently maps undefined stepId to an empty string which will
collide when used as object keys in buildPreviousStepsSchema; update
toGeneratedSteps to either (A) filter out steps with no stepId before mapping so
they don't become keys in buildPreviousStepsSchema, or (B) assign a stable
unique temporary id for missing stepId (e.g., based on index or a generated
UUID) instead of an empty string; adjust any consumers if you choose B to be
aware of temp ids. Ensure you modify the toGeneratedSteps implementation (and,
if needed, update buildPreviousStepsSchema expectations) rather than leaving
empty string defaults.
apps/api/src/app/ai/tools/workflow-generation.tools.ts (5)

167-173: Consider extracting repeated step mapping pattern.

The same step-to-minimal-object transformation is repeated in updateWorkflow, removeWorkflowStep, and moveWorkflowStep. Extracting a helper function would reduce duplication and ensure consistency.

♻️ Example helper extraction
const toMinimalSteps = (steps: WorkflowResponseDto['steps']) =>
  steps.map((s) => ({
    _id: s._id,
    stepId: s.stepId,
    name: s.name,
    type: s.type,
    controlValues: s.controlValues ?? {},
  }));

Also applies to: 367-375, 507-513

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts` around lines 167 -
173, Extract the repeated step-mapping into a single helper (e.g.,
toMinimalSteps) and replace the inline mapping in updateWorkflow,
removeWorkflowStep, and moveWorkflowStep with calls to that helper; the helper
should accept WorkflowResponseDto['steps'] (or the same steps type used across
those functions) and return the minimal step objects with _id, stepId, name,
type, and controlValues defaulted to {} to ensure consistency and remove
duplication across the mappings currently at lines around the mapping in each
function.

470-533: Missing error handling and silent index clamping in moveWorkflowStep.

Two observations:

  1. This function lacks try-catch around the upsert call, unlike other step manipulation helpers.
  2. Line 501 silently clamps toIndex without logging. If the caller provides an out-of-bounds index, this could mask bugs or produce unexpected behavior.

Consider adding error handling and a warning log when the index is clamped.

♻️ Proposed refactor
   const clampedIndex = Math.max(0, Math.min(toIndex, latestWorkflow.steps.length - 1));
+  if (clampedIndex !== toIndex) {
+    logger.warn({ stepId, toIndex, clampedIndex }, 'Step move index clamped to valid range');
+  }

   const steps = [...latestWorkflow.steps];
   const [step] = steps.splice(fromIndex, 1);
   steps.splice(clampedIndex, 0, step);

   const reorderedSteps = steps.map((s) => ({
     _id: s._id,
     stepId: s.stepId,
     name: s.name,
     type: s.type,
     controlValues: s.controlValues ?? {},
   }));

+  try {
     const persistedWorkflow = await upsertWorkflowUseCase.execute(
       // ... existing code
     );
     draftState.setWorkflow(persistedWorkflow);
     // ... logging

     return persistedWorkflow;
+  } catch (error) {
+    logger.error({ error }, 'Failed to move workflow step');
+
+    throw error;
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts` around lines 470 -
533, The moveWorkflowStep function needs explicit error handling and visibility
when requested index is out of bounds: wrap the upsertWorkflowUseCase.execute
(and subsequent draftState.setWorkflow and logger.info) in a try-catch, log an
error via logger.error including workflowId/_id, stepId and the caught error,
and rethrow (or throw a new Error with context) so callers can handle failures;
additionally, detect when clampedIndex !== toIndex and emit a logger.warn
(including stepId, requested toIndex, clampedIndex and workflowId) before
mutating steps so out-of-range requests are visible; update references:
moveWorkflowStep, upsertWorkflowUseCase.execute, draftState.setWorkflow, and
logger.info to reflect this change.

740-796: Code duplication between addStepTool and addStepInBetweenTool.

Lines 741-772 are nearly identical to lines 684-715 in addStepTool. The only difference is the insertion method (addWorkflowStep vs addWorkflowStepInBetween). Consider extracting the common step generation logic to reduce duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts` around lines 740 -
796, Extract the duplicated step-generation logic from addStepTool and
addStepInBetweenTool into a shared async helper (e.g., generateAndPrepareStep)
that accepts parameters: input, draftState, llmService,
stepTypeToSchemaAndPrompt, and any context needed; inside it perform the
stepConfig lookup (stepTypeToSchemaAndPrompt[input.stepType]),
buildFullVariableSchema(using toGeneratedSteps), call llmService.generateObject
with buildStepSystemPrompt and buildStepUserPrompt, apply the StepTypeEnum.EMAIL
block-editor JSON conversion, and apply the input.skip controlValues merge; then
replace the duplicated blocks in addStepTool and addStepInBetweenTool to call
this helper and pass the resulting newStep into addWorkflowStep or
addWorkflowStepInBetween respectively, ensuring runtime.writer and logger calls
remain in the original tools.

343-396: Missing error handling in removeWorkflowStep.

Unlike addWorkflowStep, updateWorkflowStep, and addWorkflowStepInBetween, this function lacks a try-catch block around the upsertWorkflowUseCase.execute call. For consistency and better error diagnostics, consider wrapping the upsert in try-catch and logging failures.

♻️ Proposed refactor
   const { payloadSchema, validatePayload } = computePayloadSchemaFromSteps(steps);

+  try {
     const persistedWorkflow = await upsertWorkflowUseCase.execute(
       UpsertWorkflowCommand.create({
         workflowDto: {
           ...latestWorkflow,
           steps,
           validatePayload,
           payloadSchema: validatePayload ? payloadSchema : undefined,
         },
         user: command.user,
         workflowIdOrInternalId: workflowId,
       })
     );
     draftState.setWorkflow(persistedWorkflow);

     logger.info({ _id: persistedWorkflow._id, slug: persistedWorkflow.slug }, `AI Workflow step removed: ${stepId}`);

     return persistedWorkflow;
+  } catch (error) {
+    logger.error({ error }, 'Failed to remove workflow step');
+
+    throw error;
+  }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts` around lines 343 -
396, Wrap the upsert step in removeWorkflowStep with a try-catch around the call
to upsertWorkflowUseCase.execute (and subsequent
draftState.setWorkflow/logger.info) to mirror other functions; in the catch,
call logger.error and include identifying context (workflowId, stepId and any
persistedWorkflow._id/slug if available) and the caught error details, then
rethrow the error so callers still receive the failure. Ensure you reference
removeWorkflowStep, upsertWorkflowUseCase.execute, draftState.setWorkflow and
logger in the change.

70-76: Consider using interface instead of type.

As per coding guidelines for backend code, prefer interface over type for object shapes.

♻️ Proposed refactor
-export type WorkflowMetadata = {
+export interface WorkflowMetadata {
   description?: string | null;
   tags?: string[] | null;
   name: string;
   severity: SeverityLevelEnum;
   critical: boolean;
-};
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts` around lines 70 - 76,
Replace the exported type alias WorkflowMetadata with an exported interface
named WorkflowMetadata to follow backend coding guidelines; update the
declaration for WorkflowMetadata (keeping properties description?: string |
null; tags?: string[] | null; name: string; severity: SeverityLevelEnum;
critical: boolean;) as an interface, leaving all types and optional/null unions
intact and ensuring any imports or references to SeverityLevelEnum remain
unchanged so consumers of WorkflowMetadata continue to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx`:
- Around line 353-375: The component is missing UI handling for
AiWorkflowToolsEnum.MOVE_STEP and AiWorkflowToolsEnum.REMOVE_STEP; add blocks
analogous to the existing ones (e.g., the ADD_STEP_IN_BETWEEN,
EDIT_STEP_CONTENT, UPDATE_STEP_CONDITIONS blocks) that check tool.toolName ===
AiWorkflowToolsEnum.MOVE_STEP and === AiWorkflowToolsEnum.REMOVE_STEP, use
corresponding parts arrays (e.g., moveStepParts and removeStepParts) filtered by
p.state === 'output-available' && p.output, push entries into toolItems like {
type: 'moveStep', steps: stepsSoFar } and { type: 'removeStep', steps:
stepsSoFar }, set flags (e.g., moveStepAdded, removeStepAdded) to avoid
duplicates, and update the toolItems union/type definition to include 'moveStep'
and 'removeStep' variants so the UI can render them.

---

Nitpick comments:
In `@apps/api/src/app/ai/tools/workflow-generation.tools.ts`:
- Around line 167-173: Extract the repeated step-mapping into a single helper
(e.g., toMinimalSteps) and replace the inline mapping in updateWorkflow,
removeWorkflowStep, and moveWorkflowStep with calls to that helper; the helper
should accept WorkflowResponseDto['steps'] (or the same steps type used across
those functions) and return the minimal step objects with _id, stepId, name,
type, and controlValues defaulted to {} to ensure consistency and remove
duplication across the mappings currently at lines around the mapping in each
function.
- Around line 470-533: The moveWorkflowStep function needs explicit error
handling and visibility when requested index is out of bounds: wrap the
upsertWorkflowUseCase.execute (and subsequent draftState.setWorkflow and
logger.info) in a try-catch, log an error via logger.error including
workflowId/_id, stepId and the caught error, and rethrow (or throw a new Error
with context) so callers can handle failures; additionally, detect when
clampedIndex !== toIndex and emit a logger.warn (including stepId, requested
toIndex, clampedIndex and workflowId) before mutating steps so out-of-range
requests are visible; update references: moveWorkflowStep,
upsertWorkflowUseCase.execute, draftState.setWorkflow, and logger.info to
reflect this change.
- Around line 740-796: Extract the duplicated step-generation logic from
addStepTool and addStepInBetweenTool into a shared async helper (e.g.,
generateAndPrepareStep) that accepts parameters: input, draftState, llmService,
stepTypeToSchemaAndPrompt, and any context needed; inside it perform the
stepConfig lookup (stepTypeToSchemaAndPrompt[input.stepType]),
buildFullVariableSchema(using toGeneratedSteps), call llmService.generateObject
with buildStepSystemPrompt and buildStepUserPrompt, apply the StepTypeEnum.EMAIL
block-editor JSON conversion, and apply the input.skip controlValues merge; then
replace the duplicated blocks in addStepTool and addStepInBetweenTool to call
this helper and pass the resulting newStep into addWorkflowStep or
addWorkflowStepInBetween respectively, ensuring runtime.writer and logger calls
remain in the original tools.
- Around line 343-396: Wrap the upsert step in removeWorkflowStep with a
try-catch around the call to upsertWorkflowUseCase.execute (and subsequent
draftState.setWorkflow/logger.info) to mirror other functions; in the catch,
call logger.error and include identifying context (workflowId, stepId and any
persistedWorkflow._id/slug if available) and the caught error details, then
rethrow the error so callers still receive the failure. Ensure you reference
removeWorkflowStep, upsertWorkflowUseCase.execute, draftState.setWorkflow and
logger in the change.
- Around line 70-76: Replace the exported type alias WorkflowMetadata with an
exported interface named WorkflowMetadata to follow backend coding guidelines;
update the declaration for WorkflowMetadata (keeping properties description?:
string | null; tags?: string[] | null; name: string; severity:
SeverityLevelEnum; critical: boolean;) as an interface, leaving all types and
optional/null unions intact and ensuring any imports or references to
SeverityLevelEnum remain unchanged so consumers of WorkflowMetadata continue to
work.

In `@apps/api/src/app/ai/utils/variable-schema.utils.ts`:
- Around line 330-344: toGeneratedSteps currently maps undefined stepId to an
empty string which will collide when used as object keys in
buildPreviousStepsSchema; update toGeneratedSteps to either (A) filter out steps
with no stepId before mapping so they don't become keys in
buildPreviousStepsSchema, or (B) assign a stable unique temporary id for missing
stepId (e.g., based on index or a generated UUID) instead of an empty string;
adjust any consumers if you choose B to be aware of temp ids. Ensure you modify
the toGeneratedSteps implementation (and, if needed, update
buildPreviousStepsSchema expectations) rather than leaving empty string
defaults.

In `@apps/dashboard/src/components/workflow-editor/workflow-tabs.tsx`:
- Around line 468-471: The AiChatProvider is mounted unconditionally while AI UI
components are only rendered when isAiWorkflowGenerationEnabled &&
isDevEnvironment; update the mount so AiChatProvider is only instantiated under
the same condition to avoid unnecessary chat initialization and fetching — wrap
or gate AiChatProvider with the same boolean check used for AiSidekickPanel and
WorkflowCanvasToast (referencing AiChatProvider, AiSidekickPanel,
WorkflowCanvasToast, isAiWorkflowGenerationEnabled, isDevEnvironment) so
provider and consumers mount/unmount together.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1afd2a2 and 134da3a.

📒 Files selected for processing (11)
  • apps/api/src/app/ai/ai.module.ts
  • apps/api/src/app/ai/prompts/step.prompt.ts
  • apps/api/src/app/ai/prompts/workflow.prompt.ts
  • apps/api/src/app/ai/schemas/steps-control.schema.ts
  • apps/api/src/app/ai/tools/workflow-generation.tools.ts
  • apps/api/src/app/ai/usecases/stream-workflow-generation/stream-workflow-generation.usecase.ts
  • apps/api/src/app/ai/utils/variable-schema.utils.ts
  • apps/dashboard/src/components/ai-sidekick/chat-body.tsx
  • apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx
  • apps/dashboard/src/components/workflow-editor/workflow-tabs.tsx
  • packages/shared/src/types/ai.ts

Comment on lines +353 to +375
if (tool.toolName === AiWorkflowToolsEnum.ADD_STEP_IN_BETWEEN && !addStepInBetweenAdded) {
const stepsSoFar = addStepInBetweenParts.filter((p) => p.state === 'output-available' && p.output);
if (stepsSoFar.length > 0) {
toolItems.push({ type: 'addStepInBetween', steps: stepsSoFar });
addStepInBetweenAdded = true;
}
}

if (tool.toolName === AiWorkflowToolsEnum.EDIT_STEP_CONTENT && !editStepContentAdded) {
const stepsSoFar = editStepParts.filter((p) => p.state === 'output-available' && p.output);
if (stepsSoFar.length > 0) {
toolItems.push({ type: 'editStep', steps: stepsSoFar });
editStepContentAdded = true;
}
}

if (tool.toolName === AiWorkflowToolsEnum.UPDATE_STEP_CONDITIONS && !updateStepConditionsAdded) {
const stepsSoFar = updateStepConditionsParts.filter((p) => p.state === 'output-available' && p.output);
if (stepsSoFar.length > 0) {
toolItems.push({ type: 'updateStepConditions', steps: stepsSoFar });
updateStepConditionsAdded = true;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg "MOVE_STEP" --type ts -C 2

Repository: novuhq/novu

Length of output: 2515


🏁 Script executed:

# Also search for the enum definition to understand the context
rg "AiWorkflowToolsEnum" --type ts -A 10 | head -50

Repository: novuhq/novu

Length of output: 4446


🏁 Script executed:

# Check if there's any MOVE_STEP handling elsewhere in the chat-chain-of-thought file
cat -n apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx | grep -i "move"

Repository: novuhq/novu

Length of output: 37


🏁 Script executed:

# Search for REMOVE_STEP in the chat-chain-of-thought component
rg "REMOVE_STEP|removeStep" apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx -C 3

Repository: novuhq/novu

Length of output: 37


🏁 Script executed:

# Get a broader view of all tool type handling in the component
rg "tool\.toolName|type:" apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx | head -30

Repository: novuhq/novu

Length of output: 1453


🏁 Script executed:

# Check what tool types are handled in toolItems
rg "toolItems\.push|type:" apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx

Repository: novuhq/novu

Length of output: 1004


Add UI rendering for MOVE_STEP and REMOVE_STEP tools.

Both MOVE_STEP and REMOVE_STEP are defined in AiWorkflowToolsEnum and have backend implementations, but they lack corresponding UI handling in this component. The toolItems union type only includes handlers for workflowInit, addStep, addStepInBetween, editStep, and updateStepConditions. To maintain consistency with other workflow tools and provide visibility into AI-driven step operations, these tools should have similar UI rendering blocks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/ai-sidekick/chat-chain-of-thought.tsx` around
lines 353 - 375, The component is missing UI handling for
AiWorkflowToolsEnum.MOVE_STEP and AiWorkflowToolsEnum.REMOVE_STEP; add blocks
analogous to the existing ones (e.g., the ADD_STEP_IN_BETWEEN,
EDIT_STEP_CONTENT, UPDATE_STEP_CONDITIONS blocks) that check tool.toolName ===
AiWorkflowToolsEnum.MOVE_STEP and === AiWorkflowToolsEnum.REMOVE_STEP, use
corresponding parts arrays (e.g., moveStepParts and removeStepParts) filtered by
p.state === 'output-available' && p.output, push entries into toolItems like {
type: 'moveStep', steps: stepsSoFar } and { type: 'removeStep', steps:
stepsSoFar }, set flags (e.g., moveStepAdded, removeStepAdded) to avoid
duplicates, and update the toolItems union/type definition to include 'moveStep'
and 'removeStep' variants so the UI can render them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant