@@ -3,161 +3,12 @@ import { isEqual } from 'lodash'
33import { createLogger } from '@/lib/logs/console-logger'
44import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
55import { getProviderFromModel } from '@/providers/utils'
6- import { useGeneralStore } from '@/stores/settings/general/store'
76import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
87import { useSubBlockStore } from '@/stores/workflows/subblock/store'
98import { useWorkflowStore } from '@/stores/workflows/workflow/store'
109
1110const logger = createLogger ( 'SubBlockValue' )
1211
13- // Helper function to dispatch collaborative subblock updates
14- const dispatchSubblockUpdate = ( blockId : string , subBlockId : string , value : any ) => {
15- const event = new CustomEvent ( 'update-subblock-value' , {
16- detail : {
17- blockId,
18- subBlockId,
19- value,
20- } ,
21- } )
22- window . dispatchEvent ( event )
23- }
24-
25- /**
26- * Helper to handle API key auto-fill for provider-based blocks
27- * Used for agent, router, evaluator, and any other blocks that use LLM providers
28- */
29- function handleProviderBasedApiKey (
30- blockId : string ,
31- subBlockId : string ,
32- modelValue : string | null | undefined ,
33- storeValue : any ,
34- isModelChange = false
35- ) {
36- // Only proceed if we have a model selected
37- if ( ! modelValue ) return
38-
39- // Get the provider for this model
40- const provider = getProviderFromModel ( modelValue )
41-
42- // Skip if we couldn't determine a provider
43- if ( ! provider || provider === 'ollama' ) return
44-
45- const subBlockStore = useSubBlockStore . getState ( )
46- const isAutoFillEnabled = useGeneralStore . getState ( ) . isAutoFillEnvVarsEnabled
47-
48- // Try to get a saved API key for this provider (only if auto-fill is enabled)
49- const savedValue = isAutoFillEnabled
50- ? subBlockStore . resolveToolParamValue ( provider , 'apiKey' , blockId )
51- : null
52-
53- // If we have a valid saved API key and auto-fill is enabled, use it
54- if ( savedValue && savedValue !== '' && isAutoFillEnabled ) {
55- // Only update if the current value is different to avoid unnecessary updates
56- if ( storeValue !== savedValue ) {
57- dispatchSubblockUpdate ( blockId , subBlockId , savedValue )
58- }
59- } else if ( isModelChange && ( ! storeValue || storeValue === '' ) ) {
60- // Only clear the field when switching models AND the field is already empty
61- // Don't clear existing user-entered values on initial load
62- dispatchSubblockUpdate ( blockId , subBlockId , '' )
63- }
64- // If no saved value and this is initial load, preserve existing value
65- }
66-
67- /**
68- * Helper to handle API key auto-fill for non-agent blocks
69- */
70- function handleStandardBlockApiKey (
71- blockId : string ,
72- subBlockId : string ,
73- blockType : string | undefined ,
74- storeValue : any
75- ) {
76- if ( ! blockType ) return
77-
78- const subBlockStore = useSubBlockStore . getState ( )
79-
80- // Only auto-fill if the field is empty
81- if ( ! storeValue || storeValue === '' ) {
82- // Pass the blockId as instanceId to check if this specific instance has been cleared
83- const savedValue = subBlockStore . resolveToolParamValue ( blockType , 'apiKey' , blockId )
84-
85- if ( savedValue && savedValue !== '' && savedValue !== storeValue ) {
86- // Auto-fill the API key from the param store
87- dispatchSubblockUpdate ( blockId , subBlockId , savedValue )
88- }
89- }
90- // Handle environment variable references
91- else if (
92- storeValue &&
93- typeof storeValue === 'string' &&
94- storeValue . startsWith ( '{{' ) &&
95- storeValue . endsWith ( '}}' )
96- ) {
97- // Pass the blockId as instanceId
98- const currentValue = subBlockStore . resolveToolParamValue ( blockType , 'apiKey' , blockId )
99-
100- if ( currentValue !== storeValue ) {
101- // If we got a replacement or null, update the field
102- if ( currentValue ) {
103- // Replacement found - update to new reference
104- dispatchSubblockUpdate ( blockId , subBlockId , currentValue )
105- }
106- }
107- }
108- }
109-
110- /**
111- * Helper to store API key values
112- */
113- function storeApiKeyValue (
114- blockId : string ,
115- blockType : string | undefined ,
116- modelValue : string | null | undefined ,
117- newValue : any ,
118- storeValue : any
119- ) {
120- if ( ! blockType ) return
121-
122- const subBlockStore = useSubBlockStore . getState ( )
123-
124- // Check if this is user explicitly clearing a field that had a value
125- // We only want to mark it as cleared if it's a user action, not an automatic
126- // clearing from model switching
127- if (
128- storeValue &&
129- storeValue !== '' &&
130- ( newValue === null || newValue === '' || String ( newValue ) . trim ( ) === '' )
131- ) {
132- // Mark this specific instance as cleared so we don't auto-fill it
133- subBlockStore . markParamAsCleared ( blockId , 'apiKey' )
134- return
135- }
136-
137- // Only store non-empty values
138- if ( ! newValue || String ( newValue ) . trim ( ) === '' ) return
139-
140- // If user enters a value, we should clear any "cleared" flag
141- // to ensure auto-fill will work in the future
142- if ( subBlockStore . isParamCleared ( blockId , 'apiKey' ) ) {
143- subBlockStore . unmarkParamAsCleared ( blockId , 'apiKey' )
144- }
145-
146- // For provider-based blocks, store the API key under the provider name
147- if (
148- ( blockType === 'agent' || blockType === 'router' || blockType === 'evaluator' ) &&
149- modelValue
150- ) {
151- const provider = getProviderFromModel ( modelValue )
152- if ( provider && provider !== 'ollama' ) {
153- subBlockStore . setToolParam ( provider , 'apiKey' , String ( newValue ) )
154- }
155- } else {
156- // For other blocks, store under the block type
157- subBlockStore . setToolParam ( blockType , 'apiKey' , String ( newValue ) )
158- }
159- }
160-
16112interface UseSubBlockValueOptions {
16213 debounceMs ?: number
16314 isStreaming ?: boolean // Explicit streaming state
@@ -199,9 +50,6 @@ export function useSubBlockValue<T = any>(
19950 // Keep a ref to the latest value to prevent unnecessary re-renders
20051 const valueRef = useRef < T | null > ( null )
20152
202- // Previous model reference for detecting model changes
203- const prevModelRef = useRef < string | null > ( null )
204-
20553 // Streaming refs
20654 const lastEmittedValueRef = useRef < T | null > ( null )
20755 const streamingValueRef = useRef < T | null > ( null )
@@ -216,9 +64,6 @@ export function useSubBlockValue<T = any>(
21664 const isApiKey =
21765 subBlockId === 'apiKey' || ( subBlockId ?. toLowerCase ( ) . includes ( 'apikey' ) ?? false )
21866
219- // Check if auto-fill environment variables is enabled - always call this hook unconditionally
220- const isAutoFillEnvVarsEnabled = useGeneralStore ( ( state ) => state . isAutoFillEnvVarsEnabled )
221-
22267 // Always call this hook unconditionally - don't wrap it in a condition
22368 const modelSubBlockValue = useSubBlockStore ( ( state ) =>
22469 blockId ? state . getValue ( blockId , 'model' ) : null
@@ -276,6 +121,29 @@ export function useSubBlockValue<T = any>(
276121 } ,
277122 } ) )
278123
124+ // Handle model changes for provider-based blocks - clear API key when provider changes
125+ if (
126+ subBlockId === 'model' &&
127+ isProviderBasedBlock &&
128+ newValue &&
129+ typeof newValue === 'string'
130+ ) {
131+ const currentApiKeyValue = useSubBlockStore . getState ( ) . getValue ( blockId , 'apiKey' )
132+
133+ // Only clear if there's currently an API key value
134+ if ( currentApiKeyValue && currentApiKeyValue !== '' ) {
135+ const oldModelValue = storeValue as string
136+ const oldProvider = oldModelValue ? getProviderFromModel ( oldModelValue ) : null
137+ const newProvider = getProviderFromModel ( newValue )
138+
139+ // Clear API key if provider changed
140+ if ( oldProvider !== newProvider ) {
141+ // Use collaborative function to clear the API key
142+ collaborativeSetSubblockValue ( blockId , 'apiKey' , '' )
143+ }
144+ }
145+ }
146+
279147 // Ensure we're passing the actual value, not a reference that might change
280148 const valueCopy =
281149 newValue === null
@@ -284,11 +152,6 @@ export function useSubBlockValue<T = any>(
284152 ? JSON . parse ( JSON . stringify ( newValue ) )
285153 : newValue
286154
287- // Handle API key storage for reuse across blocks
288- if ( isApiKey && blockType ) {
289- storeApiKeyValue ( blockId , blockType , modelValue , newValue , storeValue )
290- }
291-
292155 // If streaming, just store the value without emitting
293156 if ( isStreaming ) {
294157 streamingValueRef . current = valueCopy
@@ -320,61 +183,6 @@ export function useSubBlockValue<T = any>(
320183 valueRef . current = storeValue !== undefined ? storeValue : initialValue
321184 } , [ ] )
322185
323- // When component mounts, check for existing API key in toolParamsStore
324- useEffect ( ( ) => {
325- // Skip autofill if the feature is disabled in settings
326- if ( ! isAutoFillEnvVarsEnabled ) return
327-
328- // Only process API key fields
329- if ( ! isApiKey ) return
330-
331- // Handle different block types
332- if ( isProviderBasedBlock ) {
333- handleProviderBasedApiKey ( blockId , subBlockId , modelValue , storeValue , false )
334- } else {
335- // Normal handling for non-provider blocks
336- handleStandardBlockApiKey ( blockId , subBlockId , blockType , storeValue )
337- }
338- } , [
339- blockId ,
340- subBlockId ,
341- blockType ,
342- storeValue ,
343- isApiKey ,
344- isAutoFillEnvVarsEnabled ,
345- modelValue ,
346- isProviderBasedBlock ,
347- ] )
348-
349- // Monitor for model changes in provider-based blocks
350- useEffect ( ( ) => {
351- // Only process API key fields in model-based blocks
352- if ( ! isApiKey || ! isProviderBasedBlock ) return
353-
354- // Check if the model has changed
355- if ( modelValue !== prevModelRef . current ) {
356- // Update the previous model reference
357- prevModelRef . current = modelValue
358-
359- // Handle API key auto-fill for model changes
360- if ( modelValue ) {
361- handleProviderBasedApiKey ( blockId , subBlockId , modelValue , storeValue , true )
362- } else {
363- // If no model is selected, clear the API key field
364- dispatchSubblockUpdate ( blockId , subBlockId , '' )
365- }
366- }
367- } , [
368- blockId ,
369- subBlockId ,
370- blockType ,
371- isApiKey ,
372- modelValue ,
373- isAutoFillEnvVarsEnabled ,
374- storeValue ,
375- isProviderBasedBlock ,
376- ] )
377-
378186 // Update the ref if the store value changes
379187 // This ensures we're always working with the latest value
380188 useEffect ( ( ) => {
0 commit comments