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
|
@@ -1,3 +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
|
+
|
|
1
10
|
"""
|
|
2
11
|
Contexts and Steps System for SignalWire Agents
|
|
3
12
|
|
|
@@ -18,9 +27,16 @@ class Step:
|
|
|
18
27
|
self._step_criteria: Optional[str] = None
|
|
19
28
|
self._functions: Optional[Union[str, List[str]]] = None
|
|
20
29
|
self._valid_steps: Optional[List[str]] = None
|
|
30
|
+
self._valid_contexts: Optional[List[str]] = None
|
|
21
31
|
|
|
22
32
|
# POM-style sections for rich prompts
|
|
23
33
|
self._sections: List[Dict[str, Any]] = []
|
|
34
|
+
|
|
35
|
+
# Reset object for context switching from steps
|
|
36
|
+
self._reset_system_prompt: Optional[str] = None
|
|
37
|
+
self._reset_user_prompt: Optional[str] = None
|
|
38
|
+
self._reset_consolidate: bool = False
|
|
39
|
+
self._reset_full_reset: bool = False
|
|
24
40
|
|
|
25
41
|
def set_text(self, text: str) -> 'Step':
|
|
26
42
|
"""
|
|
@@ -108,6 +124,71 @@ class Step:
|
|
|
108
124
|
self._valid_steps = steps
|
|
109
125
|
return self
|
|
110
126
|
|
|
127
|
+
def set_valid_contexts(self, contexts: List[str]) -> 'Step':
|
|
128
|
+
"""
|
|
129
|
+
Set which contexts can be navigated to from this step
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
contexts: List of valid context names
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Self for method chaining
|
|
136
|
+
"""
|
|
137
|
+
self._valid_contexts = contexts
|
|
138
|
+
return self
|
|
139
|
+
|
|
140
|
+
def set_reset_system_prompt(self, system_prompt: str) -> 'Step':
|
|
141
|
+
"""
|
|
142
|
+
Set system prompt for context switching when this step navigates to a context
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
system_prompt: New system prompt for context switching
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Self for method chaining
|
|
149
|
+
"""
|
|
150
|
+
self._reset_system_prompt = system_prompt
|
|
151
|
+
return self
|
|
152
|
+
|
|
153
|
+
def set_reset_user_prompt(self, user_prompt: str) -> 'Step':
|
|
154
|
+
"""
|
|
155
|
+
Set user prompt for context switching when this step navigates to a context
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
user_prompt: User message to inject for context switching
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
Self for method chaining
|
|
162
|
+
"""
|
|
163
|
+
self._reset_user_prompt = user_prompt
|
|
164
|
+
return self
|
|
165
|
+
|
|
166
|
+
def set_reset_consolidate(self, consolidate: bool) -> 'Step':
|
|
167
|
+
"""
|
|
168
|
+
Set whether to consolidate conversation when this step switches contexts
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
consolidate: Whether to consolidate previous conversation
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Self for method chaining
|
|
175
|
+
"""
|
|
176
|
+
self._reset_consolidate = consolidate
|
|
177
|
+
return self
|
|
178
|
+
|
|
179
|
+
def set_reset_full_reset(self, full_reset: bool) -> 'Step':
|
|
180
|
+
"""
|
|
181
|
+
Set whether to do full reset when this step switches contexts
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
full_reset: Whether to completely rewrite system prompt vs inject
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Self for method chaining
|
|
188
|
+
"""
|
|
189
|
+
self._reset_full_reset = full_reset
|
|
190
|
+
return self
|
|
191
|
+
|
|
111
192
|
def _render_text(self) -> str:
|
|
112
193
|
"""Render the step's prompt text"""
|
|
113
194
|
if self._text is not None:
|
|
@@ -133,6 +214,7 @@ class Step:
|
|
|
133
214
|
def to_dict(self) -> Dict[str, Any]:
|
|
134
215
|
"""Convert step to dictionary for SWML generation"""
|
|
135
216
|
step_dict = {
|
|
217
|
+
"name": self.name,
|
|
136
218
|
"text": self._render_text()
|
|
137
219
|
}
|
|
138
220
|
|
|
@@ -145,6 +227,23 @@ class Step:
|
|
|
145
227
|
if self._valid_steps is not None:
|
|
146
228
|
step_dict["valid_steps"] = self._valid_steps
|
|
147
229
|
|
|
230
|
+
if self._valid_contexts is not None:
|
|
231
|
+
step_dict["valid_contexts"] = self._valid_contexts
|
|
232
|
+
|
|
233
|
+
# Add reset object if any reset parameters are set
|
|
234
|
+
reset_obj = {}
|
|
235
|
+
if self._reset_system_prompt is not None:
|
|
236
|
+
reset_obj["system_prompt"] = self._reset_system_prompt
|
|
237
|
+
if self._reset_user_prompt is not None:
|
|
238
|
+
reset_obj["user_prompt"] = self._reset_user_prompt
|
|
239
|
+
if self._reset_consolidate:
|
|
240
|
+
reset_obj["consolidate"] = self._reset_consolidate
|
|
241
|
+
if self._reset_full_reset:
|
|
242
|
+
reset_obj["full_reset"] = self._reset_full_reset
|
|
243
|
+
|
|
244
|
+
if reset_obj:
|
|
245
|
+
step_dict["reset"] = reset_obj
|
|
246
|
+
|
|
148
247
|
return step_dict
|
|
149
248
|
|
|
150
249
|
|
|
@@ -156,6 +255,23 @@ class Context:
|
|
|
156
255
|
self._steps: Dict[str, Step] = {}
|
|
157
256
|
self._step_order: List[str] = []
|
|
158
257
|
self._valid_contexts: Optional[List[str]] = None
|
|
258
|
+
|
|
259
|
+
# Context entry parameters
|
|
260
|
+
self._post_prompt: Optional[str] = None
|
|
261
|
+
self._system_prompt: Optional[str] = None
|
|
262
|
+
self._system_prompt_sections: List[Dict[str, Any]] = [] # For POM-style system prompts
|
|
263
|
+
self._consolidate: bool = False
|
|
264
|
+
self._full_reset: bool = False
|
|
265
|
+
self._user_prompt: Optional[str] = None
|
|
266
|
+
self._isolated: bool = False
|
|
267
|
+
|
|
268
|
+
# Context prompt (separate from system_prompt)
|
|
269
|
+
self._prompt_text: Optional[str] = None
|
|
270
|
+
self._prompt_sections: List[Dict[str, Any]] = []
|
|
271
|
+
|
|
272
|
+
# Context fillers
|
|
273
|
+
self._enter_fillers: Optional[Dict[str, List[str]]] = None
|
|
274
|
+
self._exit_fillers: Optional[Dict[str, List[str]]] = None
|
|
159
275
|
|
|
160
276
|
def add_step(self, name: str) -> Step:
|
|
161
277
|
"""
|
|
@@ -188,6 +304,273 @@ class Context:
|
|
|
188
304
|
self._valid_contexts = contexts
|
|
189
305
|
return self
|
|
190
306
|
|
|
307
|
+
def set_post_prompt(self, post_prompt: str) -> 'Context':
|
|
308
|
+
"""
|
|
309
|
+
Set post prompt override for this context
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
post_prompt: Post prompt text to use when this context is active
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Self for method chaining
|
|
316
|
+
"""
|
|
317
|
+
self._post_prompt = post_prompt
|
|
318
|
+
return self
|
|
319
|
+
|
|
320
|
+
def set_system_prompt(self, system_prompt: str) -> 'Context':
|
|
321
|
+
"""
|
|
322
|
+
Set system prompt for context switching (triggers context reset)
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
system_prompt: New system prompt for when this context is entered
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
Self for method chaining
|
|
329
|
+
"""
|
|
330
|
+
if self._system_prompt_sections:
|
|
331
|
+
raise ValueError("Cannot use set_system_prompt() when POM sections have been added for system prompt. Use one approach or the other.")
|
|
332
|
+
self._system_prompt = system_prompt
|
|
333
|
+
return self
|
|
334
|
+
|
|
335
|
+
def set_consolidate(self, consolidate: bool) -> 'Context':
|
|
336
|
+
"""
|
|
337
|
+
Set whether to consolidate conversation history when entering this context
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
consolidate: Whether to consolidate previous conversation
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
Self for method chaining
|
|
344
|
+
"""
|
|
345
|
+
self._consolidate = consolidate
|
|
346
|
+
return self
|
|
347
|
+
|
|
348
|
+
def set_full_reset(self, full_reset: bool) -> 'Context':
|
|
349
|
+
"""
|
|
350
|
+
Set whether to do full reset when entering this context
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
full_reset: Whether to completely rewrite system prompt vs inject
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
Self for method chaining
|
|
357
|
+
"""
|
|
358
|
+
self._full_reset = full_reset
|
|
359
|
+
return self
|
|
360
|
+
|
|
361
|
+
def set_user_prompt(self, user_prompt: str) -> 'Context':
|
|
362
|
+
"""
|
|
363
|
+
Set user prompt to inject when entering this context
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
user_prompt: User message to inject for context
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Self for method chaining
|
|
370
|
+
"""
|
|
371
|
+
self._user_prompt = user_prompt
|
|
372
|
+
return self
|
|
373
|
+
|
|
374
|
+
def set_isolated(self, isolated: bool) -> 'Context':
|
|
375
|
+
"""
|
|
376
|
+
Set whether to truncate conversation history when entering this context
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
isolated: Whether to truncate conversation on context switch
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
Self for method chaining
|
|
383
|
+
"""
|
|
384
|
+
self._isolated = isolated
|
|
385
|
+
return self
|
|
386
|
+
|
|
387
|
+
def add_system_section(self, title: str, body: str) -> 'Context':
|
|
388
|
+
"""
|
|
389
|
+
Add a POM section to the system prompt
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
title: Section title
|
|
393
|
+
body: Section body text
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
Self for method chaining
|
|
397
|
+
"""
|
|
398
|
+
if self._system_prompt is not None:
|
|
399
|
+
raise ValueError("Cannot add POM sections for system prompt when set_system_prompt() has been used. Use one approach or the other.")
|
|
400
|
+
self._system_prompt_sections.append({"title": title, "body": body})
|
|
401
|
+
return self
|
|
402
|
+
|
|
403
|
+
def add_system_bullets(self, title: str, bullets: List[str]) -> 'Context':
|
|
404
|
+
"""
|
|
405
|
+
Add a POM section with bullet points to the system prompt
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
title: Section title
|
|
409
|
+
bullets: List of bullet points
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Self for method chaining
|
|
413
|
+
"""
|
|
414
|
+
if self._system_prompt is not None:
|
|
415
|
+
raise ValueError("Cannot add POM sections for system prompt when set_system_prompt() has been used. Use one approach or the other.")
|
|
416
|
+
self._system_prompt_sections.append({"title": title, "bullets": bullets})
|
|
417
|
+
return self
|
|
418
|
+
|
|
419
|
+
def set_prompt(self, prompt: str) -> 'Context':
|
|
420
|
+
"""
|
|
421
|
+
Set the context's prompt text directly
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
prompt: The prompt text for this context
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
Self for method chaining
|
|
428
|
+
"""
|
|
429
|
+
if self._prompt_sections:
|
|
430
|
+
raise ValueError("Cannot use set_prompt() when POM sections have been added. Use one approach or the other.")
|
|
431
|
+
self._prompt_text = prompt
|
|
432
|
+
return self
|
|
433
|
+
|
|
434
|
+
def add_section(self, title: str, body: str) -> 'Context':
|
|
435
|
+
"""
|
|
436
|
+
Add a POM section to the context prompt
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
title: Section title
|
|
440
|
+
body: Section body text
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Self for method chaining
|
|
444
|
+
"""
|
|
445
|
+
if self._prompt_text is not None:
|
|
446
|
+
raise ValueError("Cannot add POM sections when set_prompt() has been used. Use one approach or the other.")
|
|
447
|
+
self._prompt_sections.append({"title": title, "body": body})
|
|
448
|
+
return self
|
|
449
|
+
|
|
450
|
+
def add_bullets(self, title: str, bullets: List[str]) -> 'Context':
|
|
451
|
+
"""
|
|
452
|
+
Add a POM section with bullet points to the context prompt
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
title: Section title
|
|
456
|
+
bullets: List of bullet points
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
Self for method chaining
|
|
460
|
+
"""
|
|
461
|
+
if self._prompt_text is not None:
|
|
462
|
+
raise ValueError("Cannot add POM sections when set_prompt() has been used. Use one approach or the other.")
|
|
463
|
+
self._prompt_sections.append({"title": title, "bullets": bullets})
|
|
464
|
+
return self
|
|
465
|
+
|
|
466
|
+
def set_enter_fillers(self, enter_fillers: Dict[str, List[str]]) -> 'Context':
|
|
467
|
+
"""
|
|
468
|
+
Set fillers that the AI says when entering this context
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
enter_fillers: Dictionary mapping language codes (or "default") to lists of filler phrases
|
|
472
|
+
Example: {"en-US": ["Welcome...", "Hello..."], "default": ["Entering..."]}
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
Self for method chaining
|
|
476
|
+
"""
|
|
477
|
+
if enter_fillers and isinstance(enter_fillers, dict):
|
|
478
|
+
self._enter_fillers = enter_fillers
|
|
479
|
+
return self
|
|
480
|
+
|
|
481
|
+
def set_exit_fillers(self, exit_fillers: Dict[str, List[str]]) -> 'Context':
|
|
482
|
+
"""
|
|
483
|
+
Set fillers that the AI says when exiting this context
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
exit_fillers: Dictionary mapping language codes (or "default") to lists of filler phrases
|
|
487
|
+
Example: {"en-US": ["Goodbye...", "Thank you..."], "default": ["Exiting..."]}
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
Self for method chaining
|
|
491
|
+
"""
|
|
492
|
+
if exit_fillers and isinstance(exit_fillers, dict):
|
|
493
|
+
self._exit_fillers = exit_fillers
|
|
494
|
+
return self
|
|
495
|
+
|
|
496
|
+
def add_enter_filler(self, language_code: str, fillers: List[str]) -> 'Context':
|
|
497
|
+
"""
|
|
498
|
+
Add enter fillers for a specific language
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
language_code: Language code (e.g., "en-US", "es") or "default" for catch-all
|
|
502
|
+
fillers: List of filler phrases for entering this context
|
|
503
|
+
|
|
504
|
+
Returns:
|
|
505
|
+
Self for method chaining
|
|
506
|
+
"""
|
|
507
|
+
if language_code and fillers and isinstance(fillers, list):
|
|
508
|
+
if self._enter_fillers is None:
|
|
509
|
+
self._enter_fillers = {}
|
|
510
|
+
self._enter_fillers[language_code] = fillers
|
|
511
|
+
return self
|
|
512
|
+
|
|
513
|
+
def add_exit_filler(self, language_code: str, fillers: List[str]) -> 'Context':
|
|
514
|
+
"""
|
|
515
|
+
Add exit fillers for a specific language
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
language_code: Language code (e.g., "en-US", "es") or "default" for catch-all
|
|
519
|
+
fillers: List of filler phrases for exiting this context
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
Self for method chaining
|
|
523
|
+
"""
|
|
524
|
+
if language_code and fillers and isinstance(fillers, list):
|
|
525
|
+
if self._exit_fillers is None:
|
|
526
|
+
self._exit_fillers = {}
|
|
527
|
+
self._exit_fillers[language_code] = fillers
|
|
528
|
+
return self
|
|
529
|
+
|
|
530
|
+
def _render_prompt(self) -> Optional[str]:
|
|
531
|
+
"""Render the context's prompt text"""
|
|
532
|
+
if self._prompt_text is not None:
|
|
533
|
+
return self._prompt_text
|
|
534
|
+
|
|
535
|
+
if not self._prompt_sections:
|
|
536
|
+
return None
|
|
537
|
+
|
|
538
|
+
# Convert POM sections to markdown
|
|
539
|
+
markdown_parts = []
|
|
540
|
+
for section in self._prompt_sections:
|
|
541
|
+
if "bullets" in section:
|
|
542
|
+
markdown_parts.append(f"## {section['title']}")
|
|
543
|
+
for bullet in section["bullets"]:
|
|
544
|
+
markdown_parts.append(f"- {bullet}")
|
|
545
|
+
else:
|
|
546
|
+
markdown_parts.append(f"## {section['title']}")
|
|
547
|
+
markdown_parts.append(section["body"])
|
|
548
|
+
markdown_parts.append("") # Add spacing
|
|
549
|
+
|
|
550
|
+
return "\n".join(markdown_parts).strip()
|
|
551
|
+
|
|
552
|
+
def _render_system_prompt(self) -> Optional[str]:
|
|
553
|
+
"""Render the system prompt text"""
|
|
554
|
+
if self._system_prompt is not None:
|
|
555
|
+
return self._system_prompt
|
|
556
|
+
|
|
557
|
+
if not self._system_prompt_sections:
|
|
558
|
+
return None
|
|
559
|
+
|
|
560
|
+
# Convert POM sections to markdown
|
|
561
|
+
markdown_parts = []
|
|
562
|
+
for section in self._system_prompt_sections:
|
|
563
|
+
if "bullets" in section:
|
|
564
|
+
markdown_parts.append(f"## {section['title']}")
|
|
565
|
+
for bullet in section["bullets"]:
|
|
566
|
+
markdown_parts.append(f"- {bullet}")
|
|
567
|
+
else:
|
|
568
|
+
markdown_parts.append(f"## {section['title']}")
|
|
569
|
+
markdown_parts.append(section["body"])
|
|
570
|
+
markdown_parts.append("") # Add spacing
|
|
571
|
+
|
|
572
|
+
return "\n".join(markdown_parts).strip()
|
|
573
|
+
|
|
191
574
|
def to_dict(self) -> Dict[str, Any]:
|
|
192
575
|
"""Convert context to dictionary for SWML generation"""
|
|
193
576
|
if not self._steps:
|
|
@@ -199,6 +582,41 @@ class Context:
|
|
|
199
582
|
|
|
200
583
|
if self._valid_contexts is not None:
|
|
201
584
|
context_dict["valid_contexts"] = self._valid_contexts
|
|
585
|
+
|
|
586
|
+
# Add context entry parameters
|
|
587
|
+
if self._post_prompt is not None:
|
|
588
|
+
context_dict["post_prompt"] = self._post_prompt
|
|
589
|
+
|
|
590
|
+
rendered_system_prompt = self._render_system_prompt()
|
|
591
|
+
if rendered_system_prompt is not None:
|
|
592
|
+
context_dict["system_prompt"] = rendered_system_prompt
|
|
593
|
+
|
|
594
|
+
if self._consolidate:
|
|
595
|
+
context_dict["consolidate"] = self._consolidate
|
|
596
|
+
|
|
597
|
+
if self._full_reset:
|
|
598
|
+
context_dict["full_reset"] = self._full_reset
|
|
599
|
+
|
|
600
|
+
if self._user_prompt is not None:
|
|
601
|
+
context_dict["user_prompt"] = self._user_prompt
|
|
602
|
+
|
|
603
|
+
if self._isolated:
|
|
604
|
+
context_dict["isolated"] = self._isolated
|
|
605
|
+
|
|
606
|
+
# Add context prompt - use POM structure if sections exist, otherwise use string
|
|
607
|
+
if self._prompt_sections:
|
|
608
|
+
# Use structured POM format
|
|
609
|
+
context_dict["pom"] = self._prompt_sections
|
|
610
|
+
elif self._prompt_text is not None:
|
|
611
|
+
# Use string format
|
|
612
|
+
context_dict["prompt"] = self._prompt_text
|
|
613
|
+
|
|
614
|
+
# Add enter and exit fillers if defined
|
|
615
|
+
if self._enter_fillers is not None:
|
|
616
|
+
context_dict["enter_fillers"] = self._enter_fillers
|
|
617
|
+
|
|
618
|
+
if self._exit_fillers is not None:
|
|
619
|
+
context_dict["exit_fillers"] = self._exit_fillers
|
|
202
620
|
|
|
203
621
|
return context_dict
|
|
204
622
|
|
|
@@ -257,7 +257,6 @@ class DataMap:
|
|
|
257
257
|
|
|
258
258
|
Args:
|
|
259
259
|
foreach_config: Either:
|
|
260
|
-
- String: JSON path to array in response (deprecated, kept for compatibility)
|
|
261
260
|
- Dict: Foreach configuration with keys:
|
|
262
261
|
- input_key: Key in API response containing the array
|
|
263
262
|
- output_key: Name for the built string variable
|
|
@@ -278,20 +277,7 @@ class DataMap:
|
|
|
278
277
|
if not self._webhooks:
|
|
279
278
|
raise ValueError("Must add webhook before setting foreach")
|
|
280
279
|
|
|
281
|
-
if isinstance(foreach_config,
|
|
282
|
-
# Legacy support - convert string to basic foreach config
|
|
283
|
-
# Extract the key from "${response.key}" format if present
|
|
284
|
-
if foreach_config.startswith("${response.") and foreach_config.endswith("}"):
|
|
285
|
-
key = foreach_config[12:-1] # Remove "${response." and "}"
|
|
286
|
-
else:
|
|
287
|
-
key = foreach_config
|
|
288
|
-
|
|
289
|
-
foreach_data = {
|
|
290
|
-
"input_key": key,
|
|
291
|
-
"output_key": "foreach_output",
|
|
292
|
-
"append": "${this}"
|
|
293
|
-
}
|
|
294
|
-
else:
|
|
280
|
+
if isinstance(foreach_config, dict):
|
|
295
281
|
# New format - validate required keys
|
|
296
282
|
required_keys = ["input_key", "output_key", "append"]
|
|
297
283
|
missing_keys = [key for key in required_keys if key not in foreach_config]
|
|
@@ -299,6 +285,8 @@ class DataMap:
|
|
|
299
285
|
raise ValueError(f"foreach config missing required keys: {missing_keys}")
|
|
300
286
|
|
|
301
287
|
foreach_data = foreach_config
|
|
288
|
+
else:
|
|
289
|
+
raise ValueError("foreach_config must be a dictionary")
|
|
302
290
|
|
|
303
291
|
self._webhooks[-1]["foreach"] = foreach_data
|
|
304
292
|
return self
|