@shogo-ai/voice 1.10.0 → 2.4.2
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 +89 -0
- package/dist/{chunk-S3S2RNO6.js → chunk-BI6SL35K.js} +1 -184
- package/dist/chunk-IOFWML5L.js +1078 -0
- package/dist/chunk-KMSL5PWK.js +540 -0
- package/dist/chunk-ME3SIZZU.js +581 -0
- package/dist/{chunk-T3T4EBWY.js → chunk-RALZRMFL.js} +6 -2
- package/dist/chunk-TQOBJMEK.js +17 -0
- package/dist/chunk-U5UC7ZVS.js +988 -0
- package/dist/chunk-UW7VQ3S6.js +148 -0
- package/dist/chunk-ZAW6F3YT.js +172 -0
- package/dist/index.cjs +748 -25
- package/dist/index.d.cts +396 -3
- package/dist/index.d.ts +396 -3
- package/dist/index.js +63 -3
- package/dist/live/client.cjs +173 -0
- package/dist/live/client.d.cts +132 -0
- package/dist/live/client.d.ts +132 -0
- package/dist/live/client.js +9 -0
- package/dist/native/index.d.cts +5 -2
- package/dist/native/index.d.ts +5 -2
- package/dist/native/index.js +15 -11
- package/dist/{organicParticlesShaders-DIva0vBO.d.ts → organicParticlesShaders-seZq7jYX.d.cts} +1 -421
- package/dist/{organicParticlesShaders-DIva0vBO.d.cts → organicParticlesShaders-seZq7jYX.d.ts} +1 -421
- package/dist/particlesConfig-0YbdPOdY.d.cts +223 -0
- package/dist/particlesConfig-0YbdPOdY.d.ts +223 -0
- package/dist/react/conversation.cjs +789 -0
- package/dist/react/conversation.d.cts +134 -0
- package/dist/react/conversation.d.ts +134 -0
- package/dist/react/conversation.js +13 -0
- package/dist/react/index.cjs +374 -36
- package/dist/react/index.d.cts +10 -141
- package/dist/react/index.d.ts +10 -141
- package/dist/react/index.js +23 -770
- package/dist/react/visuals.cjs +1048 -0
- package/dist/react/visuals.d.cts +70 -0
- package/dist/react/visuals.d.ts +70 -0
- package/dist/react/visuals.js +10 -0
- package/dist/route/agent.cjs +1047 -85
- package/dist/route/agent.js +3 -3
- package/dist/route/audio-tags.cjs +1047 -85
- package/dist/route/audio-tags.js +3 -3
- package/dist/route/index.cjs +1051 -85
- package/dist/route/index.d.cts +19 -3
- package/dist/route/index.d.ts +19 -3
- package/dist/route/index.js +3 -3
- package/dist/route/music.cjs +1047 -85
- package/dist/route/music.js +3 -3
- package/dist/route/op.cjs +2127 -0
- package/dist/route/op.d.cts +43 -0
- package/dist/route/op.d.ts +43 -0
- package/dist/route/op.js +27 -0
- package/dist/route/signed-url.cjs +1047 -85
- package/dist/route/signed-url.js +3 -3
- package/dist/route/tts-preview.cjs +1047 -85
- package/dist/route/tts-preview.d.cts +6 -4
- package/dist/route/tts-preview.d.ts +6 -4
- package/dist/route/tts-preview.js +3 -3
- package/dist/server.cjs +1047 -85
- package/dist/server.d.cts +40 -8
- package/dist/server.d.ts +40 -8
- package/dist/server.js +2 -2
- package/dist/types-Bfhu-aQH.d.cts +199 -0
- package/dist/types-Bfhu-aQH.d.ts +199 -0
- package/dist/{types-W9y6eMj3.d.ts → types-CadjTXNH.d.cts} +193 -12
- package/dist/{types-W9y6eMj3.d.cts → types-CadjTXNH.d.ts} +193 -12
- package/package.json +21 -1
- package/dist/chunk-B4JC3DK2.js +0 -529
- package/dist/chunk-O362EJQR.js +0 -524
package/dist/chunk-O362EJQR.js
DELETED
|
@@ -1,524 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CONVAI_TTS_MODEL_FALLBACK,
|
|
3
|
-
ElevenLabsApiError,
|
|
4
|
-
ElevenLabsClient,
|
|
5
|
-
MEMORY_CLIENT_TOOLS,
|
|
6
|
-
extractBasePrompt,
|
|
7
|
-
resolveConvaiTtsModel
|
|
8
|
-
} from "./chunk-B4JC3DK2.js";
|
|
9
|
-
import {
|
|
10
|
-
AUDIO_TAGS,
|
|
11
|
-
AUDIO_TAG_GROUPS,
|
|
12
|
-
DEFAULT_ALLOWED_TAGS,
|
|
13
|
-
DEFAULT_VOICE_SETTINGS,
|
|
14
|
-
EXPRESSIVITY_OPTIONS,
|
|
15
|
-
buildPreviewLine,
|
|
16
|
-
normalizeAudioTags,
|
|
17
|
-
normalizeExpressivity,
|
|
18
|
-
normalizeVoiceSettings,
|
|
19
|
-
readAudioTags,
|
|
20
|
-
readExpressivity,
|
|
21
|
-
readVoiceSettings
|
|
22
|
-
} from "./chunk-Q3TJAJ54.js";
|
|
23
|
-
|
|
24
|
-
// src/server.ts
|
|
25
|
-
function json(data, status = 200, extraHeaders = {}) {
|
|
26
|
-
return new Response(JSON.stringify(data), {
|
|
27
|
-
status,
|
|
28
|
-
headers: { "Content-Type": "application/json", ...extraHeaders }
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
async function readJson(req) {
|
|
32
|
-
try {
|
|
33
|
-
const text = await req.text();
|
|
34
|
-
if (!text) return {};
|
|
35
|
-
return JSON.parse(text);
|
|
36
|
-
} catch {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
var NOOP_LOGGER = () => {
|
|
41
|
-
};
|
|
42
|
-
function parseMusicBody(raw) {
|
|
43
|
-
if (raw === null || typeof raw !== "object") return { error: "Invalid JSON body" };
|
|
44
|
-
const b = raw;
|
|
45
|
-
const hasPrompt = typeof b.prompt === "string" && b.prompt.trim().length > 0;
|
|
46
|
-
const hasPlan = b.compositionPlan != null && typeof b.compositionPlan === "object";
|
|
47
|
-
if (hasPrompt === hasPlan) {
|
|
48
|
-
return { error: "Provide exactly one of `prompt` or `compositionPlan`" };
|
|
49
|
-
}
|
|
50
|
-
const params = {};
|
|
51
|
-
if (hasPrompt) {
|
|
52
|
-
params.prompt = b.prompt.trim();
|
|
53
|
-
if (typeof b.musicLengthMs === "number") params.musicLengthMs = b.musicLengthMs;
|
|
54
|
-
if (typeof b.forceInstrumental === "boolean") params.forceInstrumental = b.forceInstrumental;
|
|
55
|
-
} else {
|
|
56
|
-
params.compositionPlan = b.compositionPlan;
|
|
57
|
-
}
|
|
58
|
-
if (typeof b.modelId === "string" && b.modelId.length > 0) params.modelId = b.modelId;
|
|
59
|
-
if (typeof b.outputFormat === "string" && b.outputFormat.length > 0) {
|
|
60
|
-
params.outputFormat = b.outputFormat;
|
|
61
|
-
}
|
|
62
|
-
return { params };
|
|
63
|
-
}
|
|
64
|
-
function resolveProxyOptions(config) {
|
|
65
|
-
if (config.proxy) {
|
|
66
|
-
if (!config.proxy.runtimeToken || !config.proxy.projectId || !config.proxy.apiUrl) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
"createVoiceHandlers: proxy requires runtimeToken, projectId, and apiUrl"
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
return config.proxy;
|
|
72
|
-
}
|
|
73
|
-
if (typeof process === "undefined" || !process.env) return null;
|
|
74
|
-
const runtimeToken = process.env.RUNTIME_AUTH_SECRET;
|
|
75
|
-
const projectId = process.env.PROJECT_ID;
|
|
76
|
-
if (!runtimeToken || !projectId) return null;
|
|
77
|
-
const apiUrl = process.env.SHOGO_API_URL ?? process.env.SHOGO_CLOUD_URL ?? "http://localhost:8002";
|
|
78
|
-
return {
|
|
79
|
-
runtimeToken,
|
|
80
|
-
projectId,
|
|
81
|
-
apiUrl,
|
|
82
|
-
...config.fetch ? { fetch: config.fetch } : {}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
function createProxyHandlers(proxy, log) {
|
|
86
|
-
const fetchImpl = proxy.fetch ?? globalThis.fetch;
|
|
87
|
-
if (typeof fetchImpl !== "function") {
|
|
88
|
-
throw new Error(
|
|
89
|
-
"createVoiceHandlers proxy: global fetch is unavailable; pass proxy.fetch"
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
const apiBase = proxy.apiUrl.replace(/\/+$/, "");
|
|
93
|
-
function proxyUrl(path, forward) {
|
|
94
|
-
const tail = [`projectId=${encodeURIComponent(proxy.projectId)}`];
|
|
95
|
-
for (const [k, v] of Object.entries(forward)) {
|
|
96
|
-
if (typeof v === "string" && v.length > 0) {
|
|
97
|
-
tail.push(`${k}=${encodeURIComponent(v)}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const sep = path.includes("?") ? "&" : "?";
|
|
101
|
-
return `${apiBase}${path}${sep}${tail.join("&")}`;
|
|
102
|
-
}
|
|
103
|
-
const FORWARDED_SIGNED_URL_PARAMS = ["agentName"];
|
|
104
|
-
async function doSignedUrl(req) {
|
|
105
|
-
if (req.method !== "GET") return json({ error: "Method Not Allowed" }, 405);
|
|
106
|
-
try {
|
|
107
|
-
let incomingUrl = null;
|
|
108
|
-
try {
|
|
109
|
-
incomingUrl = new URL(req.url);
|
|
110
|
-
} catch {
|
|
111
|
-
}
|
|
112
|
-
const forward = {};
|
|
113
|
-
if (incomingUrl) {
|
|
114
|
-
for (const key of FORWARDED_SIGNED_URL_PARAMS) {
|
|
115
|
-
const v = incomingUrl.searchParams.get(key);
|
|
116
|
-
if (v != null) forward[key] = v;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
const upstream = await fetchImpl(proxyUrl("/api/voice/signed-url", forward), {
|
|
120
|
-
method: "GET",
|
|
121
|
-
headers: { "x-runtime-token": proxy.runtimeToken },
|
|
122
|
-
credentials: "omit"
|
|
123
|
-
});
|
|
124
|
-
const body = await upstream.text();
|
|
125
|
-
const headers = { "content-type": "application/json" };
|
|
126
|
-
const ct = upstream.headers.get("content-type");
|
|
127
|
-
if (ct) headers["content-type"] = ct;
|
|
128
|
-
return new Response(body, { status: upstream.status, headers });
|
|
129
|
-
} catch (err) {
|
|
130
|
-
log("error", "proxy signedUrl failed", {
|
|
131
|
-
error: err instanceof Error ? err.message : String(err)
|
|
132
|
-
});
|
|
133
|
-
return json({ error: "signedUrl proxy failed" }, 502);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async function doAudioTags(req) {
|
|
137
|
-
if (req.method !== "GET") return json({ error: "Method Not Allowed" }, 405);
|
|
138
|
-
return json({
|
|
139
|
-
tags: AUDIO_TAGS,
|
|
140
|
-
groups: AUDIO_TAG_GROUPS,
|
|
141
|
-
expressivity: EXPRESSIVITY_OPTIONS,
|
|
142
|
-
defaults: {
|
|
143
|
-
allowedTags: DEFAULT_ALLOWED_TAGS,
|
|
144
|
-
voiceSettings: DEFAULT_VOICE_SETTINGS,
|
|
145
|
-
ttsModelId: CONVAI_TTS_MODEL_FALLBACK
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
async function doMusic(req) {
|
|
150
|
-
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
151
|
-
const raw = await readJson(req);
|
|
152
|
-
const parsed = parseMusicBody(raw);
|
|
153
|
-
if ("error" in parsed) return json({ error: parsed.error }, 400);
|
|
154
|
-
try {
|
|
155
|
-
const upstream = await fetchImpl(proxyUrl("/api/voice/music", {}), {
|
|
156
|
-
method: "POST",
|
|
157
|
-
headers: {
|
|
158
|
-
"x-runtime-token": proxy.runtimeToken,
|
|
159
|
-
"content-type": "application/json",
|
|
160
|
-
accept: "audio/mpeg"
|
|
161
|
-
},
|
|
162
|
-
body: JSON.stringify(parsed.params),
|
|
163
|
-
credentials: "omit"
|
|
164
|
-
});
|
|
165
|
-
const buf = await upstream.arrayBuffer();
|
|
166
|
-
const headers = {};
|
|
167
|
-
const ct = upstream.headers.get("content-type");
|
|
168
|
-
if (ct) headers["content-type"] = ct;
|
|
169
|
-
return new Response(buf, { status: upstream.status, headers });
|
|
170
|
-
} catch (err) {
|
|
171
|
-
log("error", "proxy music failed", {
|
|
172
|
-
error: err instanceof Error ? err.message : String(err)
|
|
173
|
-
});
|
|
174
|
-
return json({ error: "music proxy failed" }, 502);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function notImplemented(label) {
|
|
178
|
-
return async () => json(
|
|
179
|
-
{
|
|
180
|
-
error: "Not Implemented",
|
|
181
|
-
detail: `${label} is not available in runtime-token proxy mode; use BYO-EL or the hosted bearer SDK path.`
|
|
182
|
-
},
|
|
183
|
-
501
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
return {
|
|
187
|
-
signedUrl: doSignedUrl,
|
|
188
|
-
tts: notImplemented("tts"),
|
|
189
|
-
music: doMusic,
|
|
190
|
-
agent: {
|
|
191
|
-
create: notImplemented("agent.create"),
|
|
192
|
-
patch: notImplemented("agent.patch"),
|
|
193
|
-
delete: notImplemented("agent.delete")
|
|
194
|
-
},
|
|
195
|
-
audioTags: doAudioTags,
|
|
196
|
-
// In proxy mode we don't own an EL client. Expose a throwing stub so
|
|
197
|
-
// accidental use is loud instead of silently passing around a
|
|
198
|
-
// half-configured client.
|
|
199
|
-
elevenLabs: new Proxy({}, {
|
|
200
|
-
get(_t, prop) {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`createVoiceHandlers: elevenLabs.${String(prop)} is not available in runtime-token proxy mode`
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
function createVoiceHandlers(config) {
|
|
209
|
-
const log = config.logger ?? NOOP_LOGGER;
|
|
210
|
-
const proxy = resolveProxyOptions(config);
|
|
211
|
-
if (proxy) {
|
|
212
|
-
if (config.apiKey) {
|
|
213
|
-
log("warn", "createVoiceHandlers: apiKey provided but runtime-token proxy mode is active; apiKey is ignored");
|
|
214
|
-
}
|
|
215
|
-
return createProxyHandlers(proxy, log);
|
|
216
|
-
}
|
|
217
|
-
if (!config.apiKey) throw new Error("createVoiceHandlers: apiKey is required");
|
|
218
|
-
if (!config.getUser) throw new Error("createVoiceHandlers: getUser is required");
|
|
219
|
-
if (!config.companionStore) throw new Error("createVoiceHandlers: companionStore is required");
|
|
220
|
-
const getUser = config.getUser;
|
|
221
|
-
const companionStore = config.companionStore;
|
|
222
|
-
const includeMemoryTools = config.includeMemoryTools ?? true;
|
|
223
|
-
const tools = includeMemoryTools ? MEMORY_CLIENT_TOOLS : void 0;
|
|
224
|
-
const elConfig = {
|
|
225
|
-
apiKey: config.apiKey,
|
|
226
|
-
...config.elevenLabsBaseUrl ? { baseUrl: config.elevenLabsBaseUrl } : {},
|
|
227
|
-
...config.fetch ? { fetch: config.fetch } : {}
|
|
228
|
-
};
|
|
229
|
-
const el = new ElevenLabsClient(elConfig);
|
|
230
|
-
async function resolveUser(req) {
|
|
231
|
-
const u = await getUser(req);
|
|
232
|
-
if (!u) return json({ error: "Unauthorized" }, 401);
|
|
233
|
-
return u;
|
|
234
|
-
}
|
|
235
|
-
function handleElError(e, fallbackLabel) {
|
|
236
|
-
if (e instanceof ElevenLabsApiError) {
|
|
237
|
-
log("warn", `${fallbackLabel}: 11Labs ${e.status}`, { body: e.body });
|
|
238
|
-
return json({ error: fallbackLabel, detail: e.body }, 502);
|
|
239
|
-
}
|
|
240
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
241
|
-
log("error", `${fallbackLabel}: ${message}`);
|
|
242
|
-
return json({ error: fallbackLabel, detail: message }, 500);
|
|
243
|
-
}
|
|
244
|
-
async function doSignedUrl(req) {
|
|
245
|
-
if (req.method !== "GET") return json({ error: "Method Not Allowed" }, 405);
|
|
246
|
-
const u = await resolveUser(req);
|
|
247
|
-
if (u instanceof Response) return u;
|
|
248
|
-
const companion = await companionStore.findByUserId(u.id);
|
|
249
|
-
if (!companion || !companion.agentId) return json({ error: "No companion" }, 404);
|
|
250
|
-
const basePrompt = extractBasePrompt(companion.systemPrompt || "");
|
|
251
|
-
try {
|
|
252
|
-
await el.patchAgent(companion.agentId, {
|
|
253
|
-
systemPrompt: basePrompt,
|
|
254
|
-
tools,
|
|
255
|
-
enableUserContextOverride: includeMemoryTools,
|
|
256
|
-
voiceId: companion.voiceId,
|
|
257
|
-
expressivity: readExpressivity(companion.expressivity),
|
|
258
|
-
audioTags: readAudioTags(companion.audioTags),
|
|
259
|
-
voiceSettings: readVoiceSettings(companion.voiceSettings),
|
|
260
|
-
ttsModelId: companion.ttsModelId ?? null,
|
|
261
|
-
...includeMemoryTools ? {} : { memoryBlock: null }
|
|
262
|
-
});
|
|
263
|
-
if (basePrompt !== companion.systemPrompt) {
|
|
264
|
-
await companionStore.update(u.id, { systemPrompt: basePrompt });
|
|
265
|
-
}
|
|
266
|
-
} catch (e) {
|
|
267
|
-
log("warn", "signedUrl: pre-sync patch failed; continuing", {
|
|
268
|
-
error: e instanceof Error ? e.message : String(e)
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
let signedUrl;
|
|
272
|
-
try {
|
|
273
|
-
signedUrl = await el.getSignedUrl(companion.agentId);
|
|
274
|
-
} catch (e) {
|
|
275
|
-
return handleElError(e, "Failed to get signed url");
|
|
276
|
-
}
|
|
277
|
-
let userContext = "";
|
|
278
|
-
if (config.memoryStore) {
|
|
279
|
-
try {
|
|
280
|
-
const store = config.memoryStore(u.id);
|
|
281
|
-
const hits = store.search(companion.characterName || "recent context", { limit: 5 });
|
|
282
|
-
if (hits.length) {
|
|
283
|
-
userContext = hits.map(
|
|
284
|
-
(h) => `- ${h.matchType ? `[${h.matchType}] ` : ""}${h.chunk.trim().replace(/\s+/g, " ").slice(0, 220)}`
|
|
285
|
-
).join("\n");
|
|
286
|
-
}
|
|
287
|
-
} catch (e) {
|
|
288
|
-
log("warn", "signedUrl: memory preload failed", {
|
|
289
|
-
error: e instanceof Error ? e.message : String(e)
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return json({ signedUrl, agentId: companion.agentId, userContext });
|
|
294
|
-
}
|
|
295
|
-
async function doTts(req) {
|
|
296
|
-
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
297
|
-
const u = await resolveUser(req);
|
|
298
|
-
if (u instanceof Response) return u;
|
|
299
|
-
const raw = await readJson(req);
|
|
300
|
-
if (raw === null || typeof raw !== "object") return json({ error: "Invalid JSON body" }, 400);
|
|
301
|
-
const body = raw;
|
|
302
|
-
const voiceId = typeof body.voiceId === "string" ? body.voiceId.trim() : "";
|
|
303
|
-
if (!voiceId) return json({ error: "Missing voiceId" }, 400);
|
|
304
|
-
const voiceSettings = normalizeVoiceSettings(body.voiceSettings) ?? { stability: 0.5, similarity_boost: 0.8, style: 0 };
|
|
305
|
-
let text;
|
|
306
|
-
if (typeof body.text === "string" && body.text.trim().length > 0) {
|
|
307
|
-
text = body.text.slice(0, 400);
|
|
308
|
-
} else {
|
|
309
|
-
const tags = normalizeAudioTags(body.audioTags) ?? [];
|
|
310
|
-
text = buildPreviewLine(tags, body.characterName ?? "your companion").slice(0, 400);
|
|
311
|
-
}
|
|
312
|
-
try {
|
|
313
|
-
const { audio, modelId, contentType } = await el.textToSpeech({
|
|
314
|
-
voiceId,
|
|
315
|
-
text,
|
|
316
|
-
...body.modelId ? { modelId: body.modelId } : {},
|
|
317
|
-
voiceSettings
|
|
318
|
-
});
|
|
319
|
-
return new Response(audio, {
|
|
320
|
-
headers: {
|
|
321
|
-
"content-type": contentType,
|
|
322
|
-
"cache-control": "private, max-age=3600",
|
|
323
|
-
"x-tts-model-used": modelId
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
} catch (e) {
|
|
327
|
-
return handleElError(e, "TTS failed");
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
async function doMusic(req) {
|
|
331
|
-
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
332
|
-
const u = await resolveUser(req);
|
|
333
|
-
if (u instanceof Response) return u;
|
|
334
|
-
const raw = await readJson(req);
|
|
335
|
-
const parsed = parseMusicBody(raw);
|
|
336
|
-
if ("error" in parsed) return json({ error: parsed.error }, 400);
|
|
337
|
-
try {
|
|
338
|
-
const { audio, contentType } = await el.composeMusic(parsed.params);
|
|
339
|
-
return new Response(audio, {
|
|
340
|
-
headers: {
|
|
341
|
-
"content-type": contentType,
|
|
342
|
-
"cache-control": "private, max-age=3600"
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
} catch (e) {
|
|
346
|
-
return handleElError(e, "Music generation failed");
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
async function doAgentCreate(req) {
|
|
350
|
-
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
351
|
-
const u = await resolveUser(req);
|
|
352
|
-
if (u instanceof Response) return u;
|
|
353
|
-
const existing = await companionStore.findByUserId(u.id);
|
|
354
|
-
if (existing) return json({ error: "Companion already exists" }, 409);
|
|
355
|
-
const raw = await readJson(req);
|
|
356
|
-
if (raw === null || typeof raw !== "object") return json({ error: "Invalid JSON body" }, 400);
|
|
357
|
-
const body = raw;
|
|
358
|
-
if (typeof body.displayName !== "string" || typeof body.characterName !== "string" || typeof body.voiceId !== "string" || typeof body.systemPrompt !== "string" || typeof body.firstMessage !== "string") {
|
|
359
|
-
return json({ error: "Missing required fields" }, 400);
|
|
360
|
-
}
|
|
361
|
-
const expressivity = readExpressivity(body.expressivity);
|
|
362
|
-
const audioTags = readAudioTags(body.audioTags);
|
|
363
|
-
const voiceSettings = readVoiceSettings(body.voiceSettings);
|
|
364
|
-
const ttsModelId = resolveConvaiTtsModel(body.ttsModelId);
|
|
365
|
-
let agentId;
|
|
366
|
-
try {
|
|
367
|
-
agentId = await el.createAgent({
|
|
368
|
-
displayName: body.displayName,
|
|
369
|
-
characterName: body.characterName,
|
|
370
|
-
voiceId: body.voiceId,
|
|
371
|
-
systemPrompt: body.systemPrompt,
|
|
372
|
-
firstMessage: body.firstMessage,
|
|
373
|
-
expressivity,
|
|
374
|
-
audioTags,
|
|
375
|
-
voiceSettings,
|
|
376
|
-
ttsModelId,
|
|
377
|
-
...tools ? { tools } : {},
|
|
378
|
-
...includeMemoryTools ? {} : { memoryBlock: null }
|
|
379
|
-
});
|
|
380
|
-
} catch (e) {
|
|
381
|
-
return handleElError(e, "Failed to create agent");
|
|
382
|
-
}
|
|
383
|
-
const cleanedPrompt = extractBasePrompt(body.systemPrompt);
|
|
384
|
-
const companion = await companionStore.create({
|
|
385
|
-
userId: u.id,
|
|
386
|
-
agentId,
|
|
387
|
-
displayName: body.displayName,
|
|
388
|
-
characterName: body.characterName,
|
|
389
|
-
voiceId: body.voiceId,
|
|
390
|
-
systemPrompt: cleanedPrompt,
|
|
391
|
-
firstMessage: body.firstMessage,
|
|
392
|
-
expressivity,
|
|
393
|
-
audioTags,
|
|
394
|
-
voiceSettings,
|
|
395
|
-
ttsModelId
|
|
396
|
-
});
|
|
397
|
-
return json(companion);
|
|
398
|
-
}
|
|
399
|
-
async function doAgentPatch(req) {
|
|
400
|
-
if (req.method !== "PATCH") return json({ error: "Method Not Allowed" }, 405);
|
|
401
|
-
const u = await resolveUser(req);
|
|
402
|
-
if (u instanceof Response) return u;
|
|
403
|
-
const existing = await companionStore.findByUserId(u.id);
|
|
404
|
-
if (!existing) return json({ error: "No companion" }, 404);
|
|
405
|
-
const raw = await readJson(req);
|
|
406
|
-
if (raw === null || typeof raw !== "object") return json({ error: "Invalid JSON body" }, 400);
|
|
407
|
-
const body = raw;
|
|
408
|
-
const patch = {};
|
|
409
|
-
if (body.displayName !== void 0) patch.displayName = body.displayName;
|
|
410
|
-
if (body.characterName !== void 0) patch.characterName = body.characterName;
|
|
411
|
-
if (body.voiceId !== void 0) patch.voiceId = body.voiceId;
|
|
412
|
-
if (body.firstMessage !== void 0) patch.firstMessage = body.firstMessage;
|
|
413
|
-
const expressivity = normalizeExpressivity(body.expressivity);
|
|
414
|
-
if (expressivity !== void 0) patch.expressivity = expressivity;
|
|
415
|
-
let audioTagsPatch;
|
|
416
|
-
if (body.audioTags !== void 0) {
|
|
417
|
-
audioTagsPatch = normalizeAudioTags(body.audioTags) ?? [];
|
|
418
|
-
patch.audioTags = audioTagsPatch;
|
|
419
|
-
}
|
|
420
|
-
if (body.voiceSettings !== void 0) {
|
|
421
|
-
const vs = normalizeVoiceSettings(body.voiceSettings);
|
|
422
|
-
patch.voiceSettings = vs ?? null;
|
|
423
|
-
}
|
|
424
|
-
if (body.ttsModelId !== void 0) patch.ttsModelId = body.ttsModelId ?? null;
|
|
425
|
-
const cleanedPrompt = body.systemPrompt !== void 0 ? extractBasePrompt(body.systemPrompt) : void 0;
|
|
426
|
-
if (cleanedPrompt !== void 0) patch.systemPrompt = cleanedPrompt;
|
|
427
|
-
const needs11Labs = body.displayName !== void 0 || body.characterName !== void 0 || body.voiceId !== void 0 || body.systemPrompt !== void 0 || body.firstMessage !== void 0 || body.expressivity !== void 0 || body.audioTags !== void 0 || body.voiceSettings !== void 0 || body.ttsModelId !== void 0;
|
|
428
|
-
if (existing.agentId && needs11Labs) {
|
|
429
|
-
const finalExpressivity = patch.expressivity ?? readExpressivity(existing.expressivity);
|
|
430
|
-
const finalTags = audioTagsPatch !== void 0 ? audioTagsPatch : readAudioTags(existing.audioTags);
|
|
431
|
-
const finalVoiceSettings = body.voiceSettings !== void 0 ? normalizeVoiceSettings(body.voiceSettings) ?? void 0 : readVoiceSettings(existing.voiceSettings);
|
|
432
|
-
const finalTtsModelId = body.ttsModelId !== void 0 ? body.ttsModelId ?? null : existing.ttsModelId ?? null;
|
|
433
|
-
try {
|
|
434
|
-
await el.patchAgent(existing.agentId, {
|
|
435
|
-
...body.displayName !== void 0 ? { displayName: body.displayName } : {},
|
|
436
|
-
...body.characterName !== void 0 ? { characterName: body.characterName } : {},
|
|
437
|
-
...body.voiceId !== void 0 ? { voiceId: body.voiceId } : {},
|
|
438
|
-
systemPrompt: cleanedPrompt !== void 0 ? cleanedPrompt : body.expressivity !== void 0 || body.audioTags !== void 0 ? existing.systemPrompt : void 0,
|
|
439
|
-
...body.firstMessage !== void 0 ? { firstMessage: body.firstMessage } : {},
|
|
440
|
-
expressivity: finalExpressivity,
|
|
441
|
-
audioTags: finalTags,
|
|
442
|
-
...finalVoiceSettings ? { voiceSettings: finalVoiceSettings } : {},
|
|
443
|
-
ttsModelId: finalTtsModelId,
|
|
444
|
-
...includeMemoryTools ? {} : { memoryBlock: null }
|
|
445
|
-
});
|
|
446
|
-
} catch (e) {
|
|
447
|
-
return handleElError(e, "Failed to patch agent");
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
const companion = await companionStore.update(u.id, patch);
|
|
451
|
-
return json(companion);
|
|
452
|
-
}
|
|
453
|
-
async function doAgentDelete(req) {
|
|
454
|
-
if (req.method !== "DELETE") return json({ error: "Method Not Allowed" }, 405);
|
|
455
|
-
const u = await resolveUser(req);
|
|
456
|
-
if (u instanceof Response) return u;
|
|
457
|
-
const existing = await companionStore.findByUserId(u.id);
|
|
458
|
-
if (!existing) return json({ ok: true });
|
|
459
|
-
if (existing.agentId) await el.deleteAgent(existing.agentId);
|
|
460
|
-
await companionStore.delete(u.id);
|
|
461
|
-
return json({ ok: true });
|
|
462
|
-
}
|
|
463
|
-
async function doAudioTags(req) {
|
|
464
|
-
if (req.method !== "GET") return json({ error: "Method Not Allowed" }, 405);
|
|
465
|
-
return json({
|
|
466
|
-
tags: AUDIO_TAGS,
|
|
467
|
-
groups: AUDIO_TAG_GROUPS,
|
|
468
|
-
expressivity: EXPRESSIVITY_OPTIONS,
|
|
469
|
-
defaults: {
|
|
470
|
-
allowedTags: DEFAULT_ALLOWED_TAGS,
|
|
471
|
-
voiceSettings: DEFAULT_VOICE_SETTINGS,
|
|
472
|
-
ttsModelId: CONVAI_TTS_MODEL_FALLBACK
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
return {
|
|
477
|
-
signedUrl: doSignedUrl,
|
|
478
|
-
tts: doTts,
|
|
479
|
-
music: doMusic,
|
|
480
|
-
agent: {
|
|
481
|
-
create: doAgentCreate,
|
|
482
|
-
patch: doAgentPatch,
|
|
483
|
-
delete: doAgentDelete
|
|
484
|
-
},
|
|
485
|
-
audioTags: doAudioTags,
|
|
486
|
-
elevenLabs: el
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
function toNodeListener(handler) {
|
|
490
|
-
return (nodeReq, nodeRes) => {
|
|
491
|
-
void (async () => {
|
|
492
|
-
const url = `http://${nodeReq.headers.host ?? "localhost"}${nodeReq.url ?? "/"}`;
|
|
493
|
-
const chunks = [];
|
|
494
|
-
for await (const chunk of nodeReq) {
|
|
495
|
-
chunks.push(chunk);
|
|
496
|
-
}
|
|
497
|
-
const body = Buffer.concat(chunks);
|
|
498
|
-
const init = {
|
|
499
|
-
method: nodeReq.method,
|
|
500
|
-
headers: nodeReq.headers
|
|
501
|
-
};
|
|
502
|
-
if (body.length > 0) {
|
|
503
|
-
init.body = body;
|
|
504
|
-
}
|
|
505
|
-
const req = new Request(url, init);
|
|
506
|
-
const res = await handler(req);
|
|
507
|
-
nodeRes.statusCode = res.status;
|
|
508
|
-
res.headers.forEach((value, key) => {
|
|
509
|
-
nodeRes.setHeader(key, value);
|
|
510
|
-
});
|
|
511
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
512
|
-
nodeRes.end(buf);
|
|
513
|
-
})().catch((err) => {
|
|
514
|
-
nodeRes.statusCode = 500;
|
|
515
|
-
nodeRes.end(err instanceof Error ? err.message : String(err));
|
|
516
|
-
});
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
export {
|
|
521
|
-
createVoiceHandlers,
|
|
522
|
-
toNodeListener
|
|
523
|
-
};
|
|
524
|
-
//# sourceMappingURL=chunk-O362EJQR.js.map
|