signalwire-agents 0.1.23__py3-none-any.whl → 0.1.25__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.
Files changed (64) hide show
  1. signalwire_agents/__init__.py +1 -1
  2. signalwire_agents/agent_server.py +2 -1
  3. signalwire_agents/cli/config.py +61 -0
  4. signalwire_agents/cli/core/__init__.py +1 -0
  5. signalwire_agents/cli/core/agent_loader.py +254 -0
  6. signalwire_agents/cli/core/argparse_helpers.py +164 -0
  7. signalwire_agents/cli/core/dynamic_config.py +62 -0
  8. signalwire_agents/cli/execution/__init__.py +1 -0
  9. signalwire_agents/cli/execution/datamap_exec.py +437 -0
  10. signalwire_agents/cli/execution/webhook_exec.py +125 -0
  11. signalwire_agents/cli/output/__init__.py +1 -0
  12. signalwire_agents/cli/output/output_formatter.py +132 -0
  13. signalwire_agents/cli/output/swml_dump.py +177 -0
  14. signalwire_agents/cli/simulation/__init__.py +1 -0
  15. signalwire_agents/cli/simulation/data_generation.py +365 -0
  16. signalwire_agents/cli/simulation/data_overrides.py +187 -0
  17. signalwire_agents/cli/simulation/mock_env.py +271 -0
  18. signalwire_agents/cli/test_swaig.py +522 -2539
  19. signalwire_agents/cli/types.py +72 -0
  20. signalwire_agents/core/agent/__init__.py +1 -3
  21. signalwire_agents/core/agent/config/__init__.py +1 -3
  22. signalwire_agents/core/agent/prompt/manager.py +25 -7
  23. signalwire_agents/core/agent/tools/decorator.py +2 -0
  24. signalwire_agents/core/agent/tools/registry.py +8 -0
  25. signalwire_agents/core/agent_base.py +492 -3053
  26. signalwire_agents/core/function_result.py +31 -42
  27. signalwire_agents/core/mixins/__init__.py +28 -0
  28. signalwire_agents/core/mixins/ai_config_mixin.py +373 -0
  29. signalwire_agents/core/mixins/auth_mixin.py +287 -0
  30. signalwire_agents/core/mixins/prompt_mixin.py +345 -0
  31. signalwire_agents/core/mixins/serverless_mixin.py +368 -0
  32. signalwire_agents/core/mixins/skill_mixin.py +55 -0
  33. signalwire_agents/core/mixins/state_mixin.py +219 -0
  34. signalwire_agents/core/mixins/tool_mixin.py +295 -0
  35. signalwire_agents/core/mixins/web_mixin.py +1130 -0
  36. signalwire_agents/core/skill_manager.py +3 -1
  37. signalwire_agents/core/swaig_function.py +10 -1
  38. signalwire_agents/core/swml_service.py +140 -58
  39. signalwire_agents/skills/README.md +452 -0
  40. signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
  41. signalwire_agents/skills/datasphere/README.md +210 -0
  42. signalwire_agents/skills/datasphere_serverless/README.md +258 -0
  43. signalwire_agents/skills/datetime/README.md +132 -0
  44. signalwire_agents/skills/joke/README.md +149 -0
  45. signalwire_agents/skills/math/README.md +161 -0
  46. signalwire_agents/skills/native_vector_search/skill.py +33 -13
  47. signalwire_agents/skills/play_background_file/README.md +218 -0
  48. signalwire_agents/skills/spider/README.md +236 -0
  49. signalwire_agents/skills/spider/__init__.py +4 -0
  50. signalwire_agents/skills/spider/skill.py +479 -0
  51. signalwire_agents/skills/swml_transfer/README.md +395 -0
  52. signalwire_agents/skills/swml_transfer/__init__.py +1 -0
  53. signalwire_agents/skills/swml_transfer/skill.py +257 -0
  54. signalwire_agents/skills/weather_api/README.md +178 -0
  55. signalwire_agents/skills/web_search/README.md +163 -0
  56. signalwire_agents/skills/wikipedia_search/README.md +228 -0
  57. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/METADATA +47 -2
  58. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/RECORD +62 -22
  59. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/entry_points.txt +1 -1
  60. signalwire_agents/core/agent/config/ephemeral.py +0 -176
  61. signalwire_agents-0.1.23.data/data/schema.json +0 -5611
  62. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/WHEEL +0 -0
  63. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/licenses/LICENSE +0 -0
  64. {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/top_level.txt +0 -0
@@ -188,7 +188,7 @@ class SwaigFunctionResult:
188
188
  self.action.append(swml_action)
189
189
  return self
190
190
 
191
- def swml_transfer(self, dest: str, ai_response: str) -> 'SwaigFunctionResult':
191
+ def swml_transfer(self, dest: str, ai_response: str, final: bool = True) -> 'SwaigFunctionResult':
192
192
  """
193
193
  Add a SWML transfer action with AI response setup for when transfer completes.
194
194
 
@@ -202,22 +202,28 @@ class SwaigFunctionResult:
202
202
  Args:
203
203
  dest: Destination URL for the transfer (SWML endpoint, SIP address, etc.)
204
204
  ai_response: Message the AI should say when transfer completes and control returns
205
+ final: Whether this is a permanent transfer (True) or temporary (False).
206
+ Defaults to True for permanent transfers (same as connect method).
205
207
 
206
208
  Returns:
207
209
  Self for method chaining
208
210
 
209
211
  Example:
210
- # Transfer with post-processing (speak first, then transfer)
212
+ # Permanent transfer (default)
211
213
  result = (
212
214
  SwaigFunctionResult("I'm transferring you to support", post_process=True)
213
215
  .swml_transfer(
214
216
  "https://support.example.com/swml",
215
- "The support call is complete. How else can I help?"
217
+ "Goodbye!" # Won't be used since final=True by default
216
218
  )
217
219
  )
218
220
 
219
- # Or enable post-processing with method chaining
220
- result.swml_transfer(dest, ai_response).set_post_process(True)
221
+ # Temporary transfer with return
222
+ result.swml_transfer(
223
+ dest,
224
+ "The support call is complete. How else can I help?",
225
+ final=False
226
+ )
221
227
  """
222
228
  # Create the SWML action structure directly
223
229
  swml_action = {
@@ -229,7 +235,8 @@ class SwaigFunctionResult:
229
235
  {"transfer": {"dest": dest}}
230
236
  ]
231
237
  }
232
- }
238
+ },
239
+ "transfer": str(final).lower() # Convert boolean to "true"/"false" string
233
240
  }
234
241
 
235
242
  # Add to actions list directly
@@ -251,8 +258,7 @@ class SwaigFunctionResult:
251
258
  Returns:
252
259
  self for method chaining
253
260
  """
254
- action = {"set_global_data": data}
255
- return self.add_action("set_global_data", action)
261
+ return self.add_action("set_global_data", data)
256
262
 
257
263
  def execute_swml(self, swml_content, transfer: bool = False) -> 'SwaigFunctionResult':
258
264
  """
@@ -294,8 +300,7 @@ class SwaigFunctionResult:
294
300
  Returns:
295
301
  self for method chaining
296
302
  """
297
- action = {"hangup": True}
298
- return self.add_action("hangup", action)
303
+ return self.add_action("hangup", True)
299
304
 
300
305
  def hold(self, timeout: int = 300) -> 'SwaigFunctionResult':
301
306
  """
@@ -309,8 +314,7 @@ class SwaigFunctionResult:
309
314
  """
310
315
  # Clamp timeout to valid range
311
316
  timeout = max(0, min(timeout, 900))
312
- action = {"hold": timeout}
313
- return self.add_action("hold", action)
317
+ return self.add_action("hold", timeout)
314
318
 
315
319
  def wait_for_user(self, enabled: Optional[bool] = None, timeout: Optional[int] = None, answer_first: bool = False) -> 'SwaigFunctionResult':
316
320
  """
@@ -333,8 +337,7 @@ class SwaigFunctionResult:
333
337
  else:
334
338
  wait_value = True
335
339
 
336
- action = {"wait_for_user": wait_value}
337
- return self.add_action("wait_for_user", action)
340
+ return self.add_action("wait_for_user", wait_value)
338
341
 
339
342
  def stop(self) -> 'SwaigFunctionResult':
340
343
  """
@@ -343,8 +346,7 @@ class SwaigFunctionResult:
343
346
  Returns:
344
347
  self for method chaining
345
348
  """
346
- action = {"stop": True}
347
- return self.add_action("stop", action)
349
+ return self.add_action("stop", True)
348
350
 
349
351
  def say(self, text: str) -> 'SwaigFunctionResult':
350
352
  """
@@ -356,8 +358,7 @@ class SwaigFunctionResult:
356
358
  Returns:
357
359
  self for method chaining
358
360
  """
359
- action = {"say": text}
360
- return self.add_action("say", action)
361
+ return self.add_action("say", text)
361
362
 
362
363
  def play_background_file(self, filename: str, wait: bool = False) -> 'SwaigFunctionResult':
363
364
  """
@@ -395,8 +396,7 @@ class SwaigFunctionResult:
395
396
  Returns:
396
397
  self for method chaining
397
398
  """
398
- action = {"end_of_speech_timeout": milliseconds}
399
- return self.add_action("end_of_speech_timeout", action)
399
+ return self.add_action("end_of_speech_timeout", milliseconds)
400
400
 
401
401
  def set_speech_event_timeout(self, milliseconds: int) -> 'SwaigFunctionResult':
402
402
  """
@@ -409,8 +409,7 @@ class SwaigFunctionResult:
409
409
  Returns:
410
410
  self for method chaining
411
411
  """
412
- action = {"speech_event_timeout": milliseconds}
413
- return self.add_action("speech_event_timeout", action)
412
+ return self.add_action("speech_event_timeout", milliseconds)
414
413
 
415
414
  def remove_global_data(self, keys: Union[str, List[str]]) -> 'SwaigFunctionResult':
416
415
  """
@@ -422,8 +421,7 @@ class SwaigFunctionResult:
422
421
  Returns:
423
422
  self for method chaining
424
423
  """
425
- action = {"unset_global_data": keys}
426
- return self.add_action("unset_global_data", action)
424
+ return self.add_action("unset_global_data", keys)
427
425
 
428
426
  def set_metadata(self, data: Dict[str, Any]) -> 'SwaigFunctionResult':
429
427
  """
@@ -435,8 +433,7 @@ class SwaigFunctionResult:
435
433
  Returns:
436
434
  self for method chaining
437
435
  """
438
- action = {"set_meta_data": data}
439
- return self.add_action("set_meta_data", action)
436
+ return self.add_action("set_meta_data", data)
440
437
 
441
438
  def remove_metadata(self, keys: Union[str, List[str]]) -> 'SwaigFunctionResult':
442
439
  """
@@ -448,8 +445,7 @@ class SwaigFunctionResult:
448
445
  Returns:
449
446
  self for method chaining
450
447
  """
451
- action = {"unset_meta_data": keys}
452
- return self.add_action("unset_meta_data", action)
448
+ return self.add_action("unset_meta_data", keys)
453
449
 
454
450
  def toggle_functions(self, function_toggles: List[Dict[str, Any]]) -> 'SwaigFunctionResult':
455
451
  """
@@ -461,8 +457,7 @@ class SwaigFunctionResult:
461
457
  Returns:
462
458
  self for method chaining
463
459
  """
464
- action = {"toggle_functions": function_toggles}
465
- return self.add_action("toggle_functions", action)
460
+ return self.add_action("toggle_functions", function_toggles)
466
461
 
467
462
  def enable_functions_on_timeout(self, enabled: bool = True) -> 'SwaigFunctionResult':
468
463
  """
@@ -474,8 +469,7 @@ class SwaigFunctionResult:
474
469
  Returns:
475
470
  self for method chaining
476
471
  """
477
- action = {"functions_on_speaker_timeout": enabled}
478
- return self.add_action("functions_on_speaker_timeout", action)
472
+ return self.add_action("functions_on_speaker_timeout", enabled)
479
473
 
480
474
  def enable_extensive_data(self, enabled: bool = True) -> 'SwaigFunctionResult':
481
475
  """
@@ -488,8 +482,7 @@ class SwaigFunctionResult:
488
482
  Returns:
489
483
  self for method chaining
490
484
  """
491
- action = {"extensive_data": enabled}
492
- return self.add_action("extensive_data", action)
485
+ return self.add_action("extensive_data", enabled)
493
486
 
494
487
  def update_settings(self, settings: Dict[str, Any]) -> 'SwaigFunctionResult':
495
488
  """
@@ -510,8 +503,7 @@ class SwaigFunctionResult:
510
503
  Returns:
511
504
  self for method chaining
512
505
  """
513
- action = {"settings": settings}
514
- return self.add_action("settings", action)
506
+ return self.add_action("settings", settings)
515
507
 
516
508
  def switch_context(self, system_prompt: Optional[str] = None, user_prompt: Optional[str] = None,
517
509
  consolidate: bool = False, full_reset: bool = False) -> 'SwaigFunctionResult':
@@ -529,7 +521,7 @@ class SwaigFunctionResult:
529
521
  """
530
522
  if system_prompt and not user_prompt and not consolidate and not full_reset:
531
523
  # Simple string context switch
532
- action = {"context_switch": system_prompt}
524
+ return self.add_action("context_switch", system_prompt)
533
525
  else:
534
526
  # Advanced object context switch
535
527
  context_data = {}
@@ -541,9 +533,7 @@ class SwaigFunctionResult:
541
533
  context_data["consolidate"] = True
542
534
  if full_reset:
543
535
  context_data["full_reset"] = True
544
- action = {"context_switch": context_data}
545
-
546
- return self.add_action("context_switch", action)
536
+ return self.add_action("context_switch", context_data)
547
537
 
548
538
  def simulate_user_input(self, text: str) -> 'SwaigFunctionResult':
549
539
  """
@@ -555,8 +545,7 @@ class SwaigFunctionResult:
555
545
  Returns:
556
546
  self for method chaining
557
547
  """
558
- action = {"user_input": text}
559
- return self.add_action("user_input", action)
548
+ return self.add_action("user_input", text)
560
549
 
561
550
  def send_sms(self, to_number: str, from_number: str, body: Optional[str] = None,
562
551
  media: Optional[List[str]] = None, tags: Optional[List[str]] = None,
@@ -0,0 +1,28 @@
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 .prompt_mixin import PromptMixin
11
+ from .tool_mixin import ToolMixin
12
+ from .web_mixin import WebMixin
13
+ from .auth_mixin import AuthMixin
14
+ from .skill_mixin import SkillMixin
15
+ from .ai_config_mixin import AIConfigMixin
16
+ from .serverless_mixin import ServerlessMixin
17
+ from .state_mixin import StateMixin
18
+
19
+ __all__ = [
20
+ 'PromptMixin',
21
+ 'ToolMixin',
22
+ 'WebMixin',
23
+ 'AuthMixin',
24
+ 'SkillMixin',
25
+ 'AIConfigMixin',
26
+ 'ServerlessMixin',
27
+ 'StateMixin'
28
+ ]
@@ -0,0 +1,373 @@
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 typing import List, Dict, Any, Optional
11
+
12
+
13
+ class AIConfigMixin:
14
+ """
15
+ Mixin class containing all AI configuration methods for AgentBase
16
+ """
17
+
18
+ def add_hint(self, hint: str) -> 'AgentBase':
19
+ """
20
+ Add a simple string hint to help the AI agent understand certain words better
21
+
22
+ Args:
23
+ hint: The hint string to add
24
+
25
+ Returns:
26
+ Self for method chaining
27
+ """
28
+ if isinstance(hint, str) and hint:
29
+ self._hints.append(hint)
30
+ return self
31
+
32
+ def add_hints(self, hints: List[str]) -> 'AgentBase':
33
+ """
34
+ Add multiple string hints
35
+
36
+ Args:
37
+ hints: List of hint strings
38
+
39
+ Returns:
40
+ Self for method chaining
41
+ """
42
+ if hints and isinstance(hints, list):
43
+ for hint in hints:
44
+ if isinstance(hint, str) and hint:
45
+ self._hints.append(hint)
46
+ return self
47
+
48
+ def add_pattern_hint(self,
49
+ hint: str,
50
+ pattern: str,
51
+ replace: str,
52
+ ignore_case: bool = False) -> 'AgentBase':
53
+ """
54
+ Add a complex hint with pattern matching
55
+
56
+ Args:
57
+ hint: The hint to match
58
+ pattern: Regular expression pattern
59
+ replace: Text to replace the hint with
60
+ ignore_case: Whether to ignore case when matching
61
+
62
+ Returns:
63
+ Self for method chaining
64
+ """
65
+ if hint and pattern and replace:
66
+ self._hints.append({
67
+ "hint": hint,
68
+ "pattern": pattern,
69
+ "replace": replace,
70
+ "ignore_case": ignore_case
71
+ })
72
+ return self
73
+
74
+ def add_language(self,
75
+ name: str,
76
+ code: str,
77
+ voice: str,
78
+ speech_fillers: Optional[List[str]] = None,
79
+ function_fillers: Optional[List[str]] = None,
80
+ engine: Optional[str] = None,
81
+ model: Optional[str] = None) -> 'AgentBase':
82
+ """
83
+ Add a language configuration to support multilingual conversations
84
+
85
+ Args:
86
+ name: Name of the language (e.g., "English", "French")
87
+ code: Language code (e.g., "en-US", "fr-FR")
88
+ voice: TTS voice to use. Can be a simple name (e.g., "en-US-Neural2-F")
89
+ or a combined format "engine.voice:model" (e.g., "elevenlabs.josh:eleven_turbo_v2_5")
90
+ speech_fillers: Optional list of filler phrases for natural speech
91
+ function_fillers: Optional list of filler phrases during function calls
92
+ engine: Optional explicit engine name (e.g., "elevenlabs", "rime")
93
+ model: Optional explicit model name (e.g., "eleven_turbo_v2_5", "arcana")
94
+
95
+ Returns:
96
+ Self for method chaining
97
+
98
+ Examples:
99
+ # Simple voice name
100
+ agent.add_language("English", "en-US", "en-US-Neural2-F")
101
+
102
+ # Explicit parameters
103
+ agent.add_language("English", "en-US", "josh", engine="elevenlabs", model="eleven_turbo_v2_5")
104
+
105
+ # Combined format
106
+ agent.add_language("English", "en-US", "elevenlabs.josh:eleven_turbo_v2_5")
107
+ """
108
+ language = {
109
+ "name": name,
110
+ "code": code
111
+ }
112
+
113
+ # Handle voice formatting (either explicit params or combined string)
114
+ if engine or model:
115
+ # Use explicit parameters if provided
116
+ language["voice"] = voice
117
+ if engine:
118
+ language["engine"] = engine
119
+ if model:
120
+ language["model"] = model
121
+ elif "." in voice and ":" in voice:
122
+ # Parse combined string format: "engine.voice:model"
123
+ try:
124
+ engine_voice, model_part = voice.split(":", 1)
125
+ engine_part, voice_part = engine_voice.split(".", 1)
126
+
127
+ language["voice"] = voice_part
128
+ language["engine"] = engine_part
129
+ language["model"] = model_part
130
+ except ValueError:
131
+ # If parsing fails, use the voice string as-is
132
+ language["voice"] = voice
133
+ else:
134
+ # Simple voice string
135
+ language["voice"] = voice
136
+
137
+ # Add fillers if provided
138
+ if speech_fillers and function_fillers:
139
+ language["speech_fillers"] = speech_fillers
140
+ language["function_fillers"] = function_fillers
141
+ elif speech_fillers or function_fillers:
142
+ # If only one type of fillers is provided, use the deprecated "fillers" field
143
+ fillers = speech_fillers or function_fillers
144
+ language["fillers"] = fillers
145
+
146
+ self._languages.append(language)
147
+ return self
148
+
149
+ def set_languages(self, languages: List[Dict[str, Any]]) -> 'AgentBase':
150
+ """
151
+ Set all language configurations at once
152
+
153
+ Args:
154
+ languages: List of language configuration dictionaries
155
+
156
+ Returns:
157
+ Self for method chaining
158
+ """
159
+ if languages and isinstance(languages, list):
160
+ self._languages = languages
161
+ return self
162
+
163
+ def add_pronunciation(self,
164
+ replace: str,
165
+ with_text: str,
166
+ ignore_case: bool = False) -> 'AgentBase':
167
+ """
168
+ Add a pronunciation rule to help the AI speak certain words correctly
169
+
170
+ Args:
171
+ replace: The expression to replace
172
+ with_text: The phonetic spelling to use instead
173
+ ignore_case: Whether to ignore case when matching
174
+
175
+ Returns:
176
+ Self for method chaining
177
+ """
178
+ if replace and with_text:
179
+ rule = {
180
+ "replace": replace,
181
+ "with": with_text
182
+ }
183
+ if ignore_case:
184
+ rule["ignore_case"] = True
185
+
186
+ self._pronounce.append(rule)
187
+ return self
188
+
189
+ def set_pronunciations(self, pronunciations: List[Dict[str, Any]]) -> 'AgentBase':
190
+ """
191
+ Set all pronunciation rules at once
192
+
193
+ Args:
194
+ pronunciations: List of pronunciation rule dictionaries
195
+
196
+ Returns:
197
+ Self for method chaining
198
+ """
199
+ if pronunciations and isinstance(pronunciations, list):
200
+ self._pronounce = pronunciations
201
+ return self
202
+
203
+ def set_param(self, key: str, value: Any) -> 'AgentBase':
204
+ """
205
+ Set a single AI parameter
206
+
207
+ Args:
208
+ key: Parameter name
209
+ value: Parameter value
210
+
211
+ Returns:
212
+ Self for method chaining
213
+ """
214
+ if key:
215
+ self._params[key] = value
216
+ return self
217
+
218
+ def set_params(self, params: Dict[str, Any]) -> 'AgentBase':
219
+ """
220
+ Set multiple AI parameters at once
221
+
222
+ Args:
223
+ params: Dictionary of parameter name/value pairs
224
+
225
+ Returns:
226
+ Self for method chaining
227
+ """
228
+ if params and isinstance(params, dict):
229
+ self._params.update(params)
230
+ return self
231
+
232
+ def set_global_data(self, data: Dict[str, Any]) -> 'AgentBase':
233
+ """
234
+ Set the global data available to the AI throughout the conversation
235
+
236
+ Args:
237
+ data: Dictionary of global data
238
+
239
+ Returns:
240
+ Self for method chaining
241
+ """
242
+ if data and isinstance(data, dict):
243
+ self._global_data = data
244
+ return self
245
+
246
+ def update_global_data(self, data: Dict[str, Any]) -> 'AgentBase':
247
+ """
248
+ Update the global data with new values
249
+
250
+ Args:
251
+ data: Dictionary of global data to update
252
+
253
+ Returns:
254
+ Self for method chaining
255
+ """
256
+ if data and isinstance(data, dict):
257
+ self._global_data.update(data)
258
+ return self
259
+
260
+ def set_native_functions(self, function_names: List[str]) -> 'AgentBase':
261
+ """
262
+ Set the list of native functions to enable
263
+
264
+ Args:
265
+ function_names: List of native function names
266
+
267
+ Returns:
268
+ Self for method chaining
269
+ """
270
+ if function_names and isinstance(function_names, list):
271
+ self.native_functions = [name for name in function_names if isinstance(name, str)]
272
+ return self
273
+
274
+ def set_internal_fillers(self, internal_fillers: Dict[str, Dict[str, List[str]]]) -> 'AgentBase':
275
+ """
276
+ Set internal fillers for native SWAIG functions
277
+
278
+ Internal fillers provide custom phrases the AI says while executing
279
+ internal/native functions like check_time, wait_for_user, next_step, etc.
280
+
281
+ Args:
282
+ internal_fillers: Dictionary mapping function names to language-specific filler phrases
283
+ Format: {"function_name": {"language_code": ["phrase1", "phrase2"]}}
284
+ Example: {"next_step": {"en-US": ["Moving to the next step...", "Great, let's continue..."]}}
285
+
286
+ Returns:
287
+ Self for method chaining
288
+
289
+ Example:
290
+ agent.set_internal_fillers({
291
+ "next_step": {
292
+ "en-US": ["Moving to the next step...", "Great, let's continue..."],
293
+ "es": ["Pasando al siguiente paso...", "Excelente, continuemos..."]
294
+ },
295
+ "check_time": {
296
+ "en-US": ["Let me check the time...", "Getting the current time..."]
297
+ }
298
+ })
299
+ """
300
+ if internal_fillers and isinstance(internal_fillers, dict):
301
+ if not hasattr(self, '_internal_fillers'):
302
+ self._internal_fillers = {}
303
+ self._internal_fillers.update(internal_fillers)
304
+ return self
305
+
306
+ def add_internal_filler(self, function_name: str, language_code: str, fillers: List[str]) -> 'AgentBase':
307
+ """
308
+ Add internal fillers for a specific function and language
309
+
310
+ Args:
311
+ function_name: Name of the internal function (e.g., 'next_step', 'check_time')
312
+ language_code: Language code (e.g., 'en-US', 'es', 'fr')
313
+ fillers: List of filler phrases for this function and language
314
+
315
+ Returns:
316
+ Self for method chaining
317
+
318
+ Example:
319
+ agent.add_internal_filler("next_step", "en-US", ["Moving to the next step...", "Great, let's continue..."])
320
+ """
321
+ if function_name and language_code and fillers and isinstance(fillers, list):
322
+ if not hasattr(self, '_internal_fillers'):
323
+ self._internal_fillers = {}
324
+
325
+ if function_name not in self._internal_fillers:
326
+ self._internal_fillers[function_name] = {}
327
+
328
+ self._internal_fillers[function_name][language_code] = fillers
329
+ return self
330
+
331
+ def add_function_include(self, url: str, functions: List[str], meta_data: Optional[Dict[str, Any]] = None) -> 'AgentBase':
332
+ """
333
+ Add a remote function include to the SWAIG configuration
334
+
335
+ Args:
336
+ url: URL to fetch remote functions from
337
+ functions: List of function names to include
338
+ meta_data: Optional metadata to include with the function include
339
+
340
+ Returns:
341
+ Self for method chaining
342
+ """
343
+ if url and functions and isinstance(functions, list):
344
+ include = {
345
+ "url": url,
346
+ "functions": functions
347
+ }
348
+ if meta_data and isinstance(meta_data, dict):
349
+ include["meta_data"] = meta_data
350
+
351
+ self._function_includes.append(include)
352
+ return self
353
+
354
+ def set_function_includes(self, includes: List[Dict[str, Any]]) -> 'AgentBase':
355
+ """
356
+ Set the complete list of function includes
357
+
358
+ Args:
359
+ includes: List of include objects, each with url and functions properties
360
+
361
+ Returns:
362
+ Self for method chaining
363
+ """
364
+ if includes and isinstance(includes, list):
365
+ # Validate each include has required properties
366
+ valid_includes = []
367
+ for include in includes:
368
+ if isinstance(include, dict) and "url" in include and "functions" in include:
369
+ if isinstance(include["functions"], list):
370
+ valid_includes.append(include)
371
+
372
+ self._function_includes = valid_includes
373
+ return self