realtime-avatar 0.5.2 → 0.5.4
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/dist/chunk-I3BFZHMQ.js +678 -0
- package/dist/chunk-XZ5DRDND.js +72 -0
- package/dist/express.js +2 -715
- package/dist/hono.js +2 -715
- package/dist/index.js +1 -678
- package/dist/nextjs.js +2 -715
- package/dist/{proxy-client-BIaUo0az.d.ts → proxy-client-DylBmlgX.d.ts} +5 -5
- package/dist/react-native.d.ts +14 -2
- package/dist/react-native.js +11 -1
- package/dist/react.d.ts +2 -2
- package/dist/server.js +1 -678
- package/dist/tanstack-start.js +2 -715
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-I3BFZHMQ.js';
|
|
2
|
+
|
|
3
|
+
// ../proxy/src/config.ts
|
|
4
|
+
var json = (body, status = 200) => new Response(JSON.stringify(body), {
|
|
5
|
+
status,
|
|
6
|
+
headers: { "content-type": "application/json", "cache-control": "no-store" }
|
|
7
|
+
});
|
|
8
|
+
function operationFor(pathname, method) {
|
|
9
|
+
const tail = pathname.replace(/\/+$/, "").split("/").pop() ?? "";
|
|
10
|
+
if (method === "POST" && (tail === "connect" || tail === "call")) return "connect";
|
|
11
|
+
if (method === "POST" && (tail === "end" || tail === "release")) return "end";
|
|
12
|
+
if (method === "GET" && tail === "avatars") return "avatars";
|
|
13
|
+
if (method === "GET" && tail === "credits") return "credits";
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function createProxyHandler(config) {
|
|
17
|
+
const minted = /* @__PURE__ */ new Map();
|
|
18
|
+
const MINTED_TTL_MS = 30 * 6e4;
|
|
19
|
+
return async (request) => {
|
|
20
|
+
const url = new URL(request.url);
|
|
21
|
+
const operation = operationFor(url.pathname, request.method);
|
|
22
|
+
if (!operation) return json({ error: "not found" }, 404);
|
|
23
|
+
const refusal = await config.authorize?.({ request, operation });
|
|
24
|
+
if (refusal instanceof Response) return refusal;
|
|
25
|
+
const apiKey = typeof config.apiKey === "function" ? await config.apiKey() : config.apiKey;
|
|
26
|
+
const rta = new RealtimeAvatar({ apiKey, baseUrl: config.baseUrl });
|
|
27
|
+
try {
|
|
28
|
+
if (operation === "avatars") return json({ data: await rta.listAvatars() });
|
|
29
|
+
if (operation === "credits") return json(await rta.creditBalance());
|
|
30
|
+
if (operation === "end") {
|
|
31
|
+
const ended = await request.json().catch(() => ({}));
|
|
32
|
+
const sessionId = ended.session_id ?? ended.queue_ticket_id;
|
|
33
|
+
if (!sessionId) return json({ error: "session_id or queue_ticket_id is required" }, 422);
|
|
34
|
+
const owns = config.ownsSession ? await config.ownsSession({ request, sessionId }) : minted.delete(sessionId);
|
|
35
|
+
if (!owns) return new Response(null, { status: 204 });
|
|
36
|
+
const reason = ended.reason === "page_hide" || ended.reason === "unmount" ? ended.reason : "manual";
|
|
37
|
+
await rta.endCall(sessionId, { reason });
|
|
38
|
+
return new Response(null, { status: 204 });
|
|
39
|
+
}
|
|
40
|
+
const body = await request.json().catch(() => ({}));
|
|
41
|
+
if (!body.avatarId) return json({ error: "avatarId is required" }, 422);
|
|
42
|
+
const mode = body.mode === "voice" ? "voice" : "avatar";
|
|
43
|
+
const decided = await config.session?.({ request, avatarId: body.avatarId, mode });
|
|
44
|
+
if (decided instanceof Response) return decided;
|
|
45
|
+
const call = await rta.startCall({ avatarId: body.avatarId, mode, ...decided ?? {} });
|
|
46
|
+
if (isQueued(call)) {
|
|
47
|
+
if (call.queueTicketId) minted.set(call.queueTicketId, Date.now());
|
|
48
|
+
return json(
|
|
49
|
+
{
|
|
50
|
+
queued: true,
|
|
51
|
+
position: call.position,
|
|
52
|
+
size: call.size,
|
|
53
|
+
retryAfterMs: call.retryAfterMs,
|
|
54
|
+
queue_ticket_id: call.queueTicketId
|
|
55
|
+
},
|
|
56
|
+
429
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
for (const [id, at] of minted) if (now - at > MINTED_TTL_MS) minted.delete(id);
|
|
61
|
+
minted.set(call.sessionId, now);
|
|
62
|
+
return json(call.raw);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (error instanceof RealtimeAvatarHttpError && error.isBilling) {
|
|
65
|
+
return json({ code: error.code ?? "insufficient_credits" }, 402);
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { createProxyHandler };
|