signalwire-agents 0.1.17__py3-none-any.whl → 0.1.19__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/cli/test_swaig.py +285 -142
- 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/datasphere_serverless/skill.py +0 -1
- signalwire_agents/skills/web_search/skill.py +1 -1
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/METADATA +43 -30
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/RECORD +15 -15
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/entry_points.txt +1 -1
- {signalwire_agents-0.1.17.data → signalwire_agents-0.1.19.data}/data/schema.json +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.17.dist-info → signalwire_agents-0.1.19.dist-info}/top_level.txt +0 -0
@@ -1079,183 +1079,326 @@ def simple_template_expand(template: str, data: Dict[str, Any]) -> str:
|
|
1079
1079
|
def execute_datamap_function(datamap_config: Dict[str, Any], args: Dict[str, Any],
|
1080
1080
|
verbose: bool = False) -> Dict[str, Any]:
|
1081
1081
|
"""
|
1082
|
-
Execute a DataMap function
|
1082
|
+
Execute a DataMap function following the actual DataMap processing pipeline:
|
1083
|
+
1. Expressions (pattern matching)
|
1084
|
+
2. Webhooks (try each sequentially until one succeeds)
|
1085
|
+
3. Foreach (within successful webhook)
|
1086
|
+
4. Output (from successful webhook)
|
1087
|
+
5. Fallback output (if all webhooks fail)
|
1083
1088
|
|
1084
1089
|
Args:
|
1085
|
-
datamap_config:
|
1090
|
+
datamap_config: DataMap configuration dictionary
|
1086
1091
|
args: Function arguments
|
1087
|
-
verbose:
|
1092
|
+
verbose: Enable verbose output
|
1088
1093
|
|
1089
1094
|
Returns:
|
1090
|
-
|
1095
|
+
Function result (should be string or dict with 'response' key)
|
1091
1096
|
"""
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1097
|
+
if verbose:
|
1098
|
+
print("=== DataMap Function Execution ===")
|
1099
|
+
print(f"Config: {json.dumps(datamap_config, indent=2)}")
|
1100
|
+
print(f"Args: {json.dumps(args, indent=2)}")
|
1101
|
+
|
1102
|
+
# Extract the actual data_map configuration
|
1103
|
+
# DataMap configs have the structure: {"function": "...", "data_map": {...}}
|
1104
|
+
actual_datamap = datamap_config.get("data_map", datamap_config)
|
1105
|
+
|
1106
|
+
if verbose:
|
1107
|
+
print(f"Extracted data_map: {json.dumps(actual_datamap, indent=2)}")
|
1108
|
+
|
1109
|
+
# Initialize context with function arguments
|
1110
|
+
context = {"args": args}
|
1111
|
+
context.update(args) # Also make args available at top level for backward compatibility
|
1112
|
+
|
1113
|
+
if verbose:
|
1114
|
+
print(f"Initial context: {json.dumps(context, indent=2)}")
|
1115
|
+
|
1116
|
+
# Step 1: Process expressions first (pattern matching)
|
1117
|
+
if "expressions" in actual_datamap:
|
1100
1118
|
if verbose:
|
1101
|
-
print(
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1119
|
+
print("\n--- Processing Expressions ---")
|
1120
|
+
for expr in actual_datamap["expressions"]:
|
1121
|
+
# Simple expression evaluation - in real implementation this would be more sophisticated
|
1122
|
+
if "pattern" in expr and "output" in expr:
|
1123
|
+
# For testing, we'll just match simple strings
|
1124
|
+
pattern = expr["pattern"]
|
1125
|
+
if pattern in str(args):
|
1126
|
+
if verbose:
|
1127
|
+
print(f"Expression matched: {pattern}")
|
1128
|
+
result = simple_template_expand(str(expr["output"]), context)
|
1129
|
+
if verbose:
|
1130
|
+
print(f"Expression result: {result}")
|
1131
|
+
return result
|
1132
|
+
|
1133
|
+
# Step 2: Process webhooks sequentially
|
1134
|
+
if "webhooks" in actual_datamap:
|
1107
1135
|
if verbose:
|
1108
|
-
print(
|
1136
|
+
print("\n--- Processing Webhooks ---")
|
1109
1137
|
|
1110
|
-
for
|
1111
|
-
|
1112
|
-
|
1138
|
+
for i, webhook in enumerate(actual_datamap["webhooks"]):
|
1139
|
+
if verbose:
|
1140
|
+
print(f"\n=== Webhook {i+1}/{len(actual_datamap['webhooks'])} ===")
|
1113
1141
|
|
1114
|
-
|
1115
|
-
|
1142
|
+
url = webhook.get("url", "")
|
1143
|
+
method = webhook.get("method", "POST").upper()
|
1144
|
+
headers = webhook.get("headers", {})
|
1145
|
+
|
1146
|
+
# Expand template variables in URL and headers
|
1147
|
+
url = simple_template_expand(url, context)
|
1148
|
+
expanded_headers = {}
|
1149
|
+
for key, value in headers.items():
|
1150
|
+
expanded_headers[key] = simple_template_expand(str(value), context)
|
1116
1151
|
|
1117
1152
|
if verbose:
|
1118
|
-
print(f"
|
1153
|
+
print(f"Making {method} request to: {url}")
|
1154
|
+
print(f"Headers: {json.dumps(expanded_headers, indent=2)}")
|
1155
|
+
|
1156
|
+
# Prepare request data
|
1157
|
+
request_data = None
|
1158
|
+
if method in ["POST", "PUT", "PATCH"]:
|
1159
|
+
# Check for 'params' (SignalWire style) or 'data' (generic style) or 'body'
|
1160
|
+
if "params" in webhook:
|
1161
|
+
# Expand template variables in params
|
1162
|
+
expanded_params = {}
|
1163
|
+
for key, value in webhook["params"].items():
|
1164
|
+
expanded_params[key] = simple_template_expand(str(value), context)
|
1165
|
+
request_data = json.dumps(expanded_params)
|
1166
|
+
elif "body" in webhook:
|
1167
|
+
# Expand template variables in body
|
1168
|
+
if isinstance(webhook["body"], str):
|
1169
|
+
request_data = simple_template_expand(webhook["body"], context)
|
1170
|
+
else:
|
1171
|
+
expanded_body = {}
|
1172
|
+
for key, value in webhook["body"].items():
|
1173
|
+
expanded_body[key] = simple_template_expand(str(value), context)
|
1174
|
+
request_data = json.dumps(expanded_body)
|
1175
|
+
elif "data" in webhook:
|
1176
|
+
# Expand template variables in data
|
1177
|
+
if isinstance(webhook["data"], str):
|
1178
|
+
request_data = simple_template_expand(webhook["data"], context)
|
1179
|
+
else:
|
1180
|
+
request_data = json.dumps(webhook["data"])
|
1181
|
+
|
1182
|
+
if verbose and request_data:
|
1183
|
+
print(f"Request data: {request_data}")
|
1184
|
+
|
1185
|
+
webhook_failed = False
|
1186
|
+
response_data = None
|
1119
1187
|
|
1120
|
-
# Use regex to match
|
1121
1188
|
try:
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
elif
|
1128
|
-
|
1189
|
+
# Make the HTTP request
|
1190
|
+
if method == "GET":
|
1191
|
+
response = requests.get(url, headers=expanded_headers, timeout=30)
|
1192
|
+
elif method == "POST":
|
1193
|
+
response = requests.post(url, data=request_data, headers=expanded_headers, timeout=30)
|
1194
|
+
elif method == "PUT":
|
1195
|
+
response = requests.put(url, data=request_data, headers=expanded_headers, timeout=30)
|
1196
|
+
elif method == "PATCH":
|
1197
|
+
response = requests.patch(url, data=request_data, headers=expanded_headers, timeout=30)
|
1198
|
+
elif method == "DELETE":
|
1199
|
+
response = requests.delete(url, headers=expanded_headers, timeout=30)
|
1200
|
+
else:
|
1201
|
+
raise ValueError(f"Unsupported HTTP method: {method}")
|
1202
|
+
|
1203
|
+
if verbose:
|
1204
|
+
print(f"Response status: {response.status_code}")
|
1205
|
+
print(f"Response headers: {dict(response.headers)}")
|
1206
|
+
|
1207
|
+
# Parse response
|
1208
|
+
try:
|
1209
|
+
response_data = response.json()
|
1210
|
+
except json.JSONDecodeError:
|
1211
|
+
response_data = {"text": response.text, "status_code": response.status_code}
|
1212
|
+
# Add parse_error like server does
|
1213
|
+
response_data["parse_error"] = True
|
1214
|
+
response_data["raw_response"] = response.text
|
1215
|
+
|
1216
|
+
if verbose:
|
1217
|
+
print(f"Response data: {json.dumps(response_data, indent=2)}")
|
1218
|
+
|
1219
|
+
# Check for webhook failure following server logic
|
1220
|
+
|
1221
|
+
# 1. Check HTTP status code (fix the server bug - should be OR not AND)
|
1222
|
+
if response.status_code < 200 or response.status_code > 299:
|
1223
|
+
webhook_failed = True
|
1129
1224
|
if verbose:
|
1130
|
-
print(f"
|
1131
|
-
|
1132
|
-
|
1225
|
+
print(f"Webhook failed: HTTP status {response.status_code} outside 200-299 range")
|
1226
|
+
|
1227
|
+
# 2. Check for explicit error keys (parse_error, protocol_error)
|
1228
|
+
if not webhook_failed:
|
1229
|
+
explicit_error_keys = ["parse_error", "protocol_error"]
|
1230
|
+
for error_key in explicit_error_keys:
|
1231
|
+
if error_key in response_data and response_data[error_key]:
|
1232
|
+
webhook_failed = True
|
1233
|
+
if verbose:
|
1234
|
+
print(f"Webhook failed: Found explicit error key '{error_key}' = {response_data[error_key]}")
|
1235
|
+
break
|
1236
|
+
|
1237
|
+
# 3. Check for custom error_keys from webhook config
|
1238
|
+
if not webhook_failed and "error_keys" in webhook:
|
1239
|
+
error_keys = webhook["error_keys"]
|
1240
|
+
if isinstance(error_keys, str):
|
1241
|
+
error_keys = [error_keys] # Convert single string to list
|
1242
|
+
elif not isinstance(error_keys, list):
|
1243
|
+
error_keys = []
|
1244
|
+
|
1245
|
+
for error_key in error_keys:
|
1246
|
+
if error_key in response_data and response_data[error_key]:
|
1247
|
+
webhook_failed = True
|
1248
|
+
if verbose:
|
1249
|
+
print(f"Webhook failed: Found custom error key '{error_key}' = {response_data[error_key]}")
|
1250
|
+
break
|
1251
|
+
|
1252
|
+
except Exception as e:
|
1253
|
+
webhook_failed = True
|
1133
1254
|
if verbose:
|
1134
|
-
print(f"
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
# Get webhooks from matched expression
|
1142
|
-
webhooks = matched_expression.get('webhooks', [])
|
1143
|
-
fallback_output = matched_expression.get('output', 'Function completed')
|
1144
|
-
webhook_result = None
|
1145
|
-
|
1146
|
-
if verbose:
|
1147
|
-
print(f"Processing {len(webhooks)} webhook(s)...")
|
1148
|
-
|
1149
|
-
for i, webhook in enumerate(webhooks):
|
1150
|
-
url = webhook.get('url', '')
|
1151
|
-
method = webhook.get('method', 'POST').upper()
|
1152
|
-
headers = webhook.get('headers', {})
|
1153
|
-
|
1154
|
-
if verbose:
|
1155
|
-
print(f" Webhook {i+1}: {method} {url}")
|
1156
|
-
|
1157
|
-
# Prepare request data
|
1158
|
-
request_data = args.copy()
|
1159
|
-
|
1160
|
-
# Expand URL template with arguments
|
1161
|
-
template_context = {"args": args, "array": [], **args}
|
1162
|
-
expanded_url = simple_template_expand(url, template_context)
|
1163
|
-
|
1164
|
-
if verbose:
|
1165
|
-
print(f" Original URL: {url}")
|
1166
|
-
print(f" Template context: {template_context}")
|
1167
|
-
print(f" Expanded URL: {expanded_url}")
|
1168
|
-
|
1169
|
-
try:
|
1170
|
-
if method == 'GET':
|
1171
|
-
response = requests.get(expanded_url, params=request_data, headers=headers, timeout=10)
|
1172
|
-
else:
|
1173
|
-
response = requests.post(expanded_url, json=request_data, headers=headers, timeout=10)
|
1255
|
+
print(f"Webhook failed: HTTP request exception: {e}")
|
1256
|
+
# Create error response like server does
|
1257
|
+
response_data = {
|
1258
|
+
"protocol_error": True,
|
1259
|
+
"error": str(e)
|
1260
|
+
}
|
1174
1261
|
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1262
|
+
# If webhook succeeded, process its output
|
1263
|
+
if not webhook_failed:
|
1264
|
+
if verbose:
|
1265
|
+
print(f"Webhook {i+1} succeeded!")
|
1266
|
+
|
1267
|
+
# Add response data to context
|
1268
|
+
webhook_context = context.copy()
|
1269
|
+
|
1270
|
+
# Handle different response types
|
1271
|
+
if isinstance(response_data, list):
|
1272
|
+
# For array responses, use ${array[0].field} syntax
|
1273
|
+
webhook_context["array"] = response_data
|
1274
|
+
if verbose:
|
1275
|
+
print(f"Array response: {len(response_data)} items")
|
1276
|
+
else:
|
1277
|
+
# For object responses, use ${response.field} syntax
|
1278
|
+
webhook_context["response"] = response_data
|
1279
|
+
if verbose:
|
1280
|
+
print("Object response")
|
1281
|
+
|
1282
|
+
# Step 3: Process webhook-level foreach (if present)
|
1283
|
+
if "foreach" in webhook:
|
1284
|
+
foreach_config = webhook["foreach"]
|
1178
1285
|
if verbose:
|
1179
|
-
print(f"
|
1180
|
-
print(f"
|
1286
|
+
print(f"\n--- Processing Webhook Foreach ---")
|
1287
|
+
print(f"Foreach config: {json.dumps(foreach_config, indent=2)}")
|
1181
1288
|
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1289
|
+
input_key = foreach_config.get("input_key", "data")
|
1290
|
+
output_key = foreach_config.get("output_key", "result")
|
1291
|
+
max_items = foreach_config.get("max", 100)
|
1292
|
+
append_template = foreach_config.get("append", "${this.value}")
|
1293
|
+
|
1294
|
+
# Look for the input data in the response
|
1295
|
+
input_data = None
|
1296
|
+
if input_key in response_data and isinstance(response_data[input_key], list):
|
1297
|
+
input_data = response_data[input_key]
|
1298
|
+
if verbose:
|
1299
|
+
print(f"Found array data in response.{input_key}: {len(input_data)} items")
|
1300
|
+
|
1301
|
+
if input_data:
|
1302
|
+
result_parts = []
|
1303
|
+
items_to_process = input_data[:max_items]
|
1190
1304
|
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1305
|
+
for item in items_to_process:
|
1306
|
+
if isinstance(item, dict):
|
1307
|
+
# For objects, make properties available as ${this.property}
|
1308
|
+
item_context = {"this": item}
|
1309
|
+
expanded = simple_template_expand(append_template, item_context)
|
1310
|
+
else:
|
1311
|
+
# For non-dict items, make them available as ${this.value}
|
1312
|
+
item_context = {"this": {"value": item}}
|
1313
|
+
expanded = simple_template_expand(append_template, item_context)
|
1314
|
+
result_parts.append(expanded)
|
1194
1315
|
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
for key, template in webhook_output.items():
|
1199
|
-
if isinstance(template, str):
|
1200
|
-
webhook_result[key] = simple_template_expand(template, template_context)
|
1201
|
-
else:
|
1202
|
-
webhook_result[key] = template
|
1203
|
-
elif isinstance(webhook_output, str):
|
1204
|
-
# Simple string template
|
1205
|
-
webhook_result = {"response": simple_template_expand(webhook_output, template_context)}
|
1206
|
-
else:
|
1207
|
-
# Other types
|
1208
|
-
webhook_result = {"response": str(webhook_output)}
|
1316
|
+
# Store the concatenated result
|
1317
|
+
foreach_result = "".join(result_parts)
|
1318
|
+
webhook_context[output_key] = foreach_result
|
1209
1319
|
|
1210
1320
|
if verbose:
|
1211
|
-
print(f"
|
1321
|
+
print(f"Processed {len(items_to_process)} items")
|
1322
|
+
print(f"Foreach result ({output_key}): {foreach_result[:200]}{'...' if len(foreach_result) > 200 else ''}")
|
1212
1323
|
else:
|
1213
|
-
|
1324
|
+
if verbose:
|
1325
|
+
print(f"No array data found for foreach input_key: {input_key}")
|
1326
|
+
|
1327
|
+
# Step 4: Process webhook-level output (this is the final result)
|
1328
|
+
if "output" in webhook:
|
1329
|
+
webhook_output = webhook["output"]
|
1330
|
+
if verbose:
|
1331
|
+
print(f"\n--- Processing Webhook Output ---")
|
1332
|
+
print(f"Output template: {json.dumps(webhook_output, indent=2)}")
|
1333
|
+
|
1334
|
+
if isinstance(webhook_output, dict):
|
1335
|
+
# Process each key-value pair in the output
|
1336
|
+
final_result = {}
|
1337
|
+
for key, template in webhook_output.items():
|
1338
|
+
expanded_value = simple_template_expand(str(template), webhook_context)
|
1339
|
+
final_result[key] = expanded_value
|
1340
|
+
if verbose:
|
1341
|
+
print(f"Set {key} = {expanded_value}")
|
1342
|
+
else:
|
1343
|
+
# Single output value (string template)
|
1344
|
+
final_result = simple_template_expand(str(webhook_output), webhook_context)
|
1345
|
+
if verbose:
|
1346
|
+
print(f"Final result = {final_result}")
|
1214
1347
|
|
1215
|
-
break
|
1216
|
-
except json.JSONDecodeError:
|
1217
|
-
webhook_result = {"response": response.text}
|
1218
1348
|
if verbose:
|
1219
|
-
print(f"
|
1220
|
-
|
1349
|
+
print(f"\n--- Webhook {i+1} Final Result ---")
|
1350
|
+
print(f"Result: {json.dumps(final_result, indent=2) if isinstance(final_result, dict) else final_result}")
|
1351
|
+
|
1352
|
+
return final_result
|
1353
|
+
|
1354
|
+
else:
|
1355
|
+
# No output template defined, return the response data
|
1356
|
+
if verbose:
|
1357
|
+
print("No output template defined, returning response data")
|
1358
|
+
return response_data
|
1359
|
+
|
1221
1360
|
else:
|
1361
|
+
# This webhook failed, try next webhook
|
1222
1362
|
if verbose:
|
1223
|
-
print(f"
|
1224
|
-
|
1225
|
-
if verbose:
|
1226
|
-
print(f" ✗ Webhook request failed: {e}")
|
1363
|
+
print(f"Webhook {i+1} failed, trying next webhook...")
|
1364
|
+
continue
|
1227
1365
|
|
1228
|
-
#
|
1229
|
-
if
|
1366
|
+
# Step 5: All webhooks failed, use fallback output if available
|
1367
|
+
if "output" in actual_datamap:
|
1230
1368
|
if verbose:
|
1231
|
-
print("
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
elif isinstance(output_template, str):
|
1246
|
-
# Simple string template
|
1247
|
-
webhook_result = {"response": simple_template_expand(output_template, {"args": args})}
|
1369
|
+
print(f"\n--- Using DataMap Fallback Output ---")
|
1370
|
+
datamap_output = actual_datamap["output"]
|
1371
|
+
if verbose:
|
1372
|
+
print(f"Fallback output template: {json.dumps(datamap_output, indent=2)}")
|
1373
|
+
|
1374
|
+
if isinstance(datamap_output, dict):
|
1375
|
+
# Process each key-value pair in the fallback output
|
1376
|
+
final_result = {}
|
1377
|
+
for key, template in datamap_output.items():
|
1378
|
+
expanded_value = simple_template_expand(str(template), context)
|
1379
|
+
final_result[key] = expanded_value
|
1380
|
+
if verbose:
|
1381
|
+
print(f"Fallback: Set {key} = {expanded_value}")
|
1382
|
+
result = final_result
|
1248
1383
|
else:
|
1249
|
-
#
|
1250
|
-
|
1384
|
+
# Single fallback output value
|
1385
|
+
result = simple_template_expand(str(datamap_output), context)
|
1386
|
+
if verbose:
|
1387
|
+
print(f"Fallback result = {result}")
|
1251
1388
|
|
1252
1389
|
if verbose:
|
1253
|
-
print(f"Fallback
|
1390
|
+
print(f"\n--- DataMap Fallback Final Result ---")
|
1391
|
+
print(f"Result: {json.dumps(result, indent=2) if isinstance(result, dict) else result}")
|
1392
|
+
|
1393
|
+
return result
|
1254
1394
|
|
1255
|
-
#
|
1256
|
-
|
1395
|
+
# No fallback defined, return generic error
|
1396
|
+
error_result = {"error": "All webhooks failed and no fallback output defined", "status": "failed"}
|
1397
|
+
if verbose:
|
1398
|
+
print(f"\n--- DataMap Error Result ---")
|
1399
|
+
print(f"Result: {json.dumps(error_result, indent=2)}")
|
1257
1400
|
|
1258
|
-
return
|
1401
|
+
return error_result
|
1259
1402
|
|
1260
1403
|
|
1261
1404
|
def execute_external_webhook_function(func: 'SWAIGFunction', function_name: str, function_args: Dict[str, Any],
|
@@ -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
|