Skip to content

Conversation

@Sg312
Copy link
Contributor

@Sg312 Sg312 commented Jan 25, 2026

Summary

Brief description of what this PR does and why.

Fixes #(issue)

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Other: ___________

Testing

How has this been tested? What should reviewers focus on?

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

@vercel
Copy link

vercel bot commented Jan 25, 2026

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 25, 2026 9:27pm

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 25, 2026

Greptile Overview

Greptile Summary

This PR adds pre-validation for credential and API key inputs in workflow edit operations. The changes introduce a new preValidateCredentialInputs function that:

  • Validates oauth-input (credential) IDs belong to the user before applying operations
  • Filters out apiKey inputs for hosted models when isHosted is true
  • Skips oauth-input validation in the post-validation phase to avoid duplicate checks

Key changes:

  • Added preValidateCredentialInputs function that validates credentials and filters API keys before operations are applied
  • Modified validateWorkflowSelectorIds to skip oauth-input validation (now handled in pre-validation)
  • Integrated pre-validation into the main edit workflow flow, merging errors from both phases

Potential concerns:

  • Uses JSON.parse(JSON.stringify()) for deep cloning which has limitations
  • Adds error messages when filtering API keys from hosted models (may create unnecessary noise)
  • Minor optimization: hosted model list is created even when not needed

Confidence Score: 3/5

  • This PR is moderately safe to merge with minor optimization opportunities
  • The core logic is sound - validating credentials before applying operations is a good security practice. However, there are some code quality issues: using JSON.parse(JSON.stringify()) for cloning (which could fail on edge cases), adding error messages for filtered API keys (which may be unexpected by users), and minor inefficiencies like creating hosted model lists even when not in hosted mode. These are style/optimization issues rather than critical bugs.
  • No files require special attention - the changes are localized and follow existing patterns

Important Files Changed

Filename Overview
apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts Added credential validation and API key filtering for hosted models with potential missing workspaceId context

Sequence Diagram

sequenceDiagram
    participant Client
    participant EditWorkflowTool
    participant PreValidate as preValidateCredentialInputs
    participant Validator as validateSelectorIds
    participant DB as Database
    participant ApplyOps as applyOperationsToWorkflowState
    participant PostValidate as validateWorkflowSelectorIds

    Client->>EditWorkflowTool: editWorkflow(operations, workflowId)
    
    EditWorkflowTool->>PreValidate: preValidateCredentialInputs(operations, {userId})
    
    PreValidate->>PreValidate: Collect oauth-input credentials
    PreValidate->>PreValidate: Collect apiKey inputs for hosted models
    
    alt Has credentials to validate
        PreValidate->>Validator: validateSelectorIds('oauth-input', credentialIds, context)
        Validator->>DB: Query accounts by userId
        DB-->>Validator: Return valid credential IDs
        Validator-->>PreValidate: {valid, invalid, warning}
        PreValidate->>PreValidate: Remove invalid credentials from operations
        PreValidate->>PreValidate: Add validation errors
    end
    
    alt Has hosted model apiKeys (isHosted=true)
        PreValidate->>PreValidate: Delete apiKey from operations
        PreValidate->>PreValidate: Add error messages
    end
    
    PreValidate-->>EditWorkflowTool: {filteredOperations, errors}
    
    EditWorkflowTool->>ApplyOps: applyOperationsToWorkflowState(state, filteredOperations)
    ApplyOps-->>EditWorkflowTool: {modifiedState, validationErrors, skippedItems}
    
    EditWorkflowTool->>EditWorkflowTool: Merge credential errors with validation errors
    
    EditWorkflowTool->>DB: Get workspaceId
    DB-->>EditWorkflowTool: workspaceId
    
    EditWorkflowTool->>PostValidate: validateWorkflowSelectorIds(modifiedState, {userId, workspaceId})
    Note over PostValidate: Skips oauth-input (already validated)
    PostValidate->>Validator: Validate other selector types
    Validator->>DB: Query selector resources
    DB-->>Validator: Return valid IDs
    Validator-->>PostValidate: Validation results
    PostValidate-->>EditWorkflowTool: Additional errors
    
    EditWorkflowTool->>EditWorkflowTool: Merge all validation errors
    EditWorkflowTool-->>Client: {modifiedState, validationErrors, skippedItems}
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

})

const allCredentialIds = credentialInputs.map((c) => c.value)
const validationResult = await validateSelectorIds('oauth-input', allCredentialIds, context)
Copy link
Contributor

Choose a reason for hiding this comment

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

context only contains userId but validateSelectorIds expects { userId: string; workspaceId?: string } - workspaceId is missing

Suggested change
const validationResult = await validateSelectorIds('oauth-input', allCredentialIds, context)
const validationResult = await validateSelectorIds('oauth-input', allCredentialIds, { userId: context.userId })
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts
Line: 2695:2695

Comment:
`context` only contains `userId` but `validateSelectorIds` expects `{ userId: string; workspaceId?: string }` - workspaceId is missing

```suggestion
    const validationResult = await validateSelectorIds('oauth-input', allCredentialIds, { userId: context.userId })
```

How can I resolve this? If you propose a fix, please make it concise.

}

// Deep clone operations so we can modify them
const filteredOperations = JSON.parse(JSON.stringify(operations)) as EditWorkflowOperation[]
Copy link
Contributor

Choose a reason for hiding this comment

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

JSON.parse(JSON.stringify()) will fail on operations containing functions, undefined values, or circular references - consider using a proper deep clone library like structuredClone() or lodash's cloneDeep

Suggested change
const filteredOperations = JSON.parse(JSON.stringify(operations)) as EditWorkflowOperation[]
const filteredOperations = structuredClone(operations)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts
Line: 2661:2661

Comment:
`JSON.parse(JSON.stringify())` will fail on operations containing functions, undefined values, or circular references - consider using a proper deep clone library like `structuredClone()` or lodash's `cloneDeep`

```suggestion
  const filteredOperations = structuredClone(operations)
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 2677 to 2683
errors.push({
blockId: apiKeyInput.blockId,
blockType: apiKeyInput.blockType,
field: 'apiKey',
value: '[redacted]',
error: `API key not allowed for hosted model "${apiKeyInput.model}" - platform provides the key`,
})
Copy link
Contributor

Choose a reason for hiding this comment

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

adding an error for filtering out apiKey creates noise - users expect apiKeys to be ignored on hosted models, not receive errors about them

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts
Line: 2677:2683

Comment:
adding an error for filtering out `apiKey` creates noise - users expect apiKeys to be ignored on hosted models, not receive errors about them

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 2612 to 2613
const hostedModels = isHosted ? getHostedModels() : []
const hostedModelsLower = new Set(hostedModels.map((m) => m.toLowerCase()))
Copy link
Contributor

Choose a reason for hiding this comment

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

calling getHostedModels() when isHosted is false returns an empty array, making the subsequent hostedModelsLower Set and all hosted model checks unnecessary - move this inside the if (isHosted) check on line 2638

Suggested change
const hostedModels = isHosted ? getHostedModels() : []
const hostedModelsLower = new Set(hostedModels.map((m) => m.toLowerCase()))
const hostedModels = isHosted ? getHostedModels() : []
const hostedModelsLower = isHosted ? new Set(hostedModels.map((m) => m.toLowerCase())) : new Set()

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/copilot/tools/server/workflow/edit-workflow.ts
Line: 2612:2613

Comment:
calling `getHostedModels()` when `isHosted` is false returns an empty array, making the subsequent `hostedModelsLower` Set and all hosted model checks unnecessary - move this inside the `if (isHosted)` check on line 2638

```suggestion
  const hostedModels = isHosted ? getHostedModels() : []
  const hostedModelsLower = isHosted ? new Set(hostedModels.map((m) => m.toLowerCase())) : new Set()
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants