signalwire-agents 0.1.31__py3-none-any.whl → 0.1.33__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.
@@ -18,7 +18,7 @@ A package for building AI agents using SignalWire's AI and SWML capabilities.
18
18
  from .core.logging_config import configure_logging
19
19
  configure_logging()
20
20
 
21
- __version__ = "0.1.31"
21
+ __version__ = "0.1.33"
22
22
 
23
23
  # Import core classes for easier access
24
24
  from .core.agent_base import AgentBase
@@ -19,96 +19,175 @@ from typing import List, Dict, Any, Optional
19
19
  # Import after checking if available
20
20
  try:
21
21
  from signalwire_agents.core.agent_base import AgentBase
22
+ from signalwire_agents.core.swml_service import SWMLService
23
+ # Import the new service loader
24
+ from .service_loader import ServiceCapture, load_agent_from_file as new_load_agent
22
25
  AGENT_BASE_AVAILABLE = True
26
+ SWML_SERVICE_AVAILABLE = True
27
+ NEW_LOADER_AVAILABLE = True
23
28
  except ImportError:
24
29
  AgentBase = None
30
+ SWMLService = None
31
+ ServiceCapture = None
32
+ new_load_agent = None
25
33
  AGENT_BASE_AVAILABLE = False
34
+ SWML_SERVICE_AVAILABLE = False
35
+ NEW_LOADER_AVAILABLE = False
26
36
 
27
37
 
28
- def discover_agents_in_file(agent_path: str) -> List[Dict[str, Any]]:
38
+ def discover_services_in_file(service_path: str) -> List[Dict[str, Any]]:
29
39
  """
30
- Discover all available agents in a Python file without instantiating them
40
+ Discover all available SWML services (including agents) in a Python file without instantiating them
31
41
 
32
42
  Args:
33
- agent_path: Path to the Python file containing agents
43
+ service_path: Path to the Python file containing services
34
44
 
35
45
  Returns:
36
- List of dictionaries with agent information
46
+ List of dictionaries with service information
37
47
 
38
48
  Raises:
39
49
  ImportError: If the file cannot be imported
40
50
  FileNotFoundError: If the file doesn't exist
41
51
  """
42
- if not AGENT_BASE_AVAILABLE:
43
- raise ImportError("AgentBase not available. Please install signalwire-agents package.")
52
+ if not SWML_SERVICE_AVAILABLE:
53
+ raise ImportError("SWMLService not available. Please install signalwire-agents package.")
54
+
55
+ # Keep backward compatibility
56
+ return _discover_services_impl(service_path)
57
+
58
+
59
+ def discover_agents_in_file(agent_path: str) -> List[Dict[str, Any]]:
60
+ """
61
+ Backward compatibility wrapper - discovers agents in a file
62
+
63
+ Args:
64
+ agent_path: Path to the Python file containing agents
65
+
66
+ Returns:
67
+ List of dictionaries with agent information
68
+ """
69
+ # Filter to only return AgentBase instances/classes
70
+ all_services = discover_services_in_file(agent_path)
71
+ return [s for s in all_services if s.get('is_agent', False)]
72
+
73
+
74
+ def _discover_services_impl(service_path: str) -> List[Dict[str, Any]]:
75
+ """
76
+ Internal implementation for discovering services
77
+ """
78
+ service_path = Path(service_path).resolve()
44
79
 
45
- agent_path = Path(agent_path).resolve()
80
+ if not service_path.exists():
81
+ raise FileNotFoundError(f"Service file not found: {service_path}")
46
82
 
47
- if not agent_path.exists():
48
- raise FileNotFoundError(f"Agent file not found: {agent_path}")
83
+ if not service_path.suffix == '.py':
84
+ raise ValueError(f"Service file must be a Python file (.py): {service_path}")
49
85
 
50
- if not agent_path.suffix == '.py':
51
- raise ValueError(f"Agent file must be a Python file (.py): {agent_path}")
86
+ # Add the module's directory to sys.path temporarily to allow local imports
87
+ import sys
88
+ module_dir = str(service_path.parent)
89
+ sys_path_added = False
90
+ if module_dir not in sys.path:
91
+ sys.path.insert(0, module_dir)
92
+ sys_path_added = True
52
93
 
53
94
  # Load the module, but prevent main() execution by setting __name__ to something other than "__main__"
54
- spec = importlib.util.spec_from_file_location("agent_module", agent_path)
95
+ spec = importlib.util.spec_from_file_location("service_module", service_path)
55
96
  module = importlib.util.module_from_spec(spec)
56
97
 
57
98
  try:
58
99
  # Set __name__ to prevent if __name__ == "__main__": blocks from running
59
- module.__name__ = "agent_module"
100
+ module.__name__ = "service_module"
60
101
  spec.loader.exec_module(module)
61
102
  except Exception as e:
62
- raise ImportError(f"Failed to load agent module: {e}")
103
+ # Clean up sys.path if we added to it
104
+ if sys_path_added:
105
+ sys.path.remove(module_dir)
106
+ raise ImportError(f"Failed to load service module: {e}")
107
+ finally:
108
+ # Clean up sys.path after successful load too
109
+ if sys_path_added and module_dir in sys.path:
110
+ sys.path.remove(module_dir)
63
111
 
64
- agents_found = []
112
+ services_found = []
65
113
 
66
- # Look for AgentBase instances
114
+ # Look for SWMLService instances (including AgentBase which inherits from it)
67
115
  for name, obj in vars(module).items():
68
- if isinstance(obj, AgentBase):
69
- agents_found.append({
116
+ if isinstance(obj, SWMLService):
117
+ is_agent = isinstance(obj, AgentBase) if AgentBase else False
118
+ services_found.append({
70
119
  'name': name,
71
120
  'class_name': obj.__class__.__name__,
72
121
  'type': 'instance',
73
- 'agent_name': getattr(obj, 'name', 'Unknown'),
122
+ 'service_name': getattr(obj, 'name', 'Unknown'),
74
123
  'route': getattr(obj, 'route', 'Unknown'),
75
124
  'description': obj.__class__.__doc__,
76
- 'object': obj
125
+ 'object': obj,
126
+ 'is_agent': is_agent,
127
+ 'has_tools': is_agent and hasattr(obj, '_tool_registry')
77
128
  })
78
129
 
79
- # Look for AgentBase subclasses (that could be instantiated)
130
+ # Look for SWMLService subclasses (that could be instantiated)
80
131
  for name, obj in vars(module).items():
81
132
  if (isinstance(obj, type) and
82
- issubclass(obj, AgentBase) and
83
- obj != AgentBase):
133
+ issubclass(obj, SWMLService) and
134
+ obj not in (SWMLService, AgentBase)): # Don't include base classes
84
135
  # Check if we already found an instance of this class
85
- instance_found = any(agent['class_name'] == name for agent in agents_found)
136
+ instance_found = any(service['class_name'] == name for service in services_found)
86
137
  if not instance_found:
138
+ is_agent = AgentBase and issubclass(obj, AgentBase)
87
139
  try:
88
140
  # Try to get class information without instantiating
89
- agent_info = {
141
+ service_info = {
90
142
  'name': name,
91
143
  'class_name': name,
92
144
  'type': 'class',
93
- 'agent_name': 'Unknown (not instantiated)',
145
+ 'service_name': 'Unknown (not instantiated)',
94
146
  'route': 'Unknown (not instantiated)',
95
147
  'description': obj.__doc__,
96
- 'object': obj
148
+ 'object': obj,
149
+ 'is_agent': is_agent,
150
+ 'has_tools': False # Can't determine without instantiation
97
151
  }
98
- agents_found.append(agent_info)
152
+ services_found.append(service_info)
99
153
  except Exception:
100
154
  # If we can't get info, still record that the class exists
101
- agents_found.append({
155
+ services_found.append({
102
156
  'name': name,
103
157
  'class_name': name,
104
158
  'type': 'class',
105
- 'agent_name': 'Unknown (not instantiated)',
159
+ 'service_name': 'Unknown (not instantiated)',
106
160
  'route': 'Unknown (not instantiated)',
107
161
  'description': obj.__doc__ or 'No description available',
108
- 'object': obj
162
+ 'object': obj,
163
+ 'is_agent': is_agent,
164
+ 'has_tools': False
109
165
  })
110
166
 
111
- return agents_found
167
+ return services_found
168
+
169
+
170
+ def load_service_from_file(service_path: str, service_identifier: Optional[str] = None, prefer_route: bool = True) -> 'SWMLService':
171
+ """
172
+ Load a SWML service from a Python file
173
+
174
+ Args:
175
+ service_path: Path to the Python file containing the service
176
+ service_identifier: Optional service identifier - can be class name or route
177
+ prefer_route: If True, interpret identifier as route first, then class name
178
+
179
+ Returns:
180
+ SWMLService instance (could be AgentBase or basic SWMLService)
181
+
182
+ Raises:
183
+ ImportError: If the file cannot be imported
184
+ ValueError: If no service is found in the file
185
+ """
186
+ if not SWML_SERVICE_AVAILABLE:
187
+ raise ImportError("SWMLService not available. Please install signalwire-agents package.")
188
+
189
+ # Use the main implementation
190
+ return _load_service_impl(service_path, service_identifier, prefer_route)
112
191
 
113
192
 
114
193
  def load_agent_from_file(agent_path: str, agent_class_name: Optional[str] = None) -> 'AgentBase':
@@ -129,135 +208,263 @@ def load_agent_from_file(agent_path: str, agent_class_name: Optional[str] = None
129
208
  if not AGENT_BASE_AVAILABLE:
130
209
  raise ImportError("AgentBase not available. Please install signalwire-agents package.")
131
210
 
132
- agent_path = Path(agent_path).resolve()
211
+ # Check if we're being called from swaig-test --dump-swml (or similar)
212
+ # We can detect this by checking the call stack or environment
213
+ import inspect
214
+ suppress_output = False
215
+
216
+ # Check if we're in a context where output should be suppressed
217
+ frame = inspect.currentframe()
218
+ try:
219
+ # Walk up the call stack to see if we're being called from dump_swml
220
+ while frame:
221
+ if 'dump_swml' in frame.f_code.co_filename or 'swml_dump' in frame.f_code.co_filename:
222
+ suppress_output = True
223
+ break
224
+ frame = frame.f_back
225
+ finally:
226
+ del frame # Avoid reference cycles
227
+
228
+ # Use the old implementation but with a fix for the ordering
229
+ return _load_service_impl(agent_path, agent_class_name, prefer_route=False)
230
+
231
+
232
+ def _load_service_impl(service_path: str, service_identifier: Optional[str] = None, prefer_route: bool = True) -> 'SWMLService':
233
+ """
234
+ Internal implementation for loading services with smart detection
235
+ """
236
+ service_path = Path(service_path).resolve()
237
+
238
+ if not service_path.exists():
239
+ raise FileNotFoundError(f"Service file not found: {service_path}")
133
240
 
134
- if not agent_path.exists():
135
- raise FileNotFoundError(f"Agent file not found: {agent_path}")
241
+ if not service_path.suffix == '.py':
242
+ raise ValueError(f"Service file must be a Python file (.py): {service_path}")
136
243
 
137
- if not agent_path.suffix == '.py':
138
- raise ValueError(f"Agent file must be a Python file (.py): {agent_path}")
244
+ # Add the module's directory to sys.path temporarily to allow local imports
245
+ import sys
246
+ module_dir = str(service_path.parent)
247
+ sys_path_added = False
248
+ if module_dir not in sys.path:
249
+ sys.path.insert(0, module_dir)
250
+ sys_path_added = True
139
251
 
140
252
  # Load the module, but prevent main() execution by setting __name__ to something other than "__main__"
141
- spec = importlib.util.spec_from_file_location("agent_module", agent_path)
253
+ spec = importlib.util.spec_from_file_location("service_module", service_path)
142
254
  module = importlib.util.module_from_spec(spec)
143
255
 
144
256
  try:
145
257
  # Set __name__ to prevent if __name__ == "__main__": blocks from running
146
- module.__name__ = "agent_module"
258
+ module.__name__ = "service_module"
147
259
  spec.loader.exec_module(module)
148
260
  except Exception as e:
149
- raise ImportError(f"Failed to load agent module: {e}")
261
+ # Clean up sys.path if we added to it
262
+ if sys_path_added:
263
+ sys.path.remove(module_dir)
264
+ raise ImportError(f"Failed to load service module: {e}")
265
+ finally:
266
+ # Clean up sys.path after successful load too
267
+ if sys_path_added and module_dir in sys.path:
268
+ sys.path.remove(module_dir)
150
269
 
151
- # Find the agent instance
152
- agent = None
270
+ # Find the service instance
271
+ service = None
153
272
 
154
- # If agent_class_name is specified, try to instantiate that specific class first
155
- if agent_class_name:
156
- if hasattr(module, agent_class_name):
157
- obj = getattr(module, agent_class_name)
158
- if isinstance(obj, type) and issubclass(obj, AgentBase) and obj != AgentBase:
273
+ # If service_identifier is specified and prefer_route is True, try to find by route first
274
+ if service_identifier and prefer_route:
275
+ # First, try to find an existing instance with matching route
276
+ for name, obj in vars(module).items():
277
+ if isinstance(obj, SWMLService) and hasattr(obj, 'route'):
278
+ if obj.route == service_identifier:
279
+ service = obj
280
+ break
281
+
282
+ # If not found, try instantiating classes to check their routes
283
+ if service is None:
284
+ for name, obj in vars(module).items():
285
+ if (isinstance(obj, type) and
286
+ issubclass(obj, SWMLService) and
287
+ obj not in (SWMLService, AgentBase)):
288
+ try:
289
+ temp_instance = obj()
290
+ if hasattr(temp_instance, 'route') and temp_instance.route == service_identifier:
291
+ service = temp_instance
292
+ break
293
+ except Exception:
294
+ # Skip classes that can't be instantiated
295
+ pass
296
+
297
+ # If still not found and service_identifier looks like a class name, fall back to class name
298
+ if service is None and hasattr(module, service_identifier):
299
+ obj = getattr(module, service_identifier)
300
+ if isinstance(obj, type) and issubclass(obj, SWMLService):
159
301
  try:
160
- agent = obj()
161
- if agent and not agent.route.endswith('dummy'): # Avoid test agents with dummy routes
162
- pass # Successfully created specific agent
302
+ service = obj()
303
+ except Exception as e:
304
+ raise ValueError(f"No service found with route '{service_identifier}' and failed to instantiate class '{service_identifier}': {e}")
305
+ elif isinstance(obj, SWMLService):
306
+ service = obj
307
+
308
+ if service is None:
309
+ raise ValueError(f"No service found with route '{service_identifier}'")
310
+
311
+ # If service_identifier is specified as a class name, try to instantiate that specific class first
312
+ elif service_identifier and not prefer_route:
313
+ if hasattr(module, service_identifier):
314
+ obj = getattr(module, service_identifier)
315
+ if isinstance(obj, type) and issubclass(obj, SWMLService):
316
+ try:
317
+ service = obj()
318
+ if service and not service.route.endswith('dummy'): # Avoid test services with dummy routes
319
+ pass # Successfully created specific service
163
320
  else:
164
- agent = obj() # Create anyway if requested specifically
321
+ service = obj() # Create anyway if requested specifically
165
322
  except Exception as e:
166
- raise ValueError(f"Failed to instantiate agent class '{agent_class_name}': {e}")
323
+ raise ValueError(f"Failed to instantiate service class '{service_identifier}': {e}")
324
+ elif isinstance(obj, SWMLService):
325
+ # It's already an instance
326
+ service = obj
167
327
  else:
168
- raise ValueError(f"'{agent_class_name}' is not a valid AgentBase subclass")
328
+ raise ValueError(f"'{service_identifier}' is not a valid SWMLService class or instance")
169
329
  else:
170
- raise ValueError(f"Agent class '{agent_class_name}' not found in {agent_path}")
330
+ raise ValueError(f"Service class '{service_identifier}' not found in {service_path}")
171
331
 
172
- # Strategy 1: Look for 'agent' variable (most common pattern)
173
- if agent is None and hasattr(module, 'agent') and isinstance(module.agent, AgentBase):
174
- agent = module.agent
332
+ # Strategy 1: Look for 'agent' or 'service' variable (most common pattern)
333
+ if service is None:
334
+ if hasattr(module, 'agent') and isinstance(module.agent, SWMLService):
335
+ service = module.agent
336
+ elif hasattr(module, 'service') and isinstance(module.service, SWMLService):
337
+ service = module.service
175
338
 
176
- # Strategy 2: Look for any AgentBase instance in module globals
177
- if agent is None:
178
- agents_found = []
339
+ # Strategy 2: Look for any SWMLService instance in module globals
340
+ if service is None:
341
+ services_found = []
179
342
  for name, obj in vars(module).items():
180
- if isinstance(obj, AgentBase):
181
- agents_found.append((name, obj))
343
+ if isinstance(obj, SWMLService):
344
+ services_found.append((name, obj))
182
345
 
183
- if len(agents_found) == 1:
184
- agent = agents_found[0][1]
185
- elif len(agents_found) > 1:
186
- # Multiple agents found, prefer one named 'agent'
187
- for name, obj in agents_found:
188
- if name == 'agent':
189
- agent = obj
346
+ if len(services_found) == 1:
347
+ service = services_found[0][1]
348
+ elif len(services_found) > 1:
349
+ # Multiple services found, prefer one named 'agent' or 'service'
350
+ for name, obj in services_found:
351
+ if name in ('agent', 'service'):
352
+ service = obj
190
353
  break
191
- # If no 'agent' variable, use the first one
192
- if agent is None:
193
- agent = agents_found[0][1]
194
- print(f"Warning: Multiple agents found, using '{agents_found[0][0]}'")
195
- print(f"Hint: Use --agent-class parameter to choose specific agent")
196
-
197
- # Strategy 3: Look for AgentBase subclass and try to instantiate it
198
- if agent is None:
199
- agent_classes_found = []
354
+ # If no preferred variable, use the first one
355
+ if service is None:
356
+ service = services_found[0][1]
357
+ print(f"Warning: Multiple services found, using '{services_found[0][0]}'")
358
+ print(f"Hint: Use --route or service identifier to choose specific service")
359
+
360
+ # Strategy 3: Look for SWMLService subclass and try to instantiate it
361
+ if service is None and not hasattr(module, 'main'):
362
+ service_classes_found = []
200
363
  for name, obj in vars(module).items():
201
364
  if (isinstance(obj, type) and
202
- issubclass(obj, AgentBase) and
203
- obj != AgentBase):
204
- agent_classes_found.append((name, obj))
365
+ issubclass(obj, SWMLService) and
366
+ obj not in (SWMLService, AgentBase)):
367
+ service_classes_found.append((name, obj))
205
368
 
206
- if len(agent_classes_found) == 1:
369
+ if len(service_classes_found) == 1:
207
370
  try:
208
- agent = agent_classes_found[0][1]()
371
+ service = service_classes_found[0][1]()
209
372
  except Exception as e:
210
- print(f"Warning: Failed to instantiate {agent_classes_found[0][0]}: {e}")
211
- elif len(agent_classes_found) > 1:
212
- # Multiple agent classes found
213
- class_names = [name for name, _ in agent_classes_found]
214
- raise ValueError(f"Multiple agent classes found: {', '.join(class_names)}. "
215
- f"Please specify which agent class to use with --agent-class parameter. "
216
- f"Usage: swaig-test {agent_path} [tool_name] [args] --agent-class <AgentClassName>")
373
+ print(f"Warning: Failed to instantiate {service_classes_found[0][0]}: {e}")
374
+ elif len(service_classes_found) > 1:
375
+ # Multiple service classes found - get detailed info
376
+ service_info = []
377
+ for name, cls in service_classes_found:
378
+ try:
379
+ # Try to instantiate temporarily to get route
380
+ temp_instance = cls()
381
+ route = getattr(temp_instance, 'route', 'Unknown')
382
+ service_name = getattr(temp_instance, 'name', 'Unknown')
383
+ service_info.append({
384
+ 'class_name': name,
385
+ 'route': route,
386
+ 'service_name': service_name
387
+ })
388
+ except Exception:
389
+ # If instantiation fails, still include the class
390
+ service_info.append({
391
+ 'class_name': name,
392
+ 'route': 'Unknown (instantiation failed)',
393
+ 'service_name': 'Unknown'
394
+ })
395
+
396
+ # Format error message with service details
397
+ error_lines = ["Multiple service classes found:"]
398
+ error_lines.append("")
399
+ for info in service_info:
400
+ error_lines.append(f" {info['class_name']}:")
401
+ error_lines.append(f" Route: {info['route']}")
402
+ error_lines.append(f" Name: {info['service_name']}")
403
+ error_lines.append("")
404
+ error_lines.append("Please specify which service to use:")
405
+ error_lines.append(f" swaig-test {service_path} --agent-class <ClassName>")
406
+ error_lines.append(f" swaig-test {service_path} --route <route>")
407
+
408
+ raise ValueError("\n".join(error_lines))
217
409
  else:
218
- # Try instantiating any AgentBase class we can find
410
+ # Try instantiating any SWMLService class we can find
219
411
  for name, obj in vars(module).items():
220
412
  if (isinstance(obj, type) and
221
- issubclass(obj, AgentBase) and
222
- obj != AgentBase):
413
+ issubclass(obj, SWMLService) and
414
+ obj not in (SWMLService, AgentBase)):
223
415
  try:
224
- agent = obj()
416
+ service = obj()
225
417
  break
226
418
  except Exception as e:
227
419
  print(f"Warning: Failed to instantiate {name}: {e}")
228
420
 
229
421
  # Strategy 4: Try calling a modified main() function that doesn't start the server
230
- if agent is None and hasattr(module, 'main'):
422
+ if service is None and hasattr(module, 'main'):
231
423
  print("Warning: No agent instance found, attempting to call main() without server startup")
232
424
  try:
233
- # Temporarily patch AgentBase.serve to prevent server startup
234
- original_serve = AgentBase.serve
235
- captured_agent = []
425
+ # Temporarily patch serve() and run() on both SWMLService and AgentBase
426
+ captured_services = []
427
+ patches_applied = []
236
428
 
237
429
  def mock_serve(self, *args, **kwargs):
238
- captured_agent.append(self)
239
- print(f" (Intercepted serve() call, agent captured for testing)")
430
+ captured_services.append(self)
431
+ print(f" (Intercepted serve() call, service captured for testing)")
432
+ return self
433
+
434
+ def mock_run(self, *args, **kwargs):
435
+ captured_services.append(self)
436
+ print(f" (Intercepted run() call, service captured for testing)")
240
437
  return self
241
438
 
242
- AgentBase.serve = mock_serve
439
+ # Apply patches to both base classes
440
+ for base_class in [SWMLService, AgentBase]:
441
+ if base_class:
442
+ if hasattr(base_class, 'serve'):
443
+ patches_applied.append((base_class, 'serve', base_class.serve))
444
+ base_class.serve = mock_serve
445
+ if hasattr(base_class, 'run'):
446
+ patches_applied.append((base_class, 'run', base_class.run))
447
+ base_class.run = mock_run
243
448
 
244
449
  try:
245
450
  result = module.main()
246
- if isinstance(result, AgentBase):
247
- agent = result
248
- elif captured_agent:
249
- agent = captured_agent[0]
451
+ if isinstance(result, SWMLService):
452
+ service = result
453
+ elif captured_services:
454
+ # Use the last captured service (most likely the configured one)
455
+ service = captured_services[-1]
250
456
  finally:
251
- # Restore original serve method
252
- AgentBase.serve = original_serve
457
+ # Restore original methods
458
+ for base_class, method_name, original_method in patches_applied:
459
+ setattr(base_class, method_name, original_method)
253
460
 
254
461
  except Exception as e:
255
462
  print(f"Warning: Failed to call main() function: {e}")
256
463
 
257
- if agent is None:
258
- raise ValueError(f"No agent found in {agent_path}. The file must contain either:\n"
259
- f"- An AgentBase instance (e.g., agent = MyAgent())\n"
260
- f"- An AgentBase subclass that can be instantiated\n"
261
- f"- A main() function that creates and returns an agent")
464
+ if service is None:
465
+ raise ValueError(f"No service found in {service_path}. The file must contain either:\n"
466
+ f"- A SWMLService instance (e.g., agent = MyAgent() or service = MyService())\n"
467
+ f"- A SWMLService subclass that can be instantiated\n"
468
+ f"- A main() function that creates and returns a service")
262
469
 
263
- return agent
470
+ return service
@@ -144,7 +144,13 @@ def parse_function_arguments(function_args_list: List[str], func_schema: Dict[st
144
144
  else:
145
145
  # Need a value
146
146
  if i + 1 >= len(function_args_list):
147
- raise ValueError(f"Parameter --{param_name} requires a value")
147
+ # Check if this looks like a CLI flag that was misplaced
148
+ if param_name in ['verbose', 'raw', 'help', 'list-tools', 'list-agents', 'dump-swml',
149
+ 'minimal', 'fake-full-data', 'simulate-serverless', 'agent-class', 'route']:
150
+ raise ValueError(f"CLI flag --{param_name} must come BEFORE --exec, not after.\n"
151
+ f"Example: swaig-test file.py --{param_name} --exec function_name")
152
+ else:
153
+ raise ValueError(f"Parameter --{param_name} requires a value")
148
154
 
149
155
  value = function_args_list[i + 1]
150
156