@shogo-ai/voice 1.4.1
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/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/chunk-D2EVSUZX.js +27 -0
- package/dist/chunk-Q3TJAJ54.js +165 -0
- package/dist/chunk-QHDIEE7O.js +453 -0
- package/dist/chunk-S3S2RNO6.js +671 -0
- package/dist/chunk-ZGYHDC5G.js +423 -0
- package/dist/index.cjs +1316 -0
- package/dist/index.d.cts +432 -0
- package/dist/index.d.ts +432 -0
- package/dist/index.js +735 -0
- package/dist/native/index.cjs +1667 -0
- package/dist/native/index.d.cts +285 -0
- package/dist/native/index.d.ts +285 -0
- package/dist/native/index.js +949 -0
- package/dist/organicParticlesShaders-DIva0vBO.d.cts +693 -0
- package/dist/organicParticlesShaders-DIva0vBO.d.ts +693 -0
- package/dist/react/index.cjs +1670 -0
- package/dist/react/index.d.cts +423 -0
- package/dist/react/index.d.ts +423 -0
- package/dist/react/index.js +952 -0
- package/dist/route/agent.cjs +981 -0
- package/dist/route/agent.d.cts +20 -0
- package/dist/route/agent.d.ts +20 -0
- package/dist/route/agent.js +17 -0
- package/dist/route/audio-tags.cjs +975 -0
- package/dist/route/audio-tags.d.cts +16 -0
- package/dist/route/audio-tags.d.ts +16 -0
- package/dist/route/audio-tags.js +13 -0
- package/dist/route/index.cjs +987 -0
- package/dist/route/index.d.cts +115 -0
- package/dist/route/index.d.ts +115 -0
- package/dist/route/index.js +12 -0
- package/dist/route/signed-url.cjs +975 -0
- package/dist/route/signed-url.d.cts +12 -0
- package/dist/route/signed-url.d.ts +12 -0
- package/dist/route/signed-url.js +13 -0
- package/dist/route/tts-preview.cjs +975 -0
- package/dist/route/tts-preview.d.cts +17 -0
- package/dist/route/tts-preview.d.ts +17 -0
- package/dist/route/tts-preview.js +13 -0
- package/dist/server.cjs +999 -0
- package/dist/server.d.cts +88 -0
- package/dist/server.d.ts +88 -0
- package/dist/server.js +11 -0
- package/dist/types-BKJtOUbE.d.cts +352 -0
- package/dist/types-BKJtOUbE.d.ts +352 -0
- package/package.json +148 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import {
|
|
2
|
+
composeExpressivityBlock,
|
|
3
|
+
stripExpressivityBlock
|
|
4
|
+
} from "./chunk-Q3TJAJ54.js";
|
|
5
|
+
|
|
6
|
+
// src/prompt.ts
|
|
7
|
+
var DEFAULT_MEMORY_BLOCK = `# Memory
|
|
8
|
+
|
|
9
|
+
Known context about this user from past conversations:
|
|
10
|
+
{{user_context}}
|
|
11
|
+
|
|
12
|
+
Memory retrieval is automatic \u2014 the top matching facts are already injected above. Never say "let me check my memory" or "searching memories."
|
|
13
|
+
|
|
14
|
+
You have one tool:
|
|
15
|
+
- add_memory(fact): save a concise, canonical fact about the user \u2014 preferences, decisions, personal details, follow-ups. Use short normalized phrasings like "favorite color: green" or "lives in Honolulu". Always call it when the user explicitly asks you to remember something.`;
|
|
16
|
+
function stripMemoryBlock(prompt) {
|
|
17
|
+
if (!prompt) return prompt;
|
|
18
|
+
return prompt.replace(/\n*<!-- zix-memory-v\d+ -->[\s\S]*$/m, "").replace(/\n*# Memory\s*\n\s*Known context about this user[\s\S]*$/m, "").trimEnd();
|
|
19
|
+
}
|
|
20
|
+
function extractBasePrompt(prompt) {
|
|
21
|
+
return stripExpressivityBlock(stripMemoryBlock(prompt));
|
|
22
|
+
}
|
|
23
|
+
function composeAgentPrompt(basePrompt, options = {}) {
|
|
24
|
+
const { expressivity = "subtle", audioTags = null, memoryBlock = DEFAULT_MEMORY_BLOCK } = options;
|
|
25
|
+
const stripped = extractBasePrompt(basePrompt);
|
|
26
|
+
const expr = composeExpressivityBlock(expressivity, audioTags);
|
|
27
|
+
const parts = [stripped];
|
|
28
|
+
if (expr) parts.push(expr);
|
|
29
|
+
if (memoryBlock) parts.push(memoryBlock);
|
|
30
|
+
return parts.join("\n\n");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/elevenlabs.ts
|
|
34
|
+
var DEFAULT_ELEVENLABS_BASE_URL = "https://api.elevenlabs.io";
|
|
35
|
+
var CONVAI_SUPPORTED_TTS_MODELS = /* @__PURE__ */ new Set([
|
|
36
|
+
"eleven_turbo_v2",
|
|
37
|
+
"eleven_turbo_v2_5",
|
|
38
|
+
"eleven_flash_v2",
|
|
39
|
+
"eleven_flash_v2_5",
|
|
40
|
+
"eleven_multilingual_v2"
|
|
41
|
+
]);
|
|
42
|
+
var CONVAI_TTS_MODEL_FALLBACK = "eleven_turbo_v2_5";
|
|
43
|
+
function resolveConvaiTtsModel(requested) {
|
|
44
|
+
if (requested && CONVAI_SUPPORTED_TTS_MODELS.has(requested)) return requested;
|
|
45
|
+
return CONVAI_TTS_MODEL_FALLBACK;
|
|
46
|
+
}
|
|
47
|
+
var ElevenLabsApiError = class extends Error {
|
|
48
|
+
constructor(message, status, body) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.status = status;
|
|
51
|
+
this.body = body;
|
|
52
|
+
this.name = "ElevenLabsApiError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var ElevenLabsClient = class {
|
|
56
|
+
constructor(config) {
|
|
57
|
+
this.config = config;
|
|
58
|
+
if (!config.apiKey) throw new Error("ElevenLabsClient: apiKey is required");
|
|
59
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_ELEVENLABS_BASE_URL).replace(/\/+$/, "");
|
|
60
|
+
this.fetchImpl = config.fetch ?? globalThis.fetch;
|
|
61
|
+
if (typeof this.fetchImpl !== "function") {
|
|
62
|
+
throw new Error("ElevenLabsClient: global fetch is unavailable; pass config.fetch");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
headers(extra = {}) {
|
|
66
|
+
return {
|
|
67
|
+
"xi-api-key": this.config.apiKey,
|
|
68
|
+
...extra
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Create a new convai agent. Returns the new `agent_id`. */
|
|
72
|
+
async createAgent(params) {
|
|
73
|
+
const prompt = composeAgentPrompt(params.systemPrompt, {
|
|
74
|
+
expressivity: params.expressivity ?? "subtle",
|
|
75
|
+
audioTags: params.audioTags ?? null,
|
|
76
|
+
memoryBlock: params.memoryBlock
|
|
77
|
+
});
|
|
78
|
+
const ttsConfig = {
|
|
79
|
+
voice_id: params.voiceId,
|
|
80
|
+
model_id: resolveConvaiTtsModel(params.ttsModelId)
|
|
81
|
+
};
|
|
82
|
+
if (params.voiceSettings) ttsConfig.voice_settings = params.voiceSettings;
|
|
83
|
+
const body = {
|
|
84
|
+
name: `Companion-${params.characterName}-for-${params.displayName}`,
|
|
85
|
+
conversation_config: {
|
|
86
|
+
agent: {
|
|
87
|
+
prompt: {
|
|
88
|
+
prompt,
|
|
89
|
+
...params.tools ? { tools: params.tools } : {}
|
|
90
|
+
},
|
|
91
|
+
first_message: params.firstMessage,
|
|
92
|
+
language: params.language ?? "en"
|
|
93
|
+
},
|
|
94
|
+
tts: ttsConfig
|
|
95
|
+
},
|
|
96
|
+
platform_settings: {
|
|
97
|
+
overrides: {
|
|
98
|
+
conversation_config_override: {
|
|
99
|
+
agent: { prompt: { prompt: true }, first_message: true, language: true },
|
|
100
|
+
tts: { voice_id: true },
|
|
101
|
+
conversation: { text_only: true }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
dynamic_variables: {
|
|
105
|
+
dynamic_variable_placeholders: {
|
|
106
|
+
user_context: "No prior memories yet.",
|
|
107
|
+
character_name: "",
|
|
108
|
+
...params.dynamicVariablePlaceholders ?? {}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const res = await this.fetchImpl(`${this.baseUrl}/v1/convai/agents/create`, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: this.headers({ "content-type": "application/json" }),
|
|
116
|
+
body: JSON.stringify(body)
|
|
117
|
+
});
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
const text = await res.text();
|
|
120
|
+
throw new ElevenLabsApiError(`createAgent failed: ${res.status}`, res.status, text);
|
|
121
|
+
}
|
|
122
|
+
const data = await res.json();
|
|
123
|
+
return data.agent_id;
|
|
124
|
+
}
|
|
125
|
+
/** PATCH any subset of agent settings. Idempotent; only sends the keys you supply. */
|
|
126
|
+
async patchAgent(agentId, params) {
|
|
127
|
+
const body = {};
|
|
128
|
+
if (params.displayName !== void 0 || params.characterName !== void 0) {
|
|
129
|
+
body.name = `Companion-${params.characterName ?? ""}-for-${params.displayName ?? ""}`.replace(
|
|
130
|
+
/-for-$/,
|
|
131
|
+
""
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
const conv = {};
|
|
135
|
+
const agent = {};
|
|
136
|
+
const prompt = {};
|
|
137
|
+
if (params.systemPrompt !== void 0) {
|
|
138
|
+
prompt.prompt = composeAgentPrompt(params.systemPrompt, {
|
|
139
|
+
expressivity: params.expressivity ?? "subtle",
|
|
140
|
+
audioTags: params.audioTags ?? null,
|
|
141
|
+
memoryBlock: params.memoryBlock
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (params.tools) prompt.tools = params.tools;
|
|
145
|
+
if (Object.keys(prompt).length) agent.prompt = prompt;
|
|
146
|
+
if (params.firstMessage !== void 0) agent.first_message = params.firstMessage;
|
|
147
|
+
if (Object.keys(agent).length) conv.agent = agent;
|
|
148
|
+
const tts = {};
|
|
149
|
+
if (params.voiceId !== void 0) tts.voice_id = params.voiceId;
|
|
150
|
+
if (params.voiceSettings) tts.voice_settings = params.voiceSettings;
|
|
151
|
+
if (params.ttsModelId !== void 0) tts.model_id = resolveConvaiTtsModel(params.ttsModelId);
|
|
152
|
+
if (Object.keys(tts).length) conv.tts = tts;
|
|
153
|
+
if (Object.keys(conv).length) body.conversation_config = conv;
|
|
154
|
+
if (params.enableUserContextOverride) {
|
|
155
|
+
body.platform_settings = {
|
|
156
|
+
overrides: {
|
|
157
|
+
conversation_config_override: {
|
|
158
|
+
agent: { prompt: { prompt: true }, first_message: true, language: true },
|
|
159
|
+
tts: { voice_id: true },
|
|
160
|
+
conversation: { text_only: true }
|
|
161
|
+
},
|
|
162
|
+
custom_llm_extra_body: false,
|
|
163
|
+
enable_conversation_initiation_client_data_from_webhook: false
|
|
164
|
+
},
|
|
165
|
+
dynamic_variables: {
|
|
166
|
+
dynamic_variable_placeholders: {
|
|
167
|
+
user_context: "No prior memories yet.",
|
|
168
|
+
character_name: ""
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (!Object.keys(body).length) return;
|
|
174
|
+
const res = await this.fetchImpl(`${this.baseUrl}/v1/convai/agents/${encodeURIComponent(agentId)}`, {
|
|
175
|
+
method: "PATCH",
|
|
176
|
+
headers: this.headers({ "content-type": "application/json" }),
|
|
177
|
+
body: JSON.stringify(body)
|
|
178
|
+
});
|
|
179
|
+
if (!res.ok) {
|
|
180
|
+
const text = await res.text();
|
|
181
|
+
throw new ElevenLabsApiError(`patchAgent failed: ${res.status}`, res.status, text);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Delete a convai agent. Best-effort: swallow errors so teardown during a
|
|
186
|
+
* 500 response doesn't cascade into a second failure.
|
|
187
|
+
*/
|
|
188
|
+
async deleteAgent(agentId) {
|
|
189
|
+
try {
|
|
190
|
+
await this.fetchImpl(`${this.baseUrl}/v1/convai/agents/${encodeURIComponent(agentId)}`, {
|
|
191
|
+
method: "DELETE",
|
|
192
|
+
headers: this.headers()
|
|
193
|
+
});
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Fetch a short-lived signed URL the browser can use to start a session. */
|
|
198
|
+
async getSignedUrl(agentId) {
|
|
199
|
+
const res = await this.fetchImpl(
|
|
200
|
+
`${this.baseUrl}/v1/convai/conversation/get-signed-url?agent_id=${encodeURIComponent(agentId)}`,
|
|
201
|
+
{ headers: this.headers() }
|
|
202
|
+
);
|
|
203
|
+
if (!res.ok) {
|
|
204
|
+
const text = await res.text();
|
|
205
|
+
throw new ElevenLabsApiError(`getSignedUrl failed: ${res.status}`, res.status, text);
|
|
206
|
+
}
|
|
207
|
+
const data = await res.json();
|
|
208
|
+
return data.signed_url;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* One-shot TTS. Returns the raw audio bytes plus the model id that was
|
|
212
|
+
* actually used (some models aren't available for every account, so we
|
|
213
|
+
* fall back to `eleven_turbo_v2_5` on the first failure).
|
|
214
|
+
*/
|
|
215
|
+
async textToSpeech(params) {
|
|
216
|
+
const modelId = params.modelId && params.modelId.length > 0 ? params.modelId : "eleven_v3";
|
|
217
|
+
const accept = params.accept ?? "audio/mpeg";
|
|
218
|
+
const attempt = async (m) => {
|
|
219
|
+
const res2 = await this.fetchImpl(
|
|
220
|
+
`${this.baseUrl}/v1/text-to-speech/${encodeURIComponent(params.voiceId)}`,
|
|
221
|
+
{
|
|
222
|
+
method: "POST",
|
|
223
|
+
headers: this.headers({ "content-type": "application/json", accept }),
|
|
224
|
+
body: JSON.stringify({
|
|
225
|
+
text: params.text,
|
|
226
|
+
model_id: m,
|
|
227
|
+
voice_settings: params.voiceSettings
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
return res2;
|
|
232
|
+
};
|
|
233
|
+
let res = await attempt(modelId);
|
|
234
|
+
let used = modelId;
|
|
235
|
+
if (!res.ok && modelId !== "eleven_turbo_v2_5") {
|
|
236
|
+
res = await attempt("eleven_turbo_v2_5");
|
|
237
|
+
used = "eleven_turbo_v2_5";
|
|
238
|
+
}
|
|
239
|
+
if (!res.ok) {
|
|
240
|
+
const text = await res.text();
|
|
241
|
+
throw new ElevenLabsApiError(`textToSpeech failed: ${res.status}`, res.status, text);
|
|
242
|
+
}
|
|
243
|
+
const audio = await res.arrayBuffer();
|
|
244
|
+
const contentType = res.headers.get("content-type") ?? accept;
|
|
245
|
+
return { audio, modelId: used, contentType };
|
|
246
|
+
}
|
|
247
|
+
/** Probe whether a given voice id still exists on the caller's account. */
|
|
248
|
+
async voiceExists(voiceId) {
|
|
249
|
+
const res = await this.fetchImpl(
|
|
250
|
+
`${this.baseUrl}/v1/voices/${encodeURIComponent(voiceId)}`,
|
|
251
|
+
{ headers: this.headers() }
|
|
252
|
+
);
|
|
253
|
+
return res.ok;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Register a Twilio phone number with an ElevenLabs agent. EL becomes
|
|
257
|
+
* the SIP target for inbound calls to that number — Twilio bridges
|
|
258
|
+
* the call via EL's native integration and we never have to run a
|
|
259
|
+
* Media Streams ↔ convai WebSocket bridge ourselves.
|
|
260
|
+
*
|
|
261
|
+
* Returns the ElevenLabs `phone_number_id` (distinct from the Twilio
|
|
262
|
+
* `sid`) which is the handle used by `outboundCall` + `deletePhoneNumber`.
|
|
263
|
+
*/
|
|
264
|
+
async createPhoneNumberTwilio(params) {
|
|
265
|
+
const body = {
|
|
266
|
+
phone_number: params.phoneNumber,
|
|
267
|
+
label: params.label ?? params.phoneNumber,
|
|
268
|
+
provider: "twilio",
|
|
269
|
+
sid: params.twilioAccountSid,
|
|
270
|
+
token: params.twilioAuthToken
|
|
271
|
+
};
|
|
272
|
+
const res = await this.fetchImpl(
|
|
273
|
+
`${this.baseUrl}/v1/convai/phone-numbers`,
|
|
274
|
+
{
|
|
275
|
+
method: "POST",
|
|
276
|
+
headers: this.headers({ "content-type": "application/json" }),
|
|
277
|
+
body: JSON.stringify(body)
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
if (!res.ok) {
|
|
281
|
+
const text = await res.text();
|
|
282
|
+
throw new ElevenLabsApiError(
|
|
283
|
+
`createPhoneNumberTwilio failed: ${res.status}`,
|
|
284
|
+
res.status,
|
|
285
|
+
text
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const data = await res.json();
|
|
289
|
+
const id = data.phone_number_id ?? data.id;
|
|
290
|
+
if (!id) {
|
|
291
|
+
throw new ElevenLabsApiError(
|
|
292
|
+
"createPhoneNumberTwilio returned no id",
|
|
293
|
+
500,
|
|
294
|
+
JSON.stringify(data)
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const patchRes = await this.fetchImpl(
|
|
298
|
+
`${this.baseUrl}/v1/convai/phone-numbers/${encodeURIComponent(id)}`,
|
|
299
|
+
{
|
|
300
|
+
method: "PATCH",
|
|
301
|
+
headers: this.headers({ "content-type": "application/json" }),
|
|
302
|
+
body: JSON.stringify({ agent_id: params.agentId })
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
if (!patchRes.ok) {
|
|
306
|
+
const text = await patchRes.text();
|
|
307
|
+
try {
|
|
308
|
+
await this.deletePhoneNumber(id);
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
throw new ElevenLabsApiError(
|
|
312
|
+
`assignAgentToPhoneNumber failed: ${patchRes.status}`,
|
|
313
|
+
patchRes.status,
|
|
314
|
+
text
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return { phoneNumberId: id };
|
|
318
|
+
}
|
|
319
|
+
/** Detach a previously-registered phone number from ElevenLabs. */
|
|
320
|
+
async deletePhoneNumber(phoneNumberId) {
|
|
321
|
+
const res = await this.fetchImpl(
|
|
322
|
+
`${this.baseUrl}/v1/convai/phone-numbers/${encodeURIComponent(phoneNumberId)}`,
|
|
323
|
+
{ method: "DELETE", headers: this.headers() }
|
|
324
|
+
);
|
|
325
|
+
if (!res.ok && res.status !== 404) {
|
|
326
|
+
const text = await res.text();
|
|
327
|
+
throw new ElevenLabsApiError(
|
|
328
|
+
`deletePhoneNumber failed: ${res.status}`,
|
|
329
|
+
res.status,
|
|
330
|
+
text
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Place an outbound PSTN call via a previously-registered EL phone
|
|
336
|
+
* number. EL drives Twilio (or a SIP trunk) under the hood — we just
|
|
337
|
+
* hand it the destination number and the agent to bridge to. Returns
|
|
338
|
+
* the Twilio `callSid` + EL `conversationId` for metering / tracing.
|
|
339
|
+
*
|
|
340
|
+
* As of 2026-Q2 the EL API uses provider-scoped routes:
|
|
341
|
+
* - Twilio numbers → POST /v1/convai/twilio/outbound-call
|
|
342
|
+
* - SIP numbers → POST /v1/convai/sip-trunk/outbound-call
|
|
343
|
+
* and `agent_phone_number_id` is a body field (no longer a path
|
|
344
|
+
* segment). The previous `/v1/convai/phone-numbers/{id}/outbound-call`
|
|
345
|
+
* route now returns 404. Callers that don't know the provider can
|
|
346
|
+
* look it up from `GET /v1/convai/phone-numbers/{id}` (`provider:
|
|
347
|
+
* "twilio" | "sip_trunk"`); most hosted setups are Twilio, so that's
|
|
348
|
+
* the default here.
|
|
349
|
+
*/
|
|
350
|
+
async outboundCall(params) {
|
|
351
|
+
const provider = params.provider ?? "twilio";
|
|
352
|
+
const body = {
|
|
353
|
+
agent_id: params.agentId,
|
|
354
|
+
agent_phone_number_id: params.phoneNumberId,
|
|
355
|
+
to_number: params.toNumber
|
|
356
|
+
};
|
|
357
|
+
if (params.dynamicVariables) {
|
|
358
|
+
body.conversation_initiation_client_data = {
|
|
359
|
+
dynamic_variables: params.dynamicVariables
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
const res = await this.fetchImpl(
|
|
363
|
+
`${this.baseUrl}/v1/convai/${provider}/outbound-call`,
|
|
364
|
+
{
|
|
365
|
+
method: "POST",
|
|
366
|
+
headers: this.headers({ "content-type": "application/json" }),
|
|
367
|
+
body: JSON.stringify(body)
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
if (!res.ok) {
|
|
371
|
+
const text = await res.text();
|
|
372
|
+
throw new ElevenLabsApiError(
|
|
373
|
+
`outboundCall failed: ${res.status}`,
|
|
374
|
+
res.status,
|
|
375
|
+
text
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
const data = await res.json();
|
|
379
|
+
const callSid = data.call_sid ?? data.callSid;
|
|
380
|
+
const conversationId = data.conversation_id ?? data.conversationId;
|
|
381
|
+
if (!callSid || !conversationId) {
|
|
382
|
+
throw new ElevenLabsApiError(
|
|
383
|
+
"outboundCall missing callSid or conversationId",
|
|
384
|
+
500,
|
|
385
|
+
JSON.stringify(data)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
return { callSid, conversationId };
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
var MEMORY_CLIENT_TOOLS = [
|
|
392
|
+
{
|
|
393
|
+
type: "client",
|
|
394
|
+
name: "add_memory",
|
|
395
|
+
description: "Save a concise canonical fact about the user (preferences, decisions, personal details, follow-ups). Use whenever the user shares something worth remembering.",
|
|
396
|
+
expects_response: true,
|
|
397
|
+
parameters: {
|
|
398
|
+
type: "object",
|
|
399
|
+
properties: {
|
|
400
|
+
fact: {
|
|
401
|
+
type: "string",
|
|
402
|
+
description: 'A short normalized fact, e.g. "prefers window seats", "favorite color: green". Max 500 chars.'
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
required: ["fact"]
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
export {
|
|
411
|
+
DEFAULT_MEMORY_BLOCK,
|
|
412
|
+
stripMemoryBlock,
|
|
413
|
+
extractBasePrompt,
|
|
414
|
+
composeAgentPrompt,
|
|
415
|
+
DEFAULT_ELEVENLABS_BASE_URL,
|
|
416
|
+
CONVAI_SUPPORTED_TTS_MODELS,
|
|
417
|
+
CONVAI_TTS_MODEL_FALLBACK,
|
|
418
|
+
resolveConvaiTtsModel,
|
|
419
|
+
ElevenLabsApiError,
|
|
420
|
+
ElevenLabsClient,
|
|
421
|
+
MEMORY_CLIENT_TOOLS
|
|
422
|
+
};
|
|
423
|
+
//# sourceMappingURL=chunk-ZGYHDC5G.js.map
|