realtime-avatar 0.3.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 +176 -0
- package/dist/browser.d.ts +203 -0
- package/dist/browser.js +172 -0
- package/dist/express.d.ts +28 -0
- package/dist/express.js +510 -0
- package/dist/hono.d.ts +19 -0
- package/dist/hono.js +498 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.js +453 -0
- package/dist/nextjs.d.ts +18 -0
- package/dist/nextjs.js +498 -0
- package/dist/proxy-client-cZyX50-O.d.ts +1508 -0
- package/dist/react-native.d.ts +103 -0
- package/dist/react-native.js +2305 -0
- package/dist/react.d.ts +107 -0
- package/dist/react.js +2610 -0
- package/dist/server-only-guard.d.ts +2 -0
- package/dist/server-only-guard.js +4 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +453 -0
- package/dist/tanstack-start.d.ts +24 -0
- package/dist/tanstack-start.js +498 -0
- package/dist/tools.d.ts +111 -0
- package/dist/tools.js +121 -0
- package/dist/types-C_EMPwN7.d.ts +831 -0
- package/dist/types-E8SrD6sv.d.ts +48 -0
- package/package.json +150 -0
package/dist/tools.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ../tools/src/index.ts
|
|
2
|
+
var MAX_TOOLS = 32;
|
|
3
|
+
var MAX_MANIFEST_BYTES = 12e3;
|
|
4
|
+
var MAX_RESULT_CHARS = 8192;
|
|
5
|
+
var TOOL_DEADLINE_MS = 2500;
|
|
6
|
+
var REGISTER_METHOD = "rta.tools.register";
|
|
7
|
+
var INVOKE_METHOD = "rta.tool.invoke";
|
|
8
|
+
var NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
9
|
+
function candidateIdentities(room) {
|
|
10
|
+
const all = Array.from(room.remoteParticipants.values(), (p) => p.identity).filter(Boolean);
|
|
11
|
+
const agents = all.filter((id) => /^agent[-_]/i.test(id));
|
|
12
|
+
return [...agents, ...all.filter((id) => !agents.includes(id))];
|
|
13
|
+
}
|
|
14
|
+
function methodMissing(error) {
|
|
15
|
+
const code = error?.code;
|
|
16
|
+
if (code === "UNSUPPORTED_METHOD" || code === "RECIPIENT_NOT_FOUND" || code === 1401 || code === 1402) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
20
|
+
return /not supported|unsupported_method|recipient_not_found|recipient not found/i.test(message);
|
|
21
|
+
}
|
|
22
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
23
|
+
function buildManifest(tools) {
|
|
24
|
+
const descriptors = [];
|
|
25
|
+
const rejected = [];
|
|
26
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
27
|
+
if (!NAME_RE.test(name)) {
|
|
28
|
+
rejected.push({ name, reason: "name must match [a-zA-Z0-9_-]{1,64}" });
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!tool?.description) {
|
|
32
|
+
rejected.push({ name, reason: "description is required \u2014 it is how she knows when to call it" });
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (typeof tool.execute !== "function") {
|
|
36
|
+
rejected.push({ name, reason: "execute must be a function" });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (descriptors.length >= MAX_TOOLS) {
|
|
40
|
+
rejected.push({ name, reason: `over the ${MAX_TOOLS}-tool limit for one session` });
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
descriptors.push({ name, description: tool.description, parameters: tool.parameters ?? {} });
|
|
44
|
+
}
|
|
45
|
+
return { descriptors, rejected };
|
|
46
|
+
}
|
|
47
|
+
async function attachAvatarTools(room, tools, options = {}) {
|
|
48
|
+
const { descriptors, rejected } = buildManifest(tools);
|
|
49
|
+
const payload = JSON.stringify({ tools: descriptors });
|
|
50
|
+
if (payload.length > MAX_MANIFEST_BYTES) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`tool manifest is ${payload.length} bytes, over the ${MAX_MANIFEST_BYTES} limit \u2014 shorten descriptions or register fewer tools`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
room.localParticipant.registerRpcMethod(INVOKE_METHOD, async ({ payload: payload2 }) => {
|
|
56
|
+
let name = "", callId = "";
|
|
57
|
+
try {
|
|
58
|
+
const req = JSON.parse(payload2);
|
|
59
|
+
name = req.name;
|
|
60
|
+
callId = req.call_id;
|
|
61
|
+
const tool = tools[name];
|
|
62
|
+
if (!tool) return JSON.stringify({ ok: false, call_id: callId, error: `no tool named ${name}` });
|
|
63
|
+
const args = req.args ? JSON.parse(req.args) : {};
|
|
64
|
+
options.onInvoke?.(name, args);
|
|
65
|
+
const run = tool.execute;
|
|
66
|
+
const controller = new AbortController();
|
|
67
|
+
const timer = setTimeout(() => controller.abort(), TOOL_DEADLINE_MS);
|
|
68
|
+
let result;
|
|
69
|
+
try {
|
|
70
|
+
result = await run(args, { signal: controller.signal, callId });
|
|
71
|
+
} finally {
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
}
|
|
74
|
+
const encoded = typeof result === "string" ? result : JSON.stringify(result ?? null);
|
|
75
|
+
if (encoded.length > MAX_RESULT_CHARS) {
|
|
76
|
+
return JSON.stringify({
|
|
77
|
+
ok: false,
|
|
78
|
+
call_id: callId,
|
|
79
|
+
error: `result was ${encoded.length} chars, over the ${MAX_RESULT_CHARS} limit`
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return JSON.stringify({ ok: true, call_id: callId, result: encoded });
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return JSON.stringify({
|
|
85
|
+
ok: false,
|
|
86
|
+
call_id: callId,
|
|
87
|
+
error: error instanceof Error ? error.message : "tool failed"
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const deadline = Date.now() + Math.max(0, options.timeoutMs ?? 8e3);
|
|
92
|
+
let lastError = null;
|
|
93
|
+
let sawCandidate = false;
|
|
94
|
+
for (; ; ) {
|
|
95
|
+
for (const identity of candidateIdentities(room)) {
|
|
96
|
+
sawCandidate = true;
|
|
97
|
+
try {
|
|
98
|
+
const raw = await room.localParticipant.performRpc({
|
|
99
|
+
destinationIdentity: identity,
|
|
100
|
+
method: REGISTER_METHOD,
|
|
101
|
+
payload
|
|
102
|
+
});
|
|
103
|
+
const result = JSON.parse(raw);
|
|
104
|
+
return {
|
|
105
|
+
accepted: result.accepted ?? [],
|
|
106
|
+
rejected: [...rejected, ...result.rejected ?? []]
|
|
107
|
+
};
|
|
108
|
+
} catch (error) {
|
|
109
|
+
lastError = error;
|
|
110
|
+
if (!methodMissing(error)) throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (Date.now() >= deadline) break;
|
|
114
|
+
await sleep(200);
|
|
115
|
+
}
|
|
116
|
+
throw new Error(
|
|
117
|
+
sawCandidate ? `no participant accepted the tool manifest \u2014 either this session was not minted with the \`client_tools\` capability (a server-side grant), or the agent never armed registration within ${options.timeoutMs ?? 8e3}ms` + (lastError instanceof Error ? ` (last error: ${lastError.message})` : "") : "no remote participant joined the room before the timeout \u2014 nothing to register with"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { MAX_MANIFEST_BYTES, MAX_RESULT_CHARS, MAX_TOOLS, TOOL_DEADLINE_MS, attachAvatarTools };
|