@@ -50,6 +50,25 @@ class ContextRequire(BaseModel):
5050 pass
5151
5252
53+ class CredentialModel :
54+ """凭证模型基类,用于声明插件需要的凭证"""
55+ pass
56+
57+
58+ class Credential (BaseModel ):
59+ """凭证定义类,用于声明插件需要的凭证"""
60+
61+ key : str
62+ name : str = ""
63+ description : str = ""
64+
65+ def __init__ (self , key : str , name : str = "" , description : str = "" , ** kwargs ):
66+ # 如果 name 为空,使用 key 作为 name
67+ if not name :
68+ name = key
69+ super ().__init__ (key = key , name = name , description = description , ** kwargs )
70+
71+
5372class Callback (object ):
5473 def __init__ (self , callback_id : str = "" , callback_data : dict = {}):
5574 self .id = callback_id
@@ -66,6 +85,7 @@ def __init__(
6685 callback : Callback = None ,
6786 outputs : typing .Optional [dict ] = None ,
6887 storage : typing .Optional [dict ] = None ,
88+ credentials : typing .Optional [dict ] = None ,
6989 ):
7090 self .trace_id = trace_id
7191 self .data = data
@@ -74,6 +94,7 @@ def __init__(
7494 self .callback = callback
7595 self .storage = storage or {}
7696 self .outputs = outputs or {}
97+ self .credentials = credentials or {}
7798
7899 @property
79100 def schedule_context (self ) -> dict :
@@ -140,6 +161,28 @@ def __new__(cls, name, bases, dct):
140161 "plugin deinition error, {}'s ContextInputs is not subclass of {}" .format (new_cls , ContextRequire )
141162 )
142163
164+ # credentials validation (class attribute, similar to ContextInputs)
165+ credentials = getattr (new_cls , "credentials" , None )
166+ if credentials is None :
167+ credentials = []
168+ if not isinstance (credentials , list ):
169+ raise TypeError (
170+ "plugin deinition error, credentials field is not a list in {}" .format (new_cls )
171+ )
172+
173+ # Validate each credential in the list
174+ for idx , credential in enumerate (credentials ):
175+ if not isinstance (credential , Credential ):
176+ raise TypeError (
177+ "plugin deinition error, credentials[{}] is not a Credential instance in {}" .format (
178+ idx , new_cls
179+ )
180+ )
181+ if not credential .key :
182+ raise ValueError (
183+ "plugin deinition error, credentials[{}].key cannot be empty in {}" .format (idx , new_cls )
184+ )
185+
143186 # inputs form check
144187 inputs_form_cls = getattr (new_cls , "InputsForm" , None )
145188 if inputs_form_cls and not issubclass (inputs_form_cls , FormModel ):
@@ -200,6 +243,7 @@ def dict(cls) -> dict:
200243 "desc" : getattr (cls .Meta , "desc" , "" ),
201244 "version" : cls .Meta .version ,
202245 "enable_plugin_callback" : getattr (cls .Meta , "enable_plugin_callback" , False ),
246+ "credentials" : cls ._EMPTY_SCHEMA ,
203247 "inputs" : cls ._EMPTY_SCHEMA ,
204248 "outputs" : cls ._EMPTY_SCHEMA ,
205249 "context_inputs" : cls ._EMPTY_SCHEMA ,
@@ -227,4 +271,16 @@ def dict(cls) -> dict:
227271 if context_cls :
228272 data ["context_inputs" ] = cls ._trim_schema (context_cls .schema ())
229273
274+ # Extract credentials from Credentials class
275+ credentials_cls = getattr (cls , "Credentials" , None )
276+ if credentials_cls :
277+ credentials_list = []
278+ for attr_name in dir (credentials_cls ):
279+ if attr_name .startswith ("_" ):
280+ continue
281+ attr_value = getattr (credentials_cls , attr_name )
282+ if isinstance (attr_value , Credential ):
283+ credentials_list .append (attr_value )
284+
285+ data ["credentials" ] = [{"key" : c .key , "name" : c .name , "description" : c .description } for c in credentials_list ]
230286 return data
0 commit comments