@@ -50,6 +50,26 @@ class ContextRequire(BaseModel):
5050 pass
5151
5252
53+ class CredentialModel :
54+ """凭证模型基类,用于声明插件需要的凭证"""
55+
56+ pass
57+
58+
59+ class Credential (BaseModel ):
60+ """凭证定义类,用于声明插件需要的凭证"""
61+
62+ key : str
63+ name : str = ""
64+ description : str = ""
65+
66+ def __init__ (self , key : str , name : str = "" , description : str = "" , ** kwargs ):
67+ # 如果 name 为空,使用 key 作为 name
68+ if not name :
69+ name = key
70+ super ().__init__ (key = key , name = name , description = description , ** kwargs )
71+
72+
5373class Callback (object ):
5474 def __init__ (self , callback_id : str = "" , callback_data : dict = {}):
5575 self .id = callback_id
@@ -66,6 +86,7 @@ def __init__(
6686 callback : Callback = None ,
6787 outputs : typing .Optional [dict ] = None ,
6888 storage : typing .Optional [dict ] = None ,
89+ credentials : typing .Optional [dict ] = None ,
6990 ):
7091 self .trace_id = trace_id
7192 self .data = data
@@ -74,6 +95,7 @@ def __init__(
7495 self .callback = callback
7596 self .storage = storage or {}
7697 self .outputs = outputs or {}
98+ self .credentials = credentials or {}
7799
78100 @property
79101 def schedule_context (self ) -> dict :
@@ -140,6 +162,28 @@ def __new__(cls, name, bases, dct):
140162 "plugin deinition error, {}'s ContextInputs is not subclass of {}" .format (new_cls , ContextRequire )
141163 )
142164
165+ # credentials validation (class attribute, similar to ContextInputs)
166+ credentials_cls = getattr (new_cls , "Credentials" , None )
167+ if credentials_cls :
168+ # Check if Credentials class inherits from CredentialModel
169+ if not issubclass (credentials_cls , CredentialModel ):
170+ raise TypeError (
171+ "plugin deinition error, {}'s Credentials is not subclass of {}" .format (new_cls , CredentialModel )
172+ )
173+
174+ # Validate each Credential instance in the Credentials class
175+ for attr_name in dir (credentials_cls ):
176+ if attr_name .startswith ("_" ):
177+ continue
178+ attr_value = getattr (credentials_cls , attr_name )
179+ if isinstance (attr_value , Credential ):
180+ if not attr_value .key :
181+ raise ValueError (
182+ "plugin deinition error, Credentials.{}.key cannot be empty in {}" .format (
183+ attr_name , new_cls
184+ )
185+ )
186+
143187 # inputs form check
144188 inputs_form_cls = getattr (new_cls , "InputsForm" , None )
145189 if inputs_form_cls and not issubclass (inputs_form_cls , FormModel ):
@@ -200,6 +244,7 @@ def dict(cls) -> dict:
200244 "desc" : getattr (cls .Meta , "desc" , "" ),
201245 "version" : cls .Meta .version ,
202246 "enable_plugin_callback" : getattr (cls .Meta , "enable_plugin_callback" , False ),
247+ "credentials" : cls ._EMPTY_SCHEMA ,
203248 "inputs" : cls ._EMPTY_SCHEMA ,
204249 "outputs" : cls ._EMPTY_SCHEMA ,
205250 "context_inputs" : cls ._EMPTY_SCHEMA ,
@@ -227,4 +272,18 @@ def dict(cls) -> dict:
227272 if context_cls :
228273 data ["context_inputs" ] = cls ._trim_schema (context_cls .schema ())
229274
275+ # Extract credentials from Credentials class
276+ credentials_cls = getattr (cls , "Credentials" , None )
277+ if credentials_cls :
278+ credentials_list = []
279+ for attr_name in dir (credentials_cls ):
280+ if attr_name .startswith ("_" ):
281+ continue
282+ attr_value = getattr (credentials_cls , attr_name )
283+ if isinstance (attr_value , Credential ):
284+ credentials_list .append (attr_value )
285+
286+ data ["credentials" ] = [
287+ {"key" : c .key , "name" : c .name , "description" : c .description } for c in credentials_list
288+ ]
230289 return data
0 commit comments