soprano-sdk 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -128,14 +128,18 @@ class MFANodeConfig:
128
128
  )
129
129
 
130
130
  @classmethod
131
- def get_validate_user_input(cls, source_node: str, next_node: str, model_name: str):
131
+ def get_validate_user_input(cls, source_node: str, next_node: str, mfa_config: dict):
132
+ model_name = mfa_config['model']
133
+ max_attempts = mfa_config.get('max_attempts', 3)
134
+ on_max_attempts_reached = mfa_config.get('on_max_attempts_reached')
135
+
132
136
  input_field_name = f"{source_node}_mfa_input"
133
- return dict(
137
+ node_config = dict(
134
138
  id=f"{source_node}_mfa_validate",
135
139
  action="collect_input_with_agent",
136
140
  description="Collect Input for MFA value",
137
141
  field=input_field_name,
138
- max_attempts=3,
142
+ max_attempts=max_attempts,
139
143
  validator="soprano_sdk.authenticators.mfa.mfa_validate_user_input",
140
144
  agent=dict(
141
145
  name="MFA Input Data Collector",
@@ -164,3 +168,8 @@ class MFANodeConfig:
164
168
  )
165
169
  ]
166
170
  )
171
+
172
+ if on_max_attempts_reached:
173
+ node_config['on_max_attempts_reached'] = on_max_attempts_reached
174
+
175
+ return node_config
@@ -209,8 +209,9 @@ class WorkflowEngine:
209
209
 
210
210
  if mfa_config := step.get('mfa'):
211
211
  mfa_data_collector = MFANodeConfig.get_validate_user_input(
212
- next_node=step_id, model_name=mfa_config['model'],
213
- source_node=step_id
212
+ next_node=step_id,
213
+ source_node=step_id,
214
+ mfa_config=mfa_config
214
215
  )
215
216
  mfa_start = MFANodeConfig.get_call_function_template(
216
217
  source_node=step_id,
@@ -92,6 +92,7 @@ class CollectInputStrategy(ActionStrategy):
92
92
  self.field = step_config.get('field')
93
93
  self.agent_config = step_config.get('agent', {})
94
94
  self.max_attempts = step_config.get('retry_limit') or engine_context.get_config_value("max_retry_limit", DEFAULT_MAX_ATTEMPTS)
95
+ self.on_max_attempts_reached = step_config.get('on_max_attempts_reached')
95
96
  self.transitions = self._get_transitions()
96
97
  self.next_step = self.step_config.get("next", None)
97
98
  self.is_structured_output = self.agent_config.get("structured_output", {}).get("enabled", False)
@@ -272,7 +273,10 @@ class CollectInputStrategy(ActionStrategy):
272
273
  def _handle_max_attempts(self, state: Dict[str, Any]) -> Dict[str, Any]:
273
274
  logger.warning(f"Max attempts reached for field '{self.field}'")
274
275
  self._set_status(state, 'max_attempts')
275
- message = MAX_ATTEMPTS_MESSAGE.format(field=self.field)
276
+ if self.on_max_attempts_reached:
277
+ message = self.on_max_attempts_reached
278
+ else:
279
+ message = MAX_ATTEMPTS_MESSAGE.format(field=self.field)
276
280
  state[WorkflowKeys.MESSAGES] = [message]
277
281
  return state
278
282
 
@@ -90,6 +90,10 @@ WORKFLOW_SCHEMA = {
90
90
  "maximum": 20,
91
91
  "description": "Maximum attempts (for collect_input_with_agent)"
92
92
  },
93
+ "on_max_attempts_reached": {
94
+ "type": "string",
95
+ "description": "Custom error message to display when max attempts are exhausted (for collect_input_with_agent)"
96
+ },
93
97
  "agent": {
94
98
  "type": "object",
95
99
  "description": "Agent configuration (for collect_input_with_agent)",
@@ -245,6 +249,16 @@ WORKFLOW_SCHEMA = {
245
249
  "type": "object",
246
250
  "description": "MFA payload data that is posted to the RESTAPI, Apart from the properties provided transactionId is sent by the framework in the post payload as an additional property, transactionId is the same throughout the MFA process",
247
251
  "additionalProperties": True
252
+ },
253
+ "max_attempts": {
254
+ "type": "integer",
255
+ "minimum": 1,
256
+ "maximum": 20,
257
+ "description": "Maximum number of attempts allowed for MFA validation (default: 3)"
258
+ },
259
+ "on_max_attempts_reached": {
260
+ "type": "string",
261
+ "description": "Custom error message to display when MFA max attempts are exhausted"
248
262
  }
249
263
  }
250
264
  },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soprano-sdk
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: YAML-driven workflow engine with AI agent integration for building conversational SOPs
5
5
  Author: Arvind Thangamani
6
6
  License: MIT
@@ -6,16 +6,16 @@ soprano_sdk/agents/adaptor.py,sha256=Cm02YKFclrESu-Qq4CTknCgU7KaA7Z_2FspnQDkEVfU
6
6
  soprano_sdk/agents/factory.py,sha256=Aucfz4rZVKCXMAQtbGAqp1JR8aYwa66mokRmKkKGhYA,6699
7
7
  soprano_sdk/agents/structured_output.py,sha256=7DSVzfMPsZAqBwI3v6XL15qG5Gh4jJ-qddcVPaa3gdc,3326
8
8
  soprano_sdk/authenticators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- soprano_sdk/authenticators/mfa.py,sha256=OHbPYsns2LZEbnqod7H_iW0AE9bdJ_74-EiaAmvOoVc,5644
9
+ soprano_sdk/authenticators/mfa.py,sha256=7aTueLu2jLxl213Q5_BkNQ534RgEwf6lodQa_PaJFWs,5980
10
10
  soprano_sdk/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  soprano_sdk/core/constants.py,sha256=F7gL3hkpq5mZgbgiBcEERmzxYJ4zZG2ZFx1YQp5Z580,3130
12
- soprano_sdk/core/engine.py,sha256=RbLmKSq65I8q-vFTBFC_dqozvhQ13X_eRh_aHuEkRT0,11259
12
+ soprano_sdk/core/engine.py,sha256=UTFJimrgUzfdDZgc4rW5nvkOKevAEGW8C5Zr1D0tgcs,11270
13
13
  soprano_sdk/core/rollback_strategies.py,sha256=NjDTtBCZlqyDql5PSwI9SMDLK7_BNlTxbW_cq_5gV0g,7783
14
14
  soprano_sdk/core/state.py,sha256=k8ojLfWgjES3p9XWMeGU5s4UK-Xa5T8mS4VtZzTrcDw,2961
15
15
  soprano_sdk/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  soprano_sdk/nodes/base.py,sha256=idFyOGGPnjsASYnrOF_NIh7eFcSuJqw61EoVN_WCTaU,2360
17
17
  soprano_sdk/nodes/call_function.py,sha256=PdmSSVXkMT5ptxeUjmKqND-wvqbaXp1i61QzIzFOfgQ,5535
18
- soprano_sdk/nodes/collect_input.py,sha256=IsHXb8J-4Dpjcza4zVLLtzQ82NMlZDgXhpNxtoJ6FCg,23567
18
+ soprano_sdk/nodes/collect_input.py,sha256=lEltZOU5ALvc57q8I_4SjzzEapVejy9mS0E73Jf7-sk,23759
19
19
  soprano_sdk/nodes/factory.py,sha256=l-Gysfgnao-o2dphhnbjjxcH3ojZanZNYN3CBH9dDbA,1624
20
20
  soprano_sdk/routing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  soprano_sdk/routing/router.py,sha256=SrNciTIXXdC9bAbbO5bX7PN9mlRbITjr4RZdNm4jEVA,3450
@@ -26,9 +26,9 @@ soprano_sdk/utils/template.py,sha256=MG_B9TMx1ShpnSGo7s7TO-VfQzuFByuRNhJTvZ668kM
26
26
  soprano_sdk/utils/tool.py,sha256=hWN826HIKmLdswLCTURLH8hWlb2WU0MB8nIUErbpB-8,1877
27
27
  soprano_sdk/utils/tracing.py,sha256=gSHeBDLe-MbAZ9rkzpCoGFveeMdR9KLaA6tteB0IWjk,1991
28
28
  soprano_sdk/validation/__init__.py,sha256=ImChmO86jYHU90xzTttto2-LmOUOmvY_ibOQaLRz5BA,262
29
- soprano_sdk/validation/schema.py,sha256=R6bm4Pzgx8p08o77FN9FFSKTLTKOCf7WuThrR6rV2FI,14578
29
+ soprano_sdk/validation/schema.py,sha256=7B60_8xIt5bLXTYEGEDwU2DwmQn2f4QFyyIca2FYM9s,15420
30
30
  soprano_sdk/validation/validator.py,sha256=GaCvHvjwVe88Z8yatQsueiPnqtq1oo5uN75gogzpQT0,8940
31
- soprano_sdk-0.2.3.dist-info/METADATA,sha256=gZasJ2fAEfHIcgd7wKjyPsPUJv0PdTeP5B06eimF03U,11297
32
- soprano_sdk-0.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
- soprano_sdk-0.2.3.dist-info/licenses/LICENSE,sha256=A1aBauSjPNtVehOXJe3WuvdU2xvM9H8XmigFMm6665s,1073
34
- soprano_sdk-0.2.3.dist-info/RECORD,,
31
+ soprano_sdk-0.2.4.dist-info/METADATA,sha256=W-e-Si4pewUkpuWewKz_pmkWvUeRVR8HPwQ-Z-7tpTQ,11297
32
+ soprano_sdk-0.2.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
+ soprano_sdk-0.2.4.dist-info/licenses/LICENSE,sha256=A1aBauSjPNtVehOXJe3WuvdU2xvM9H8XmigFMm6665s,1073
34
+ soprano_sdk-0.2.4.dist-info/RECORD,,