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.
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/PKG-INFO +110 -3
- signalwire_agents-0.1.11/signalwire_agents.egg-info/PKG-INFO → signalwire_agents-0.1.12/README.md +73 -32
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/pyproject.toml +53 -2
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/__init__.py +5 -1
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/agent_server.py +222 -13
- signalwire_agents-0.1.12/signalwire_agents/cli/build_search.py +457 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/cli/test_swaig.py +177 -113
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/agent_base.py +1 -1
- signalwire_agents-0.1.12/signalwire_agents/core/logging_config.py +232 -0
- signalwire_agents-0.1.12/signalwire_agents/search/__init__.py +131 -0
- signalwire_agents-0.1.12/signalwire_agents/search/document_processor.py +764 -0
- signalwire_agents-0.1.12/signalwire_agents/search/index_builder.py +534 -0
- signalwire_agents-0.1.12/signalwire_agents/search/query_processor.py +371 -0
- signalwire_agents-0.1.12/signalwire_agents/search/search_engine.py +383 -0
- signalwire_agents-0.1.12/signalwire_agents/search/search_service.py +251 -0
- signalwire_agents-0.1.12/signalwire_agents/skills/native_vector_search/__init__.py +1 -0
- signalwire_agents-0.1.12/signalwire_agents/skills/native_vector_search/skill.py +352 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/registry.py +2 -15
- signalwire_agents-0.1.12/signalwire_agents/utils/__init__.py +23 -0
- signalwire_agents-0.1.11/README.md → signalwire_agents-0.1.12/signalwire_agents.egg-info/PKG-INFO +139 -2
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/SOURCES.txt +10 -1
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/entry_points.txt +1 -0
- signalwire_agents-0.1.12/signalwire_agents.egg-info/requires.txt +50 -0
- signalwire_agents-0.1.11/signalwire_agents/utils/__init__.py +0 -11
- signalwire_agents-0.1.11/signalwire_agents/utils/serverless.py +0 -38
- signalwire_agents-0.1.11/signalwire_agents.egg-info/requires.txt +0 -10
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/LICENSE +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/schema.json +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/setup.cfg +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/setup.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/cli/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/contexts.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/data_map.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/function_result.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/pom_builder.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/security/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/security/session_manager.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/skill_base.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/skill_manager.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/file_state_manager.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/state/state_manager.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swaig_function.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_builder.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_handler.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_renderer.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/core/swml_service.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/concierge.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/faq_bot.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/info_gatherer.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/receptionist.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/prefabs/survey.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/schema.json +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere_serverless/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datasphere_serverless/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datetime/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/datetime/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/joke/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/joke/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/math/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/math/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/web_search/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/web_search/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/wikipedia/__init__.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/skills/wikipedia/skill.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/pom_utils.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/schema_utils.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/token_generators.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents/utils/validators.py +0 -0
- {signalwire_agents-0.1.11 → signalwire_agents-0.1.12}/signalwire_agents.egg-info/dependency_links.txt +0 -0
- {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.
|
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
|
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
|
|
signalwire_agents-0.1.11/signalwire_agents.egg-info/PKG-INFO → signalwire_agents-0.1.12/README.md
RENAMED
@@ -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
|
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.
|
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
|
-
|
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
|
-
|
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) ->
|
301
|
+
def run(self, event=None, context=None, host: Optional[str] = None, port: Optional[int] = None) -> Any:
|
308
302
|
"""
|
309
|
-
|
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
|
-
|
313
|
-
|
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
|
|