signalwire-agents 0.1.13__py3-none-any.whl → 0.1.15__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.
@@ -46,8 +46,14 @@ Examples:
46
46
  swaig-test examples/my_agent.py --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions'
47
47
  """
48
48
 
49
+ # CRITICAL: Set environment variable BEFORE any imports to suppress logs for --raw
49
50
  import sys
50
51
  import os
52
+
53
+ if "--raw" in sys.argv or "--dump-swml" in sys.argv:
54
+ os.environ["SIGNALWIRE_LOG_MODE"] = "off"
55
+
56
+ import warnings
51
57
  import json
52
58
  import importlib.util
53
59
  import argparse
@@ -56,13 +62,18 @@ import time
56
62
  import hashlib
57
63
  import re
58
64
  import requests
59
- import warnings
60
65
  from pathlib import Path
61
66
  from typing import Dict, Any, Optional, List, Tuple
62
67
  from datetime import datetime
63
68
  import logging
64
69
  import inspect
65
70
 
71
+ # Store original print function before any potential suppression
72
+ original_print = print
73
+
74
+ # Add the parent directory to the path so we can import signalwire_agents
75
+ sys.path.insert(0, str(Path(__file__).parent.parent.parent))
76
+
66
77
  try:
67
78
  # Try to import the AgentBase class
68
79
  from signalwire_agents.core.agent_base import AgentBase
@@ -72,22 +83,15 @@ except ImportError:
72
83
  AgentBase = None
73
84
  SwaigFunctionResult = None
74
85
 
75
- # Early setup for raw mode using the central logging system
76
- if "--raw" in sys.argv:
77
- # Use the central logging system's OFF mode for raw output
78
- # This eliminates all logging output without complex suppression hacks
79
- os.environ["SIGNALWIRE_LOG_MODE"] = "off"
80
- warnings.filterwarnings("ignore")
81
-
82
- # Store original print function before any potential suppression
83
- original_print = print
84
-
85
- # Add the parent directory to the path so we can import signalwire_agents
86
- sys.path.insert(0, str(Path(__file__).parent.parent.parent))
87
-
88
- from signalwire_agents import AgentBase
89
- from signalwire_agents.core.function_result import SwaigFunctionResult
90
-
86
+ # Reset logging configuration if --raw flag was set
87
+ # This must happen AFTER signalwire_agents imports but BEFORE any logging is used
88
+ if "--raw" in sys.argv or "--dump-swml" in sys.argv:
89
+ try:
90
+ from signalwire_agents.core.logging_config import reset_logging_configuration, configure_logging
91
+ reset_logging_configuration()
92
+ configure_logging() # Reconfigure with the new environment variable
93
+ except ImportError:
94
+ pass
91
95
 
92
96
  # ===== MOCK REQUEST OBJECTS FOR DYNAMIC AGENT TESTING =====
93
97
 
@@ -666,7 +670,6 @@ def handle_dump_swml(agent: 'AgentBase', args: argparse.Namespace) -> int:
666
670
  Exit code (0 for success, 1 for error)
667
671
  """
668
672
  if not args.raw:
669
- print("\nGenerating SWML document...")
670
673
  if args.verbose:
671
674
  print(f"Agent: {agent.get_name()}")
672
675
  print(f"Route: {agent.route}")
@@ -767,20 +770,13 @@ def handle_dump_swml(agent: 'AgentBase', args: argparse.Namespace) -> int:
767
770
  # Output only the raw JSON for piping to jq/yq
768
771
  print(swml_doc)
769
772
  else:
770
- # Normal output with headers
771
- print("SWML Document:")
772
- print("=" * 50)
773
- print(swml_doc)
774
- print("=" * 50)
775
-
776
- if args.verbose:
777
- # Parse and show formatted JSON for better readability
778
- try:
779
- swml_parsed = json.loads(swml_doc)
780
- print("\nFormatted SWML:")
781
- print(json.dumps(swml_parsed, indent=2))
782
- except json.JSONDecodeError:
783
- print("\nNote: SWML document is not valid JSON format")
773
+ # Output formatted JSON (like raw but pretty-printed)
774
+ try:
775
+ swml_parsed = json.loads(swml_doc)
776
+ print(json.dumps(swml_parsed, indent=2))
777
+ except json.JSONDecodeError:
778
+ # If not valid JSON, show raw
779
+ print(swml_doc)
784
780
 
785
781
  return 0
786
782
 
@@ -1375,6 +1371,94 @@ def execute_external_webhook_function(func: 'SWAIGFunction', function_name: str,
1375
1371
  return {"error": error_msg}
1376
1372
 
1377
1373
 
1374
+ def display_agent_tools(agent: 'AgentBase', verbose: bool = False) -> None:
1375
+ """
1376
+ Display the available SWAIG functions for an agent
1377
+
1378
+ Args:
1379
+ agent: The agent instance
1380
+ verbose: Whether to show verbose details
1381
+ """
1382
+ print("\nAvailable SWAIG functions:")
1383
+ if hasattr(agent, '_swaig_functions') and agent._swaig_functions:
1384
+ for name, func in agent._swaig_functions.items():
1385
+ if isinstance(func, dict):
1386
+ # DataMap function
1387
+ description = func.get('description', 'DataMap function (serverless)')
1388
+ print(f" {name} - {description}")
1389
+
1390
+ # Show parameters for DataMap functions
1391
+ if 'parameters' in func and func['parameters']:
1392
+ params = func['parameters']
1393
+ # Handle both formats: direct properties dict or full schema
1394
+ if 'properties' in params:
1395
+ properties = params['properties']
1396
+ required_fields = params.get('required', [])
1397
+ else:
1398
+ properties = params
1399
+ required_fields = []
1400
+
1401
+ if properties:
1402
+ print(f" Parameters:")
1403
+ for param_name, param_def in properties.items():
1404
+ param_type = param_def.get('type', 'unknown')
1405
+ param_desc = param_def.get('description', 'No description')
1406
+ is_required = param_name in required_fields
1407
+ required_marker = " (required)" if is_required else ""
1408
+ print(f" {param_name} ({param_type}){required_marker}: {param_desc}")
1409
+ else:
1410
+ print(f" Parameters: None")
1411
+ else:
1412
+ print(f" Parameters: None")
1413
+
1414
+ if verbose:
1415
+ print(f" Config: {json.dumps(func, indent=6)}")
1416
+ else:
1417
+ # Regular SWAIG function
1418
+ func_type = ""
1419
+ if hasattr(func, 'webhook_url') and func.webhook_url and func.is_external:
1420
+ func_type = " (EXTERNAL webhook)"
1421
+ elif hasattr(func, 'webhook_url') and func.webhook_url:
1422
+ func_type = " (webhook)"
1423
+ else:
1424
+ func_type = " (LOCAL webhook)"
1425
+
1426
+ print(f" {name} - {func.description}{func_type}")
1427
+
1428
+ # Show external URL if applicable
1429
+ if hasattr(func, 'webhook_url') and func.webhook_url and func.is_external:
1430
+ print(f" External URL: {func.webhook_url}")
1431
+
1432
+ # Show parameters
1433
+ if hasattr(func, 'parameters') and func.parameters:
1434
+ params = func.parameters
1435
+ # Handle both formats: direct properties dict or full schema
1436
+ if 'properties' in params:
1437
+ properties = params['properties']
1438
+ required_fields = params.get('required', [])
1439
+ else:
1440
+ properties = params
1441
+ required_fields = []
1442
+
1443
+ if properties:
1444
+ print(f" Parameters:")
1445
+ for param_name, param_def in properties.items():
1446
+ param_type = param_def.get('type', 'unknown')
1447
+ param_desc = param_def.get('description', 'No description')
1448
+ is_required = param_name in required_fields
1449
+ required_marker = " (required)" if is_required else ""
1450
+ print(f" {param_name} ({param_type}){required_marker}: {param_desc}")
1451
+ else:
1452
+ print(f" Parameters: None")
1453
+ else:
1454
+ print(f" Parameters: None")
1455
+
1456
+ if verbose:
1457
+ print(f" Function object: {func}")
1458
+ else:
1459
+ print(" No SWAIG functions registered")
1460
+
1461
+
1378
1462
  def discover_agents_in_file(agent_path: str) -> List[Dict[str, Any]]:
1379
1463
  """
1380
1464
  Discover all available agents in a Python file without instantiating them
@@ -2315,7 +2399,29 @@ Examples:
2315
2399
 
2316
2400
  print()
2317
2401
 
2318
- if len(agents) > 1:
2402
+ # Show tools if there's only one agent or if --agent-class is specified
2403
+ show_tools = False
2404
+ selected_agent = None
2405
+
2406
+ if len(agents) == 1:
2407
+ # Single agent - show tools automatically
2408
+ show_tools = True
2409
+ selected_agent = agents[0]['object']
2410
+ print("This file contains a single agent, no --agent-class needed.")
2411
+ elif args.agent_class:
2412
+ # Specific agent class requested - show tools for that agent
2413
+ for agent_info in agents:
2414
+ if agent_info['class_name'] == args.agent_class:
2415
+ show_tools = True
2416
+ selected_agent = agent_info['object']
2417
+ break
2418
+
2419
+ if not selected_agent:
2420
+ print(f"Error: Agent class '{args.agent_class}' not found.")
2421
+ print(f"Available agents: {[a['class_name'] for a in agents]}")
2422
+ return 1
2423
+ else:
2424
+ # Multiple agents, no specific class - show usage examples
2319
2425
  print("To use a specific agent with this tool:")
2320
2426
  print(f" swaig-test {args.agent_path} [tool_name] [args] --agent-class <AgentClassName>")
2321
2427
  print()
@@ -2324,8 +2430,24 @@ Examples:
2324
2430
  print(f" swaig-test {args.agent_path} --list-tools --agent-class {agent_info['class_name']}")
2325
2431
  print(f" swaig-test {args.agent_path} --dump-swml --agent-class {agent_info['class_name']}")
2326
2432
  print()
2327
- else:
2328
- print("This file contains a single agent, no --agent-class needed.")
2433
+
2434
+ # Show tools if we have a selected agent
2435
+ if show_tools and selected_agent:
2436
+ try:
2437
+ # If it's a class, try to instantiate it
2438
+ if not isinstance(selected_agent, AgentBase):
2439
+ if isinstance(selected_agent, type) and issubclass(selected_agent, AgentBase):
2440
+ selected_agent = selected_agent()
2441
+ else:
2442
+ print(f"Warning: Cannot instantiate agent to show tools")
2443
+ return 0
2444
+
2445
+ display_agent_tools(selected_agent, args.verbose)
2446
+ except Exception as e:
2447
+ print(f"Warning: Could not load agent tools: {e}")
2448
+ if args.verbose:
2449
+ import traceback
2450
+ traceback.print_exc()
2329
2451
 
2330
2452
  return 0
2331
2453
 
@@ -2374,84 +2496,7 @@ Examples:
2374
2496
 
2375
2497
  # List tools if requested
2376
2498
  if args.list_tools:
2377
- print("\nAvailable SWAIG functions:")
2378
- if hasattr(agent, '_swaig_functions') and agent._swaig_functions:
2379
- for name, func in agent._swaig_functions.items():
2380
- if isinstance(func, dict):
2381
- # DataMap function
2382
- description = func.get('description', 'DataMap function (serverless)')
2383
- print(f" {name} - {description}")
2384
-
2385
- # Show parameters for DataMap functions
2386
- if 'parameters' in func and func['parameters']:
2387
- params = func['parameters']
2388
- # Handle both formats: direct properties dict or full schema
2389
- if 'properties' in params:
2390
- properties = params['properties']
2391
- required_fields = params.get('required', [])
2392
- else:
2393
- properties = params
2394
- required_fields = []
2395
-
2396
- if properties:
2397
- print(f" Parameters:")
2398
- for param_name, param_def in properties.items():
2399
- param_type = param_def.get('type', 'unknown')
2400
- param_desc = param_def.get('description', 'No description')
2401
- is_required = param_name in required_fields
2402
- required_marker = " (required)" if is_required else ""
2403
- print(f" {param_name} ({param_type}){required_marker}: {param_desc}")
2404
- else:
2405
- print(f" Parameters: None")
2406
- else:
2407
- print(f" Parameters: None")
2408
-
2409
- if args.verbose:
2410
- print(f" Config: {json.dumps(func, indent=6)}")
2411
- else:
2412
- # Regular SWAIG function
2413
- func_type = ""
2414
- if hasattr(func, 'webhook_url') and func.webhook_url and func.is_external:
2415
- func_type = " (EXTERNAL webhook)"
2416
- elif hasattr(func, 'webhook_url') and func.webhook_url:
2417
- func_type = " (webhook)"
2418
- else:
2419
- func_type = " (LOCAL webhook)"
2420
-
2421
- print(f" {name} - {func.description}{func_type}")
2422
-
2423
- # Show external URL if applicable
2424
- if hasattr(func, 'webhook_url') and func.webhook_url and func.is_external:
2425
- print(f" External URL: {func.webhook_url}")
2426
-
2427
- # Show parameters
2428
- if hasattr(func, 'parameters') and func.parameters:
2429
- params = func.parameters
2430
- # Handle both formats: direct properties dict or full schema
2431
- if 'properties' in params:
2432
- properties = params['properties']
2433
- required_fields = params.get('required', [])
2434
- else:
2435
- properties = params
2436
- required_fields = []
2437
-
2438
- if properties:
2439
- print(f" Parameters:")
2440
- for param_name, param_def in properties.items():
2441
- param_type = param_def.get('type', 'unknown')
2442
- param_desc = param_def.get('description', 'No description')
2443
- is_required = param_name in required_fields
2444
- required_marker = " (required)" if is_required else ""
2445
- print(f" {param_name} ({param_type}){required_marker}: {param_desc}")
2446
- else:
2447
- print(f" Parameters: None")
2448
- else:
2449
- print(f" Parameters: None")
2450
-
2451
- if args.verbose:
2452
- print(f" Function object: {func}")
2453
- else:
2454
- print(" No SWAIG functions registered")
2499
+ display_agent_tools(agent, args.verbose)
2455
2500
  return 0
2456
2501
 
2457
2502
  # Dump SWML if requested
@@ -2606,4 +2651,4 @@ def console_entry_point():
2606
2651
 
2607
2652
 
2608
2653
  if __name__ == "__main__":
2609
- sys.exit(main())
2654
+ sys.exit(main())