@rymi/mcp 2.8.1 → 2.9.0
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.
- package/README.md +5 -1
- package/dist/index.js +274 -92
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -104,6 +104,10 @@ Run the server on your own machine — it speaks **stdio** by default and talks
|
|
|
104
104
|
<td><code>create_call</code> · <code>batch_call</code> · <code>end_call</code> · <code>add_call_participant</code></td>
|
|
105
105
|
</tr>
|
|
106
106
|
<tr>
|
|
107
|
+
<td><b>Task calls</b></td>
|
|
108
|
+
<td><code>place_task_call</code> · <code>wait_for_call</code></td>
|
|
109
|
+
</tr>
|
|
110
|
+
<tr>
|
|
107
111
|
<td><b>Numbers</b></td>
|
|
108
112
|
<td><code>list_numbers</code> · <code>register_number</code> · <code>attach_number</code> · <code>remove_number</code></td>
|
|
109
113
|
</tr>
|
|
@@ -151,7 +155,7 @@ Run the server on your own machine — it speaks **stdio** by default and talks
|
|
|
151
155
|
|
|
152
156
|
### ⚠️ Gated tools
|
|
153
157
|
|
|
154
|
-
`create_call` and `batch_call` place **real, billable** outbound calls; `publish_agent` flips an agent **live** to end users.
|
|
158
|
+
`place_task_call`, `create_call` and `batch_call` place **real, billable** outbound calls; `publish_agent` flips an agent **live** to end users.
|
|
155
159
|
|
|
156
160
|
What restrains them depends on which server you're talking to.
|
|
157
161
|
|
package/dist/index.js
CHANGED
|
@@ -153,6 +153,7 @@ var init_studioCatalog = __esm({
|
|
|
153
153
|
"gpt-realtime-2.1-mini",
|
|
154
154
|
"gpt-live-1",
|
|
155
155
|
"gemini-3.8-live",
|
|
156
|
+
"gemini-3.8-live-extended-thinking",
|
|
156
157
|
"grok-voice-3.0",
|
|
157
158
|
"grok-voice-think-fast-2.0",
|
|
158
159
|
"ultravox-v0.7",
|
|
@@ -176,10 +177,6 @@ var init_studioCatalog = __esm({
|
|
|
176
177
|
"gemini-2.5-flash-native-audio-preview-12-2025",
|
|
177
178
|
"nova-sonic-1",
|
|
178
179
|
"nova-sonic-2",
|
|
179
|
-
"llama-3.1-8b-instant",
|
|
180
|
-
"llama-3.3-70b-versatile",
|
|
181
|
-
"meta-llama/llama-4-scout-17b-16e-instruct",
|
|
182
|
-
"qwen/qwen3-32b",
|
|
183
180
|
"openai/gpt-oss-20b",
|
|
184
181
|
"openai/gpt-oss-120b",
|
|
185
182
|
"openai/gpt-oss-safeguard-20b",
|
|
@@ -190,6 +187,7 @@ var init_studioCatalog = __esm({
|
|
|
190
187
|
"llama-4-scout",
|
|
191
188
|
"deepseek-v4-flash",
|
|
192
189
|
"deepseek-v4-pro",
|
|
190
|
+
"grok-4.7",
|
|
193
191
|
"grok-4-1-fast",
|
|
194
192
|
"grok-3-mini",
|
|
195
193
|
"grok-3-mini-fast",
|
|
@@ -253,6 +251,7 @@ var init_studioCatalog = __esm({
|
|
|
253
251
|
],
|
|
254
252
|
tts: [
|
|
255
253
|
"aura-2",
|
|
254
|
+
"flux-tts",
|
|
256
255
|
"gemini-2.5-pro-preview-tts",
|
|
257
256
|
"sonic-3.5",
|
|
258
257
|
"sonic-turbo",
|
|
@@ -263,6 +262,7 @@ var init_studioCatalog = __esm({
|
|
|
263
262
|
"gemini-3.1-flash-tts-preview",
|
|
264
263
|
"tts-1",
|
|
265
264
|
"bulbul:v3",
|
|
265
|
+
"bulbul:v4-flash",
|
|
266
266
|
"gpt-4o-mini-tts",
|
|
267
267
|
"eleven_multilingual_v2",
|
|
268
268
|
// Additional TTS
|
|
@@ -1218,6 +1218,80 @@ var init_variables = __esm({
|
|
|
1218
1218
|
}
|
|
1219
1219
|
});
|
|
1220
1220
|
|
|
1221
|
+
// ../shared-types/dist/safeUrl.js
|
|
1222
|
+
var safeUrl_exports = {};
|
|
1223
|
+
__export(safeUrl_exports, {
|
|
1224
|
+
isSafeAudioUrl: () => isSafeAudioUrl,
|
|
1225
|
+
isSafeUrl: () => isSafeUrl
|
|
1226
|
+
});
|
|
1227
|
+
function unmapIpv4(v6) {
|
|
1228
|
+
const dotted = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(v6);
|
|
1229
|
+
if (dotted)
|
|
1230
|
+
return dotted[1];
|
|
1231
|
+
const hex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);
|
|
1232
|
+
if (!hex)
|
|
1233
|
+
return null;
|
|
1234
|
+
const high = parseInt(hex[1], 16);
|
|
1235
|
+
const low = parseInt(hex[2], 16);
|
|
1236
|
+
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
1237
|
+
}
|
|
1238
|
+
function isBlockedHost(host) {
|
|
1239
|
+
const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
1240
|
+
if (bare === "localhost" || bare === "0.0.0.0" || bare === "::")
|
|
1241
|
+
return true;
|
|
1242
|
+
if (bare.endsWith(".local") || bare.endsWith(".internal") || bare.endsWith(".localhost"))
|
|
1243
|
+
return true;
|
|
1244
|
+
if (/^127\./.test(bare))
|
|
1245
|
+
return true;
|
|
1246
|
+
if (/^10\./.test(bare))
|
|
1247
|
+
return true;
|
|
1248
|
+
if (/^192\.168\./.test(bare))
|
|
1249
|
+
return true;
|
|
1250
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(bare))
|
|
1251
|
+
return true;
|
|
1252
|
+
if (/^169\.254\./.test(bare))
|
|
1253
|
+
return true;
|
|
1254
|
+
const v6 = bare.toLowerCase();
|
|
1255
|
+
if (v6 === "::1")
|
|
1256
|
+
return true;
|
|
1257
|
+
if (/^f[cd][0-9a-f]{2}:/.test(v6))
|
|
1258
|
+
return true;
|
|
1259
|
+
if (/^fe[89ab][0-9a-f]:/.test(v6))
|
|
1260
|
+
return true;
|
|
1261
|
+
const mapped = unmapIpv4(v6);
|
|
1262
|
+
if (mapped)
|
|
1263
|
+
return isBlockedHost(mapped);
|
|
1264
|
+
return false;
|
|
1265
|
+
}
|
|
1266
|
+
function isSafeUrl(raw, options = {}) {
|
|
1267
|
+
const protocols = options.protocols ?? ["http:", "https:"];
|
|
1268
|
+
let url;
|
|
1269
|
+
try {
|
|
1270
|
+
url = new URL(raw);
|
|
1271
|
+
} catch {
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
if (!protocols.includes(url.protocol))
|
|
1275
|
+
return false;
|
|
1276
|
+
return !isBlockedHost(url.hostname.toLowerCase());
|
|
1277
|
+
}
|
|
1278
|
+
function isSafeAudioUrl(raw) {
|
|
1279
|
+
if (!isSafeUrl(raw, { protocols: ["https:"] }))
|
|
1280
|
+
return false;
|
|
1281
|
+
try {
|
|
1282
|
+
const parsed = new URL(raw.trim());
|
|
1283
|
+
const path = parsed.pathname.toLowerCase();
|
|
1284
|
+
return path.endsWith(".wav") || path.endsWith(".mp3");
|
|
1285
|
+
} catch {
|
|
1286
|
+
return false;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
var init_safeUrl = __esm({
|
|
1290
|
+
"../shared-types/dist/safeUrl.js"() {
|
|
1291
|
+
"use strict";
|
|
1292
|
+
}
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1221
1295
|
// ../../node_modules/.pnpm/dlv@1.1.3/node_modules/dlv/dist/dlv.es.js
|
|
1222
1296
|
function dlv_es_default(t, e, l, n, r) {
|
|
1223
1297
|
for (e = e.split ? e.split(".") : e, n = 0; n < e.length; n++) t = t ? t[e[n]] : r;
|
|
@@ -1407,9 +1481,10 @@ var AGENT_CONFIG_SCHEMA_VERSION, CHANGE_SET_VALIDATORS, DERIVED_SERIALIZE_RULES,
|
|
|
1407
1481
|
var init_agentConfigSchema = __esm({
|
|
1408
1482
|
"../shared-types/dist/agentConfigSchema.js"() {
|
|
1409
1483
|
"use strict";
|
|
1484
|
+
init_safeUrl();
|
|
1410
1485
|
init_dlv_es();
|
|
1411
1486
|
init_dist();
|
|
1412
|
-
AGENT_CONFIG_SCHEMA_VERSION = "2026-
|
|
1487
|
+
AGENT_CONFIG_SCHEMA_VERSION = "2026-10-23";
|
|
1413
1488
|
CHANGE_SET_VALIDATORS = [
|
|
1414
1489
|
// Catalog validation for enum-catalog model + language fields.
|
|
1415
1490
|
// Skips silently when no catalogs are wired (legacy callers / tests).
|
|
@@ -1453,6 +1528,21 @@ var init_agentConfigSchema = __esm({
|
|
|
1453
1528
|
}
|
|
1454
1529
|
}
|
|
1455
1530
|
return errors.length === 0 ? { valid: true } : { valid: false, errors };
|
|
1531
|
+
},
|
|
1532
|
+
(cfg, changes) => {
|
|
1533
|
+
if (!changes.some((c) => c.key === "background_sound" || c.key === "background_sound_url"))
|
|
1534
|
+
return { valid: true };
|
|
1535
|
+
const errors = [];
|
|
1536
|
+
const url = cfg.background_sound_url;
|
|
1537
|
+
const mode = cfg.background_sound;
|
|
1538
|
+
const hasUrl = typeof url === "string" && url.trim() !== "";
|
|
1539
|
+
if (hasUrl && (url.length > 512 || !isSafeAudioUrl(url))) {
|
|
1540
|
+
errors.push({ field: "background_sound_url", error: "Use a public https:// link to a .wav or .mp3 file (up to 512 characters)." });
|
|
1541
|
+
}
|
|
1542
|
+
if (mode === "custom" && !hasUrl) {
|
|
1543
|
+
errors.push({ field: "background_sound_url", error: "Custom background sound needs a link to a .wav or .mp3 file." });
|
|
1544
|
+
}
|
|
1545
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors };
|
|
1456
1546
|
}
|
|
1457
1547
|
];
|
|
1458
1548
|
DERIVED_SERIALIZE_RULES = [
|
|
@@ -1718,6 +1808,7 @@ var init_agentConfigSchema = __esm({
|
|
|
1718
1808
|
// ── Features ────────────────────────────────────────────────────────────
|
|
1719
1809
|
{ key: "transcriptionEnabled", label: "Transcription", description: "Generate text transcripts of calls.", default: true, type: { kind: "boolean" }, apiPath: "features.transcription_enabled", section: "features", editableIn: "both" },
|
|
1720
1810
|
{ key: "requireConsent", label: "Require Consent", description: "Ask caller for recording consent before proceeding.", default: true, type: { kind: "boolean" }, apiPath: "features.require_consent", section: "features", editableIn: "both" },
|
|
1811
|
+
{ key: "taskCallsEnabled", label: "Allow Task Calls", description: "Outside AI agents (MCP/API) can place one-off calls through this agent.", default: false, type: { kind: "boolean" }, apiPath: "features.task_calls_enabled", section: "features", editableIn: "both" },
|
|
1721
1812
|
{ key: "postCallSummaryEnabled", label: "Post-Call Summary", description: "Generate an AI summary after each call.", default: true, type: { kind: "boolean" }, apiPath: "post_call.summary.enabled", section: "features", editableIn: "both" },
|
|
1722
1813
|
{ key: "postCallSummaryPrompt", label: "Summary Prompt", description: "Custom prompt for post-call summary generation.", default: "Summarize the call in a few sentences: the caller's main reason for calling, what was discussed or resolved, and any agreed next steps.", type: { kind: "string", maxLength: 2e3 }, apiPath: "post_call.summary.prompt", section: "features", editableIn: "both" },
|
|
1723
1814
|
{ key: "postCallExtractionEnabled", label: "Post-Call Extraction", description: "Extract structured data from call transcripts.", default: false, type: { kind: "boolean" }, apiPath: "post_call.structured_extraction.prompt", section: "features", editableIn: "both" },
|
|
@@ -1748,7 +1839,7 @@ var init_agentConfigSchema = __esm({
|
|
|
1748
1839
|
},
|
|
1749
1840
|
// ── Runtime Timing ──────────────────────────────────────────────────────
|
|
1750
1841
|
{ key: "maxTurnLength", label: "Max Turn Length", description: "Maximum number of conversational turns.", default: 50, type: { kind: "number", min: 1, max: 200 }, apiPath: "advanced.maxTurnLength", section: "advanced", editableIn: "both" },
|
|
1751
|
-
{ key: "postSilenceHangup", label: "Post-Silence Hangup", description: "Hang up after this many seconds of silence.", default:
|
|
1842
|
+
{ key: "postSilenceHangup", label: "Post-Silence Hangup", description: "Hang up after this many seconds of silence.", default: 60, type: { kind: "number", min: 1, max: 6e4, unit: "s" }, apiPath: "advanced.postSilenceHangup", section: "advanced", editableIn: "both" },
|
|
1752
1843
|
{ key: "silencePromptMaxCount", label: "Silence Check-ins", description: "How many times the agent checks on a silent caller before the silence goodbye.", default: 2, type: { kind: "number", min: 1, max: 3 }, apiPath: "advanced.silencePromptMaxCount", section: "advanced", editableIn: "both" },
|
|
1753
1844
|
{ key: "silenceHangupMessage", label: "Silence Goodbye", description: "Exact line spoken before a silence hangup. Leave empty to let the agent say a short goodbye in the caller's language.", default: "", type: { kind: "string", maxLength: 200 }, apiPath: "advanced.silenceHangupMessage", section: "advanced", editableIn: "both" },
|
|
1754
1845
|
{ key: "maxCallDuration", label: "Max Call Duration", description: "Hard limit on call length.", default: 600, type: { kind: "number", min: 30, max: 7200, unit: "s" }, apiPath: "advanced.maxCallDuration", section: "advanced", editableIn: "both" },
|
|
@@ -1773,7 +1864,10 @@ var init_agentConfigSchema = __esm({
|
|
|
1773
1864
|
{ key: "stt_keywords", label: "STT Keywords", description: "Comma-separated keywords to boost STT accuracy.", default: "", type: { kind: "string", maxLength: 1e3 }, apiPath: "advanced.stt_keywords", section: "advanced", editableIn: "both" },
|
|
1774
1865
|
{ key: "pronunciations", label: "Pronunciations", aliases: ["pronunciation", "pronounce", "say as", "how to say"], description: "Words the agent should say a specific way: each word with how to say it, plus optional IPA where the voice engine reads it.", default: [], type: { kind: "list-object", itemShape: [{ key: "word", type: { kind: "string", maxLength: 64 }, required: true }, { key: "say_as", type: { kind: "string", maxLength: 128 }, required: true }, { key: "ipa", type: { kind: "string", maxLength: 128 }, required: false }] }, apiPath: "advanced.pronunciations", section: "advanced", editableIn: "both" },
|
|
1775
1866
|
{ key: "stt_background_denoising", label: "Background Denoising", aliases: ["denoise", "noise suppression", "background noise"], description: "Server-side noise suppression on the inbound audio (Deepgram smart-format).", default: true, type: { kind: "boolean" }, apiPath: "advanced.stt_background_denoising", section: "advanced", editableIn: "both" },
|
|
1776
|
-
{ key: "
|
|
1867
|
+
{ key: "voice_focus", label: "Voice Focus", aliases: ["krisp", "noise cancellation", "inbound denoising", "background voice", "voice focus", "noise_cancellation_krisp"], description: "Transport-level inbound speech isolation (RNNoise). Suppresses steady room noise before VAD and speech recognition; off by default.", default: "off", type: { kind: "enum", options: [{ value: "off", label: "Off" }, { value: "standard", label: "Standard" }] }, apiPath: "advanced.voice_focus", section: "advanced", editableIn: "both" },
|
|
1868
|
+
{ key: "background_sound", label: "Background Sound", aliases: ["ambience", "background audio", "office sound", "call ambience"], description: "Continuous low-volume ambient audio mixed under the agent voice on the outbound call track (`off`, built-in `office`, or `custom` URL).", default: "off", type: { kind: "enum", options: [{ value: "off", label: "Off" }, { value: "office", label: "Office" }, { value: "custom", label: "Custom URL" }] }, apiPath: "advanced.background_sound", section: "advanced", editableIn: "both" },
|
|
1869
|
+
{ key: "background_sound_volume", label: "Background Sound Volume", aliases: ["ambience volume", "office sound volume"], description: "Base linear gain for outbound background sound (0.00 to 0.40, default 0.15). Ducks automatically by 8 dB while the agent speaks.", default: 0.15, type: { kind: "number", min: 0, max: 0.4 }, apiPath: "advanced.background_sound_volume", section: "advanced", editableIn: "both" },
|
|
1870
|
+
{ key: "background_sound_url", label: "Background Sound URL", aliases: ["ambience url", "custom background sound url"], description: "Public HTTPS URL to a mono/stereo .wav or .mp3 file (3\u2013120 s, max 15 MB) used when background_sound is set to custom.", default: "", type: { kind: "string", maxLength: 512 }, apiPath: "advanced.background_sound_url", section: "advanced", editableIn: "both" },
|
|
1777
1871
|
{ key: "stt_eot_confidence", label: "End-of-Turn Confidence", description: "Deepgram Flux: how sure the model must be before deciding you finished speaking.", default: 0.7, type: { kind: "number", min: 0.5, max: 0.9 }, apiPath: "advanced.stt_eot_confidence", section: "advanced", editableIn: "both" },
|
|
1778
1872
|
{ key: "stt_eot_timeout_ms", label: "End-of-Turn Timeout", description: "Deepgram Flux: max silence before end-of-turn is forced.", default: 5e3, type: { kind: "number", min: 500, max: 1e4, unit: "ms" }, apiPath: "advanced.stt_eot_timeout_ms", section: "advanced", editableIn: "both" },
|
|
1779
1873
|
{ key: "stt_min_turn_silence_ms", label: "Min Turn Silence", description: "AssemblyAI: minimum silence before detecting end-of-turn when confident.", default: 160, type: { kind: "number", min: 0, max: 3e3, unit: "ms" }, apiPath: "advanced.stt_min_turn_silence_ms", section: "advanced", editableIn: "both" },
|
|
@@ -2151,6 +2245,8 @@ var init_flatDiff = __esm({
|
|
|
2151
2245
|
"features.transcription_enabled": "transcriptionEnabled",
|
|
2152
2246
|
"features.requireConsent": "requireConsent",
|
|
2153
2247
|
"features.require_consent": "requireConsent",
|
|
2248
|
+
"features.taskCallsEnabled": "taskCallsEnabled",
|
|
2249
|
+
"features.task_calls_enabled": "taskCallsEnabled",
|
|
2154
2250
|
"features.postCallSummaryEnabled": "postCallSummaryEnabled",
|
|
2155
2251
|
"features.post_call_summary_enabled": "postCallSummaryEnabled",
|
|
2156
2252
|
"features.postCallExtractionEnabled": "postCallExtractionEnabled",
|
|
@@ -2174,6 +2270,12 @@ var init_flatDiff = __esm({
|
|
|
2174
2270
|
"stt.stt_keywords": "stt_keywords",
|
|
2175
2271
|
"stt.background_denoising": "stt_background_denoising",
|
|
2176
2272
|
"stt.stt_background_denoising": "stt_background_denoising",
|
|
2273
|
+
"noise_cancellation_krisp": "voice_focus",
|
|
2274
|
+
"advanced.noise_cancellation_krisp": "voice_focus",
|
|
2275
|
+
"stt.voice_focus": "voice_focus",
|
|
2276
|
+
"tts.background_sound": "background_sound",
|
|
2277
|
+
"tts.background_sound_volume": "background_sound_volume",
|
|
2278
|
+
"tts.background_sound_url": "background_sound_url",
|
|
2177
2279
|
"stt.eot_confidence": "stt_eot_confidence",
|
|
2178
2280
|
"stt.stt_eot_confidence": "stt_eot_confidence",
|
|
2179
2281
|
"stt.eot_timeout_ms": "stt_eot_timeout_ms",
|
|
@@ -2310,6 +2412,8 @@ var init_pricing = __esm({
|
|
|
2310
2412
|
"gpt-realtime-2.1": 0.096,
|
|
2311
2413
|
"gpt-realtime-2.1-mini": 0.03,
|
|
2312
2414
|
"gemini-3.8-live": 0.035,
|
|
2415
|
+
"gemini-3.8-live-extended-thinking": 0.035,
|
|
2416
|
+
// provisional: same list rates, thinking tokens extra
|
|
2313
2417
|
"gpt-live-1": 0.06,
|
|
2314
2418
|
// 0.05 voice layer + ~0.01 gpt-5.4-mini delegation backend
|
|
2315
2419
|
"grok-voice-think-fast-2.0": 0.08,
|
|
@@ -2400,6 +2504,7 @@ var init_pricing = __esm({
|
|
|
2400
2504
|
"llama-4-scout": 56e-5,
|
|
2401
2505
|
"deepseek-v4-flash": 34e-5,
|
|
2402
2506
|
"deepseek-v4-pro": 418e-5,
|
|
2507
|
+
"grok-4.7": 64e-4,
|
|
2403
2508
|
"grok-4-1-fast": 56e-5,
|
|
2404
2509
|
"grok-3-mini": 64e-5,
|
|
2405
2510
|
"grok-3-mini-fast": 48e-5,
|
|
@@ -2429,10 +2534,12 @@ var init_pricing = __esm({
|
|
|
2429
2534
|
"Qwen/Qwen2.5-72B-Instruct": 22e-4,
|
|
2430
2535
|
"deepseek-ai/DeepSeek-V3": 14e-4,
|
|
2431
2536
|
"sarvam-30b": 10526e-8,
|
|
2432
|
-
"sarvam-105b":
|
|
2433
|
-
|
|
2537
|
+
"sarvam-105b": 0.01024,
|
|
2538
|
+
// measured 2026-10-25, see rates.py
|
|
2539
|
+
"sarvam-105b-conversations": 0.01024,
|
|
2434
2540
|
// TTS
|
|
2435
2541
|
"aura-2": 0.027,
|
|
2542
|
+
"flux-tts": 0.0405,
|
|
2436
2543
|
"gemini-2.5-flash-preview-tts": 0.015,
|
|
2437
2544
|
"gemini-3.1-flash-tts-preview": 0.015,
|
|
2438
2545
|
"gpt-4o-mini-tts": 0.015,
|
|
@@ -2446,6 +2553,7 @@ var init_pricing = __esm({
|
|
|
2446
2553
|
"inworld-tts-1": 5e-3,
|
|
2447
2554
|
"speech-1.6": 0.015,
|
|
2448
2555
|
"s2.1-pro": 0.020833,
|
|
2556
|
+
"drama-3": 0.069444,
|
|
2449
2557
|
"polly-neural": 0.012,
|
|
2450
2558
|
"sonic-3.5": 0.037594,
|
|
2451
2559
|
"sonic-3.6": 0.037594,
|
|
@@ -2466,7 +2574,9 @@ var init_pricing = __esm({
|
|
|
2466
2574
|
"PlayDialogTurbo": 0.06,
|
|
2467
2575
|
"speech-02-turbo": 0.024,
|
|
2468
2576
|
"speech-02-hd": 0.04,
|
|
2469
|
-
"bulbul:v3": 0.02842105
|
|
2577
|
+
"bulbul:v3": 0.02842105,
|
|
2578
|
+
// ₹2.00/1K chars PAYG, WebSocket (sarvam.ai/api-pricing, 2026-10-17) at ₹95/$, 900 chars/min.
|
|
2579
|
+
"bulbul:v4-flash": 0.01894737
|
|
2470
2580
|
};
|
|
2471
2581
|
}
|
|
2472
2582
|
});
|
|
@@ -2488,68 +2598,6 @@ var init_knowledge = __esm({
|
|
|
2488
2598
|
}
|
|
2489
2599
|
});
|
|
2490
2600
|
|
|
2491
|
-
// ../shared-types/dist/safeUrl.js
|
|
2492
|
-
var safeUrl_exports = {};
|
|
2493
|
-
__export(safeUrl_exports, {
|
|
2494
|
-
isSafeUrl: () => isSafeUrl
|
|
2495
|
-
});
|
|
2496
|
-
function unmapIpv4(v6) {
|
|
2497
|
-
const dotted = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(v6);
|
|
2498
|
-
if (dotted)
|
|
2499
|
-
return dotted[1];
|
|
2500
|
-
const hex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);
|
|
2501
|
-
if (!hex)
|
|
2502
|
-
return null;
|
|
2503
|
-
const high = parseInt(hex[1], 16);
|
|
2504
|
-
const low = parseInt(hex[2], 16);
|
|
2505
|
-
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
2506
|
-
}
|
|
2507
|
-
function isBlockedHost(host) {
|
|
2508
|
-
const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
2509
|
-
if (bare === "localhost" || bare === "0.0.0.0" || bare === "::")
|
|
2510
|
-
return true;
|
|
2511
|
-
if (bare.endsWith(".local") || bare.endsWith(".internal") || bare.endsWith(".localhost"))
|
|
2512
|
-
return true;
|
|
2513
|
-
if (/^127\./.test(bare))
|
|
2514
|
-
return true;
|
|
2515
|
-
if (/^10\./.test(bare))
|
|
2516
|
-
return true;
|
|
2517
|
-
if (/^192\.168\./.test(bare))
|
|
2518
|
-
return true;
|
|
2519
|
-
if (/^172\.(1[6-9]|2\d|3[01])\./.test(bare))
|
|
2520
|
-
return true;
|
|
2521
|
-
if (/^169\.254\./.test(bare))
|
|
2522
|
-
return true;
|
|
2523
|
-
const v6 = bare.toLowerCase();
|
|
2524
|
-
if (v6 === "::1")
|
|
2525
|
-
return true;
|
|
2526
|
-
if (/^f[cd][0-9a-f]{2}:/.test(v6))
|
|
2527
|
-
return true;
|
|
2528
|
-
if (/^fe[89ab][0-9a-f]:/.test(v6))
|
|
2529
|
-
return true;
|
|
2530
|
-
const mapped = unmapIpv4(v6);
|
|
2531
|
-
if (mapped)
|
|
2532
|
-
return isBlockedHost(mapped);
|
|
2533
|
-
return false;
|
|
2534
|
-
}
|
|
2535
|
-
function isSafeUrl(raw, options = {}) {
|
|
2536
|
-
const protocols = options.protocols ?? ["http:", "https:"];
|
|
2537
|
-
let url;
|
|
2538
|
-
try {
|
|
2539
|
-
url = new URL(raw);
|
|
2540
|
-
} catch {
|
|
2541
|
-
return false;
|
|
2542
|
-
}
|
|
2543
|
-
if (!protocols.includes(url.protocol))
|
|
2544
|
-
return false;
|
|
2545
|
-
return !isBlockedHost(url.hostname.toLowerCase());
|
|
2546
|
-
}
|
|
2547
|
-
var init_safeUrl = __esm({
|
|
2548
|
-
"../shared-types/dist/safeUrl.js"() {
|
|
2549
|
-
"use strict";
|
|
2550
|
-
}
|
|
2551
|
-
});
|
|
2552
|
-
|
|
2553
2601
|
// ../shared-types/dist/agentTools.js
|
|
2554
2602
|
var agentTools_exports = {};
|
|
2555
2603
|
__export(agentTools_exports, {
|
|
@@ -3736,6 +3784,20 @@ var init_sttCapabilities = __esm({
|
|
|
3736
3784
|
function resolveManagedPricePerMin(sku) {
|
|
3737
3785
|
return sku.pricePerMin ?? 0;
|
|
3738
3786
|
}
|
|
3787
|
+
function skuAllowsCountry(sku, country, strict) {
|
|
3788
|
+
const allowed = sku.allowedCountries;
|
|
3789
|
+
if (!allowed || allowed.length === 0)
|
|
3790
|
+
return true;
|
|
3791
|
+
if (!country)
|
|
3792
|
+
return !strict;
|
|
3793
|
+
return allowed.includes(country.toUpperCase());
|
|
3794
|
+
}
|
|
3795
|
+
function skuFeaturedInCountry(sku, country) {
|
|
3796
|
+
const featured = sku.featuredCountries;
|
|
3797
|
+
if (!featured || featured.length === 0)
|
|
3798
|
+
return true;
|
|
3799
|
+
return !!country && featured.includes(country.toUpperCase());
|
|
3800
|
+
}
|
|
3739
3801
|
var init_managedAgentSkus = __esm({
|
|
3740
3802
|
"../shared-types/dist/managedAgentSkus.js"() {
|
|
3741
3803
|
"use strict";
|
|
@@ -7011,6 +7073,7 @@ __export(dist_exports, {
|
|
|
7011
7073
|
isE164: () => isE164,
|
|
7012
7074
|
isKnownSessionEndReason: () => isKnownSessionEndReason,
|
|
7013
7075
|
isRealtimeModel: () => isRealtimeModel,
|
|
7076
|
+
isSafeAudioUrl: () => isSafeAudioUrl,
|
|
7014
7077
|
isSafeUrl: () => isSafeUrl,
|
|
7015
7078
|
isSupportedCountry: () => isSupportedCountry2,
|
|
7016
7079
|
isSupportedPhoneNumber: () => isSupportedPhoneNumber,
|
|
@@ -7034,6 +7097,7 @@ __export(dist_exports, {
|
|
|
7034
7097
|
populatedFocusedStudioSections: () => populatedFocusedStudioSections,
|
|
7035
7098
|
pronunciationSupport: () => pronunciationSupport,
|
|
7036
7099
|
providerIdsForTool: () => providerIdsForTool,
|
|
7100
|
+
providerRequiresExplicitVoice: () => providerRequiresExplicitVoice,
|
|
7037
7101
|
publishRequiredKeys: () => publishRequiredKeys,
|
|
7038
7102
|
readFocusedSectionField: () => readFocusedSectionField,
|
|
7039
7103
|
readFromPayload: () => readFromPayload,
|
|
@@ -7047,6 +7111,8 @@ __export(dist_exports, {
|
|
|
7047
7111
|
sanitizeTranscriptText: () => sanitizeTranscriptText,
|
|
7048
7112
|
scalarContextKeys: () => scalarContextKeys,
|
|
7049
7113
|
serializeSection: () => serializeSection,
|
|
7114
|
+
skuAllowsCountry: () => skuAllowsCountry,
|
|
7115
|
+
skuFeaturedInCountry: () => skuFeaturedInCountry,
|
|
7050
7116
|
stackCostPerMin: () => stackCostPerMin,
|
|
7051
7117
|
supportedCountry: () => supportedCountry,
|
|
7052
7118
|
toSupportedE164: () => toSupportedE164,
|
|
@@ -7142,6 +7208,7 @@ var require_dist = __commonJS({
|
|
|
7142
7208
|
keyAllowsTool: () => keyAllowsTool2,
|
|
7143
7209
|
opsToolCatalog: () => opsToolCatalog2,
|
|
7144
7210
|
resolveToolDisposition: () => resolveToolDisposition,
|
|
7211
|
+
toolAnnotations: () => toolAnnotations2,
|
|
7145
7212
|
withWorkspaceParam: () => withWorkspaceParam2
|
|
7146
7213
|
});
|
|
7147
7214
|
module2.exports = __toCommonJS2(index_exports);
|
|
@@ -7179,20 +7246,20 @@ var require_dist = __commonJS({
|
|
|
7179
7246
|
var agentConfigFields = {
|
|
7180
7247
|
system_prompt: import_zod.z.string().optional().describe("Full system prompt for the agent. If given without persona/playbook, the server auto-structures it."),
|
|
7181
7248
|
voice: import_zod.z.string().optional().describe('Voice ID (e.g. "Aoede", "Charon"). Call list_llm_options for valid values. Leave empty for realtime LLMs and Deepgram TTS, which carry their own voice.'),
|
|
7182
|
-
language: import_zod.z.string().optional().describe('Primary BCP-47 language tag (e.g. "hi-IN", "en-US").'),
|
|
7183
|
-
supported_languages: import_zod.z.array(import_zod.z.string()).optional().describe('All BCP-47 languages the agent should handle, e.g. ["hi-IN","en-US"] for a bilingual agent.
|
|
7184
|
-
llm_provider: import_zod.z.enum(import_shared_types.AGENT_LLM_PROVIDERS).optional(),
|
|
7185
|
-
llm_model: import_zod.z.string().optional().describe('LLM model id from list_llm_options (e.g. "gemini-2.5-flash", "sarvam-105b").'),
|
|
7186
|
-
llm_fallback_provider: import_zod.z.string().nullable().optional().describe("Fallback LLM provider; null clears it."),
|
|
7187
|
-
llm_fallback_model: import_zod.z.string().nullable().optional().describe("Fallback LLM model; null clears it."),
|
|
7188
|
-
stt_provider: import_zod.z.string().optional().describe('Speech-to-text provider (e.g. "deepgram", "sarvam").'),
|
|
7189
|
-
stt_model: import_zod.z.string().optional(),
|
|
7190
|
-
stt_fallback_provider: import_zod.z.string().nullable().optional(),
|
|
7191
|
-
stt_fallback_model: import_zod.z.string().nullable().optional(),
|
|
7192
|
-
tts_provider: import_zod.z.string().optional().describe('Text-to-speech provider (e.g. "elevenlabs", "sarvam", "cartesia").'),
|
|
7193
|
-
tts_model: import_zod.z.string().optional(),
|
|
7194
|
-
tts_fallback_provider: import_zod.z.string().nullable().optional(),
|
|
7195
|
-
tts_fallback_model: import_zod.z.string().nullable().optional(),
|
|
7249
|
+
language: import_zod.z.string().optional().describe('Primary BCP-47 language tag (e.g. "hi-IN", "en-US"). For managed agents, must belong to the SKU\u2019s supported_languages.'),
|
|
7250
|
+
supported_languages: import_zod.z.array(import_zod.z.string()).optional().describe('All BCP-47 languages the agent should handle, e.g. ["hi-IN","en-US"] for a bilingual custom agent. Fixed to [language] by the plan for managed agents.'),
|
|
7251
|
+
llm_provider: import_zod.z.enum(import_shared_types.AGENT_LLM_PROVIDERS).optional().describe("LLM provider (custom agents only; fixed by the plan for managed agents)."),
|
|
7252
|
+
llm_model: import_zod.z.string().optional().describe('LLM model id from list_llm_options (e.g. "gemini-2.5-flash", "sarvam-105b"). Fixed by the plan for managed agents.'),
|
|
7253
|
+
llm_fallback_provider: import_zod.z.string().nullable().optional().describe("Fallback LLM provider; null clears it. Fixed by the plan for managed agents."),
|
|
7254
|
+
llm_fallback_model: import_zod.z.string().nullable().optional().describe("Fallback LLM model; null clears it. Fixed by the plan for managed agents."),
|
|
7255
|
+
stt_provider: import_zod.z.string().optional().describe('Speech-to-text provider (e.g. "deepgram", "sarvam"). Fixed by the plan for managed agents.'),
|
|
7256
|
+
stt_model: import_zod.z.string().optional().describe("Speech-to-text model id. Fixed by the plan for managed agents."),
|
|
7257
|
+
stt_fallback_provider: import_zod.z.string().nullable().optional().describe("Fallback STT provider. Fixed by the plan for managed agents."),
|
|
7258
|
+
stt_fallback_model: import_zod.z.string().nullable().optional().describe("Fallback STT model. Fixed by the plan for managed agents."),
|
|
7259
|
+
tts_provider: import_zod.z.string().optional().describe('Text-to-speech provider (e.g. "elevenlabs", "sarvam", "cartesia"). Fixed by the plan for managed agents.'),
|
|
7260
|
+
tts_model: import_zod.z.string().optional().describe("Text-to-speech model id. Fixed by the plan for managed agents."),
|
|
7261
|
+
tts_fallback_provider: import_zod.z.string().nullable().optional().describe("Fallback TTS provider. Fixed by the plan for managed agents."),
|
|
7262
|
+
tts_fallback_model: import_zod.z.string().nullable().optional().describe("Fallback TTS model. Fixed by the plan for managed agents."),
|
|
7196
7263
|
custom_llm_url: import_zod.z.string().nullable().optional().describe("Self-hosted LLM endpoint (https:// or wss://). Enterprise only; null clears."),
|
|
7197
7264
|
custom_voice_url: import_zod.z.string().nullable().optional().describe("Self-hosted TTS endpoint (https:// or wss://). Enterprise only; null clears."),
|
|
7198
7265
|
custom_voice_mode: import_zod.z.enum(["rymi", "openai-compat"]).optional().describe("Wire format for custom_voice_url."),
|
|
@@ -8255,7 +8322,7 @@ var require_dist = __commonJS({
|
|
|
8255
8322
|
];
|
|
8256
8323
|
var import_zod11 = require("zod");
|
|
8257
8324
|
var import_agentTools = (init_agentTools(), __toCommonJS(agentTools_exports));
|
|
8258
|
-
var
|
|
8325
|
+
var import_safeUrl3 = (init_safeUrl(), __toCommonJS(safeUrl_exports));
|
|
8259
8326
|
var DEFAULT_NAME = "call_webhook";
|
|
8260
8327
|
var METHODS = ["GET", "POST", "PUT", "PATCH"];
|
|
8261
8328
|
var FIELD_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
@@ -8293,7 +8360,7 @@ var require_dist = __commonJS({
|
|
|
8293
8360
|
const url = typeof s.url === "string" ? s.url.trim() : "";
|
|
8294
8361
|
if (!url) errors.push("url is required.");
|
|
8295
8362
|
else if (!/^https:\/\//i.test(url)) errors.push("url must be https \u2014 the request carries caller details.");
|
|
8296
|
-
else if (!(0,
|
|
8363
|
+
else if (!(0, import_safeUrl3.isSafeUrl)(url, { protocols: ["https:"] })) errors.push("url must be a valid public host; private and loopback addresses are refused at call time.");
|
|
8297
8364
|
if (!METHODS.includes(s.method)) errors.push(`method must be one of ${METHODS.join(", ")}.`);
|
|
8298
8365
|
if (!Number.isInteger(b.timeout_ms) || b.timeout_ms < 1e3 || b.timeout_ms > 1e4) errors.push("timeout_ms must be an integer from 1000 to 10000.");
|
|
8299
8366
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8768,6 +8835,98 @@ var require_dist = __commonJS({
|
|
|
8768
8835
|
run: (client, { account_id, user_id }) => client.accounts.members.remove(account_id, user_id)
|
|
8769
8836
|
})
|
|
8770
8837
|
];
|
|
8838
|
+
var import_zod16 = require("zod");
|
|
8839
|
+
var returnField = import_zod16.z.object({
|
|
8840
|
+
name: import_zod16.z.string().regex(/^[a-z][a-z0-9_]{0,39}$/).describe('snake_case field name, e.g. "booked"'),
|
|
8841
|
+
description: import_zod16.z.string().min(1).max(300).describe("What the value means, for the extractor"),
|
|
8842
|
+
type: import_zod16.z.enum(["string", "number", "boolean"]).optional().describe('Default "string"')
|
|
8843
|
+
});
|
|
8844
|
+
var IN_FLIGHT = /* @__PURE__ */ new Set(["queued", "initiated", "ringing", "in_progress", "active", "pending", "dialing"]);
|
|
8845
|
+
var INTEL_DONE = /* @__PURE__ */ new Set(["completed", "partial", "skipped", "failed"]);
|
|
8846
|
+
function isCallDone(call) {
|
|
8847
|
+
if (!call.status || IN_FLIGHT.has(call.status)) return false;
|
|
8848
|
+
if (call.status !== "completed") return true;
|
|
8849
|
+
return INTEL_DONE.has(call.intelligence?.status ?? "");
|
|
8850
|
+
}
|
|
8851
|
+
var POLL_MS = 3e3;
|
|
8852
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8853
|
+
var taskCallTools = [
|
|
8854
|
+
defineTool({
|
|
8855
|
+
name: "place_task_call",
|
|
8856
|
+
description: "WARNING: places a real, billable phone call. Places a real, billable call through an agent with task calls enabled. Use list_agents to find one (features.task_calls_enabled: true), then call wait_for_call with the returned call_id to get the results.",
|
|
8857
|
+
scope: "agent",
|
|
8858
|
+
risk: "sensitive",
|
|
8859
|
+
routes: ["POST /v1/agents/:id/task-calls"],
|
|
8860
|
+
keyScopes: ["calls:write"],
|
|
8861
|
+
input: {
|
|
8862
|
+
agent_id: import_zod16.z.string().describe("Agent with task calls enabled; find one with list_agents (features.task_calls_enabled: true)"),
|
|
8863
|
+
to: import_zod16.z.string().regex(/^\+[1-9]\d{6,14}$/).describe("Number to call, strict E.164, e.g. +919812345678"),
|
|
8864
|
+
on_behalf_of: import_zod16.z.string().min(1).max(120).describe("Business or person the call is for; spoken in the opener"),
|
|
8865
|
+
instructions: import_zod16.z.string().min(1).max(4e3).describe("What the call must do, in plain words"),
|
|
8866
|
+
return_fields: import_zod16.z.array(returnField).min(1).max(20).refine((fs) => new Set(fs.map((f) => f.name)).size === fs.length, "return_fields names must be unique").describe("Fields to extract from the call and return via wait_for_call"),
|
|
8867
|
+
opening_line: import_zod16.z.string().min(1).max(300).optional().describe("First line spoken; defaults to the agent opener or an AI disclosure"),
|
|
8868
|
+
from_number: import_zod16.z.string().optional().describe("Caller ID registered to the workspace; omit to use the agent's attached number")
|
|
8869
|
+
},
|
|
8870
|
+
run: async (client, p) => {
|
|
8871
|
+
const res = await client.agents.placeTaskCall(p.agent_id, {
|
|
8872
|
+
to: p.to,
|
|
8873
|
+
on_behalf_of: p.on_behalf_of,
|
|
8874
|
+
instructions: p.instructions,
|
|
8875
|
+
return_fields: p.return_fields,
|
|
8876
|
+
...p.opening_line ? { opening_line: p.opening_line } : {},
|
|
8877
|
+
...p.from_number ? { from_number: p.from_number } : {}
|
|
8878
|
+
});
|
|
8879
|
+
return {
|
|
8880
|
+
call_id: res?.call_id ?? res?.id,
|
|
8881
|
+
agent_id: res?.agent_id ?? p.agent_id,
|
|
8882
|
+
status: res?.status,
|
|
8883
|
+
next: "Call wait_for_call with this call_id to get the summary and fields."
|
|
8884
|
+
};
|
|
8885
|
+
}
|
|
8886
|
+
}),
|
|
8887
|
+
defineTool({
|
|
8888
|
+
name: "wait_for_call",
|
|
8889
|
+
description: "Wait (up to timeout_s, default 90) for a call to finish and its post-call results to be ready, then return status, summary and the extracted fields. Returns done:false if still running \u2014 just call it again.",
|
|
8890
|
+
scope: "agent",
|
|
8891
|
+
risk: "read",
|
|
8892
|
+
routes: ["GET /v1/calls/:id"],
|
|
8893
|
+
keyScopes: ["calls:read"],
|
|
8894
|
+
input: {
|
|
8895
|
+
call_id: import_zod16.z.string().describe("The call ID from place_task_call or create_call"),
|
|
8896
|
+
timeout_s: import_zod16.z.number().int().min(5).max(240).optional().describe("Max seconds to wait (5\u2013240, default 90)")
|
|
8897
|
+
},
|
|
8898
|
+
run: async (client, { call_id, timeout_s }) => {
|
|
8899
|
+
const deadline = Date.now() + (timeout_s ?? 90) * 1e3;
|
|
8900
|
+
let call = null;
|
|
8901
|
+
for (; ; ) {
|
|
8902
|
+
try {
|
|
8903
|
+
call = await client.calls.retrieve(call_id);
|
|
8904
|
+
} catch {
|
|
8905
|
+
}
|
|
8906
|
+
if (call && isCallDone(call)) {
|
|
8907
|
+
return {
|
|
8908
|
+
done: true,
|
|
8909
|
+
call_id,
|
|
8910
|
+
status: call.status,
|
|
8911
|
+
end_reason: call.end_reason ?? null,
|
|
8912
|
+
duration_seconds: call.bill_duration ?? call.duration_seconds ?? null,
|
|
8913
|
+
summary: call.intelligence?.summary ?? null,
|
|
8914
|
+
fields: call.intelligence?.structured_data ?? null,
|
|
8915
|
+
intelligence_status: call.intelligence?.status ?? null
|
|
8916
|
+
};
|
|
8917
|
+
}
|
|
8918
|
+
if (Date.now() + POLL_MS > deadline) break;
|
|
8919
|
+
await sleep(POLL_MS);
|
|
8920
|
+
}
|
|
8921
|
+
return {
|
|
8922
|
+
done: false,
|
|
8923
|
+
call_id,
|
|
8924
|
+
status: call?.status ?? "unknown",
|
|
8925
|
+
note: "Still running \u2014 call wait_for_call again with the same call_id."
|
|
8926
|
+
};
|
|
8927
|
+
}
|
|
8928
|
+
})
|
|
8929
|
+
];
|
|
8771
8930
|
var import_agentTools2 = (init_agentTools(), __toCommonJS(agentTools_exports));
|
|
8772
8931
|
var REDACTED = "[redacted]";
|
|
8773
8932
|
function redactToolSecrets(value) {
|
|
@@ -8810,15 +8969,16 @@ var require_dist = __commonJS({
|
|
|
8810
8969
|
...publish(shareLinkTools),
|
|
8811
8970
|
...publish(workspaceTools),
|
|
8812
8971
|
...publish(complianceTools),
|
|
8813
|
-
...publish(accountTools)
|
|
8972
|
+
...publish(accountTools),
|
|
8973
|
+
...publish(taskCallTools)
|
|
8814
8974
|
];
|
|
8815
8975
|
var names = /* @__PURE__ */ new Set();
|
|
8816
8976
|
for (const tool of opsToolCatalog2) {
|
|
8817
8977
|
if (names.has(tool.name)) throw new Error(`Duplicate ops tool name: ${tool.name}`);
|
|
8818
8978
|
names.add(tool.name);
|
|
8819
8979
|
}
|
|
8820
|
-
var
|
|
8821
|
-
var WORKSPACE =
|
|
8980
|
+
var import_zod17 = require("zod");
|
|
8981
|
+
var WORKSPACE = import_zod17.z.string().optional().describe("Act in this workspace, e.g. one of your client workspaces (id from list_workspaces). Default: the workspace this connection uses.");
|
|
8822
8982
|
function withWorkspaceParam2(tool) {
|
|
8823
8983
|
return {
|
|
8824
8984
|
...tool,
|
|
@@ -8829,6 +8989,26 @@ var require_dist = __commonJS({
|
|
|
8829
8989
|
}
|
|
8830
8990
|
};
|
|
8831
8991
|
}
|
|
8992
|
+
var DESTRUCTIVE_NAMES = /* @__PURE__ */ new Set([
|
|
8993
|
+
"end_call",
|
|
8994
|
+
"undo_agent_change",
|
|
8995
|
+
"regenerate_share_link",
|
|
8996
|
+
"rotate_campaign_intake"
|
|
8997
|
+
]);
|
|
8998
|
+
var ACRONYMS = { dnc: "DNC", llm: "LLM" };
|
|
8999
|
+
function titleOf(name) {
|
|
9000
|
+
const words = name.split("_").map((w) => ACRONYMS[w] ?? w);
|
|
9001
|
+
return words.join(" ").replace(/^./, (c) => c.toUpperCase());
|
|
9002
|
+
}
|
|
9003
|
+
function toolAnnotations2(tool) {
|
|
9004
|
+
const readOnly = tool.risk === "read";
|
|
9005
|
+
return {
|
|
9006
|
+
title: titleOf(tool.name),
|
|
9007
|
+
readOnlyHint: readOnly,
|
|
9008
|
+
destructiveHint: !readOnly && (DESTRUCTIVE_NAMES.has(tool.name) || tool.routes.some((r) => r.startsWith("DELETE "))),
|
|
9009
|
+
openWorldHint: !readOnly
|
|
9010
|
+
};
|
|
9011
|
+
}
|
|
8832
9012
|
}
|
|
8833
9013
|
});
|
|
8834
9014
|
|
|
@@ -8858,7 +9038,8 @@ function withToolErrors(handler) {
|
|
|
8858
9038
|
// package.json
|
|
8859
9039
|
var package_default = {
|
|
8860
9040
|
name: "@rymi/mcp",
|
|
8861
|
-
|
|
9041
|
+
mcpName: "io.github.rymi-live/rymi-mcp",
|
|
9042
|
+
version: "2.9.0",
|
|
8862
9043
|
description: "Rymi MCP server \u2014 manage AI voice agents via Model Context Protocol",
|
|
8863
9044
|
license: "MIT",
|
|
8864
9045
|
author: "Rymi AI <engineering@rymi.live>",
|
|
@@ -8954,6 +9135,7 @@ async function createServer(apiKey2, options = {}) {
|
|
|
8954
9135
|
tool.name,
|
|
8955
9136
|
tool.description,
|
|
8956
9137
|
tool.input,
|
|
9138
|
+
(0, import_ops_tools.toolAnnotations)(tool),
|
|
8957
9139
|
withToolErrors(async (params) => {
|
|
8958
9140
|
const result2 = await tool.run(rymi, params);
|
|
8959
9141
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rymi/mcp",
|
|
3
|
-
"
|
|
3
|
+
"mcpName": "io.github.rymi-live/rymi-mcp",
|
|
4
|
+
"version": "2.9.0",
|
|
4
5
|
"description": "Rymi MCP server — manage AI voice agents via Model Context Protocol",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "Rymi AI <engineering@rymi.live>",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"@modelcontextprotocol/sdk": "^1.11.1",
|
|
47
|
-
"@rymi/node": "^2.7.
|
|
48
|
+
"@rymi/node": "^2.7.2",
|
|
48
49
|
"zod": "^3.23.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|