signalwire-agents 0.1.13__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 +99 -15
- signalwire_agents/agent_server.py +248 -60
- signalwire_agents/agents/bedrock.py +296 -0
- signalwire_agents/cli/__init__.py +9 -0
- signalwire_agents/cli/build_search.py +951 -41
- signalwire_agents/cli/config.py +80 -0
- signalwire_agents/cli/core/__init__.py +10 -0
- signalwire_agents/cli/core/agent_loader.py +470 -0
- signalwire_agents/cli/core/argparse_helpers.py +179 -0
- signalwire_agents/cli/core/dynamic_config.py +71 -0
- signalwire_agents/cli/core/service_loader.py +303 -0
- signalwire_agents/cli/dokku.py +2320 -0
- signalwire_agents/cli/execution/__init__.py +10 -0
- signalwire_agents/cli/execution/datamap_exec.py +446 -0
- signalwire_agents/cli/execution/webhook_exec.py +134 -0
- signalwire_agents/cli/init_project.py +2636 -0
- signalwire_agents/cli/output/__init__.py +10 -0
- signalwire_agents/cli/output/output_formatter.py +255 -0
- signalwire_agents/cli/output/swml_dump.py +186 -0
- signalwire_agents/cli/simulation/__init__.py +10 -0
- signalwire_agents/cli/simulation/data_generation.py +374 -0
- signalwire_agents/cli/simulation/data_overrides.py +200 -0
- signalwire_agents/cli/simulation/mock_env.py +282 -0
- signalwire_agents/cli/swaig_test_wrapper.py +52 -0
- signalwire_agents/cli/test_swaig.py +566 -2366
- signalwire_agents/cli/types.py +81 -0
- signalwire_agents/core/__init__.py +2 -2
- signalwire_agents/core/agent/__init__.py +12 -0
- signalwire_agents/core/agent/config/__init__.py +12 -0
- signalwire_agents/core/agent/deployment/__init__.py +9 -0
- signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
- signalwire_agents/core/agent/prompt/__init__.py +14 -0
- signalwire_agents/core/agent/prompt/manager.py +306 -0
- signalwire_agents/core/agent/routing/__init__.py +9 -0
- signalwire_agents/core/agent/security/__init__.py +9 -0
- signalwire_agents/core/agent/swml/__init__.py +9 -0
- signalwire_agents/core/agent/tools/__init__.py +15 -0
- signalwire_agents/core/agent/tools/decorator.py +97 -0
- signalwire_agents/core/agent/tools/registry.py +210 -0
- signalwire_agents/core/agent_base.py +845 -2916
- signalwire_agents/core/auth_handler.py +233 -0
- signalwire_agents/core/config_loader.py +259 -0
- signalwire_agents/core/contexts.py +418 -0
- signalwire_agents/core/data_map.py +3 -15
- signalwire_agents/core/function_result.py +116 -44
- signalwire_agents/core/logging_config.py +162 -18
- signalwire_agents/core/mixins/__init__.py +28 -0
- signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
- signalwire_agents/core/mixins/auth_mixin.py +280 -0
- signalwire_agents/core/mixins/prompt_mixin.py +358 -0
- signalwire_agents/core/mixins/serverless_mixin.py +460 -0
- signalwire_agents/core/mixins/skill_mixin.py +55 -0
- signalwire_agents/core/mixins/state_mixin.py +153 -0
- signalwire_agents/core/mixins/tool_mixin.py +230 -0
- signalwire_agents/core/mixins/web_mixin.py +1142 -0
- signalwire_agents/core/security_config.py +333 -0
- signalwire_agents/core/skill_base.py +84 -1
- signalwire_agents/core/skill_manager.py +62 -20
- signalwire_agents/core/swaig_function.py +18 -5
- signalwire_agents/core/swml_builder.py +207 -11
- signalwire_agents/core/swml_handler.py +27 -21
- signalwire_agents/core/swml_renderer.py +123 -312
- signalwire_agents/core/swml_service.py +171 -203
- 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/prefabs/concierge.py +0 -3
- signalwire_agents/prefabs/faq_bot.py +0 -3
- signalwire_agents/prefabs/info_gatherer.py +0 -3
- signalwire_agents/prefabs/receptionist.py +0 -3
- signalwire_agents/prefabs/survey.py +0 -3
- signalwire_agents/schema.json +9218 -5489
- signalwire_agents/search/__init__.py +7 -1
- signalwire_agents/search/document_processor.py +490 -31
- signalwire_agents/search/index_builder.py +307 -37
- signalwire_agents/search/migration.py +418 -0
- signalwire_agents/search/models.py +30 -0
- signalwire_agents/search/pgvector_backend.py +748 -0
- signalwire_agents/search/query_processor.py +162 -31
- signalwire_agents/search/search_engine.py +916 -35
- signalwire_agents/search/search_service.py +376 -53
- signalwire_agents/skills/README.md +452 -0
- signalwire_agents/skills/__init__.py +14 -2
- signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
- signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
- signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
- signalwire_agents/skills/datasphere/README.md +210 -0
- signalwire_agents/skills/datasphere/skill.py +84 -3
- signalwire_agents/skills/datasphere_serverless/README.md +258 -0
- signalwire_agents/skills/datasphere_serverless/__init__.py +9 -0
- signalwire_agents/skills/datasphere_serverless/skill.py +82 -1
- signalwire_agents/skills/datetime/README.md +132 -0
- signalwire_agents/skills/datetime/__init__.py +9 -0
- signalwire_agents/skills/datetime/skill.py +20 -7
- signalwire_agents/skills/joke/README.md +149 -0
- signalwire_agents/skills/joke/__init__.py +9 -0
- signalwire_agents/skills/joke/skill.py +21 -0
- signalwire_agents/skills/math/README.md +161 -0
- signalwire_agents/skills/math/__init__.py +9 -0
- signalwire_agents/skills/math/skill.py +18 -4
- signalwire_agents/skills/mcp_gateway/README.md +230 -0
- signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
- signalwire_agents/skills/mcp_gateway/skill.py +421 -0
- signalwire_agents/skills/native_vector_search/README.md +210 -0
- signalwire_agents/skills/native_vector_search/__init__.py +9 -0
- signalwire_agents/skills/native_vector_search/skill.py +569 -101
- signalwire_agents/skills/play_background_file/README.md +218 -0
- signalwire_agents/skills/play_background_file/__init__.py +12 -0
- signalwire_agents/skills/play_background_file/skill.py +242 -0
- signalwire_agents/skills/registry.py +395 -40
- signalwire_agents/skills/spider/README.md +236 -0
- signalwire_agents/skills/spider/__init__.py +13 -0
- signalwire_agents/skills/spider/skill.py +598 -0
- signalwire_agents/skills/swml_transfer/README.md +395 -0
- signalwire_agents/skills/swml_transfer/__init__.py +10 -0
- signalwire_agents/skills/swml_transfer/skill.py +359 -0
- signalwire_agents/skills/weather_api/README.md +178 -0
- signalwire_agents/skills/weather_api/__init__.py +12 -0
- signalwire_agents/skills/weather_api/skill.py +191 -0
- signalwire_agents/skills/web_search/README.md +163 -0
- signalwire_agents/skills/web_search/__init__.py +9 -0
- signalwire_agents/skills/web_search/skill.py +586 -112
- signalwire_agents/skills/wikipedia_search/README.md +228 -0
- signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
- signalwire_agents/skills/{wikipedia → wikipedia_search}/skill.py +33 -3
- signalwire_agents/web/__init__.py +17 -0
- signalwire_agents/web/web_service.py +559 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-agent-init.1 +400 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-search.1 +483 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/swaig-test.1 +308 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/METADATA +347 -215
- signalwire_agents-1.0.17.dev4.dist-info/RECORD +147 -0
- signalwire_agents-1.0.17.dev4.dist-info/entry_points.txt +6 -0
- signalwire_agents/core/state/file_state_manager.py +0 -219
- signalwire_agents/core/state/state_manager.py +0 -101
- signalwire_agents/skills/wikipedia/__init__.py +0 -9
- signalwire_agents-0.1.13.data/data/schema.json +0 -5611
- signalwire_agents-0.1.13.dist-info/RECORD +0 -67
- signalwire_agents-0.1.13.dist-info/entry_points.txt +0 -3
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Play Background File Skill
|
|
2
|
+
|
|
3
|
+
A configurable skill for managing background file playback with custom tool names and multiple file collections. Supports both audio and video files with serverless DataMap execution.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Instances**: Create different tools with unique names and file sets
|
|
8
|
+
- **Dynamic Enum Generation**: Function parameters built from your file configuration
|
|
9
|
+
- **Audio & Video Support**: Works with any background file type
|
|
10
|
+
- **DataMap Efficiency**: Serverless execution, no agent processing load
|
|
11
|
+
- **Post-Processing**: AI speaks first, then executes the action
|
|
12
|
+
- **Configurable Wait**: Control attention-getting behavior per file
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
### Basic Structure
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
agent.add_skill("play_background_file", {
|
|
20
|
+
"tool_name": "your_custom_tool_name",
|
|
21
|
+
"files": [
|
|
22
|
+
{
|
|
23
|
+
"key": "unique_identifier",
|
|
24
|
+
"description": "Human readable description",
|
|
25
|
+
"url": "https://example.com/file.mp4",
|
|
26
|
+
"wait": True # Optional, defaults to False
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Parameters
|
|
33
|
+
|
|
34
|
+
- **tool_name** (string): Custom name for the generated SWAIG function (default: "play_background_file")
|
|
35
|
+
- **files** (array): List of file objects to manage
|
|
36
|
+
|
|
37
|
+
### File Object Properties
|
|
38
|
+
|
|
39
|
+
- **key** (string, required): Unique identifier for the file (alphanumeric, underscores, hyphens only)
|
|
40
|
+
- **description** (string, required): Human-readable description used in AI responses
|
|
41
|
+
- **url** (string, required): URL to the audio/video file
|
|
42
|
+
- **wait** (boolean, optional): Whether to suppress attention-getting behavior during playback (default: false)
|
|
43
|
+
|
|
44
|
+
## Usage Examples
|
|
45
|
+
|
|
46
|
+
### Single File Testimonial
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
agent.add_skill("play_background_file", {
|
|
50
|
+
"tool_name": "play_testimonial",
|
|
51
|
+
"files": [
|
|
52
|
+
{
|
|
53
|
+
"key": "massey_success",
|
|
54
|
+
"description": "Customer success story from Massey Energy",
|
|
55
|
+
"url": "https://tatooine.cantina.cloud/vids/massey.mp4",
|
|
56
|
+
"wait": True
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Generated Tool**: `play_testimonial(action)`
|
|
63
|
+
**Actions**: `["start_massey_success", "stop"]`
|
|
64
|
+
|
|
65
|
+
### Multiple Demo Videos
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
agent.add_skill("play_background_file", {
|
|
69
|
+
"tool_name": "play_demo",
|
|
70
|
+
"files": [
|
|
71
|
+
{
|
|
72
|
+
"key": "product_overview",
|
|
73
|
+
"description": "Product overview demonstration",
|
|
74
|
+
"url": "https://example.com/overview.mp4",
|
|
75
|
+
"wait": False
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"key": "advanced_features",
|
|
79
|
+
"description": "Advanced features walkthrough",
|
|
80
|
+
"url": "https://example.com/advanced.mp4",
|
|
81
|
+
"wait": True
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Generated Tool**: `play_demo(action)`
|
|
88
|
+
**Actions**: `["start_product_overview", "start_advanced_features", "stop"]`
|
|
89
|
+
|
|
90
|
+
### Music Playlist
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
agent.add_skill("play_background_file", {
|
|
94
|
+
"tool_name": "play_music",
|
|
95
|
+
"files": [
|
|
96
|
+
{
|
|
97
|
+
"key": "jazz",
|
|
98
|
+
"description": "smooth jazz background music",
|
|
99
|
+
"url": "https://example.com/jazz.mp3"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"key": "classical",
|
|
103
|
+
"description": "classical piano background music",
|
|
104
|
+
"url": "https://example.com/classical.mp3"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Generated SWAIG Function
|
|
111
|
+
|
|
112
|
+
For the testimonial example above, the skill generates:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"function": "play_testimonial",
|
|
117
|
+
"description": "Control background file playback for play testimonial",
|
|
118
|
+
"parameters": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": {
|
|
121
|
+
"action": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Action to perform. Options: start_massey_success: Customer success story from Massey Energy; stop: Stop any currently playing background file",
|
|
124
|
+
"enum": ["start_massey_success", "stop"]
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": ["action"]
|
|
128
|
+
},
|
|
129
|
+
"data_map": {
|
|
130
|
+
"expressions": [
|
|
131
|
+
{
|
|
132
|
+
"string": "${args.action}",
|
|
133
|
+
"pattern": "/start_massey_success/i",
|
|
134
|
+
"output": {
|
|
135
|
+
"response": "Tell the user you are now going to play Customer success story from Massey Energy for them.",
|
|
136
|
+
"action": [
|
|
137
|
+
{
|
|
138
|
+
"playback_bg": {
|
|
139
|
+
"file": "https://tatooine.cantina.cloud/vids/massey.mp4",
|
|
140
|
+
"wait": true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"post_process": true
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"string": "${args.action}",
|
|
149
|
+
"pattern": "/stop/i",
|
|
150
|
+
"output": {
|
|
151
|
+
"response": "Tell the user you have stopped the background file playback.",
|
|
152
|
+
"action": [
|
|
153
|
+
{
|
|
154
|
+
"stop_playback_bg": true
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"post_process": true
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Execution Flow
|
|
166
|
+
|
|
167
|
+
1. **AI calls function**: `play_testimonial(action: "start_massey_success")`
|
|
168
|
+
2. **DataMap matches pattern**: `/start_massey_success/i`
|
|
169
|
+
3. **AI receives instruction**: "Tell the user you are now going to play Customer success story from Massey Energy for them."
|
|
170
|
+
4. **AI responds naturally**: The AI interprets this and responds in its own voice
|
|
171
|
+
5. **Action executes**: Background video starts playing
|
|
172
|
+
6. **User experience**: Natural AI announcement before action
|
|
173
|
+
|
|
174
|
+
## Multiple Instances
|
|
175
|
+
|
|
176
|
+
You can add multiple instances of this skill with different tool names:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
# Testimonials
|
|
180
|
+
agent.add_skill("play_background_file", {
|
|
181
|
+
"tool_name": "play_testimonial",
|
|
182
|
+
"files": [{"key": "massey", "description": "Massey Energy success story", "url": "..."}]
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
# Demos
|
|
186
|
+
agent.add_skill("play_background_file", {
|
|
187
|
+
"tool_name": "play_demo",
|
|
188
|
+
"files": [
|
|
189
|
+
{"key": "overview", "description": "Product overview", "url": "..."},
|
|
190
|
+
{"key": "features", "description": "Advanced features", "url": "..."}
|
|
191
|
+
]
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
# Music
|
|
195
|
+
agent.add_skill("play_background_file", {
|
|
196
|
+
"tool_name": "play_music",
|
|
197
|
+
"files": [{"key": "jazz", "description": "Jazz music", "url": "..."}]
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
This creates three separate tools: `play_testimonial`, `play_demo`, and `play_music`.
|
|
202
|
+
|
|
203
|
+
## Benefits
|
|
204
|
+
|
|
205
|
+
- **Reusable**: Same skill manages different file collections
|
|
206
|
+
- **Configurable**: Easy to add/remove files without code changes
|
|
207
|
+
- **Efficient**: DataMap serverless execution
|
|
208
|
+
- **Type Safe**: Enum parameters prevent invalid file references
|
|
209
|
+
- **Natural**: AI speaks before actions with post-processing
|
|
210
|
+
- **Maintainable**: Centralized file management logic
|
|
211
|
+
|
|
212
|
+
## Implementation Notes
|
|
213
|
+
|
|
214
|
+
- File keys are converted to `start_{key}` enum values
|
|
215
|
+
- All tools include a "stop" action to halt playback
|
|
216
|
+
- Post-processing is enabled by default for natural conversation flow
|
|
217
|
+
- The skill validates all configuration parameters at initialization
|
|
218
|
+
- Instance keys combine skill name and tool name for uniqueness
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2025 SignalWire
|
|
3
|
+
|
|
4
|
+
This file is part of the SignalWire AI Agents SDK.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License.
|
|
7
|
+
See LICENSE file in the project root for full license information.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .skill import PlayBackgroundFileSkill
|
|
11
|
+
|
|
12
|
+
__all__ = ['PlayBackgroundFileSkill']
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2025 SignalWire
|
|
3
|
+
|
|
4
|
+
This file is part of the SignalWire AI Agents SDK.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License.
|
|
7
|
+
See LICENSE file in the project root for full license information.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
Play Background File Skill
|
|
12
|
+
|
|
13
|
+
A configurable skill for managing background file playback with custom tool names
|
|
14
|
+
and multiple file collections. Supports both audio and video files.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from typing import Dict, Any, List
|
|
18
|
+
from signalwire_agents.core import SwaigFunctionResult
|
|
19
|
+
from signalwire_agents.core.skill_base import SkillBase
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PlayBackgroundFileSkill(SkillBase):
|
|
23
|
+
"""
|
|
24
|
+
Skill for playing background files (audio/video) with configurable tool names.
|
|
25
|
+
|
|
26
|
+
Supports multiple instances with different tool names and file collections.
|
|
27
|
+
Uses DataMap for serverless execution with dynamic enum generation.
|
|
28
|
+
|
|
29
|
+
Configuration:
|
|
30
|
+
- tool_name: Custom name for the generated SWAIG function
|
|
31
|
+
- files: Array of file objects with key, description, url, and optional wait
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
agent.add_skill("play_background_file", {
|
|
35
|
+
"tool_name": "play_testimonial",
|
|
36
|
+
"files": [
|
|
37
|
+
{
|
|
38
|
+
"key": "massey",
|
|
39
|
+
"description": "Customer success story from Massey Energy",
|
|
40
|
+
"url": "https://example.com/massey.mp4",
|
|
41
|
+
"wait": True
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
})
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
SKILL_NAME = "play_background_file"
|
|
48
|
+
SKILL_DESCRIPTION = "Control background file playback"
|
|
49
|
+
SUPPORTS_MULTIPLE_INSTANCES = True
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
|
|
53
|
+
"""Get parameter schema for Play Background File skill"""
|
|
54
|
+
schema = super().get_parameter_schema()
|
|
55
|
+
schema.update({
|
|
56
|
+
"files": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"description": "Array of file configurations to make available for playback",
|
|
59
|
+
"required": True,
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"key": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Unique identifier for the file"
|
|
66
|
+
},
|
|
67
|
+
"description": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Human-readable description of the file"
|
|
70
|
+
},
|
|
71
|
+
"url": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "URL of the audio/video file to play"
|
|
74
|
+
},
|
|
75
|
+
"wait": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"description": "Whether to wait for file to finish playing",
|
|
78
|
+
"default": False
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"required": ["key", "description", "url"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
return schema
|
|
86
|
+
|
|
87
|
+
def __init__(self, agent, params: Dict[str, Any] = None):
|
|
88
|
+
"""
|
|
89
|
+
Initialize the skill with configuration parameters.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
agent: The agent instance this skill belongs to
|
|
93
|
+
params: Configuration dictionary containing:
|
|
94
|
+
- tool_name: Custom tool name (default: "play_background_file")
|
|
95
|
+
- files: Array of file objects with key, description, url, wait
|
|
96
|
+
"""
|
|
97
|
+
super().__init__(agent, params)
|
|
98
|
+
|
|
99
|
+
# Extract configuration
|
|
100
|
+
self.tool_name = self.params.get('tool_name', 'play_background_file')
|
|
101
|
+
self.files = self.params.get('files', [])
|
|
102
|
+
|
|
103
|
+
# Validate configuration
|
|
104
|
+
self._validate_config()
|
|
105
|
+
|
|
106
|
+
def _validate_config(self):
|
|
107
|
+
"""Validate the skill configuration."""
|
|
108
|
+
if not isinstance(self.files, list) or len(self.files) == 0:
|
|
109
|
+
raise ValueError("files parameter must be a non-empty list")
|
|
110
|
+
|
|
111
|
+
for i, file_obj in enumerate(self.files):
|
|
112
|
+
if not isinstance(file_obj, dict):
|
|
113
|
+
raise ValueError(f"File {i} must be a dictionary")
|
|
114
|
+
|
|
115
|
+
required_fields = ['key', 'description', 'url']
|
|
116
|
+
for field in required_fields:
|
|
117
|
+
if field not in file_obj:
|
|
118
|
+
raise ValueError(f"File {i} missing required field: {field}")
|
|
119
|
+
if not isinstance(file_obj[field], str) or not file_obj[field].strip():
|
|
120
|
+
raise ValueError(f"File {i} field '{field}' must be a non-empty string")
|
|
121
|
+
|
|
122
|
+
# Validate optional wait field
|
|
123
|
+
if 'wait' in file_obj and not isinstance(file_obj['wait'], bool):
|
|
124
|
+
raise ValueError(f"File {i} field 'wait' must be a boolean")
|
|
125
|
+
|
|
126
|
+
# Validate key format (alphanumeric, underscores, hyphens)
|
|
127
|
+
key = file_obj['key']
|
|
128
|
+
if not key.replace('_', '').replace('-', '').isalnum():
|
|
129
|
+
raise ValueError(f"File {i} key '{key}' must contain only alphanumeric characters, underscores, and hyphens")
|
|
130
|
+
|
|
131
|
+
def get_instance_key(self) -> str:
|
|
132
|
+
"""
|
|
133
|
+
Generate a unique instance key for this skill configuration.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Unique key combining skill name and tool name
|
|
137
|
+
"""
|
|
138
|
+
return f"{self.SKILL_NAME}_{self.tool_name}"
|
|
139
|
+
|
|
140
|
+
def setup(self) -> bool:
|
|
141
|
+
"""
|
|
142
|
+
Setup the skill - no external dependencies needed.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
True if setup successful
|
|
146
|
+
"""
|
|
147
|
+
return True
|
|
148
|
+
|
|
149
|
+
def register_tools(self) -> None:
|
|
150
|
+
"""Register SWAIG tools with the agent"""
|
|
151
|
+
tools = self.get_tools()
|
|
152
|
+
for tool in tools:
|
|
153
|
+
# Merge any swaig_fields from params into the tool
|
|
154
|
+
if self.swaig_fields:
|
|
155
|
+
tool.update(self.swaig_fields)
|
|
156
|
+
self.agent.register_swaig_function(tool)
|
|
157
|
+
|
|
158
|
+
def get_tools(self) -> List[Dict[str, Any]]:
|
|
159
|
+
"""
|
|
160
|
+
Generate the SWAIG tool with DataMap expressions.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List containing the generated tool configuration
|
|
164
|
+
"""
|
|
165
|
+
# Build enum values and descriptions
|
|
166
|
+
enum_values = []
|
|
167
|
+
descriptions = []
|
|
168
|
+
|
|
169
|
+
for file_obj in self.files:
|
|
170
|
+
enum_values.append(f"start_{file_obj['key']}")
|
|
171
|
+
descriptions.append(f"start_{file_obj['key']}: {file_obj['description']}")
|
|
172
|
+
|
|
173
|
+
enum_values.append("stop")
|
|
174
|
+
descriptions.append("stop: Stop any currently playing background file")
|
|
175
|
+
|
|
176
|
+
# Build parameter description
|
|
177
|
+
description = "Action to perform. Options: " + "; ".join(descriptions)
|
|
178
|
+
|
|
179
|
+
# Create the tool configuration
|
|
180
|
+
tool = {
|
|
181
|
+
"function": self.tool_name,
|
|
182
|
+
"description": f"Control background file playback for {self.tool_name.replace('_', ' ')}",
|
|
183
|
+
"parameters": {
|
|
184
|
+
"type": "object",
|
|
185
|
+
"properties": {
|
|
186
|
+
"action": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"description": description,
|
|
189
|
+
"enum": enum_values
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"required": ["action"]
|
|
193
|
+
},
|
|
194
|
+
"wait_for_fillers": True,
|
|
195
|
+
"skip_fillers": True,
|
|
196
|
+
"data_map": {
|
|
197
|
+
"expressions": self._build_expressions()
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return [tool]
|
|
202
|
+
|
|
203
|
+
def _build_expressions(self) -> List[Dict[str, Any]]:
|
|
204
|
+
"""
|
|
205
|
+
Build DataMap expressions for file playback and stop actions.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
List of expression configurations
|
|
209
|
+
"""
|
|
210
|
+
expressions = []
|
|
211
|
+
|
|
212
|
+
# Add expressions for each file
|
|
213
|
+
for file_obj in self.files:
|
|
214
|
+
key = file_obj['key']
|
|
215
|
+
url = file_obj['url']
|
|
216
|
+
wait = file_obj.get('wait', False)
|
|
217
|
+
description = file_obj['description']
|
|
218
|
+
|
|
219
|
+
# Create the result with appropriate response
|
|
220
|
+
result = SwaigFunctionResult(
|
|
221
|
+
f"Tell the user you are now going to play {description} for them.",
|
|
222
|
+
post_process=True
|
|
223
|
+
).play_background_file(url, wait=wait)
|
|
224
|
+
|
|
225
|
+
expressions.append({
|
|
226
|
+
"string": "${args.action}",
|
|
227
|
+
"pattern": f"/start_{key}/i",
|
|
228
|
+
"output": result.to_dict()
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
# Add stop expression
|
|
232
|
+
stop_result = SwaigFunctionResult(
|
|
233
|
+
"Tell the user you have stopped the background file playback."
|
|
234
|
+
).stop_background_file()
|
|
235
|
+
|
|
236
|
+
expressions.append({
|
|
237
|
+
"string": "${args.action}",
|
|
238
|
+
"pattern": "/stop/i",
|
|
239
|
+
"output": stop_result.to_dict()
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
return expressions
|