Skip to content

chore(release): staging to production - 2026.02.06 - #944

Merged
maxtechera merged 7 commits into
productionfrom
staging
Feb 6, 2026
Merged

chore(release): staging to production - 2026.02.06#944
maxtechera merged 7 commits into
productionfrom
staging

Conversation

@github-actions

@github-actions github-actions Bot commented Feb 6, 2026

Copy link
Copy Markdown

🚀 Release: Staging to Production

Release Date: 2026-02-06

Changes in this release

  • fix(AGENT-76): add credential modal to agentcanvas pages (71b0186)
  • fix(AGENT-76): sync canvas after credential modal saves (9c42e9c)
  • fix(AGENT-76): address PR review feedback for credential refresh (bbf926e)
  • fix: reference correct _chats prop in ChatDrawer (27843dc)

This PR is automatically created/updated when commits are pushed to staging.
Merging this PR will trigger the release workflow to create a new GitHub release.

maxtechera and others added 2 commits February 6, 2026 13:16
The destructured prop was named `_chats` but referenced as `chats` in
the useSWRInfinite fallbackData option, causing a ReferenceError.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ce-chatdrawer

fix: reference correct _chats prop in ChatDrawer
@vercel

vercel Bot commented Feb 6, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
answerai-docs Building Building Preview Feb 6, 2026 4:30pm
the-answerai Building Building Preview Feb 6, 2026 4:30pm

Request Review

maxtechera and others added 2 commits February 6, 2026 13:51
- Fix mutation ordering in ReactFlowContext: update FLOWISE_CREDENTIAL_ID
  before spreading into updatedData to avoid confusing reference semantics
- Fix hasChanges check to detect input and credential changes, not just
  inputParams (credential-only changes were silently dropped)
- Refactor DocStoreInputHandler to use centralized onNodeDataChange for
  credential updates instead of direct state mutation
- Remove unused credentialSetInNode variable from E2E test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…iew-feedback

fix(AGENT-76): address PR review feedback for credential refresh
@claude

claude Bot commented Feb 6, 2026

Copy link
Copy Markdown

PR Review: Staging to Production Release (2026.02.06)

Overview

This release includes two bug fixes addressing credential refresh behavior and a prop naming issue in the chat drawer. Overall, the changes are well-structured and demonstrate careful attention to state management patterns.


✅ Strengths

1. Improved Credential State Management (ReactFlowContext.jsx)

The fix correctly addresses the mutation ordering issue:

  • Moving FLOWISE_CREDENTIAL_ID assignment before spreading updatedInputs into updatedData ensures proper reference semantics
  • Using the spread operator for conditional credential assignment (...(inputParam.type === 'credential' && { credential: newValue })) is a clean pattern

2. Enhanced Change Detection (ReactFlowContext.jsx:94-99)

The expanded hasChanges check now properly detects:

  • inputParams changes
  • inputs changes
  • credential changes

This fixes the critical bug where credential-only changes were silently dropped.

3. Centralized State Management (DocStoreInputHandler.jsx)

Refactoring to use onNodeDataChange instead of direct state mutation is the correct architectural approach. This ensures:

  • Consistent ReactFlow state updates
  • Proper change detection triggers
  • Reduced risk of state synchronization bugs

4. Test Cleanup (canvas-credential-refresh.spec.ts)

Removing the fragile internal state check (window.__REACT_FLOW_NODES) is appropriate. The UI-based verification is more robust and tests the actual user-facing behavior.

5. Clear Prop Naming (ChatDrawer.tsx)

The fix correctly references the destructured prop name _chats instead of the incorrect chats.


⚠️ Issues & Concerns

1. Potential Race Condition (ReactFlowContext.jsx:73-75)

// Handle credential inputs: update both credential field and FLOWISE_CREDENTIAL_ID
if (inputParam.type === 'credential') {
    updatedInputs[FLOWISE_CREDENTIAL_ID] = newValue
}

Issue: This mutation happens after updatedInputs is already created as a shallow copy but before it's spread into updatedData. While this works, the timing is subtle and could be confusing.

Recommendation: Add a comment explaining why this happens before the spread:

// Update FLOWISE_CREDENTIAL_ID before spreading into updatedData
// to ensure the credential ID is included in the final inputs object
if (inputParam.type === 'credential') {
    updatedInputs[FLOWISE_CREDENTIAL_ID] = newValue
}

2. Incomplete Equality Check (ReactFlowContext.jsx:98)

node.data.credential \!== currentNodes[index].data.credential

Issue: Using strict inequality (\!==) for credential comparison could miss cases where both values are null or undefined but should be treated as equal. This is likely fine in practice, but isEqual would be more consistent with the other checks.

Recommendation: Consider using isEqual for all three checks for consistency:

\!isEqual(node.data.credential, currentNodes[index].data.credential)

3. Missing Null Safety (DocStoreInputHandler.jsx:160-165)

if (nodeDataChangeHandler) {
    nodeDataChangeHandler({ nodeId: data.id, inputParam, newValue })
} else {
    data.credential = newValue
    data.inputs[FLOWISE_CREDENTIAL_ID] = newValue
}

Issue: If data.id is undefined/null, this will fail silently or cause downstream issues.

Recommendation: Add defensive check:

if (nodeDataChangeHandler && data?.id) {
    nodeDataChangeHandler({ nodeId: data.id, inputParam, newValue })
} else {
    // Fallback for nodes without context or missing ID
    data.credential = newValue
    data.inputs[FLOWISE_CREDENTIAL_ID] = newValue
}

4. Index-Based Comparison Risk (ReactFlowContext.jsx:95)

const hasChanges = updatedNodes.some(
    (node, index) =>
        \!isEqual(node.data.inputParams, currentNodes[index].data.inputParams) ||
        // ...
)

Issue: This assumes updatedNodes and currentNodes arrays have the same order and length. If nodes are reordered or added/removed during the update cycle, this could produce incorrect results.

Recommendation: Use node ID-based comparison instead:

const hasChanges = updatedNodes.some((node) => {
    const currentNode = currentNodes.find(n => n.id === node.id)
    if (\!currentNode) return true // Node was added
    return \!isEqual(node.data.inputParams, currentNode.data.inputParams) ||
           \!isEqual(node.data.inputs, currentNode.data.inputs) ||
           node.data.credential \!== currentNode.data.credential
})

🔒 Security

No security concerns identified

  • No sensitive data exposure
  • No SQL injection or XSS vectors
  • Proper use of state management patterns

🧪 Testing

Strengths:

  • E2E test properly validates the fix works from a user perspective
  • Test is resilient to internal implementation changes

Recommendations:

  1. Add unit tests for ReactFlowContext.onNodeDataChange to verify:

    • Credential updates trigger state changes
    • hasChanges correctly detects all change types
    • Edge cases (null credentials, missing inputParams, etc.)
  2. Add integration test for DocStoreInputHandler credential selection to verify it calls onNodeDataChange correctly


📊 Performance

No performance concerns

  • isEqual checks are efficient for shallow objects
  • Change detection prevents unnecessary re-renders
  • No obvious memory leaks

🎯 Adherence to Repository Standards

Follows TheAnswer patterns:

  • ✅ Proper error handling patterns
  • ✅ Centralized state management via context
  • ✅ Consistent use of ReactFlow best practices
  • ✅ Conventional commit messages

⚠️ Minor deviation:

  • Test removal could have been a separate commit for better git history

📝 Summary

Critical Issues: 0

High Priority: 0

Medium Priority: 4

  1. Add clarifying comment for credential mutation timing
  2. Use isEqual for credential comparison consistency
  3. Add null safety check for data.id
  4. Use ID-based comparison instead of index-based

Low Priority: 2

  1. Add unit tests for state change detection
  2. Add integration tests for credential selection flow

Recommendation: ✅ APPROVE with suggestions

This PR is ready to merge. The fixes correctly address the reported issues and follow good architectural patterns. The suggested improvements are minor and can be addressed in follow-up work if desired.

The credential refresh fix is well-implemented and solves a real UX problem. The centralized state management approach is the right long-term solution.

Nice work on the systematic fix with proper E2E test coverage! 🎉

maxtechera and others added 3 commits February 6, 2026 14:48
The UnifiedCredentialsModal (auto-popup for missing credentials) saved
to the backend but never notified the canvas to re-fetch. The canvas
View and SidekickSetupModal are independent components with no shared
state — View loads via useApi (once at mount), while the modal saves
via SWR.

Bridge with a lightweight custom event:
- SidekickSetupModal dispatches 'credentials-updated' after saving
- Canvas listens and re-fetches chatflow data via getSpecificChatflowApi

This covers the primary credential setup flow (canvas, chat, marketplace)
which is separate from the inline NodeInputHandler dropdown (PR #935).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agentcanvas and v2/agentcanvas pages were missing
SidekickSetupModal entirely — users opening agentflows with missing
credentials never got the auto-prompt.

- Add SidekickSetupModal to agentcanvas/[chatflowid]/page.tsx
- Add SidekickSetupModal to v2/agentcanvas/[chatflowid]/page.tsx
- Add credentials-updated event listener to agentflowsv2/Canvas.jsx

Now consistent with chatflow canvas page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…al-canvas-sync

fix(AGENT-76): sync canvas after credential modal saves
@claude

claude Bot commented Feb 6, 2026

Copy link
Copy Markdown

Pull Request Review: Staging to Production Release (2026.02.06)

Overview

This is a staging-to-production release PR that includes credential modal improvements for the agent canvas (AGENT-76) and a bug fix for ChatDrawer. The changes look solid overall with good architectural patterns, but there are a few areas that warrant attention.


Strengths

1. Centralized State Management

The use of ReactFlowContext for credential updates is excellent:

  • packages/ui/src/store/context/ReactFlowContext.jsx:72-82 - Proper handling of credential updates with both credential field and FLOWISE_CREDENTIAL_ID
  • packages/ui/src/views/docstore/DocStoreInputHandler.jsx:160-165 - Good delegation to centralized handler when available

2. Event-Driven Architecture

The custom event pattern for credential updates is a clean solution:

  • packages/ui/src/components/SidekickSetupModal.jsx:114 - Dispatches credentials-updated event
  • packages/ui/src/views/canvas/index.jsx:605-614 - Listens and re-fetches canvas data
  • packages/ui/src/views/agentflowsv2/Canvas.jsx:680-688 - Consistent implementation across both canvas versions

3. Proper Cleanup

All event listeners have proper cleanup in useEffect return functions - this prevents memory leaks.

4. Bug Fix Quality

The ChatDrawer fix (packages-answers/ui/src/ChatDrawer.tsx:79) correctly references _chats instead of undefined chats - good catch!


⚠️ Issues & Concerns

1. Critical: Potential Race Condition in ReactFlowContext

Location: packages/ui/src/store/context/ReactFlowContext.jsx:72-82

Issue: The credential update logic modifies updatedInputs AFTER creating updatedData:

// Handle credential inputs: update both credential field and FLOWISE_CREDENTIAL_ID
if (inputParam.type === 'credential') {
    updatedInputs[FLOWISE_CREDENTIAL_ID] = newValue  // ❌ Modifies after updatedData is created
}

const updatedData = {
    ...node.data,
    inputParams: updatedInputParams,
    inputs: updatedInputs,  // This already has the mutation
    ...(inputParam.type === 'credential' && { credential: newValue })
}

Why it works but is confusing: JavaScript objects are passed by reference, so the mutation to updatedInputs affects updatedData.inputs. However, this is non-obvious and could lead to bugs if refactored.

Recommendation: Move the credential check BEFORE creating updatedData:

// Handle credential inputs: update both credential field and FLOWISE_CREDENTIAL_ID
if (inputParam.type === 'credential') {
    updatedInputs[FLOWISE_CREDENTIAL_ID] = newValue
}

const updatedData = {
    ...node.data,
    inputParams: updatedInputParams,
    inputs: updatedInputs,
    ...(inputParam.type === 'credential' && { credential: newValue })
}

2. Inconsistent Change Detection

Location: packages/ui/src/store/context/ReactFlowContext.jsx:92-99

Issue: The change detection uses array index-based comparison:

const hasChanges = updatedNodes.some(
    (node, index) =>
        \!isEqual(node.data.inputParams, currentNodes[index].data.inputParams) ||
        \!isEqual(node.data.inputs, currentNodes[index].data.inputs) ||
        node.data.credential \!== currentNodes[index].data.credential
)

Potential Problem: If node order changes or nodes are added/removed, this will fail or produce false positives. Consider using a Map keyed by node.id instead.

Recommendation:

const currentNodesMap = new Map(currentNodes.map(n => [n.id, n]))
const hasChanges = updatedNodes.some((node) => {
    const currentNode = currentNodesMap.get(node.id)
    if (\!currentNode) return true
    return (
        \!isEqual(node.data.inputParams, currentNode.data.inputParams) ||
        \!isEqual(node.data.inputs, currentNode.data.inputs) ||
        node.data.credential \!== currentNode.data.credential
    )
})

3. Test Simplification May Hide Issues

Location: apps/web/e2e/tests/canvas-credential-refresh.spec.ts:152-156

Issue: The test was simplified by removing the ReactFlow internal state verification:

// Removed code that verified:
// const credentialSetInNode = await page.evaluate(() => {
//     const nodes = (window as any).__REACT_FLOW_NODES || []
//     return nodes.some((node: any) => node.data?.credential || ...)
// })

Concern: While the removed code was brittle (accessing internals), the new test only verifies UI state, not actual data persistence. If the UI shows the credential but the node data isn't updated, the bug could still exist.

Recommendation: Consider adding an integration test that verifies the credential is actually saved by:

  1. Setting a credential
  2. Saving the canvas
  3. Reloading the page
  4. Verifying the credential persists

4. Missing Error Handling for Event Listener

Location: packages/ui/src/views/canvas/index.jsx:606-609

Issue: No error handling if getSpecificChatflowApi.request() fails:

const handleCredentialsUpdated = (e) => {
    if (e.detail?.chatflowId === chatflowId) {
        getSpecificChatflowApi.request(chatflowId)  // ❌ No error handling
    }
}

Recommendation:

const handleCredentialsUpdated = async (e) => {
    if (e.detail?.chatflowId === chatflowId) {
        try {
            await getSpecificChatflowApi.request(chatflowId)
        } catch (error) {
            console.error('Failed to refresh canvas after credential update:', error)
            // Optionally show user notification
        }
    }
}

5. Unused Interface Removal

Location: apps/web/app/(Main UI)/(Studio Layout)/sidekick-studio/(minimal-layout)/agentcanvas/[chatflowid]/page.tsx:4-6

Minor Issue: The ViewProps interface was removed but appears to have never been used. Good cleanup, but verify it wasn't intended for future typing.


🔍 Security Considerations

No Security Issues Found

  • No credential exposure in client code
  • Proper use of server-side components for sensitive operations
  • Event payload validation (e.detail?.chatflowId === chatflowId)

🧪 Testing Recommendations

  1. Add Integration Test: Verify credential persistence across page reloads
  2. Test Error Scenarios:
    • What happens if credentials-updated event fires while canvas is still loading?
    • What if the API request fails during credential refresh?
  3. Manual Testing Checklist:
    • Open agent canvas
    • Add credential via setup modal
    • Verify canvas updates without page reload
    • Save chatflow
    • Reload page
    • Verify credential persists

📊 Code Quality Metrics

  • Lines Changed: +51/-26 (net +25)
  • Files Changed: 9
  • Commit Convention: ✅ Follows conventional commits
  • TypeScript Safety: ⚠️ Some files are .jsx instead of .tsx

🎯 Recommendations Summary

Must Fix (Before Merge)

None - the code is functional

Should Fix (Post-Merge)

  1. Refactor credential update logic in ReactFlowContext for clarity
  2. Improve change detection to use node IDs instead of array indices
  3. Add error handling to event listener API calls

Nice to Have

  1. Convert .jsx files to .tsx for better type safety
  2. Add integration test for credential persistence
  3. Add JSDoc comments for the custom event pattern

Approval Status

Recommendation: APPROVE with minor suggestions for follow-up

This PR successfully addresses AGENT-76 and includes a critical bug fix for ChatDrawer. The architectural approach using custom events is sound, and the changes are well-contained. The issues identified are primarily about code clarity and robustness rather than functional correctness.

The code is safe to merge to production with the understanding that the suggestions above should be addressed in a follow-up PR to improve maintainability and error resilience.


📝 Additional Notes

  • This is an automated release PR from staging → production
  • All changes have already been tested in staging environment
  • Consider adding a CHANGELOG.md entry for the AGENT-76 fix
  • The credential refresh pattern could be documented for future reference

Great work on the credential sync fix! 🎉

@maxtechera
maxtechera merged commit be31e18 into production Feb 6, 2026
11 checks passed
@maxtechera
maxtechera temporarily deployed to staging - aai-unified2-flowise-moonstruck February 6, 2026 18:56 — with Render Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant