signalwire-agents 0.1.11__tar.gz → 0.1.12__tar.gz

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.
Files changed (76) hide show
  1. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/PKG-INFO +110 -3
  2. signalwire_agents-0.1.11/signalwire_agents.egg-info/PKG-INFO → signalwire_agents-0.1.12/README.md +73 -32
  3. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/pyproject.toml +53 -2
  4. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/__init__.py +5 -1
  5. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/agent_server.py +222 -13
  6. signalwire_agents-0.1.12/signalwire_agents/cli/build_search.py +457 -0
  7. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/cli/test_swaig.py +177 -113
  8. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/agent_base.py +1 -1
  9. signalwire_agents-0.1.12/signalwire_agents/core/logging_config.py +232 -0
  10. signalwire_agents-0.1.12/signalwire_agents/search/__init__.py +131 -0
  11. signalwire_agents-0.1.12/signalwire_agents/search/document_processor.py +764 -0
  12. signalwire_agents-0.1.12/signalwire_agents/search/index_builder.py +534 -0
  13. signalwire_agents-0.1.12/signalwire_agents/search/query_processor.py +371 -0
  14. signalwire_agents-0.1.12/signalwire_agents/search/search_engine.py +383 -0
  15. signalwire_agents-0.1.12/signalwire_agents/search/search_service.py +251 -0
  16. signalwire_agents-0.1.12/signalwire_agents/skills/native_vector_search/__init__.py +1 -0
  17. signalwire_agents-0.1.12/signalwire_agents/skills/native_vector_search/skill.py +352 -0
  18. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/registry.py +2 -15
  19. signalwire_agents-0.1.12/signalwire_agents/utils/__init__.py +23 -0
  20. signalwire_agents-0.1.11/README.md → signalwire_agents-0.1.12/signalwire_agents.egg-info/PKG-INFO +139 -2
  21. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/SOURCES.txt +10 -1
  22. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/entry_points.txt +1 -0
  23. signalwire_agents-0.1.12/signalwire_agents.egg-info/requires.txt +50 -0
  24. signalwire_agents-0.1.11/signalwire_agents/utils/__init__.py +0 -11
  25. signalwire_agents-0.1.11/signalwire_agents/utils/serverless.py +0 -38
  26. signalwire_agents-0.1.11/signalwire_agents.egg-info/requires.txt +0 -10
  27. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/LICENSE +0 -0
  28. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/schema.json +0 -0
  29. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/setup.cfg +0 -0
  30. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/setup.py +0 -0
  31. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/cli/__init__.py +0 -0
  32. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/__init__.py +0 -0
  33. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/contexts.py +0 -0
  34. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/data_map.py +0 -0
  35. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/function_result.py +0 -0
  36. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/pom_builder.py +0 -0
  37. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/security/__init__.py +0 -0
  38. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/security/session_manager.py +0 -0
  39. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/skill_base.py +0 -0
  40. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/skill_manager.py +0 -0
  41. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/__init__.py +0 -0
  42. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/file_state_manager.py +0 -0
  43. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/state_manager.py +0 -0
  44. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swaig_function.py +0 -0
  45. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_builder.py +0 -0
  46. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_handler.py +0 -0
  47. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_renderer.py +0 -0
  48. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_service.py +0 -0
  49. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/__init__.py +0 -0
  50. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/concierge.py +0 -0
  51. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/faq_bot.py +0 -0
  52. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/info_gatherer.py +0 -0
  53. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/receptionist.py +0 -0
  54. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/survey.py +0 -0
  55. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/schema.json +0 -0
  56. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/__init__.py +0 -0
  57. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere/__init__.py +0 -0
  58. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere/skill.py +0 -0
  59. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere_serverless/__init__.py +0 -0
  60. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere_serverless/skill.py +0 -0
  61. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datetime/__init__.py +0 -0
  62. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datetime/skill.py +0 -0
  63. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/joke/__init__.py +0 -0
  64. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/joke/skill.py +0 -0
  65. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/math/__init__.py +0 -0
  66. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/math/skill.py +0 -0
  67. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/web_search/__init__.py +0 -0
  68. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/web_search/skill.py +0 -0
  69. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/wikipedia/__init__.py +0 -0
  70. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/wikipedia/skill.py +0 -0
  71. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/pom_utils.py +0 -0
  72. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/schema_utils.py +0 -0
  73. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/token_generators.py +0 -0
  74. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/validators.py +0 -0
  75. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/dependency_links.txt +0 -0
  76. {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  Project-URL: Homepage, https://github.com/signalwire/signalwire-ai-agents
@@ -26,6 +26,42 @@ Requires-Dist: structlog==25.3.0
26
26
  Requires-Dist: uvicorn==0.34.2
27
27
  Requires-Dist: beautifulsoup4==4.12.3
28
28
  Requires-Dist: pytz==2023.3
29
+ Provides-Extra: search
30
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "search"
31
+ Requires-Dist: scikit-learn>=1.3.0; extra == "search"
32
+ Requires-Dist: nltk>=3.8; extra == "search"
33
+ Requires-Dist: numpy>=1.24.0; extra == "search"
34
+ Provides-Extra: search-full
35
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "search-full"
36
+ Requires-Dist: scikit-learn>=1.3.0; extra == "search-full"
37
+ Requires-Dist: nltk>=3.8; extra == "search-full"
38
+ Requires-Dist: numpy>=1.24.0; extra == "search-full"
39
+ Requires-Dist: pdfplumber>=0.9.0; extra == "search-full"
40
+ Requires-Dist: python-docx>=0.8.11; extra == "search-full"
41
+ Requires-Dist: markdown>=3.4.0; extra == "search-full"
42
+ Requires-Dist: striprtf>=0.0.26; extra == "search-full"
43
+ Requires-Dist: openpyxl>=3.1.0; extra == "search-full"
44
+ Requires-Dist: python-pptx>=0.6.21; extra == "search-full"
45
+ Requires-Dist: python-magic>=0.4.27; extra == "search-full"
46
+ Provides-Extra: search-nlp
47
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "search-nlp"
48
+ Requires-Dist: scikit-learn>=1.3.0; extra == "search-nlp"
49
+ Requires-Dist: nltk>=3.8; extra == "search-nlp"
50
+ Requires-Dist: numpy>=1.24.0; extra == "search-nlp"
51
+ Requires-Dist: spacy>=3.6.0; extra == "search-nlp"
52
+ Provides-Extra: search-all
53
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "search-all"
54
+ Requires-Dist: scikit-learn>=1.3.0; extra == "search-all"
55
+ Requires-Dist: nltk>=3.8; extra == "search-all"
56
+ Requires-Dist: numpy>=1.24.0; extra == "search-all"
57
+ Requires-Dist: spacy>=3.6.0; extra == "search-all"
58
+ Requires-Dist: pdfplumber>=0.9.0; extra == "search-all"
59
+ Requires-Dist: python-docx>=0.8.11; extra == "search-all"
60
+ Requires-Dist: markdown>=3.4.0; extra == "search-all"
61
+ Requires-Dist: striprtf>=0.0.26; extra == "search-all"
62
+ Requires-Dist: openpyxl>=3.1.0; extra == "search-all"
63
+ Requires-Dist: python-pptx>=0.6.21; extra == "search-all"
64
+ Requires-Dist: python-magic>=0.4.27; extra == "search-all"
29
65
  Dynamic: license-file
30
66
 
31
67
  # SignalWire AI Agent SDK
@@ -45,6 +81,7 @@ A Python SDK for creating, hosting, and securing SignalWire AI agents as microse
45
81
  - **Prefab Archetypes**: Ready-to-use agent types for common scenarios
46
82
  - **Multi-Agent Support**: Host multiple agents on a single server
47
83
  - **Modular Skills System**: Add capabilities to agents with simple one-liner calls
84
+ - **Local Search System**: Offline document search with vector similarity and keyword search
48
85
 
49
86
  ## Skills System
50
87
 
@@ -124,6 +161,7 @@ agent.serve()
124
161
  - **datetime**: Current date and time with timezone support
125
162
  - **math**: Safe mathematical expression evaluation
126
163
  - **datasphere**: SignalWire DataSphere knowledge search (supports multiple instances)
164
+ - **native_vector_search**: Offline document search with vector similarity and keyword search
127
165
 
128
166
  ### Benefits
129
167
 
@@ -424,10 +462,73 @@ For detailed documentation and advanced examples, see [Contexts and Steps Guide]
424
462
 
425
463
  ## Installation
426
464
 
465
+ ### Basic Installation
466
+
427
467
  ```bash
428
468
  pip install signalwire-agents
429
469
  ```
430
470
 
471
+ ### Optional Search Functionality
472
+
473
+ The SDK includes optional local search capabilities that can be installed separately to avoid adding large dependencies to the base installation:
474
+
475
+ #### Search Installation Options
476
+
477
+ ```bash
478
+ # Basic search (vector search + keyword search)
479
+ pip install signalwire-agents[search]
480
+
481
+ # Full search with document processing (PDF, DOCX, etc.)
482
+ pip install signalwire-agents[search-full]
483
+
484
+ # Advanced NLP features (includes spaCy)
485
+ pip install signalwire-agents[search-nlp]
486
+
487
+ # All search features
488
+ pip install signalwire-agents[search-all]
489
+ ```
490
+
491
+ #### What Each Option Includes
492
+
493
+ | Option | Size | Features |
494
+ |--------|------|----------|
495
+ | `search` | ~500MB | Vector embeddings, keyword search, basic text processing |
496
+ | `search-full` | ~600MB | + PDF, DOCX, Excel, PowerPoint, HTML, Markdown processing |
497
+ | `search-nlp` | ~600MB | + Advanced spaCy NLP features |
498
+ | `search-all` | ~700MB | All search features combined |
499
+
500
+ #### Search Features
501
+
502
+ - **Local/Offline Search**: No external API dependencies
503
+ - **Hybrid Search**: Vector similarity + keyword search
504
+ - **Smart Document Processing**: Markdown, Python, PDF, DOCX, etc.
505
+ - **Multiple Languages**: English, Spanish, with extensible framework
506
+ - **CLI Tools**: Build search indexes from document directories
507
+ - **HTTP API**: Standalone or embedded search service
508
+
509
+ #### Usage Example
510
+
511
+ ```python
512
+ # Only available with search extras installed
513
+ from signalwire_agents.search import IndexBuilder, SearchEngine
514
+
515
+ # Build search index
516
+ builder = IndexBuilder()
517
+ builder.build_index(
518
+ source_dir="./docs",
519
+ output_file="knowledge.swsearch",
520
+ file_types=['md', 'txt', 'pdf']
521
+ )
522
+
523
+ # Search documents
524
+ engine = SearchEngine("knowledge.swsearch")
525
+ results = engine.search(
526
+ query_vector=embeddings,
527
+ enhanced_text="search query",
528
+ count=5
529
+ )
530
+ ```
531
+
431
532
  ## Quick Start
432
533
 
433
534
  ```python
@@ -634,9 +735,12 @@ To enable HTTPS directly (without a reverse proxy), set `SWML_SSL_ENABLED` to "t
634
735
 
635
736
  ## Testing
636
737
 
637
- The SDK includes a powerful `swaig-test` CLI tool for comprehensive local testing and serverless environment simulation.
738
+ The SDK includes powerful CLI tools for development and testing:
739
+
740
+ - **`swaig-test`**: Comprehensive local testing and serverless environment simulation
741
+ - **`sw-search`**: Build local search indexes from document directories and search within them
638
742
 
639
- ### Local Testing
743
+ ### Local Testing with swaig-test
640
744
 
641
745
  Test your agents locally without deployment:
642
746
 
@@ -748,6 +852,9 @@ The package includes comprehensive documentation in the `docs/` directory:
748
852
  - [Agent Guide](docs/agent_guide.md) - Detailed guide to creating and customizing agents, including dynamic configuration
749
853
  - [Architecture](docs/architecture.md) - Overview of the SDK architecture and core concepts
750
854
  - [SWML Service Guide](docs/swml_service_guide.md) - Guide to the underlying SWML service
855
+ - [Local Search System](docs/search-system.md) - Complete guide to the local search system with vector similarity and keyword search
856
+ - [Skills System](docs/skills_system.md) - Detailed documentation on the modular skills system
857
+ - [CLI Tools](docs/cli.md) - Command-line interface tools for development and testing
751
858
 
752
859
  These documents provide in-depth explanations of the features, APIs, and usage patterns.
753
860
 
@@ -1,33 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: signalwire_agents
3
- Version: 0.1.11
4
- Summary: SignalWire AI Agents SDK
5
- Author-email: SignalWire Team <info@signalwire.com>
6
- Project-URL: Homepage, https://github.com/signalwire/signalwire-ai-agents
7
- Classifier: Development Status :: 3 - Alpha
8
- Classifier: Intended Audience :: Developers
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.7
12
- Classifier: Programming Language :: Python :: 3.8
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Requires-Python: >=3.7
17
- Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
- Requires-Dist: fastapi==0.115.12
20
- Requires-Dist: pydantic==2.11.4
21
- Requires-Dist: PyYAML==6.0.2
22
- Requires-Dist: Requests==2.32.3
23
- Requires-Dist: setuptools==66.1.1
24
- Requires-Dist: signalwire_pom==2.7.1
25
- Requires-Dist: structlog==25.3.0
26
- Requires-Dist: uvicorn==0.34.2
27
- Requires-Dist: beautifulsoup4==4.12.3
28
- Requires-Dist: pytz==2023.3
29
- Dynamic: license-file
30
-
31
1
  # SignalWire AI Agent SDK
32
2
 
33
3
  A Python SDK for creating, hosting, and securing SignalWire AI agents as microservices with minimal boilerplate.
@@ -45,6 +15,7 @@ A Python SDK for creating, hosting, and securing SignalWire AI agents as microse
45
15
  - **Prefab Archetypes**: Ready-to-use agent types for common scenarios
46
16
  - **Multi-Agent Support**: Host multiple agents on a single server
47
17
  - **Modular Skills System**: Add capabilities to agents with simple one-liner calls
18
+ - **Local Search System**: Offline document search with vector similarity and keyword search
48
19
 
49
20
  ## Skills System
50
21
 
@@ -124,6 +95,7 @@ agent.serve()
124
95
  - **datetime**: Current date and time with timezone support
125
96
  - **math**: Safe mathematical expression evaluation
126
97
  - **datasphere**: SignalWire DataSphere knowledge search (supports multiple instances)
98
+ - **native_vector_search**: Offline document search with vector similarity and keyword search
127
99
 
128
100
  ### Benefits
129
101
 
@@ -424,10 +396,73 @@ For detailed documentation and advanced examples, see [Contexts and Steps Guide]
424
396
 
425
397
  ## Installation
426
398
 
399
+ ### Basic Installation
400
+
427
401
  ```bash
428
402
  pip install signalwire-agents
429
403
  ```
430
404
 
405
+ ### Optional Search Functionality
406
+
407
+ The SDK includes optional local search capabilities that can be installed separately to avoid adding large dependencies to the base installation:
408
+
409
+ #### Search Installation Options
410
+
411
+ ```bash
412
+ # Basic search (vector search + keyword search)
413
+ pip install signalwire-agents[search]
414
+
415
+ # Full search with document processing (PDF, DOCX, etc.)
416
+ pip install signalwire-agents[search-full]
417
+
418
+ # Advanced NLP features (includes spaCy)
419
+ pip install signalwire-agents[search-nlp]
420
+
421
+ # All search features
422
+ pip install signalwire-agents[search-all]
423
+ ```
424
+
425
+ #### What Each Option Includes
426
+
427
+ | Option | Size | Features |
428
+ |--------|------|----------|
429
+ | `search` | ~500MB | Vector embeddings, keyword search, basic text processing |
430
+ | `search-full` | ~600MB | + PDF, DOCX, Excel, PowerPoint, HTML, Markdown processing |
431
+ | `search-nlp` | ~600MB | + Advanced spaCy NLP features |
432
+ | `search-all` | ~700MB | All search features combined |
433
+
434
+ #### Search Features
435
+
436
+ - **Local/Offline Search**: No external API dependencies
437
+ - **Hybrid Search**: Vector similarity + keyword search
438
+ - **Smart Document Processing**: Markdown, Python, PDF, DOCX, etc.
439
+ - **Multiple Languages**: English, Spanish, with extensible framework
440
+ - **CLI Tools**: Build search indexes from document directories
441
+ - **HTTP API**: Standalone or embedded search service
442
+
443
+ #### Usage Example
444
+
445
+ ```python
446
+ # Only available with search extras installed
447
+ from signalwire_agents.search import IndexBuilder, SearchEngine
448
+
449
+ # Build search index
450
+ builder = IndexBuilder()
451
+ builder.build_index(
452
+ source_dir="./docs",
453
+ output_file="knowledge.swsearch",
454
+ file_types=['md', 'txt', 'pdf']
455
+ )
456
+
457
+ # Search documents
458
+ engine = SearchEngine("knowledge.swsearch")
459
+ results = engine.search(
460
+ query_vector=embeddings,
461
+ enhanced_text="search query",
462
+ count=5
463
+ )
464
+ ```
465
+
431
466
  ## Quick Start
432
467
 
433
468
  ```python
@@ -634,9 +669,12 @@ To enable HTTPS directly (without a reverse proxy), set `SWML_SSL_ENABLED` to "t
634
669
 
635
670
  ## Testing
636
671
 
637
- The SDK includes a powerful `swaig-test` CLI tool for comprehensive local testing and serverless environment simulation.
672
+ The SDK includes powerful CLI tools for development and testing:
673
+
674
+ - **`swaig-test`**: Comprehensive local testing and serverless environment simulation
675
+ - **`sw-search`**: Build local search indexes from document directories and search within them
638
676
 
639
- ### Local Testing
677
+ ### Local Testing with swaig-test
640
678
 
641
679
  Test your agents locally without deployment:
642
680
 
@@ -748,6 +786,9 @@ The package includes comprehensive documentation in the `docs/` directory:
748
786
  - [Agent Guide](docs/agent_guide.md) - Detailed guide to creating and customizing agents, including dynamic configuration
749
787
  - [Architecture](docs/architecture.md) - Overview of the SDK architecture and core concepts
750
788
  - [SWML Service Guide](docs/swml_service_guide.md) - Guide to the underlying SWML service
789
+ - [Local Search System](docs/search-system.md) - Complete guide to the local search system with vector similarity and keyword search
790
+ - [Skills System](docs/skills_system.md) - Detailed documentation on the modular skills system
791
+ - [CLI Tools](docs/cli.md) - Command-line interface tools for development and testing
751
792
 
752
793
  These documents provide in-depth explanations of the features, APIs, and usage patterns.
753
794
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "signalwire_agents"
7
- version = "0.1.11"
7
+ version = "0.1.12"
8
8
  description = "SignalWire AI Agents SDK"
9
9
  authors = [
10
10
  {name = "SignalWire Team", email = "info@signalwire.com"}
@@ -35,14 +35,65 @@ dependencies = [
35
35
  "pytz==2023.3",
36
36
  ]
37
37
 
38
+ # Optional dependencies for search functionality
39
+ [project.optional-dependencies]
40
+ search = [
41
+ "sentence-transformers>=2.2.0",
42
+ "scikit-learn>=1.3.0",
43
+ "nltk>=3.8",
44
+ "numpy>=1.24.0",
45
+ ]
46
+
47
+ search-full = [
48
+ "sentence-transformers>=2.2.0",
49
+ "scikit-learn>=1.3.0",
50
+ "nltk>=3.8",
51
+ "numpy>=1.24.0",
52
+ # Document processing dependencies
53
+ "pdfplumber>=0.9.0",
54
+ "python-docx>=0.8.11",
55
+ "markdown>=3.4.0",
56
+ "striprtf>=0.0.26",
57
+ "openpyxl>=3.1.0",
58
+ "python-pptx>=0.6.21",
59
+ "python-magic>=0.4.27",
60
+ ]
61
+
62
+ # Advanced NLP (optional)
63
+ search-nlp = [
64
+ "sentence-transformers>=2.2.0",
65
+ "scikit-learn>=1.3.0",
66
+ "nltk>=3.8",
67
+ "numpy>=1.24.0",
68
+ "spacy>=3.6.0",
69
+ ]
70
+
71
+ # All search features
72
+ search-all = [
73
+ "sentence-transformers>=2.2.0",
74
+ "scikit-learn>=1.3.0",
75
+ "nltk>=3.8",
76
+ "numpy>=1.24.0",
77
+ "spacy>=3.6.0",
78
+ # Document processing dependencies
79
+ "pdfplumber>=0.9.0",
80
+ "python-docx>=0.8.11",
81
+ "markdown>=3.4.0",
82
+ "striprtf>=0.0.26",
83
+ "openpyxl>=3.1.0",
84
+ "python-pptx>=0.6.21",
85
+ "python-magic>=0.4.27",
86
+ ]
87
+
38
88
  [project.urls]
39
89
  Homepage = "https://github.com/signalwire/signalwire-ai-agents"
40
90
 
41
91
  [project.scripts]
42
92
  swaig-test = "signalwire_agents.cli.test_swaig:console_entry_point"
93
+ sw-search = "signalwire_agents.cli.build_search:console_entry_point"
43
94
 
44
95
  [tool.setuptools]
45
- packages = ["signalwire_agents", "signalwire_agents.prefabs", "signalwire_agents.utils", "signalwire_agents.core", "signalwire_agents.core.state", "signalwire_agents.core.security", "signalwire_agents.skills", "signalwire_agents.skills.web_search", "signalwire_agents.skills.datetime", "signalwire_agents.skills.math", "signalwire_agents.skills.joke", "signalwire_agents.skills.datasphere", "signalwire_agents.skills.datasphere_serverless", "signalwire_agents.skills.wikipedia", "signalwire_agents.cli"]
96
+ packages = ["signalwire_agents", "signalwire_agents.prefabs", "signalwire_agents.utils", "signalwire_agents.core", "signalwire_agents.core.state", "signalwire_agents.core.security", "signalwire_agents.skills", "signalwire_agents.skills.web_search", "signalwire_agents.skills.datetime", "signalwire_agents.skills.math", "signalwire_agents.skills.joke", "signalwire_agents.skills.datasphere", "signalwire_agents.skills.datasphere_serverless", "signalwire_agents.skills.wikipedia", "signalwire_agents.skills.native_vector_search", "signalwire_agents.cli", "signalwire_agents.search"]
46
97
  include-package-data = true
47
98
 
48
99
  [tool.setuptools.package-data]
@@ -14,7 +14,11 @@ SignalWire AI Agents SDK
14
14
  A package for building AI agents using SignalWire's AI and SWML capabilities.
15
15
  """
16
16
 
17
- __version__ = "0.1.11"
17
+ # Configure logging before any other imports to ensure early initialization
18
+ from .core.logging_config import configure_logging
19
+ configure_logging()
20
+
21
+ __version__ = "0.1.12"
18
22
 
19
23
  # Import core classes for easier access
20
24
  from .core.agent_base import AgentBase
@@ -11,7 +11,6 @@ See LICENSE file in the project root for full license information.
11
11
  AgentServer - Class for hosting multiple SignalWire AI Agents in a single server
12
12
  """
13
13
 
14
- import logging
15
14
  import re
16
15
  from typing import Dict, Any, Optional, List, Tuple, Callable
17
16
 
@@ -25,6 +24,7 @@ except ImportError:
25
24
 
26
25
  from signalwire_agents.core.agent_base import AgentBase
27
26
  from signalwire_agents.core.swml_service import SWMLService
27
+ from signalwire_agents.core.logging_config import get_logger, get_execution_mode
28
28
 
29
29
 
30
30
  class AgentServer:
@@ -48,19 +48,13 @@ class AgentServer:
48
48
  Args:
49
49
  host: Host to bind the server to
50
50
  port: Port to bind the server to
51
- log_level: Logging level (debug, info, warning, error)
51
+ log_level: Logging level (debug, info, warning, error, critical)
52
52
  """
53
53
  self.host = host
54
54
  self.port = port
55
55
  self.log_level = log_level.lower()
56
56
 
57
- # Set up logging
58
- numeric_level = getattr(logging, self.log_level.upper(), logging.INFO)
59
- logging.basicConfig(
60
- level=numeric_level,
61
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
62
- )
63
- self.logger = logging.getLogger("AgentServer")
57
+ self.logger = get_logger("AgentServer")
64
58
 
65
59
  # Create FastAPI app
66
60
  self.app = FastAPI(
@@ -304,14 +298,229 @@ class AgentServer:
304
298
 
305
299
  return self.agents.get(route)
306
300
 
307
- def run(self, host: Optional[str] = None, port: Optional[int] = None) -> None:
301
+ def run(self, event=None, context=None, host: Optional[str] = None, port: Optional[int] = None) -> Any:
308
302
  """
309
- Start the server
303
+ Universal run method that automatically detects environment and handles accordingly
304
+
305
+ Detects execution mode and routes appropriately:
306
+ - Server mode: Starts uvicorn server with FastAPI
307
+ - CGI mode: Uses same routing logic but outputs CGI headers
308
+ - Lambda mode: Uses same routing logic but returns Lambda response
310
309
 
311
310
  Args:
312
- host: Optional host to override the default
313
- port: Optional port to override the default
311
+ event: Serverless event object (Lambda, Cloud Functions)
312
+ context: Serverless context object (Lambda, Cloud Functions)
313
+ host: Optional host to override the default (server mode only)
314
+ port: Optional port to override the default (server mode only)
315
+
316
+ Returns:
317
+ Response for serverless modes, None for server mode
314
318
  """
319
+ from signalwire_agents.core.logging_config import get_execution_mode
320
+ import os
321
+ import json
322
+
323
+ # Detect execution mode
324
+ mode = get_execution_mode()
325
+
326
+ if mode == 'cgi':
327
+ return self._handle_cgi_request()
328
+ elif mode == 'lambda':
329
+ return self._handle_lambda_request(event, context)
330
+ else:
331
+ # Server mode - use existing logic
332
+ return self._run_server(host, port)
333
+
334
+ def _handle_cgi_request(self) -> str:
335
+ """Handle CGI request using same routing logic as server"""
336
+ import os
337
+ import sys
338
+ import json
339
+
340
+ # Get PATH_INFO to determine routing
341
+ path_info = os.getenv('PATH_INFO', '').strip('/')
342
+
343
+ # Use same routing logic as the server
344
+ if not path_info:
345
+ # Root request - return basic info or 404
346
+ response = {"error": "No agent specified in path"}
347
+ return self._format_cgi_response(response, status="404 Not Found")
348
+
349
+ # Find matching agent using same logic as server
350
+ for route, agent in self.agents.items():
351
+ route_clean = route.lstrip("/")
352
+
353
+ if path_info == route_clean:
354
+ # Request to agent root - return SWML
355
+ try:
356
+ swml = agent._render_swml()
357
+ return self._format_cgi_response(swml, content_type="application/json")
358
+ except Exception as e:
359
+ error_response = {"error": f"Failed to generate SWML: {str(e)}"}
360
+ return self._format_cgi_response(error_response, status="500 Internal Server Error")
361
+
362
+ elif path_info.startswith(route_clean + "/"):
363
+ # Request to agent sub-path
364
+ relative_path = path_info[len(route_clean):].lstrip("/")
365
+
366
+ if relative_path == "swaig":
367
+ # SWAIG function call - parse stdin for POST data
368
+ try:
369
+ # Read POST data from stdin
370
+ content_length = os.getenv('CONTENT_LENGTH')
371
+ if content_length:
372
+ raw_data = sys.stdin.buffer.read(int(content_length))
373
+ try:
374
+ post_data = json.loads(raw_data.decode('utf-8'))
375
+ except:
376
+ post_data = {}
377
+ else:
378
+ post_data = {}
379
+
380
+ # Execute SWAIG function
381
+ result = agent._execute_swaig_function("", post_data, None, None)
382
+ return self._format_cgi_response(result, content_type="application/json")
383
+
384
+ except Exception as e:
385
+ error_response = {"error": f"SWAIG function failed: {str(e)}"}
386
+ return self._format_cgi_response(error_response, status="500 Internal Server Error")
387
+
388
+ elif relative_path.startswith("swaig/"):
389
+ # Direct function call like /matti/swaig/function_name
390
+ function_name = relative_path[6:] # Remove "swaig/"
391
+ try:
392
+ # Read POST data from stdin
393
+ content_length = os.getenv('CONTENT_LENGTH')
394
+ if content_length:
395
+ raw_data = sys.stdin.buffer.read(int(content_length))
396
+ try:
397
+ post_data = json.loads(raw_data.decode('utf-8'))
398
+ except:
399
+ post_data = {}
400
+ else:
401
+ post_data = {}
402
+
403
+ result = agent._execute_swaig_function(function_name, post_data, None, None)
404
+ return self._format_cgi_response(result, content_type="application/json")
405
+
406
+ except Exception as e:
407
+ error_response = {"error": f"Function call failed: {str(e)}"}
408
+ return self._format_cgi_response(error_response, status="500 Internal Server Error")
409
+
410
+ # No matching agent found
411
+ error_response = {"error": "Not Found"}
412
+ return self._format_cgi_response(error_response, status="404 Not Found")
413
+
414
+ def _handle_lambda_request(self, event, context) -> dict:
415
+ """Handle Lambda request using same routing logic as server"""
416
+ import json
417
+
418
+ # Extract path from Lambda event
419
+ path = ""
420
+ if event and 'pathParameters' in event and event['pathParameters']:
421
+ path = event['pathParameters'].get('proxy', '')
422
+ elif event and 'path' in event:
423
+ path = event['path']
424
+
425
+ path = path.strip('/')
426
+
427
+ # Use same routing logic as server
428
+ if not path:
429
+ return {
430
+ "statusCode": 404,
431
+ "headers": {"Content-Type": "application/json"},
432
+ "body": json.dumps({"error": "No agent specified in path"})
433
+ }
434
+
435
+ # Find matching agent
436
+ for route, agent in self.agents.items():
437
+ route_clean = route.lstrip("/")
438
+
439
+ if path == route_clean:
440
+ # Request to agent root - return SWML
441
+ try:
442
+ swml = agent._render_swml()
443
+ return {
444
+ "statusCode": 200,
445
+ "headers": {"Content-Type": "application/json"},
446
+ "body": json.dumps(swml) if isinstance(swml, dict) else swml
447
+ }
448
+ except Exception as e:
449
+ return {
450
+ "statusCode": 500,
451
+ "headers": {"Content-Type": "application/json"},
452
+ "body": json.dumps({"error": f"Failed to generate SWML: {str(e)}"})
453
+ }
454
+
455
+ elif path.startswith(route_clean + "/"):
456
+ # Request to agent sub-path
457
+ relative_path = path[len(route_clean):].lstrip("/")
458
+
459
+ if relative_path == "swaig" or relative_path.startswith("swaig/"):
460
+ # SWAIG function call
461
+ try:
462
+ # Parse function name and body from event
463
+ function_name = relative_path[6:] if relative_path.startswith("swaig/") else ""
464
+
465
+ # Get POST data from Lambda event body
466
+ post_data = {}
467
+ if event and 'body' in event and event['body']:
468
+ try:
469
+ post_data = json.loads(event['body'])
470
+ except:
471
+ pass
472
+
473
+ result = agent._execute_swaig_function(function_name, post_data, None, None)
474
+ return {
475
+ "statusCode": 200,
476
+ "headers": {"Content-Type": "application/json"},
477
+ "body": json.dumps(result) if isinstance(result, dict) else result
478
+ }
479
+
480
+ except Exception as e:
481
+ return {
482
+ "statusCode": 500,
483
+ "headers": {"Content-Type": "application/json"},
484
+ "body": json.dumps({"error": f"Function call failed: {str(e)}"})
485
+ }
486
+
487
+ # No matching agent found
488
+ return {
489
+ "statusCode": 404,
490
+ "headers": {"Content-Type": "application/json"},
491
+ "body": json.dumps({"error": "Not Found"})
492
+ }
493
+
494
+ def _format_cgi_response(self, data, content_type: str = "application/json", status: str = "200 OK") -> str:
495
+ """Format response for CGI output"""
496
+ import json
497
+ import sys
498
+
499
+ # Format the body
500
+ if isinstance(data, dict):
501
+ body = json.dumps(data)
502
+ else:
503
+ body = str(data)
504
+
505
+ # Build CGI response with headers
506
+ response_lines = [
507
+ f"Status: {status}",
508
+ f"Content-Type: {content_type}",
509
+ f"Content-Length: {len(body.encode('utf-8'))}",
510
+ "", # Empty line separates headers from body
511
+ body
512
+ ]
513
+
514
+ response = "\n".join(response_lines)
515
+
516
+ # Write directly to stdout and flush to ensure immediate output
517
+ sys.stdout.write(response)
518
+ sys.stdout.flush()
519
+
520
+ return response
521
+
522
+ def _run_server(self, host: Optional[str] = None, port: Optional[int] = None) -> None:
523
+ """Original server mode logic"""
315
524
  if not self.agents:
316
525
  self.logger.warning("Starting server with no registered agents")
317
526