signalwire-agents 0.1.17__py3-none-any.whl → 0.1.18__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/cli/build_search.py +152 -4
- signalwire_agents/core/agent_base.py +77 -4
- signalwire_agents/core/contexts.py +333 -0
- signalwire_agents/core/swml_handler.py +27 -21
- signalwire_agents/skills/web_search/skill.py +1 -1
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/METADATA +43 -30
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/RECORD +13 -13
- {signalwire_agents-0.1.17.data → signalwire_agents-0.1.18.data}/data/schema.json +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/entry_points.txt +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.18.dist-info}/top_level.txt +0 -0
signalwire_agents/__init__.py
CHANGED
@@ -18,7 +18,7 @@ A package for building AI agents using SignalWire's AI and SWML capabilities.
|
|
18
18
|
from .core.logging_config import configure_logging
|
19
19
|
configure_logging()
|
20
20
|
|
21
|
-
__version__ = "0.1.
|
21
|
+
__version__ = "0.1.18"
|
22
22
|
|
23
23
|
# Import core classes for easier access
|
24
24
|
from .core.agent_base import AgentBase
|
@@ -85,6 +85,10 @@ Examples:
|
|
85
85
|
sw-search search ./docs.swsearch "how to create an agent"
|
86
86
|
sw-search search ./docs.swsearch "API reference" --count 3 --verbose
|
87
87
|
sw-search search ./docs.swsearch "configuration" --tags documentation --json
|
88
|
+
|
89
|
+
# Search via remote API
|
90
|
+
sw-search remote http://localhost:8001 "how to create an agent" --index-name docs
|
91
|
+
sw-search remote localhost:8001 "API reference" --index-name docs --count 3 --verbose
|
88
92
|
"""
|
89
93
|
)
|
90
94
|
|
@@ -263,7 +267,7 @@ Examples:
|
|
263
267
|
|
264
268
|
try:
|
265
269
|
# Create index builder - import only when actually needed
|
266
|
-
from
|
270
|
+
from signalwire_agents.search.index_builder import IndexBuilder
|
267
271
|
builder = IndexBuilder(
|
268
272
|
model_name=args.model,
|
269
273
|
chunking_strategy=args.chunking_strategy,
|
@@ -328,7 +332,7 @@ def validate_command():
|
|
328
332
|
sys.exit(1)
|
329
333
|
|
330
334
|
try:
|
331
|
-
from
|
335
|
+
from signalwire_agents.search.index_builder import IndexBuilder
|
332
336
|
builder = IndexBuilder()
|
333
337
|
|
334
338
|
validation = builder.validate_index(args.index_file)
|
@@ -376,8 +380,8 @@ def search_command():
|
|
376
380
|
try:
|
377
381
|
# Import search dependencies
|
378
382
|
try:
|
379
|
-
from
|
380
|
-
from
|
383
|
+
from signalwire_agents.search.search_engine import SearchEngine
|
384
|
+
from signalwire_agents.search.query_processor import preprocess_query
|
381
385
|
except ImportError as e:
|
382
386
|
print(f"Error: Search functionality not available. Install with: pip install signalwire-agents[search]")
|
383
387
|
print(f"Details: {e}")
|
@@ -478,6 +482,141 @@ def search_command():
|
|
478
482
|
traceback.print_exc()
|
479
483
|
sys.exit(1)
|
480
484
|
|
485
|
+
def remote_command():
|
486
|
+
"""Search via remote API endpoint"""
|
487
|
+
parser = argparse.ArgumentParser(description='Search via remote API endpoint')
|
488
|
+
parser.add_argument('endpoint', help='Remote API endpoint URL (e.g., http://localhost:8001)')
|
489
|
+
parser.add_argument('query', help='Search query')
|
490
|
+
parser.add_argument('--index-name', required=True, help='Name of the index to search')
|
491
|
+
parser.add_argument('--count', type=int, default=5, help='Number of results to return (default: 5)')
|
492
|
+
parser.add_argument('--distance-threshold', type=float, default=0.0, help='Minimum similarity score (default: 0.0)')
|
493
|
+
parser.add_argument('--tags', help='Comma-separated tags to filter by')
|
494
|
+
parser.add_argument('--verbose', action='store_true', help='Show detailed information')
|
495
|
+
parser.add_argument('--json', action='store_true', help='Output results as JSON')
|
496
|
+
parser.add_argument('--no-content', action='store_true', help='Hide content in results (show only metadata)')
|
497
|
+
parser.add_argument('--timeout', type=int, default=30, help='Request timeout in seconds (default: 30)')
|
498
|
+
|
499
|
+
args = parser.parse_args()
|
500
|
+
|
501
|
+
# Ensure endpoint starts with http:// or https://
|
502
|
+
endpoint = args.endpoint
|
503
|
+
if not endpoint.startswith(('http://', 'https://')):
|
504
|
+
endpoint = f"http://{endpoint}"
|
505
|
+
|
506
|
+
# Ensure endpoint ends with /search
|
507
|
+
if not endpoint.endswith('/search'):
|
508
|
+
if endpoint.endswith('/'):
|
509
|
+
endpoint += 'search'
|
510
|
+
else:
|
511
|
+
endpoint += '/search'
|
512
|
+
|
513
|
+
try:
|
514
|
+
import requests
|
515
|
+
except ImportError:
|
516
|
+
print("Error: requests library not available. Install with: pip install requests")
|
517
|
+
sys.exit(1)
|
518
|
+
|
519
|
+
# Prepare request payload
|
520
|
+
payload = {
|
521
|
+
'query': args.query,
|
522
|
+
'index_name': args.index_name,
|
523
|
+
'count': args.count,
|
524
|
+
'distance_threshold': args.distance_threshold
|
525
|
+
}
|
526
|
+
|
527
|
+
if args.tags:
|
528
|
+
payload['tags'] = [tag.strip() for tag in args.tags.split(',')]
|
529
|
+
|
530
|
+
if args.verbose:
|
531
|
+
print(f"Searching remote endpoint: {endpoint}")
|
532
|
+
print(f"Payload: {payload}")
|
533
|
+
print()
|
534
|
+
|
535
|
+
try:
|
536
|
+
# Make the API request
|
537
|
+
response = requests.post(
|
538
|
+
endpoint,
|
539
|
+
json=payload,
|
540
|
+
headers={'Content-Type': 'application/json'},
|
541
|
+
timeout=args.timeout
|
542
|
+
)
|
543
|
+
|
544
|
+
if response.status_code == 200:
|
545
|
+
result = response.json()
|
546
|
+
|
547
|
+
if args.json:
|
548
|
+
# Output raw JSON response
|
549
|
+
import json
|
550
|
+
print(json.dumps(result, indent=2))
|
551
|
+
else:
|
552
|
+
# Human-readable output
|
553
|
+
results = result.get('results', [])
|
554
|
+
if not results:
|
555
|
+
print(f"No results found for '{args.query}' in index '{args.index_name}'")
|
556
|
+
sys.exit(0)
|
557
|
+
|
558
|
+
print(f"Found {len(results)} result(s) for '{args.query}' in index '{args.index_name}':")
|
559
|
+
if result.get('enhanced_query') and result.get('enhanced_query') != args.query:
|
560
|
+
print(f"Enhanced query: '{result.get('enhanced_query')}'")
|
561
|
+
print("=" * 80)
|
562
|
+
|
563
|
+
for i, search_result in enumerate(results):
|
564
|
+
print(f"\n[{i+1}] Score: {search_result.get('score', 0):.4f}")
|
565
|
+
|
566
|
+
# Show metadata
|
567
|
+
metadata = search_result.get('metadata', {})
|
568
|
+
print(f"File: {metadata.get('filename', 'Unknown')}")
|
569
|
+
if metadata.get('section'):
|
570
|
+
print(f"Section: {metadata['section']}")
|
571
|
+
if metadata.get('line_start'):
|
572
|
+
print(f"Lines: {metadata['line_start']}-{metadata.get('line_end', metadata['line_start'])}")
|
573
|
+
if metadata.get('tags'):
|
574
|
+
print(f"Tags: {', '.join(metadata['tags'])}")
|
575
|
+
|
576
|
+
# Show content unless suppressed
|
577
|
+
if not args.no_content and 'content' in search_result:
|
578
|
+
content = search_result['content']
|
579
|
+
if len(content) > 500 and not args.verbose:
|
580
|
+
content = content[:500] + "..."
|
581
|
+
print(f"\nContent:\n{content}")
|
582
|
+
|
583
|
+
if i < len(results) - 1:
|
584
|
+
print("-" * 80)
|
585
|
+
|
586
|
+
elif response.status_code == 404:
|
587
|
+
try:
|
588
|
+
error_detail = response.json()
|
589
|
+
error_msg = error_detail.get('detail', 'Index not found')
|
590
|
+
except:
|
591
|
+
error_msg = 'Index not found'
|
592
|
+
print(f"Error: {error_msg}")
|
593
|
+
sys.exit(1)
|
594
|
+
else:
|
595
|
+
try:
|
596
|
+
error_detail = response.json()
|
597
|
+
error_msg = error_detail.get('detail', f'HTTP {response.status_code}')
|
598
|
+
except:
|
599
|
+
error_msg = f'HTTP {response.status_code}: {response.text}'
|
600
|
+
print(f"Error: {error_msg}")
|
601
|
+
sys.exit(1)
|
602
|
+
|
603
|
+
except requests.ConnectionError:
|
604
|
+
print(f"Error: Could not connect to {endpoint}")
|
605
|
+
print("Make sure the search server is running")
|
606
|
+
sys.exit(1)
|
607
|
+
except requests.Timeout:
|
608
|
+
print(f"Error: Request timed out after {args.timeout} seconds")
|
609
|
+
sys.exit(1)
|
610
|
+
except requests.RequestException as e:
|
611
|
+
print(f"Error making request: {e}")
|
612
|
+
sys.exit(1)
|
613
|
+
except Exception as e:
|
614
|
+
print(f"Error: {e}")
|
615
|
+
if args.verbose:
|
616
|
+
import traceback
|
617
|
+
traceback.print_exc()
|
618
|
+
sys.exit(1)
|
619
|
+
|
481
620
|
def console_entry_point():
|
482
621
|
"""Console script entry point for pip installation"""
|
483
622
|
import sys
|
@@ -594,6 +733,10 @@ Examples:
|
|
594
733
|
sw-search search ./docs.swsearch "how to create an agent"
|
595
734
|
sw-search search ./docs.swsearch "API reference" --count 3 --verbose
|
596
735
|
sw-search search ./docs.swsearch "configuration" --tags documentation --json
|
736
|
+
|
737
|
+
# Search via remote API
|
738
|
+
sw-search remote http://localhost:8001 "how to create an agent" --index-name docs
|
739
|
+
sw-search remote localhost:8001 "API reference" --index-name docs --count 3 --verbose
|
597
740
|
""")
|
598
741
|
return
|
599
742
|
|
@@ -609,6 +752,11 @@ Examples:
|
|
609
752
|
sys.argv.pop(1)
|
610
753
|
search_command()
|
611
754
|
return
|
755
|
+
elif sys.argv[1] == 'remote':
|
756
|
+
# Remove 'remote' from argv and call remote_command
|
757
|
+
sys.argv.pop(1)
|
758
|
+
remote_command()
|
759
|
+
return
|
612
760
|
|
613
761
|
# Regular build command
|
614
762
|
main()
|
@@ -1496,6 +1496,10 @@ class AgentBase(SWMLService):
|
|
1496
1496
|
if self._function_includes:
|
1497
1497
|
swaig_obj["includes"] = self._function_includes
|
1498
1498
|
|
1499
|
+
# Add internal_fillers if any are defined
|
1500
|
+
if hasattr(self, '_internal_fillers') and self._internal_fillers:
|
1501
|
+
swaig_obj["internal_fillers"] = self._internal_fillers
|
1502
|
+
|
1499
1503
|
# Create functions array
|
1500
1504
|
functions = []
|
1501
1505
|
|
@@ -1577,13 +1581,25 @@ class AgentBase(SWMLService):
|
|
1577
1581
|
try:
|
1578
1582
|
# Check if we're in contexts mode
|
1579
1583
|
if self._contexts_defined and self._contexts_builder:
|
1580
|
-
# Generate contexts
|
1584
|
+
# Generate contexts and combine with base prompt
|
1581
1585
|
contexts_dict = self._contexts_builder.to_dict()
|
1582
1586
|
|
1583
|
-
#
|
1587
|
+
# Determine base prompt (required when using contexts)
|
1588
|
+
base_prompt_text = None
|
1589
|
+
base_prompt_pom = None
|
1590
|
+
|
1591
|
+
if prompt_is_pom:
|
1592
|
+
base_prompt_pom = prompt
|
1593
|
+
elif prompt:
|
1594
|
+
base_prompt_text = prompt
|
1595
|
+
else:
|
1596
|
+
# Provide default base prompt if none exists
|
1597
|
+
base_prompt_text = f"You are {self.name}, a helpful AI assistant that follows structured workflows."
|
1598
|
+
|
1599
|
+
# Build AI config with base prompt + contexts
|
1584
1600
|
ai_config = ai_handler.build_config(
|
1585
|
-
prompt_text=
|
1586
|
-
prompt_pom=
|
1601
|
+
prompt_text=base_prompt_text,
|
1602
|
+
prompt_pom=base_prompt_pom,
|
1587
1603
|
contexts=contexts_dict,
|
1588
1604
|
post_prompt=post_prompt,
|
1589
1605
|
post_prompt_url=post_prompt_url,
|
@@ -2613,6 +2629,63 @@ class AgentBase(SWMLService):
|
|
2613
2629
|
self.native_functions = [name for name in function_names if isinstance(name, str)]
|
2614
2630
|
return self
|
2615
2631
|
|
2632
|
+
def set_internal_fillers(self, internal_fillers: Dict[str, Dict[str, List[str]]]) -> 'AgentBase':
|
2633
|
+
"""
|
2634
|
+
Set internal fillers for native SWAIG functions
|
2635
|
+
|
2636
|
+
Internal fillers provide custom phrases the AI says while executing
|
2637
|
+
internal/native functions like check_time, wait_for_user, next_step, etc.
|
2638
|
+
|
2639
|
+
Args:
|
2640
|
+
internal_fillers: Dictionary mapping function names to language-specific filler phrases
|
2641
|
+
Format: {"function_name": {"language_code": ["phrase1", "phrase2"]}}
|
2642
|
+
Example: {"next_step": {"en-US": ["Moving to the next step...", "Great, let's continue..."]}}
|
2643
|
+
|
2644
|
+
Returns:
|
2645
|
+
Self for method chaining
|
2646
|
+
|
2647
|
+
Example:
|
2648
|
+
agent.set_internal_fillers({
|
2649
|
+
"next_step": {
|
2650
|
+
"en-US": ["Moving to the next step...", "Great, let's continue..."],
|
2651
|
+
"es": ["Pasando al siguiente paso...", "Excelente, continuemos..."]
|
2652
|
+
},
|
2653
|
+
"check_time": {
|
2654
|
+
"en-US": ["Let me check the time...", "Getting the current time..."]
|
2655
|
+
}
|
2656
|
+
})
|
2657
|
+
"""
|
2658
|
+
if internal_fillers and isinstance(internal_fillers, dict):
|
2659
|
+
if not hasattr(self, '_internal_fillers'):
|
2660
|
+
self._internal_fillers = {}
|
2661
|
+
self._internal_fillers.update(internal_fillers)
|
2662
|
+
return self
|
2663
|
+
|
2664
|
+
def add_internal_filler(self, function_name: str, language_code: str, fillers: List[str]) -> 'AgentBase':
|
2665
|
+
"""
|
2666
|
+
Add internal fillers for a specific function and language
|
2667
|
+
|
2668
|
+
Args:
|
2669
|
+
function_name: Name of the internal function (e.g., 'next_step', 'check_time')
|
2670
|
+
language_code: Language code (e.g., 'en-US', 'es', 'fr')
|
2671
|
+
fillers: List of filler phrases for this function and language
|
2672
|
+
|
2673
|
+
Returns:
|
2674
|
+
Self for method chaining
|
2675
|
+
|
2676
|
+
Example:
|
2677
|
+
agent.add_internal_filler("next_step", "en-US", ["Moving to the next step...", "Great, let's continue..."])
|
2678
|
+
"""
|
2679
|
+
if function_name and language_code and fillers and isinstance(fillers, list):
|
2680
|
+
if not hasattr(self, '_internal_fillers'):
|
2681
|
+
self._internal_fillers = {}
|
2682
|
+
|
2683
|
+
if function_name not in self._internal_fillers:
|
2684
|
+
self._internal_fillers[function_name] = {}
|
2685
|
+
|
2686
|
+
self._internal_fillers[function_name][language_code] = fillers
|
2687
|
+
return self
|
2688
|
+
|
2616
2689
|
def add_function_include(self, url: str, functions: List[str], meta_data: Optional[Dict[str, Any]] = None) -> 'AgentBase':
|
2617
2690
|
"""
|
2618
2691
|
Add a remote function include to the SWAIG configuration
|
@@ -18,9 +18,16 @@ class Step:
|
|
18
18
|
self._step_criteria: Optional[str] = None
|
19
19
|
self._functions: Optional[Union[str, List[str]]] = None
|
20
20
|
self._valid_steps: Optional[List[str]] = None
|
21
|
+
self._valid_contexts: Optional[List[str]] = None
|
21
22
|
|
22
23
|
# POM-style sections for rich prompts
|
23
24
|
self._sections: List[Dict[str, Any]] = []
|
25
|
+
|
26
|
+
# Reset object for context switching from steps
|
27
|
+
self._reset_system_prompt: Optional[str] = None
|
28
|
+
self._reset_user_prompt: Optional[str] = None
|
29
|
+
self._reset_consolidate: bool = False
|
30
|
+
self._reset_full_reset: bool = False
|
24
31
|
|
25
32
|
def set_text(self, text: str) -> 'Step':
|
26
33
|
"""
|
@@ -108,6 +115,71 @@ class Step:
|
|
108
115
|
self._valid_steps = steps
|
109
116
|
return self
|
110
117
|
|
118
|
+
def set_valid_contexts(self, contexts: List[str]) -> 'Step':
|
119
|
+
"""
|
120
|
+
Set which contexts can be navigated to from this step
|
121
|
+
|
122
|
+
Args:
|
123
|
+
contexts: List of valid context names
|
124
|
+
|
125
|
+
Returns:
|
126
|
+
Self for method chaining
|
127
|
+
"""
|
128
|
+
self._valid_contexts = contexts
|
129
|
+
return self
|
130
|
+
|
131
|
+
def set_reset_system_prompt(self, system_prompt: str) -> 'Step':
|
132
|
+
"""
|
133
|
+
Set system prompt for context switching when this step navigates to a context
|
134
|
+
|
135
|
+
Args:
|
136
|
+
system_prompt: New system prompt for context switching
|
137
|
+
|
138
|
+
Returns:
|
139
|
+
Self for method chaining
|
140
|
+
"""
|
141
|
+
self._reset_system_prompt = system_prompt
|
142
|
+
return self
|
143
|
+
|
144
|
+
def set_reset_user_prompt(self, user_prompt: str) -> 'Step':
|
145
|
+
"""
|
146
|
+
Set user prompt for context switching when this step navigates to a context
|
147
|
+
|
148
|
+
Args:
|
149
|
+
user_prompt: User message to inject for context switching
|
150
|
+
|
151
|
+
Returns:
|
152
|
+
Self for method chaining
|
153
|
+
"""
|
154
|
+
self._reset_user_prompt = user_prompt
|
155
|
+
return self
|
156
|
+
|
157
|
+
def set_reset_consolidate(self, consolidate: bool) -> 'Step':
|
158
|
+
"""
|
159
|
+
Set whether to consolidate conversation when this step switches contexts
|
160
|
+
|
161
|
+
Args:
|
162
|
+
consolidate: Whether to consolidate previous conversation
|
163
|
+
|
164
|
+
Returns:
|
165
|
+
Self for method chaining
|
166
|
+
"""
|
167
|
+
self._reset_consolidate = consolidate
|
168
|
+
return self
|
169
|
+
|
170
|
+
def set_reset_full_reset(self, full_reset: bool) -> 'Step':
|
171
|
+
"""
|
172
|
+
Set whether to do full reset when this step switches contexts
|
173
|
+
|
174
|
+
Args:
|
175
|
+
full_reset: Whether to completely rewrite system prompt vs inject
|
176
|
+
|
177
|
+
Returns:
|
178
|
+
Self for method chaining
|
179
|
+
"""
|
180
|
+
self._reset_full_reset = full_reset
|
181
|
+
return self
|
182
|
+
|
111
183
|
def _render_text(self) -> str:
|
112
184
|
"""Render the step's prompt text"""
|
113
185
|
if self._text is not None:
|
@@ -145,6 +217,23 @@ class Step:
|
|
145
217
|
if self._valid_steps is not None:
|
146
218
|
step_dict["valid_steps"] = self._valid_steps
|
147
219
|
|
220
|
+
if self._valid_contexts is not None:
|
221
|
+
step_dict["valid_contexts"] = self._valid_contexts
|
222
|
+
|
223
|
+
# Add reset object if any reset parameters are set
|
224
|
+
reset_obj = {}
|
225
|
+
if self._reset_system_prompt is not None:
|
226
|
+
reset_obj["system_prompt"] = self._reset_system_prompt
|
227
|
+
if self._reset_user_prompt is not None:
|
228
|
+
reset_obj["user_prompt"] = self._reset_user_prompt
|
229
|
+
if self._reset_consolidate:
|
230
|
+
reset_obj["consolidate"] = self._reset_consolidate
|
231
|
+
if self._reset_full_reset:
|
232
|
+
reset_obj["full_reset"] = self._reset_full_reset
|
233
|
+
|
234
|
+
if reset_obj:
|
235
|
+
step_dict["reset"] = reset_obj
|
236
|
+
|
148
237
|
return step_dict
|
149
238
|
|
150
239
|
|
@@ -156,6 +245,19 @@ class Context:
|
|
156
245
|
self._steps: Dict[str, Step] = {}
|
157
246
|
self._step_order: List[str] = []
|
158
247
|
self._valid_contexts: Optional[List[str]] = None
|
248
|
+
|
249
|
+
# Context entry parameters
|
250
|
+
self._post_prompt: Optional[str] = None
|
251
|
+
self._system_prompt: Optional[str] = None
|
252
|
+
self._system_prompt_sections: List[Dict[str, Any]] = [] # For POM-style system prompts
|
253
|
+
self._consolidate: bool = False
|
254
|
+
self._full_reset: bool = False
|
255
|
+
self._user_prompt: Optional[str] = None
|
256
|
+
self._isolated: bool = False
|
257
|
+
|
258
|
+
# Context prompt (separate from system_prompt)
|
259
|
+
self._prompt_text: Optional[str] = None
|
260
|
+
self._prompt_sections: List[Dict[str, Any]] = []
|
159
261
|
|
160
262
|
def add_step(self, name: str) -> Step:
|
161
263
|
"""
|
@@ -188,6 +290,209 @@ class Context:
|
|
188
290
|
self._valid_contexts = contexts
|
189
291
|
return self
|
190
292
|
|
293
|
+
def set_post_prompt(self, post_prompt: str) -> 'Context':
|
294
|
+
"""
|
295
|
+
Set post prompt override for this context
|
296
|
+
|
297
|
+
Args:
|
298
|
+
post_prompt: Post prompt text to use when this context is active
|
299
|
+
|
300
|
+
Returns:
|
301
|
+
Self for method chaining
|
302
|
+
"""
|
303
|
+
self._post_prompt = post_prompt
|
304
|
+
return self
|
305
|
+
|
306
|
+
def set_system_prompt(self, system_prompt: str) -> 'Context':
|
307
|
+
"""
|
308
|
+
Set system prompt for context switching (triggers context reset)
|
309
|
+
|
310
|
+
Args:
|
311
|
+
system_prompt: New system prompt for when this context is entered
|
312
|
+
|
313
|
+
Returns:
|
314
|
+
Self for method chaining
|
315
|
+
"""
|
316
|
+
if self._system_prompt_sections:
|
317
|
+
raise ValueError("Cannot use set_system_prompt() when POM sections have been added for system prompt. Use one approach or the other.")
|
318
|
+
self._system_prompt = system_prompt
|
319
|
+
return self
|
320
|
+
|
321
|
+
def set_consolidate(self, consolidate: bool) -> 'Context':
|
322
|
+
"""
|
323
|
+
Set whether to consolidate conversation history when entering this context
|
324
|
+
|
325
|
+
Args:
|
326
|
+
consolidate: Whether to consolidate previous conversation
|
327
|
+
|
328
|
+
Returns:
|
329
|
+
Self for method chaining
|
330
|
+
"""
|
331
|
+
self._consolidate = consolidate
|
332
|
+
return self
|
333
|
+
|
334
|
+
def set_full_reset(self, full_reset: bool) -> 'Context':
|
335
|
+
"""
|
336
|
+
Set whether to do full reset when entering this context
|
337
|
+
|
338
|
+
Args:
|
339
|
+
full_reset: Whether to completely rewrite system prompt vs inject
|
340
|
+
|
341
|
+
Returns:
|
342
|
+
Self for method chaining
|
343
|
+
"""
|
344
|
+
self._full_reset = full_reset
|
345
|
+
return self
|
346
|
+
|
347
|
+
def set_user_prompt(self, user_prompt: str) -> 'Context':
|
348
|
+
"""
|
349
|
+
Set user prompt to inject when entering this context
|
350
|
+
|
351
|
+
Args:
|
352
|
+
user_prompt: User message to inject for context
|
353
|
+
|
354
|
+
Returns:
|
355
|
+
Self for method chaining
|
356
|
+
"""
|
357
|
+
self._user_prompt = user_prompt
|
358
|
+
return self
|
359
|
+
|
360
|
+
def set_isolated(self, isolated: bool) -> 'Context':
|
361
|
+
"""
|
362
|
+
Set whether to truncate conversation history when entering this context
|
363
|
+
|
364
|
+
Args:
|
365
|
+
isolated: Whether to truncate conversation on context switch
|
366
|
+
|
367
|
+
Returns:
|
368
|
+
Self for method chaining
|
369
|
+
"""
|
370
|
+
self._isolated = isolated
|
371
|
+
return self
|
372
|
+
|
373
|
+
def add_system_section(self, title: str, body: str) -> 'Context':
|
374
|
+
"""
|
375
|
+
Add a POM section to the system prompt
|
376
|
+
|
377
|
+
Args:
|
378
|
+
title: Section title
|
379
|
+
body: Section body text
|
380
|
+
|
381
|
+
Returns:
|
382
|
+
Self for method chaining
|
383
|
+
"""
|
384
|
+
if self._system_prompt is not None:
|
385
|
+
raise ValueError("Cannot add POM sections for system prompt when set_system_prompt() has been used. Use one approach or the other.")
|
386
|
+
self._system_prompt_sections.append({"title": title, "body": body})
|
387
|
+
return self
|
388
|
+
|
389
|
+
def add_system_bullets(self, title: str, bullets: List[str]) -> 'Context':
|
390
|
+
"""
|
391
|
+
Add a POM section with bullet points to the system prompt
|
392
|
+
|
393
|
+
Args:
|
394
|
+
title: Section title
|
395
|
+
bullets: List of bullet points
|
396
|
+
|
397
|
+
Returns:
|
398
|
+
Self for method chaining
|
399
|
+
"""
|
400
|
+
if self._system_prompt is not None:
|
401
|
+
raise ValueError("Cannot add POM sections for system prompt when set_system_prompt() has been used. Use one approach or the other.")
|
402
|
+
self._system_prompt_sections.append({"title": title, "bullets": bullets})
|
403
|
+
return self
|
404
|
+
|
405
|
+
def set_prompt(self, prompt: str) -> 'Context':
|
406
|
+
"""
|
407
|
+
Set the context's prompt text directly
|
408
|
+
|
409
|
+
Args:
|
410
|
+
prompt: The prompt text for this context
|
411
|
+
|
412
|
+
Returns:
|
413
|
+
Self for method chaining
|
414
|
+
"""
|
415
|
+
if self._prompt_sections:
|
416
|
+
raise ValueError("Cannot use set_prompt() when POM sections have been added. Use one approach or the other.")
|
417
|
+
self._prompt_text = prompt
|
418
|
+
return self
|
419
|
+
|
420
|
+
def add_section(self, title: str, body: str) -> 'Context':
|
421
|
+
"""
|
422
|
+
Add a POM section to the context prompt
|
423
|
+
|
424
|
+
Args:
|
425
|
+
title: Section title
|
426
|
+
body: Section body text
|
427
|
+
|
428
|
+
Returns:
|
429
|
+
Self for method chaining
|
430
|
+
"""
|
431
|
+
if self._prompt_text is not None:
|
432
|
+
raise ValueError("Cannot add POM sections when set_prompt() has been used. Use one approach or the other.")
|
433
|
+
self._prompt_sections.append({"title": title, "body": body})
|
434
|
+
return self
|
435
|
+
|
436
|
+
def add_bullets(self, title: str, bullets: List[str]) -> 'Context':
|
437
|
+
"""
|
438
|
+
Add a POM section with bullet points to the context prompt
|
439
|
+
|
440
|
+
Args:
|
441
|
+
title: Section title
|
442
|
+
bullets: List of bullet points
|
443
|
+
|
444
|
+
Returns:
|
445
|
+
Self for method chaining
|
446
|
+
"""
|
447
|
+
if self._prompt_text is not None:
|
448
|
+
raise ValueError("Cannot add POM sections when set_prompt() has been used. Use one approach or the other.")
|
449
|
+
self._prompt_sections.append({"title": title, "bullets": bullets})
|
450
|
+
return self
|
451
|
+
|
452
|
+
def _render_prompt(self) -> Optional[str]:
|
453
|
+
"""Render the context's prompt text"""
|
454
|
+
if self._prompt_text is not None:
|
455
|
+
return self._prompt_text
|
456
|
+
|
457
|
+
if not self._prompt_sections:
|
458
|
+
return None
|
459
|
+
|
460
|
+
# Convert POM sections to markdown
|
461
|
+
markdown_parts = []
|
462
|
+
for section in self._prompt_sections:
|
463
|
+
if "bullets" in section:
|
464
|
+
markdown_parts.append(f"## {section['title']}")
|
465
|
+
for bullet in section["bullets"]:
|
466
|
+
markdown_parts.append(f"- {bullet}")
|
467
|
+
else:
|
468
|
+
markdown_parts.append(f"## {section['title']}")
|
469
|
+
markdown_parts.append(section["body"])
|
470
|
+
markdown_parts.append("") # Add spacing
|
471
|
+
|
472
|
+
return "\n".join(markdown_parts).strip()
|
473
|
+
|
474
|
+
def _render_system_prompt(self) -> Optional[str]:
|
475
|
+
"""Render the system prompt text"""
|
476
|
+
if self._system_prompt is not None:
|
477
|
+
return self._system_prompt
|
478
|
+
|
479
|
+
if not self._system_prompt_sections:
|
480
|
+
return None
|
481
|
+
|
482
|
+
# Convert POM sections to markdown
|
483
|
+
markdown_parts = []
|
484
|
+
for section in self._system_prompt_sections:
|
485
|
+
if "bullets" in section:
|
486
|
+
markdown_parts.append(f"## {section['title']}")
|
487
|
+
for bullet in section["bullets"]:
|
488
|
+
markdown_parts.append(f"- {bullet}")
|
489
|
+
else:
|
490
|
+
markdown_parts.append(f"## {section['title']}")
|
491
|
+
markdown_parts.append(section["body"])
|
492
|
+
markdown_parts.append("") # Add spacing
|
493
|
+
|
494
|
+
return "\n".join(markdown_parts).strip()
|
495
|
+
|
191
496
|
def to_dict(self) -> Dict[str, Any]:
|
192
497
|
"""Convert context to dictionary for SWML generation"""
|
193
498
|
if not self._steps:
|
@@ -199,6 +504,34 @@ class Context:
|
|
199
504
|
|
200
505
|
if self._valid_contexts is not None:
|
201
506
|
context_dict["valid_contexts"] = self._valid_contexts
|
507
|
+
|
508
|
+
# Add context entry parameters
|
509
|
+
if self._post_prompt is not None:
|
510
|
+
context_dict["post_prompt"] = self._post_prompt
|
511
|
+
|
512
|
+
rendered_system_prompt = self._render_system_prompt()
|
513
|
+
if rendered_system_prompt is not None:
|
514
|
+
context_dict["system_prompt"] = rendered_system_prompt
|
515
|
+
|
516
|
+
if self._consolidate:
|
517
|
+
context_dict["consolidate"] = self._consolidate
|
518
|
+
|
519
|
+
if self._full_reset:
|
520
|
+
context_dict["full_reset"] = self._full_reset
|
521
|
+
|
522
|
+
if self._user_prompt is not None:
|
523
|
+
context_dict["user_prompt"] = self._user_prompt
|
524
|
+
|
525
|
+
if self._isolated:
|
526
|
+
context_dict["isolated"] = self._isolated
|
527
|
+
|
528
|
+
# Add context prompt - use POM structure if sections exist, otherwise use string
|
529
|
+
if self._prompt_sections:
|
530
|
+
# Use structured POM format
|
531
|
+
context_dict["pom"] = self._prompt_sections
|
532
|
+
elif self._prompt_text is not None:
|
533
|
+
# Use string format
|
534
|
+
context_dict["prompt"] = self._prompt_text
|
202
535
|
|
203
536
|
return context_dict
|
204
537
|
|
@@ -103,19 +103,19 @@ class AIVerbHandler(SWMLVerbHandler):
|
|
103
103
|
errors.append("'prompt' must be an object")
|
104
104
|
return False, errors
|
105
105
|
|
106
|
-
# Check that prompt contains
|
106
|
+
# Check that prompt contains either text or pom (required)
|
107
107
|
has_text = "text" in prompt
|
108
108
|
has_pom = "pom" in prompt
|
109
109
|
has_contexts = "contexts" in prompt
|
110
110
|
|
111
|
-
|
111
|
+
# Require either text or pom (mutually exclusive)
|
112
|
+
base_prompt_count = sum([has_text, has_pom])
|
113
|
+
if base_prompt_count == 0:
|
114
|
+
errors.append("'prompt' must contain either 'text' or 'pom' as base prompt")
|
115
|
+
elif base_prompt_count > 1:
|
116
|
+
errors.append("'prompt' can only contain one of: 'text' or 'pom' (mutually exclusive)")
|
112
117
|
|
113
|
-
|
114
|
-
errors.append("'prompt' must contain one of: 'text', 'pom', or 'contexts'")
|
115
|
-
elif options_count > 1:
|
116
|
-
errors.append("'prompt' can only contain one of: 'text', 'pom', or 'contexts'")
|
117
|
-
|
118
|
-
# Validate contexts structure if present
|
118
|
+
# Contexts are optional and can be combined with text or pom
|
119
119
|
if has_contexts:
|
120
120
|
contexts = prompt["contexts"]
|
121
121
|
if not isinstance(contexts, dict):
|
@@ -141,9 +141,9 @@ class AIVerbHandler(SWMLVerbHandler):
|
|
141
141
|
Build a configuration for the AI verb
|
142
142
|
|
143
143
|
Args:
|
144
|
-
prompt_text: Text prompt for the AI (mutually exclusive with prompt_pom
|
145
|
-
prompt_pom: POM structure for the AI prompt (mutually exclusive with prompt_text
|
146
|
-
contexts:
|
144
|
+
prompt_text: Text prompt for the AI (mutually exclusive with prompt_pom)
|
145
|
+
prompt_pom: POM structure for the AI prompt (mutually exclusive with prompt_text)
|
146
|
+
contexts: Optional contexts and steps configuration (can be combined with text or pom)
|
147
147
|
post_prompt: Optional post-prompt text
|
148
148
|
post_prompt_url: Optional URL for post-prompt processing
|
149
149
|
swaig: Optional SWAIG configuration
|
@@ -154,19 +154,25 @@ class AIVerbHandler(SWMLVerbHandler):
|
|
154
154
|
"""
|
155
155
|
config = {}
|
156
156
|
|
157
|
-
#
|
158
|
-
|
159
|
-
if
|
160
|
-
raise ValueError("
|
161
|
-
elif
|
162
|
-
raise ValueError("prompt_text
|
157
|
+
# Require either text or pom as base prompt (mutually exclusive)
|
158
|
+
base_prompt_count = sum(x is not None for x in [prompt_text, prompt_pom])
|
159
|
+
if base_prompt_count == 0:
|
160
|
+
raise ValueError("Either prompt_text or prompt_pom must be provided as base prompt")
|
161
|
+
elif base_prompt_count > 1:
|
162
|
+
raise ValueError("prompt_text and prompt_pom are mutually exclusive")
|
163
163
|
|
164
|
+
# Build prompt object with base prompt
|
165
|
+
prompt_config = {}
|
164
166
|
if prompt_text is not None:
|
165
|
-
|
167
|
+
prompt_config["text"] = prompt_text
|
166
168
|
elif prompt_pom is not None:
|
167
|
-
|
168
|
-
|
169
|
-
|
169
|
+
prompt_config["pom"] = prompt_pom
|
170
|
+
|
171
|
+
# Add contexts if provided (optional, activates steps feature)
|
172
|
+
if contexts is not None:
|
173
|
+
prompt_config["contexts"] = contexts
|
174
|
+
|
175
|
+
config["prompt"] = prompt_config
|
170
176
|
|
171
177
|
# Add post-prompt if provided
|
172
178
|
if post_prompt is not None:
|
@@ -224,7 +224,7 @@ class WebSearchSkill(SkillBase):
|
|
224
224
|
formatted_message = self.no_results_message.format(query=query) if '{query}' in self.no_results_message else self.no_results_message
|
225
225
|
return SwaigFunctionResult(formatted_message)
|
226
226
|
|
227
|
-
response = f"
|
227
|
+
response = f"Here are {num_results} results for '{query}':\n\nReiterate them to the user in a concise summary format\n\n{search_results}"
|
228
228
|
return SwaigFunctionResult(response)
|
229
229
|
|
230
230
|
except Exception as e:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: signalwire_agents
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.18
|
4
4
|
Summary: SignalWire AI Agents SDK
|
5
5
|
Author-email: SignalWire Team <info@signalwire.com>
|
6
6
|
Project-URL: Homepage, https://github.com/signalwire/signalwire-ai-agents
|
@@ -287,7 +287,7 @@ For detailed documentation, see [DataMap Guide](docs/datamap_guide.md).
|
|
287
287
|
|
288
288
|
## Contexts and Steps
|
289
289
|
|
290
|
-
The SignalWire Agents SDK provides a powerful
|
290
|
+
The SignalWire Agents SDK provides a powerful enhancement to traditional prompts through the **Contexts and Steps** system. This feature allows you to add structured, workflow-driven AI interactions on top of your base prompt, with explicit navigation control and step-by-step guidance.
|
291
291
|
|
292
292
|
### Why Use Contexts and Steps?
|
293
293
|
|
@@ -296,7 +296,7 @@ The SignalWire Agents SDK provides a powerful alternative to traditional Prompt
|
|
296
296
|
- **Completion Criteria**: Set specific criteria for step completion and progression
|
297
297
|
- **Function Restrictions**: Limit which AI tools are available in each step
|
298
298
|
- **Workflow Isolation**: Create separate contexts for different conversation flows
|
299
|
-
- **
|
299
|
+
- **Enhanced Base Prompts**: Adds structured workflows on top of your existing prompt foundation
|
300
300
|
|
301
301
|
### Basic Usage
|
302
302
|
|
@@ -307,30 +307,34 @@ class WorkflowAgent(AgentBase):
|
|
307
307
|
def __init__(self):
|
308
308
|
super().__init__(name="Workflow Assistant", route="/workflow")
|
309
309
|
|
310
|
-
#
|
310
|
+
# Set base prompt (required even when using contexts)
|
311
|
+
self.prompt_add_section("Role", "You are a helpful workflow assistant.")
|
312
|
+
self.prompt_add_section("Instructions", "Guide users through structured processes step by step.")
|
313
|
+
|
314
|
+
# Define contexts and steps (adds structured workflow to base prompt)
|
311
315
|
contexts = self.define_contexts()
|
312
316
|
|
313
317
|
# Create a single context named "default" (required for single context)
|
314
|
-
context = contexts.
|
318
|
+
context = contexts.add_context("default")
|
315
319
|
|
316
320
|
# Add step-by-step workflow
|
317
|
-
context.
|
321
|
+
context.add_step("greeting") \
|
318
322
|
.set_text("Welcome! I'm here to help you complete your application. Let's start with your personal information.") \
|
319
323
|
.set_step_criteria("User has provided their name and confirmed they want to continue") \
|
320
324
|
.set_valid_steps(["personal_info"]) # Can only go to personal_info step
|
321
325
|
|
322
|
-
context.
|
326
|
+
context.add_step("personal_info") \
|
323
327
|
.add_section("Instructions", "Collect the user's personal information") \
|
324
328
|
.add_bullets(["Ask for full name", "Ask for email address", "Ask for phone number"]) \
|
325
329
|
.set_step_criteria("All personal information has been collected and confirmed") \
|
326
330
|
.set_valid_steps(["review", "personal_info"]) # Can stay or move to review
|
327
331
|
|
328
|
-
context.
|
332
|
+
context.add_step("review") \
|
329
333
|
.set_text("Let me review the information you've provided. Please confirm if everything is correct.") \
|
330
334
|
.set_step_criteria("User has confirmed or requested changes") \
|
331
335
|
.set_valid_steps(["personal_info", "complete"]) # Can go back or complete
|
332
336
|
|
333
|
-
context.
|
337
|
+
context.add_step("complete") \
|
334
338
|
.set_text("Thank you! Your application has been submitted successfully.") \
|
335
339
|
.set_step_criteria("Application processing is complete")
|
336
340
|
# No valid_steps = end of workflow
|
@@ -346,22 +350,27 @@ class MultiContextAgent(AgentBase):
|
|
346
350
|
def __init__(self):
|
347
351
|
super().__init__(name="Multi-Context Agent", route="/multi-context")
|
348
352
|
|
349
|
-
#
|
353
|
+
# Set base prompt (required)
|
354
|
+
self.prompt_add_section("Role", "You are a versatile AI assistant.")
|
355
|
+
self.prompt_add_section("Capabilities", "You can help with calculations and provide time information.")
|
356
|
+
|
357
|
+
# Add skills
|
350
358
|
self.add_skill("datetime")
|
351
359
|
self.add_skill("math")
|
352
360
|
|
361
|
+
# Define contexts for different service modes
|
353
362
|
contexts = self.define_contexts()
|
354
363
|
|
355
364
|
# Main conversation context
|
356
|
-
main_context = contexts.
|
357
|
-
main_context.
|
365
|
+
main_context = contexts.add_context("main")
|
366
|
+
main_context.add_step("welcome") \
|
358
367
|
.set_text("Welcome! I can help with calculations or provide date/time info. What would you like to do?") \
|
359
368
|
.set_step_criteria("User has chosen a service type") \
|
360
369
|
.set_valid_contexts(["calculator", "datetime_info"]) # Can switch contexts
|
361
370
|
|
362
371
|
# Calculator context with function restrictions
|
363
|
-
calc_context = contexts.
|
364
|
-
calc_context.
|
372
|
+
calc_context = contexts.add_context("calculator")
|
373
|
+
calc_context.add_step("math_mode") \
|
365
374
|
.add_section("Role", "You are a mathematical assistant") \
|
366
375
|
.add_section("Instructions", "Help users with calculations") \
|
367
376
|
.set_functions(["math"]) # Only math function available \
|
@@ -369,8 +378,8 @@ class MultiContextAgent(AgentBase):
|
|
369
378
|
.set_valid_contexts(["main"]) # Can return to main
|
370
379
|
|
371
380
|
# DateTime context
|
372
|
-
datetime_context = contexts.
|
373
|
-
datetime_context.
|
381
|
+
datetime_context = contexts.add_context("datetime_info")
|
382
|
+
datetime_context.add_step("time_mode") \
|
374
383
|
.set_text("I can provide current date and time information. What would you like to know?") \
|
375
384
|
.set_functions(["datetime"]) # Only datetime function available \
|
376
385
|
.set_step_criteria("Date/time information has been provided") \
|
@@ -380,7 +389,7 @@ class MultiContextAgent(AgentBase):
|
|
380
389
|
### Context and Step Methods
|
381
390
|
|
382
391
|
#### Context Methods
|
383
|
-
- `
|
392
|
+
- `add_step(name)`: Create a new step in this context
|
384
393
|
- `set_valid_contexts(contexts)`: Control which contexts can be accessed from this context
|
385
394
|
|
386
395
|
#### Step Methods
|
@@ -406,41 +415,45 @@ class SupportAgent(AgentBase):
|
|
406
415
|
def __init__(self):
|
407
416
|
super().__init__(name="Customer Support", route="/support")
|
408
417
|
|
418
|
+
# Set base prompt (required)
|
419
|
+
self.prompt_add_section("Role", "You are a professional customer support representative.")
|
420
|
+
self.prompt_add_section("Goal", "Provide excellent customer service using structured workflows.")
|
421
|
+
|
409
422
|
# Add skills for enhanced capabilities
|
410
423
|
self.add_skill("datetime")
|
411
424
|
self.add_skill("web_search", {"api_key": "your-key", "search_engine_id": "your-id"})
|
412
425
|
|
426
|
+
# Define support workflow contexts
|
413
427
|
contexts = self.define_contexts()
|
414
428
|
|
415
429
|
# Triage context
|
416
|
-
triage = contexts.
|
417
|
-
triage.
|
418
|
-
.add_section("
|
419
|
-
.
|
420
|
-
.add_bullets(["Be empathetic and professional", "Ask clarifying questions", "Categorize the issue"]) \
|
430
|
+
triage = contexts.add_context("triage")
|
431
|
+
triage.add_step("initial_greeting") \
|
432
|
+
.add_section("Current Task", "Understand the customer's issue and route them appropriately") \
|
433
|
+
.add_bullets("Questions to Ask", ["What problem are you experiencing?", "How urgent is this issue?", "Have you tried any troubleshooting steps?"]) \
|
421
434
|
.set_step_criteria("Issue type has been identified") \
|
422
435
|
.set_valid_contexts(["technical_support", "billing_support", "general_inquiry"])
|
423
436
|
|
424
437
|
# Technical support context
|
425
|
-
tech = contexts.
|
426
|
-
tech.
|
427
|
-
.add_section("
|
428
|
-
.add_section("
|
438
|
+
tech = contexts.add_context("technical_support")
|
439
|
+
tech.add_step("technical_diagnosis") \
|
440
|
+
.add_section("Current Task", "Help diagnose and resolve technical issues") \
|
441
|
+
.add_section("Available Tools", "Use web search to find solutions and datetime to check service windows") \
|
429
442
|
.set_functions(["web_search", "datetime"]) # Can search for solutions and check times \
|
430
443
|
.set_step_criteria("Technical issue is resolved or escalated") \
|
431
444
|
.set_valid_contexts(["triage"]) # Can return to triage
|
432
445
|
|
433
446
|
# Billing support context
|
434
|
-
billing = contexts.
|
435
|
-
billing.
|
447
|
+
billing = contexts.add_context("billing_support")
|
448
|
+
billing.add_step("billing_assistance") \
|
436
449
|
.set_text("I'll help you with your billing inquiry. Please provide your account details.") \
|
437
450
|
.set_functions("none") # No external tools for sensitive billing info \
|
438
451
|
.set_step_criteria("Billing issue is addressed") \
|
439
452
|
.set_valid_contexts(["triage"])
|
440
453
|
|
441
454
|
# General inquiry context
|
442
|
-
general = contexts.
|
443
|
-
general.
|
455
|
+
general = contexts.add_context("general_inquiry")
|
456
|
+
general.add_step("general_help") \
|
444
457
|
.set_text("I'm here to help with general questions. What can I assist you with?") \
|
445
458
|
.set_functions(["web_search", "datetime"]) # Full access to search and time \
|
446
459
|
.set_step_criteria("Inquiry has been answered") \
|
@@ -1,12 +1,12 @@
|
|
1
|
-
signalwire_agents/__init__.py,sha256=
|
1
|
+
signalwire_agents/__init__.py,sha256=3YN2p2ynw-LH_LXSsuM52E0U5fCBzjAoxlOaQ7H1bvA,2707
|
2
2
|
signalwire_agents/agent_server.py,sha256=3Or8rIMAqW750V-XitBUMgOpW9BAIXmKXoGq7LkejAA,24988
|
3
3
|
signalwire_agents/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
|
4
4
|
signalwire_agents/cli/__init__.py,sha256=Iy2BfWDWBEZoA1cyHTDsooBSVMx4vH5Ddhr3sEuFe8c,197
|
5
|
-
signalwire_agents/cli/build_search.py,sha256=
|
5
|
+
signalwire_agents/cli/build_search.py,sha256=KLQJBqVSADFyGcKAi0KLwU_UoUd5rtRoKAdfcH91u70,28652
|
6
6
|
signalwire_agents/cli/test_swaig.py,sha256=CqfdBWE8_fiFnFWHbv9ouU1eUA_rGUUHwyOf_iUaZFU,101851
|
7
7
|
signalwire_agents/core/__init__.py,sha256=mVDLbpq1pg_WwiqsQR28NNZwJ6-VUXFIfg-vN7pk0ew,806
|
8
|
-
signalwire_agents/core/agent_base.py,sha256=
|
9
|
-
signalwire_agents/core/contexts.py,sha256=
|
8
|
+
signalwire_agents/core/agent_base.py,sha256=O-sQ9k6L8_qE94Xzpds3bSS52onxqVs8rYU9_1B0LV8,159349
|
9
|
+
signalwire_agents/core/contexts.py,sha256=RQGIZGR92AC90nv8_hGa8S4YGY-SmMa1giR4g7jLgQI,21283
|
10
10
|
signalwire_agents/core/data_map.py,sha256=U-HLEZQomWf-UI0-nLAE8g1oyRdE5bU_WxQpboI2YI4,17695
|
11
11
|
signalwire_agents/core/function_result.py,sha256=GGmd2gAB9uJFFyldrhC86LCmpCnccU1bb-3gZVW2rxE,45360
|
12
12
|
signalwire_agents/core/logging_config.py,sha256=x4d_RAjBjVpJOFA2vXnPP2dNr13BZHz091J5rGpC77Y,13142
|
@@ -15,7 +15,7 @@ signalwire_agents/core/skill_base.py,sha256=lOpVTLhD9NjStF7Lxh6bAQUGa3DpNYV4agXJ
|
|
15
15
|
signalwire_agents/core/skill_manager.py,sha256=XWq4MeDQ3kmM4Th8qI-Gx5klokDHNZ-K9cChJPW-zmQ,8113
|
16
16
|
signalwire_agents/core/swaig_function.py,sha256=3xJrrQVxCZX-DssLkdjaui_psTUzahkzAsQ1EyRVMFk,6837
|
17
17
|
signalwire_agents/core/swml_builder.py,sha256=Q1ikU9pedgjW888mjbqDFv-jMDvDZ-tZgfyMfu4qQN0,6719
|
18
|
-
signalwire_agents/core/swml_handler.py,sha256=
|
18
|
+
signalwire_agents/core/swml_handler.py,sha256=hFDq41dQWL3EdFbq6h0hizE1dIqdVeiTeCrujbZsPzo,8397
|
19
19
|
signalwire_agents/core/swml_renderer.py,sha256=u6HnbOC0NUnPpr6uz0FkXNEqcTF2OjWDui6gceD1Bhs,14773
|
20
20
|
signalwire_agents/core/swml_service.py,sha256=oLdVYRYDyucgBVDAuhiOWVTN6p21SvPvddkPIMMd5kw,48346
|
21
21
|
signalwire_agents/core/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
@@ -50,7 +50,7 @@ signalwire_agents/skills/math/skill.py,sha256=5sErd5x1rFHJg2GlmdJB3LvrmvTNOrZsA2
|
|
50
50
|
signalwire_agents/skills/native_vector_search/__init__.py,sha256=buvncVoH5u8MJA0SLlz1JQgIuyBTQW5aql-ydnc7Wh8,29
|
51
51
|
signalwire_agents/skills/native_vector_search/skill.py,sha256=da-3eM1NT7Tcju1GiQipxOrYhP7OIry68l2dLKpDV4I,15859
|
52
52
|
signalwire_agents/skills/web_search/__init__.py,sha256=wJlptYDExYw-nxZJVzlTLOgkKkDOLUUt1ZdoLt44ixs,45
|
53
|
-
signalwire_agents/skills/web_search/skill.py,sha256=
|
53
|
+
signalwire_agents/skills/web_search/skill.py,sha256=6EwoNABxEH5UkEdXsPT72PQzoVlFUbWsFJR6NuyhglI,10363
|
54
54
|
signalwire_agents/skills/wikipedia_search/__init__.py,sha256=8Db_aE0ly7QoXg7n2RDvCqKupkyR-UYlK9uFUnGNCE8,184
|
55
55
|
signalwire_agents/skills/wikipedia_search/skill.py,sha256=Q_HWJoG2RkQuZMgWxD9czuzEor79Gy1tjo6ywVzec84,6877
|
56
56
|
signalwire_agents/utils/__init__.py,sha256=1KVsHzwgfktSXHe3vqSRGImjtIE58szwD2FHHoFBtvY,601
|
@@ -58,10 +58,10 @@ signalwire_agents/utils/pom_utils.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_Pu
|
|
58
58
|
signalwire_agents/utils/schema_utils.py,sha256=i4okv_O9bUApwT_jJf4Yoij3bLCrGrW3DC-vzSy2RuY,16392
|
59
59
|
signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
60
60
|
signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
|
61
|
-
signalwire_agents-0.1.
|
62
|
-
signalwire_agents-0.1.
|
63
|
-
signalwire_agents-0.1.
|
64
|
-
signalwire_agents-0.1.
|
65
|
-
signalwire_agents-0.1.
|
66
|
-
signalwire_agents-0.1.
|
67
|
-
signalwire_agents-0.1.
|
61
|
+
signalwire_agents-0.1.18.data/data/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
|
62
|
+
signalwire_agents-0.1.18.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
|
63
|
+
signalwire_agents-0.1.18.dist-info/METADATA,sha256=OdI3xK6tg17jbWrZkWhAN4hsK2G67oG4VYSQ5BVTIMA,35364
|
64
|
+
signalwire_agents-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
65
|
+
signalwire_agents-0.1.18.dist-info/entry_points.txt,sha256=LRwltbVfaKUFMYmQoMxJGTT_-iQm0ftzXK0xPfD64Is,138
|
66
|
+
signalwire_agents-0.1.18.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
|
67
|
+
signalwire_agents-0.1.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|