signalwire-agents 1.0.7__py3-none-any.whl → 1.0.17.dev4__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/agent_server.py +103 -68
- signalwire_agents/cli/dokku.py +2320 -0
- signalwire_agents/cli/init_project.py +1503 -92
- signalwire_agents/core/agent_base.py +25 -5
- signalwire_agents/core/mixins/auth_mixin.py +6 -13
- signalwire_agents/core/mixins/serverless_mixin.py +204 -112
- signalwire_agents/core/mixins/web_mixin.py +14 -6
- signalwire_agents/core/swml_service.py +4 -3
- signalwire_agents/mcp_gateway/__init__.py +29 -0
- signalwire_agents/mcp_gateway/gateway_service.py +564 -0
- signalwire_agents/mcp_gateway/mcp_manager.py +513 -0
- signalwire_agents/mcp_gateway/session_manager.py +218 -0
- signalwire_agents/search/pgvector_backend.py +10 -14
- signalwire_agents/skills/__init__.py +4 -1
- {signalwire_agents-1.0.7.data → signalwire_agents-1.0.17.dev4.data}/data/share/man/man1/sw-agent-init.1 +107 -14
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/METADATA +4 -1
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/RECORD +24 -19
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/entry_points.txt +2 -0
- {signalwire_agents-1.0.7.data → signalwire_agents-1.0.17.dev4.data}/data/share/man/man1/sw-search.1 +0 -0
- {signalwire_agents-1.0.7.data → signalwire_agents-1.0.17.dev4.data}/data/share/man/man1/swaig-test.1 +0 -0
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/WHEEL +0 -0
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Copyright (c) 2025 SignalWire
|
|
4
|
+
|
|
5
|
+
This file is part of the SignalWire AI Agents SDK.
|
|
6
|
+
|
|
7
|
+
Licensed under the MIT License.
|
|
8
|
+
See LICENSE file in the project root for full license information.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
Session Manager for MCP Gateway
|
|
13
|
+
|
|
14
|
+
Manages lifecycle of MCP server sessions tied to SignalWire call IDs.
|
|
15
|
+
Handles timeouts, cleanup, and resource limits.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import threading
|
|
19
|
+
import time
|
|
20
|
+
import logging
|
|
21
|
+
from typing import Dict, Optional, Any
|
|
22
|
+
from datetime import datetime, timedelta
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class Session:
|
|
30
|
+
"""Represents an active MCP session"""
|
|
31
|
+
session_id: str
|
|
32
|
+
service_name: str
|
|
33
|
+
process: Any # MCPClient instance
|
|
34
|
+
created_at: datetime = field(default_factory=datetime.now)
|
|
35
|
+
last_accessed: datetime = field(default_factory=datetime.now)
|
|
36
|
+
timeout: int = 300 # seconds
|
|
37
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def is_expired(self) -> bool:
|
|
41
|
+
"""Check if session has expired based on timeout"""
|
|
42
|
+
return datetime.now() > self.last_accessed + timedelta(seconds=self.timeout)
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def is_alive(self) -> bool:
|
|
46
|
+
"""Check if the underlying MCP client is still running"""
|
|
47
|
+
return self.process and self.process.process and self.process.process.poll() is None
|
|
48
|
+
|
|
49
|
+
def touch(self):
|
|
50
|
+
"""Update last accessed time"""
|
|
51
|
+
self.last_accessed = datetime.now()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class SessionManager:
|
|
55
|
+
"""Manages MCP server sessions with automatic cleanup"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, config: Dict[str, Any]):
|
|
58
|
+
self.config = config
|
|
59
|
+
self.sessions: Dict[str, Session] = {}
|
|
60
|
+
self.lock = threading.RLock()
|
|
61
|
+
self.cleanup_interval = config.get('session', {}).get('cleanup_interval', 60)
|
|
62
|
+
self.max_sessions_per_service = config.get('session', {}).get('max_sessions_per_service', 100)
|
|
63
|
+
self.default_timeout = config.get('session', {}).get('default_timeout', 300)
|
|
64
|
+
self._shutdown = threading.Event()
|
|
65
|
+
|
|
66
|
+
# Start cleanup thread
|
|
67
|
+
self.cleanup_thread = threading.Thread(target=self._cleanup_loop, daemon=True)
|
|
68
|
+
self.cleanup_thread.start()
|
|
69
|
+
|
|
70
|
+
logger.info(f"SessionManager initialized with cleanup_interval={self.cleanup_interval}s")
|
|
71
|
+
|
|
72
|
+
def create_session(self, session_id: str, service_name: str, process: Any,
|
|
73
|
+
timeout: Optional[int] = None, metadata: Optional[Dict[str, Any]] = None) -> Session:
|
|
74
|
+
"""Create and register a new session"""
|
|
75
|
+
with self.lock:
|
|
76
|
+
# Check if session already exists
|
|
77
|
+
if session_id in self.sessions:
|
|
78
|
+
logger.warning(f"Session {session_id} already exists, closing old session")
|
|
79
|
+
self.close_session(session_id)
|
|
80
|
+
|
|
81
|
+
# Check service limits
|
|
82
|
+
service_count = sum(1 for s in self.sessions.values() if s.service_name == service_name)
|
|
83
|
+
if service_count >= self.max_sessions_per_service:
|
|
84
|
+
raise RuntimeError(f"Max sessions limit reached for service {service_name}")
|
|
85
|
+
|
|
86
|
+
# Create new session
|
|
87
|
+
session = Session(
|
|
88
|
+
session_id=session_id,
|
|
89
|
+
service_name=service_name,
|
|
90
|
+
process=process,
|
|
91
|
+
timeout=timeout or self.default_timeout,
|
|
92
|
+
metadata=metadata or {}
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
self.sessions[session_id] = session
|
|
96
|
+
logger.info(f"Created session {session_id} for service {service_name}")
|
|
97
|
+
|
|
98
|
+
return session
|
|
99
|
+
|
|
100
|
+
def get_session(self, session_id: str) -> Optional[Session]:
|
|
101
|
+
"""Get an active session by ID"""
|
|
102
|
+
with self.lock:
|
|
103
|
+
session = self.sessions.get(session_id)
|
|
104
|
+
|
|
105
|
+
if session:
|
|
106
|
+
if not session.is_alive:
|
|
107
|
+
logger.warning(f"Session {session_id} process is dead, removing")
|
|
108
|
+
self.close_session(session_id)
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
if session.is_expired:
|
|
112
|
+
logger.info(f"Session {session_id} has expired, removing")
|
|
113
|
+
self.close_session(session_id)
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
# Update last accessed time
|
|
117
|
+
session.touch()
|
|
118
|
+
|
|
119
|
+
return session
|
|
120
|
+
|
|
121
|
+
def close_session(self, session_id: str) -> bool:
|
|
122
|
+
"""Close and remove a session"""
|
|
123
|
+
with self.lock:
|
|
124
|
+
session = self.sessions.pop(session_id, None)
|
|
125
|
+
|
|
126
|
+
if not session:
|
|
127
|
+
logger.warning(f"Attempted to close non-existent session {session_id}")
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
# Terminate the MCP client
|
|
131
|
+
if session.process:
|
|
132
|
+
try:
|
|
133
|
+
# Stop the MCP client
|
|
134
|
+
session.process.stop()
|
|
135
|
+
except Exception as e:
|
|
136
|
+
logger.error(f"Error stopping MCP client for session {session_id}: {e}")
|
|
137
|
+
|
|
138
|
+
logger.info(f"Closed session {session_id}")
|
|
139
|
+
return True
|
|
140
|
+
|
|
141
|
+
def list_sessions(self) -> Dict[str, Dict[str, Any]]:
|
|
142
|
+
"""List all active sessions with their info"""
|
|
143
|
+
with self.lock:
|
|
144
|
+
result = {}
|
|
145
|
+
|
|
146
|
+
for session_id, session in list(self.sessions.items()):
|
|
147
|
+
# Check if still valid
|
|
148
|
+
if not session.is_alive or session.is_expired:
|
|
149
|
+
self.close_session(session_id)
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
result[session_id] = {
|
|
153
|
+
'service_name': session.service_name,
|
|
154
|
+
'created_at': session.created_at.isoformat(),
|
|
155
|
+
'last_accessed': session.last_accessed.isoformat(),
|
|
156
|
+
'timeout': session.timeout,
|
|
157
|
+
'metadata': session.metadata,
|
|
158
|
+
'time_remaining': max(0, (session.last_accessed + timedelta(seconds=session.timeout) - datetime.now()).total_seconds())
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result
|
|
162
|
+
|
|
163
|
+
def get_service_session_count(self, service_name: str) -> int:
|
|
164
|
+
"""Get number of active sessions for a service"""
|
|
165
|
+
with self.lock:
|
|
166
|
+
return sum(1 for s in self.sessions.values()
|
|
167
|
+
if s.service_name == service_name and s.is_alive and not s.is_expired)
|
|
168
|
+
|
|
169
|
+
def _cleanup_loop(self):
|
|
170
|
+
"""Background thread that cleans up expired sessions"""
|
|
171
|
+
logger.info("Session cleanup thread started")
|
|
172
|
+
|
|
173
|
+
while not self._shutdown.is_set():
|
|
174
|
+
try:
|
|
175
|
+
# Wait with timeout so we can check shutdown flag
|
|
176
|
+
if self._shutdown.wait(timeout=self.cleanup_interval):
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
with self.lock:
|
|
180
|
+
expired_sessions = []
|
|
181
|
+
|
|
182
|
+
for session_id, session in self.sessions.items():
|
|
183
|
+
if session.is_expired or not session.is_alive:
|
|
184
|
+
expired_sessions.append(session_id)
|
|
185
|
+
|
|
186
|
+
for session_id in expired_sessions:
|
|
187
|
+
logger.info(f"Cleaning up expired session {session_id}")
|
|
188
|
+
self.close_session(session_id)
|
|
189
|
+
|
|
190
|
+
if expired_sessions:
|
|
191
|
+
logger.info(f"Cleaned up {len(expired_sessions)} expired sessions")
|
|
192
|
+
|
|
193
|
+
except Exception as e:
|
|
194
|
+
logger.error(f"Error in cleanup thread: {e}")
|
|
195
|
+
|
|
196
|
+
logger.info("Session cleanup thread stopped")
|
|
197
|
+
|
|
198
|
+
def shutdown(self):
|
|
199
|
+
"""Shutdown all sessions and cleanup"""
|
|
200
|
+
logger.info("Shutting down SessionManager")
|
|
201
|
+
|
|
202
|
+
# Signal cleanup thread to stop
|
|
203
|
+
self._shutdown.set()
|
|
204
|
+
|
|
205
|
+
with self.lock:
|
|
206
|
+
# Close all sessions
|
|
207
|
+
session_ids = list(self.sessions.keys())
|
|
208
|
+
logger.info(f"Closing {len(session_ids)} active sessions")
|
|
209
|
+
for session_id in session_ids:
|
|
210
|
+
self.close_session(session_id)
|
|
211
|
+
|
|
212
|
+
# Wait for cleanup thread to finish (with timeout)
|
|
213
|
+
if self.cleanup_thread.is_alive():
|
|
214
|
+
self.cleanup_thread.join(timeout=2.0)
|
|
215
|
+
if self.cleanup_thread.is_alive():
|
|
216
|
+
logger.warning("Cleanup thread did not stop gracefully")
|
|
217
|
+
|
|
218
|
+
logger.info("SessionManager shutdown complete")
|
|
@@ -441,37 +441,33 @@ class PgVectorSearchBackend:
|
|
|
441
441
|
List of search results with scores and metadata
|
|
442
442
|
"""
|
|
443
443
|
self._ensure_connection()
|
|
444
|
-
|
|
444
|
+
|
|
445
445
|
# Extract query terms for metadata search
|
|
446
446
|
query_terms = enhanced_text.lower().split()
|
|
447
|
-
|
|
447
|
+
|
|
448
448
|
# Vector search
|
|
449
449
|
vector_results = self._vector_search(query_vector, count * 2, tags)
|
|
450
450
|
|
|
451
|
+
# Apply similarity threshold to raw vector scores BEFORE weighting
|
|
452
|
+
# This ensures threshold behaves intuitively (filters on actual similarity, not weighted score)
|
|
453
|
+
if similarity_threshold > 0:
|
|
454
|
+
vector_results = [r for r in vector_results if r['score'] >= similarity_threshold]
|
|
455
|
+
|
|
451
456
|
# Keyword search
|
|
452
457
|
keyword_results = self._keyword_search(enhanced_text, count * 2, tags)
|
|
453
458
|
|
|
454
459
|
# Metadata search
|
|
455
460
|
metadata_results = self._metadata_search(query_terms, count * 2, tags)
|
|
456
461
|
|
|
457
|
-
|
|
458
|
-
# Merge all results
|
|
462
|
+
# Merge all results (threshold already applied to vector results)
|
|
459
463
|
merged_results = self._merge_all_results(vector_results, keyword_results, metadata_results, keyword_weight)
|
|
460
464
|
|
|
461
|
-
|
|
462
|
-
# Filter by distance threshold
|
|
463
|
-
filtered_results = [
|
|
464
|
-
r for r in merged_results
|
|
465
|
-
if r['score'] >= similarity_threshold
|
|
466
|
-
]
|
|
467
|
-
|
|
468
|
-
|
|
469
465
|
# Ensure 'score' field exists for CLI compatibility
|
|
470
|
-
for r in
|
|
466
|
+
for r in merged_results:
|
|
471
467
|
if 'score' not in r:
|
|
472
468
|
r['score'] = r.get('final_score', 0.0)
|
|
473
469
|
|
|
474
|
-
return
|
|
470
|
+
return merged_results[:count]
|
|
475
471
|
|
|
476
472
|
def _vector_search(self, query_vector: List[float], count: int,
|
|
477
473
|
tags: Optional[List[str]] = None) -> List[Dict[str, Any]]:
|
|
@@ -17,7 +17,10 @@ Skills are automatically discovered from subdirectories.
|
|
|
17
17
|
# Import the registry to make it available
|
|
18
18
|
from .registry import skill_registry
|
|
19
19
|
|
|
20
|
+
# Import SkillBase for convenience
|
|
21
|
+
from signalwire_agents.core.skill_base import SkillBase
|
|
22
|
+
|
|
20
23
|
# Trigger skill discovery on import
|
|
21
24
|
# skill_registry.discover_skills()
|
|
22
25
|
|
|
23
|
-
__all__ = ["skill_registry"]
|
|
26
|
+
__all__ = ["skill_registry", "SkillBase"]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" Man page for sw-agent-init
|
|
2
2
|
.\" Copyright (c) 2025 SignalWire
|
|
3
3
|
.\" Licensed under the MIT License
|
|
4
|
-
.TH SW-AGENT-INIT 1 "November 2025" "SignalWire Agents SDK 1.0.
|
|
4
|
+
.TH SW-AGENT-INIT 1 "November 2025" "SignalWire Agents SDK 1.0.8" "SignalWire Commands"
|
|
5
5
|
.SH NAME
|
|
6
6
|
sw-agent-init \- create a new SignalWire AI agent project
|
|
7
7
|
.SH SYNOPSIS
|
|
@@ -14,14 +14,14 @@ sw-agent-init \- create a new SignalWire AI agent project
|
|
|
14
14
|
.SH DESCRIPTION
|
|
15
15
|
.B sw-agent-init
|
|
16
16
|
is an interactive command-line tool for creating new SignalWire AI agent
|
|
17
|
-
projects. It
|
|
18
|
-
|
|
17
|
+
projects. It supports both local agent projects (FastAPI/uvicorn) and
|
|
18
|
+
cloud function deployments (AWS Lambda, Google Cloud Functions, Azure Functions).
|
|
19
19
|
.PP
|
|
20
20
|
When run without arguments, the tool enters interactive mode and prompts
|
|
21
|
-
for project configuration. When given a project
|
|
22
|
-
mode with sensible defaults.
|
|
21
|
+
for project configuration including platform selection. When given a project
|
|
22
|
+
name, it runs in quick mode with sensible defaults (local platform by default).
|
|
23
23
|
.PP
|
|
24
|
-
|
|
24
|
+
For local projects, the generated project includes:
|
|
25
25
|
.IP \(bu 2
|
|
26
26
|
Agent module with sample SWAIG function
|
|
27
27
|
.IP \(bu 2
|
|
@@ -46,8 +46,36 @@ interactive mode and prompts for a name.
|
|
|
46
46
|
.BR \-h ", " \-\-help
|
|
47
47
|
Display help message and exit.
|
|
48
48
|
.TP
|
|
49
|
+
.BI \-p ", " \-\-platform " PLATFORM"
|
|
50
|
+
Target deployment platform. Valid values:
|
|
51
|
+
.RS
|
|
52
|
+
.IP \(bu 2
|
|
53
|
+
.B local
|
|
54
|
+
\- Local agent with FastAPI/uvicorn server (default)
|
|
55
|
+
.IP \(bu 2
|
|
56
|
+
.B aws
|
|
57
|
+
\- AWS Lambda function with API Gateway
|
|
58
|
+
.IP \(bu 2
|
|
59
|
+
.B gcp
|
|
60
|
+
\- Google Cloud Function (Gen 2)
|
|
61
|
+
.IP \(bu 2
|
|
62
|
+
.B azure
|
|
63
|
+
\- Azure Function
|
|
64
|
+
.RE
|
|
65
|
+
.TP
|
|
66
|
+
.BI \-r ", " \-\-region " REGION"
|
|
67
|
+
Cloud region for deployment (only for cloud platforms). Default regions:
|
|
68
|
+
.RS
|
|
69
|
+
.IP \(bu 2
|
|
70
|
+
AWS: us-east-1
|
|
71
|
+
.IP \(bu 2
|
|
72
|
+
GCP: us-central1
|
|
73
|
+
.IP \(bu 2
|
|
74
|
+
Azure: eastus
|
|
75
|
+
.RE
|
|
76
|
+
.TP
|
|
49
77
|
.BI \-\-type " TYPE"
|
|
50
|
-
Agent type to create. Valid values:
|
|
78
|
+
Agent type to create (only for local platform). Valid values:
|
|
51
79
|
.RS
|
|
52
80
|
.IP \(bu 2
|
|
53
81
|
.B basic
|
|
@@ -58,8 +86,8 @@ Agent type to create. Valid values:
|
|
|
58
86
|
.RE
|
|
59
87
|
.TP
|
|
60
88
|
.B \-\-no\-venv
|
|
61
|
-
Skip virtual environment creation. By default,
|
|
62
|
-
environment is created in the project directory.
|
|
89
|
+
Skip virtual environment creation (only for local platform). By default,
|
|
90
|
+
a Python virtual environment is created in the project directory.
|
|
63
91
|
.TP
|
|
64
92
|
.BI \-\-dir " DIRECTORY"
|
|
65
93
|
Parent directory for the project. The project will be created as
|
|
@@ -68,14 +96,20 @@ a subdirectory. Default is the current directory.
|
|
|
68
96
|
When run without a project name, the tool prompts for:
|
|
69
97
|
.SS Project Configuration
|
|
70
98
|
.IP \(bu 2
|
|
99
|
+
.B Target platform
|
|
100
|
+
\- Local, AWS Lambda, GCP, or Azure
|
|
101
|
+
.IP \(bu 2
|
|
71
102
|
.B Project name
|
|
72
103
|
\- Name of the project directory
|
|
73
104
|
.IP \(bu 2
|
|
74
105
|
.B Project directory
|
|
75
106
|
\- Where to create the project
|
|
76
107
|
.IP \(bu 2
|
|
108
|
+
.B Region
|
|
109
|
+
\- Cloud region (for cloud platforms only)
|
|
110
|
+
.IP \(bu 2
|
|
77
111
|
.B Agent type
|
|
78
|
-
\- Basic or full setup
|
|
112
|
+
\- Basic or full setup (for local platform only)
|
|
79
113
|
.SS Feature Selection
|
|
80
114
|
The following features can be enabled or disabled:
|
|
81
115
|
.IP \(bu 2
|
|
@@ -189,8 +223,8 @@ Run without arguments for guided setup:
|
|
|
189
223
|
sw-agent-init
|
|
190
224
|
.fi
|
|
191
225
|
.RE
|
|
192
|
-
.SS Quick Mode
|
|
193
|
-
Create a basic agent project:
|
|
226
|
+
.SS Quick Mode - Local
|
|
227
|
+
Create a basic local agent project:
|
|
194
228
|
.PP
|
|
195
229
|
.RS
|
|
196
230
|
.nf
|
|
@@ -198,7 +232,7 @@ sw-agent-init myagent
|
|
|
198
232
|
.fi
|
|
199
233
|
.RE
|
|
200
234
|
.PP
|
|
201
|
-
Create a full-featured project:
|
|
235
|
+
Create a full-featured local project:
|
|
202
236
|
.PP
|
|
203
237
|
.RS
|
|
204
238
|
.nf
|
|
@@ -221,7 +255,39 @@ Create in a specific directory:
|
|
|
221
255
|
sw-agent-init myagent --dir /opt/projects
|
|
222
256
|
.fi
|
|
223
257
|
.RE
|
|
224
|
-
.SS
|
|
258
|
+
.SS Quick Mode - Cloud Functions
|
|
259
|
+
Create an AWS Lambda project:
|
|
260
|
+
.PP
|
|
261
|
+
.RS
|
|
262
|
+
.nf
|
|
263
|
+
sw-agent-init myagent -p aws
|
|
264
|
+
.fi
|
|
265
|
+
.RE
|
|
266
|
+
.PP
|
|
267
|
+
Create an AWS Lambda project in a specific region:
|
|
268
|
+
.PP
|
|
269
|
+
.RS
|
|
270
|
+
.nf
|
|
271
|
+
sw-agent-init myagent -p aws -r us-west-2
|
|
272
|
+
.fi
|
|
273
|
+
.RE
|
|
274
|
+
.PP
|
|
275
|
+
Create a Google Cloud Function project:
|
|
276
|
+
.PP
|
|
277
|
+
.RS
|
|
278
|
+
.nf
|
|
279
|
+
sw-agent-init myagent -p gcp
|
|
280
|
+
.fi
|
|
281
|
+
.RE
|
|
282
|
+
.PP
|
|
283
|
+
Create an Azure Function project:
|
|
284
|
+
.PP
|
|
285
|
+
.RS
|
|
286
|
+
.nf
|
|
287
|
+
sw-agent-init myagent -p azure
|
|
288
|
+
.fi
|
|
289
|
+
.RE
|
|
290
|
+
.SS After Creation - Local
|
|
225
291
|
Start the agent:
|
|
226
292
|
.PP
|
|
227
293
|
.RS
|
|
@@ -251,6 +317,33 @@ swaig-test agents/main_agent.py --exec get_info --topic "test"
|
|
|
251
317
|
swaig-test agents/main_agent.py --dump-swml
|
|
252
318
|
.fi
|
|
253
319
|
.RE
|
|
320
|
+
.SS After Creation - Cloud Functions
|
|
321
|
+
Deploy to AWS Lambda:
|
|
322
|
+
.PP
|
|
323
|
+
.RS
|
|
324
|
+
.nf
|
|
325
|
+
cd myagent
|
|
326
|
+
./deploy.sh
|
|
327
|
+
.fi
|
|
328
|
+
.RE
|
|
329
|
+
.PP
|
|
330
|
+
Deploy to Google Cloud:
|
|
331
|
+
.PP
|
|
332
|
+
.RS
|
|
333
|
+
.nf
|
|
334
|
+
cd myagent
|
|
335
|
+
./deploy.sh
|
|
336
|
+
.fi
|
|
337
|
+
.RE
|
|
338
|
+
.PP
|
|
339
|
+
Deploy to Azure:
|
|
340
|
+
.PP
|
|
341
|
+
.RS
|
|
342
|
+
.nf
|
|
343
|
+
cd myagent
|
|
344
|
+
./deploy.sh
|
|
345
|
+
.fi
|
|
346
|
+
.RE
|
|
254
347
|
.SH AGENT TYPES
|
|
255
348
|
.SS Basic Agent
|
|
256
349
|
The basic agent type includes:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: signalwire_agents
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.17.dev4
|
|
4
4
|
Summary: SignalWire AI Agents SDK
|
|
5
5
|
Author-email: SignalWire Team <info@signalwire.com>
|
|
6
6
|
License: MIT
|
|
@@ -75,6 +75,9 @@ Requires-Dist: pgvector>=0.2.0; extra == "search-all"
|
|
|
75
75
|
Provides-Extra: pgvector
|
|
76
76
|
Requires-Dist: psycopg2-binary>=2.9.0; extra == "pgvector"
|
|
77
77
|
Requires-Dist: pgvector>=0.2.0; extra == "pgvector"
|
|
78
|
+
Provides-Extra: mcp-gateway
|
|
79
|
+
Requires-Dist: flask>=2.0.0; extra == "mcp-gateway"
|
|
80
|
+
Requires-Dist: flask-limiter>=3.5.0; extra == "mcp-gateway"
|
|
78
81
|
Provides-Extra: all
|
|
79
82
|
Requires-Dist: sentence-transformers>=2.2.0; extra == "all"
|
|
80
83
|
Requires-Dist: scikit-learn>=1.3.0; extra == "all"
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
signalwire_agents/__init__.py,sha256=
|
|
2
|
-
signalwire_agents/agent_server.py,sha256=
|
|
1
|
+
signalwire_agents/__init__.py,sha256=DYvpwmWb5SgEYdvPhRykJUF0J_AJQUOS7ExFWD0nfrg,5036
|
|
2
|
+
signalwire_agents/agent_server.py,sha256=2zJFNOOEpEOXn5J5Diz1NpL1JFEUA2_6qbV0PPK_Vhc,32352
|
|
3
3
|
signalwire_agents/schema.json,sha256=YQv4-KiegE00XvxoLMKAml6aCGitnt3kBq31ECxTHK8,385886
|
|
4
4
|
signalwire_agents/agents/bedrock.py,sha256=J582gooNtxtep4xdVOfyDzRtHp_XrurPMS93xf2Xod0,10836
|
|
5
5
|
signalwire_agents/cli/__init__.py,sha256=XbxAQFaCIdGXIXJiriVBWoFPOJsC401u21588nO4TG8,388
|
|
6
6
|
signalwire_agents/cli/build_search.py,sha256=wDuonVY9fcqspThRHmbArTuZLKsiStu-ozVExtqawA8,54937
|
|
7
7
|
signalwire_agents/cli/config.py,sha256=2i4e0BArdKsaXxjeueYYRNke7GWicHPYC2wuitVrP7A,2541
|
|
8
|
-
signalwire_agents/cli/
|
|
8
|
+
signalwire_agents/cli/dokku.py,sha256=WuyqErWPZ-Wyqfxlzb3DyPhkyrSropUYzHtTuqzjGiM,80255
|
|
9
|
+
signalwire_agents/cli/init_project.py,sha256=nNBPni3x1xzdJ5pAZsQRUYK1t1e64NzwUUkq-Uc3mzo,78835
|
|
9
10
|
signalwire_agents/cli/swaig_test_wrapper.py,sha256=t63HQpEc1Up5AcysEHP1OsEQcgSMKH-9H1L2IhFso18,1533
|
|
10
11
|
signalwire_agents/cli/test_swaig.py,sha256=-v-XjTUWZNxmMJuOF5_cB1Jz8x8emJoqgqS_8jLeT4Y,31487
|
|
11
12
|
signalwire_agents/cli/types.py,sha256=U8Abc4Atb5-wMbhM3MjcuIXsbONLOu1ucePWOCgqdco,1810
|
|
@@ -25,7 +26,7 @@ signalwire_agents/cli/simulation/data_generation.py,sha256=pxa9aJ6XkI0O8yAIGvBTU
|
|
|
25
26
|
signalwire_agents/cli/simulation/data_overrides.py,sha256=3_3pT6j-q2gRufPX2bZ1BrmY7u1IdloLooKAJil33vI,6319
|
|
26
27
|
signalwire_agents/cli/simulation/mock_env.py,sha256=fvaR_xdLMm8AbpNUbTJOFG9THcti3Zds-0QNDbKMaYk,10249
|
|
27
28
|
signalwire_agents/core/__init__.py,sha256=xjPq8DmUnWYUG28sd17n430VWPmMH9oZ9W14gYwG96g,806
|
|
28
|
-
signalwire_agents/core/agent_base.py,sha256=
|
|
29
|
+
signalwire_agents/core/agent_base.py,sha256=zZRykB8VD277_5_NZbYP7ZcpeqTdQ4yWlpNnLXOljEY,58883
|
|
29
30
|
signalwire_agents/core/auth_handler.py,sha256=jXrof9WZ1W9qqlQT9WElcmSRafL2kG7207x5SqWN9MU,8481
|
|
30
31
|
signalwire_agents/core/config_loader.py,sha256=rStVRRUaeMGrMc44ocr0diMQQARZhbKqwMqQ6kqUNos,8722
|
|
31
32
|
signalwire_agents/core/contexts.py,sha256=g9FgOGMfGCUWlm57YZcv7CvOf-Ub9FdKZIOMu14ADfE,24428
|
|
@@ -40,7 +41,7 @@ signalwire_agents/core/swaig_function.py,sha256=KnUQ2g99kDSzOzD1PJ0Iqs8DeeZ6jDII
|
|
|
40
41
|
signalwire_agents/core/swml_builder.py,sha256=tJBFDAVTENEfjGLp2h9_AKOYt5O9FrSYLI-nZZVwM1E,15604
|
|
41
42
|
signalwire_agents/core/swml_handler.py,sha256=hFDq41dQWL3EdFbq6h0hizE1dIqdVeiTeCrujbZsPzo,8397
|
|
42
43
|
signalwire_agents/core/swml_renderer.py,sha256=-WAB_5ss836a8nBo5zlb6SaQKFNF4XIo1odWIXM4eE8,6860
|
|
43
|
-
signalwire_agents/core/swml_service.py,sha256=
|
|
44
|
+
signalwire_agents/core/swml_service.py,sha256=TCsn3g_kAxz1DfSiPygpBv6KTd6EEDaWplFVqZZnZw8,49995
|
|
44
45
|
signalwire_agents/core/agent/__init__.py,sha256=qccTmLD9b24tZDAoIPEY6vJ2p1R_ArZ_ZCKbBlKvPQ8,239
|
|
45
46
|
signalwire_agents/core/agent/config/__init__.py,sha256=5XvTfnYeeGdoLr4tJjbe1OhF26nOcR5VTDIhtMGCu3I,244
|
|
46
47
|
signalwire_agents/core/agent/deployment/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
|
@@ -55,15 +56,19 @@ signalwire_agents/core/agent/tools/decorator.py,sha256=pC6j1114GwVBd2U3h23I9gKLt
|
|
|
55
56
|
signalwire_agents/core/agent/tools/registry.py,sha256=HScbKKwpJqFZ_odmeFklSQ0p0EMasEyKSxNwX568OPo,8054
|
|
56
57
|
signalwire_agents/core/mixins/__init__.py,sha256=NsFpfF7TDP_lNR0Riw4Nbvt4fDbv_A3OoVbBqRrtXQM,652
|
|
57
58
|
signalwire_agents/core/mixins/ai_config_mixin.py,sha256=In7SrVlKoRaGsDIXEDNGsrEqCjotmcQr_XA563VWABQ,16265
|
|
58
|
-
signalwire_agents/core/mixins/auth_mixin.py,sha256=
|
|
59
|
+
signalwire_agents/core/mixins/auth_mixin.py,sha256=FIzQjLOkEgQhy6uIKjnevsM3ubdMnY5gDDksslEUtF8,9729
|
|
59
60
|
signalwire_agents/core/mixins/prompt_mixin.py,sha256=bEsuw9J2F_upFYI02KyC7o2eGZjwOKQ352rmJBZirAM,13729
|
|
60
|
-
signalwire_agents/core/mixins/serverless_mixin.py,sha256=
|
|
61
|
+
signalwire_agents/core/mixins/serverless_mixin.py,sha256=XP_dFGO1aa4_Ouq9YLRhQ_MmjNTv-qsAXKHyf90ETMQ,20599
|
|
61
62
|
signalwire_agents/core/mixins/skill_mixin.py,sha256=Qz3RKPmq_iMY4NecyxOHk3dW3W-O4iEm2ahhMjAcqRs,1861
|
|
62
63
|
signalwire_agents/core/mixins/state_mixin.py,sha256=q3achpyUYZKuJaqKf12O22FXpSsNNsMEonSvlpSHCkA,6594
|
|
63
64
|
signalwire_agents/core/mixins/tool_mixin.py,sha256=6CaNdaspHcfte0qSB_bSN8PTsqxRZzL_AXYk8QoWyXE,8660
|
|
64
|
-
signalwire_agents/core/mixins/web_mixin.py,sha256=
|
|
65
|
+
signalwire_agents/core/mixins/web_mixin.py,sha256=Yknov_Rd2k7R0DO9JRsrbsv5l_ztkAjBy5MBPMjmNYU,51057
|
|
65
66
|
signalwire_agents/core/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
|
66
67
|
signalwire_agents/core/security/session_manager.py,sha256=s5hXYcFnrsYFoyo-zcN7EJy-wInZQI_cWTBHX9MxHR4,9164
|
|
68
|
+
signalwire_agents/mcp_gateway/__init__.py,sha256=uZhyt0cBa9Wk_OPr_Ewphh6apsaf_5O9G48NVkm_00I,619
|
|
69
|
+
signalwire_agents/mcp_gateway/gateway_service.py,sha256=hytoEhiXSyZxk_LxV-zo0mfCCAJf-y2Gs5gJ__iIRB0,23081
|
|
70
|
+
signalwire_agents/mcp_gateway/mcp_manager.py,sha256=DaR49BX5b6hn2mXJygS3idNEr3IDImWGNdsrQSYxiEE,19669
|
|
71
|
+
signalwire_agents/mcp_gateway/session_manager.py,sha256=sGMPT8aSzS2RRR_ewkd0nxwYI-LK5CaWrendGhXAW9c,8505
|
|
67
72
|
signalwire_agents/prefabs/__init__.py,sha256=MW11J63XH7KxF2MWguRsMFM9iqMWexaEO9ynDPL_PDM,715
|
|
68
73
|
signalwire_agents/prefabs/concierge.py,sha256=XB-Ziy0tteYI5NHu7Sinx-N960nzkhq2m4v8Ei8UHas,9921
|
|
69
74
|
signalwire_agents/prefabs/faq_bot.py,sha256=cUuHhnDB8S4aVg-DiQe4jBmCAPrYQrND_Mff9iaeEa0,10572
|
|
@@ -75,12 +80,12 @@ signalwire_agents/search/document_processor.py,sha256=emlmYAgr34Qyhfqm4VppqTCpm1
|
|
|
75
80
|
signalwire_agents/search/index_builder.py,sha256=v1LGhbzzKlCilO4g6nqQJVYEAWvInP2j5B1QrAEj4V8,33772
|
|
76
81
|
signalwire_agents/search/migration.py,sha256=UZPrpUOMZeLVNO1cEDp3tnZYG6ys8-VCFlZXmzig_E0,16582
|
|
77
82
|
signalwire_agents/search/models.py,sha256=isYOYwQT0eWCVdcYSSd8w6z2gFYUobtC8BAUhV7FUVI,840
|
|
78
|
-
signalwire_agents/search/pgvector_backend.py,sha256=
|
|
83
|
+
signalwire_agents/search/pgvector_backend.py,sha256=bFxdAtBWEBPLlbQYrcSvyUqcyJn8Y_22GJNknkGTGP0,28717
|
|
79
84
|
signalwire_agents/search/query_processor.py,sha256=34MXOWyEKKMgSCNNM5X2SRyWwF8CPJeorgNjFn661zs,19587
|
|
80
85
|
signalwire_agents/search/search_engine.py,sha256=kDIIBuxSMAoedMS0mnxvPCZOx59fx4mJwxhVRpB6BNU,57461
|
|
81
86
|
signalwire_agents/search/search_service.py,sha256=FYjX95TD0Cr6jakYU4A1GIdBkj72euq2fM3zaBe2b9U,22379
|
|
82
87
|
signalwire_agents/skills/README.md,sha256=sM1_08IsKdRDCzYHPLzppJbaK5MvRelsVL6Kd9A9Ubo,12193
|
|
83
|
-
signalwire_agents/skills/__init__.py,sha256=
|
|
88
|
+
signalwire_agents/skills/__init__.py,sha256=JrFQR7IaLtT3BXFURP_a1ZySPhv7FfPWM60xpLMnLqc,638
|
|
84
89
|
signalwire_agents/skills/registry.py,sha256=zURdeAaccZyUSwLRl8K4ILXICMV3ouYQIA4rUBq6b5E,20792
|
|
85
90
|
signalwire_agents/skills/api_ninjas_trivia/README.md,sha256=SoyS7VFh3eVIiVnQ5gfTfs0a_gAlLwnmT2W2FrbNU0A,6762
|
|
86
91
|
signalwire_agents/skills/api_ninjas_trivia/__init__.py,sha256=zN305bBQkzlJyUNsPUMPt3gDJbvc-Iigkdh0rBou_RE,267
|
|
@@ -131,12 +136,12 @@ signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663
|
|
|
131
136
|
signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
|
132
137
|
signalwire_agents/web/__init__.py,sha256=XE_pSTY9Aalzr7J7wqFth1Zr3cccQHPPcF5HWNrOpz8,383
|
|
133
138
|
signalwire_agents/web/web_service.py,sha256=a2PSHJgX1tlZr0Iz1A1UouZjXEePJAZL632evvLVM38,21071
|
|
134
|
-
signalwire_agents-1.0.
|
|
135
|
-
signalwire_agents-1.0.
|
|
136
|
-
signalwire_agents-1.0.
|
|
137
|
-
signalwire_agents-1.0.
|
|
138
|
-
signalwire_agents-1.0.
|
|
139
|
-
signalwire_agents-1.0.
|
|
140
|
-
signalwire_agents-1.0.
|
|
141
|
-
signalwire_agents-1.0.
|
|
142
|
-
signalwire_agents-1.0.
|
|
139
|
+
signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-agent-init.1,sha256=J4k5Oi74BnWCPCvsaw00vuyyqDPuIECjJIPu5OynvJc,8381
|
|
140
|
+
signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-search.1,sha256=9jJ6V6t6DgmXByz8Lw9exjf683Cw3sJGro8-eB0M9EY,10413
|
|
141
|
+
signalwire_agents-1.0.17.dev4.data/data/share/man/man1/swaig-test.1,sha256=Ri0EITo8YMFowkcYltwPSwU4VJdRzo7XTWloi5WddCg,7815
|
|
142
|
+
signalwire_agents-1.0.17.dev4.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
|
|
143
|
+
signalwire_agents-1.0.17.dev4.dist-info/METADATA,sha256=cUBLrL5nVgu8q1agp7cMq4bOuRIcfPjZaWoIMETqFF8,41745
|
|
144
|
+
signalwire_agents-1.0.17.dev4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
145
|
+
signalwire_agents-1.0.17.dev4.dist-info/entry_points.txt,sha256=fMiBH-GLeXGaWWn58Mcj7KM_m3SdomQMUQu-1LTqscw,315
|
|
146
|
+
signalwire_agents-1.0.17.dev4.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
|
|
147
|
+
signalwire_agents-1.0.17.dev4.dist-info/RECORD,,
|
{signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/entry_points.txt
RENAMED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
[console_scripts]
|
|
2
|
+
mcp-gateway = signalwire_agents.mcp_gateway.gateway_service:main
|
|
3
|
+
sw-agent-dokku = signalwire_agents.cli.dokku:main
|
|
2
4
|
sw-agent-init = signalwire_agents.cli.init_project:main
|
|
3
5
|
sw-search = signalwire_agents.cli.build_search:console_entry_point
|
|
4
6
|
swaig-test = signalwire_agents.cli.swaig_test_wrapper:main
|
{signalwire_agents-1.0.7.data → signalwire_agents-1.0.17.dev4.data}/data/share/man/man1/sw-search.1
RENAMED
|
File without changes
|
{signalwire_agents-1.0.7.data → signalwire_agents-1.0.17.dev4.data}/data/share/man/man1/swaig-test.1
RENAMED
|
File without changes
|
|
File without changes
|
{signalwire_agents-1.0.7.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|