signalwire-agents 0.1.17__py3-none-any.whl → 0.1.19__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.
- signalwire_agents/__init__.py +1 -1
- signalwire_agents/cli/build_search.py +152 -4
- signalwire_agents/cli/test_swaig.py +285 -142
- signalwire_agents/core/agent_base.py +77 -4
- signalwire_agents/core/contexts.py +333 -0
- signalwire_agents/core/swml_handler.py +27 -21
- signalwire_agents/skills/datasphere_serverless/skill.py +0 -1
- signalwire_agents/skills/web_search/skill.py +1 -1
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/METADATA +43 -30
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/RECORD +15 -15
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/entry_points.txt +1 -1
- {signalwire_agents-0.1.17.data → signalwire_agents-0.1.19.data}/data/schema.json +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/top_level.txt +0 -0
signalwire_agents/__init__.py
CHANGED
@@ -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.
|
21
|
+
__version__ = "0.1.19"
|
22
22
|
|
23
23
|
# Import core classes for easier access
|
24
24
|
from .core.agent_base import AgentBase
|
@@ -85,6 +85,10 @@ Examples:
|
|
85
85
|
sw-search search ./docs.swsearch "how to create an agent"
|
86
86
|
sw-search search ./docs.swsearch "API reference" --count 3 --verbose
|
87
87
|
sw-search search ./docs.swsearch "configuration" --tags documentation --json
|
88
|
+
|
89
|
+
# Search via remote API
|
90
|
+
sw-search remote http://localhost:8001 "how to create an agent" --index-name docs
|
91
|
+
sw-search remote localhost:8001 "API reference" --index-name docs --count 3 --verbose
|
88
92
|
"""
|
89
93
|
)
|
90
94
|
|
@@ -263,7 +267,7 @@ Examples:
|
|
263
267
|
|
264
268
|
try:
|
265
269
|
# Create index builder - import only when actually needed
|
266
|
-
from
|
270
|
+
from signalwire_agents.search.index_builder import IndexBuilder
|
267
271
|
builder = IndexBuilder(
|
268
272
|
model_name=args.model,
|
269
273
|
chunking_strategy=args.chunking_strategy,
|
@@ -328,7 +332,7 @@ def validate_command():
|
|
328
332
|
sys.exit(1)
|
329
333
|
|
330
334
|
try:
|
331
|
-
from
|
335
|
+
from signalwire_agents.search.index_builder import IndexBuilder
|
332
336
|
builder = IndexBuilder()
|
333
337
|
|
334
338
|
validation = builder.validate_index(args.index_file)
|
@@ -376,8 +380,8 @@ def search_command():
|
|
376
380
|
try:
|
377
381
|
# Import search dependencies
|
378
382
|
try:
|
379
|
-
from
|
380
|
-
from
|
383
|
+
from signalwire_agents.search.search_engine import SearchEngine
|
384
|
+
from signalwire_agents.search.query_processor import preprocess_query
|
381
385
|
except ImportError as e:
|
382
386
|
print(f"Error: Search functionality not available. Install with: pip install signalwire-agents[search]")
|
383
387
|
print(f"Details: {e}")
|
@@ -478,6 +482,141 @@ def search_command():
|
|
478
482
|
traceback.print_exc()
|
479
483
|
sys.exit(1)
|
480
484
|
|
485
|
+
def remote_command():
|
486
|
+
"""Search via remote API endpoint"""
|
487
|
+
parser = argparse.ArgumentParser(description='Search via remote API endpoint')
|
488
|
+
parser.add_argument('endpoint', help='Remote API endpoint URL (e.g., http://localhost:8001)')
|
489
|
+
parser.add_argument('query', help='Search query')
|
490
|
+
parser.add_argument('--index-name', required=True, help='Name of the index to search')
|
491
|
+
parser.add_argument('--count', type=int, default=5, help='Number of results to return (default: 5)')
|
492
|
+
parser.add_argument('--distance-threshold', type=float, default=0.0, help='Minimum similarity score (default: 0.0)')
|
493
|
+
parser.add_argument('--tags', help='Comma-separated tags to filter by')
|
494
|
+
parser.add_argument('--verbose', action='store_true', help='Show detailed information')
|
495
|
+
parser.add_argument('--json', action='store_true', help='Output results as JSON')
|
496
|
+
parser.add_argument('--no-content', action='store_true', help='Hide content in results (show only metadata)')
|
497
|
+
parser.add_argument('--timeout', type=int, default=30, help='Request timeout in seconds (default: 30)')
|
498
|
+
|
499
|
+
args = parser.parse_args()
|
500
|
+
|
501
|
+
# Ensure endpoint starts with http:// or https://
|
502
|
+
endpoint = args.endpoint
|
503
|
+
if not endpoint.startswith(('http://', 'https://')):
|
504
|
+
endpoint = f"http://{endpoint}"
|
505
|
+
|
506
|
+
# Ensure endpoint ends with /search
|
507
|
+
if not endpoint.endswith('/search'):
|
508
|
+
if endpoint.endswith('/'):
|
509
|
+
endpoint += 'search'
|
510
|
+
else:
|
511
|
+
endpoint += '/search'
|
512
|
+
|
513
|
+
try:
|
514
|
+
import requests
|
515
|
+
except ImportError:
|
516
|
+
print("Error: requests library not available. Install with: pip install requests")
|
517
|
+
sys.exit(1)
|
518
|
+
|
519
|
+
# Prepare request payload
|
520
|
+
payload = {
|
521
|
+
'query': args.query,
|
522
|
+
'index_name': args.index_name,
|
523
|
+
'count': args.count,
|
524
|
+
'distance_threshold': args.distance_threshold
|
525
|
+
}
|
526
|
+
|
527
|
+
if args.tags:
|
528
|
+
payload['tags'] = [tag.strip() for tag in args.tags.split(',')]
|
529
|
+
|
530
|
+
if args.verbose:
|
531
|
+
print(f"Searching remote endpoint: {endpoint}")
|
532
|
+
print(f"Payload: {payload}")
|
533
|
+
print()
|
534
|
+
|
535
|
+
try:
|
536
|
+
# Make the API request
|
537
|
+
response = requests.post(
|
538
|
+
endpoint,
|
539
|
+
json=payload,
|
540
|
+
headers={'Content-Type': 'application/json'},
|
541
|
+
timeout=args.timeout
|
542
|
+
)
|
543
|
+
|
544
|
+
if response.status_code == 200:
|
545
|
+
result = response.json()
|
546
|
+
|
547
|
+
if args.json:
|
548
|
+
# Output raw JSON response
|
549
|
+
import json
|
550
|
+
print(json.dumps(result, indent=2))
|
551
|
+
else:
|
552
|
+
# Human-readable output
|
553
|
+
results = result.get('results', [])
|
554
|
+
if not results:
|
555
|
+
print(f"No results found for '{args.query}' in index '{args.index_name}'")
|
556
|
+
sys.exit(0)
|
557
|
+
|
558
|
+
print(f"Found {len(results)} result(s) for '{args.query}' in index '{args.index_name}':")
|
559
|
+
if result.get('enhanced_query') and result.get('enhanced_query') != args.query:
|
560
|
+
print(f"Enhanced query: '{result.get('enhanced_query')}'")
|
561
|
+
print("=" * 80)
|
562
|
+
|
563
|
+
for i, search_result in enumerate(results):
|
564
|
+
print(f"\n[{i+1}] Score: {search_result.get('score', 0):.4f}")
|
565
|
+
|
566
|
+
# Show metadata
|
567
|
+
metadata = search_result.get('metadata', {})
|
568
|
+
print(f"File: {metadata.get('filename', 'Unknown')}")
|
569
|
+
if metadata.get('section'):
|
570
|
+
print(f"Section: {metadata['section']}")
|
571
|
+
if metadata.get('line_start'):
|
572
|
+
print(f"Lines: {metadata['line_start']}-{metadata.get('line_end', metadata['line_start'])}")
|
573
|
+
if metadata.get('tags'):
|
574
|
+
print(f"Tags: {', '.join(metadata['tags'])}")
|
575
|
+
|
576
|
+
# Show content unless suppressed
|
577
|
+
if not args.no_content and 'content' in search_result:
|
578
|
+
content = search_result['content']
|
579
|
+
if len(content) > 500 and not args.verbose:
|
580
|
+
content = content[:500] + "..."
|
581
|
+
print(f"\nContent:\n{content}")
|
582
|
+
|
583
|
+
if i < len(results) - 1:
|
584
|
+
print("-" * 80)
|
585
|
+
|
586
|
+
elif response.status_code == 404:
|
587
|
+
try:
|
588
|
+
error_detail = response.json()
|
589
|
+
error_msg = error_detail.get('detail', 'Index not found')
|
590
|
+
except:
|
591
|
+
error_msg = 'Index not found'
|
592
|
+
print(f"Error: {error_msg}")
|
593
|
+
sys.exit(1)
|
594
|
+
else:
|
595
|
+
try:
|
596
|
+
error_detail = response.json()
|
597
|
+
error_msg = error_detail.get('detail', f'HTTP {response.status_code}')
|
598
|
+
except:
|
599
|
+
error_msg = f'HTTP {response.status_code}: {response.text}'
|
600
|
+
print(f"Error: {error_msg}")
|
601
|
+
sys.exit(1)
|
602
|
+
|
603
|
+
except requests.ConnectionError:
|
604
|
+
print(f"Error: Could not connect to {endpoint}")
|
605
|
+
print("Make sure the search server is running")
|
606
|
+
sys.exit(1)
|
607
|
+
except requests.Timeout:
|
608
|
+
print(f"Error: Request timed out after {args.timeout} seconds")
|
609
|
+
sys.exit(1)
|
610
|
+
except requests.RequestException as e:
|
611
|
+
print(f"Error making request: {e}")
|
612
|
+
sys.exit(1)
|
613
|
+
except Exception as e:
|
614
|
+
print(f"Error: {e}")
|
615
|
+
if args.verbose:
|
616
|
+
import traceback
|
617
|
+
traceback.print_exc()
|
618
|
+
sys.exit(1)
|
619
|
+
|
481
620
|
def console_entry_point():
|
482
621
|
"""Console script entry point for pip installation"""
|
483
622
|
import sys
|
@@ -594,6 +733,10 @@ Examples:
|
|
594
733
|
sw-search search ./docs.swsearch "how to create an agent"
|
595
734
|
sw-search search ./docs.swsearch "API reference" --count 3 --verbose
|
596
735
|
sw-search search ./docs.swsearch "configuration" --tags documentation --json
|
736
|
+
|
737
|
+
# Search via remote API
|
738
|
+
sw-search remote http://localhost:8001 "how to create an agent" --index-name docs
|
739
|
+
sw-search remote localhost:8001 "API reference" --index-name docs --count 3 --verbose
|
597
740
|
""")
|
598
741
|
return
|
599
742
|
|
@@ -609,6 +752,11 @@ Examples:
|
|
609
752
|
sys.argv.pop(1)
|
610
753
|
search_command()
|
611
754
|
return
|
755
|
+
elif sys.argv[1] == 'remote':
|
756
|
+
# Remove 'remote' from argv and call remote_command
|
757
|
+
sys.argv.pop(1)
|
758
|
+
remote_command()
|
759
|
+
return
|
612
760
|
|
613
761
|
# Regular build command
|
614
762
|
main()
|